From 69b0fea4c49422f5e3c377994c4cf249bdc5a434 Mon Sep 17 00:00:00 2001 From: Soren Stoutner Date: Wed, 18 Jul 2018 16:05:23 -0700 Subject: [PATCH] Add an option to block all third-party requests. https://redmine.stoutner.com/issues/209 --- .idea/assetWizardSettings.xml | 4 +- .../main/assets/de/about_licenses_dark.html | 1 + .../main/assets/de/about_licenses_light.html | 1 + .../main/assets/en/about_licenses_dark.html | 1 + .../main/assets/en/about_licenses_light.html | 1 + .../main/assets/es/about_licenses_dark.html | 1 + .../main/assets/es/about_licenses_light.html | 1 + .../main/assets/it/about_licenses_dark.html | 1 + .../main/assets/it/about_licenses_light.html | 1 + .../main/assets/ru/about_licenses_dark.html | 1 + .../main/assets/ru/about_licenses_light.html | 1 + .../shared_images/new_releases_dark.png | Bin 0 -> 2322 bytes .../shared_images/new_releases_light.png | Bin 0 -> 2020 bytes .../activities/DomainsActivity.java | 16 +-- .../activities/MainWebViewActivity.java | 108 +++++++++++++++--- .../activities/RequestsActivity.java | 26 ++++- .../adapters/RequestsArrayAdapter.java | 29 +++-- .../dialogs/ViewRequestDialog.java | 30 +++-- .../fragments/AboutTabFragment.java | 4 +- .../fragments/DomainSettingsFragment.java | 46 ++++++++ .../fragments/SettingsFragment.java | 35 +++++- .../helpers/BlockListHelper.java | 24 ++-- .../helpers/DomainsDatabaseHelper.java | 23 +++- .../allow_screenshots_disabled_dark.xml | 11 +- .../allow_screenshots_disabled_light.xml | 11 +- .../allow_screenshots_enabled_dark.xml | 11 +- .../allow_screenshots_enabled_light.xml | 11 +- ...all_third_party_requests_disabled_dark.xml | 14 +++ ...ll_third_party_requests_disabled_light.xml | 14 +++ ..._all_third_party_requests_enabled_dark.xml | 14 +++ ...all_third_party_requests_enabled_light.xml | 14 +++ .../res/layout/domain_settings_fragment.xml | 31 ++++- .../res/layout/requests_item_linearlayout.xml | 2 +- .../main/res/layout/view_request_dialog.xml | 2 +- .../main/res/menu/webview_options_menu.xml | 7 ++ app/src/main/res/values/colors.xml | 4 +- app/src/main/res/values/strings.xml | 5 + app/src/main/res/xml/preferences.xml | 6 + 38 files changed, 417 insertions(+), 95 deletions(-) create mode 100644 app/src/main/assets/shared_images/new_releases_dark.png create mode 100644 app/src/main/assets/shared_images/new_releases_light.png create mode 100644 app/src/main/res/drawable/block_all_third_party_requests_disabled_dark.xml create mode 100644 app/src/main/res/drawable/block_all_third_party_requests_disabled_light.xml create mode 100644 app/src/main/res/drawable/block_all_third_party_requests_enabled_dark.xml create mode 100644 app/src/main/res/drawable/block_all_third_party_requests_enabled_light.xml diff --git a/.idea/assetWizardSettings.xml b/.idea/assetWizardSettings.xml index 02141c9f..6e3671ed 100644 --- a/.idea/assetWizardSettings.xml +++ b/.idea/assetWizardSettings.xml @@ -68,7 +68,7 @@ @@ -78,7 +78,7 @@ diff --git a/app/src/main/assets/de/about_licenses_dark.html b/app/src/main/assets/de/about_licenses_dark.html index 165f8f98..c83a1368 100644 --- a/app/src/main/assets/de/about_licenses_dark.html +++ b/app/src/main/assets/de/about_licenses_dark.html @@ -117,6 +117,7 @@

lock.

map.

more.

+

new releases.

question_answer.

refresh.

search.

diff --git a/app/src/main/assets/de/about_licenses_light.html b/app/src/main/assets/de/about_licenses_light.html index f242dc07..7b5b0cb4 100644 --- a/app/src/main/assets/de/about_licenses_light.html +++ b/app/src/main/assets/de/about_licenses_light.html @@ -117,6 +117,7 @@

lock.

map.

more.

+

new releases.

question_answer.

refresh.

search.

diff --git a/app/src/main/assets/en/about_licenses_dark.html b/app/src/main/assets/en/about_licenses_dark.html index 3bddeab5..56d6b1c1 100644 --- a/app/src/main/assets/en/about_licenses_dark.html +++ b/app/src/main/assets/en/about_licenses_dark.html @@ -115,6 +115,7 @@

lock.

map.

more.

+

new releases.

question_answer.

refresh.

search.

diff --git a/app/src/main/assets/en/about_licenses_light.html b/app/src/main/assets/en/about_licenses_light.html index 49397f98..e4be1e11 100644 --- a/app/src/main/assets/en/about_licenses_light.html +++ b/app/src/main/assets/en/about_licenses_light.html @@ -116,6 +116,7 @@

lock.

map.

more.

+

new releases.

question_answer.

refresh.

search.

diff --git a/app/src/main/assets/es/about_licenses_dark.html b/app/src/main/assets/es/about_licenses_dark.html index c7ae7228..db1fdcef 100644 --- a/app/src/main/assets/es/about_licenses_dark.html +++ b/app/src/main/assets/es/about_licenses_dark.html @@ -120,6 +120,7 @@

lock.

map.

more.

+

new releases.

question_answer.

refresh.

search.

diff --git a/app/src/main/assets/es/about_licenses_light.html b/app/src/main/assets/es/about_licenses_light.html index 6d1fb8ba..e21b26f0 100644 --- a/app/src/main/assets/es/about_licenses_light.html +++ b/app/src/main/assets/es/about_licenses_light.html @@ -121,6 +121,7 @@

lock.

map.

more.

+

new releases.

question_answer.

refresh.

search.

diff --git a/app/src/main/assets/it/about_licenses_dark.html b/app/src/main/assets/it/about_licenses_dark.html index f0fd34f4..8b51ffea 100644 --- a/app/src/main/assets/it/about_licenses_dark.html +++ b/app/src/main/assets/it/about_licenses_dark.html @@ -124,6 +124,7 @@

lock.

map.

more.

+

new releases.

question_answer.

refresh.

search.

diff --git a/app/src/main/assets/it/about_licenses_light.html b/app/src/main/assets/it/about_licenses_light.html index 82dea778..5e085388 100644 --- a/app/src/main/assets/it/about_licenses_light.html +++ b/app/src/main/assets/it/about_licenses_light.html @@ -124,6 +124,7 @@

lock.

map.

more.

+

new releases.

question_answer.

refresh.

search.

diff --git a/app/src/main/assets/ru/about_licenses_dark.html b/app/src/main/assets/ru/about_licenses_dark.html index e18c1e1f..9a0806f8 100644 --- a/app/src/main/assets/ru/about_licenses_dark.html +++ b/app/src/main/assets/ru/about_licenses_dark.html @@ -117,6 +117,7 @@

lock.

map.

more.

+

new releases.

question_answer.

refresh.

search.

diff --git a/app/src/main/assets/ru/about_licenses_light.html b/app/src/main/assets/ru/about_licenses_light.html index b337dfdd..4b5ed099 100644 --- a/app/src/main/assets/ru/about_licenses_light.html +++ b/app/src/main/assets/ru/about_licenses_light.html @@ -117,6 +117,7 @@

lock.

map.

more.

+

new releases.

question_answer.

refresh.

search.

diff --git a/app/src/main/assets/shared_images/new_releases_dark.png b/app/src/main/assets/shared_images/new_releases_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..b918a6318d63ad1e2e22ba5a739802ed5b19eed7 GIT binary patch literal 2322 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 resourceRequests; @@ -209,7 +209,8 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook public final static int REQUEST_DEFAULT = 0; public final static int REQUEST_ALLOWED = 1; - public final static int REQUEST_BLOCKED = 2; + public final static int REQUEST_THIRD_PARTY = 2; + public final static int REQUEST_BLOCKED = 3; public final static int MAIN_WHITELIST = 1; public final static int FINAL_WHITELIST = 2; @@ -235,6 +236,10 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook public final static int THIRD_PARTY_DOMAIN_REGULAR_EXPRESSION_BLACKLIST = 21; public final static int REGULAR_EXPRESSION_BLACKLIST = 22; + // `blockAllThirdPartyRequests` is public static so it can be accessed from `RequestsActivity`. + // It is also used in `onCreate()`, `onPrepareOptionsMenu()`, `onOptionsItemSelected()`, and `applyAppSettings()` + public static boolean blockAllThirdPartyRequests; + // `currentBookmarksFolder` is public static so it can be accessed from `BookmarksActivity`. It is also used in `onCreate()`, `onBackPressed()`, `onCreateBookmark()`, `onCreateBookmarkFolder()`, // `onSaveEditBookmark()`, `onSaveEditBookmarkFolder()`, and `loadBookmarksFolder()`. public static String currentBookmarksFolder; @@ -874,9 +879,15 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook // Count the number of blocked requests. for (int i = 0; i < resourceRequests.size(); i++) { + // Add the blocked requests. if (Integer.valueOf(resourceRequests.get(i)[REQUEST_DISPOSITION]) == REQUEST_BLOCKED) { blockedRequests++; } + + // Add the third-party requests if they are blocked. + if (blockAllThirdPartyRequests && (Integer.valueOf(resourceRequests.get(i)[REQUEST_DISPOSITION]) == REQUEST_THIRD_PARTY)) { + blockedRequests++; + } } // Update the back, forward, history, and requests menu items. @@ -1162,14 +1173,14 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook // Parse the block lists. final ArrayList> easyList = blockListHelper.parseBlockList(getAssets(), "blocklists/easylist.txt"); final ArrayList> easyPrivacy = blockListHelper.parseBlockList(getAssets(), "blocklists/easyprivacy.txt"); - final ArrayList> fanboyAnnoyance = blockListHelper.parseBlockList(getAssets(), "blocklists/fanboy-annoyance.txt"); - final ArrayList> fanboySocial = blockListHelper.parseBlockList(getAssets(), "blocklists/fanboy-social.txt"); + final ArrayList> fanboysAnnoyanceList = blockListHelper.parseBlockList(getAssets(), "blocklists/fanboy-annoyance.txt"); + final ArrayList> fanboysSocialList = blockListHelper.parseBlockList(getAssets(), "blocklists/fanboy-social.txt"); // Store the list versions. easyListVersion = easyList.get(0).get(0)[0]; easyPrivacyVersion = easyPrivacy.get(0).get(0)[0]; - fanboyAnnoyanceVersion = fanboyAnnoyance.get(0).get(0)[0]; - fanboySocialVersion = fanboySocial.get(0).get(0)[0]; + fanboysAnnoyanceVersion = fanboysAnnoyanceList.get(0).get(0)[0]; + fanboysSocialVersion = fanboysSocialList.get(0).get(0)[0]; mainWebView.setWebViewClient(new WebViewClient() { // `shouldOverrideUrlLoading` makes this `WebView` the default handler for URLs inside the app, so that links are not kicked out to other apps. @@ -1248,9 +1259,56 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook // Reset `whiteListResultStringArray`. whiteListResultStringArray = null; + // Initialize the third party request tracker. + boolean isThirdPartyRequest = false; + + // + String currentDomain = ""; + + // Nobody is happy when comparing null strings. + if (!(formattedUrlString == null) && !(url == null)) { + // Get the domain strings to URIs. + Uri currentDomainUri = Uri.parse(formattedUrlString); + Uri requestDomainUri = Uri.parse(url); + + // Get the domain host names. + String currentBaseDomain = currentDomainUri.getHost(); + String requestBaseDomain = requestDomainUri.getHost(); + + // Update the current domain variable. + currentDomain = currentBaseDomain; + + // Only compare the current base domain and the request base domain if neither is null. + if (!(currentBaseDomain == null) && !(requestBaseDomain == null)) { + // Determine the current base domain. + while (currentBaseDomain.indexOf(".", currentBaseDomain.indexOf(".") + 1) > 0) { // There is at least one subdomain. + // Remove the first subdomain. + currentBaseDomain = currentBaseDomain.substring(currentBaseDomain.indexOf(".") + 1); + } + + // Determine the request base domain. + while (requestBaseDomain.indexOf(".", requestBaseDomain.indexOf(".") + 1) > 0) { // There is at least one subdomain. + // Remove the first subdomain. + requestBaseDomain = requestBaseDomain.substring(requestBaseDomain.indexOf(".") + 1); + } + + // Update the third party request tracker. + isThirdPartyRequest = !currentBaseDomain.equals(requestBaseDomain); + } + } + + // Block third-party requests if enabled. + if (isThirdPartyRequest && blockAllThirdPartyRequests) { + // Add the request to the log. + resourceRequests.add(new String[]{String.valueOf(REQUEST_THIRD_PARTY), url}); + + // Return an empty web resource response. + return emptyWebResourceResponse; + } + // Check EasyList if it is enabled. if (easyListEnabled) { - if (blockListHelper.isBlocked(formattedUrlString, url, easyList)) { + if (blockListHelper.isBlocked(currentDomain, url, isThirdPartyRequest, easyList)) { // The resource request was blocked. Return an empty web resource response. return emptyWebResourceResponse; } @@ -1258,7 +1316,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook // Check EasyPrivacy if it is enabled. if (easyPrivacyEnabled) { - if (blockListHelper.isBlocked(formattedUrlString, url, easyPrivacy)) { + if (blockListHelper.isBlocked(currentDomain, url, isThirdPartyRequest, easyPrivacy)) { // The resource request was blocked. Return an empty web resource response. return emptyWebResourceResponse; } @@ -1266,18 +1324,18 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook // Check Fanboy’s Annoyance List if it is enabled. if (fanboysAnnoyanceListEnabled) { - if (blockListHelper.isBlocked(formattedUrlString, url, fanboyAnnoyance)) { + if (blockListHelper.isBlocked(currentDomain, url, isThirdPartyRequest, fanboysAnnoyanceList)) { // The resource request was blocked. Return an empty web resource response. return emptyWebResourceResponse; } } else if (fanboysSocialBlockingListEnabled){ // Only check Fanboy’s Social Blocking List if Fanboy’s Annoyance List is disabled. - if (blockListHelper.isBlocked(formattedUrlString, url, fanboySocial)) { + if (blockListHelper.isBlocked(currentDomain, url, isThirdPartyRequest, fanboysSocialList)) { // The resource request was blocked. Return an empty web resource response. return emptyWebResourceResponse; } } - // Add the request to the log. + // Add the request to the log because it hasn't been processed by any of the previous checks. if (whiteListResultStringArray != null ) { // The request was processed by a whitelist. resourceRequests.add(whiteListResultStringArray); } else { // The request didn't match any blocklist entry. Log it as a defult request. @@ -1511,12 +1569,11 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook // Check to see if the intent contains a new URL. if (intent.getData() != null) { - // Get the intent data and convert it to a string. + // Get the intent data. final Uri intentUriData = intent.getData(); - formattedUrlString = intentUriData.toString(); // Load the website. - loadUrl(formattedUrlString); + loadUrl(intentUriData.toString()); // Close the navigation drawer if it is open. if (drawerLayout.isDrawerVisible(GravityCompat.START)) { @@ -1701,6 +1758,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook MenuItem easyPrivacyMenuItem = menu.findItem(R.id.easyprivacy); MenuItem fanboysAnnoyanceListMenuItem = menu.findItem(R.id.fanboys_annoyance_list); MenuItem fanboysSocialBlockingListMenuItem = menu.findItem(R.id.fanboys_social_blocking_list); + MenuItem blockAllThirdParyRequestsMenuItem = menu.findItem(R.id.block_all_third_party_requests); MenuItem fontSizeMenuItem = menu.findItem(R.id.font_size); MenuItem swipeToRefreshMenuItem = menu.findItem(R.id.swipe_to_refresh); MenuItem displayImagesMenuItem = menu.findItem(R.id.display_images); @@ -1721,6 +1779,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook easyPrivacyMenuItem.setChecked(easyPrivacyEnabled); fanboysAnnoyanceListMenuItem.setChecked(fanboysAnnoyanceListEnabled); fanboysSocialBlockingListMenuItem.setChecked(fanboysSocialBlockingListEnabled); + blockAllThirdParyRequestsMenuItem.setChecked(blockAllThirdPartyRequests); swipeToRefreshMenuItem.setChecked(swipeRefreshLayout.isEnabled()); displayImagesMenuItem.setChecked(mainWebView.getSettings().getLoadsImagesAutomatically()); @@ -2190,13 +2249,24 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook // Toggle Fanboy's Social Blocking List status. fanboysSocialBlockingListEnabled = !fanboysSocialBlockingListEnabled; - // Update teh menu checkbox. + // Update the menu checkbox. menuItem.setChecked(fanboysSocialBlockingListEnabled); // Reload the main WebView. mainWebView.reload(); return true; + case R.id.block_all_third_party_requests: + //Toggle the third-party requests blocker status. + blockAllThirdPartyRequests = !blockAllThirdPartyRequests; + + // Update the menu checkbox. + menuItem.setChecked(blockAllThirdPartyRequests); + + // Reload the main WebView. + mainWebView.reload(); + return true; + case R.id.share: // Setup the share string. String shareString = webViewTitle + " – " + urlTextBox.getText().toString(); @@ -3248,6 +3318,10 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook } private void loadUrl(String url) {// Apply any custom domain settings. + // Set the URL as the formatted URL string so that checking third-party requests works correctly. + formattedUrlString = url; + + // Apply the domain settings. applyDomainSettings(url, true, false); // Set `urlIsLoading` to prevent changes in the user agent on websites with redirects from reloading the current website. @@ -3554,6 +3628,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook easyPrivacyEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYPRIVACY)) == 1); fanboysAnnoyanceListEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST)) == 1); fanboysSocialBlockingListEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST)) == 1); + blockAllThirdPartyRequests = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS)) == 1); String userAgentName = currentHostDomainSettingsCursor.getString(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.USER_AGENT)); int fontSize = currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.FONT_SIZE)); int swipeToRefreshInt = currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SWIPE_TO_REFRESH)); @@ -3709,6 +3784,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook easyPrivacyEnabled = sharedPreferences.getBoolean("easyprivacy", true); fanboysAnnoyanceListEnabled = sharedPreferences.getBoolean("fanboy_annoyance_list", true); fanboysSocialBlockingListEnabled = sharedPreferences.getBoolean("fanboy_social_blocking_list", true); + blockAllThirdPartyRequests = sharedPreferences.getBoolean("block_all_third_party_requests", false); // Set `javaScriptEnabled` to be `true` if `night_mode` is `true`. if (nightMode) { diff --git a/app/src/main/java/com/stoutner/privacybrowser/activities/RequestsActivity.java b/app/src/main/java/com/stoutner/privacybrowser/activities/RequestsActivity.java index dcf64129..4b58053a 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/activities/RequestsActivity.java +++ b/app/src/main/java/com/stoutner/privacybrowser/activities/RequestsActivity.java @@ -86,6 +86,7 @@ public class RequestsActivity extends AppCompatActivity implements ViewRequestDi List allResourceRequests = new ArrayList<>(); List defaultResourceRequests = new ArrayList<>(); List allowedResourceRequests = new ArrayList<>(); + List thirdPartyResourceRequests = new ArrayList<>(); List blockedResourceRequests = new ArrayList<>(); // Populate the resource array lists. @@ -107,6 +108,14 @@ public class RequestsActivity extends AppCompatActivity implements ViewRequestDi allowedResourceRequests.add(request); break; + case MainWebViewActivity.REQUEST_THIRD_PARTY: + // Add the request to the list of all requests. + allResourceRequests.add(request); + + // Add the request to the list of third-party requests. + thirdPartyResourceRequests.add(request); + break; + case MainWebViewActivity.REQUEST_BLOCKED: // Add the request to the list of all requests. allResourceRequests.add(request); @@ -122,7 +131,10 @@ public class RequestsActivity extends AppCompatActivity implements ViewRequestDi spinnerCursor.addRow(new Object[]{0, getString(R.string.all) + " - " + allResourceRequests.size()}); spinnerCursor.addRow(new Object[]{1, getString(R.string.default_label) + " - " + defaultResourceRequests.size()}); spinnerCursor.addRow(new Object[]{2, getString(R.string.allowed_plural) + " - " + allowedResourceRequests.size()}); - spinnerCursor.addRow(new Object[]{3, getString(R.string.blocked_plural) + " - " + blockedResourceRequests.size()}); + if (MainWebViewActivity.blockAllThirdPartyRequests) { + spinnerCursor.addRow(new Object[]{3, getString(R.string.third_party_plural) + " - " + thirdPartyResourceRequests.size()}); + } + spinnerCursor.addRow(new Object[]{4, getString(R.string.blocked_plural) + " - " + blockedResourceRequests.size()}); // Create a resource cursor adapter for the spinner. ResourceCursorAdapter spinnerCursorAdapter = new ResourceCursorAdapter(this, R.layout.requests_spinner_item, spinnerCursor, 0) { @@ -147,7 +159,7 @@ public class RequestsActivity extends AppCompatActivity implements ViewRequestDi appBarSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView parent, View view, int position, long id) { - switch (position) { + switch ((int) id) { case 0: // All requests. // Get an adapter for all the request. ArrayAdapter allResourceRequestsArrayAdapter = new RequestsArrayAdapter(getApplicationContext(), allResourceRequests); @@ -172,7 +184,15 @@ public class RequestsActivity extends AppCompatActivity implements ViewRequestDi resourceRequestsListView.setAdapter(allowedResourceRequestsArrayAdapter); break; - case 3: // Blocked requests. + case 3: // Third-party requests. + // Get an adapter for the third-party requests. + ArrayAdapter thirdPartyResourceRequestsArrayAdapter = new RequestsArrayAdapter(getApplicationContext(), thirdPartyResourceRequests); + + //Display the adapter in the list view. + resourceRequestsListView.setAdapter(thirdPartyResourceRequestsArrayAdapter); + break; + + case 4: // Blocked requests. // Get an adapter fo the blocked requests. ArrayAdapter blockedResourceRequestsArrayAdapter = new RequestsArrayAdapter(getApplicationContext(), blockedResourceRequests); diff --git a/app/src/main/java/com/stoutner/privacybrowser/adapters/RequestsArrayAdapter.java b/app/src/main/java/com/stoutner/privacybrowser/adapters/RequestsArrayAdapter.java index e0c58cea..62dec5d8 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/adapters/RequestsArrayAdapter.java +++ b/app/src/main/java/com/stoutner/privacybrowser/adapters/RequestsArrayAdapter.java @@ -52,7 +52,7 @@ public class RequestsArrayAdapter extends ArrayAdapter { // Get handles for the views. LinearLayout linearLayout = view.findViewById(R.id.request_item_linearlayout); - TextView actionTextView = view.findViewById(R.id.request_item_action); + TextView dispositionTextView = view.findViewById(R.id.request_item_disposition); TextView urlTextView = view.findViewById(R.id.request_item_url); // Get the string array for this entry. @@ -71,7 +71,7 @@ public class RequestsArrayAdapter extends ArrayAdapter { String requestDefault = id + ". " + context.getResources().getString(R.string.allowed); // Set the disposition text. - actionTextView.setText(requestDefault); + dispositionTextView.setText(requestDefault); // Set the background color. linearLayout.setBackgroundColor(context.getResources().getColor(R.color.transparent)); @@ -82,7 +82,7 @@ public class RequestsArrayAdapter extends ArrayAdapter { String requestAllowed = id + ". " + context.getResources().getString(R.string.allowed); // Set the disposition text. - actionTextView.setText(requestAllowed); + dispositionTextView.setText(requestAllowed); // Set the background color. if (MainWebViewActivity.darkTheme) { @@ -92,17 +92,32 @@ public class RequestsArrayAdapter extends ArrayAdapter { } break; + case MainWebViewActivity.REQUEST_THIRD_PARTY: + // Create the disposition string. + String requestThirdParty = id + ". " + context.getResources().getString(R.string.blocked); + + // Set the disposition text. + dispositionTextView.setText(requestThirdParty); + + // Set the background color. + if (MainWebViewActivity.darkTheme) { + linearLayout.setBackgroundColor(context.getResources().getColor(R.color.yellow_700_50)); + } else { + linearLayout.setBackgroundColor(context.getResources().getColor(R.color.yellow_100)); + } + break; + case MainWebViewActivity.REQUEST_BLOCKED: // Create the disposition string. String requestBlocked = id + ". " + context.getResources().getString(R.string.blocked); // Set the disposition text. - actionTextView.setText(requestBlocked); + dispositionTextView.setText(requestBlocked); // Set the background color. if (MainWebViewActivity.darkTheme) { - linearLayout.setBackgroundColor(context.getResources().getColor(R.color.red_700_50)); + linearLayout.setBackgroundColor(context.getResources().getColor(R.color.red_700_40)); } else { linearLayout.setBackgroundColor(context.getResources().getColor(R.color.red_100)); } @@ -114,10 +129,10 @@ public class RequestsArrayAdapter extends ArrayAdapter { // Set the text color. For some unexplained reason, `android:textColor="?android:textColorPrimary"` doesn't work in the layout file. Probably some bug relating to array adapters. if (MainWebViewActivity.darkTheme) { - actionTextView.setTextColor(context.getResources().getColor(R.color.gray_200)); + dispositionTextView.setTextColor(context.getResources().getColor(R.color.gray_200)); urlTextView.setTextColor(context.getResources().getColor(R.color.gray_200)); } else { - actionTextView.setTextColor(context.getResources().getColor(R.color.black)); + dispositionTextView.setTextColor(context.getResources().getColor(R.color.black)); urlTextView.setTextColor(context.getResources().getColor(R.color.black)); } diff --git a/app/src/main/java/com/stoutner/privacybrowser/dialogs/ViewRequestDialog.java b/app/src/main/java/com/stoutner/privacybrowser/dialogs/ViewRequestDialog.java index 6969b32c..86b4f953 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/dialogs/ViewRequestDialog.java +++ b/app/src/main/java/com/stoutner/privacybrowser/dialogs/ViewRequestDialog.java @@ -142,7 +142,7 @@ public class ViewRequestDialog extends AppCompatDialogFragment { alertDialog.show(); // Get handles for the dialog views. - TextView requestAction = alertDialog.findViewById(R.id.request_action); + TextView requestDisposition = alertDialog.findViewById(R.id.request_disposition); TextView requestUrl = alertDialog.findViewById(R.id.request_url); TextView requestBlockListLabel = alertDialog.findViewById(R.id.request_blocklist_label); TextView requestBlockList = alertDialog.findViewById(R.id.request_blocklist); @@ -165,33 +165,45 @@ public class ViewRequestDialog extends AppCompatDialogFragment { switch (Integer.valueOf(requestDetails[MainWebViewActivity.REQUEST_DISPOSITION])) { case MainWebViewActivity.REQUEST_DEFAULT: // Set the text. - requestAction.setText(R.string.default_allowed); + requestDisposition.setText(R.string.default_allowed); // Set the background color. - requestAction.setBackgroundColor(getResources().getColor(R.color.transparent)); + requestDisposition.setBackgroundColor(getResources().getColor(R.color.transparent)); break; case MainWebViewActivity.REQUEST_ALLOWED: // Set the text. - requestAction.setText(R.string.allowed); + requestDisposition.setText(R.string.allowed); // Set the background color. if (MainWebViewActivity.darkTheme) { - requestAction.setBackgroundColor(getResources().getColor(R.color.blue_700_50)); + requestDisposition.setBackgroundColor(getResources().getColor(R.color.blue_700_50)); } else { - requestAction.setBackgroundColor(getResources().getColor(R.color.blue_100)); + requestDisposition.setBackgroundColor(getResources().getColor(R.color.blue_100)); + } + break; + + case MainWebViewActivity.REQUEST_THIRD_PARTY: + // Set the text. + requestDisposition.setText(R.string.third_party_blocked); + + // Set the background color. + if (MainWebViewActivity.darkTheme) { + requestDisposition.setBackgroundColor(getResources().getColor(R.color.yellow_700_50)); + } else { + requestDisposition.setBackgroundColor(getResources().getColor(R.color.yellow_100)); } break; case MainWebViewActivity.REQUEST_BLOCKED: // Set the text. - requestAction.setText(R.string.blocked); + requestDisposition.setText(R.string.blocked); // Set the background color. if (MainWebViewActivity.darkTheme) { - requestAction.setBackgroundColor(getResources().getColor(R.color.red_700_50)); + requestDisposition.setBackgroundColor(getResources().getColor(R.color.red_700_40)); } else { - requestAction.setBackgroundColor(getResources().getColor(R.color.red_100)); + requestDisposition.setBackgroundColor(getResources().getColor(R.color.red_100)); } break; } diff --git a/app/src/main/java/com/stoutner/privacybrowser/fragments/AboutTabFragment.java b/app/src/main/java/com/stoutner/privacybrowser/fragments/AboutTabFragment.java index 57048f70..fbc487e9 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/fragments/AboutTabFragment.java +++ b/app/src/main/java/com/stoutner/privacybrowser/fragments/AboutTabFragment.java @@ -181,8 +181,8 @@ public class AboutTabFragment extends Fragment { SpannableStringBuilder chromeStringBuilder = new SpannableStringBuilder(chromeLabel + chrome); SpannableStringBuilder easyListStringBuilder = new SpannableStringBuilder(easyListLabel + MainWebViewActivity.easyListVersion); SpannableStringBuilder easyPrivacyStringBuilder = new SpannableStringBuilder(easyPrivacyLabel + MainWebViewActivity.easyPrivacyVersion); - SpannableStringBuilder fanboyAnnoyanceStringBuilder = new SpannableStringBuilder(fanboyAnnoyanceLabel + MainWebViewActivity.fanboyAnnoyanceVersion); - SpannableStringBuilder fanboySocialStringBuilder = new SpannableStringBuilder(fanboySocialLabel + MainWebViewActivity.fanboySocialVersion); + SpannableStringBuilder fanboyAnnoyanceStringBuilder = new SpannableStringBuilder(fanboyAnnoyanceLabel + MainWebViewActivity.fanboysAnnoyanceVersion); + SpannableStringBuilder fanboySocialStringBuilder = new SpannableStringBuilder(fanboySocialLabel + MainWebViewActivity.fanboysSocialVersion); // Create the `blueColorSpan` variable. ForegroundColorSpan blueColorSpan; diff --git a/app/src/main/java/com/stoutner/privacybrowser/fragments/DomainSettingsFragment.java b/app/src/main/java/com/stoutner/privacybrowser/fragments/DomainSettingsFragment.java index 90b999ce..51337fb7 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/fragments/DomainSettingsFragment.java +++ b/app/src/main/java/com/stoutner/privacybrowser/fragments/DomainSettingsFragment.java @@ -120,6 +120,8 @@ public class DomainSettingsFragment extends Fragment { ImageView fanboysAnnoyanceListImageView = domainSettingsView.findViewById(R.id.domain_settings_fanboys_annoyance_list_imageview); Switch fanboysSocialBlockingListSwitch = domainSettingsView.findViewById(R.id.domain_settings_fanboys_social_blocking_list_switch); ImageView fanboysSocialBlockingListImageView = domainSettingsView.findViewById(R.id.domain_settings_fanboys_social_blocking_list_imageview); + Switch blockAllThirdPartyRequestsSwitch = domainSettingsView.findViewById(R.id.domain_settings_block_all_third_party_requests_switch); + ImageView blockAllThirdPartyRequestsImageView = domainSettingsView.findViewById(R.id.domain_settings_block_all_third_party_requests_imageview); final Spinner userAgentSpinner = domainSettingsView.findViewById(R.id.domain_settings_user_agent_spinner); final TextView userAgentTextView = domainSettingsView.findViewById(R.id.domain_settings_user_agent_textview); final EditText customUserAgentEditText = domainSettingsView.findViewById(R.id.domain_settings_custom_user_agent_edittext); @@ -186,6 +188,7 @@ public class DomainSettingsFragment extends Fragment { int easyPrivacyEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYPRIVACY)); int fanboysAnnoyanceListInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST)); int fanboysSocialBlockingListInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST)); + int blockAllThirdPartyRequestsInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS)); final String currentUserAgentName = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.USER_AGENT)); int fontSizeInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.FONT_SIZE)); int swipeToRefreshInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.SWIPE_TO_REFRESH)); @@ -589,6 +592,29 @@ public class DomainSettingsFragment extends Fragment { } } + // Set the third-party resource blocking status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons. + if (blockAllThirdPartyRequestsInt == 1) { // Blocking all third-party requests is on. + // Turn the switch on. + blockAllThirdPartyRequestsSwitch.setChecked(true); + + // Set the icon according to the theme. + if (MainWebViewActivity.darkTheme) { + blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_enabled_dark)); + } else { + blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_enabled_light)); + } + } else { // Blocking all third-party requests is off. + // Turn the switch off. + blockAllThirdPartyRequestsSwitch.setChecked(false); + + // Set the icon according to the theme. + if (MainWebViewActivity.darkTheme) { + blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_disabled_dark)); + } else { + blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_disabled_light)); + } + } + // Inflated a WebView to get the default user agent. // `@SuppressLint("InflateParams")` removes the warning about using `null` as the `ViewGroup`, which in this case makes sense because the bare WebView should not be displayed on the screen. @SuppressLint("InflateParams") View bareWebViewLayout = inflater.inflate(R.layout.bare_webview, null, false); @@ -1293,6 +1319,26 @@ public class DomainSettingsFragment extends Fragment { } }); + // Set the block all third-party requests switch listener. + blockAllThirdPartyRequestsSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> { + // Update the icon. + if (isChecked) { // Blocking all third-party requests is on. + // Set the icon according to the theme. + if (MainWebViewActivity.darkTheme) { + blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_enabled_dark)); + } else { + blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_enabled_light)); + } + } else { // Blocking all third-party requests is off. + // Set the icon according to the theme. + if (MainWebViewActivity.darkTheme) { + blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_disabled_dark)); + } else { + blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_disabled_light)); + } + } + }); + // Set the user agent spinner listener. userAgentSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override diff --git a/app/src/main/java/com/stoutner/privacybrowser/fragments/SettingsFragment.java b/app/src/main/java/com/stoutner/privacybrowser/fragments/SettingsFragment.java index aac9b0d3..19fa1e3a 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/fragments/SettingsFragment.java +++ b/app/src/main/java/com/stoutner/privacybrowser/fragments/SettingsFragment.java @@ -51,7 +51,7 @@ public class SettingsFragment extends PreferenceFragment { // Initialize savedPreferences. savedPreferences = getPreferenceScreen().getSharedPreferences(); - // Get handles for the preferences we need to modify. + // Get handles for the preferences. final Preference javaScriptPreference = findPreference("javascript_enabled"); final Preference firstPartyCookiesPreference = findPreference("first_party_cookies_enabled"); final Preference thirdPartyCookiesPreference = findPreference("third_party_cookies_enabled"); @@ -66,6 +66,7 @@ public class SettingsFragment extends PreferenceFragment { final Preference easyPrivacyPreference = findPreference("easyprivacy"); final Preference fanboyAnnoyanceListPreference = findPreference("fanboy_annoyance_list"); final Preference fanboySocialBlockingListPreference = findPreference("fanboy_social_blocking_list"); + final Preference blockAllThirdPartyRequestsPreference = findPreference("block_all_third_party_requests"); final Preference proxyThroughOrbotPreference = findPreference("proxy_through_orbot"); final Preference torHomepagePreference = findPreference("tor_homepage"); final Preference torSearchPreference = findPreference("tor_search"); @@ -423,6 +424,21 @@ public class SettingsFragment extends PreferenceFragment { } } + // Set the block all third-party requests icon. + if (savedPreferences.getBoolean("block_all_third_party_requests", false)) { + if (MainWebViewActivity.darkTheme) { + blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_dark); + } else { + blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_light); + } + } else { + if (MainWebViewActivity.darkTheme) { + blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_dark); + } else { + blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_light); + } + } + // Set the Tor icons according to the theme. if (proxyThroughOrbot) { // Proxying is enabled. if (MainWebViewActivity.darkTheme) { @@ -1003,6 +1019,23 @@ public class SettingsFragment extends PreferenceFragment { } break; + case "block_all_third_party_requests": + // Update the icon. + if (sharedPreferences.getBoolean("block_all_third_party_requests", false)) { + if (MainWebViewActivity.darkTheme) { + blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_dark); + } else { + blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_light); + } + } else { + if (MainWebViewActivity.darkTheme) { + blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_dark); + } else { + blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_light); + } + } + break; + case "proxy_through_orbot": // Get current settings. boolean currentProxyThroughOrbot = sharedPreferences.getBoolean("proxy_through_orbot", false); diff --git a/app/src/main/java/com/stoutner/privacybrowser/helpers/BlockListHelper.java b/app/src/main/java/com/stoutner/privacybrowser/helpers/BlockListHelper.java index 2adfb6f7..619537a9 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/helpers/BlockListHelper.java +++ b/app/src/main/java/com/stoutner/privacybrowser/helpers/BlockListHelper.java @@ -1580,24 +1580,14 @@ public class BlockListHelper { return combinedLists; } - public boolean isBlocked(String currentUrl, String resourceUrl, ArrayList> blockList) { + public boolean isBlocked(String currentDomain, String resourceUrl, boolean isThirdPartyRequest, ArrayList> blockList) { // Get the block list name. String BLOCK_LIST_NAME_STRING = blockList.get(0).get(1)[0]; - // Get the current domain. - Uri currentUri = Uri.parse(currentUrl); - String currentDomain = currentUri.getHost(); - - // Get the resource domain. - Uri resourceUri = Uri.parse(resourceUrl); - String resourceDomain = resourceUri.getHost(); - - // Initialize the third-party request tracker. - boolean thirdPartyRequest = false; - - // If one of the domains is `about:blank` it will throw a null object reference on the string comparison. - if ((currentDomain != null) && (resourceDomain != null)) { - thirdPartyRequest = !resourceDomain.equals(currentDomain); + // Assert that currentDomain != null only if this is a third party request. Apparently, lint can't tell that this isn't redundant. + //noinspection RedundantIfStatement + if (isThirdPartyRequest) { + assert currentDomain != null; } // Process the white lists. @@ -1786,7 +1776,7 @@ public class BlockListHelper { } // Only check the third-party white lists if this is a third-party request. - if (thirdPartyRequest) { + if (isThirdPartyRequest) { // Third-party white list. for (String[] whiteListEntry : blockList.get(MainWebViewActivity.THIRD_PARTY_WHITELIST)) { switch (whiteListEntry.length) { @@ -2115,7 +2105,7 @@ public class BlockListHelper { } // Only check the third-party black lists if this is a third-party request. - if (thirdPartyRequest) { + if (isThirdPartyRequest) { // Third-party black list. for (String[] blackListEntry : blockList.get(MainWebViewActivity.THIRD_PARTY_BLACKLIST)) { switch (blackListEntry.length) { diff --git a/app/src/main/java/com/stoutner/privacybrowser/helpers/DomainsDatabaseHelper.java b/app/src/main/java/com/stoutner/privacybrowser/helpers/DomainsDatabaseHelper.java index c495e73e..0c853e56 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/helpers/DomainsDatabaseHelper.java +++ b/app/src/main/java/com/stoutner/privacybrowser/helpers/DomainsDatabaseHelper.java @@ -28,7 +28,7 @@ import android.database.sqlite.SQLiteOpenHelper; import android.preference.PreferenceManager; public class DomainsDatabaseHelper extends SQLiteOpenHelper { - private static final int SCHEMA_VERSION = 6; + private static final int SCHEMA_VERSION = 7; private static final String DOMAINS_DATABASE = "domains.db"; private static final String DOMAINS_TABLE = "domains"; @@ -42,6 +42,7 @@ public class DomainsDatabaseHelper extends SQLiteOpenHelper { public static final String ENABLE_EASYLIST = "enableeasylist"; public static final String ENABLE_EASYPRIVACY = "enableeasyprivacy"; public static final String ENABLE_FANBOYS_ANNOYANCE_LIST = "enablefanboysannoyancelist"; + public static final String BLOCK_ALL_THIRD_PARTY_REQUESTS = "blockallthirdpartyrequests"; public static final String ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST = "enablefanboyssocialblockinglist"; public static final String USER_AGENT = "useragent"; public static final String FONT_SIZE = "fontsize"; @@ -98,6 +99,7 @@ public class DomainsDatabaseHelper extends SQLiteOpenHelper { ENABLE_EASYPRIVACY + " BOOLEAN, " + ENABLE_FANBOYS_ANNOYANCE_LIST + " BOOLEAN, " + ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST + " BOOLEAN, " + + BLOCK_ALL_THIRD_PARTY_REQUESTS + " BOOLEAN, " + USER_AGENT + " TEXT, " + FONT_SIZE + " INTEGER, " + SWIPE_TO_REFRESH + " INTEGER, " + @@ -193,6 +195,11 @@ public class DomainsDatabaseHelper extends SQLiteOpenHelper { case 5: // Add the swipe to refresh column. domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + SWIPE_TO_REFRESH + " INTEGER"); + + // Upgrade from schema version 6. + case 6: + // Add the block all third-party requests column. + domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + BLOCK_ALL_THIRD_PARTY_REQUESTS + " BOOLEAN"); } } @@ -261,6 +268,7 @@ public class DomainsDatabaseHelper extends SQLiteOpenHelper { boolean easyPrivacyEnabled = sharedPreferences.getBoolean("easyprivacy", true); boolean fanboyAnnoyanceListEnabled = sharedPreferences.getBoolean("fanboy_annoyance_list", true); boolean fanboySocialBlockingListEnabled = sharedPreferences.getBoolean("fanboy_social_blocking_list", true); + boolean blockAllThirdPartyRequests = sharedPreferences.getBoolean("block_all_third_party_requests", false); // Create entries for the database fields. The ID is created automatically. The pinned SSL certificate information is not created unless added by the user. domainContentValues.put(DOMAIN_NAME, domainName); @@ -273,6 +281,7 @@ public class DomainsDatabaseHelper extends SQLiteOpenHelper { domainContentValues.put(ENABLE_EASYPRIVACY, easyPrivacyEnabled); domainContentValues.put(ENABLE_FANBOYS_ANNOYANCE_LIST, fanboyAnnoyanceListEnabled); domainContentValues.put(ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST, fanboySocialBlockingListEnabled); + domainContentValues.put(BLOCK_ALL_THIRD_PARTY_REQUESTS, blockAllThirdPartyRequests); domainContentValues.put(USER_AGENT, "System default user agent"); domainContentValues.put(FONT_SIZE, 0); domainContentValues.put(SWIPE_TO_REFRESH, 0); @@ -294,7 +303,7 @@ public class DomainsDatabaseHelper extends SQLiteOpenHelper { public void updateDomainExceptCertificate(int databaseId, String domainName, boolean javaScriptEnabled, boolean firstPartyCookiesEnabled, boolean thirdPartyCookiesEnabled, boolean domStorageEnabled, boolean formDataEnabled, boolean easyListEnabled, boolean easyPrivacyEnabled, boolean fanboysAnnoyanceEnabled, boolean fanboysSocialBlockingEnabled, - String userAgent, int fontSize, int swipeToRefresh, int nightMode, int displayImages, boolean pinnedSslCertificate) { + boolean blockAllThirdPartyRequests, String userAgent, int fontSize, int swipeToRefresh, int nightMode, int displayImages, boolean pinnedSslCertificate) { // Store the domain data in a `ContentValues`. ContentValues domainContentValues = new ContentValues(); @@ -310,6 +319,7 @@ public class DomainsDatabaseHelper extends SQLiteOpenHelper { domainContentValues.put(ENABLE_EASYPRIVACY, easyPrivacyEnabled); domainContentValues.put(ENABLE_FANBOYS_ANNOYANCE_LIST, fanboysAnnoyanceEnabled); domainContentValues.put(ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST, fanboysSocialBlockingEnabled); + domainContentValues.put(BLOCK_ALL_THIRD_PARTY_REQUESTS, blockAllThirdPartyRequests); domainContentValues.put(USER_AGENT, userAgent); domainContentValues.put(FONT_SIZE, fontSize); domainContentValues.put(SWIPE_TO_REFRESH, swipeToRefresh); @@ -328,10 +338,10 @@ public class DomainsDatabaseHelper extends SQLiteOpenHelper { } public void updateDomainWithCertificate(int databaseId, String domainName, boolean javaScriptEnabled, boolean firstPartyCookiesEnabled, boolean thirdPartyCookiesEnabled, boolean domStorageEnabled, - boolean formDataEnabled, boolean easyListEnabled, boolean easyPrivacyEnabled, boolean fanboysAnnoyanceEnabled, boolean fanboysSocialBlockingEnabled, String userAgent, - int fontSize, int swipeToRefresh, int nightMode, int displayImages, boolean pinnedSslCertificate, String sslIssuedToCommonName, String sslIssuedToOrganization, - String sslIssuedToOrganizationalUnit, String sslIssuedByCommonName, String sslIssuedByOrganization, String sslIssuedByOrganizationalUnit, long sslStartDate, - long sslEndDate) { + boolean formDataEnabled, boolean easyListEnabled, boolean easyPrivacyEnabled, boolean fanboysAnnoyanceEnabled, boolean fanboysSocialBlockingEnabled, + boolean blockAllThirdPartyRequests, String userAgent, int fontSize, int swipeToRefresh, int nightMode, int displayImages, boolean pinnedSslCertificate, + String sslIssuedToCommonName, String sslIssuedToOrganization, String sslIssuedToOrganizationalUnit, String sslIssuedByCommonName, String sslIssuedByOrganization, + String sslIssuedByOrganizationalUnit, long sslStartDate, long sslEndDate) { // Store the domain data in a `ContentValues`. ContentValues domainContentValues = new ContentValues(); @@ -347,6 +357,7 @@ public class DomainsDatabaseHelper extends SQLiteOpenHelper { domainContentValues.put(ENABLE_EASYPRIVACY, easyPrivacyEnabled); domainContentValues.put(ENABLE_FANBOYS_ANNOYANCE_LIST, fanboysAnnoyanceEnabled); domainContentValues.put(ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST, fanboysSocialBlockingEnabled); + domainContentValues.put(BLOCK_ALL_THIRD_PARTY_REQUESTS, blockAllThirdPartyRequests); domainContentValues.put(USER_AGENT, userAgent); domainContentValues.put(FONT_SIZE, fontSize); domainContentValues.put(SWIPE_TO_REFRESH, swipeToRefresh); diff --git a/app/src/main/res/drawable/allow_screenshots_disabled_dark.xml b/app/src/main/res/drawable/allow_screenshots_disabled_dark.xml index 33234b98..b320afb2 100644 --- a/app/src/main/res/drawable/allow_screenshots_disabled_dark.xml +++ b/app/src/main/res/drawable/allow_screenshots_disabled_dark.xml @@ -1,9 +1,10 @@ - + - + - + - + + + + + + diff --git a/app/src/main/res/drawable/block_all_third_party_requests_disabled_light.xml b/app/src/main/res/drawable/block_all_third_party_requests_disabled_light.xml new file mode 100644 index 00000000..21db2f97 --- /dev/null +++ b/app/src/main/res/drawable/block_all_third_party_requests_disabled_light.xml @@ -0,0 +1,14 @@ + + + + + + diff --git a/app/src/main/res/drawable/block_all_third_party_requests_enabled_dark.xml b/app/src/main/res/drawable/block_all_third_party_requests_enabled_dark.xml new file mode 100644 index 00000000..c5b66784 --- /dev/null +++ b/app/src/main/res/drawable/block_all_third_party_requests_enabled_dark.xml @@ -0,0 +1,14 @@ + + + + + + diff --git a/app/src/main/res/drawable/block_all_third_party_requests_enabled_light.xml b/app/src/main/res/drawable/block_all_third_party_requests_enabled_light.xml new file mode 100644 index 00000000..2dda9112 --- /dev/null +++ b/app/src/main/res/drawable/block_all_third_party_requests_enabled_light.xml @@ -0,0 +1,14 @@ + + + + + + diff --git a/app/src/main/res/layout/domain_settings_fragment.xml b/app/src/main/res/layout/domain_settings_fragment.xml index 64d3747f..da292457 100644 --- a/app/src/main/res/layout/domain_settings_fragment.xml +++ b/app/src/main/res/layout/domain_settings_fragment.xml @@ -294,7 +294,7 @@ android:layout_marginStart="8dp" android:layout_marginTop="14dp" android:layout_marginBottom="14dp" - android:text="@string/fanboy_annoyance_list" + android:text="@string/fanboys_annoyance_list" android:textColor="?android:textColorPrimary" android:textSize="18sp" /> @@ -321,7 +321,34 @@ android:layout_marginStart="8dp" android:layout_marginTop="14dp" android:layout_marginBottom="14dp" - android:text="@string/fanboy_social_blocking_list" + android:text="@string/fanboys_social_blocking_list" + android:textColor="?android:textColorPrimary" + android:textSize="18sp" /> + + + + + + + + diff --git a/app/src/main/res/layout/requests_item_linearlayout.xml b/app/src/main/res/layout/requests_item_linearlayout.xml index 33d48cbf..b0489d74 100644 --- a/app/src/main/res/layout/requests_item_linearlayout.xml +++ b/app/src/main/res/layout/requests_item_linearlayout.xml @@ -26,7 +26,7 @@ android:orientation="horizontal"> + + diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 8c17b837..d2ce68b7 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -72,7 +72,7 @@ #FFEF9A9A #FFE53935 #FFD32F2F - #55D32F2F + #55D32F2F #FFC62828 #FFB71C1C #FFD50000 @@ -81,6 +81,8 @@ #FFFFFFFF + #FFFFF9C4 + #88FBC02D #FFF57F17 #FFFFD600 \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 5bbcecbc..23efb274 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -133,6 +133,7 @@ Clear Form Data Fanboy’s Annoyance List Fanboy’s Social Blocking List + Block All Third-Party Requests Layout Font Size 25% @@ -233,6 +234,8 @@ Default - Allowed Allowed Allowed + Third-party + Third-party - Blocked Blocked Blocked Blocklist @@ -389,6 +392,8 @@ Block annoying popups and links. Includes Fanboy’s social blocking lists. Fanboy’s social blocking list Blocks third-party social media content. + Block all third-party requests + Blocking all third-party requests increases privacy, but it breaks many websites. Tor Proxy through Orbot Proxy all web traffic through Orbot on localhost:8118. diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index c3687d0c..4549040a 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -115,6 +115,12 @@ android:title="@string/fanboys_social_blocking_list" android:summary="@string/fanboys_social_blocking_list_summary" android:defaultValue="true" /> + +