]> gitweb.stoutner.com Git - PrivacyBrowserAndroid.git/blobdiff - app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java
Make the favorite icon tab aware.
[PrivacyBrowserAndroid.git] / app / src / main / java / com / stoutner / privacybrowser / activities / MainWebViewActivity.java
index e0a310c8f63dd734eb228e095d949be66a1b03e3..c0f2b824ffd31f99de096b907f9cc3ea75941e12 100644 (file)
@@ -168,14 +168,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     // `allowScreenshots` is public static so it can be accessed from everywhere.  It is also used in `onCreate()`.
     public static boolean allowScreenshots;
 
-    // `favoriteIconBitmap` is public static so it can be accessed from `BookmarksActivity`, `BookmarksDatabaseViewActivity`, `CreateBookmarkFolderDialog`,
-    // `EditBookmarkDialog`, `EditBookmarkFolderDialog`, `EditBookmarkDatabaseViewDialog`, and `ViewSslCertificateDialog`.  It is also used in `onCreate()`, `onCreateBookmark()`, `onCreateBookmarkFolder()`,
-    // `onCreateHomeScreenShortcut()`, `onSaveEditBookmark()`, `onSaveEditBookmarkFolder()`, and `applyDomainSettings()`.
-    public static Bitmap favoriteIconBitmap;
-
-    // `favoriteIconDefaultBitmap` public static so it can be accessed from `PinnedMismatchDialog`.  It is also used in `onCreate()` and `applyDomainSettings`.
-    public static Bitmap favoriteIconDefaultBitmap;
-
     // TODO Remove.
     // `formattedUrlString` is public static so it can be accessed from `AddDomainDialog`, `BookmarksActivity`, `DomainSettingsFragment`, and `PinnedMismatchDialog`.
     // It is also used in `onCreate()`, `onOptionsItemSelected()`, `onNavigationItemSelected()`, `onCreateHomeScreenShortcutCreate()`, `loadUrlFromTextBox()`, and `applyProxyThroughOrbot()`.
@@ -203,10 +195,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     public static String fanboysSocialVersion;
     public static String ultraPrivacyVersion;
 
-    // `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;
@@ -222,30 +210,18 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
 
     // `navigatingHistory` is used in `onCreate()`, `onNavigationItemSelected()`, `onSslMismatchBack()`, and `applyDomainSettings()`.
-    private boolean navigatingHistory;
+    private boolean navigatingHistory;  // TODO.
 
     // The current WebView is used in `onCreate()`, `onPrepareOptionsMenu()`, `onOptionsItemSelected()`, `onNavigationItemSelected()`, `onRestart()`, `onCreateContextMenu()`, `findPreviousOnPage()`,
     // `findNextOnPage()`, `closeFindOnPage()`, `loadUrlFromTextBox()`, `onSslMismatchBack()`, `applyProxyThroughOrbot()`, and `applyDomainSettings()`.
     private NestedScrollWebView currentWebView;
 
-    // `fullScreenVideoFrameLayout` is used in `onCreate()` and `onConfigurationChanged()`.
-    private FrameLayout fullScreenVideoFrameLayout;
-
-    // `cookieManager` is used in `onCreate()`, `onOptionsItemSelected()`, and `onNavigationItemSelected()`, `loadUrlFromTextBox()`, `onDownloadImage()`, `onDownloadFile()`, and `onRestart()`.
-    private CookieManager cookieManager;
-
     // `customHeader` is used in `onCreate()`, `onOptionsItemSelected()`, `onCreateContextMenu()`, and `loadUrl()`.
     private final Map<String, String> customHeaders = new HashMap<>();
 
     // `firstPartyCookiesEnabled` is used in `onCreate()`, `onPrepareOptionsMenu()`, `onOptionsItemSelected()`, `onDownloadImage()`, `onDownloadFile()`, and `applyDomainSettings()`.
     private boolean firstPartyCookiesEnabled;
 
-    // `thirdPartyCookiesEnabled` used in `onCreate()`, `onPrepareOptionsMenu()`, `onPrepareOptionsMenu()`, `onOptionsItemSelected()`, and `applyDomainSettings()`.
-    private boolean thirdPartyCookiesEnabled;
-
-    // `domStorageEnabled` is used in `onCreate()`, `onPrepareOptionsMenu()`, `onOptionsItemSelected()`, and `applyDomainSettings()`.
-    private boolean domStorageEnabled;
-
     // `saveFormDataEnabled` is used in `onCreate()`, `onPrepareOptionsMenu()`, `onOptionsItemSelected()`, and `applyDomainSettings()`.  It can be removed once the minimum API >= 26.
     private boolean saveFormDataEnabled;
 
@@ -254,20 +230,17 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     private boolean nightMode;
 
     // 'homepage' is used in `onCreate()`, `onNavigationItemSelected()`, and `applyProxyThroughOrbot()`.
-    private String homepage;
+    private String homepage;  // TODO ?
 
     // `searchURL` is used in `loadURLFromTextBox()` and `applyProxyThroughOrbot()`.
-    private String searchURL;
+    private String searchURL;  // TODO ?
 
     // The options menu is set in `onCreateOptionsMenu()` and used in `onOptionsItemSelected()` and `updatePrivacyIcons()`.
     private Menu optionsMenu;
 
     // The refresh menu item is set in `onCreateOptionsMenu()` and accessed from `initializeWebView()`.
     // It must be this way because `initializeWebView()` runs before the menu is created but doesn't actually modify the menu until later.
-    private MenuItem refreshMenuItem;
-
-    // The navigation requests menu item is used in `onCreate()` and accessed from `WebViewPagerAdapter`.
-    private MenuItem navigationRequestsMenuItem;  // TODO.
+    private MenuItem refreshMenuItem;  // TODO.  Create it from `optionsMenu`.
 
     // TODO.  This could probably be removed.
     // The blocklist helper is used in `onCreate()` and `WebViewPagerAdapter`.
@@ -280,7 +253,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     private ArrayList<List<String[]>> fanboysSocialList;
     private ArrayList<List<String[]>> ultraPrivacy;
 
-    // The blocklist menu items are used in `onCreate()`, `onCreateOptionsMenu()`, and `onPrepareOptionsMenu()`.
+    // The blocklist menu items are used in `onCreateOptionsMenu()`, `onPrepareOptionsMenu()`, and `initializeWebView()`.  // TODO.
     private MenuItem blocklistsMenuItem;
     private MenuItem easyListMenuItem;
     private MenuItem easyPrivacyMenuItem;
@@ -289,33 +262,23 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     private MenuItem ultraPrivacyMenuItem;
     private MenuItem blockAllThirdPartyRequestsMenuItem;
 
-    // The blocklist variables are used in `onCreate()`, `onPrepareOptionsMenu()`, `onOptionsItemSelected()`, and `applyAppSettings()`.
-    private boolean easyListEnabled;
-    private boolean easyPrivacyEnabled;
-    private boolean fanboysAnnoyanceListEnabled;
-    private boolean fanboysSocialBlockingListEnabled;
-    private boolean ultraPrivacyEnabled;
-
     // `webViewDefaultUserAgent` is used in `onCreate()` and `onPrepareOptionsMenu()`.
     private String webViewDefaultUserAgent;
 
-    // `privacyBrowserRuntime` is used in `onCreate()`, `onOptionsItemSelected()`, and `applyAppSettings()`.
-    private Runtime privacyBrowserRuntime;
-
     // `proxyThroughOrbot` is used in `onRestart()`, `onOptionsItemSelected()`, `applyAppSettings()`, and `applyProxyThroughOrbot()`.
     private boolean proxyThroughOrbot;
 
     // `incognitoModeEnabled` is used in `onCreate()` and `applyAppSettings()`.
-    private boolean incognitoModeEnabled;
+    private boolean incognitoModeEnabled;  // TODO.
 
     // `fullScreenBrowsingModeEnabled` is used in `onCreate()` and `applyAppSettings()`.
-    private boolean fullScreenBrowsingModeEnabled;
+    private boolean fullScreenBrowsingModeEnabled;  // TODO.
 
     // `inFullScreenBrowsingMode` is used in `onCreate()`, `onConfigurationChanged()`, and `applyAppSettings()`.
     private boolean inFullScreenBrowsingMode;
 
     // Hide app bar is used in `onCreate()` and `applyAppSettings()`.
-    private boolean hideAppBar;
+    private boolean hideAppBar;  // TODO.
 
     // `reapplyDomainSettingsOnRestart` is used in `onCreate()`, `onOptionsItemSelected()`, `onNavigationItemSelected()`, `onRestart()`, and `onAddDomain()`, .
     private boolean reapplyDomainSettingsOnRestart;
@@ -327,7 +290,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     private boolean displayingFullScreenVideo;
 
     // `downloadWithExternalApp` is used in `onCreate()`, `onCreateContextMenu()`, and `applyDomainSettings()`.
-    private boolean downloadWithExternalApp;
+    private boolean downloadWithExternalApp;  // TODO.
 
     // `orbotStatusBroadcastReceiver` is used in `onCreate()` and `onDestroy()`.
     private BroadcastReceiver orbotStatusBroadcastReceiver;
@@ -336,22 +299,22 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     private boolean waitingForOrbot;
 
     // `domainSettingsJavaScriptEnabled` is used in `onOptionsItemSelected()` and `applyDomainSettings()`.
-    private Boolean domainSettingsJavaScriptEnabled;
+    private Boolean domainSettingsJavaScriptEnabled;  // TODO.
 
     // `waitingForOrbotHtmlString` is used in `onCreate()` and `applyProxyThroughOrbot()`.
-    private String waitingForOrbotHtmlString;
+    private String waitingForOrbotHtmlString;  // TODO.
 
     // `privateDataDirectoryString` is used in `onCreate()`, `onOptionsItemSelected()`, and `onNavigationItemSelected()`.
-    private String privateDataDirectoryString;
+    private String privateDataDirectoryString;  // TODO.
 
     // `findOnPageEditText` is used in `onCreate()`, `onOptionsItemSelected()`, and `closeFindOnPage()`.
-    private EditText findOnPageEditText;
+    private EditText findOnPageEditText;  // TODO.
 
     // `displayAdditionalAppBarIcons` is used in `onCreate()` and `onCreateOptionsMenu()`.
-    private boolean displayAdditionalAppBarIcons;
+    private boolean displayAdditionalAppBarIcons;  // TODO.
 
     // The action bar drawer toggle is initialized in `onCreate()` and used in `onResume()`.
-    private ActionBarDrawerToggle actionBarDrawerToggle;
+    private ActionBarDrawerToggle actionBarDrawerToggle;  // TODO.
 
     // The color spans are used in `onCreate()` and `highlightUrlText()`.
     private ForegroundColorSpan redColorSpan;
@@ -364,23 +327,23 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     private int drawerHeaderPaddingBottom;
 
     // `sslErrorHandler` is used in `onCreate()`, `onSslErrorCancel()`, and `onSslErrorProceed`.
-    private SslErrorHandler sslErrorHandler;
+    private SslErrorHandler sslErrorHandler;  // TODO.
 
     // `httpAuthHandler` is used in `onCreate()`, `onHttpAuthenticationCancel()`, and `onHttpAuthenticationProceed()`.
-    private static HttpAuthHandler httpAuthHandler;
+    private static HttpAuthHandler httpAuthHandler;  // TODO.
 
     // `inputMethodManager` is used in `onOptionsItemSelected()`, `loadUrlFromTextBox()`, and `closeFindOnPage()`.
-    private InputMethodManager inputMethodManager;
+    private InputMethodManager inputMethodManager;  // TODO.
 
     // `bookmarksDatabaseHelper` is used in `onCreate()`, `onDestroy`, `onOptionsItemSelected()`, `onCreateBookmark()`, `onCreateBookmarkFolder()`, `onSaveEditBookmark()`, `onSaveEditBookmarkFolder()`,
     // and `loadBookmarksFolder()`.
-    private BookmarksDatabaseHelper bookmarksDatabaseHelper;
+    private BookmarksDatabaseHelper bookmarksDatabaseHelper;  // TODO.
 
     // `bookmarksListView` is used in `onCreate()`, `onCreateBookmark()`, `onCreateBookmarkFolder()`, and `loadBookmarksFolder()`.
-    private ListView bookmarksListView;
+    private ListView bookmarksListView;  // TODO.
 
     // `bookmarksTitleTextView` is used in `onCreate()` and `loadBookmarksFolder()`.
-    private TextView bookmarksTitleTextView;
+    private TextView bookmarksTitleTextView;  // TODO.
 
     // `bookmarksCursor` is used in `onDestroy()`, `onOptionsItemSelected()`, `onCreateBookmark()`, `onCreateBookmarkFolder()`, `onSaveEditBookmark()`, `onSaveEditBookmarkFolder()`, and `loadBookmarksFolder()`.
     private Cursor bookmarksCursor;
@@ -459,7 +422,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         initialGrayColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.gray_500));
         finalGrayColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.gray_500));
 
-        // Get a handle for `urlTextBox`.
+        // Get handles for the URL views.
         EditText urlEditText = findViewById(R.id.url_edittext);
 
         // Remove the formatting from `urlTextBar` when the user is editing the text.
@@ -540,7 +503,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
         // Get handles for views that need to be modified.
         DrawerLayout drawerLayout = findViewById(R.id.drawerlayout);
-        final NavigationView navigationView = findViewById(R.id.navigationview);
+        NavigationView navigationView = findViewById(R.id.navigationview);
         TabLayout tabLayout = findViewById(R.id.tablayout);
         SwipeRefreshLayout swipeRefreshLayout = findViewById(R.id.swiperefreshlayout);
         ViewPager webViewPager = findViewById(R.id.webviewpager);
@@ -550,18 +513,17 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         FloatingActionButton createBookmarkFolderFab = findViewById(R.id.create_bookmark_folder_fab);
         FloatingActionButton createBookmarkFab = findViewById(R.id.create_bookmark_fab);
         findOnPageEditText = findViewById(R.id.find_on_page_edittext);
-        fullScreenVideoFrameLayout = findViewById(R.id.full_screen_video_framelayout);
 
         // Listen for touches on the navigation menu.
         navigationView.setNavigationItemSelectedListener(this);
 
         // Get handles for the navigation menu and the back and forward menu items.  The menu is zero-based.
-        final Menu navigationMenu = navigationView.getMenu();
-        final MenuItem navigationCloseTabMenuItem = navigationMenu.getItem(0);
-        final MenuItem navigationBackMenuItem = navigationMenu.getItem(3);
-        final MenuItem navigationForwardMenuItem = navigationMenu.getItem(4);
-        final MenuItem navigationHistoryMenuItem = navigationMenu.getItem(5);
-        navigationRequestsMenuItem = navigationMenu.getItem(6);
+        Menu navigationMenu = navigationView.getMenu();
+        MenuItem navigationCloseTabMenuItem = navigationMenu.getItem(0);
+        MenuItem navigationBackMenuItem = navigationMenu.getItem(3);
+        MenuItem navigationForwardMenuItem = navigationMenu.getItem(4);
+        MenuItem navigationHistoryMenuItem = navigationMenu.getItem(5);
+        MenuItem navigationRequestsMenuItem = navigationMenu.getItem(6);
 
         // Initialize the web view pager adapter.
         webViewPagerAdapter = new WebViewPagerAdapter(getSupportFragmentManager());
@@ -581,47 +543,8 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
             @Override
             public void onPageSelected(int position) {
-                // Get the WebView tab fragment.
-                WebViewTabFragment webViewTabFragment = webViewPagerAdapter.getPageFragment(position);
-
-                // Get the fragment view.
-                View fragmentView = webViewTabFragment.getView();
-
-                // Remove the incorrect lint warning below that the fragment view might be null.
-                assert fragmentView != null;
-
-                // Store the current WebView.
-                currentWebView = fragmentView.findViewById(R.id.nestedscroll_webview);
-
-                // Update the privacy icons.  `true` redraws the icons in the app bar.
-                updatePrivacyIcons(true);
-
-                // Store the current formatted URL string.
-                formattedUrlString = currentWebView.getUrl();
-
-                // Clear the focus from the URL text box.
-                urlEditText.clearFocus();
-
-                // Hide the soft keyboard.
-                inputMethodManager.hideSoftInputFromWindow(currentWebView.getWindowToken(), 0);
-
-                // Display the current URL in the URL text box.
-                urlEditText.setText(formattedUrlString);
-
-                // Highlight the URL text.
-                highlightUrlText();
-
-                // Set the background to indicate the domain settings status.
-                if (currentWebView.getDomainSettingsApplied()) {
-                    // Set a green background on `urlTextBox` to indicate that custom domain settings are being used. The deprecated `.getDrawable()` must be used until the minimum API >= 21.
-                    if (darkTheme) {
-                        urlEditText.setBackground(getResources().getDrawable(R.drawable.url_bar_background_dark_blue));
-                    } else {
-                        urlEditText.setBackground(getResources().getDrawable(R.drawable.url_bar_background_light_green));
-                    }
-                } else {
-                    urlEditText.setBackground(getResources().getDrawable(R.color.transparent));
-                }
+                // Set the current WebView.
+                setCurrentWebView(position);
 
                 // Select the corresponding tab if it does not match the currently selected page.  This will happen if the page was scrolled via swiping in the view pager.
                 if (tabLayout.getSelectedTabPosition() != position) {
@@ -658,15 +581,15 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             @Override
             public void onTabReselected(TabLayout.Tab tab) {
                 // Instantiate the View SSL Certificate dialog.
-                DialogFragment viewSslCertificateDialogFragment = ViewSslCertificateDialog.displayDialog(currentWebView.getWebViewFragmentId());
+                DialogFragment viewSslCertificateDialogFragment = ViewSslCertificateDialog.displayDialog(currentWebView.getWebViewFragmentId(), currentWebView.getFavoriteOrDefaultIcon());
 
                 // Display the View SSL Certificate dialog.
                 viewSslCertificateDialogFragment.show(getSupportFragmentManager(), getString(R.string.view_ssl_certificate));
             }
         });
 
-        // Add the first tab.  (It doesn't matter what view is passed.  That is just required as part of the ImageView `onClick()` syntax).
-        addTab(webViewPager);
+        // Add the first tab.
+        addTab(null);
 
         // Set the bookmarks drawer resources according to the theme.  This can't be done in the layout due to compatibility issues with the `DrawerLayout` support widget.
         // The deprecated `getResources().getDrawable()` must be used until the minimum API >= 21 and and `getResources().getColor()` must be used until the minimum API >= 23.
@@ -684,15 +607,28 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
         // Set the launch bookmarks activity FAB to launch the bookmarks activity.
         launchBookmarksActivityFab.setOnClickListener(v -> {
-            // Store the current WebView url and title in the bookmarks activity.
+            // Store the current WebView url and title in the bookmarks activity.  // TODO.
             BookmarksActivity.currentWebViewUrl = currentWebView.getUrl();
             BookmarksActivity.currentWebViewTitle = currentWebView.getTitle();
 
+            // Get a copy of the favorite icon bitmap.
+            Bitmap favoriteIconBitmap = currentWebView.getFavoriteOrDefaultIcon();
+
+            // Create a favorite icon byte array output stream.
+            ByteArrayOutputStream favoriteIconByteArrayOutputStream = new ByteArrayOutputStream();
+
+            // Convert the favorite icon bitmap to a byte array.  `0` is for lossless compression (the only option for a PNG).
+            favoriteIconBitmap.compress(Bitmap.CompressFormat.PNG, 0, favoriteIconByteArrayOutputStream);
+
+            // Convert the favorite icon byte array stream to a byte array.
+            byte[] favoriteIconByteArray = favoriteIconByteArrayOutputStream.toByteArray();
+
             // Create an intent to launch the bookmarks activity.
             Intent bookmarksIntent = new Intent(getApplicationContext(), BookmarksActivity.class);
 
-            // Include the current folder with the `Intent`.
-            bookmarksIntent.putExtra("Current Folder", currentBookmarksFolder);
+            // Add the extra information to the intent.
+            bookmarksIntent.putExtra("current_folder", currentBookmarksFolder);
+            bookmarksIntent.putExtra("favorite_icon_byte_array", favoriteIconByteArray);
 
             // Make it so.
             startActivity(bookmarksIntent);
@@ -700,15 +636,17 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
         // Set the create new bookmark folder FAB to display an alert dialog.
         createBookmarkFolderFab.setOnClickListener(v -> {
-            // Show the create bookmark folder dialog and name the instance `@string/create_folder`.
-            DialogFragment createBookmarkFolderDialog = new CreateBookmarkFolderDialog();
+            // Create a create bookmark folder dialog.
+            DialogFragment createBookmarkFolderDialog = CreateBookmarkFolderDialog.createBookmarkFolder(currentWebView.getFavoriteOrDefaultIcon());
+
+            // Show the create bookmark folder dialog.
             createBookmarkFolderDialog.show(getSupportFragmentManager(), getString(R.string.create_folder));
         });
 
         // Set the create new bookmark FAB to display an alert dialog.
         createBookmarkFab.setOnClickListener(view -> {
             // Instantiate the create bookmark dialog.
-            DialogFragment createBookmarkDialog = CreateBookmarkDialog.createBookmark(currentWebView.getUrl(), currentWebView.getTitle(), favoriteIconBitmap);
+            DialogFragment createBookmarkDialog = CreateBookmarkDialog.createBookmark(currentWebView.getUrl(), currentWebView.getTitle(), currentWebView.getFavoriteOrDefaultIcon());
 
             // Display the create bookmark dialog.
             createBookmarkDialog.show(getSupportFragmentManager(), getString(R.string.create_bookmark));
@@ -813,11 +751,11 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 oldFolderNameString = bookmarksCursor.getString(bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME));
 
                 // Show the edit bookmark folder `AlertDialog` and name the instance `@string/edit_folder`.
-                DialogFragment editBookmarkFolderDialog = EditBookmarkFolderDialog.folderDatabaseId(databaseId);
+                DialogFragment editBookmarkFolderDialog = EditBookmarkFolderDialog.folderDatabaseId(databaseId, currentWebView.getFavoriteOrDefaultIcon());
                 editBookmarkFolderDialog.show(getSupportFragmentManager(), getString(R.string.edit_folder));
             } else {
                 // Show the edit bookmark `AlertDialog` and name the instance `@string/edit_bookmark`.
-                DialogFragment editBookmarkDialog = EditBookmarkDialog.bookmarkDatabaseId(databaseId);
+                DialogFragment editBookmarkDialog = EditBookmarkDialog.bookmarkDatabaseId(databaseId, currentWebView.getFavoriteOrDefaultIcon());
                 editBookmarkDialog.show(getSupportFragmentManager(), getString(R.string.edit_bookmark));
             }
 
@@ -888,18 +826,12 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         // Create the hamburger icon at the start of the AppBar.
         actionBarDrawerToggle = new ActionBarDrawerToggle(this, drawerLayout, toolbar, R.string.open_navigation_drawer, R.string.close_navigation_drawer);
 
-        // Initialize cookieManager.
-        cookieManager = CookieManager.getInstance();
-
         // Replace the header that `WebView` creates for `X-Requested-With` with a null value.  The default value is the application ID (com.stoutner.privacybrowser.standard).
         customHeaders.put("X-Requested-With", "");
 
         // Initialize the default preference values the first time the program is run.  `false` keeps this command from resetting any current preferences back to default.
         PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
 
-        // Get a handle for the `Runtime`.
-        privacyBrowserRuntime = Runtime.getRuntime();
-
         // Store the application's private data directory.
         privateDataDirectoryString = getApplicationInfo().dataDir;
         // `dataDir` will vary, but will be something like `/data/user/0/com.stoutner.privacybrowser.standard`, which links to `/data/data/com.stoutner.privacybrowser.standard`.
@@ -909,8 +841,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
         // Initialize the privacy settings variables.
         firstPartyCookiesEnabled = false;
-        thirdPartyCookiesEnabled = false;
-        domStorageEnabled = false;
         saveFormDataEnabled = false;  // Form data can be removed once the minimum API >= 26.
         nightMode = false;
 
@@ -926,17 +856,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         // Destroy the bare WebView.
         bareWebView.destroy();
 
-        // Initialize the favorite icon bitmap.  `ContextCompat` must be used until API >= 21.
-        Drawable favoriteIconDrawable = ContextCompat.getDrawable(getApplicationContext(), R.drawable.world);
-        BitmapDrawable favoriteIconBitmapDrawable = (BitmapDrawable) favoriteIconDrawable;
-        assert favoriteIconBitmapDrawable != null;
-        favoriteIconDefaultBitmap = favoriteIconBitmapDrawable.getBitmap();
-
-        // If the favorite icon is null, load the default.
-        if (favoriteIconBitmap == null) {
-            favoriteIconBitmap = favoriteIconDefaultBitmap;
-        }
-
         // Initialize the user agent array adapter and string array.
         userAgentNamesArray = ArrayAdapter.createFromResource(this, R.array.user_agent_names, R.layout.spinner_item);
         userAgentDataArray = getResources().getStringArray(R.array.user_agent_data);
@@ -970,50 +889,56 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
     @Override
     protected void onNewIntent(Intent intent) {
-        // Sets the new intent as the activity intent, so that any future `getIntent()`s pick up this one instead of creating a new activity.
-        setIntent(intent);
-
         // Get the information from the intent.
         String intentAction = intent.getAction();
         Uri intentUriData = intent.getData();
 
-        // If the intent action is a web search, perform the search.
-        if ((intentAction != null) && intentAction.equals(Intent.ACTION_WEB_SEARCH)) {
-            // Create an encoded URL string.
-            String encodedUrlString;
+        // Only process the URI if it contains data.  If the user pressed the desktop icon after the app was already running the URI will be null.
+        if (intentUriData != null) {
+            // Sets the new intent as the activity intent, which replaces the one that originally started the app.
+            setIntent(intent);
 
-            // Sanitize the search input and convert it to a search.
-            try {
-                encodedUrlString = URLEncoder.encode(intent.getStringExtra(SearchManager.QUERY), "UTF-8");
-            } catch (UnsupportedEncodingException exception) {
-                encodedUrlString = "";
+            // Add a new tab.
+            addTab(null);
+
+            // If the intent action is a web search, perform the search.
+            if ((intentAction != null) && intentAction.equals(Intent.ACTION_WEB_SEARCH)) {
+                // Create an encoded URL string.
+                String encodedUrlString;
+
+                // Sanitize the search input and convert it to a search.
+                try {
+                    encodedUrlString = URLEncoder.encode(intent.getStringExtra(SearchManager.QUERY), "UTF-8");
+                } catch (UnsupportedEncodingException exception) {
+                    encodedUrlString = "";
+                }
+
+                // Add the base search URL.
+                formattedUrlString = searchURL + encodedUrlString;
+            } else {  // The intent should contain a URL.
+                // Set the formatted URL string.
+                formattedUrlString = intentUriData.toString();
             }
 
-            // Add the base search URL.
-            formattedUrlString = searchURL + encodedUrlString;
-        } else if (intentUriData != null){  // Check to see if the intent contains a new URL.
-            // Set the formatted URL string.
-            formattedUrlString = intentUriData.toString();
-        }
+            // Load the URL.
+            loadUrl(formattedUrlString);
 
-        // Load the URL.
-        loadUrl(formattedUrlString);
+            // Get a handle for the drawer layout.
+            DrawerLayout drawerLayout = findViewById(R.id.drawerlayout);
 
-        // Get a handle for the drawer layout.
-        DrawerLayout drawerLayout = findViewById(R.id.drawerlayout);
+            // Close the navigation drawer if it is open.
+            if (drawerLayout.isDrawerVisible(GravityCompat.START)) {
+                drawerLayout.closeDrawer(GravityCompat.START);
+            }
 
-        // Close the navigation drawer if it is open.
-        if (drawerLayout.isDrawerVisible(GravityCompat.START)) {
-            drawerLayout.closeDrawer(GravityCompat.START);
-        }
+            // Close the bookmarks drawer if it is open.
+            if (drawerLayout.isDrawerVisible(GravityCompat.END)) {
+                drawerLayout.closeDrawer(GravityCompat.END);
+            }
 
-        // Close the bookmarks drawer if it is open.
-        if (drawerLayout.isDrawerVisible(GravityCompat.END)) {
-            drawerLayout.closeDrawer(GravityCompat.END);
+            // Clear the keyboard if displayed and remove the focus on the urlTextBar if it has it.
+            currentWebView.requestFocus();
         }
-
-        // Clear the keyboard if displayed and remove the focus on the urlTextBar if it has it.
-        currentWebView.requestFocus();
     }
 
     @Override
@@ -1298,6 +1223,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         MenuItem nightModeMenuItem = menu.findItem(R.id.night_mode);
         MenuItem proxyThroughOrbotMenuItem = menu.findItem(R.id.proxy_through_orbot);
 
+        // Get a handle for the cookie manager.
+        CookieManager cookieManager = CookieManager.getInstance();
+
         // Initialize the current user agent string and the font size.
         String currentUserAgent = getString(R.string.user_agent_privacy_browser);
         int fontSize = 100;
@@ -1317,37 +1245,41 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             // Get the current font size from the
             fontSize = currentWebView.getSettings().getTextZoom();
 
-            // Set the status of the display images menu item.
+            // Set the status of the menu item checkboxes.
+            toggleDomStorageMenuItem.setChecked(currentWebView.getSettings().getDomStorageEnabled());
+            easyListMenuItem.setChecked(currentWebView.isBlocklistEnabled(NestedScrollWebView.EASY_LIST));
+            easyPrivacyMenuItem.setChecked(currentWebView.isBlocklistEnabled(NestedScrollWebView.EASY_PRIVACY));
+            fanboysAnnoyanceListMenuItem.setChecked(currentWebView.isBlocklistEnabled(NestedScrollWebView.FANBOYS_ANNOYANCE_LIST));
+            fanboysSocialBlockingListMenuItem.setChecked(currentWebView.isBlocklistEnabled(NestedScrollWebView.FANBOYS_SOCIAL_BLOCKING_LIST));
+            ultraPrivacyMenuItem.setChecked(currentWebView.isBlocklistEnabled(NestedScrollWebView.ULTRA_PRIVACY));
+            blockAllThirdPartyRequestsMenuItem.setChecked(currentWebView.isBlocklistEnabled(NestedScrollWebView.THIRD_PARTY_REQUESTS));
             displayImagesMenuItem.setChecked(currentWebView.getSettings().getLoadsImagesAutomatically());
 
             // Initialize the display names for the blocklists with the number of blocked requests.
             blocklistsMenuItem.setTitle(getString(R.string.blocklists) + " - " + currentWebView.getRequestsCount(NestedScrollWebView.BLOCKED_REQUESTS));
-            easyListMenuItem.setTitle(currentWebView.getRequestsCount(NestedScrollWebView.EASY_LIST_BLOCKED_REQUESTS) + " - " + getString(R.string.easylist));
-            easyPrivacyMenuItem.setTitle(currentWebView.getRequestsCount(NestedScrollWebView.EASY_PRIVACY_BLOCKED_REQUESTS) + " - " + getString(R.string.easyprivacy));
-            fanboysAnnoyanceListMenuItem.setTitle(currentWebView.getRequestsCount(NestedScrollWebView.FANBOYS_ANNOYANCE_LIST_BLOCKED_REQUESTS) + " - " + getString(R.string.fanboys_annoyance_list));
-            fanboysSocialBlockingListMenuItem.setTitle(currentWebView.getRequestsCount(NestedScrollWebView.FANBOYS_SOCIAL_BLOCKING_LIST_BLOCKED_REQUESTS) + " - " +
-                    getString(R.string.fanboys_social_blocking_list));
-            ultraPrivacyMenuItem.setTitle(currentWebView.getRequestsCount(NestedScrollWebView.ULTRA_PRIVACY_BLOCKED_REQUESTS) + " - " + getString(R.string.ultraprivacy));
-            blockAllThirdPartyRequestsMenuItem.setTitle(currentWebView.getRequestsCount(NestedScrollWebView.THIRD_PARTY_BLOCKED_REQUESTS) + " - " + getString(R.string.block_all_third_party_requests));
+            easyListMenuItem.setTitle(currentWebView.getRequestsCount(NestedScrollWebView.EASY_LIST) + " - " + getString(R.string.easylist));
+            easyPrivacyMenuItem.setTitle(currentWebView.getRequestsCount(NestedScrollWebView.EASY_PRIVACY) + " - " + getString(R.string.easyprivacy));
+            fanboysAnnoyanceListMenuItem.setTitle(currentWebView.getRequestsCount(NestedScrollWebView.FANBOYS_ANNOYANCE_LIST) + " - " + getString(R.string.fanboys_annoyance_list));
+            fanboysSocialBlockingListMenuItem.setTitle(currentWebView.getRequestsCount(NestedScrollWebView.FANBOYS_SOCIAL_BLOCKING_LIST) + " - " + getString(R.string.fanboys_social_blocking_list));
+            ultraPrivacyMenuItem.setTitle(currentWebView.getRequestsCount(NestedScrollWebView.ULTRA_PRIVACY) + " - " + getString(R.string.ultraprivacy));
+            blockAllThirdPartyRequestsMenuItem.setTitle(currentWebView.getRequestsCount(NestedScrollWebView.THIRD_PARTY_REQUESTS) + " - " + getString(R.string.block_all_third_party_requests));
         }
 
         // Set the status of the menu item checkboxes.
         toggleFirstPartyCookiesMenuItem.setChecked(firstPartyCookiesEnabled);
-        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);
-        blockAllThirdPartyRequestsMenuItem.setChecked(blockAllThirdPartyRequests);
         swipeToRefreshMenuItem.setChecked(swipeRefreshLayout.isEnabled());
         nightModeMenuItem.setChecked(nightMode);
         proxyThroughOrbotMenuItem.setChecked(proxyThroughOrbot);
 
-        // Enable third-party cookies if first-party cookies are enabled.
-        toggleThirdPartyCookiesMenuItem.setEnabled(firstPartyCookiesEnabled);
+        // Only modify third-party cookies if the API >= 21.
+        if (Build.VERSION.SDK_INT >= 21) {
+            // Set the status of the third-party cookies checkbox.
+            toggleThirdPartyCookiesMenuItem.setChecked(cookieManager.acceptThirdPartyCookies(currentWebView));
+
+            // Enable third-party cookies if first-party cookies are enabled.
+            toggleThirdPartyCookiesMenuItem.setEnabled(firstPartyCookiesEnabled);
+        }
 
         // Enable DOM Storage if JavaScript is enabled.
         toggleDomStorageMenuItem.setEnabled(currentWebView.getSettings().getJavaScriptEnabled());
@@ -1384,8 +1316,8 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         // 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);
+        // Disable Fanboy's Social Blocking List menu item if Fanboy's Annoyance List is checked.
+        fanboysSocialBlockingListMenuItem.setEnabled(!fanboysAnnoyanceListMenuItem.isChecked());
 
         // Select the current user agent menu item.  A switch statement cannot be used because the user agents are not compile time constants.
         if (currentUserAgent.equals(getResources().getStringArray(R.array.user_agent_data)[0])) {  // Privacy Browser.
@@ -1508,6 +1440,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         // Get a handle for the shared preferences.
         SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
 
+        // Get a handle for the cookie manager.
+        CookieManager cookieManager = CookieManager.getInstance();
+
         // Run the commands that correlate to the selected menu item.
         switch (menuItemId) {
             case R.id.toggle_javascript:
@@ -1611,16 +1546,13 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             case R.id.toggle_third_party_cookies:
                 if (Build.VERSION.SDK_INT >= 21) {
                     // Switch the status of thirdPartyCookiesEnabled.
-                    thirdPartyCookiesEnabled = !thirdPartyCookiesEnabled;
+                    cookieManager.setAcceptThirdPartyCookies(currentWebView, !cookieManager.acceptThirdPartyCookies(currentWebView));
 
                     // Update the menu checkbox.
-                    menuItem.setChecked(thirdPartyCookiesEnabled);
-
-                    // Apply the new cookie status.
-                    cookieManager.setAcceptThirdPartyCookies(currentWebView, thirdPartyCookiesEnabled);
+                    menuItem.setChecked(cookieManager.acceptThirdPartyCookies(currentWebView));
 
-                    // Display a `Snackbar`.
-                    if (thirdPartyCookiesEnabled) {
+                    // Display a snackbar.
+                    if (cookieManager.acceptThirdPartyCookies(currentWebView)) {
                         Snackbar.make(findViewById(R.id.webviewpager), R.string.third_party_cookies_enabled, Snackbar.LENGTH_SHORT).show();
                     } else {
                         Snackbar.make(findViewById(R.id.webviewpager), R.string.third_party_cookies_disabled, Snackbar.LENGTH_SHORT).show();
@@ -1632,20 +1564,17 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 return true;
 
             case R.id.toggle_dom_storage:
-                // Switch the status of domStorageEnabled.
-                domStorageEnabled = !domStorageEnabled;
+                // Toggle the status of domStorageEnabled.
+                currentWebView.getSettings().setDomStorageEnabled(!currentWebView.getSettings().getDomStorageEnabled());
 
                 // Update the menu checkbox.
-                menuItem.setChecked(domStorageEnabled);
+                menuItem.setChecked(currentWebView.getSettings().getDomStorageEnabled());
 
-                // Apply the new DOM Storage status.
-                currentWebView.getSettings().setDomStorageEnabled(domStorageEnabled);
-
-                // Update the privacy icon.  `true` runs `invalidateOptionsMenu` as the last step.
+                // Update the privacy icon.  `true` refreshes the app bar icons.
                 updatePrivacyIcons(true);
 
-                // Display a `Snackbar`.
-                if (domStorageEnabled) {
+                // Display a snackbar.
+                if (currentWebView.getSettings().getDomStorageEnabled()) {
                     Snackbar.make(findViewById(R.id.webviewpager), R.string.dom_storage_enabled, Snackbar.LENGTH_SHORT).show();
                 } else {
                     Snackbar.make(findViewById(R.id.webviewpager), R.string.dom_storage_disabled, Snackbar.LENGTH_SHORT).show();
@@ -1736,14 +1665,17 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                                         // Setup a runnable to manually delete the DOM storage files and directories.
                                         Runnable deleteDomStorageRunnable = () -> {
                                             try {
+                                                // Get a handle for the runtime.
+                                                Runtime runtime = Runtime.getRuntime();
+
                                                 // A string array must be used because the directory contains a space and `Runtime.exec` will otherwise not escape the string correctly.
-                                                Process deleteLocalStorageProcess = privacyBrowserRuntime.exec(new String[]{"rm", "-rf", privateDataDirectoryString + "/app_webview/Local Storage/"});
+                                                Process deleteLocalStorageProcess = runtime.exec(new String[]{"rm", "-rf", privateDataDirectoryString + "/app_webview/Local Storage/"});
 
                                                 // Multiple commands must be used because `Runtime.exec()` does not like `*`.
-                                                Process deleteIndexProcess = privacyBrowserRuntime.exec("rm -rf " + privateDataDirectoryString + "/app_webview/IndexedDB");
-                                                Process deleteQuotaManagerProcess = privacyBrowserRuntime.exec("rm -f " + privateDataDirectoryString + "/app_webview/QuotaManager");
-                                                Process deleteQuotaManagerJournalProcess = privacyBrowserRuntime.exec("rm -f " + privateDataDirectoryString + "/app_webview/QuotaManager-journal");
-                                                Process deleteDatabasesProcess = privacyBrowserRuntime.exec("rm -rf " + privateDataDirectoryString + "/app_webview/databases");
+                                                Process deleteIndexProcess = runtime.exec("rm -rf " + privateDataDirectoryString + "/app_webview/IndexedDB");
+                                                Process deleteQuotaManagerProcess = runtime.exec("rm -f " + privateDataDirectoryString + "/app_webview/QuotaManager");
+                                                Process deleteQuotaManagerJournalProcess = runtime.exec("rm -f " + privateDataDirectoryString + "/app_webview/QuotaManager-journal");
+                                                Process deleteDatabasesProcess = runtime.exec("rm -rf " + privateDataDirectoryString + "/app_webview/databases");
 
                                                 // Wait for the processes to finish.
                                                 deleteLocalStorageProcess.waitFor();
@@ -1793,10 +1725,10 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
             case R.id.easylist:
                 // Toggle the EasyList status.
-                easyListEnabled = !easyListEnabled;
+                currentWebView.enableBlocklist(NestedScrollWebView.EASY_LIST, !currentWebView.isBlocklistEnabled(NestedScrollWebView.EASY_LIST));
 
                 // Update the menu checkbox.
-                menuItem.setChecked(easyListEnabled);
+                menuItem.setChecked(currentWebView.isBlocklistEnabled(NestedScrollWebView.EASY_LIST));
 
                 // Reload the current WebView.
                 currentWebView.reload();
@@ -1804,10 +1736,10 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
             case R.id.easyprivacy:
                 // Toggle the EasyPrivacy status.
-                easyPrivacyEnabled = !easyPrivacyEnabled;
+                currentWebView.enableBlocklist(NestedScrollWebView.EASY_PRIVACY, !currentWebView.isBlocklistEnabled(NestedScrollWebView.EASY_PRIVACY));
 
                 // Update the menu checkbox.
-                menuItem.setChecked(easyPrivacyEnabled);
+                menuItem.setChecked(currentWebView.isBlocklistEnabled(NestedScrollWebView.EASY_PRIVACY));
 
                 // Reload the current WebView.
                 currentWebView.reload();
@@ -1815,14 +1747,14 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
             case R.id.fanboys_annoyance_list:
                 // Toggle Fanboy's Annoyance List status.
-                fanboysAnnoyanceListEnabled = !fanboysAnnoyanceListEnabled;
+                currentWebView.enableBlocklist(NestedScrollWebView.FANBOYS_ANNOYANCE_LIST, !currentWebView.isBlocklistEnabled(NestedScrollWebView.FANBOYS_ANNOYANCE_LIST));
 
                 // Update the menu checkbox.
-                menuItem.setChecked(fanboysAnnoyanceListEnabled);
+                menuItem.setChecked(currentWebView.isBlocklistEnabled(NestedScrollWebView.FANBOYS_ANNOYANCE_LIST));
 
                 // Update the staus of Fanboy's Social Blocking List.
                 MenuItem fanboysSocialBlockingListMenuItem = optionsMenu.findItem(R.id.fanboys_social_blocking_list);
-                fanboysSocialBlockingListMenuItem.setEnabled(!fanboysAnnoyanceListEnabled);
+                fanboysSocialBlockingListMenuItem.setEnabled(!currentWebView.isBlocklistEnabled(NestedScrollWebView.FANBOYS_ANNOYANCE_LIST));
 
                 // Reload the current WebView.
                 currentWebView.reload();
@@ -1830,10 +1762,10 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
             case R.id.fanboys_social_blocking_list:
                 // Toggle Fanboy's Social Blocking List status.
-                fanboysSocialBlockingListEnabled = !fanboysSocialBlockingListEnabled;
+                currentWebView.enableBlocklist(NestedScrollWebView.FANBOYS_SOCIAL_BLOCKING_LIST, !currentWebView.isBlocklistEnabled(NestedScrollWebView.FANBOYS_SOCIAL_BLOCKING_LIST));
 
                 // Update the menu checkbox.
-                menuItem.setChecked(fanboysSocialBlockingListEnabled);
+                menuItem.setChecked(currentWebView.isBlocklistEnabled(NestedScrollWebView.FANBOYS_SOCIAL_BLOCKING_LIST));
 
                 // Reload the current WebView.
                 currentWebView.reload();
@@ -1841,10 +1773,10 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
             case R.id.ultraprivacy:
                 // Toggle the UltraPrivacy status.
-                ultraPrivacyEnabled = !ultraPrivacyEnabled;
+                currentWebView.enableBlocklist(NestedScrollWebView.ULTRA_PRIVACY, !currentWebView.isBlocklistEnabled(NestedScrollWebView.ULTRA_PRIVACY));
 
                 // Update the menu checkbox.
-                menuItem.setChecked(ultraPrivacyEnabled);
+                menuItem.setChecked(currentWebView.isBlocklistEnabled(NestedScrollWebView.ULTRA_PRIVACY));
 
                 // Reload the current WebView.
                 currentWebView.reload();
@@ -1852,10 +1784,10 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
             case R.id.block_all_third_party_requests:
                 //Toggle the third-party requests blocker status.
-                blockAllThirdPartyRequests = !blockAllThirdPartyRequests;
+                currentWebView.enableBlocklist(NestedScrollWebView.THIRD_PARTY_REQUESTS, !currentWebView.isBlocklistEnabled(NestedScrollWebView.THIRD_PARTY_REQUESTS));
 
                 // Update the menu checkbox.
-                menuItem.setChecked(blockAllThirdPartyRequests);
+                menuItem.setChecked(currentWebView.isBlocklistEnabled(NestedScrollWebView.THIRD_PARTY_REQUESTS));
 
                 // Reload the current WebView.
                 currentWebView.reload();
@@ -2111,7 +2043,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
             case R.id.add_to_homescreen:
                 // Instantiate the create home screen shortcut dialog.
-                DialogFragment createHomeScreenShortcutDialogFragment = CreateHomeScreenShortcutDialog.createDialog(currentWebView.getTitle(), formattedUrlString, favoriteIconBitmap);
+                DialogFragment createHomeScreenShortcutDialogFragment = CreateHomeScreenShortcutDialog.createDialog(currentWebView.getTitle(), formattedUrlString, currentWebView.getFavoriteOrDefaultIcon());
 
                 // Show the create home screen shortcut dialog.
                 createHomeScreenShortcutDialogFragment.show(getSupportFragmentManager(), getString(R.string.create_shortcut));
@@ -2157,8 +2089,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         // Run the commands that correspond to the selected menu item.
         switch (menuItemId) {
             case R.id.close_tab:
-                // Get a handle for the tab layout.
+                // Get a handle for the tab layout and the view pager.
                 TabLayout tabLayout = findViewById(R.id.tablayout);
+                ViewPager webViewPager = findViewById(R.id.webviewpager);
 
                 // Get the current tab number.
                 int currentTabNumber = tabLayout.getSelectedTabPosition();
@@ -2166,8 +2099,10 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 // Delete the current tab.
                 tabLayout.removeTabAt(currentTabNumber);
 
-                // Delete the current page.
-                webViewPagerAdapter.deletePage(currentTabNumber);
+                // Delete the current page.  If the selected page number did not change during the delete, it will return true, meaning that the current WebView must be reset.
+                if (webViewPagerAdapter.deletePage(currentTabNumber, webViewPager)) {
+                    setCurrentWebView(currentTabNumber);
+                }
                 break;
 
             case R.id.clear_and_exit:
@@ -2181,20 +2116,23 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 // Get the status of the clear everything preference.
                 boolean clearEverything = sharedPreferences.getBoolean("clear_everything", true);
 
+                // Get a handle for the runtime.
+                Runtime runtime = Runtime.getRuntime();
+
                 // Clear cookies.
                 if (clearEverything || sharedPreferences.getBoolean("clear_cookies", true)) {
                     // The command to remove cookies changed slightly in API 21.
                     if (Build.VERSION.SDK_INT >= 21) {
-                        cookieManager.removeAllCookies(null);
+                        CookieManager.getInstance().removeAllCookies(null);
                     } else {
-                        cookieManager.removeAllCookie();
+                        CookieManager.getInstance().removeAllCookie();
                     }
 
                     // Manually delete the cookies database, as `CookieManager` sometimes will not flush its changes to disk before `System.exit(0)` is run.
                     try {
                         // Two commands must be used because `Runtime.exec()` does not like `*`.
-                        Process deleteCookiesProcess = privacyBrowserRuntime.exec("rm -f " + privateDataDirectoryString + "/app_webview/Cookies");
-                        Process deleteCookiesJournalProcess = privacyBrowserRuntime.exec("rm -f " + privateDataDirectoryString + "/app_webview/Cookies-journal");
+                        Process deleteCookiesProcess = runtime.exec("rm -f " + privateDataDirectoryString + "/app_webview/Cookies");
+                        Process deleteCookiesJournalProcess = runtime.exec("rm -f " + privateDataDirectoryString + "/app_webview/Cookies-journal");
 
                         // Wait until the processes have finished.
                         deleteCookiesProcess.waitFor();
@@ -2213,13 +2151,13 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                     // Manually delete the DOM storage files and directories, as `WebStorage` sometimes will not flush its changes to disk before `System.exit(0)` is run.
                     try {
                         // A `String[]` must be used because the directory contains a space and `Runtime.exec` will otherwise not escape the string correctly.
-                        Process deleteLocalStorageProcess = privacyBrowserRuntime.exec(new String[] {"rm", "-rf", privateDataDirectoryString + "/app_webview/Local Storage/"});
+                        Process deleteLocalStorageProcess = runtime.exec(new String[] {"rm", "-rf", privateDataDirectoryString + "/app_webview/Local Storage/"});
 
                         // Multiple commands must be used because `Runtime.exec()` does not like `*`.
-                        Process deleteIndexProcess = privacyBrowserRuntime.exec("rm -rf " + privateDataDirectoryString + "/app_webview/IndexedDB");
-                        Process deleteQuotaManagerProcess = privacyBrowserRuntime.exec("rm -f " + privateDataDirectoryString + "/app_webview/QuotaManager");
-                        Process deleteQuotaManagerJournalProcess = privacyBrowserRuntime.exec("rm -f " + privateDataDirectoryString + "/app_webview/QuotaManager-journal");
-                        Process deleteDatabaseProcess = privacyBrowserRuntime.exec("rm -rf " + privateDataDirectoryString + "/app_webview/databases");
+                        Process deleteIndexProcess = runtime.exec("rm -rf " + privateDataDirectoryString + "/app_webview/IndexedDB");
+                        Process deleteQuotaManagerProcess = runtime.exec("rm -f " + privateDataDirectoryString + "/app_webview/QuotaManager");
+                        Process deleteQuotaManagerJournalProcess = runtime.exec("rm -f " + privateDataDirectoryString + "/app_webview/QuotaManager-journal");
+                        Process deleteDatabaseProcess = runtime.exec("rm -rf " + privateDataDirectoryString + "/app_webview/databases");
 
                         // Wait until the processes have finished.
                         deleteLocalStorageProcess.waitFor();
@@ -2240,8 +2178,8 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                     // Manually delete the form data database, as `WebViewDatabase` sometimes will not flush its changes to disk before `System.exit(0)` is run.
                     try {
                         // A string array must be used because the database contains a space and `Runtime.exec` will not otherwise escape the string correctly.
-                        Process deleteWebDataProcess = privacyBrowserRuntime.exec(new String[] {"rm", "-f", privateDataDirectoryString + "/app_webview/Web Data"});
-                        Process deleteWebDataJournalProcess = privacyBrowserRuntime.exec(new String[] {"rm", "-f", privateDataDirectoryString + "/app_webview/Web Data-journal"});
+                        Process deleteWebDataProcess = runtime.exec(new String[] {"rm", "-f", privateDataDirectoryString + "/app_webview/Web Data"});
+                        Process deleteWebDataJournalProcess = runtime.exec(new String[] {"rm", "-f", privateDataDirectoryString + "/app_webview/Web Data-journal"});
 
                         // Wait until the processes have finished.
                         deleteWebDataProcess.waitFor();
@@ -2274,11 +2212,11 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                     // Manually delete the cache directories.
                     try {
                         // Delete the main cache directory.
-                        Process deleteCacheProcess = privacyBrowserRuntime.exec("rm -rf " + privateDataDirectoryString + "/cache");
+                        Process deleteCacheProcess = runtime.exec("rm -rf " + privateDataDirectoryString + "/cache");
 
                         // Delete the secondary `Service Worker` cache directory.
                         // A string array must be used because the directory contains a space and `Runtime.exec` will otherwise not escape the string correctly.
-                        Process deleteServiceWorkerProcess = privacyBrowserRuntime.exec(new String[] {"rm", "-rf", privateDataDirectoryString + "/app_webview/Service Worker/"});
+                        Process deleteServiceWorkerProcess = runtime.exec(new String[] {"rm", "-rf", privateDataDirectoryString + "/app_webview/Service Worker/"});
 
                         // Wait until the processes have finished.
                         deleteCacheProcess.waitFor();
@@ -2323,7 +2261,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 if (clearEverything) {
                     try {
                         // Delete the folder.
-                        Process deleteAppWebviewProcess = privacyBrowserRuntime.exec("rm -rf " + privateDataDirectoryString + "/app_webview");
+                        Process deleteAppWebviewProcess = runtime.exec("rm -rf " + privateDataDirectoryString + "/app_webview");
 
                         // Wait until the process has finished.
                         deleteAppWebviewProcess.waitFor();
@@ -2389,6 +2327,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 // Create an intent to launch the Requests activity.
                 Intent requestsIntent = new Intent(this, RequestsActivity.class);
 
+                // Add the block third-party requests status to the intent.
+                requestsIntent.putExtra("block_all_third_party_requests", currentWebView.isBlocklistEnabled(NestedScrollWebView.THIRD_PARTY_REQUESTS));
+
                 // Make it so.
                 startActivity(requestsIntent);
                 break;
@@ -2780,7 +2721,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     }
 
     @Override
-    public void onCreateBookmark(DialogFragment dialogFragment) {
+    public void onCreateBookmark(DialogFragment dialogFragment, Bitmap favoriteIconBitmap) {
         // Get the views from the dialog fragment.
         EditText createBookmarkNameEditText = dialogFragment.getDialog().findViewById(R.id.create_bookmark_name_edittext);
         EditText createBookmarkUrlEditText = dialogFragment.getDialog().findViewById(R.id.create_bookmark_url_edittext);
@@ -2789,19 +2730,11 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         String bookmarkNameString = createBookmarkNameEditText.getText().toString();
         String bookmarkUrlString = createBookmarkUrlEditText.getText().toString();
 
-        // Get a copy of the favorite icon bitmap.
-        Bitmap favoriteIcon = favoriteIconBitmap;
-
-        // Scale the favorite icon bitmap down if it is larger than 256 x 256.  Filtering uses bilinear interpolation.
-        if ((favoriteIcon.getHeight() > 256) || (favoriteIcon.getWidth() > 256)) {
-            favoriteIcon = Bitmap.createScaledBitmap(favoriteIcon, 256, 256, true);
-        }
-
         // Create a favorite icon byte array output stream.
         ByteArrayOutputStream favoriteIconByteArrayOutputStream = new ByteArrayOutputStream();
 
         // Convert the favorite icon bitmap to a byte array.  `0` is for lossless compression (the only option for a PNG).
-        favoriteIcon.compress(Bitmap.CompressFormat.PNG, 0, favoriteIconByteArrayOutputStream);
+        favoriteIconBitmap.compress(Bitmap.CompressFormat.PNG, 0, favoriteIconByteArrayOutputStream);
 
         // Convert the favorite icon byte array stream to a byte array.
         byte[] favoriteIconByteArray = favoriteIconByteArrayOutputStream.toByteArray();
@@ -2823,7 +2756,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     }
 
     @Override
-    public void onCreateBookmarkFolder(DialogFragment dialogFragment) {
+    public void onCreateBookmarkFolder(DialogFragment dialogFragment, Bitmap favoriteIconBitmap) {
         // Get handles for the views in the dialog fragment.
         EditText createFolderNameEditText = dialogFragment.getDialog().findViewById(R.id.create_folder_name_edittext);
         RadioButton defaultFolderIconRadioButton = dialogFragment.getDialog().findViewById(R.id.create_folder_default_icon_radiobutton);
@@ -2846,13 +2779,8 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             // Convert the folder icon bitmap drawable to a bitmap.
             folderIconBitmap = folderIconBitmapDrawable.getBitmap();
         } else {  // Use the WebView favorite icon.
-            // Get a copy of the favorite icon bitmap.
+            // Copy the favorite icon bitmap to the folder icon bitmap.
             folderIconBitmap = favoriteIconBitmap;
-
-            // Scale the folder icon bitmap down if it is larger than 256 x 256.  Filtering uses bilinear interpolation.
-            if ((folderIconBitmap.getHeight() > 256) || (folderIconBitmap.getWidth() > 256)) {
-                folderIconBitmap = Bitmap.createScaledBitmap(folderIconBitmap, 256, 256, true);
-            }
         }
 
         // Create a folder icon byte array output stream.
@@ -2884,7 +2812,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     }
 
     @Override
-    public void onSaveBookmark(DialogFragment dialogFragment, int selectedBookmarkDatabaseId) {
+    public void onSaveBookmark(DialogFragment dialogFragment, int selectedBookmarkDatabaseId, Bitmap favoriteIconBitmap) {
         // Get handles for the views from `dialogFragment`.
         EditText editBookmarkNameEditText = dialogFragment.getDialog().findViewById(R.id.edit_bookmark_name_edittext);
         EditText editBookmarkUrlEditText = dialogFragment.getDialog().findViewById(R.id.edit_bookmark_url_edittext);
@@ -2898,19 +2826,11 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         if (currentBookmarkIconRadioButton.isChecked()) {  // Update the bookmark without changing the favorite icon.
             bookmarksDatabaseHelper.updateBookmark(selectedBookmarkDatabaseId, bookmarkNameString, bookmarkUrlString);
         } else {  // Update the bookmark using the `WebView` favorite icon.
-            // Get a copy of the favorite icon bitmap.
-            Bitmap favoriteIcon = favoriteIconBitmap;
-
-            // Scale the favorite icon bitmap down if it is larger than 256 x 256.  Filtering uses bilinear interpolation.
-            if ((favoriteIcon.getHeight() > 256) || (favoriteIcon.getWidth() > 256)) {
-                favoriteIcon = Bitmap.createScaledBitmap(favoriteIcon, 256, 256, true);
-            }
-
             // Create a favorite icon byte array output stream.
             ByteArrayOutputStream newFavoriteIconByteArrayOutputStream = new ByteArrayOutputStream();
 
             // Convert the favorite icon bitmap to a byte array.  `0` is for lossless compression (the only option for a PNG).
-            favoriteIcon.compress(Bitmap.CompressFormat.PNG, 0, newFavoriteIconByteArrayOutputStream);
+            favoriteIconBitmap.compress(Bitmap.CompressFormat.PNG, 0, newFavoriteIconByteArrayOutputStream);
 
             // Convert the favorite icon byte array stream to a byte array.
             byte[] newFavoriteIconByteArray = newFavoriteIconByteArrayOutputStream.toByteArray();
@@ -2927,7 +2847,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     }
 
     @Override
-    public void onSaveBookmarkFolder(DialogFragment dialogFragment, int selectedFolderDatabaseId) {
+    public void onSaveBookmarkFolder(DialogFragment dialogFragment, int selectedFolderDatabaseId, Bitmap favoriteIconBitmap) {
         // Get handles for the views from `dialogFragment`.
         EditText editFolderNameEditText = dialogFragment.getDialog().findViewById(R.id.edit_folder_name_edittext);
         RadioButton currentFolderIconRadioButton = dialogFragment.getDialog().findViewById(R.id.edit_folder_current_icon_radiobutton);
@@ -2956,13 +2876,8 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 // Convert the folder icon bitmap drawable to a bitmap.
                 folderIconBitmap = folderIconBitmapDrawable.getBitmap();
             } else {  // Use the `WebView` favorite icon.
-                // Get a copy of the favorite icon bitmap.
-                folderIconBitmap = MainWebViewActivity.favoriteIconBitmap;
-
-                // Scale the folder icon bitmap down if it is larger than 256 x 256.  Filtering uses bilinear interpolation.
-                if ((folderIconBitmap.getHeight() > 256) || (folderIconBitmap.getWidth() > 256)) {
-                    folderIconBitmap = Bitmap.createScaledBitmap(folderIconBitmap, 256, 256, true);
-                }
+                // Copy the favorite icon bitmap to the folder icon bitmap.
+                folderIconBitmap = favoriteIconBitmap;
             }
 
             // Create a folder icon byte array output stream.
@@ -2989,13 +2904,8 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 // Convert the folder icon bitmap drawable to a bitmap.
                 folderIconBitmap = folderIconBitmapDrawable.getBitmap();
             } else {  // Use the `WebView` favorite icon.
-                // Get a copy of the favorite icon bitmap.
-                folderIconBitmap = MainWebViewActivity.favoriteIconBitmap;
-
-                // Scale the folder icon bitmap down if it is larger than 256 x 256.  Filtering uses bilinear interpolation.
-                if ((folderIconBitmap.getHeight() > 256) || (folderIconBitmap.getWidth() > 256)) {
-                    folderIconBitmap = Bitmap.createScaledBitmap(folderIconBitmap, 256, 256, true);
-                }
+                // Copy the favorite icon bitmap to the folder icon bitmap.
+                folderIconBitmap = favoriteIconBitmap;
             }
 
             // Create a folder icon byte array output stream.
@@ -3087,7 +2997,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             // Code contributed 2017 Hendrik Knackstedt.  Copyright assigned to Soren Stoutner <soren@stoutner.com>.
             if (firstPartyCookiesEnabled) {
                 // Get the cookies for `imageUrl`.
-                String cookies = cookieManager.getCookie(imageUrl);
+                String cookies = CookieManager.getInstance().getCookie(imageUrl);
 
                 // Add the cookies to `downloadRequest`.  In the HTTP request header, cookies are named `Cookie`.
                 downloadRequest.addRequestHeader("Cookie", cookies);
@@ -3139,7 +3049,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             // Code contributed 2017 Hendrik Knackstedt.  Copyright assigned to Soren Stoutner <soren@stoutner.com>.
             if (firstPartyCookiesEnabled) {
                 // Get the cookies for `downloadUrl`.
-                String cookies = cookieManager.getCookie(downloadUrl);
+                String cookies = CookieManager.getInstance().getCookie(downloadUrl);
 
                 // Add the cookies to `downloadRequest`.  In the HTTP request header, cookies are named `Cookie`.
                 downloadRequest.addRequestHeader("Cookie", cookies);
@@ -3500,8 +3410,8 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     // `reloadWebsite` is used if returning from the Domains activity.  Otherwise JavaScript might not function correctly if it is newly enabled.
     @SuppressLint("SetJavaScriptEnabled")
     private boolean applyDomainSettings(NestedScrollWebView nestedScrollWebView, String url, boolean resetFavoriteIcon, boolean reloadWebsite) {
-        // Get a handle for the URL edit text.
-        EditText urlEditText = findViewById(R.id.url_edittext);
+        // Get a handle for the URL relative layout.
+        RelativeLayout urlRelativeLayout = findViewById(R.id.url_relativelayout);
 
         // Store a copy of the current user agent to track changes for the return boolean.
         String initialUserAgent = nestedScrollWebView.getSettings().getUserAgentString();
@@ -3531,8 +3441,8 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
             // Reset the favorite icon if specified.
             if (resetFavoriteIcon) {
-                // Store the favorite icon bitmap.
-                favoriteIconBitmap = favoriteIconDefaultBitmap;  // TODO.
+                // Initialize the favorite icon.
+                currentWebView.initializeFavoriteIcon();
 
                 // Get a handle for the tab layout.
                 TabLayout tabLayout = findViewById(R.id.tablayout);
@@ -3553,7 +3463,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 ImageView currentTabFavoriteIconImageView = currentTabCustomView.findViewById(R.id.favorite_icon_imageview);
 
                 // Set the default favorite icon as the favorite icon for this tab.
-                currentTabFavoriteIconImageView.setImageBitmap(Bitmap.createScaledBitmap(favoriteIconBitmap, 64, 64, true));
+                currentTabFavoriteIconImageView.setImageBitmap(Bitmap.createScaledBitmap(nestedScrollWebView.getFavoriteOrDefaultIcon(), 64, 64, true));
             }
 
             // Get a handle for the swipe refresh layout.
@@ -3623,59 +3533,65 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             nightMode = sharedPreferences.getBoolean("night_mode", false);  // TODO.
             boolean displayWebpageImages = sharedPreferences.getBoolean("display_webpage_images", true);
 
-            // Declare the JavaScript tracker.
-            boolean javaScriptEnabled;
+            // Get a handle for the cookie manager.
+            CookieManager cookieManager = CookieManager.getInstance();
 
             if (nestedScrollWebView.getDomainSettingsApplied()) {  // The url has custom domain settings.
                 // Get a cursor for the current host and move it to the first position.
-                Cursor currentHostDomainSettingsCursor = domainsDatabaseHelper.getCursorForDomainName(domainNameInDatabase);
-                currentHostDomainSettingsCursor.moveToFirst();
+                Cursor currentDomainSettingsCursor = domainsDatabaseHelper.getCursorForDomainName(domainNameInDatabase);
+                currentDomainSettingsCursor.moveToFirst();
 
                 // Get the settings from the cursor.
-                nestedScrollWebView.setDomainSettingsDatabaseId(currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper._ID)));
-                javaScriptEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_JAVASCRIPT)) == 1);  // TODO.  Rename to domainSettingsJavaScriptEnabled after the global variable is removed.
-                firstPartyCookiesEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FIRST_PARTY_COOKIES)) == 1);  // TODO.
-                thirdPartyCookiesEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_THIRD_PARTY_COOKIES)) == 1);  // TODO.
-                domStorageEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_DOM_STORAGE)) == 1);  // TODO.
+                nestedScrollWebView.setDomainSettingsDatabaseId(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper._ID)));
+                boolean domainJavaScriptEnabled = (currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_JAVASCRIPT)) == 1);
+                firstPartyCookiesEnabled = (currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FIRST_PARTY_COOKIES)) == 1);  // TODO.
+                boolean domainThirdPartyCookiesEnabled = (currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_THIRD_PARTY_COOKIES)) == 1);
+                boolean domainDomStorageEnabled = (currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_DOM_STORAGE)) == 1);
                 // Form data can be removed once the minimum API >= 26.
-                saveFormDataEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FORM_DATA)) == 1);  // TODO.
-                easyListEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYLIST)) == 1);  // TODO.
-                easyPrivacyEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYPRIVACY)) == 1);  // TODO.
-                fanboysAnnoyanceListEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST)) == 1);  // TODO.
-                fanboysSocialBlockingListEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST)) == 1);  // TODO.
-                ultraPrivacyEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY)) == 1);  // TODO.
-                blockAllThirdPartyRequests = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS)) == 1);  // TODO.
-                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));
-                int nightModeInt = currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.NIGHT_MODE));
-                int displayWebpageImagesInt = currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.DISPLAY_IMAGES));
-                boolean pinnedSslCertificate = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.PINNED_SSL_CERTIFICATE)) == 1);
-                String pinnedSslIssuedToCName = currentHostDomainSettingsCursor.getString(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_COMMON_NAME));
-                String pinnedSslIssuedToOName = currentHostDomainSettingsCursor.getString(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATION));
-                String pinnedSslIssuedToUName = currentHostDomainSettingsCursor.getString(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATIONAL_UNIT));
-                String pinnedSslIssuedByCName = currentHostDomainSettingsCursor.getString(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_COMMON_NAME));
-                String pinnedSslIssuedByOName = currentHostDomainSettingsCursor.getString(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATION));
-                String pinnedSslIssuedByUName = currentHostDomainSettingsCursor.getString(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATIONAL_UNIT));
-                boolean pinnedIpAddresses = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.PINNED_IP_ADDRESSES)) == 1);
-                String pinnedHostIpAddresses = currentHostDomainSettingsCursor.getString(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.IP_ADDRESSES));
+                saveFormDataEnabled = (currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FORM_DATA)) == 1);  // TODO.
+                nestedScrollWebView.enableBlocklist(NestedScrollWebView.EASY_LIST,
+                        currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYLIST)) == 1);
+                nestedScrollWebView.enableBlocklist(NestedScrollWebView.EASY_PRIVACY,
+                        currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYPRIVACY)) == 1);
+                nestedScrollWebView.enableBlocklist(NestedScrollWebView.FANBOYS_ANNOYANCE_LIST,
+                        currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST)) == 1);
+                nestedScrollWebView.enableBlocklist(NestedScrollWebView.FANBOYS_SOCIAL_BLOCKING_LIST,
+                        currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST)) == 1);
+                nestedScrollWebView.enableBlocklist(NestedScrollWebView.ULTRA_PRIVACY,
+                        currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY)) == 1);
+                nestedScrollWebView.enableBlocklist(NestedScrollWebView.THIRD_PARTY_REQUESTS,
+                        currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS)) == 1);
+                String userAgentName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.USER_AGENT));
+                int fontSize = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.FONT_SIZE));
+                int swipeToRefreshInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SWIPE_TO_REFRESH));
+                int nightModeInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.NIGHT_MODE));
+                int displayWebpageImagesInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.DISPLAY_IMAGES));
+                boolean pinnedSslCertificate = (currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.PINNED_SSL_CERTIFICATE)) == 1);
+                String pinnedSslIssuedToCName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_COMMON_NAME));
+                String pinnedSslIssuedToOName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATION));
+                String pinnedSslIssuedToUName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATIONAL_UNIT));
+                String pinnedSslIssuedByCName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_COMMON_NAME));
+                String pinnedSslIssuedByOName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATION));
+                String pinnedSslIssuedByUName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATIONAL_UNIT));
+                boolean pinnedIpAddresses = (currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.PINNED_IP_ADDRESSES)) == 1);
+                String pinnedHostIpAddresses = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.IP_ADDRESSES));
 
                 // Create the pinned SSL date variables.
                 Date pinnedSslStartDate;
                 Date pinnedSslEndDate;
 
                 // Set the pinned SSL certificate start date to `null` if the saved date `long` is 0 because creating a new Date results in an error if the input is 0.
-                if (currentHostDomainSettingsCursor.getLong(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_START_DATE)) == 0) {
+                if (currentDomainSettingsCursor.getLong(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_START_DATE)) == 0) {
                     pinnedSslStartDate = null;
                 } else {
-                    pinnedSslStartDate = new Date(currentHostDomainSettingsCursor.getLong(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_START_DATE)));
+                    pinnedSslStartDate = new Date(currentDomainSettingsCursor.getLong(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_START_DATE)));
                 }
 
                 // Set the pinned SSL certificate end date to `null` if the saved date `long` is 0 because creating a new Date results in an error if the input is 0.
-                if (currentHostDomainSettingsCursor.getLong(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_END_DATE)) == 0) {
+                if (currentDomainSettingsCursor.getLong(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_END_DATE)) == 0) {
                     pinnedSslEndDate = null;
                 } else {
-                    pinnedSslEndDate = new Date(currentHostDomainSettingsCursor.getLong(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_END_DATE)));
+                    pinnedSslEndDate = new Date(currentDomainSettingsCursor.getLong(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_END_DATE)));
                 }
 
                 // If there is a pinned SSL certificate, store it in the WebView.
@@ -3702,7 +3618,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
                 // TODO.
                 // Store the domain JavaScript status.  This is used by the options menu night mode toggle.
-                domainSettingsJavaScriptEnabled = javaScriptEnabled;
+                domainSettingsJavaScriptEnabled = domainJavaScriptEnabled;
 
                 // Enable JavaScript if night mode is enabled.
                 if (nightMode) {
@@ -3710,15 +3626,15 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                     nestedScrollWebView.getSettings().setJavaScriptEnabled(true);
                 } else {
                     // Set JavaScript according to the domain settings.
-                    nestedScrollWebView.getSettings().setJavaScriptEnabled(javaScriptEnabled);
+                    nestedScrollWebView.getSettings().setJavaScriptEnabled(domainJavaScriptEnabled);
                 }
 
                 // Close `currentHostDomainSettingsCursor`.
-                currentHostDomainSettingsCursor.close();
+                currentDomainSettingsCursor.close();
 
                 // Apply the domain settings.
                 cookieManager.setAcceptCookie(firstPartyCookiesEnabled);  //TODO  This could be bad.
-                nestedScrollWebView.getSettings().setDomStorageEnabled(domStorageEnabled);  // TODO.
+                nestedScrollWebView.getSettings().setDomStorageEnabled(domainDomStorageEnabled);  // TODO.  Move up.
 
                 // Apply the form data setting if the API < 26.
                 if (Build.VERSION.SDK_INT < 26) {
@@ -3734,7 +3650,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
                 // Set third-party cookies status if API >= 21.
                 if (Build.VERSION.SDK_INT >= 21) {
-                    cookieManager.setAcceptThirdPartyCookies(nestedScrollWebView, thirdPartyCookiesEnabled);  // TODO.
+                    cookieManager.setAcceptThirdPartyCookies(nestedScrollWebView, domainThirdPartyCookiesEnabled);
                 }
 
                 // Only set the user agent if the webpage is not currently loading.  Otherwise, changing the user agent on redirects can cause the original website to reload.
@@ -3819,38 +3735,37 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                         break;
                 }
 
-                // Set a green background on URL edit text to indicate that custom domain settings are being used. The deprecated `.getDrawable()` must be used until the minimum API >= 21.
+                // Set a green background on the URL relative layout to indicate that custom domain settings are being used. The deprecated `.getDrawable()` must be used until the minimum API >= 21.
                 if (darkTheme) {
-                    urlEditText.setBackground(getResources().getDrawable(R.drawable.url_bar_background_dark_blue));
+                    urlRelativeLayout.setBackground(getResources().getDrawable(R.drawable.url_bar_background_dark_blue));
                 } else {
-                    urlEditText.setBackground(getResources().getDrawable(R.drawable.url_bar_background_light_green));
+                    urlRelativeLayout.setBackground(getResources().getDrawable(R.drawable.url_bar_background_light_green));
                 }
             } else {  // The new URL does not have custom domain settings.  Load the defaults.
-                // Store the values from `sharedPreferences` in variables.
-                javaScriptEnabled = sharedPreferences.getBoolean("javascript", false);  // TODO.
+                // Store the values from the shared preferences.
+                boolean defaultJavaScriptEnabled = sharedPreferences.getBoolean("javascript", false);
                 firstPartyCookiesEnabled = sharedPreferences.getBoolean("first_party_cookies", false);  // TODO.
-                thirdPartyCookiesEnabled = sharedPreferences.getBoolean("third_party_cookies", false);  // TODO.
-                domStorageEnabled = sharedPreferences.getBoolean("dom_storage", false);  // TODO.
+                boolean defaultThirdPartyCookiesEnabled = sharedPreferences.getBoolean("third_party_cookies", false);
+                nestedScrollWebView.getSettings().setDomStorageEnabled(sharedPreferences.getBoolean("dom_storage", false));
                 saveFormDataEnabled = sharedPreferences.getBoolean("save_form_data", false);  // Form data can be removed once the minimum API >= 26.  // TODO.
-                easyListEnabled = sharedPreferences.getBoolean("easylist", true);  // TODO.
-                easyPrivacyEnabled = sharedPreferences.getBoolean("easyprivacy", true);  // TODO.
-                fanboysAnnoyanceListEnabled = sharedPreferences.getBoolean("fanboys_annoyance_list", true);  // TODO.
-                fanboysSocialBlockingListEnabled = sharedPreferences.getBoolean("fanboys_social_blocking_list", true);  // TODO.
-                ultraPrivacyEnabled = sharedPreferences.getBoolean("ultraprivacy", true);  // TODO.
-                blockAllThirdPartyRequests = sharedPreferences.getBoolean("block_all_third_party_requests", false);  // TODO.
-
-                // Set `javaScriptEnabled` to be `true` if `night_mode` is `true`.
+                nestedScrollWebView.enableBlocklist(NestedScrollWebView.EASY_LIST, sharedPreferences.getBoolean("easylist", true));
+                nestedScrollWebView.enableBlocklist(NestedScrollWebView.EASY_PRIVACY, sharedPreferences.getBoolean("easyprivacy", true));
+                nestedScrollWebView.enableBlocklist(NestedScrollWebView.FANBOYS_ANNOYANCE_LIST, sharedPreferences.getBoolean("fanboys_annoyance_list", true));
+                nestedScrollWebView.enableBlocklist(NestedScrollWebView.FANBOYS_SOCIAL_BLOCKING_LIST, sharedPreferences.getBoolean("fanboys_social_blocking_list", true));
+                nestedScrollWebView.enableBlocklist(NestedScrollWebView.ULTRA_PRIVACY, sharedPreferences.getBoolean("ultraprivacy", true));
+                nestedScrollWebView.enableBlocklist(NestedScrollWebView.THIRD_PARTY_REQUESTS, sharedPreferences.getBoolean("block_all_third_party_requests", false));
+
+                // Enable JavaScript if night mode is enabled.
                 if (nightMode) {
                     // Enable JavaScript.
                     nestedScrollWebView.getSettings().setJavaScriptEnabled(true);
                 } else {
                     // Set JavaScript according to the domain settings.
-                    nestedScrollWebView.getSettings().setJavaScriptEnabled(javaScriptEnabled);
+                    nestedScrollWebView.getSettings().setJavaScriptEnabled(defaultJavaScriptEnabled);
                 }
 
                 // Apply the default settings.
                 cookieManager.setAcceptCookie(firstPartyCookiesEnabled);  // TODO.
-                nestedScrollWebView.getSettings().setDomStorageEnabled(domStorageEnabled);  // TODO.
                 nestedScrollWebView.getSettings().setTextZoom(Integer.valueOf(defaultFontSizeString));
                 swipeRefreshLayout.setEnabled(defaultSwipeToRefresh);
 
@@ -3864,7 +3779,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
                 // Set third-party cookies status if API >= 21.
                 if (Build.VERSION.SDK_INT >= 21) {
-                    cookieManager.setAcceptThirdPartyCookies(nestedScrollWebView, thirdPartyCookiesEnabled);
+                    cookieManager.setAcceptThirdPartyCookies(nestedScrollWebView, defaultThirdPartyCookiesEnabled);
                 }
 
                 // Only set the user agent if the webpage is not currently loading.  Otherwise, changing the user agent on redirects can cause the original website to reload.
@@ -3900,7 +3815,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 nestedScrollWebView.getSettings().setLoadsImagesAutomatically(displayWebpageImages);
 
                 // Set a transparent background on URL edit text.  The deprecated `getResources().getDrawable()` must be used until the minimum API >= 21.
-                urlEditText.setBackground(getResources().getDrawable(R.color.transparent));
+                urlRelativeLayout.setBackground(getResources().getDrawable(R.color.transparent));
             }
 
             // Close the domains database helper.
@@ -4060,7 +3975,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             }
 
             // Update the DOM storage icon.
-            if (currentWebView.getSettings().getJavaScriptEnabled() && domStorageEnabled) {  // Both JavaScript and DOM storage are enabled.
+            if (currentWebView.getSettings().getJavaScriptEnabled() && currentWebView.getSettings().getDomStorageEnabled()) {  // Both JavaScript and DOM storage are enabled.
                 domStorageMenuItem.setIcon(R.drawable.dom_storage_enabled);
             } else if (currentWebView.getSettings().getJavaScriptEnabled()) {  // JavaScript is enabled but DOM storage is disabled.
                 if (darkTheme) {
@@ -4248,8 +4163,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     }
 
     public void addTab(View view) {
-        // Get a handle for the tab layout.
+        // Get a handle for the tab layout and the view pager.
         TabLayout tabLayout = findViewById(R.id.tablayout);
+        ViewPager webViewPager = findViewById(R.id.webviewpager);
 
         // Get the new page number.  The page numbers are 0 indexed, so the new page number will match the current count.
         int newTabNumber = tabLayout.getTabCount();
@@ -4263,15 +4179,58 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         // Remove the lint warning below that the current tab might be null.
         assert newTab != null;
 
-        // Set a custom view on the current tab.
+        // Set a custom view on the new tab.
         newTab.setCustomView(R.layout.custom_tab_view);
 
         // Add the new WebView page.
-        webViewPagerAdapter.addPage(newTabNumber);
+        webViewPagerAdapter.addPage(newTabNumber, webViewPager);
+    }
+
+    private void setCurrentWebView(int pageNumber) {
+        // Get handles for the URL views.
+        RelativeLayout urlRelativeLayout = findViewById(R.id.url_relativelayout);
+        EditText urlEditText = findViewById(R.id.url_edittext);
+
+        // Get the WebView tab fragment.
+        WebViewTabFragment webViewTabFragment = webViewPagerAdapter.getPageFragment(pageNumber);
+
+        // Get the fragment view.
+        View fragmentView = webViewTabFragment.getView();
+
+        // Remove the incorrect lint warning below that the fragment view might be null.
+        assert fragmentView != null;
+
+        // Store the current WebView.
+        currentWebView = fragmentView.findViewById(R.id.nestedscroll_webview);
+
+        // Update the privacy icons.  `true` redraws the icons in the app bar.
+        updatePrivacyIcons(true);
+
+        // Store the current formatted URL string.
+        formattedUrlString = currentWebView.getUrl();
+
+        // Clear the focus from the URL text box.
+        urlEditText.clearFocus();
+
+        // Hide the soft keyboard.
+        inputMethodManager.hideSoftInputFromWindow(currentWebView.getWindowToken(), 0);
+
+        // Display the current URL in the URL text box.
+        urlEditText.setText(formattedUrlString);
 
-        if (newTabNumber > 0) {
-            // Move to the new tab.
-            newTab.select();
+        // Highlight the URL text.
+        highlightUrlText();
+
+        // Set the background to indicate the domain settings status.
+        if (currentWebView.getDomainSettingsApplied()) {
+            // Set a green background on the URL relative layout to indicate that custom domain settings are being used. The deprecated `.getDrawable()` must be used until the minimum API >= 21.
+            if (darkTheme) {
+                urlRelativeLayout.setBackground(getResources().getDrawable(R.drawable.url_bar_background_dark_blue));
+            } else {
+                urlRelativeLayout.setBackground(getResources().getDrawable(R.drawable.url_bar_background_light_green));
+            }
+        } else {
+            urlRelativeLayout.setBackground(getResources().getDrawable(R.color.transparent));
         }
     }
 
@@ -4298,6 +4257,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         // Get the relevant preferences.
         boolean downloadWithExternalApp = sharedPreferences.getBoolean("download_with_external_app", false);
 
+        // Initialize the favorite icon.
+        nestedScrollWebView.initializeFavoriteIcon();
+
         // Set the app bar scrolling.
         nestedScrollWebView.setNestedScrollingEnabled(sharedPreferences.getBoolean("scroll_app_bar", true));
 
@@ -4517,8 +4479,8 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             public void onReceivedIcon(WebView view, Bitmap icon) {
                 // Only update the favorite icon if the website has finished loading.
                 if (progressBar.getVisibility() == View.GONE) {
-                    // Save a copy of the favorite icon.
-                    favoriteIconBitmap = icon;
+                    // Store the new favorite icon.
+                    nestedScrollWebView.setFavoriteOrDefaultIcon(icon);
 
                     // Get the current page position.
                     int currentPosition = webViewPagerAdapter.getPositionForId(nestedScrollWebView.getWebViewFragmentId());
@@ -4552,25 +4514,28 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 // Get the current tab.
                 TabLayout.Tab tab = tabLayout.getTabAt(currentPosition);
 
-                // Remove the lint warning below that the current tab might be null.
-                assert tab != null;
-
-                // Get the custom view from the tab.
-                View tabView = tab.getCustomView();
+                // Only populate the title text view if the tab has been fully created.
+                if (tab != null) {
+                    // Get the custom view from the tab.
+                    View tabView = tab.getCustomView();
 
-                // Remove the incorrect warning below that the current tab view might be null.
-                assert tabView != null;
+                    // Remove the incorrect warning below that the current tab view might be null.
+                    assert tabView != null;
 
-                // Get the title text view from the tab.
-                TextView tabTitleTextView = tabView.findViewById(R.id.title_textview);
+                    // Get the title text view from the tab.
+                    TextView tabTitleTextView = tabView.findViewById(R.id.title_textview);
 
-                // Set the title as the tab text.
-                tabTitleTextView.setText(title);
+                    // Set the title as the tab text.
+                    tabTitleTextView.setText(title);
+                }
             }
 
             // Enter full screen video.
             @Override
             public void onShowCustomView(View video, CustomViewCallback callback) {
+                // Get a handle for the full screen video frame layout.
+                FrameLayout fullScreenVideoFrameLayout = findViewById(R.id.full_screen_video_framelayout);
+
                 // Set the full screen video flag.
                 displayingFullScreenVideo = true;
 
@@ -4614,6 +4579,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             // Exit full screen video.
             @Override
             public void onHideCustomView() {
+                // Get a handle for the full screen video frame layout.
+                FrameLayout fullScreenVideoFrameLayout = findViewById(R.id.full_screen_video_framelayout);
+
                 // Unset the full screen video flag.
                 displayingFullScreenVideo = false;
 
@@ -4768,6 +4736,15 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             @SuppressWarnings("deprecation")
             @Override
             public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
+                // Get a handle for the navigation view.
+                NavigationView navigationView = findViewById(R.id.navigationview);
+
+                // Get a handle for the navigation menu.
+                Menu navigationMenu = navigationView.getMenu();
+
+                // Get a handle for the navigation requests menu item.  The menu is 0 based.
+                MenuItem navigationRequestsMenuItem = navigationMenu.getItem(6);
+
                 // 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()));
 
@@ -4819,13 +4796,13 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 boolean webViewDisplayed = (webViewPagePosition == tabLayout.getSelectedTabPosition());
 
                 // Block third-party requests if enabled.
-                if (isThirdPartyRequest && blockAllThirdPartyRequests) {
+                if (isThirdPartyRequest && nestedScrollWebView.isBlocklistEnabled(NestedScrollWebView.THIRD_PARTY_REQUESTS)) {
                     // Add the result to the resource requests.
                     nestedScrollWebView.addResourceRequest(new String[]{BlockListHelper.REQUEST_THIRD_PARTY, url});
 
                     // Increment the blocked requests counters.
                     nestedScrollWebView.incrementRequestsCount(NestedScrollWebView.BLOCKED_REQUESTS);
-                    nestedScrollWebView.incrementRequestsCount(NestedScrollWebView.THIRD_PARTY_BLOCKED_REQUESTS);
+                    nestedScrollWebView.incrementRequestsCount(NestedScrollWebView.THIRD_PARTY_REQUESTS);
 
                     // Update the titles of the blocklist menu items if the WebView is currently displayed.
                     if (webViewDisplayed) {
@@ -4834,7 +4811,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                             // Update the menu item titles.
                             navigationRequestsMenuItem.setTitle(getString(R.string.requests) + " - " + nestedScrollWebView.getRequestsCount(NestedScrollWebView.BLOCKED_REQUESTS));
                             blocklistsMenuItem.setTitle(getString(R.string.blocklists) + " - " + nestedScrollWebView.getRequestsCount(NestedScrollWebView.BLOCKED_REQUESTS));
-                            blockAllThirdPartyRequestsMenuItem.setTitle(nestedScrollWebView.getRequestsCount(NestedScrollWebView.THIRD_PARTY_BLOCKED_REQUESTS) + " - " +
+                            blockAllThirdPartyRequestsMenuItem.setTitle(nestedScrollWebView.getRequestsCount(NestedScrollWebView.THIRD_PARTY_REQUESTS) + " - " +
                                     getString(R.string.block_all_third_party_requests));
                         });
                     }
@@ -4844,7 +4821,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 }
 
                 // Check UltraPrivacy if it is enabled.
-                if (ultraPrivacyEnabled) {
+                if (nestedScrollWebView.isBlocklistEnabled(NestedScrollWebView.ULTRA_PRIVACY)) {
                     // Check the URL against UltraPrivacy.
                     String[] ultraPrivacyResults = blockListHelper.checkBlocklist(currentDomain, url, isThirdPartyRequest, ultraPrivacy);
 
@@ -4856,7 +4833,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
                         // Increment the blocked requests counters.
                         nestedScrollWebView.incrementRequestsCount(NestedScrollWebView.BLOCKED_REQUESTS);
-                        nestedScrollWebView.incrementRequestsCount(NestedScrollWebView.ULTRA_PRIVACY_BLOCKED_REQUESTS);
+                        nestedScrollWebView.incrementRequestsCount(NestedScrollWebView.ULTRA_PRIVACY);
 
                         // Update the titles of the blocklist menu items if the WebView is currently displayed.
                         if (webViewDisplayed) {
@@ -4865,7 +4842,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                                 // Update the menu item titles.
                                 navigationRequestsMenuItem.setTitle(getString(R.string.requests) + " - " + nestedScrollWebView.getRequestsCount(NestedScrollWebView.BLOCKED_REQUESTS));
                                 blocklistsMenuItem.setTitle(getString(R.string.blocklists) + " - " + nestedScrollWebView.getRequestsCount(NestedScrollWebView.BLOCKED_REQUESTS));
-                                ultraPrivacyMenuItem.setTitle(nestedScrollWebView.getRequestsCount(NestedScrollWebView.ULTRA_PRIVACY_BLOCKED_REQUESTS) + " - " + getString(R.string.ultraprivacy));
+                                ultraPrivacyMenuItem.setTitle(nestedScrollWebView.getRequestsCount(NestedScrollWebView.ULTRA_PRIVACY) + " - " + getString(R.string.ultraprivacy));
                             });
                         }
 
@@ -4882,7 +4859,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 }
 
                 // Check EasyList if it is enabled.
-                if (easyListEnabled) {
+                if (nestedScrollWebView.isBlocklistEnabled(NestedScrollWebView.EASY_LIST)) {
                     // Check the URL against EasyList.
                     String[] easyListResults = blockListHelper.checkBlocklist(currentDomain, url, isThirdPartyRequest, easyList);
 
@@ -4893,7 +4870,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
                         // Increment the blocked requests counters.
                         nestedScrollWebView.incrementRequestsCount(NestedScrollWebView.BLOCKED_REQUESTS);
-                        nestedScrollWebView.incrementRequestsCount(NestedScrollWebView.EASY_LIST_BLOCKED_REQUESTS);
+                        nestedScrollWebView.incrementRequestsCount(NestedScrollWebView.EASY_LIST);
 
                         // Update the titles of the blocklist menu items if the WebView is currently displayed.
                         if (webViewDisplayed) {
@@ -4902,7 +4879,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                                 // Update the menu item titles.
                                 navigationRequestsMenuItem.setTitle(getString(R.string.requests) + " - " + nestedScrollWebView.getRequestsCount(NestedScrollWebView.BLOCKED_REQUESTS));
                                 blocklistsMenuItem.setTitle(getString(R.string.blocklists) + " - " + nestedScrollWebView.getRequestsCount(NestedScrollWebView.BLOCKED_REQUESTS));
-                                easyListMenuItem.setTitle(nestedScrollWebView.getRequestsCount(NestedScrollWebView.EASY_LIST_BLOCKED_REQUESTS) + " - " + getString(R.string.easylist));
+                                easyListMenuItem.setTitle(nestedScrollWebView.getRequestsCount(NestedScrollWebView.EASY_LIST) + " - " + getString(R.string.easylist));
                             });
                         }
 
@@ -4915,19 +4892,19 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 }
 
                 // Check EasyPrivacy if it is enabled.
-                if (easyPrivacyEnabled) {
+                if (nestedScrollWebView.isBlocklistEnabled(NestedScrollWebView.EASY_PRIVACY)) {
                     // Check the URL against EasyPrivacy.
                     String[] easyPrivacyResults = blockListHelper.checkBlocklist(currentDomain, url, isThirdPartyRequest, easyPrivacy);
 
                     // Process the EasyPrivacy results.
                     if (easyPrivacyResults[0].equals(BlockListHelper.REQUEST_BLOCKED)) {  // The resource request matched EasyPrivacy's blacklist.
                         // Add the result to the resource requests.
-                        nestedScrollWebView.addResourceRequest(new String[] {easyPrivacyResults[0], easyPrivacyResults[1], easyPrivacyResults[2], easyPrivacyResults[3], easyPrivacyResults[5],
+                        nestedScrollWebView.addResourceRequest(new String[] {easyPrivacyResults[0], easyPrivacyResults[1], easyPrivacyResults[2], easyPrivacyResults[3], easyPrivacyResults[4],
                                 easyPrivacyResults[5]});
 
                         // Increment the blocked requests counters.
                         nestedScrollWebView.incrementRequestsCount(NestedScrollWebView.BLOCKED_REQUESTS);
-                        nestedScrollWebView.incrementRequestsCount(NestedScrollWebView.EASY_PRIVACY_BLOCKED_REQUESTS);
+                        nestedScrollWebView.incrementRequestsCount(NestedScrollWebView.EASY_PRIVACY);
 
                         // Update the titles of the blocklist menu items if the WebView is currently displayed.
                         if (webViewDisplayed) {
@@ -4936,7 +4913,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                                 // Update the menu item titles.
                                 navigationRequestsMenuItem.setTitle(getString(R.string.requests) + " - " + nestedScrollWebView.getRequestsCount(NestedScrollWebView.BLOCKED_REQUESTS));
                                 blocklistsMenuItem.setTitle(getString(R.string.blocklists) + " - " + nestedScrollWebView.getRequestsCount(NestedScrollWebView.BLOCKED_REQUESTS));
-                                easyPrivacyMenuItem.setTitle(nestedScrollWebView.getRequestsCount(NestedScrollWebView.EASY_PRIVACY_BLOCKED_REQUESTS) + " - " + getString(R.string.easyprivacy));
+                                easyPrivacyMenuItem.setTitle(nestedScrollWebView.getRequestsCount(NestedScrollWebView.EASY_PRIVACY) + " - " + getString(R.string.easyprivacy));
                             });
                         }
 
@@ -4949,7 +4926,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 }
 
                 // Check Fanboy’s Annoyance List if it is enabled.
-                if (fanboysAnnoyanceListEnabled) {
+                if (nestedScrollWebView.isBlocklistEnabled(NestedScrollWebView.FANBOYS_ANNOYANCE_LIST)) {
                     // Check the URL against Fanboy's Annoyance List.
                     String[] fanboysAnnoyanceListResults = blockListHelper.checkBlocklist(currentDomain, url, isThirdPartyRequest, fanboysAnnoyanceList);
 
@@ -4961,7 +4938,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
                         // Increment the blocked requests counters.
                         nestedScrollWebView.incrementRequestsCount(NestedScrollWebView.BLOCKED_REQUESTS);
-                        nestedScrollWebView.incrementRequestsCount(NestedScrollWebView.FANBOYS_ANNOYANCE_LIST_BLOCKED_REQUESTS);
+                        nestedScrollWebView.incrementRequestsCount(NestedScrollWebView.FANBOYS_ANNOYANCE_LIST);
 
                         // Update the titles of the blocklist menu items if the WebView is currently displayed.
                         if (webViewDisplayed) {
@@ -4970,7 +4947,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                                 // Update the menu item titles.
                                 navigationRequestsMenuItem.setTitle(getString(R.string.requests) + " - " + nestedScrollWebView.getRequestsCount(NestedScrollWebView.BLOCKED_REQUESTS));
                                 blocklistsMenuItem.setTitle(getString(R.string.blocklists) + " - " + nestedScrollWebView.getRequestsCount(NestedScrollWebView.BLOCKED_REQUESTS));
-                                fanboysAnnoyanceListMenuItem.setTitle(nestedScrollWebView.getRequestsCount(NestedScrollWebView.FANBOYS_ANNOYANCE_LIST_BLOCKED_REQUESTS) + " - " +
+                                fanboysAnnoyanceListMenuItem.setTitle(nestedScrollWebView.getRequestsCount(NestedScrollWebView.FANBOYS_ANNOYANCE_LIST) + " - " +
                                         getString(R.string.fanboys_annoyance_list));
                             });
                         }
@@ -4982,7 +4959,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                         whitelistResultStringArray = new String[] {fanboysAnnoyanceListResults[0], fanboysAnnoyanceListResults[1], fanboysAnnoyanceListResults[2], fanboysAnnoyanceListResults[3],
                                 fanboysAnnoyanceListResults[4], fanboysAnnoyanceListResults[5]};
                     }
-                } else if (fanboysSocialBlockingListEnabled) {  // Only check Fanboy’s Social Blocking List if Fanboy’s Annoyance List is disabled.
+                } else if (nestedScrollWebView.isBlocklistEnabled(NestedScrollWebView.FANBOYS_SOCIAL_BLOCKING_LIST)) {  // Only check Fanboy’s Social Blocking List if Fanboy’s Annoyance List is disabled.
                     // Check the URL against Fanboy's Annoyance List.
                     String[] fanboysSocialListResults = blockListHelper.checkBlocklist(currentDomain, url, isThirdPartyRequest, fanboysSocialList);
 
@@ -4994,7 +4971,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
                         // Increment the blocked requests counters.
                         nestedScrollWebView.incrementRequestsCount(NestedScrollWebView.BLOCKED_REQUESTS);
-                        nestedScrollWebView.incrementRequestsCount(NestedScrollWebView.FANBOYS_SOCIAL_BLOCKING_LIST_BLOCKED_REQUESTS);
+                        nestedScrollWebView.incrementRequestsCount(NestedScrollWebView.FANBOYS_SOCIAL_BLOCKING_LIST);
 
                         // Update the titles of the blocklist menu items if the WebView is currently displayed.
                         if (webViewDisplayed) {
@@ -5003,7 +4980,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                                 // Update the menu item titles.
                                 navigationRequestsMenuItem.setTitle(getString(R.string.requests) + " - " + nestedScrollWebView.getRequestsCount(NestedScrollWebView.BLOCKED_REQUESTS));
                                 blocklistsMenuItem.setTitle(getString(R.string.blocklists) + " - " + nestedScrollWebView.getRequestsCount(NestedScrollWebView.BLOCKED_REQUESTS));
-                                fanboysSocialBlockingListMenuItem.setTitle(nestedScrollWebView.getRequestsCount(NestedScrollWebView.FANBOYS_SOCIAL_BLOCKING_LIST_BLOCKED_REQUESTS) + " - " +
+                                fanboysSocialBlockingListMenuItem.setTitle(nestedScrollWebView.getRequestsCount(NestedScrollWebView.FANBOYS_SOCIAL_BLOCKING_LIST) + " - " +
                                         getString(R.string.fanboys_social_blocking_list));
                             });
                         }
@@ -5044,14 +5021,8 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 // Reset the list of resource requests.
                 nestedScrollWebView.clearResourceRequests();
 
-                // Initialize the counters for requests blocked by each blocklist.
-                nestedScrollWebView.resetRequestsCount(NestedScrollWebView.BLOCKED_REQUESTS);
-                nestedScrollWebView.resetRequestsCount(NestedScrollWebView.EASY_LIST_BLOCKED_REQUESTS);
-                nestedScrollWebView.resetRequestsCount(NestedScrollWebView.EASY_PRIVACY_BLOCKED_REQUESTS);
-                nestedScrollWebView.resetRequestsCount(NestedScrollWebView.FANBOYS_ANNOYANCE_LIST_BLOCKED_REQUESTS);
-                nestedScrollWebView.resetRequestsCount(NestedScrollWebView.FANBOYS_SOCIAL_BLOCKING_LIST_BLOCKED_REQUESTS);
-                nestedScrollWebView.resetRequestsCount(NestedScrollWebView.ULTRA_PRIVACY_BLOCKED_REQUESTS);
-                nestedScrollWebView.resetRequestsCount(NestedScrollWebView.THIRD_PARTY_BLOCKED_REQUESTS);
+                // Reset the requests counters.
+                nestedScrollWebView.resetRequestsCounters();
 
                 // If night mode is enabled, hide `mainWebView` until after the night mode CSS is applied.
                 if (nightMode) {
@@ -5123,7 +5094,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
                 // Flush any cookies to persistent storage.  `CookieManager` has become very lazy about flushing cookies in recent versions.
                 if (firstPartyCookiesEnabled && Build.VERSION.SDK_INT >= 21) {
-                    cookieManager.flush();
+                    CookieManager.getInstance().flush();
                 }
 
                 // Update the Refresh menu item if it has been created.
@@ -5153,11 +5124,11 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                     // Manually delete cache folders.
                     try {
                         // Delete the main cache directory.
-                        privacyBrowserRuntime.exec("rm -rf " + privateDataDirectoryString + "/cache");
+                        Runtime.getRuntime().exec("rm -rf " + privateDataDirectoryString + "/cache");
 
                         // Delete the secondary `Service Worker` cache directory.
                         // A `String[]` must be used because the directory contains a space and `Runtime.exec` will not escape the string correctly otherwise.
-                        privacyBrowserRuntime.exec(new String[]{"rm", "-rf", privateDataDirectoryString + "/app_webview/Service Worker/"});
+                        Runtime.getRuntime().exec(new String[]{"rm", "-rf", privateDataDirectoryString + "/app_webview/Service Worker/"});
                     } catch (IOException e) {
                         // Do nothing if an error is thrown.
                     }