]> gitweb.stoutner.com Git - PrivacyBrowserAndroid.git/blobdiff - app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java
Change the default search engine to Searx. https://redmine.stoutner.com/issues/308
[PrivacyBrowserAndroid.git] / app / src / main / java / com / stoutner / privacybrowser / activities / MainWebViewActivity.java
index e7d7c66184203bdf289349e6ece38aba6650fcdc..bbaff98dd8f74741f5ec9830e30f34588af1731d 100644 (file)
@@ -173,7 +173,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     // and `ViewSslCertificateDialog`.  It is also used in `onCreate()`.
     public static SslCertificate sslCertificate;
 
-    // `orbotStatus` is public static so it can be accessed from `OrbotProxyHelper`.  It is also used in `onCreate()`.
+    // `orbotStatus` is public static so it can be accessed from `OrbotProxyHelper`.  It is also used in `onCreate()` and `onResume()`.
     public static String orbotStatus;
 
     // `webViewTitle` is public static so it can be accessed from `CreateBookmarkDialog` and `CreateHomeScreenShortcutDialog`.  It is also used in `onCreate()`.
@@ -194,8 +194,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     // The block list versions are public static so they can be accessed from `AboutTabFragment`.  They are also used in `onCreate()`.
     public static String easyListVersion;
     public static String easyPrivacyVersion;
-    public static String fanboyAnnoyanceVersion;
-    public static String fanboySocialVersion;
+    public static String fanboysAnnoyanceVersion;
+    public static String fanboysSocialVersion;
+    public static String ultraPrivacyVersion;
 
     // The request items are public static so they can be accessed by `BlockListHelper`, `RequestsArrayAdapter`, and `ViewRequestsDialog`.  They are also used in `onCreate()`.
     public static List<String[]> resourceRequests;
@@ -209,7 +210,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 +237,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;
@@ -283,7 +289,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     // `fullScreenVideoFrameLayout` is used in `onCreate()` and `onConfigurationChanged()`.
     private FrameLayout fullScreenVideoFrameLayout;
 
-    // `swipeRefreshLayout` is used in `onCreate()`, `onPrepareOptionsMenu()`, `onOptionsMenuSelected()`, and `onRestart()`.
+    // `swipeRefreshLayout` is used in `onCreate()`, `onPrepareOptionsMenu()`, `onOptionsItemSelected()`, and `onRestart()`.
     private SwipeRefreshLayout swipeRefreshLayout;
 
     // `urlAppBarRelativeLayout` is used in `onCreate()` and `applyDomainSettings()`.
@@ -325,11 +331,12 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     // `searchURL` is used in `loadURLFromTextBox()` and `applyAppSettings()`.
     private String searchURL;
 
-    // The block list variables are used in `onCreate()` and `applyAppSettings()`.
+    // The block list variables are used in `onCreate()`, `onPrepareOptionsMenu()`, `onOptionsItemSelected()`, and `applyAppSettings()`.
     private boolean easyListEnabled;
     private boolean easyPrivacyEnabled;
     private boolean fanboysAnnoyanceListEnabled;
     private boolean fanboysSocialBlockingListEnabled;
+    private boolean ultraPrivacyEnabled;
 
     // `privacyBrowserRuntime` is used in `onCreate()`, `onOptionsItemSelected()`, and `applyAppSettings()`.
     private Runtime privacyBrowserRuntime;
@@ -358,13 +365,16 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     // `reapplyAppSettingsOnRestart` is used in `onNavigationItemSelected()` and `onRestart()`.
     private boolean reapplyAppSettingsOnRestart;
 
+    // `displayingFullScreenVideo` is used in `onCreate()` and `onResume()`.
+    private boolean displayingFullScreenVideo;
+
     // `currentDomainName` is used in `onCreate()`, `onOptionsItemSelected()`, `onNavigationItemSelected()`, `onAddDomain()`, and `applyDomainSettings()`.
     private String currentDomainName;
 
     // `ignorePinnedSslCertificateForDomain` is used in `onCreate()`, `onSslMismatchProceed()`, and `applyDomainSettings()`.
     private boolean ignorePinnedSslCertificate;
 
-    // `waitingForOrbot` is used in `onCreate()` and `applyAppSettings()`.
+    // `waitingForOrbot` is used in `onCreate()`, `onResume()`, and `applyAppSettings()`.
     private boolean waitingForOrbot;
 
     // `domainSettingsApplied` is used in `prepareOptionsMenu()`, `applyDomainSettings()`, and `setDisplayWebpageImages()`.
@@ -874,9 +884,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.
@@ -975,6 +991,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             // Enter full screen video.
             @Override
             public void onShowCustomView(View view, CustomViewCallback callback) {
+                // Set the full screen video flag.
+                displayingFullScreenVideo = true;
+
                 // Pause the ad if this is the free flavor.
                 if (BuildConfig.FLAVOR.contentEquals("free")) {
                     // The AdView is destroyed and recreated, which changes the ID, every time it is reloaded to handle possible rotations.
@@ -996,6 +1015,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 // Set `rootCoordinatorLayout` to fill the entire screen.
                 rootCoordinatorLayout.setFitsSystemWindows(false);
 
+                // Disable the sliding drawers.
+                drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
+
                 // Add `view` to `fullScreenVideoFrameLayout` and display it on the screen.
                 fullScreenVideoFrameLayout.addView(view);
                 fullScreenVideoFrameLayout.setVisibility(View.VISIBLE);
@@ -1004,15 +1026,72 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             // Exit full screen video.
             @Override
             public void onHideCustomView() {
+                // Unset the full screen video flag.
+                displayingFullScreenVideo = true;
+
                 // Hide `fullScreenVideoFrameLayout`.
                 fullScreenVideoFrameLayout.removeAllViews();
                 fullScreenVideoFrameLayout.setVisibility(View.GONE);
 
-                // Add the translucent status flag.  This also resets `drawerLayout's` `View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN`.
-                getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+                // Enable the sliding drawers.
+                drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
+
+                // Apply the appropriate full screen mode the `SYSTEM_UI` flags.
+                if (fullScreenBrowsingModeEnabled && inFullScreenBrowsingMode) {  // Privacy Browser is currently in full screen browsing mode.
+                    if (hideSystemBarsOnFullscreen) {  // Hide everything.
+                        // Remove the translucent navigation setting if it is currently flagged.
+                        getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
+
+                        // Remove the translucent status bar overlay.
+                        getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
 
-                // Set `rootCoordinatorLayout` to fit inside the status and navigation bars.  This also clears the `SYSTEM_UI` flags.
-                rootCoordinatorLayout.setFitsSystemWindows(true);
+                        // Remove the translucent status bar overlay on the `Drawer Layout`, which is special and needs its own command.
+                        drawerLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
+
+                        /* SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen.
+                         * SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bar on the bottom or right of the screen.
+                         * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically re-hides them after they are shown.
+                         */
+                        rootCoordinatorLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
+                    } else {  // Hide everything except the status and navigation bars.
+                        // Remove any `SYSTEM_UI` flags from `rootCoordinatorLayout`.
+                        rootCoordinatorLayout.setSystemUiVisibility(0);
+
+                        // Add the translucent status flag if it is unset.
+                        getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+
+                        if (translucentNavigationBarOnFullscreen) {
+                            // Set the navigation bar to be translucent.  This also resets `drawerLayout's` `View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN`.
+                            getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
+                        } else {
+                            // Set the navigation bar to be black.
+                            getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
+                        }
+                    }
+                } else {  // Switch to normal viewing mode.
+                    // Show the `appBar` if `findOnPageLinearLayout` is not visible.
+                    if (findOnPageLinearLayout.getVisibility() == View.GONE) {
+                        appBar.show();
+                    }
+
+                    // Show the `BannerAd` in the free flavor.
+                    if (BuildConfig.FLAVOR.contentEquals("free")) {
+                        // Initialize the ad.  The AdView is destroyed and recreated, which changes the ID, every time it is reloaded to handle possible rotations.
+                        AdHelper.initializeAds(findViewById(R.id.adview), getApplicationContext(), getFragmentManager(), getString(R.string.ad_id));
+                    }
+
+                    // Remove any `SYSTEM_UI` flags from `rootCoordinatorLayout`.
+                    rootCoordinatorLayout.setSystemUiVisibility(0);
+
+                    // Remove the translucent navigation bar flag if it is set.
+                    getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
+
+                    // Add the translucent status flag if it is unset.  This also resets `drawerLayout's` `View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN`.
+                    getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+
+                    // Constrain `rootCoordinatorLayout` inside the status and navigation bars.
+                    rootCoordinatorLayout.setFitsSystemWindows(true);
+                }
 
                 // Show the ad if this is the free flavor.
                 if (BuildConfig.FLAVOR.contentEquals("free")) {
@@ -1156,14 +1235,16 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         // Parse the block lists.
         final ArrayList<List<String[]>> easyList = blockListHelper.parseBlockList(getAssets(), "blocklists/easylist.txt");
         final ArrayList<List<String[]>> easyPrivacy = blockListHelper.parseBlockList(getAssets(), "blocklists/easyprivacy.txt");
-        final ArrayList<List<String[]>> fanboyAnnoyance = blockListHelper.parseBlockList(getAssets(), "blocklists/fanboy-annoyance.txt");
-        final ArrayList<List<String[]>> fanboySocial = blockListHelper.parseBlockList(getAssets(), "blocklists/fanboy-social.txt");
+        final ArrayList<List<String[]>> fanboysAnnoyanceList = blockListHelper.parseBlockList(getAssets(), "blocklists/fanboy-annoyance.txt");
+        final ArrayList<List<String[]>> fanboysSocialList = blockListHelper.parseBlockList(getAssets(), "blocklists/fanboy-social.txt");
+        final ArrayList<List<String[]>> ultraPrivacy = blockListHelper.parseBlockList(getAssets(), "blocklists/ultraprivacy.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];
+        ultraPrivacyVersion = ultraPrivacy.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.
@@ -1172,6 +1253,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             @Override
             public boolean shouldOverrideUrlLoading(WebView view, String url) {
                 if (url.startsWith("http")) {  // Load the URL in Privacy Browser.
+                    // Reset the formatted URL string so the page will load correctly if blocking of third-party requests is enabled.
+                    formattedUrlString = "";
+
                     // Apply the domain settings for the new URL.  `applyDomainSettings` doesn't do anything if the domain has not changed.
                     applyDomainSettings(url, true, false);
 
@@ -1239,12 +1323,79 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 // Create an empty web resource response to be used if the resource request is blocked.
                 WebResourceResponse emptyWebResourceResponse = new WebResourceResponse("text/plain", "utf8", new ByteArrayInputStream("".getBytes()));
 
-                // Reset `whiteListResultStringArray`.
+                // Reset the whitelist results tracker.
                 whiteListResultStringArray = null;
 
+                // Initialize the third party request tracker.
+                boolean isThirdPartyRequest = false;
+
+                // Initialize the current domain string.
+                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 UltraPrivacy if it is enabled.
+                if (ultraPrivacyEnabled) {
+                    if (blockListHelper.isBlocked(currentDomain, url, isThirdPartyRequest, ultraPrivacy)) {
+                        // The resource request was blocked.  Return an empty web resource response.
+                        return emptyWebResourceResponse;
+                    }
+
+                    // If the whitelist result is not null, the request has been allowed by UltraPrivacy.
+                    if (whiteListResultStringArray != null) {
+                        // Add a whitelist entry to the resource requests array.
+                        resourceRequests.add(whiteListResultStringArray);
+
+                        // The resource request has been allowed by UltraPrivacy.  `return null` loads the requested resource.
+                        return null;
+                    }
+                }
+
                 // Check EasyList if it is enabled.
                 if (easyListEnabled) {
-                    if (blockListHelper.isBlocked(formattedUrlString, url, easyList)) {
+                    if (blockListHelper.isBlocked(currentDomain, url, isThirdPartyRequest, easyList)) {
+                        // Reset the whitelist results tracker (because otherwise it will sometimes add results to the list due to a race condition).
+                        whiteListResultStringArray = null;
+
                         // The resource request was blocked.  Return an empty web resource response.
                         return emptyWebResourceResponse;
                     }
@@ -1252,7 +1403,10 @@ 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)) {
+                        // Reset the whitelist results tracker (because otherwise it will sometimes add results to the list due to a race condition).
+                        whiteListResultStringArray = null;
+
                         // The resource request was blocked.  Return an empty web resource response.
                         return emptyWebResourceResponse;
                     }
@@ -1260,18 +1414,24 @@ 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)) {
+                        // Reset the whitelist results tracker (because otherwise it will sometimes add results to the list due to a race condition).
+                        whiteListResultStringArray = null;
+
                         // 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)) {
+                        // Reset the whitelist results tracker (because otherwise it will sometimes add results to the list due to a race condition).
+                        whiteListResultStringArray = null;
+
                         // 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.
@@ -1320,6 +1480,10 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
                     // Apply any custom domain settings if the URL was loaded by navigating history.
                     if (navigatingHistory) {
+                        // Reset `navigatingHistory`.
+                        navigatingHistory = false;
+
+                        // Apply the domain settings.
                         applyDomainSettings(url, true, false);
                     }
 
@@ -1505,12 +1669,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)) {
@@ -1610,26 +1773,46 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
         // Resume the adView for the free flavor.
         if (BuildConfig.FLAVOR.contentEquals("free")) {
-            // The AdView is destroyed and recreated, which changes the ID, every time it is reloaded to handle possible rotations.
+            // Resume the ad.
             AdHelper.resumeAd(findViewById(R.id.adview));
         }
+
+        // Display a message to the user if waiting for Orbot.
+        if (waitingForOrbot && !orbotStatus.equals("ON")) {
+            // Load a waiting page.  `null` specifies no encoding, which defaults to ASCII.
+            mainWebView.loadData(waitingForOrbotHTMLString, "text/html", null);
+        }
+
+        if (displayingFullScreenVideo) {
+            // Remove the translucent overlays.
+            getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+
+            // Remove the translucent status bar overlay on the `Drawer Layout`, which is special and needs its own command.
+            drawerLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
+
+            /* SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen.
+             * SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bar on the bottom or right of the screen.
+             * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically re-hides them after they are shown.
+             */
+            rootCoordinatorLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
+        }
     }
 
     @Override
     public void onPause() {
+        super.onPause();
+
         // Pause `mainWebView`.
         mainWebView.onPause();
 
         // Stop all JavaScript.
         mainWebView.pauseTimers();
 
-        // Pause the adView or it will continue to consume resources in the background on the free flavor.
+        // Pause the ad or it will continue to consume resources in the background on the free flavor.
         if (BuildConfig.FLAVOR.contentEquals("free")) {
-            // The AdView is destroyed and recreated, which changes the ID, every time it is reloaded to handle possible rotations.
+            // Pause the ad.
             AdHelper.pauseAd(findViewById(R.id.adview));
         }
-
-        super.onPause();
     }
 
     @Override
@@ -1691,6 +1874,12 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         MenuItem clearCookiesMenuItem = menu.findItem(R.id.clear_cookies);
         MenuItem clearDOMStorageMenuItem = menu.findItem(R.id.clear_dom_storage);
         MenuItem clearFormDataMenuItem = menu.findItem(R.id.clear_form_data);  // Form data can be removed once the minimum API >= 26.
+        MenuItem easyListMenuItem = menu.findItem(R.id.easylist);
+        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 ultraPrivacyMenuItem = menu.findItem(R.id.ultraprivacy);
+        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);
@@ -1707,44 +1896,53 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         toggleThirdPartyCookiesMenuItem.setChecked(thirdPartyCookiesEnabled);
         toggleDomStorageMenuItem.setChecked(domStorageEnabled);
         toggleSaveFormDataMenuItem.setChecked(saveFormDataEnabled);  // Form data can be removed once the minimum API >= 26.
+        easyListMenuItem.setChecked(easyListEnabled);
+        easyPrivacyMenuItem.setChecked(easyPrivacyEnabled);
+        fanboysAnnoyanceListMenuItem.setChecked(fanboysAnnoyanceListEnabled);
+        fanboysSocialBlockingListMenuItem.setChecked(fanboysSocialBlockingListEnabled);
+        ultraPrivacyMenuItem.setChecked(ultraPrivacyEnabled);
+        blockAllThirdParyRequestsMenuItem.setChecked(blockAllThirdPartyRequests);
         swipeToRefreshMenuItem.setChecked(swipeRefreshLayout.isEnabled());
         displayImagesMenuItem.setChecked(mainWebView.getSettings().getLoadsImagesAutomatically());
 
         // Enable third-party cookies if first-party cookies are enabled.
         toggleThirdPartyCookiesMenuItem.setEnabled(firstPartyCookiesEnabled);
 
-        // Enable `DOM Storage` if JavaScript is enabled.
+        // Enable DOM Storage if JavaScript is enabled.
         toggleDomStorageMenuItem.setEnabled(javaScriptEnabled);
 
-        // Enable `Clear Cookies` if there are any.
+        // Enable Clear Cookies if there are any.
         clearCookiesMenuItem.setEnabled(cookieManager.hasCookies());
 
-        // Get a count of the number of files in the `Local Storage` directory.
+        // Get a count of the number of files in the Local Storage directory.
         File localStorageDirectory = new File (privateDataDirectoryString + "/app_webview/Local Storage/");
         int localStorageDirectoryNumberOfFiles = 0;
         if (localStorageDirectory.exists()) {
             localStorageDirectoryNumberOfFiles = localStorageDirectory.list().length;
         }
 
-        // Get a count of the number of files in the `IndexedDB` directory.
+        // Get a count of the number of files in the IndexedDB directory.
         File indexedDBDirectory = new File (privateDataDirectoryString + "/app_webview/IndexedDB");
         int indexedDBDirectoryNumberOfFiles = 0;
         if (indexedDBDirectory.exists()) {
             indexedDBDirectoryNumberOfFiles = indexedDBDirectory.list().length;
         }
 
-        // Enable `Clear DOM Storage` if there is any.
+        // Enable Clear DOM Storage if there is any.
         clearDOMStorageMenuItem.setEnabled(localStorageDirectoryNumberOfFiles > 0 || indexedDBDirectoryNumberOfFiles > 0);
 
-        // Enable `Clear Form Data` is there is any.  This can be removed once the minimum API >= 26.
+        // Enable Clear Form Data is there is any.  This can be removed once the minimum API >= 26.
         if (Build.VERSION.SDK_INT < 26) {
             WebViewDatabase mainWebViewDatabase = WebViewDatabase.getInstance(this);
             clearFormDataMenuItem.setEnabled(mainWebViewDatabase.hasFormData());
         }
 
-        // Enable `Clear Data` if any of the submenu items are enabled.
+        // Enable Clear Data if any of the submenu items are enabled.
         clearDataMenuItem.setEnabled(clearCookiesMenuItem.isEnabled() || clearDOMStorageMenuItem.isEnabled() || clearFormDataMenuItem.isEnabled());
 
+        // Disable Fanboy's Social Blocking List if Fanboy's Annoyance List is checked.
+        fanboysSocialBlockingListMenuItem.setEnabled(!fanboysAnnoyanceListEnabled);
+
         // Initialize font size variables.
         int fontSize = mainWebView.getSettings().getTextZoom();
         String fontSizeTitle;
@@ -2132,6 +2330,76 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 startActivity(viewSourceIntent);
                 return true;
 
+            case R.id.easylist:
+                // Toggle the EasyList status.
+                easyListEnabled = !easyListEnabled;
+
+                // Update the menu checkbox.
+                menuItem.setChecked(easyListEnabled);
+
+                // Reload the main WebView.
+                mainWebView.reload();
+                return true;
+
+            case R.id.easyprivacy:
+                // Toggle the EasyPrivacy status.
+                easyPrivacyEnabled = !easyPrivacyEnabled;
+
+                // Update the menu checkbox.
+                menuItem.setChecked(easyPrivacyEnabled);
+
+                // Reload the main WebView.
+                mainWebView.reload();
+                return true;
+
+            case R.id.fanboys_annoyance_list:
+                // Toggle Fanboy's Annoyance List status.
+                fanboysAnnoyanceListEnabled = !fanboysAnnoyanceListEnabled;
+
+                // Update the menu checkbox.
+                menuItem.setChecked(fanboysAnnoyanceListEnabled);
+
+                // Update the staus of Fanboy's Social Blocking List.
+                MenuItem fanboysSocialBlockingListMenuItem = mainMenu.findItem(R.id.fanboys_social_blocking_list);
+                fanboysSocialBlockingListMenuItem.setEnabled(!fanboysAnnoyanceListEnabled);
+
+                // Reload the main WebView.
+                mainWebView.reload();
+                return true;
+
+            case R.id.fanboys_social_blocking_list:
+                // Toggle Fanboy's Social Blocking List status.
+                fanboysSocialBlockingListEnabled = !fanboysSocialBlockingListEnabled;
+
+                // Update the menu checkbox.
+                menuItem.setChecked(fanboysSocialBlockingListEnabled);
+
+                // Reload the main WebView.
+                mainWebView.reload();
+                return true;
+
+            case R.id.ultraprivacy:
+                // Toggle the UltraPrivacy status.
+                ultraPrivacyEnabled = !ultraPrivacyEnabled;
+
+                // Update the menu checkbox.
+                menuItem.setChecked(ultraPrivacyEnabled);
+
+                // 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();
@@ -2215,6 +2483,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
             case R.id.back:
                 if (mainWebView.canGoBack()) {
+                    // Reset the formatted URL string so the page will load correctly if blocking of third-party requests is enabled.
+                    formattedUrlString = "";
+
                     // Set `navigatingHistory` so that the domain settings are applied when the new URL is loaded.
                     navigatingHistory = true;
 
@@ -2225,6 +2496,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
             case R.id.forward:
                 if (mainWebView.canGoForward()) {
+                    // Reset the formatted URL string so the page will load correctly if blocking of third-party requests is enabled.
+                    formattedUrlString = "";
+
                     // Set `navigatingHistory` so that the domain settings are applied when the new URL is loaded.
                     navigatingHistory = true;
 
@@ -2429,7 +2703,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     public void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
 
-        // Reload the ad for the free flavor if we are not in full screen mode.
+        // Reload the ad for the free flavor if we not in full screen mode.
         if (BuildConfig.FLAVOR.contentEquals("free") && !inFullScreenBrowsingMode) {
             // Reload the ad.  The AdView is destroyed and recreated, which changes the ID, every time it is reloaded to handle possible rotations.
             AdHelper.loadAd(findViewById(R.id.adview), getApplicationContext(), getString(R.string.ad_id));
@@ -3058,6 +3332,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     @Override
     public void onSslMismatchBack() {
         if (mainWebView.canGoBack()) {  // There is a back page in the history.
+            // Reset the formatted URL string so the page will load correctly if blocking of third-party requests is enabled.
+            formattedUrlString = "";
+
             // Set `navigatingHistory` so that the domain settings are applied when the new URL is loaded.
             navigatingHistory = true;
 
@@ -3077,6 +3354,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
     @Override
     public void onUrlHistoryEntrySelected(int moveBackOrForwardSteps) {
+        // Reset the formatted URL string so the page will load correctly if blocking of third-party requests is enabled.
+        formattedUrlString = "";
+
         // Set `navigatingHistory` so that the domain settings are applied when the new URL is loaded.
         navigatingHistory = true;
 
@@ -3109,6 +3389,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             }
 
         } else if (mainWebView.canGoBack()) {  // There is at least one item in the `WebView` history.
+            // Reset the formatted URL string so the page will load correctly if blocking of third-party requests is enabled.
+            formattedUrlString = "";
+
             // Set `navigatingHistory` so that the domain settings are applied when the new URL is loaded.
             navigatingHistory = true;
 
@@ -3183,6 +3466,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.
@@ -3224,11 +3511,11 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
 
         // Store the values from the shared preferences in variables.
-        String homepageString = sharedPreferences.getString("homepage", "https://start.duckduckgo.com");
-        String torHomepageString = sharedPreferences.getString("tor_homepage", "https://3g2upl4pq6kufc4m.onion");
-        String torSearchString = sharedPreferences.getString("tor_search", "https://3g2upl4pq6kufc4m.onion/html/?q=");
+        String homepageString = sharedPreferences.getString("homepage", "https://searx.me/");
+        String torHomepageString = sharedPreferences.getString("tor_homepage", "http://ulrn6sryqaifefld.onion/");
+        String torSearchString = sharedPreferences.getString("tor_search", "http://ulrn6sryqaifefld.onion/?q=");
         String torSearchCustomURLString = sharedPreferences.getString("tor_search_custom_url", "");
-        String searchString = sharedPreferences.getString("search", "https://duckduckgo.com/html/?q=");
+        String searchString = sharedPreferences.getString("search", "https://searx.me/?q=");
         String searchCustomURLString = sharedPreferences.getString("search_custom_url", "");
         incognitoModeEnabled = sharedPreferences.getBoolean("incognito_mode", false);
         boolean doNotTrackEnabled = sharedPreferences.getBoolean("do_not_track", false);
@@ -3265,7 +3552,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 appBar.setBackgroundDrawable(ContextCompat.getDrawable(this, R.color.blue_50));
             }
 
-            // Display a message to the user if we are waiting on Orbot.
+            // Display a message to the user if waiting for Orbot.
             if (!orbotStatus.equals("ON")) {
                 // Set `waitingForOrbot`.
                 waitingForOrbot = true;
@@ -3311,7 +3598,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         }
 
         // Apply the appropriate full screen mode the `SYSTEM_UI` flags.
-        if (fullScreenBrowsingModeEnabled && inFullScreenBrowsingMode) {
+        if (fullScreenBrowsingModeEnabled && inFullScreenBrowsingMode) {  // Privacy Browser is currently in full screen browsing mode.
             if (hideSystemBarsOnFullscreen) {  // Hide everything.
                 // Remove the translucent navigation setting if it is currently flagged.
                 getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
@@ -3328,6 +3615,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                  */
                 rootCoordinatorLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
             } else {  // Hide everything except the status and navigation bars.
+                // Remove any `SYSTEM_UI` flags from `rootCoordinatorLayout`.
+                rootCoordinatorLayout.setSystemUiVisibility(0);
+
                 // Add the translucent status flag if it is unset.
                 getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
 
@@ -3339,8 +3629,8 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                     getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
                 }
             }
-        } else {  // Switch to normal viewing mode.
-            // Reset `inFullScreenBrowsingMode` to `false`.
+        } else {  // Privacy Browser is not in full screen browsing mode.
+            // Reset the full screen tracker, which could be true if Privacy Browser was in full screen mode before entering settings and full screen browsing was disabled.
             inFullScreenBrowsingMode = false;
 
             // Show the `appBar` if `findOnPageLinearLayout` is not visible.
@@ -3354,15 +3644,15 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 AdHelper.initializeAds(findViewById(R.id.adview), getApplicationContext(), getFragmentManager(), getString(R.string.ad_id));
             }
 
+            // Remove any `SYSTEM_UI` flags from `rootCoordinatorLayout`.
+            rootCoordinatorLayout.setSystemUiVisibility(0);
+
             // Remove the translucent navigation bar flag if it is set.
             getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
 
             // Add the translucent status flag if it is unset.  This also resets `drawerLayout's` `View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN`.
             getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
 
-            // Remove any `SYSTEM_UI` flags from `rootCoordinatorLayout`.
-            rootCoordinatorLayout.setSystemUiVisibility(0);
-
             // Constrain `rootCoordinatorLayout` inside the status and navigation bars.
             rootCoordinatorLayout.setFitsSystemWindows(true);
         }
@@ -3372,9 +3662,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     // The deprecated `.getDrawable()` must be used until the minimum API >= 21.
     @SuppressWarnings("deprecation")
     private void applyDomainSettings(String url, boolean resetFavoriteIcon, boolean reloadWebsite) {
-        // Reset `navigatingHistory`.
-        navigatingHistory = false;
-
         // Parse the URL into a URI.
         Uri uri = Uri.parse(url);
 
@@ -3489,6 +3776,8 @@ 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);
+                ultraPrivacyEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY)) == 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));
@@ -3644,6 +3933,8 @@ 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);
+                ultraPrivacyEnabled = sharedPreferences.getBoolean("ultraprivacy", true);
+                blockAllThirdPartyRequests = sharedPreferences.getBoolean("block_all_third_party_requests", false);
 
                 // Set `javaScriptEnabled` to be `true` if `night_mode` is `true`.
                 if (nightMode) {