]> gitweb.stoutner.com Git - PrivacyBrowserAndroid.git/blobdiff - app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java
Make first-party cookies tab aware.
[PrivacyBrowserAndroid.git] / app / src / main / java / com / stoutner / privacybrowser / activities / MainWebViewActivity.java
index c0f2b824ffd31f99de096b907f9cc3ea75941e12..2be23411215e66acec896f251ef7cdefbcfe29f1 100644 (file)
@@ -154,7 +154,9 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-// TODO.  The swipe refresh indicator needs to be enabled/disabled when switching tabs.
+// TODO.  Store up reloads for tabs that are not visible.
+// TODO.  New tabs are white in dark mode.
+// TODO.  Hide the tabs in full screen mode.
 
 // AppCompatActivity from android.support.v7.app.AppCompatActivity must be used to have access to the SupportActionBar until the minimum API is >= 21.
 public class MainWebViewActivity extends AppCompatActivity implements CreateBookmarkDialog.CreateBookmarkListener, CreateBookmarkFolderDialog.CreateBookmarkFolderListener,
@@ -162,33 +164,23 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         EditBookmarkFolderDialog.EditBookmarkFolderListener, HttpAuthenticationDialog.HttpAuthenticationListener, NavigationView.OnNavigationItemSelectedListener, WebViewTabFragment.NewTabListener,
         PinnedMismatchDialog.PinnedMismatchListener, SslCertificateErrorDialog.SslCertificateErrorListener, UrlHistoryDialog.UrlHistoryListener {
 
-    // `darkTheme` is public static so it can be accessed from everywhere.
-    public static boolean darkTheme;
-
-    // `allowScreenshots` is public static so it can be accessed from everywhere.  It is also used in `onCreate()`.
-    public static boolean allowScreenshots;
-
-    // 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()`.
-    public static String formattedUrlString;
-
     // `orbotStatus` is public static so it can be accessed from `OrbotProxyHelper`.  It is also used in `onCreate()`, `onResume()`, and `applyProxyThroughOrbot()`.
     public static String orbotStatus;
 
     // The WebView pager adapter is accessed from `PinnedMismatchDialog`.  It is also used in `onCreate()`, `onResume()`, and `addTab()`.
     public static WebViewPagerAdapter webViewPagerAdapter;
 
-    // `reloadOnRestart` is public static so it can be accessed from `SettingsFragment`.  It is also used in `onRestart()`
+    // `reloadOnRestart` is public static so it can be accessed from `SettingsFragment`.  It is used in `onRestart()`
     public static boolean reloadOnRestart;
 
-    // `reloadUrlOnRestart` is public static so it can be accessed from `SettingsFragment` and `BookmarksActivity`.  It is also used in `onRestart()`.
+    // The load URL on restart variables are public static so they can be accessed from `BookmarksActivity`.  They are used in `onRestart()`.
     public static boolean loadUrlOnRestart;
+    public static String urlToLoadOnRestart;
 
     // `restartFromBookmarksActivity` is public static so it can be accessed from `BookmarksActivity`.  It is also used in `onRestart()`.
     public static boolean restartFromBookmarksActivity;
 
-    // The blocklist versions are public static so they can be accessed from `AboutTabFragment`.  They are also used in `onCreate()`.
+    // The blocklist versions are public static so they can be accessed from `AboutTabFragment`.  They are also used in `onCreate()`.  // TODO.
     public static String easyListVersion;
     public static String easyPrivacyVersion;
     public static String fanboysAnnoyanceVersion;
@@ -219,29 +211,12 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     // `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;
-
-    // `saveFormDataEnabled` is used in `onCreate()`, `onPrepareOptionsMenu()`, `onOptionsItemSelected()`, and `applyDomainSettings()`.  It can be removed once the minimum API >= 26.
-    private boolean saveFormDataEnabled;
-
-    // TODO Move to NestedScrollWebView.
-    // `nightMode` is used in `onCreate()`, `onPrepareOptionsMenu()`, `onOptionsItemSelected()`, and  `applyDomainSettings()`.
-    private boolean nightMode;
-
-    // 'homepage' is used in `onCreate()`, `onNavigationItemSelected()`, and `applyProxyThroughOrbot()`.
-    private String homepage;  // TODO ?
-
-    // `searchURL` is used in `loadURLFromTextBox()` and `applyProxyThroughOrbot()`.
-    private String searchURL;  // TODO ?
+    // The search URL is set in `applyProxyThroughOrbot()` and used in `onCreate()`, `onNewIntent()`, `loadURLFromTextBox()`, and `initializeWebView()`.
+    private String searchURL;
 
-    // The options menu is set in `onCreateOptionsMenu()` and used in `onOptionsItemSelected()` and `updatePrivacyIcons()`.
+    // The options menu is set in `onCreateOptionsMenu()` and used in `onOptionsItemSelected()`, `updatePrivacyIcons()`, and `initializeWebView()`.
     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;  // TODO.  Create it from `optionsMenu`.
-
     // TODO.  This could probably be removed.
     // The blocklist helper is used in `onCreate()` and `WebViewPagerAdapter`.
     private BlockListHelper blockListHelper;
@@ -307,14 +282,8 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     // `privateDataDirectoryString` is used in `onCreate()`, `onOptionsItemSelected()`, and `onNavigationItemSelected()`.
     private String privateDataDirectoryString;  // TODO.
 
-    // `findOnPageEditText` is used in `onCreate()`, `onOptionsItemSelected()`, and `closeFindOnPage()`.
-    private EditText findOnPageEditText;  // TODO.
-
-    // `displayAdditionalAppBarIcons` is used in `onCreate()` and `onCreateOptionsMenu()`.
-    private boolean displayAdditionalAppBarIcons;  // TODO.
-
     // The action bar drawer toggle is initialized in `onCreate()` and used in `onResume()`.
-    private ActionBarDrawerToggle actionBarDrawerToggle;  // TODO.
+    private ActionBarDrawerToggle actionBarDrawerToggle;
 
     // The color spans are used in `onCreate()` and `highlightUrlText()`.
     private ForegroundColorSpan redColorSpan;
@@ -332,18 +301,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     // `httpAuthHandler` is used in `onCreate()`, `onHttpAuthenticationCancel()`, and `onHttpAuthenticationProceed()`.
     private static HttpAuthHandler httpAuthHandler;  // TODO.
 
-    // `inputMethodManager` is used in `onOptionsItemSelected()`, `loadUrlFromTextBox()`, and `closeFindOnPage()`.
-    private InputMethodManager inputMethodManager;  // TODO.
-
     // `bookmarksDatabaseHelper` is used in `onCreate()`, `onDestroy`, `onOptionsItemSelected()`, `onCreateBookmark()`, `onCreateBookmarkFolder()`, `onSaveEditBookmark()`, `onSaveEditBookmarkFolder()`,
     // and `loadBookmarksFolder()`.
-    private BookmarksDatabaseHelper bookmarksDatabaseHelper;  // TODO.
-
-    // `bookmarksListView` is used in `onCreate()`, `onCreateBookmark()`, `onCreateBookmarkFolder()`, and `loadBookmarksFolder()`.
-    private ListView bookmarksListView;  // TODO.
-
-    // `bookmarksTitleTextView` is used in `onCreate()` and `loadBookmarksFolder()`.
-    private TextView bookmarksTitleTextView;  // TODO.
+    private BookmarksDatabaseHelper bookmarksDatabaseHelper;
 
     // `bookmarksCursor` is used in `onDestroy()`, `onOptionsItemSelected()`, `onCreateBookmark()`, `onCreateBookmarkFolder()`, `onSaveEditBookmark()`, `onSaveEditBookmarkFolder()`, and `loadBookmarksFolder()`.
     private Cursor bookmarksCursor;
@@ -365,10 +325,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     // `downloadImageUrl` is used in `onCreateContextMenu()` and `onRequestPermissionResult()`.
     private String downloadImageUrl;
 
-    // The user agent variables are used in `onCreate()` and `applyDomainSettings()`.
-    private ArrayAdapter<CharSequence> userAgentNamesArray;
-    private String[] userAgentDataArray;
-
     // The request codes are used in `onCreate()`, `onCreateContextMenu()`, `onCloseDownloadLocationPermissionDialog()`, `onRequestPermissionResult()`, and `initializeWebView()`.
     private final int DOWNLOAD_FILE_REQUEST_CODE = 1;
     private final int DOWNLOAD_IMAGE_REQUEST_CODE = 2;
@@ -381,8 +337,8 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
 
         // Get the theme and screenshot preferences.
-        darkTheme = sharedPreferences.getBoolean("dark_theme", false);
-        allowScreenshots = sharedPreferences.getBoolean("allow_screenshots", false);
+        boolean darkTheme = sharedPreferences.getBoolean("dark_theme", false);
+        boolean allowScreenshots = sharedPreferences.getBoolean("allow_screenshots", false);
 
         // Disable screenshots if not allowed.
         if (!allowScreenshots) {
@@ -402,12 +358,19 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         // Set the content view.
         setContentView(R.layout.main_framelayout);
 
-        // Get handles for the input method manager and toolbar.
-        inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+        // Get a handle for the input method.
+        InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+
+        // Remove the lint warning below that the input method manager might be null.
+        assert inputMethodManager != null;
+
+        // Get a handle for the toolbar.
         Toolbar toolbar = findViewById(R.id.toolbar);
 
         // Set the action bar.  `SupportActionBar` must be used until the minimum API is >= 21.
         setSupportActionBar(toolbar);
+
+        // Get a handle for the action bar.
         ActionBar actionBar = getSupportActionBar();
 
         // This is needed to get rid of the Android Studio warning that the action bar might be null.
@@ -472,11 +435,43 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
                 // If Privacy Browser is waiting on Orbot, load the website now that Orbot is connected.
                 if (orbotStatus.equals("ON") && waitingForOrbot) {
-                    // Reset `waitingForOrbot`.
+                    // Reset the waiting for Orbot status.
                     waitingForOrbot = false;
 
-                    // Load `formattedUrlString
-                    loadUrl(formattedUrlString);
+                    // Get the intent that started the app.
+                    Intent launchingIntent = getIntent();
+
+                    // Get the information from the intent.
+                    String launchingIntentAction = launchingIntent.getAction();
+                    Uri launchingIntentUriData = launchingIntent.getData();
+
+                    // If the intent action is a web search, perform the search.
+                    if ((launchingIntentAction != null) && launchingIntentAction.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(launchingIntent.getStringExtra(SearchManager.QUERY), "UTF-8");
+                        } catch (UnsupportedEncodingException exception) {
+                            encodedUrlString = "";
+                        }
+
+                        // Load the completed search URL.
+                        loadUrl(searchURL + encodedUrlString);
+                    } else if (launchingIntentUriData != null){  // Check to see if the intent contains a new URL.
+                        // Load the URL from the intent.
+                        loadUrl(launchingIntentUriData.toString());
+                    } else {  // The is no URL in the intent.
+                        // Select the homepage based on the proxy through Orbot status.
+                        if (proxyThroughOrbot) {
+                            // Load the Tor homepage.
+                            loadUrl(sharedPreferences.getString("tor_homepage", getString(R.string.tor_homepage_default_value)));
+                        } else {
+                            // Load the normal homepage.
+                            loadUrl(sharedPreferences.getString("homepage", getString(R.string.homepage_default_value)));
+                        }
+                    }
                 }
             }
         };
@@ -507,12 +502,11 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         TabLayout tabLayout = findViewById(R.id.tablayout);
         SwipeRefreshLayout swipeRefreshLayout = findViewById(R.id.swiperefreshlayout);
         ViewPager webViewPager = findViewById(R.id.webviewpager);
-        bookmarksListView = findViewById(R.id.bookmarks_drawer_listview);
-        bookmarksTitleTextView = findViewById(R.id.bookmarks_title_textview);
+        ListView bookmarksListView = findViewById(R.id.bookmarks_drawer_listview);
         FloatingActionButton launchBookmarksActivityFab = findViewById(R.id.launch_bookmarks_activity_fab);
         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);
+        EditText findOnPageEditText = findViewById(R.id.find_on_page_edittext);
 
         // Listen for touches on the navigation menu.
         navigationView.setNavigationItemSelectedListener(this);
@@ -581,7 +575,7 @@ 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(), currentWebView.getFavoriteOrDefaultIcon());
+                DialogFragment viewSslCertificateDialogFragment = ViewSslCertificateDialog.displayDialog(currentWebView.getWebViewFragmentId());
 
                 // Display the View SSL Certificate dialog.
                 viewSslCertificateDialogFragment.show(getSupportFragmentManager(), getString(R.string.view_ssl_certificate));
@@ -607,10 +601,6 @@ 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.  // TODO.
-            BookmarksActivity.currentWebViewUrl = currentWebView.getUrl();
-            BookmarksActivity.currentWebViewTitle = currentWebView.getTitle();
-
             // Get a copy of the favorite icon bitmap.
             Bitmap favoriteIconBitmap = currentWebView.getFavoriteOrDefaultIcon();
 
@@ -627,6 +617,8 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             Intent bookmarksIntent = new Intent(getApplicationContext(), BookmarksActivity.class);
 
             // Add the extra information to the intent.
+            bookmarksIntent.putExtra("current_url", currentWebView.getUrl());
+            bookmarksIntent.putExtra("current_title", currentWebView.getTitle());
             bookmarksIntent.putExtra("current_folder", currentBookmarksFolder);
             bookmarksIntent.putExtra("favorite_icon_byte_array", favoriteIconByteArray);
 
@@ -839,11 +831,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         // Initialize `inFullScreenBrowsingMode`, which is always false at this point because Privacy Browser never starts in full screen browsing mode.
         inFullScreenBrowsingMode = false;
 
-        // Initialize the privacy settings variables.
-        firstPartyCookiesEnabled = false;
-        saveFormDataEnabled = false;  // Form data can be removed once the minimum API >= 26.
-        nightMode = false;
-
         // Inflate a bare WebView to get the default user agent.  It is not used to render content on the screen.
         @SuppressLint("InflateParams") View webViewLayout = getLayoutInflater().inflate(R.layout.bare_webview, null, false);
 
@@ -855,36 +842,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
         // Destroy the bare WebView.
         bareWebView.destroy();
-
-        // 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);
-
-        // Get the intent that started the app.
-        Intent launchingIntent = getIntent();
-
-        // Get the information from the intent.
-        String launchingIntentAction = launchingIntent.getAction();
-        Uri launchingIntentUriData = launchingIntent.getData();
-
-        // If the intent action is a web search, perform the search.
-        if ((launchingIntentAction != null) && launchingIntentAction.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(launchingIntent.getStringExtra(SearchManager.QUERY), "UTF-8");
-            } catch (UnsupportedEncodingException exception) {
-                encodedUrlString = "";
-            }
-
-            // Add the base search URL.
-            formattedUrlString = searchURL + encodedUrlString;
-        } else if (launchingIntentUriData != null){  // Check to see if the intent contains a new URL.
-            // Set the formatted URL string.
-            formattedUrlString = launchingIntentUriData.toString();
-        }
     }
 
     @Override
@@ -901,6 +858,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             // Add a new tab.
             addTab(null);
 
+            // Create a URL string.
+            String url;
+
             // 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.
@@ -914,14 +874,14 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 }
 
                 // Add the base search URL.
-                formattedUrlString = searchURL + encodedUrlString;
+                url = searchURL + encodedUrlString;
             } else {  // The intent should contain a URL.
-                // Set the formatted URL string.
-                formattedUrlString = intentUriData.toString();
+                // Set the intent data as the URL.
+                url = intentUriData.toString();
             }
 
             // Load the URL.
-            loadUrl(formattedUrlString);
+            loadUrl(url);
 
             // Get a handle for the drawer layout.
             DrawerLayout drawerLayout = findViewById(R.id.drawerlayout);
@@ -963,7 +923,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             // Apply the app settings.
             applyAppSettings();
 
-            // Reload the webpage if displaying of images has been disabled in the Settings activity.
+            // Reload the webpage to handle changes to night mode and displaying of images.
             if (reloadOnRestart) {
                 // Reload the WebViews.
                 for (int i = 0; i < webViewPagerAdapter.getCount(); i++) {
@@ -994,19 +954,22 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         // TODO apply to all the tabs.
         // Apply the domain settings if returning from the Domains activity.
         if (reapplyDomainSettingsOnRestart) {
+            // Reset the current domain name so the domain settings will be reapplied.
+            currentWebView.resetCurrentDomainName();
+
             // Reapply the domain settings.
-            applyDomainSettings(currentWebView, formattedUrlString, false, true);
+            applyDomainSettings(currentWebView, currentWebView.getUrl(), false, true);  // TODO.
 
-            // Reset `reapplyDomainSettingsOnRestart`.
+            // Reset the reapply domain settings on restart tracker.
             reapplyDomainSettingsOnRestart = false;
         }
 
-        // Load the URL on restart to apply changes to night mode.
+        // Load the URL on restart (used when loading a bookmark.
         if (loadUrlOnRestart) {
-            // Load the current `formattedUrlString`.
-            loadUrl(formattedUrlString);
+            // Load the specified URL.
+            loadUrl(urlToLoadOnRestart);
 
-            // Reset `loadUrlOnRestart.
+            // Reset the load on restart tracker.
             loadUrlOnRestart = false;
         }
 
@@ -1135,7 +1098,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         // Inflate the menu.  This adds items to the action bar if it is present.
         getMenuInflater().inflate(R.menu.webview_options_menu, menu);
 
-        // Store a handle for the options menu so it can be used by `onOptionsItemSelected()` and `updatePrivacyIcons`.
+        // Store a handle for the options menu so it can be used by `onOptionsItemSelected()` and `updatePrivacyIcons()`.
         optionsMenu = menu;
 
         // Set the initial status of the privacy icons.  `false` does not call `invalidateOptionsMenu` as the last step.
@@ -1147,7 +1110,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         MenuItem toggleDomStorageMenuItem = menu.findItem(R.id.toggle_dom_storage);
         MenuItem toggleSaveFormDataMenuItem = menu.findItem(R.id.toggle_save_form_data);  // Form data can be removed once the minimum API >= 26.
         MenuItem clearFormDataMenuItem = menu.findItem(R.id.clear_form_data);  // Form data can be removed once the minimum API >= 26.
-        refreshMenuItem = menu.findItem(R.id.refresh);
+        MenuItem refreshMenuItem = menu.findItem(R.id.refresh);
         blocklistsMenuItem = menu.findItem(R.id.blocklists);
         easyListMenuItem = menu.findItem(R.id.easylist);
         easyPrivacyMenuItem = menu.findItem(R.id.easyprivacy);
@@ -1164,14 +1127,18 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         toggleSaveFormDataMenuItem.setVisible(Build.VERSION.SDK_INT < 26);
         clearFormDataMenuItem.setVisible(Build.VERSION.SDK_INT < 26);
 
+        // Disable the clear form data menu item if the API >= 26 so that the status of the main Clear Data is calculated correctly.
+        clearFormDataMenuItem.setEnabled(Build.VERSION.SDK_INT < 26);
+
         // Only show Ad Consent if this is the free flavor.
         adConsentMenuItem.setVisible(BuildConfig.FLAVOR.contentEquals("free"));
 
         // Get the shared preference values.
         SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
 
-        // Get the status of the additional AppBar icons.
-        displayAdditionalAppBarIcons = sharedPreferences.getBoolean("display_additional_app_bar_icons", false);
+        // Get the dark theme and app bar preferences..
+        boolean displayAdditionalAppBarIcons = sharedPreferences.getBoolean("display_additional_app_bar_icons", false);
+        boolean darkTheme = sharedPreferences.getBoolean("dark_theme", false);
 
         // Set the status of the additional app bar icons.  Setting the refresh menu item to `SHOW_AS_ACTION_ALWAYS` makes it appear even on small devices like phones.
         if (displayAdditionalAppBarIcons) {
@@ -1204,15 +1171,12 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
     @Override
     public boolean onPrepareOptionsMenu(Menu menu) {
-        // Get a handle for the swipe refresh layout.
-        SwipeRefreshLayout swipeRefreshLayout = findViewById(R.id.swiperefreshlayout);
-
         // Get handles for the menu items.
         MenuItem addOrEditDomain = menu.findItem(R.id.add_or_edit_domain);
-        MenuItem toggleFirstPartyCookiesMenuItem = menu.findItem(R.id.toggle_first_party_cookies);
-        MenuItem toggleThirdPartyCookiesMenuItem = menu.findItem(R.id.toggle_third_party_cookies);
-        MenuItem toggleDomStorageMenuItem = menu.findItem(R.id.toggle_dom_storage);
-        MenuItem toggleSaveFormDataMenuItem = menu.findItem(R.id.toggle_save_form_data);  // Form data can be removed once the minimum API >= 26.
+        MenuItem firstPartyCookiesMenuItem = menu.findItem(R.id.toggle_first_party_cookies);
+        MenuItem thirdPartyCookiesMenuItem = menu.findItem(R.id.toggle_third_party_cookies);
+        MenuItem domStorageMenuItem = menu.findItem(R.id.toggle_dom_storage);
+        MenuItem saveFormDataMenuItem = menu.findItem(R.id.toggle_save_form_data);  // Form data can be removed once the minimum API >= 26.
         MenuItem clearDataMenuItem = menu.findItem(R.id.clear_data);
         MenuItem clearCookiesMenuItem = menu.findItem(R.id.clear_cookies);
         MenuItem clearDOMStorageMenuItem = menu.findItem(R.id.clear_dom_storage);
@@ -1246,14 +1210,17 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             fontSize = currentWebView.getSettings().getTextZoom();
 
             // Set the status of the menu item checkboxes.
-            toggleDomStorageMenuItem.setChecked(currentWebView.getSettings().getDomStorageEnabled());
+            domStorageMenuItem.setChecked(currentWebView.getSettings().getDomStorageEnabled());
+            saveFormDataMenuItem.setChecked(currentWebView.getSettings().getSaveFormData());  // Form data can be removed once the minimum API >= 26.
             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));
+            swipeToRefreshMenuItem.setChecked(currentWebView.getSwipeToRefresh());
             displayImagesMenuItem.setChecked(currentWebView.getSettings().getLoadsImagesAutomatically());
+            nightModeMenuItem.setChecked(currentWebView.getNightMode());
 
             // Initialize the display names for the blocklists with the number of blocked requests.
             blocklistsMenuItem.setTitle(getString(R.string.blocklists) + " - " + currentWebView.getRequestsCount(NestedScrollWebView.BLOCKED_REQUESTS));
@@ -1263,26 +1230,23 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             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);
-        toggleSaveFormDataMenuItem.setChecked(saveFormDataEnabled);  // Form data can be removed once the minimum API >= 26.
-        swipeToRefreshMenuItem.setChecked(swipeRefreshLayout.isEnabled());
-        nightModeMenuItem.setChecked(nightMode);
-        proxyThroughOrbotMenuItem.setChecked(proxyThroughOrbot);
+            // Only modify third-party cookies if the API >= 21.
+            if (Build.VERSION.SDK_INT >= 21) {
+                // Set the status of the third-party cookies checkbox.
+                thirdPartyCookiesMenuItem.setChecked(cookieManager.acceptThirdPartyCookies(currentWebView));
 
-        // 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.
+                thirdPartyCookiesMenuItem.setEnabled(cookieManager.acceptCookie());
+            }
 
-            // Enable third-party cookies if first-party cookies are enabled.
-            toggleThirdPartyCookiesMenuItem.setEnabled(firstPartyCookiesEnabled);
+            // Enable DOM Storage if JavaScript is enabled.
+            domStorageMenuItem.setEnabled(currentWebView.getSettings().getJavaScriptEnabled());
         }
 
-        // Enable DOM Storage if JavaScript is enabled.
-        toggleDomStorageMenuItem.setEnabled(currentWebView.getSettings().getJavaScriptEnabled());
+        // Set the status of the menu item checkboxes.
+        firstPartyCookiesMenuItem.setChecked(cookieManager.acceptCookie());
+        proxyThroughOrbotMenuItem.setChecked(proxyThroughOrbot);
 
         // Enable Clear Cookies if there are any.
         clearCookiesMenuItem.setEnabled(cookieManager.hasCookies());
@@ -1306,11 +1270,11 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
         // Enable Clear Form Data is there is any.  This can be removed once the minimum API >= 26.
         if (Build.VERSION.SDK_INT < 26) {
-            WebViewDatabase mainWebViewDatabase = WebViewDatabase.getInstance(this);
-            clearFormDataMenuItem.setEnabled(mainWebViewDatabase.hasFormData());
-        } else {
-            // Disable clear form data because it is not supported on current version of Android.
-            clearFormDataMenuItem.setEnabled(false);
+            // Get the WebView database.
+            WebViewDatabase webViewDatabase = WebViewDatabase.getInstance(this);
+
+            // Enable the clear form data menu item if there is anything to clear.
+            clearFormDataMenuItem.setEnabled(webViewDatabase.hasFormData());
         }
 
         // Enable Clear Data if any of the submenu items are enabled.
@@ -1414,8 +1378,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     @Override
     // Remove Android Studio's warning about the dangers of using SetJavaScriptEnabled.
     @SuppressLint("SetJavaScriptEnabled")
-    // removeAllCookies is deprecated, but it is required for API < 21.
-    @SuppressWarnings("deprecation")
     public boolean onOptionsItemSelected(MenuItem menuItem) {
         // Reenter full screen browsing mode if it was interrupted by the options menu.  <https://redmine.stoutner.com/issues/389>
         if (inFullScreenBrowsingMode) {
@@ -1455,7 +1417,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 // Display a `Snackbar`.
                 if (currentWebView.getSettings().getJavaScriptEnabled()) {  // JavaScrip is enabled.
                     Snackbar.make(findViewById(R.id.webviewpager), R.string.javascript_enabled, Snackbar.LENGTH_SHORT).show();
-                } else if (firstPartyCookiesEnabled) {  // JavaScript is disabled, but first-party cookies are enabled.
+                } else if (cookieManager.acceptCookie()) {  // JavaScript is disabled, but first-party cookies are enabled.
                     Snackbar.make(findViewById(R.id.webviewpager), R.string.javascript_disabled, Snackbar.LENGTH_SHORT).show();
                 } else {  // Privacy mode.
                     Snackbar.make(findViewById(R.id.webviewpager), R.string.privacy_mode, Snackbar.LENGTH_SHORT).show();
@@ -1469,7 +1431,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 if (currentWebView.getDomainSettingsApplied()) {  // Edit the current domain settings.
                     // Reapply the domain settings on returning to `MainWebViewActivity`.
                     reapplyDomainSettingsOnRestart = true;
-                    currentWebView.resetCurrentDomainName();
 
                     // TODO.  Move these to `putExtra`.  The certificate can be stored as strings.
                     // Store the current SSL certificate and IP addresses in the domains activity.
@@ -1479,19 +1440,19 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                     // Create an intent to launch the domains activity.
                     Intent domainsIntent = new Intent(this, DomainsActivity.class);
 
-                    // Put extra information instructing the domains activity to directly load the current domain and close on back instead of returning to the domains list.
+                    // Add the extra information to the intent.
                     domainsIntent.putExtra("load_domain", currentWebView.getDomainSettingsDatabaseId());
                     domainsIntent.putExtra("close_on_back", true);
+                    domainsIntent.putExtra("current_url", currentWebView.getUrl());
 
                     // Make it so.
                     startActivity(domainsIntent);
                 } else {  // Add a new domain.
                     // Apply the new domain settings on returning to `MainWebViewActivity`.
                     reapplyDomainSettingsOnRestart = true;
-                    currentWebView.resetCurrentDomainName();
 
                     // Get the current domain
-                    Uri currentUri = Uri.parse(formattedUrlString);
+                    Uri currentUri = Uri.parse(currentWebView.getUrl());
                     String currentDomain = currentUri.getHost();
 
                     // Initialize the database handler.  The `0` specifies the database version, but that is ignored and set instead using a constant in `DomainsDatabaseHelper`.
@@ -1508,9 +1469,10 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                     // Create an intent to launch the domains activity.
                     Intent domainsIntent = new Intent(this, DomainsActivity.class);
 
-                    // Put extra information instructing the domains activity to directly load the new domain and close on back instead of returning to the domains list.
+                    // Add the extra information to the intent.
                     domainsIntent.putExtra("load_domain", newDomainDatabaseId);
                     domainsIntent.putExtra("close_on_back", true);
+                    domainsIntent.putExtra("current_url", currentWebView.getUrl());
 
                     // Make it so.
                     startActivity(domainsIntent);
@@ -1518,20 +1480,20 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 return true;
 
             case R.id.toggle_first_party_cookies:
-                // Switch the status of firstPartyCookiesEnabled.
-                firstPartyCookiesEnabled = !firstPartyCookiesEnabled;
+                // Switch the first-party cookie status.
+                cookieManager.setAcceptCookie(!cookieManager.acceptCookie());
 
-                // Update the menu checkbox.
-                menuItem.setChecked(firstPartyCookiesEnabled);
+                // Store the first-party cookie status.
+                currentWebView.setAcceptFirstPartyCookies(cookieManager.acceptCookie());
 
-                // Apply the new cookie status.
-                cookieManager.setAcceptCookie(firstPartyCookiesEnabled);
+                // Update the menu checkbox.
+                menuItem.setChecked(cookieManager.acceptCookie());
 
                 // Update the privacy icon.  `true` runs `invalidateOptionsMenu` as the last step.
                 updatePrivacyIcons(true);
 
-                // Display a `Snackbar`.
-                if (firstPartyCookiesEnabled) {  // First-party cookies are enabled.
+                // Display a snackbar.
+                if (cookieManager.acceptCookie()) {  // First-party cookies are enabled.
                     Snackbar.make(findViewById(R.id.webviewpager), R.string.first_party_cookies_enabled, Snackbar.LENGTH_SHORT).show();
                 } else if (currentWebView.getSettings().getJavaScriptEnabled()) {  // JavaScript is still enabled.
                     Snackbar.make(findViewById(R.id.webviewpager), R.string.first_party_cookies_disabled, Snackbar.LENGTH_SHORT).show();
@@ -1587,16 +1549,13 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             // Form data can be removed once the minimum API >= 26.
             case R.id.toggle_save_form_data:
                 // Switch the status of saveFormDataEnabled.
-                saveFormDataEnabled = !saveFormDataEnabled;
+                currentWebView.getSettings().setSaveFormData(!currentWebView.getSettings().getSaveFormData());
 
                 // Update the menu checkbox.
-                menuItem.setChecked(saveFormDataEnabled);
-
-                // Apply the new form data status.
-                currentWebView.getSettings().setSaveFormData(saveFormDataEnabled);
+                menuItem.setChecked(currentWebView.getSettings().getSaveFormData());
 
-                // Display a `Snackbar`.
-                if (saveFormDataEnabled) {
+                // Display a snackbar.
+                if (currentWebView.getSettings().getSaveFormData()) {
                     Snackbar.make(findViewById(R.id.webviewpager), R.string.form_data_enabled, Snackbar.LENGTH_SHORT).show();
                 } else {
                     Snackbar.make(findViewById(R.id.webviewpager), R.string.form_data_disabled, Snackbar.LENGTH_SHORT).show();
@@ -1930,11 +1889,25 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 return true;
 
             case R.id.swipe_to_refresh:
+                // Toggle the stored status of swipe to refresh.
+                currentWebView.setSwipeToRefresh(!currentWebView.getSwipeToRefresh());
+
                 // Get a handle for the swipe refresh layout.
                 SwipeRefreshLayout swipeRefreshLayout = findViewById(R.id.swiperefreshlayout);
 
-                // Toggle swipe to refresh.
-                swipeRefreshLayout.setEnabled(!swipeRefreshLayout.isEnabled());
+                // Update the swipe refresh layout.
+                if (currentWebView.getSwipeToRefresh()) {  // Swipe to refresh is enabled.
+                    if (Build.VERSION.SDK_INT >= 23) {  // For API >= 23, the status of the scroll refresh listener is continuously updated by the on scroll change listener.
+                        // Only enable the swipe refresh layout if the WebView is scrolled to the top.
+                        swipeRefreshLayout.setEnabled(currentWebView.getY() == 0);
+                    } else {  // For API < 23, the swipe refresh layout is always enabled.
+                        // Enable the swipe refresh layout.
+                        swipeRefreshLayout.setEnabled(true);
+                    }
+                } else {  // Swipe to refresh is disabled.
+                    // Disable the swipe refresh layout.
+                    swipeRefreshLayout.setEnabled(false);
+                }
                 return true;
 
             case R.id.display_images:
@@ -1952,15 +1925,15 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
             case R.id.night_mode:
                 // Toggle night mode.
-                nightMode = !nightMode;
+                currentWebView.setNightMode(!currentWebView.getNightMode());
 
                 // Enable or disable JavaScript according to night mode, the global preference, and any domain settings.
-                if (nightMode) {  // Night mode is enabled, which requires JavaScript.
+                if (currentWebView.getNightMode()) {  // Night mode is enabled, which requires JavaScript.
                     // Enable JavaScript.
                     currentWebView.getSettings().setJavaScriptEnabled(true);
                 } else if (currentWebView.getDomainSettingsApplied()) {  // Night mode is disabled and domain settings are applied.  Set JavaScript according to the domain settings.
                     // Apply the JavaScript preference that was stored the last time domain settings were loaded.
-                    currentWebView.getSettings().setJavaScriptEnabled(domainSettingsJavaScriptEnabled);
+                    currentWebView.getSettings().setJavaScriptEnabled(domainSettingsJavaScriptEnabled);  // TODO.
                 } else {  // Night mode is disabled and domain settings are not applied.  Set JavaScript according to the global preference.
                     // Apply the JavaScript preference.
                     currentWebView.getSettings().setJavaScriptEnabled(sharedPreferences.getBoolean("javascript", false));
@@ -1977,6 +1950,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 // Get a handle for the views.
                 Toolbar toolbar = findViewById(R.id.toolbar);
                 LinearLayout findOnPageLinearLayout = findViewById(R.id.find_on_page_linearlayout);
+                EditText findOnPageEditText = findViewById(R.id.find_on_page_edittext);
 
                 // Hide the toolbar.
                 toolbar.setVisibility(View.GONE);
@@ -1990,6 +1964,12 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                     // Set the focus on `findOnPageEditText`.
                     findOnPageEditText.requestFocus();
 
+                    // Get a handle for the input method manager.
+                    InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+
+                    // Remove the lint warning below that the input method manager might be null.
+                    assert inputMethodManager != null;
+
                     // Display the keyboard.  `0` sets no input flags.
                     inputMethodManager.showSoftInput(findOnPageEditText, 0);
                 }, 200);
@@ -1999,8 +1979,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 // Create an intent to launch the view source activity.
                 Intent viewSourceIntent = new Intent(this, ViewSourceActivity.class);
 
-                // Add the user agent as an extra to the intent.
+                // Add the variables to the intent.
                 viewSourceIntent.putExtra("user_agent", currentWebView.getSettings().getUserAgentString());
+                viewSourceIntent.putExtra("current_url", currentWebView.getUrl());
 
                 // Make it so.
                 startActivity(viewSourceIntent);
@@ -2008,7 +1989,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
             case R.id.share_url:
                 // Setup the share string.
-                String shareString = currentWebView.getTitle() + " â€“ " + formattedUrlString;
+                String shareString = currentWebView.getTitle() + " â€“ " + currentWebView.getUrl();
 
                 // Create the share intent.
                 Intent shareIntent = new Intent(Intent.ACTION_SEND);
@@ -2020,30 +2001,31 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 return true;
 
             case R.id.print:
-                // Get a `PrintManager` instance.
+                // Get a print manager instance.
                 PrintManager printManager = (PrintManager) getSystemService(Context.PRINT_SERVICE);
 
-                // Create a print document adapter form the current WebView.
-                PrintDocumentAdapter printDocumentAdapter = currentWebView.createPrintDocumentAdapter();
-
-                // Remove the lint error below that `printManager` might be `null`.
+                // Remove the lint error below that print manager might be null.
                 assert printManager != null;
 
-                // Print the document.  The print attributes are `null`.
+                // Create a print document adapter from the current WebView.
+                PrintDocumentAdapter printDocumentAdapter = currentWebView.createPrintDocumentAdapter();
+
+                // Print the document.
                 printManager.print(getString(R.string.privacy_browser_web_page), printDocumentAdapter, null);
                 return true;
 
             case R.id.open_with_app:
-                openWithApp(formattedUrlString);
+                openWithApp(currentWebView.getUrl());
                 return true;
 
             case R.id.open_with_browser:
-                openWithBrowser(formattedUrlString);
+                openWithBrowser(currentWebView.getUrl());
                 return true;
 
             case R.id.add_to_homescreen:
                 // Instantiate the create home screen shortcut dialog.
-                DialogFragment createHomeScreenShortcutDialogFragment = CreateHomeScreenShortcutDialog.createDialog(currentWebView.getTitle(), formattedUrlString, currentWebView.getFavoriteOrDefaultIcon());
+                DialogFragment createHomeScreenShortcutDialogFragment = CreateHomeScreenShortcutDialog.createDialog(currentWebView.getTitle(), currentWebView.getUrl(),
+                        currentWebView.getFavoriteOrDefaultIcon());
 
                 // Show the create home screen shortcut dialog.
                 createHomeScreenShortcutDialogFragment.show(getSupportFragmentManager(), getString(R.string.create_shortcut));
@@ -2086,6 +2068,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         // Get the menu item ID.
         int menuItemId = menuItem.getItemId();
 
+        // Get a handle for the shared preferences.
+        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
+
         // Run the commands that correspond to the selected menu item.
         switch (menuItemId) {
             case R.id.close_tab:
@@ -2110,9 +2095,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 bookmarksCursor.close();
                 bookmarksDatabaseHelper.close();
 
-                // Get a handle for the shared preferences.
-                SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
-
                 // Get the status of the clear everything preference.
                 boolean clearEverything = sharedPreferences.getBoolean("clear_everything", true);
 
@@ -2250,9 +2232,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                     }
                 }
 
-                // Clear the formatted URL string.
-                formattedUrlString = null;
-
                 // Clear the custom headers.
                 customHeaders.clear();
 
@@ -2282,13 +2261,20 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 break;
 
             case R.id.home:
-                loadUrl(homepage);
+                // Select the homepage based on the proxy through Orbot status.
+                if (proxyThroughOrbot) {
+                    // Load the Tor homepage.
+                    loadUrl(sharedPreferences.getString("tor_homepage", getString(R.string.tor_homepage_default_value)));
+                } else {
+                    // Load the normal homepage.
+                    loadUrl(sharedPreferences.getString("homepage", getString(R.string.homepage_default_value)));
+                }
                 break;
 
             case R.id.back:
                 if (currentWebView.canGoBack()) {
-                    // Reset the formatted URL string so the page will load correctly if blocking of third-party requests is enabled.
-                    formattedUrlString = "";
+                    // Reset the current domain name so that navigation works if third-party requests are blocked.
+                    currentWebView.resetCurrentDomainName();
 
                     // Set `navigatingHistory` so that the domain settings are applied when the new URL is loaded.
                     navigatingHistory = true;
@@ -2300,8 +2286,8 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
             case R.id.forward:
                 if (currentWebView.canGoForward()) {
-                    // Reset the formatted URL string so the page will load correctly if blocking of third-party requests is enabled.
-                    formattedUrlString = "";
+                    // Reset the current domain name so that navigation works if third-party requests are blocked.
+                    currentWebView.resetCurrentDomainName();
 
                     // Set `navigatingHistory` so that the domain settings are applied when the new URL is loaded.
                     navigatingHistory = true;
@@ -2347,7 +2333,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             case R.id.domains:
                 // Set the flag to reapply the domain settings on restart when returning from Domain Settings.
                 reapplyDomainSettingsOnRestart = true;
-                currentWebView.resetCurrentDomainName();  // TODO.  Do this for all tabs.
 
                 // TODO.  Move these to `putExtra`.  The certificate can be stored as strings.
                 // Store the current SSL certificate and IP addresses in the domains activity.
@@ -2356,6 +2341,11 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
                 // Launch the domains activity.
                 Intent domainsIntent = new Intent(this, DomainsActivity.class);
+
+                // Add the extra information to the intent.
+                domainsIntent.putExtra("current_url", currentWebView.getUrl());
+
+                // Make it so.
                 startActivity(domainsIntent);
                 break;
 
@@ -2365,7 +2355,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
                 // Set the flag to reapply the domain settings on restart when returning from Settings.
                 reapplyDomainSettingsOnRestart = true;
-                currentWebView.resetCurrentDomainName();  // TODO.  Do this for all tabs.
 
                 // Launch the settings activity.
                 Intent settingsIntent = new Intent(this, SettingsActivity.class);
@@ -2444,20 +2433,21 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
     @Override
     public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
-        // Store the `HitTestResult`.
+        // Store the hit test result.
         final WebView.HitTestResult hitTestResult = currentWebView.getHitTestResult();
 
-        // Create strings.
+        // Create the URL strings.
         final String imageUrl;
         final String linkUrl;
 
-        // Get a handle for the the clipboard and fragment managers.
+        // Get handles for the the clipboard and fragment managers.
         final ClipboardManager clipboardManager = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
         FragmentManager fragmentManager = getSupportFragmentManager();
 
-        // Remove the lint errors below that `clipboardManager` might be `null`.
+        // Remove the lint errors below that the clipboard manager might be null.
         assert clipboardManager != null;
 
+        // Process the link according to the type.
         switch (hitTestResult.getType()) {
             // `SRC_ANCHOR_TYPE` is a link.
             case WebView.HitTestResult.SRC_ANCHOR_TYPE:
@@ -2468,11 +2458,27 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 menu.setHeaderTitle(linkUrl);
 
                 // Add a Load URL entry.
-                menu.add(R.string.load_url).setOnMenuItemClickListener((MenuItem item) -> {
+                menu.add(R.string.open_in_new_tab).setOnMenuItemClickListener((MenuItem item) -> {
+                    // Add a new tab.
+                    addTab(null);
+
+                    // Load the URL.
                     loadUrl(linkUrl);
                     return false;
                 });
 
+                // Add an Open with App entry.
+                menu.add(R.string.open_with_app).setOnMenuItemClickListener((MenuItem item) -> {
+                    openWithApp(linkUrl);
+                    return false;
+                });
+
+                // Add an Open with Browser entry.
+                menu.add(R.string.open_with_browser).setOnMenuItemClickListener((MenuItem item) -> {
+                    openWithBrowser(linkUrl);
+                    return false;
+                });
+
                 // Add a Copy URL entry.
                 menu.add(R.string.copy_url).setOnMenuItemClickListener((MenuItem item) -> {
                     // Save the link URL in a `ClipData`.
@@ -2518,18 +2524,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                     return false;
                 });
 
-                // Add an Open with App entry.
-                menu.add(R.string.open_with_app).setOnMenuItemClickListener((MenuItem item) -> {
-                    openWithApp(linkUrl);
-                    return false;
-                });
-
-                // Add an Open with Browser entry.
-                menu.add(R.string.open_with_browser).setOnMenuItemClickListener((MenuItem item) -> {
-                    openWithBrowser(linkUrl);
-                    return false;
-                });
-
                 // Add a Cancel entry, which by default closes the context menu.
                 menu.add(R.string.cancel);
                 break;
@@ -2722,6 +2716,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
     @Override
     public void onCreateBookmark(DialogFragment dialogFragment, Bitmap favoriteIconBitmap) {
+        // Get a handle for the bookmarks list view.
+        ListView bookmarksListView = findViewById(R.id.bookmarks_drawer_listview);
+
         // 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);
@@ -2757,6 +2754,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
     @Override
     public void onCreateBookmarkFolder(DialogFragment dialogFragment, Bitmap favoriteIconBitmap) {
+        // Get a handle for the bookmarks list view.
+        ListView bookmarksListView = findViewById(R.id.bookmarks_drawer_listview);
+
         // 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);
@@ -2993,11 +2993,14 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             // Parse `imageUrl`.
             DownloadManager.Request downloadRequest = new DownloadManager.Request(Uri.parse(imageUrl));
 
+            // Get a handle for the cookie manager.
+            CookieManager cookieManager = CookieManager.getInstance();
+
             // Pass cookies to download manager if cookies are enabled.  This is required to download images from websites that require a login.
             // Code contributed 2017 Hendrik Knackstedt.  Copyright assigned to Soren Stoutner <soren@stoutner.com>.
-            if (firstPartyCookiesEnabled) {
+            if (cookieManager.acceptCookie()) {
                 // Get the cookies for `imageUrl`.
-                String cookies = CookieManager.getInstance().getCookie(imageUrl);
+                String cookies = cookieManager.getCookie(imageUrl);
 
                 // Add the cookies to `downloadRequest`.  In the HTTP request header, cookies are named `Cookie`.
                 downloadRequest.addRequestHeader("Cookie", cookies);
@@ -3045,11 +3048,14 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             // Parse `downloadUrl`.
             DownloadManager.Request downloadRequest = new DownloadManager.Request(Uri.parse(downloadUrl));
 
+            // Get a handle for the cookie manager.
+            CookieManager cookieManager = CookieManager.getInstance();
+
             // Pass cookies to download manager if cookies are enabled.  This is required to download files from websites that require a login.
             // Code contributed 2017 Hendrik Knackstedt.  Copyright assigned to Soren Stoutner <soren@stoutner.com>.
-            if (firstPartyCookiesEnabled) {
+            if (cookieManager.acceptCookie()) {
                 // Get the cookies for `downloadUrl`.
-                String cookies = CookieManager.getInstance().getCookie(downloadUrl);
+                String cookies = cookieManager.getCookie(downloadUrl);
 
                 // Add the cookies to `downloadRequest`.  In the HTTP request header, cookies are named `Cookie`.
                 downloadRequest.addRequestHeader("Cookie", cookies);
@@ -3116,8 +3122,8 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     @Override
     public void onPinnedMismatchBack() {  // TODO.  Move this logic to the dialog.
         if (currentWebView.canGoBack()) {  // There is a back page in the history.
-            // Reset the formatted URL string so the page will load correctly if blocking of third-party requests is enabled.
-            formattedUrlString = "";  // TODO.
+            // Reset the current domain name so that navigation works if third-party requests are blocked.
+            currentWebView.resetCurrentDomainName();
 
             // Set `navigatingHistory` so that the domain settings are applied when the new URL is loaded.
             navigatingHistory = true;  // TODO.
@@ -3138,8 +3144,8 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
     @Override
     public void onUrlHistoryEntrySelected(int moveBackOrForwardSteps) {
-        // Reset the formatted URL string so the page will load correctly if blocking of third-party requests is enabled.
-        formattedUrlString = "";
+        // Reset the current domain name so that navigation works if third-party requests are blocked.
+        currentWebView.resetCurrentDomainName();
 
         // Set `navigatingHistory` so that the domain settings are applied when the new URL is loaded.
         navigatingHistory = true;
@@ -3154,7 +3160,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         currentWebView.clearHistory();
     }
 
-    // Override `onBackPressed` to handle the navigation drawer and `mainWebView`.
+    // Override `onBackPressed` to handle the navigation drawer and and the WebView.
     @Override
     public void onBackPressed() {
         // Get a handle for the drawer layout.
@@ -3174,10 +3180,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 // Load the new folder.
                 loadBookmarksFolder();
             }
-
         } else if (currentWebView.canGoBack()) {  // There is at least one item in the current WebView history.
-            // Reset the formatted URL string so the page will load correctly if blocking of third-party requests is enabled.
-            formattedUrlString = "";
+            // Reset the current domain name so that navigation works if third-party requests are blocked.
+            currentWebView.resetCurrentDomainName();
 
             // Set `navigatingHistory` so that the domain settings are applied when the new URL is loaded.
             navigatingHistory = true;
@@ -3207,12 +3212,15 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         // Get the text from urlTextBox and convert it to a string.  trim() removes white spaces from the beginning and end of the string.
         String unformattedUrlString = urlEditText.getText().toString().trim();
 
+        // Initialize the formatted URL string.
+        String url = "";
+
         // Check to see if `unformattedUrlString` is a valid URL.  Otherwise, convert it into a search.
-        if (unformattedUrlString.startsWith("content://")) {
+        if (unformattedUrlString.startsWith("content://")) {  // This is a Content URL.
             // Load the entire content URL.
-            formattedUrlString = unformattedUrlString;
-        } else if (Patterns.WEB_URL.matcher(unformattedUrlString).matches() || unformattedUrlString.startsWith("http://") || unformattedUrlString.startsWith("https://")
-                || unformattedUrlString.startsWith("file://")) {
+            url = unformattedUrlString;
+        } else if (Patterns.WEB_URL.matcher(unformattedUrlString).matches() || unformattedUrlString.startsWith("http://") || unformattedUrlString.startsWith("https://") ||
+                unformattedUrlString.startsWith("file://")) {  // This is a standard URL.
             // Add `https://` at the beginning if there is no protocol.  Otherwise the app will segfault.
             if (!unformattedUrlString.startsWith("http") && !unformattedUrlString.startsWith("file://") && !unformattedUrlString.startsWith("content://")) {
                 unformattedUrlString = "https://" + unformattedUrlString;
@@ -3236,20 +3244,16 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             String fragment = unformattedUrl != null ? unformattedUrl.getRef() : null;
 
             // Build the URI.
-            Uri.Builder formattedUri = new Uri.Builder();
-            formattedUri.scheme(scheme).authority(authority).path(path).query(query).fragment(fragment);
+            Uri.Builder uri = new Uri.Builder();
+            uri.scheme(scheme).authority(authority).path(path).query(query).fragment(fragment);
 
-            // Decode `formattedUri` as a `String` in `UTF-8`.
+            // Decode the URI as a UTF-8 string in.
             try {
-                formattedUrlString = URLDecoder.decode(formattedUri.build().toString(), "UTF-8");
+                url = URLDecoder.decode(uri.build().toString(), "UTF-8");
             } catch (UnsupportedEncodingException exception) {
-                // Load a blank string.
-                formattedUrlString = "";
+                // Do nothing.  The formatted URL string will remain blank.
             }
-        } else if (unformattedUrlString.isEmpty()){  // Load a blank web site.
-            // Load a blank string.
-            formattedUrlString = "";
-        } else {  // Search for the contents of the URL box.
+        } else if (!unformattedUrlString.isEmpty()){  // This is not a URL, but rather a search string.
             // Create an encoded URL String.
             String encodedUrlString;
 
@@ -3261,20 +3265,17 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             }
 
             // Add the base search URL.
-            formattedUrlString = searchURL + encodedUrlString;
+            url = searchURL + encodedUrlString;
         }
 
         // Clear the focus from the URL edit text.  Otherwise, proximate typing in the box will retain the colorized formatting instead of being reset during refocus.
         urlEditText.clearFocus();
 
         // Make it so.
-        loadUrl(formattedUrlString);
+        loadUrl(url);
     }
 
-    private void loadUrl(String url) {// Apply any custom domain settings.
-        // Set the URL as the formatted URL string so that checking third-party requests works correctly.
-        formattedUrlString = url;
-
+    private void loadUrl(String url) {
         // Apply the domain settings.
         applyDomainSettings(currentWebView, url, true, false);
 
@@ -3296,6 +3297,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         // Get a handle for the views.
         Toolbar toolbar = findViewById(R.id.toolbar);
         LinearLayout findOnPageLinearLayout = findViewById(R.id.find_on_page_linearlayout);
+        EditText findOnPageEditText = findViewById(R.id.find_on_page_edittext);
 
         // Delete the contents of `find_on_page_edittext`.
         findOnPageEditText.setText(null);
@@ -3309,6 +3311,12 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         // Show the toolbar.
         toolbar.setVisibility(View.VISIBLE);
 
+        // Get a handle for the input method manager.
+        InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+
+        // Remove the lint warning below that the input method manager might be null.
+        assert inputMethodManager != null;
+
         // Hide the keyboard.
         inputMethodManager.hideSoftInputFromWindow(currentWebView.getWindowToken(), 0);
     }
@@ -3410,9 +3418,6 @@ 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 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();
 
@@ -3442,7 +3447,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             // Reset the favorite icon if specified.
             if (resetFavoriteIcon) {
                 // Initialize the favorite icon.
-                currentWebView.initializeFavoriteIcon();
+                nestedScrollWebView.initializeFavoriteIcon();
 
                 // Get a handle for the tab layout.
                 TabLayout tabLayout = findViewById(R.id.tablayout);
@@ -3466,9 +3471,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 currentTabFavoriteIconImageView.setImageBitmap(Bitmap.createScaledBitmap(nestedScrollWebView.getFavoriteOrDefaultIcon(), 64, 64, true));
             }
 
-            // Get a handle for the swipe refresh layout.
-            SwipeRefreshLayout swipeRefreshLayout = findViewById(R.id.swiperefreshlayout);
-
             // Initialize the database handler.  The `0` specifies the database version, but that is ignored and set instead using a constant in `DomainsDatabaseHelper`.
             DomainsDatabaseHelper domainsDatabaseHelper = new DomainsDatabaseHelper(this, null, null, 0);
 
@@ -3530,12 +3532,20 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             String defaultFontSizeString = sharedPreferences.getString("font_size", getString(R.string.font_size_default_value));
             String defaultUserAgentName = sharedPreferences.getString("user_agent", getString(R.string.user_agent_default_value));
             boolean defaultSwipeToRefresh = sharedPreferences.getBoolean("swipe_to_refresh", true);
-            nightMode = sharedPreferences.getBoolean("night_mode", false);  // TODO.
             boolean displayWebpageImages = sharedPreferences.getBoolean("display_webpage_images", true);
+            boolean darkTheme = sharedPreferences.getBoolean("dark_theme", false);
 
             // Get a handle for the cookie manager.
             CookieManager cookieManager = CookieManager.getInstance();
 
+            // Get handles for the views.
+            RelativeLayout urlRelativeLayout = findViewById(R.id.url_relativelayout);
+            SwipeRefreshLayout swipeRefreshLayout = findViewById(R.id.swiperefreshlayout);
+
+            // Initialize the user agent array adapter and string array.
+            ArrayAdapter<CharSequence> userAgentNamesArray = ArrayAdapter.createFromResource(this, R.array.user_agent_names, R.layout.spinner_item);
+            String[] userAgentDataArray = getResources().getStringArray(R.array.user_agent_data);
+
             if (nestedScrollWebView.getDomainSettingsApplied()) {  // The url has custom domain settings.
                 // Get a cursor for the current host and move it to the first position.
                 Cursor currentDomainSettingsCursor = domainsDatabaseHelper.getCursorForDomainName(domainNameInDatabase);
@@ -3544,11 +3554,11 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 // Get the settings from the cursor.
                 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.
+                nestedScrollWebView.setAcceptFirstPartyCookies(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FIRST_PARTY_COOKIES)) == 1);
                 boolean domainThirdPartyCookiesEnabled = (currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_THIRD_PARTY_COOKIES)) == 1);
-                boolean domainDomStorageEnabled = (currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_DOM_STORAGE)) == 1);
+                nestedScrollWebView.getSettings().setDomStorageEnabled(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_DOM_STORAGE)) == 1);
                 // Form data can be removed once the minimum API >= 26.
-                saveFormDataEnabled = (currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FORM_DATA)) == 1);  // TODO.
+                boolean saveFormData = (currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FORM_DATA)) == 1);
                 nestedScrollWebView.enableBlocklist(NestedScrollWebView.EASY_LIST,
                         currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYLIST)) == 1);
                 nestedScrollWebView.enableBlocklist(NestedScrollWebView.EASY_PRIVACY,
@@ -3605,14 +3615,21 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                     nestedScrollWebView.setPinnedIpAddresses(pinnedHostIpAddresses);
                 }
 
-                // Set `nightMode` according to `nightModeInt`.  If `nightModeInt` is `DomainsDatabaseHelper.NIGHT_MODE_SYSTEM_DEFAULT` the current setting from `sharedPreferences` will be used.
+                // Set night mode according to the night mode int.
                 switch (nightModeInt) {
+                    case DomainsDatabaseHelper.NIGHT_MODE_SYSTEM_DEFAULT:
+                        // Set night mode according to the current default.
+                        nestedScrollWebView.setNightMode(sharedPreferences.getBoolean("night_mode", false));
+                        break;
+
                     case DomainsDatabaseHelper.NIGHT_MODE_ENABLED:
-                        nightMode = true;  // TODO.
+                        // Enable night mode.
+                        nestedScrollWebView.setNightMode(true);
                         break;
 
                     case DomainsDatabaseHelper.NIGHT_MODE_DISABLED:
-                        nightMode = false;  // TODO.
+                        // Disable night mode.
+                        nestedScrollWebView.setNightMode(false);
                         break;
                 }
 
@@ -3621,7 +3638,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 domainSettingsJavaScriptEnabled = domainJavaScriptEnabled;
 
                 // Enable JavaScript if night mode is enabled.
-                if (nightMode) {
+                if (nestedScrollWebView.getNightMode()) {
                     // Enable JavaScript.
                     nestedScrollWebView.getSettings().setJavaScriptEnabled(true);
                 } else {
@@ -3629,16 +3646,20 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                     nestedScrollWebView.getSettings().setJavaScriptEnabled(domainJavaScriptEnabled);
                 }
 
-                // Close `currentHostDomainSettingsCursor`.
+                // Close the current host domain settings cursor.
                 currentDomainSettingsCursor.close();
 
                 // Apply the domain settings.
-                cookieManager.setAcceptCookie(firstPartyCookiesEnabled);  //TODO  This could be bad.
-                nestedScrollWebView.getSettings().setDomStorageEnabled(domainDomStorageEnabled);  // TODO.  Move up.
+                cookieManager.setAcceptCookie(nestedScrollWebView.getAcceptFirstPartyCookies());
+
+                // Set third-party cookies status if API >= 21.
+                if (Build.VERSION.SDK_INT >= 21) {
+                    cookieManager.setAcceptThirdPartyCookies(nestedScrollWebView, domainThirdPartyCookiesEnabled);
+                }
 
                 // Apply the form data setting if the API < 26.
                 if (Build.VERSION.SDK_INT < 26) {
-                    nestedScrollWebView.getSettings().setSaveFormData(saveFormDataEnabled);
+                    nestedScrollWebView.getSettings().setSaveFormData(saveFormData);
                 }
 
                 // Apply the font size.
@@ -3648,18 +3669,13 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                     nestedScrollWebView.getSettings().setTextZoom(fontSize);
                 }
 
-                // Set third-party cookies status if API >= 21.
-                if (Build.VERSION.SDK_INT >= 21) {
-                    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.
                 // <https://redmine.stoutner.com/issues/160>
                 if (nestedScrollWebView.getProgress() == 100) {  // A URL is not loading.
                     // Set the user agent.
                     if (userAgentName.equals(getString(R.string.system_default_user_agent))) {  // Use the system default user agent.
                         // Get the array position of the default user agent name.
-                        int defaultUserAgentArrayPosition = userAgentNamesArray.getPosition(defaultUserAgentName);  // TODO Could this be local.
+                        int defaultUserAgentArrayPosition = userAgentNamesArray.getPosition(defaultUserAgentName);
 
                         // Set the user agent according to the system default.
                         switch (defaultUserAgentArrayPosition) {
@@ -3704,19 +3720,28 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 }
 
                 // Set swipe to refresh.
-                switch (swipeToRefreshInt) {  // TODO.  This needs to be set and updated by tab.
+                switch (swipeToRefreshInt) {
                     case DomainsDatabaseHelper.SWIPE_TO_REFRESH_SYSTEM_DEFAULT:
-                        // Set swipe to refresh according to the default.
+                        // Store the swipe to refresh status in the nested scroll WebView.
+                        nestedScrollWebView.setSwipeToRefresh(defaultSwipeToRefresh);
+
+                        // Apply swipe to refresh according to the default.  This can be removed once the minimum API >= 23 because it is continuously set by an on scroll change listener.
                         swipeRefreshLayout.setEnabled(defaultSwipeToRefresh);
                         break;
 
                     case DomainsDatabaseHelper.SWIPE_TO_REFRESH_ENABLED:
-                        // Enable swipe to refresh.
+                        // Store the swipe to refresh status in the nested scroll WebView.
+                        nestedScrollWebView.setSwipeToRefresh(true);
+
+                        // Enable swipe to refresh.  This can be removed once the minimum API >= 23 because it is continuously set by an on scroll change listener.
                         swipeRefreshLayout.setEnabled(true);
                         break;
 
                     case DomainsDatabaseHelper.SWIPE_TO_REFRESH_DISABLED:
-                        // Disable swipe to refresh.
+                        // Store the swipe to refresh status in the nested scroll WebView.
+                        nestedScrollWebView.setSwipeToRefresh(false);
+
+                        // Disable swipe to refresh.  This can be removed once the minimum API >= 23 because it is continuously set by an on scroll change listener.
                         swipeRefreshLayout.setEnabled(false);
                 }
 
@@ -3744,19 +3769,20 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             } else {  // The new URL does not have custom domain settings.  Load the defaults.
                 // Store the values from the shared preferences.
                 boolean defaultJavaScriptEnabled = sharedPreferences.getBoolean("javascript", false);
-                firstPartyCookiesEnabled = sharedPreferences.getBoolean("first_party_cookies", false);  // TODO.
+                nestedScrollWebView.setAcceptFirstPartyCookies(sharedPreferences.getBoolean("first_party_cookies", false));
                 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.
+                boolean saveFormData = sharedPreferences.getBoolean("save_form_data", false);  // Form data can be removed once the minimum API >= 26.
                 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));
+                nestedScrollWebView.setNightMode(sharedPreferences.getBoolean("night_mode", false));
 
                 // Enable JavaScript if night mode is enabled.
-                if (nightMode) {
+                if (nestedScrollWebView.getNightMode()) {
                     // Enable JavaScript.
                     nestedScrollWebView.getSettings().setJavaScriptEnabled(true);
                 } else {
@@ -3765,15 +3791,20 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 }
 
                 // Apply the default settings.
-                cookieManager.setAcceptCookie(firstPartyCookiesEnabled);  // TODO.
+                cookieManager.setAcceptCookie(nestedScrollWebView.getAcceptFirstPartyCookies());
                 nestedScrollWebView.getSettings().setTextZoom(Integer.valueOf(defaultFontSizeString));
-                swipeRefreshLayout.setEnabled(defaultSwipeToRefresh);
 
                 // Apply the form data setting if the API < 26.
                 if (Build.VERSION.SDK_INT < 26) {
-                    currentWebView.getSettings().setSaveFormData(saveFormDataEnabled);
+                    nestedScrollWebView.getSettings().setSaveFormData(saveFormData);
                 }
 
+                // Store the swipe to refresh status in the nested scroll WebView.
+                nestedScrollWebView.setSwipeToRefresh(defaultSwipeToRefresh);
+
+                // Apply swipe to refresh according to the default.
+                swipeRefreshLayout.setEnabled(defaultSwipeToRefresh);
+
                 // Reset the pinned variables.
                 nestedScrollWebView.setDomainSettingsDatabaseId(-1);
 
@@ -3838,13 +3869,12 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         // Get a handle for the shared preferences.
         SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
 
-        // Get the search preferences.
-        String homepageString = sharedPreferences.getString("homepage", getString(R.string.homepage_default_value));
-        String torHomepageString = sharedPreferences.getString("tor_homepage", getString(R.string.tor_homepage_default_value));
+        // Get the search and theme preferences.
         String torSearchString = sharedPreferences.getString("tor_search", getString(R.string.tor_search_default_value));
         String torSearchCustomUrlString = sharedPreferences.getString("tor_search_custom_url", getString(R.string.tor_search_custom_url_default_value));
         String searchString = sharedPreferences.getString("search", getString(R.string.search_default_value));
         String searchCustomUrlString = sharedPreferences.getString("search_custom_url", getString(R.string.search_custom_url_default_value));
+        boolean darkTheme = sharedPreferences.getBoolean("dark_theme", false);
 
         // Get a handle for the action bar.  `getSupportActionBar()` must be used until the minimum API >= 21.
         ActionBar actionBar = getSupportActionBar();
@@ -3854,14 +3884,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
         // Set the homepage, search, and proxy options.
         if (proxyThroughOrbot) {  // Set the Tor options.
-            // Set `torHomepageString` as `homepage`.
-            homepage = torHomepageString;
-
-            // If formattedUrlString is null assign the homepage to it.
-            if (formattedUrlString == null) {
-                formattedUrlString = homepage;
-            }
-
             // Set the search URL.
             if (torSearchString.equals("Custom URL")) {  // Get the custom URL string.
                 searchURL = torSearchCustomUrlString;
@@ -3872,7 +3894,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             // Set the proxy.  `this` refers to the current activity where an `AlertDialog` might be displayed.
             OrbotProxyHelper.setProxy(getApplicationContext(), this, "localhost", "8118");
 
-            // Set the `appBar` background to indicate proxying through Orbot is enabled.  `this` refers to the context.
+            // Set the `appBar` background to indicate proxying through Orbot is enabled.
             if (darkTheme) {
                 actionBar.setBackgroundDrawable(ContextCompat.getDrawable(this, R.color.dark_blue_30));
             } else {
@@ -3894,14 +3916,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 currentWebView.reload();
             }
         } else {  // Set the non-Tor options.
-            // Set `homepageString` as `homepage`.
-            homepage = homepageString;
-
-            // If formattedUrlString is null assign the homepage to it.
-            if (formattedUrlString == null) {
-                formattedUrlString = homepage;
-            }
-
             // Set the search URL.
             if (searchString.equals("Custom URL")) {  // Get the custom URL string.
                 searchURL = searchCustomUrlString;
@@ -3912,7 +3926,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             // Reset the proxy to default.  The host is `""` and the port is `"0"`.
             OrbotProxyHelper.setProxy(getApplicationContext(), this, "", "0");
 
-            // Set the default `appBar` background.  `this` refers to the context.
+            // Set the default `appBar` background.
             if (darkTheme) {
                 actionBar.setBackgroundDrawable(ContextCompat.getDrawable(this, R.color.gray_900));
             } else {
@@ -3946,8 +3960,14 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     }
 
     private void updatePrivacyIcons(boolean runInvalidateOptionsMenu) {
-        // Only update the privacy icons if the options menu has already been populated.
-        if (optionsMenu != null) {
+        // Only update the privacy icons if the options menu and the current WebView have already been populated.
+        if ((optionsMenu != null) && (currentWebView != null)) {
+            // Get a handle for the shared preferences.
+            SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
+
+            // Get the theme and screenshot preferences.
+            boolean darkTheme = sharedPreferences.getBoolean("dark_theme", false);
+
             // Get handles for the menu items.
             MenuItem privacyMenuItem = optionsMenu.findItem(R.id.toggle_javascript);
             MenuItem firstPartyCookiesMenuItem = optionsMenu.findItem(R.id.toggle_first_party_cookies);
@@ -3957,14 +3977,14 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             // Update the privacy icon.
             if (currentWebView.getSettings().getJavaScriptEnabled()) {  // JavaScript is enabled.
                 privacyMenuItem.setIcon(R.drawable.javascript_enabled);
-            } else if (firstPartyCookiesEnabled) {  // JavaScript is disabled but cookies are enabled.
+            } else if (currentWebView.getAcceptFirstPartyCookies()) {  // JavaScript is disabled but cookies are enabled.
                 privacyMenuItem.setIcon(R.drawable.warning);
             } else {  // All the dangerous features are disabled.
                 privacyMenuItem.setIcon(R.drawable.privacy_mode);
             }
 
             // Update the first-party cookies icon.
-            if (firstPartyCookiesEnabled) {  // First-party cookies are enabled.
+            if (currentWebView.getAcceptFirstPartyCookies()) {  // First-party cookies are enabled.
                 firstPartyCookiesMenuItem.setIcon(R.drawable.cookies_enabled);
             } else {  // First-party cookies are disabled.
                 if (darkTheme) {
@@ -4123,9 +4143,15 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             }
         };
 
-        // Populate the `ListView` with the adapter.
+        // Get a handle for the bookmarks list view.
+        ListView bookmarksListView = findViewById(R.id.bookmarks_drawer_listview);
+
+        // Populate the list view with the adapter.
         bookmarksListView.setAdapter(bookmarksCursorAdapter);
 
+        // Get a handle for the bookmarks title text view.
+        TextView bookmarksTitleTextView = findViewById(R.id.bookmarks_title_textview);
+
         // Set the bookmarks drawer title.
         if (currentBookmarksFolder.isEmpty()) {
             bookmarksTitleTextView.setText(R.string.bookmarks);
@@ -4187,9 +4213,19 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     }
 
     private void setCurrentWebView(int pageNumber) {
+        // Get a handle for the shared preferences.
+        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
+
+        // Get the theme preference.
+        boolean darkTheme = sharedPreferences.getBoolean("dark_theme", false);
+
         // Get handles for the URL views.
         RelativeLayout urlRelativeLayout = findViewById(R.id.url_relativelayout);
         EditText urlEditText = findViewById(R.id.url_edittext);
+        SwipeRefreshLayout swipeRefreshLayout = findViewById(R.id.swiperefreshlayout);
+
+        //Stop the swipe to refresh indicator if it is running
+        swipeRefreshLayout.setRefreshing(false);
 
         // Get the WebView tab fragment.
         WebViewTabFragment webViewTabFragment = webViewPagerAdapter.getPageFragment(pageNumber);
@@ -4203,20 +4239,43 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         // Store the current WebView.
         currentWebView = fragmentView.findViewById(R.id.nestedscroll_webview);
 
+        // Update the status of swipe to refresh.
+        if (currentWebView.getSwipeToRefresh()) {  // Swipe to refresh is enabled.
+            if (Build.VERSION.SDK_INT >= 23) {  // For API >= 23, swipe refresh layout is continuously updated with an on scroll change listener and only enabled if the WebView is scrolled to the top.
+                // Enable the swipe refresh layout if the WebView is scrolled all the way to the top.
+                swipeRefreshLayout.setEnabled(currentWebView.getY() == 0);
+            } else {
+                // Enable the swipe refresh layout.
+                swipeRefreshLayout.setEnabled(true);
+            }
+        } else {  // Swipe to refresh is disabled.
+            // Disable the swipe refresh layout.
+            swipeRefreshLayout.setEnabled(false);
+        }
+
+        // Get a handle for the cookie manager.
+        CookieManager cookieManager = CookieManager.getInstance();
+
+        // Set the first-party cookie status.
+        cookieManager.setAcceptCookie(currentWebView.getAcceptFirstPartyCookies());
+
         // 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();
 
+        // Get a handle for the input method manager.
+        InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+
+        // Remove the lint warning below that the input method manager might be null.
+        assert inputMethodManager != null;
+
         // Hide the soft keyboard.
         inputMethodManager.hideSoftInputFromWindow(currentWebView.getWindowToken(), 0);
 
         // Display the current URL in the URL text box.
-        urlEditText.setText(formattedUrlString);
+        urlEditText.setText(currentWebView.getUrl());
 
         // Highlight the URL text.
         highlightUrlText();
@@ -4251,6 +4310,12 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         // Get a handle for the activity
         Activity activity = this;
 
+        // Get a handle for the input method manager.
+        InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+
+        // Remove the lint warning below that the input method manager might be null.
+        assert inputMethodManager != null;
+
         // Get a handle for the shared preferences.
         SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
 
@@ -4421,13 +4486,23 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             }
         });
 
+        if (Build.VERSION.SDK_INT >= 23) {
+            nestedScrollWebView.setOnScrollChangeListener((View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) -> {
+                // Update the status of swipe to refresh if it is enabled.
+                if (nestedScrollWebView.getSwipeToRefresh()) {
+                    // Only enable swipe to refresh if the WebView is scrolled to the top.
+                    swipeRefreshLayout.setEnabled(scrollY == 0);
+                }
+            });
+        }
+
         // Set the web chrome client.
         nestedScrollWebView.setWebChromeClient(new WebChromeClient() {
             // Update the progress bar when a page is loading.
             @Override
             public void onProgressChanged(WebView view, int progress) {
                 // Inject the night mode CSS if night mode is enabled.
-                if (nightMode) {
+                if (nestedScrollWebView.getNightMode()) {
                     // `background-color: #212121` sets the background to be dark gray.  `color: #BDBDBD` sets the text color to be light gray.  `box-shadow: none` removes a lower underline on links
                     // used by WordPress.  `text-decoration: none` removes all text underlines.  `text-shadow: none` removes text shadows, which usually have a hard coded color.
                     // `border: none` removes all borders, which can also be used to underline text.  `a {color: #1565C0}` sets links to be a dark blue.
@@ -4462,10 +4537,10 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                     // Hide the progress bar.
                     progressBar.setVisibility(View.GONE);
 
-                    // Display `mainWebView` if night mode is disabled.
-                    // Because of a race condition between `applyDomainSettings` and `onPageStarted`, when night mode is set by domain settings the `WebView` may be hidden even if night mode is not
-                    // currently enabled.
-                    if (!nightMode) {
+                    // Display the nested scroll WebView if night mode is disabled.
+                    // Because of a race condition between `applyDomainSettings` and `onPageStarted`,
+                    // when night mode is set by domain settings the WebView may be hidden even if night mode is not currently enabled.
+                    if (!nestedScrollWebView.getNightMode()) {
                         nestedScrollWebView.setVisibility(View.VISIBLE);
                     }
 
@@ -4660,10 +4735,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             @Override
             public boolean shouldOverrideUrlLoading(WebView view, String url) {
                 if (url.startsWith("http")) {  // Load the URL in Privacy Browser.
-                    // Reset the formatted URL string so the page will load correctly if blocking of third-party requests is enabled.
-                    formattedUrlString = "";
-
-                    // Apply the domain settings for the new URL.  `applyDomainSettings` doesn't do anything if the domain has not changed.
+                    // Apply the domain settings for the new URL.  This doesn't do anything if the domain has not changed.
                     boolean userAgentChanged = applyDomainSettings(nestedScrollWebView, url, true, false);
 
                     // Check if the user agent has changed.
@@ -4754,24 +4826,22 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 // Initialize the third party request tracker.
                 boolean isThirdPartyRequest = false;
 
-                // Initialize the current domain string.
-                String currentDomain = "";
+                // Get the current URL.  `.getUrl()` throws an error because operations on the WebView cannot be made from this thread.
+                String currentBaseDomain = nestedScrollWebView.getCurrentDomainName();
 
-                // Nobody is happy when comparing null strings.
-                if (!(formattedUrlString == null) && !(url == null)) {
-                    // Get the domain strings to URIs.
-                    Uri currentDomainUri = Uri.parse(formattedUrlString);
-                    Uri requestDomainUri = Uri.parse(url);
+                // Store a copy of the current domain for use in later requests.
+                String currentDomain = currentBaseDomain;
 
-                    // Get the domain host names.
-                    String currentBaseDomain = currentDomainUri.getHost();
-                    String requestBaseDomain = requestDomainUri.getHost();
+                // Nobody is happy when comparing null strings.
+                if ((currentBaseDomain != null) && (url != null)) {
+                    // Convert the request URL to a URI.
+                    Uri requestUri = Uri.parse(url);
 
-                    // Update the current domain variable.
-                    currentDomain = currentBaseDomain;
+                    // Get the request host name.
+                    String requestBaseDomain = requestUri.getHost();
 
-                    // Only compare the current base domain and the request base domain if neither is null.
-                    if (!(currentBaseDomain == null) && !(requestBaseDomain == null)) {
+                    // Only check for third-party requests if the current base domain is not empty and the request domain is not null.
+                    if (!currentBaseDomain.isEmpty() && (requestBaseDomain != null)) {
                         // Determine the current base domain.
                         while (currentBaseDomain.indexOf(".", currentBaseDomain.indexOf(".") + 1) > 0) {  // There is at least one subdomain.
                             // Remove the first subdomain.
@@ -5018,6 +5088,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
             @Override
             public void onPageStarted(WebView view, String url, Bitmap favicon) {
+                // Get the theme preference.
+                boolean darkTheme = sharedPreferences.getBoolean("dark_theme", false);
+
                 // Reset the list of resource requests.
                 nestedScrollWebView.clearResourceRequests();
 
@@ -5025,7 +5098,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 nestedScrollWebView.resetRequestsCounters();
 
                 // If night mode is enabled, hide `mainWebView` until after the night mode CSS is applied.
-                if (nightMode) {
+                if (nestedScrollWebView.getNightMode()) {
                     nestedScrollWebView.setVisibility(View.INVISIBLE);
                 }
 
@@ -5034,21 +5107,18 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
                 // Check to see if Privacy Browser is waiting on Orbot.
                 if (!waitingForOrbot) {  // Process the URL.
-                    // The formatted URL string must be updated at the beginning of the load, so that if the user toggles JavaScript during the load the new website is reloaded.
-                    formattedUrlString = url;
-
                     // Display the formatted URL text.
-                    urlEditText.setText(formattedUrlString);
+                    urlEditText.setText(url);
 
                     // Apply text highlighting to `urlTextBox`.
                     highlightUrlText();
 
-                    // Get a URI for the current URL.
-                    Uri currentUri = Uri.parse(formattedUrlString);
-
                     // Reset the list of host IP addresses.
                     nestedScrollWebView.clearCurrentIpAddresses();
 
+                    // Get a URI for the current URL.
+                    Uri currentUri = Uri.parse(url);
+
                     // Get the IP addresses for the host.
                     new GetHostIpAddresses(activity, getSupportFragmentManager(), nestedScrollWebView).execute(currentUri.getHost());
 
@@ -5062,15 +5132,21 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
                         // Manually load the URL if the user agent has changed, which will have caused the previous URL to be reloaded.
                         if (userAgentChanged) {
-                            loadUrl(formattedUrlString);
+                            loadUrl(url);
                         }
                     }
 
-                    // Replace Refresh with Stop if the menu item has been created.  (The WebView typically begins loading before the menu items are instantiated.)
-                    if (refreshMenuItem != null) {
+                    // Replace Refresh with Stop if the options menu has been created.  (The WebView typically begins loading before the menu items are instantiated.)
+                    if (optionsMenu != null) {
+                        // Get a handle for the refresh menu item.
+                        MenuItem refreshMenuItem = optionsMenu.findItem(R.id.refresh);
+
                         // Set the title.
                         refreshMenuItem.setTitle(R.string.stop);
 
+                        // Get the app bar and theme preferences.
+                        boolean displayAdditionalAppBarIcons = sharedPreferences.getBoolean("display_additional_app_bar_icons", false);
+
                         // If the icon is displayed in the AppBar, set it according to the theme.
                         if (displayAdditionalAppBarIcons) {
                             if (darkTheme) {
@@ -5083,7 +5159,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 }
             }
 
-            // It is necessary to update `formattedUrlString` and `urlTextBox` after the page finishes loading because the final URL can change during load.
             @Override
             public void onPageFinished(WebView view, String url) {
                 // Reset the wide view port if it has been turned off by the waiting for Orbot message.
@@ -5092,16 +5167,23 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                     nestedScrollWebView.getSettings().setUseWideViewPort(url.startsWith("http"));
                 }
 
-                // Flush any cookies to persistent storage.  `CookieManager` has become very lazy about flushing cookies in recent versions.
-                if (firstPartyCookiesEnabled && Build.VERSION.SDK_INT >= 21) {
+                // Flush any cookies to persistent storage.  The cookie manager has become very lazy about flushing cookies in recent versions.
+                if (nestedScrollWebView.getAcceptFirstPartyCookies() && Build.VERSION.SDK_INT >= 21) {
                     CookieManager.getInstance().flush();
                 }
 
-                // Update the Refresh menu item if it has been created.
-                if (refreshMenuItem != null) {
+                // Update the Refresh menu item if the options menu has been created.
+                if (optionsMenu != null) {
+                    // Get a handle for the refresh menu item.
+                    MenuItem refreshMenuItem = optionsMenu.findItem(R.id.refresh);
+
                     // Reset the Refresh title.
                     refreshMenuItem.setTitle(R.string.refresh);
 
+                    // Get the app bar and theme preferences.
+                    boolean displayAdditionalAppBarIcons = sharedPreferences.getBoolean("display_additional_app_bar_icons", false);
+                    boolean darkTheme = sharedPreferences.getBoolean("dark_theme", false);
+
                     // If the icon is displayed in the AppBar, reset it according to the theme.
                     if (displayAdditionalAppBarIcons) {
                         if (darkTheme) {
@@ -5112,7 +5194,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                     }
                 }
 
-
                 // Clear the cache and history if Incognito Mode is enabled.
                 if (incognitoModeEnabled) {
                     // Clear the cache.  `true` includes disk files.
@@ -5137,11 +5218,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 // Update the URL text box and apply domain settings if not waiting on Orbot.
                 if (!waitingForOrbot) {
                     // Check to see if `WebView` has set `url` to be `about:blank`.
-                    if (url.equals("about:blank")) {  // `WebView` is blank, so `formattedUrlString` should be `""` and `urlTextBox` should display a hint.
-                        // Set `formattedUrlString` to `""`.
-                        formattedUrlString = "";
-
-                        urlEditText.setText(formattedUrlString);
+                    if (url.equals("about:blank")) {  // The WebView is blank.
+                        // Display the hint in the URL edit text.
+                        urlEditText.setText("");
 
                         // Request focus for `urlTextBox`.
                         urlEditText.requestFocus();
@@ -5149,16 +5228,16 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                         // Display the keyboard.
                         inputMethodManager.showSoftInput(urlEditText, 0);
 
-                        // Apply the domain settings.  This clears any settings from the previous domain.
-                        applyDomainSettings(nestedScrollWebView, formattedUrlString, true, false);
-                    } else {  // `WebView` has loaded a webpage.
-                        // Set the formatted URL string.  Getting the URL from the WebView instead of using the one provided by `onPageFinished` makes websites like YouTube function correctly.
-                        formattedUrlString = nestedScrollWebView.getUrl();
+                        // Hide the WebView, which causes the default background color to be displayed according to the theme.
+                        nestedScrollWebView.setVisibility(View.GONE);
 
+                        // Apply the domain settings.  This clears any settings from the previous domain.
+                        applyDomainSettings(nestedScrollWebView, "", true, false);
+                    } else {  // The WebView has loaded a webpage.
                         // Only update the URL text box if the user is not typing in it.
                         if (!urlEditText.hasFocus()) {
-                            // Display the formatted URL text.
-                            urlEditText.setText(formattedUrlString);
+                            // Display the final URL.  Getting the URL from the WebView instead of using the one provided by `onPageFinished` makes websites like YouTube function correctly.
+                            urlEditText.setText(nestedScrollWebView.getUrl());
 
                             // Apply text highlighting to `urlTextBox`.
                             highlightUrlText();
@@ -5228,7 +5307,40 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
             // Load the website if not waiting for Orbot to connect.
             if (!waitingForOrbot) {
-                loadUrl(formattedUrlString);
+                // Get the intent that started the app.
+                Intent launchingIntent = getIntent();
+
+                // Get the information from the intent.
+                String launchingIntentAction = launchingIntent.getAction();
+                Uri launchingIntentUriData = launchingIntent.getData();
+
+                // If the intent action is a web search, perform the search.
+                if ((launchingIntentAction != null) && launchingIntentAction.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(launchingIntent.getStringExtra(SearchManager.QUERY), "UTF-8");
+                    } catch (UnsupportedEncodingException exception) {
+                        encodedUrlString = "";
+                    }
+
+                    // Load the completed search URL.
+                    loadUrl(searchURL + encodedUrlString);
+                } else if (launchingIntentUriData != null){  // Check to see if the intent contains a new URL.
+                    // Load the URL from the intent.
+                    loadUrl(launchingIntentUriData.toString());
+                } else {  // The is no URL in the intent.
+                    // Select the homepage based on the proxy through Orbot status.
+                    if (proxyThroughOrbot) {
+                        // Load the Tor homepage.
+                        loadUrl(sharedPreferences.getString("tor_homepage", getString(R.string.tor_homepage_default_value)));
+                    } else {
+                        // Load the normal homepage.
+                        loadUrl(sharedPreferences.getString("homepage", getString(R.string.homepage_default_value)));
+                    }
+                }
             }
         }
     }