]> gitweb.stoutner.com Git - PrivacyBrowserAndroid.git/blobdiff - app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.kt
First wrong button text in View Headers in night theme. https://redmine.stoutner...
[PrivacyBrowserAndroid.git] / app / src / main / java / com / stoutner / privacybrowser / activities / MainWebViewActivity.kt
index e257118714d0d3dafb41060dc9741617df6b4c3b..042af73dce4f9258440b6da318dcdbfaac7ba25d 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * Copyright 2015-2023 Soren Stoutner <soren@stoutner.com>.
+ * Copyright 2015-2024 Soren Stoutner <soren@stoutner.com>.
  *
  * Download cookie code contributed 2017 Hendrik Knackstedt.  Copyright assigned to Soren Stoutner <soren@stoutner.com>.
  *
- * This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
+ * This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android/>.
  *
  * Privacy Browser Android is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -76,7 +76,6 @@ import android.webkit.WebSettings
 import android.webkit.WebStorage
 import android.webkit.WebView
 import android.webkit.WebViewClient
-import android.webkit.WebViewDatabase
 import android.widget.AdapterView
 import android.widget.ArrayAdapter
 import android.widget.CheckBox
@@ -87,23 +86,26 @@ import android.widget.LinearLayout
 import android.widget.ListView
 import android.widget.ProgressBar
 import android.widget.RadioButton
+import android.widget.RadioGroup
 import android.widget.RelativeLayout
 import android.widget.TextView
 
 import androidx.activity.OnBackPressedCallback
 import androidx.activity.result.contract.ActivityResultContracts
 import androidx.appcompat.app.ActionBar
-import androidx.appcompat.app.ActionBarDrawerToggle
 import androidx.appcompat.app.AppCompatActivity
 import androidx.appcompat.app.AppCompatDelegate
 import androidx.appcompat.content.res.AppCompatResources
 import androidx.appcompat.widget.Toolbar
 import androidx.coordinatorlayout.widget.CoordinatorLayout
+import androidx.core.content.ContextCompat
 import androidx.core.view.GravityCompat
 import androidx.cursoradapter.widget.CursorAdapter
 import androidx.drawerlayout.widget.DrawerLayout
 import androidx.fragment.app.DialogFragment
 import androidx.preference.PreferenceManager
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
 import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
 import androidx.viewpager2.widget.ViewPager2
 import androidx.webkit.WebSettingsCompat
@@ -137,10 +139,44 @@ import com.stoutner.privacybrowser.dialogs.UrlHistoryDialog
 import com.stoutner.privacybrowser.dialogs.ViewSslCertificateDialog
 import com.stoutner.privacybrowser.dialogs.WaitingForProxyDialog
 import com.stoutner.privacybrowser.fragments.WebViewTabFragment
+import com.stoutner.privacybrowser.helpers.BOOKMARK_NAME
+import com.stoutner.privacybrowser.helpers.BOOKMARK_URL
+import com.stoutner.privacybrowser.helpers.COOKIES
+import com.stoutner.privacybrowser.helpers.DARK_THEME
+import com.stoutner.privacybrowser.helpers.DISABLED
+import com.stoutner.privacybrowser.helpers.DISPLAY_IMAGES
+import com.stoutner.privacybrowser.helpers.DOMAIN_NAME
+import com.stoutner.privacybrowser.helpers.ENABLE_DOM_STORAGE
+import com.stoutner.privacybrowser.helpers.ENABLE_EASYLIST
+import com.stoutner.privacybrowser.helpers.ENABLE_EASYPRIVACY
+import com.stoutner.privacybrowser.helpers.ENABLE_FANBOYS_ANNOYANCE_LIST
+import com.stoutner.privacybrowser.helpers.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST
+import com.stoutner.privacybrowser.helpers.ENABLE_JAVASCRIPT
+import com.stoutner.privacybrowser.helpers.ENABLE_ULTRAPRIVACY
+import com.stoutner.privacybrowser.helpers.ENABLED
+import com.stoutner.privacybrowser.helpers.FAVORITE_ICON
+import com.stoutner.privacybrowser.helpers.FOLDER_ID
+import com.stoutner.privacybrowser.helpers.FONT_SIZE
+import com.stoutner.privacybrowser.helpers.ID
+import com.stoutner.privacybrowser.helpers.IP_ADDRESSES
+import com.stoutner.privacybrowser.helpers.IS_FOLDER
+import com.stoutner.privacybrowser.helpers.LIGHT_THEME
+import com.stoutner.privacybrowser.helpers.PINNED_IP_ADDRESSES
+import com.stoutner.privacybrowser.helpers.PINNED_SSL_CERTIFICATE
 import com.stoutner.privacybrowser.helpers.REQUEST_ALLOWED
 import com.stoutner.privacybrowser.helpers.REQUEST_BLOCKED
 import com.stoutner.privacybrowser.helpers.REQUEST_DEFAULT
 import com.stoutner.privacybrowser.helpers.REQUEST_THIRD_PARTY
+import com.stoutner.privacybrowser.helpers.SSL_ISSUED_BY_COMMON_NAME
+import com.stoutner.privacybrowser.helpers.SSL_ISSUED_BY_ORGANIZATION
+import com.stoutner.privacybrowser.helpers.SSL_ISSUED_BY_ORGANIZATIONAL_UNIT
+import com.stoutner.privacybrowser.helpers.SSL_ISSUED_TO_COMMON_NAME
+import com.stoutner.privacybrowser.helpers.SSL_ISSUED_TO_ORGANIZATION
+import com.stoutner.privacybrowser.helpers.SSL_ISSUED_TO_ORGANIZATIONAL_UNIT
+import com.stoutner.privacybrowser.helpers.SWIPE_TO_REFRESH
+import com.stoutner.privacybrowser.helpers.SYSTEM_DEFAULT
+import com.stoutner.privacybrowser.helpers.WEBVIEW_THEME
+import com.stoutner.privacybrowser.helpers.WIDE_VIEWPORT
 import com.stoutner.privacybrowser.helpers.BookmarksDatabaseHelper
 import com.stoutner.privacybrowser.helpers.CheckFilterListHelper
 import com.stoutner.privacybrowser.helpers.DomainsDatabaseHelper
@@ -153,7 +189,6 @@ import com.stoutner.privacybrowser.views.EASYPRIVACY
 import com.stoutner.privacybrowser.views.FANBOYS_ANNOYANCE_LIST
 import com.stoutner.privacybrowser.views.FANBOYS_SOCIAL_BLOCKING_LIST
 import com.stoutner.privacybrowser.views.THIRD_PARTY_REQUESTS
-import com.stoutner.privacybrowser.views.ULTRALIST
 import com.stoutner.privacybrowser.views.ULTRAPRIVACY
 import com.stoutner.privacybrowser.views.NestedScrollWebView
 
@@ -205,7 +240,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
 
     companion object {
         // Define the public static variables.
-        var currentBookmarksFolder = ""
+        var currentBookmarksFolderId = 0L
         val executorService = Executors.newFixedThreadPool(4)!!
         var orbotStatus = "unknown"
         val pendingDialogsArrayList = ArrayList<PendingDialogDataClass>()
@@ -215,6 +250,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
 
         // Declare the public static variables.
         lateinit var appBarLayout: AppBarLayout
+        lateinit var defaultFavoriteIconBitmap : Bitmap
     }
 
     // Declare the class variables.
@@ -226,6 +262,9 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
     private lateinit var bookmarksTitleTextView: TextView
     private lateinit var coordinatorLayout: CoordinatorLayout
     private lateinit var cookieManager: CookieManager
+    private lateinit var defaultFontSizeString: String
+    private lateinit var defaultUserAgentName: String
+    private lateinit var defaultWebViewTheme: String
     private lateinit var domainsSettingsSet: MutableSet<String>
     private lateinit var drawerLayout: DrawerLayout
     private lateinit var easyList: ArrayList<List<Array<String>>>
@@ -239,16 +278,18 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
     private lateinit var findOnPageLinearLayout: LinearLayout
     private lateinit var fullScreenVideoFrameLayout: FrameLayout
     private lateinit var initialGrayColorSpan: ForegroundColorSpan
+    private lateinit var inputMethodManager: InputMethodManager
     private lateinit var navigationBackMenuItem: MenuItem
     private lateinit var navigationForwardMenuItem: MenuItem
     private lateinit var navigationHistoryMenuItem: MenuItem
     private lateinit var navigationRequestsMenuItem: MenuItem
+    private lateinit var navigationScrollToBottomMenuItem: MenuItem
+    private lateinit var navigationView: NavigationView
     private lateinit var optionsAddOrEditDomainMenuItem: MenuItem
     private lateinit var optionsBlockAllThirdPartyRequestsMenuItem: MenuItem
     private lateinit var optionsClearCookiesMenuItem: MenuItem
     private lateinit var optionsClearDataMenuItem: MenuItem
     private lateinit var optionsClearDomStorageMenuItem: MenuItem
-    private lateinit var optionsClearFormDataMenuItem: MenuItem
     private lateinit var optionsCookiesMenuItem: MenuItem
     private lateinit var optionsDarkWebViewMenuItem: MenuItem
     private lateinit var optionsDisplayImagesMenuItem: MenuItem
@@ -266,7 +307,6 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
     private lateinit var optionsProxyNoneMenuItem: MenuItem
     private lateinit var optionsProxyTorMenuItem: MenuItem
     private lateinit var optionsRefreshMenuItem: MenuItem
-    private lateinit var optionsSaveFormDataMenuItem: MenuItem
     private lateinit var optionsSwipeToRefreshMenuItem: MenuItem
     private lateinit var optionsUltraListMenuItem: MenuItem
     private lateinit var optionsUltraPrivacyMenuItem: MenuItem
@@ -278,12 +318,12 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
     private lateinit var optionsUserAgentFirefoxOnAndroidMenuItem: MenuItem
     private lateinit var optionsUserAgentFirefoxOnLinuxMenuItem: MenuItem
     private lateinit var optionsUserAgentFirefoxOnWindowsMenuItem: MenuItem
-    private lateinit var optionsUserAgentInternetExplorerOnWindowsMenuItem: MenuItem
     private lateinit var optionsUserAgentMenuItem: MenuItem
     private lateinit var optionsUserAgentPrivacyBrowserMenuItem: MenuItem
     private lateinit var optionsUserAgentSafariOnIosMenuItem: MenuItem
     private lateinit var optionsUserAgentSafariOnMacosMenuItem: MenuItem
     private lateinit var optionsUserAgentWebViewDefaultMenuItem: MenuItem
+    private lateinit var optionsViewSourceMenuItem: MenuItem
     private lateinit var optionsWideViewportMenuItem: MenuItem
     private lateinit var proxyHelper: ProxyHelper
     private lateinit var redColorSpan: ForegroundColorSpan
@@ -296,30 +336,48 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
     private lateinit var tabsLinearLayout: LinearLayout
     private lateinit var toolbar: Toolbar
     private lateinit var webViewDefaultUserAgent: String
+    private lateinit var webViewThemeEntryValuesStringArray: Array<String>
     private lateinit var webViewViewPager2: ViewPager2
     private lateinit var ultraList: ArrayList<List<Array<String>>>
     private lateinit var urlEditText: EditText
     private lateinit var urlRelativeLayout: RelativeLayout
+    private lateinit var userAgentDataArray: Array<String>
+    private lateinit var userAgentNamesArray: Array<String>
+    private lateinit var userAgentDataArrayAdapter: ArrayAdapter<CharSequence>
+    private lateinit var userAgentNamesArrayAdapter: ArrayAdapter<CharSequence>
 
     // Define the class variables.
-    private var actionBarDrawerToggle: ActionBarDrawerToggle? = null
     private var appBarHeight = 0
     private var bookmarksCursor: Cursor? = null
     private var bookmarksDatabaseHelper: BookmarksDatabaseHelper? = null
     private var bookmarksDrawerPinned = false
     private var bottomAppBar = false
     private var currentWebView: NestedScrollWebView? = null
+    private var defaultBlockAllThirdPartyRequests = false
+    private var defaultCookies = false
+    private var defaultDisplayWebpageImages = true
+    private var defaultDomStorage = false
+    private var defaultEasyList = true
+    private var defaultEasyPrivacy = true
+    private var defaultFanboysAnnoyanceList = true
+    private var defaultFanboysSocialBlockingList = true
     private var defaultProgressViewEndOffset = 0
     private var defaultProgressViewStartOffset = 0
+    private var defaultJavaScript = false
+    private var defaultSwipeToRefresh = true
+    private var defaultUltraList = true
+    private var defaultUltraPrivacy = true
+    private var defaultWideViewport = true
     private var displayAdditionalAppBarIcons = false
     private var displayingFullScreenVideo = false
     private var domainsDatabaseHelper: DomainsDatabaseHelper? = null
     private var downloadWithExternalApp = false
     private var fullScreenBrowsingModeEnabled = false
-    private var hideAppBar = false
+    private var hideAppBar = true
     private var inFullScreenBrowsingMode = false
     private var incognitoModeEnabled = false
     private var loadingNewIntent = false
+    private var navigationDrawerFirstView = true
     private var objectAnimator = ObjectAnimator()
     private var optionsMenu: Menu? = null
     private var orbotStatusBroadcastReceiver: BroadcastReceiver? = null
@@ -360,23 +418,17 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
     private val saveWebpageArchiveActivityResultLauncher = registerForActivityResult<String, Uri>(ActivityResultContracts.CreateDocument("multipart/related")) { fileUri ->
         // Only save the webpage archive if the file URI is not null, which happens if the user exited the file picker by pressing back.
         if (fileUri != null) {
-            // Initialize the file name string from the file URI last path segment.
-            var fileNameString = fileUri.lastPathSegment
+            // Get a cursor from the content resolver.
+            val contentResolverCursor = contentResolver.query(fileUri, null, null, null)!!
 
-            // Query the exact file name if the API >= 26.
-            if (Build.VERSION.SDK_INT >= 26) {
-                // Get a cursor from the content resolver.
-                val contentResolverCursor = contentResolver.query(fileUri, null, null, null)!!
+            // Move to the fist row.
+            contentResolverCursor.moveToFirst()
 
-                // Move to the fist row.
-                contentResolverCursor.moveToFirst()
+            // Get the file name from the cursor.
+            val fileNameString = contentResolverCursor.getString(contentResolverCursor.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME))
 
-                // Get the file name from the cursor.
-                fileNameString = contentResolverCursor.getString(contentResolverCursor.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME))
-
-                // Close the cursor.
-                contentResolverCursor.close()
-            }
+            // Close the cursor.
+            contentResolverCursor.close()
 
             // Use a coroutine to save the file.
             CoroutineScope(Dispatchers.Main).launch {
@@ -462,8 +514,17 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
         val allowScreenshots = sharedPreferences.getBoolean(getString(R.string.allow_screenshots_key), false)
         bottomAppBar = sharedPreferences.getBoolean(getString(R.string.bottom_app_bar_key), false)
         displayAdditionalAppBarIcons = sharedPreferences.getBoolean(getString(R.string.display_additional_app_bar_icons_key), false)
+        val displayUnderCutouts = sharedPreferences.getBoolean(getString(R.string.display_under_cutouts_key), false)
+
+        // Display under cutouts if specified.  This must be done here as it doesn't appear to work correctly if handled after the app is fully initialized.
+        if (displayUnderCutouts) {
+            if (Build.VERSION.SDK_INT >= 30)
+                window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
+            else if (Build.VERSION.SDK_INT >= 28)
+                window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
+        }
 
-        // Get the theme entry values string array.
+        // Get the entry values string arrays.
         val appThemeEntryValuesStringArray = resources.getStringArray(R.array.app_theme_entry_values)
 
         // Get the current theme status.
@@ -533,7 +594,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
             tabLayout = findViewById(R.id.tablayout)
             swipeRefreshLayout = findViewById(R.id.swiperefreshlayout)
             webViewViewPager2 = findViewById(R.id.webview_viewpager2)
-            val navigationView = findViewById<NavigationView>(R.id.navigationview)
+            navigationView = findViewById(R.id.navigationview)
             bookmarksListView = findViewById(R.id.bookmarks_drawer_listview)
             bookmarksTitleTextView = findViewById(R.id.bookmarks_title_textview)
             bookmarksDrawerPinnedImageView = findViewById(R.id.bookmarks_drawer_pinned_imageview)
@@ -545,6 +606,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
             // Get handles for the navigation menu items.
             navigationBackMenuItem = navigationMenu.findItem(R.id.back)
             navigationForwardMenuItem = navigationMenu.findItem(R.id.forward)
+            navigationScrollToBottomMenuItem = navigationMenu.findItem(R.id.scroll_to_bottom)
             navigationHistoryMenuItem = navigationMenu.findItem(R.id.history)
             navigationRequestsMenuItem = navigationMenu.findItem(R.id.requests)
 
@@ -567,9 +629,6 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
             urlRelativeLayout = findViewById(R.id.url_relativelayout)
             urlEditText = findViewById(R.id.url_edittext)
 
-            // Create the hamburger icon at the start of the AppBar.
-            actionBarDrawerToggle = ActionBarDrawerToggle(this, drawerLayout, toolbar, R.string.open_navigation_drawer, R.string.close_navigation_drawer)
-
             // Initially disable the sliding drawers.  They will be enabled once the filter lists are loaded.
             drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
 
@@ -577,9 +636,9 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
             drawerLayout.visibility = View.GONE
 
             // Initialize the WebView state adapter.
-            webViewStateAdapter = WebViewStateAdapter(this)
+            webViewStateAdapter = WebViewStateAdapter(this, bottomAppBar)
 
-            // Set the pager adapter on the web view pager.
+            // Set the WebView pager adapter.
             webViewViewPager2.adapter = webViewStateAdapter
 
             // Store up to 100 tabs in memory.
@@ -599,6 +658,15 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
             // Update the bookmarks drawer pinned image view.
             updateBookmarksDrawerPinnedImageView()
 
+            // Get the default favorite icon drawable.
+            val favoriteIconDrawable = AppCompatResources.getDrawable(this, R.drawable.world)
+
+            // Cast the favorite icon drawable to a bitmap drawable.
+            val favoriteIconBitmapDrawable = (favoriteIconDrawable as BitmapDrawable?)!!
+
+            // Store the default favorite icon bitmap.
+            defaultFavoriteIconBitmap = favoriteIconBitmapDrawable.bitmap
+
             // Initialize the app.
             initializeApp()
 
@@ -620,17 +688,8 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                         exitFullScreenVideo()
                         // It shouldn't be possible for the currentWebView to be null, but crash logs indicate it sometimes happens.
                     } else if (currentWebView != null && currentWebView!!.canGoBack()) {  // There is at least one item in the current WebView history.
-                        // Get the current web back forward list.
-                        val webBackForwardList = currentWebView!!.copyBackForwardList()
-
-                        // Get the previous entry URL.
-                        val previousUrl = webBackForwardList.getItemAtIndex(webBackForwardList.currentIndex - 1).url
-
-                        // Apply the domain settings.
-                        applyDomainSettings(currentWebView!!, previousUrl, resetTab = false, reloadWebsite = false, loadUrl = false)
-
-                        // Go back.
-                        currentWebView!!.goBack()
+                        // Navigate back one page.
+                        navigateHistory(-1)
                     } else {  // Close the current tab.
                         // A view is required because the method is also called by an XML `onClick`.
                         closeTab(null)
@@ -649,19 +708,18 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
         }
     }
 
-    public override fun onPostCreate(savedInstanceState: Bundle?) {
-        // Run the default commands.
-        super.onPostCreate(savedInstanceState)
-
-        // Sync the state of the DrawerToggle after the default `onRestoreInstanceState()` has finished.  This creates the navigation drawer icon.
-        // If the app is restarting to change the app theme the action bar drawer toggle will not yet be populated.
-        actionBarDrawerToggle?.syncState()
-    }
-
     override fun onNewIntent(intent: Intent) {
         // Run the default commands.
         super.onNewIntent(intent)
 
+        // Close the navigation drawer if it is open.
+        if (drawerLayout.isDrawerVisible(GravityCompat.START))
+            drawerLayout.closeDrawer(GravityCompat.START)
+
+        // Close the bookmarks drawer if it is open.
+        if (drawerLayout.isDrawerVisible(GravityCompat.END))
+            drawerLayout.closeDrawer(GravityCompat.END)
+
         // Get the information from the intent.
         val intentAction = intent.action
         val intentUriData = intent.data
@@ -704,26 +762,13 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                     loadingNewIntent = true
 
                     // Add a new tab.
-                    addNewTab(url!!, true)
+                    addNewPage(url!!, adjacent = false, moveToTab = true)
                 } else {  // Load the URL in the current tab.
                     // Make it so.
                     loadUrl(currentWebView!!, url!!)
                 }
-
-                // Close the navigation drawer if it is open.
-                if (drawerLayout.isDrawerVisible(GravityCompat.START))
-                    drawerLayout.closeDrawer(GravityCompat.START)
-
-                // Close the bookmarks drawer if it is open.
-                if (drawerLayout.isDrawerVisible(GravityCompat.END))
-                    drawerLayout.closeDrawer(GravityCompat.END)
             }
         } else {  // The app has been restarted.
-            // If the new intent will open a new tab, set the saved tab position to be the size of the saved state array list.
-            // The tab position is 0 based, meaning the at the new tab will be the tab position that is restored.
-            if ((intentUriData != null) || (intentStringExtra != null) || isWebSearch)
-                savedTabPosition = savedStateArrayList!!.size
-
             // Replace the intent that started the app with this one.  This will load the tab after the others have been restored.
             setIntent(intent)
         }
@@ -945,6 +990,29 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
         super.onDestroy()
     }
 
+    override fun onConfigurationChanged(newConfig: Configuration) {
+        // Run the default commands.
+        super.onConfigurationChanged(newConfig)
+
+        // Reset the navigation drawer first view flag.
+        navigationDrawerFirstView = true
+
+        // Get the current page.
+        val currentPage = webViewViewPager2.currentItem
+
+        // Toggle the pages if there is more than one so that the view pager will recalculate their size.
+        if (currentPage > 0) {
+            // Switch to the previous page after 25 milliseconds.
+            webViewViewPager2.postDelayed ({ webViewViewPager2.currentItem = (currentPage - 1) }, 25)
+
+            // Switch back to the current page after the view pager has quiesced (which we are deciding should be 25 milliseconds).
+            webViewViewPager2.postDelayed ({ webViewViewPager2.currentItem = currentPage }, 25)
+        }
+
+        // Scroll to the current tab position after 25 milliseconds.
+        tabLayout.postDelayed ({ tabLayout.setScrollPosition(currentPage, 0F, false, false) }, 25)
+    }
+
     override fun onCreateOptionsMenu(menu: Menu): Boolean {
         // Inflate the menu.  This adds items to the app bar if it is present.
         menuInflater.inflate(R.menu.webview_options_menu, menu)
@@ -955,11 +1023,9 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
         val optionsBookmarksMenuItem = menu.findItem(R.id.bookmarks)
         optionsCookiesMenuItem = menu.findItem(R.id.cookies)
         optionsDomStorageMenuItem = menu.findItem(R.id.dom_storage)
-        optionsSaveFormDataMenuItem = menu.findItem(R.id.save_form_data) // Form data can be removed once the minimum API >= 26.
         optionsClearDataMenuItem = menu.findItem(R.id.clear_data)
         optionsClearCookiesMenuItem = menu.findItem(R.id.clear_cookies)
         optionsClearDomStorageMenuItem = menu.findItem(R.id.clear_dom_storage)
-        optionsClearFormDataMenuItem = menu.findItem(R.id.clear_form_data) // Form data can be removed once the minimum API >= 26.
         optionsEasyListMenuItem = menu.findItem(R.id.easylist)
         optionsEasyPrivacyMenuItem = menu.findItem(R.id.easyprivacy)
         optionsFanboysAnnoyanceListMenuItem = menu.findItem(R.id.fanboys_annoyance_list)
@@ -984,7 +1050,6 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
         optionsUserAgentFirefoxOnWindowsMenuItem = menu.findItem(R.id.user_agent_firefox_on_windows)
         optionsUserAgentChromeOnWindowsMenuItem = menu.findItem(R.id.user_agent_chrome_on_windows)
         optionsUserAgentEdgeOnWindowsMenuItem = menu.findItem(R.id.user_agent_edge_on_windows)
-        optionsUserAgentInternetExplorerOnWindowsMenuItem = menu.findItem(R.id.user_agent_internet_explorer_on_windows)
         optionsUserAgentSafariOnMacosMenuItem = menu.findItem(R.id.user_agent_safari_on_macos)
         optionsUserAgentCustomMenuItem = menu.findItem(R.id.user_agent_custom)
         optionsSwipeToRefreshMenuItem = menu.findItem(R.id.swipe_to_refresh)
@@ -992,21 +1057,12 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
         optionsDisplayImagesMenuItem = menu.findItem(R.id.display_images)
         optionsDarkWebViewMenuItem = menu.findItem(R.id.dark_webview)
         optionsFontSizeMenuItem = menu.findItem(R.id.font_size)
+        optionsViewSourceMenuItem = menu.findItem(R.id.view_source)
         optionsAddOrEditDomainMenuItem = menu.findItem(R.id.add_or_edit_domain)
 
         // Set the initial status of the privacy icons.  `false` does not call `invalidateOptionsMenu` as the last step.
         updatePrivacyIcons(false)
 
-        // Only display the form data menu items if the API < 26.
-        optionsSaveFormDataMenuItem.isVisible = Build.VERSION.SDK_INT < 26
-        optionsClearFormDataMenuItem.isVisible = 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.
-        optionsClearFormDataMenuItem.isEnabled = Build.VERSION.SDK_INT < 26
-
-        // Only display the dark WebView menu item if the API >= 29.
-        optionsDarkWebViewMenuItem.isVisible = Build.VERSION.SDK_INT >= 29
-
         // 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) {  // Display the additional icons.
             optionsRefreshMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS)
@@ -1023,7 +1079,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
             // Set the title.
             optionsRefreshMenuItem.setTitle(R.string.stop)
 
-            // Set the icon if it is displayed in the app bar.  Once the minimum API is >= 26, the blue and black icons can be combined with a tint list.
+            // Set the icon if it is displayed in the app bar.
             if (displayAdditionalAppBarIcons)
                 optionsRefreshMenuItem.setIcon(R.drawable.close_blue)
         }
@@ -1056,8 +1112,6 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
 
             // Set the status of the menu item checkboxes.
             optionsDomStorageMenuItem.isChecked = currentWebView!!.settings.domStorageEnabled
-            @Suppress("DEPRECATION")
-            optionsSaveFormDataMenuItem.isChecked = currentWebView!!.settings.saveFormData // Form data can be removed once the minimum API >= 26.
             optionsEasyListMenuItem.isChecked = currentWebView!!.easyListEnabled
             optionsEasyPrivacyMenuItem.isChecked = currentWebView!!.easyPrivacyEnabled
             optionsFanboysAnnoyanceListMenuItem.isChecked = currentWebView!!.fanboysAnnoyanceListEnabled
@@ -1069,13 +1123,13 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
             optionsWideViewportMenuItem.isChecked = currentWebView!!.settings.useWideViewPort
             optionsDisplayImagesMenuItem.isChecked = currentWebView!!.settings.loadsImagesAutomatically
 
-            // Initialize the display names for the filter lists with the number of blocked requests.
+            // Set the display names for the filter lists with the number of blocked requests.
             optionsFilterListsMenuItem.title = getString(R.string.filterlists) + " - " + currentWebView!!.getRequestsCount(BLOCKED_REQUESTS)
             optionsEasyListMenuItem.title = currentWebView!!.getRequestsCount(EASYLIST).toString() + " - " + getString(R.string.easylist)
             optionsEasyPrivacyMenuItem.title = currentWebView!!.getRequestsCount(EASYPRIVACY).toString() + " - " + getString(R.string.easyprivacy)
             optionsFanboysAnnoyanceListMenuItem.title = currentWebView!!.getRequestsCount(FANBOYS_ANNOYANCE_LIST).toString() + " - " + getString(R.string.fanboys_annoyance_list)
             optionsFanboysSocialBlockingListMenuItem.title = currentWebView!!.getRequestsCount(FANBOYS_SOCIAL_BLOCKING_LIST).toString() + " - " + getString(R.string.fanboys_social_blocking_list)
-            optionsUltraListMenuItem.title = currentWebView!!.getRequestsCount(ULTRALIST).toString() + " - " + getString(R.string.ultralist)
+            optionsUltraListMenuItem.title = currentWebView!!.getRequestsCount(com.stoutner.privacybrowser.views.ULTRALIST).toString() + " - " + getString(R.string.ultralist)
             optionsUltraPrivacyMenuItem.title = currentWebView!!.getRequestsCount(ULTRAPRIVACY).toString() + " - " + getString(R.string.ultraprivacy)
             optionsBlockAllThirdPartyRequestsMenuItem.title = currentWebView!!.getRequestsCount(THIRD_PARTY_REQUESTS).toString() + " - " + getString(R.string.block_all_third_party_requests)
 
@@ -1088,9 +1142,15 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
             // Enable dark WebView if night mode is enabled.
             optionsDarkWebViewMenuItem.isEnabled = (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES)
 
-            // Set the checkbox status for dark WebView if the device is running API >= 29 and algorithmic darkening is supported.
-            if ((Build.VERSION.SDK_INT >= 29) && WebViewFeature.isFeatureSupported(WebViewFeature.ALGORITHMIC_DARKENING))
+            // Set the checkbox status for dark WebView if algorithmic darkening is supported.
+            if (WebViewFeature.isFeatureSupported(WebViewFeature.ALGORITHMIC_DARKENING))
                 optionsDarkWebViewMenuItem.isChecked = WebSettingsCompat.isAlgorithmicDarkeningAllowed(currentWebView!!.settings)
+
+            // Set the view source title according to the current URL.
+            if (currentWebView!!.currentUrl.startsWith("view-source:"))
+                optionsViewSourceMenuItem.title = getString(R.string.view_rendered_website)
+            else
+                optionsViewSourceMenuItem.title = getString(R.string.view_source)
         }
 
         // Set the cookies menu item checked status.
@@ -1121,18 +1181,8 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
         // Enable Clear DOM Storage if there is any.
         optionsClearDomStorageMenuItem.isEnabled = localStorageDirectoryNumberOfFiles > 0 || indexedDBDirectoryNumberOfFiles > 0
 
-        // Enable Clear Form Data is there is any.  This can be removed once the minimum API >= 26.
-        if (Build.VERSION.SDK_INT < 26) {
-            // Get the WebView database.
-            val webViewDatabase = WebViewDatabase.getInstance(this)
-
-            // Enable the clear form data menu item if there is anything to clear.
-            @Suppress("DEPRECATION")
-            optionsClearFormDataMenuItem.isEnabled = webViewDatabase.hasFormData()
-        }
-
         // Enable Clear Data if any of the submenu items are enabled.
-        optionsClearDataMenuItem.isEnabled = (optionsClearCookiesMenuItem.isEnabled || optionsClearDomStorageMenuItem.isEnabled || optionsClearFormDataMenuItem.isEnabled)
+        optionsClearDataMenuItem.isEnabled = (optionsClearCookiesMenuItem.isEnabled || optionsClearDomStorageMenuItem.isEnabled)
 
         // Disable Fanboy's Social Blocking List menu item if Fanboy's Annoyance List is checked.
         optionsFanboysSocialBlockingListMenuItem.isEnabled = !optionsFanboysAnnoyanceListMenuItem.isChecked
@@ -1254,15 +1304,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                 optionsUserAgentEdgeOnWindowsMenuItem.isChecked = true
             }
 
-            resources.getStringArray(R.array.user_agent_data)[10] -> {  // Internet Explorer on Windows.
-                // Update the user agent menu item title.
-                optionsUserAgentMenuItem.title = getString(R.string.options_user_agent) + " - " + getString(R.string.user_agent_internet_explorer_on_windows)
-
-                // Select the Internet on Windows radio box.
-                optionsUserAgentInternetExplorerOnWindowsMenuItem.isChecked = true
-            }
-
-            resources.getStringArray(R.array.user_agent_data)[11] -> {  // Safari on macOS.
+            resources.getStringArray(R.array.user_agent_data)[10] -> {  // Safari on macOS.
                 // Update the user agent menu item title.
                 optionsUserAgentMenuItem.title = getString(R.string.options_user_agent) + " - " + getString(R.string.user_agent_safari_on_macos)
 
@@ -1384,32 +1426,6 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                 true
             }
 
-            R.id.save_form_data -> {  // Form data.  This can be removed once the minimum API >= 26.
-                // Switch the status of saveFormDataEnabled.
-                @Suppress("DEPRECATION")
-                currentWebView!!.settings.saveFormData = !currentWebView!!.settings.saveFormData
-
-                // Update the menu checkbox.
-                @Suppress("DEPRECATION")
-                menuItem.isChecked = currentWebView!!.settings.saveFormData
-
-                // Display a snackbar.
-                @Suppress("DEPRECATION")
-                if (currentWebView!!.settings.saveFormData)
-                    Snackbar.make(webViewViewPager2, R.string.form_data_enabled, Snackbar.LENGTH_SHORT).show()
-                else
-                    Snackbar.make(webViewViewPager2, R.string.form_data_disabled, Snackbar.LENGTH_SHORT).show()
-
-                // Update the privacy icon.
-                updatePrivacyIcons(true)
-
-                // Reload the current WebView.
-                currentWebView!!.reload()
-
-                // Consume the event.
-                true
-            }
-
             R.id.clear_cookies -> {  // Clear cookies.
                 // Create a snackbar.
                 Snackbar.make(webViewViewPager2, R.string.cookies_deleted, Snackbar.LENGTH_LONG)
@@ -1485,28 +1501,6 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                 true
             }
 
-            R.id.clear_form_data -> {  // Clear form data.  This can be remove once the minimum API >= 26.
-                // Create a snackbar.
-                Snackbar.make(webViewViewPager2, R.string.form_data_deleted, Snackbar.LENGTH_LONG)
-                    .setAction(R.string.undo) {}  // Everything will be handled by `onDismissed()` below.
-                    .addCallback(object : Snackbar.Callback() {
-                        override fun onDismissed(snackbar: Snackbar, event: Int) {
-                            if (event != DISMISS_EVENT_ACTION) {  // The snackbar was dismissed without the undo button being pushed.
-                                // Get a handle for the webView database.
-                                val webViewDatabase = WebViewDatabase.getInstance(applicationContext)
-
-                                // Delete the form data.
-                                @Suppress("DEPRECATION")
-                                webViewDatabase.clearFormData()
-                            }
-                        }
-                    })
-                    .show()
-
-                // Consume the event.
-                true
-            }
-
             R.id.easylist -> {  // EasyList.
                 // Toggle the EasyList status.
                 currentWebView!!.easyListEnabled = !currentWebView!!.easyListEnabled
@@ -1762,20 +1756,9 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                 true
             }
 
-            R.id.user_agent_internet_explorer_on_windows -> {  // User Agent - Internet Explorer on Windows.
-                // Update the user agent.
-                currentWebView!!.settings.userAgentString = resources.getStringArray(R.array.user_agent_data)[10]
-
-                // Reload the current WebView.
-                currentWebView!!.reload()
-
-                // Consume the event.
-                true
-            }
-
             R.id.user_agent_safari_on_macos -> {  // User Agent - Safari on macOS.
                 // Update the user agent.
-                currentWebView!!.settings.userAgentString = resources.getStringArray(R.array.user_agent_data)[11]
+                currentWebView!!.settings.userAgentString = resources.getStringArray(R.array.user_agent_data)[10]
 
                 // Reload the current WebView.
                 currentWebView!!.reload()
@@ -1847,7 +1830,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
 
             R.id.dark_webview -> {  // Dark WebView.
                 // Toggle dark WebView if supported.
-                if ((Build.VERSION.SDK_INT >= 29) && WebViewFeature.isFeatureSupported(WebViewFeature.ALGORITHMIC_DARKENING))
+                if (WebViewFeature.isFeatureSupported(WebViewFeature.ALGORITHMIC_DARKENING))
                     WebSettingsCompat.setAlgorithmicDarkeningAllowed(currentWebView!!.settings, !WebSettingsCompat.isAlgorithmicDarkeningAllowed(currentWebView!!.settings)
                 )
 
@@ -1871,9 +1854,6 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                     // Set the focus on the find on page edit text.
                     findOnPageEditText.requestFocus()
 
-                    // Get a handle for the input method manager.
-                    val inputMethodManager = (getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager)
-
                     // Display the keyboard.  `0` sets no input flags.
                     inputMethodManager.showSoftInput(findOnPageEditText, 0)
                 }, 200)
@@ -1899,7 +1879,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
             R.id.save_url -> {  // Save URL.
                 // Check the download preference.
                 if (downloadWithExternalApp)  // Download with an external app.
-                    downloadUrlWithExternalApp(currentWebView!!.currentUrl)
+                    saveWithExternalApp(currentWebView!!.currentUrl)
                 else  // Handle the download inside of Privacy Browser.  The dialog will be displayed once the file size and the content disposition have been acquired.
                     PrepareSaveDialogCoroutine.prepareSaveDialog(this, supportFragmentManager, currentWebView!!.currentUrl, currentWebView!!.settings.userAgentString, currentWebView!!.acceptCookies)
 
@@ -1908,8 +1888,8 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
             }
 
             R.id.save_archive -> {
-                // Open the file picker with a default file name built from the current domain name.
-                saveWebpageArchiveActivityResultLauncher.launch(currentWebView!!.currentDomainName + ".mht")
+                // Open the file picker with a default file name built from the website title.
+                saveWebpageArchiveActivityResultLauncher.launch(currentWebView!!.title + ".mht")
 
                 // Consume the event.
                 true
@@ -1935,15 +1915,29 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
             }
 
             R.id.view_source -> {  // View source.
-                // Create an intent to launch the view source activity.
-                val viewSourceIntent = Intent(this, ViewSourceActivity::class.java)
+                // Open a new tab according to the current URL.
+                if (currentWebView!!.currentUrl.startsWith("view-source:")) {  // The source is currently viewed.
+                    // Open the rendered website in a new tab.
+                    addNewPage(currentWebView!!.currentUrl.substring(12, currentWebView!!.currentUrl.length), true, moveToTab = true)
+                } else {  // The rendered website is currently viewed.
+                    // Open the source in a new tab.
+                    addNewPage("view-source:${currentWebView!!.currentUrl}", adjacent = true, moveToTab = true)
+                }
+
+                // Consume the event.
+                true
+            }
+
+            R.id.view_headers -> {  // View headers.
+                // Create an intent to launch the view headers activity.
+                val viewHeadersIntent = Intent(this, ViewHeadersActivity::class.java)
 
                 // Add the variables to the intent.
-                viewSourceIntent.putExtra(CURRENT_URL, currentWebView!!.url)
-                viewSourceIntent.putExtra(USER_AGENT, currentWebView!!.settings.userAgentString)
+                viewHeadersIntent.putExtra(CURRENT_URL, currentWebView!!.url)
+                viewHeadersIntent.putExtra(USER_AGENT, currentWebView!!.settings.userAgentString)
 
                 // Make it so.
-                startActivity(viewSourceIntent)
+                startActivity(viewHeadersIntent)
 
                 // Consume the event.
                 true
@@ -2012,7 +2006,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
             }
 
             R.id.add_or_edit_domain -> {  // Add or edit domain.
-                // Reapply the domain settings on returning to `MainWebViewActivity`.
+                // Reapply the domain settings on returning to the main WebView activity.
                 reapplyDomainSettingsOnRestart = true
 
                 // Check if domain settings are currently applied.
@@ -2023,7 +2017,6 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                     // Add the extra information to the intent.
                     domainsIntent.putExtra(LOAD_DOMAIN, currentWebView!!.domainSettingsDatabaseId)
                     domainsIntent.putExtra(CLOSE_ON_BACK, true)
-                    domainsIntent.putExtra(CURRENT_URL, currentWebView!!.url)
                     domainsIntent.putExtra(CURRENT_IP_ADDRESSES, currentWebView!!.currentIpAddresses)
 
                     // Get the current certificate.
@@ -2061,8 +2054,105 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                     // Get the current domain from the URI.  Use an empty string if it is null.
                     val currentDomain = currentUri.host?: ""
 
+                    // Get the current settings status.
+                    val javaScriptInt = calculateSettingsInt(currentWebView!!.settings.javaScriptEnabled, sharedPreferences.getBoolean(getString(R.string.javascript_key), false))
+                    val cookiesInt = calculateSettingsInt(currentWebView!!.acceptCookies, sharedPreferences.getBoolean(getString(R.string.cookies_key), false))
+                    val domStorageInt = calculateSettingsInt(currentWebView!!.settings.domStorageEnabled, sharedPreferences.getBoolean(getString(R.string.dom_storage_key), false))
+                    val easyListInt = calculateSettingsInt(currentWebView!!.easyListEnabled, sharedPreferences.getBoolean(getString(R.string.easylist_key), true))
+                    val easyPrivacyInt = calculateSettingsInt(currentWebView!!.easyPrivacyEnabled, sharedPreferences.getBoolean(getString(R.string.easyprivacy_key), true))
+                    val fanboysAnnoyanceListInt = calculateSettingsInt(currentWebView!!.fanboysAnnoyanceListEnabled, sharedPreferences.getBoolean(getString(R.string.fanboys_annoyance_list_key), true))
+                    val fanboysSocialBlockingListInt = calculateSettingsInt(currentWebView!!.fanboysSocialBlockingListEnabled, sharedPreferences.getBoolean(getString(R.string.fanboys_social_blocking_list_key), true))
+                    val ultraListInt = calculateSettingsInt(currentWebView!!.ultraListEnabled, sharedPreferences.getBoolean(getString(R.string.ultralist_key), true))
+                    val ultraPrivacyInt = calculateSettingsInt(currentWebView!!.ultraPrivacyEnabled, sharedPreferences.getBoolean(getString(R.string.ultraprivacy_key), true))
+                    val blockAllThirdPartyRequestsInt = calculateSettingsInt(currentWebView!!.blockAllThirdPartyRequests, sharedPreferences.getBoolean(getString(R.string.block_all_third_party_requests_key), true))
+                    val swipeToRefreshInt = calculateSettingsInt(currentWebView!!.swipeToRefresh, sharedPreferences.getBoolean(getString(R.string.swipe_to_refresh_key), true))
+                    val wideViewportInt = calculateSettingsInt(currentWebView!!.settings.useWideViewPort, sharedPreferences.getBoolean(getString(R.string.wide_viewport_key), true))
+                    val displayImagesInt = calculateSettingsInt(currentWebView!!.settings.loadsImagesAutomatically, sharedPreferences.getBoolean(getString(R.string.display_webpage_images_key), true))
+
+                    // Get the current user agent string.
+                    val currentUserAgentString = currentWebView!!.settings.userAgentString
+
+                    // Get the user agent string array position.
+                    val userAgentStringArrayPosition = userAgentDataArrayAdapter.getPosition(currentUserAgentString)
+
+                    // Set the user agent name.
+                    val userAgentName = if ((userAgentStringArrayPosition >= 0) && (defaultUserAgentName == userAgentNamesArray[userAgentStringArrayPosition])) {  // The system default user agent is in use.
+                        getString(R.string.system_default_user_agent)
+                    } else {  // An on-the-fly user agent is being used (or the WebView default user agent is applied).
+                        when (userAgentStringArrayPosition) {
+                            UNRECOGNIZED_USER_AGENT -> { // The user agent is unrecognized.
+                                if (currentUserAgentString == webViewDefaultUserAgent) {  // The WebView default user agent is being used.
+                                    if (defaultUserAgentName == getString(R.string.webview_default)) {  // The WebView default user agent is the system default.
+                                        // Set the user agent name to be the system default.
+                                        getString(R.string.system_default_user_agent)
+                                    } else {  // The WebView default user agent is set as an on-the-fly setting.
+                                        // Set the default user agent name.
+                                        getString(R.string.webview_default)
+                                    }
+                                } else {  // A custom user agent is being used.
+                                    if (defaultUserAgentName == getString(R.string.custom_user_agent_non_translatable)) {  // The system custom user agent is in use.
+                                        // Set the user agent name to be the system default.
+                                        getString(R.string.system_default_user_agent)
+                                    } else {  // An on-the-fly custom user agent is in use.
+                                        // Store the user agent as currently applied.
+                                        currentUserAgentString
+                                    }
+                                }
+                            }
+
+                            else ->  // Store the standard user agent name.
+                                userAgentNamesArray[userAgentStringArrayPosition]
+                        }
+                    }
+
+                    // Get the current text zoom integer.
+                    val textZoomInt = currentWebView!!.settings.textZoom
+
+                    // Set the font size integer.
+                    val fontSizeInt = if (textZoomInt == defaultFontSizeString.toInt())  // The current system default is used, which is encoded as a zoom of `0`.
+                        SYSTEM_DEFAULT
+                    else  // A custom font size is used.
+                        textZoomInt
+
+                    // Get the current WebView dark theme status.
+                    val webViewDarkThemeCurrentlyEnabled = if (WebViewFeature.isFeatureSupported(WebViewFeature.ALGORITHMIC_DARKENING))  // Algorithmic darkening is supported.
+                        WebSettingsCompat.isAlgorithmicDarkeningAllowed(currentWebView!!.settings)
+                    else  // Algorithmic darkening is not supported.
+                        false
+
+                    // Get the default WebView dark theme setting.
+                    val defaultWebViewDarkThemeEnabled = if (WebViewFeature.isFeatureSupported(WebViewFeature.ALGORITHMIC_DARKENING)) {  // Algorithmic darkening is supported.
+                        when (defaultWebViewTheme) {
+                            webViewThemeEntryValuesStringArray[1] ->  // The dark theme is disabled by default.
+                                false
+
+                            webViewThemeEntryValuesStringArray[2] ->  // The dark theme is enabled by default.
+                                true
+
+                            else -> {  // The system default theme is selected.
+                                // Get the current app theme status.
+                                val currentAppThemeStatus = resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
+
+                                // Check if the current app theme is dark.
+                                currentAppThemeStatus == Configuration.UI_MODE_NIGHT_YES
+                            }
+                        }
+                    } else {  // Algorithmic darkening is not supported.
+                        false
+                    }
+
+                    // Set the WebView theme int.
+                    val webViewThemeInt = if (webViewDarkThemeCurrentlyEnabled == defaultWebViewDarkThemeEnabled)  // The current WebView theme matches the default.
+                        SYSTEM_DEFAULT
+                    else if (webViewDarkThemeCurrentlyEnabled)  // The current WebView theme is dark and that is not the default.
+                        DARK_THEME
+                    else  // The current WebView theme is light and that is not the default.
+                        LIGHT_THEME
+
                     // Create the domain and store the database ID.
-                    val newDomainDatabaseId = domainsDatabaseHelper!!.addDomain(currentDomain)
+                    val newDomainDatabaseId = domainsDatabaseHelper!!.addDomain(currentDomain, javaScriptInt, cookiesInt, domStorageInt, userAgentName, easyListInt, easyPrivacyInt,
+                                                                                fanboysAnnoyanceListInt, fanboysSocialBlockingListInt, ultraListInt, ultraPrivacyInt, blockAllThirdPartyRequestsInt, fontSizeInt,
+                                                                                swipeToRefreshInt, webViewThemeInt, wideViewportInt, displayImagesInt)
 
                     // Create an intent to launch the domains activity.
                     val domainsIntent = Intent(this, DomainsActivity::class.java)
@@ -2070,7 +2160,6 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                     // Add the extra information to the intent.
                     domainsIntent.putExtra(LOAD_DOMAIN, newDomainDatabaseId)
                     domainsIntent.putExtra(CLOSE_ON_BACK, true)
-                    domainsIntent.putExtra(CURRENT_URL, currentWebView!!.url)
                     domainsIntent.putExtra(CURRENT_IP_ADDRESSES, currentWebView!!.currentIpAddresses)
 
                     // Get the current certificate.
@@ -2130,34 +2219,25 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
             R.id.back -> {  // Back.
                 // Check if the WebView can go back.
                 if (currentWebView!!.canGoBack()) {
-                    // Get the current web back forward list.
-                    val webBackForwardList = currentWebView!!.copyBackForwardList()
-
-                    // Get the previous entry URL.
-                    val previousUrl = webBackForwardList.getItemAtIndex(webBackForwardList.currentIndex - 1).url
-
-                    // Apply the domain settings.
-                    applyDomainSettings(currentWebView!!, previousUrl, resetTab = false, reloadWebsite = false, loadUrl = false)
-
-                    // Load the previous website in the history.
-                    currentWebView!!.goBack()
+                    // Navigate back one page.
+                    navigateHistory(-1)
                 }
             }
 
             R.id.forward -> {  // Forward.
                 // Check if the WebView can go forward.
                 if (currentWebView!!.canGoForward()) {
-                    // Get the current web back forward list.
-                    val webBackForwardList = currentWebView!!.copyBackForwardList()
-
-                    // Get the next entry URL.
-                    val nextUrl = webBackForwardList.getItemAtIndex(webBackForwardList.currentIndex + 1).url
-
-                    // Apply the domain settings.
-                    applyDomainSettings(currentWebView!!, nextUrl, resetTab = false, reloadWebsite = false, loadUrl = false)
+                    // Navigate forward one page.
+                    navigateHistory(+1)
+                }
+            }
 
-                    // Load the next website in the history.
-                    currentWebView!!.goForward()
+            R.id.scroll_to_bottom -> {  // Scroll to Bottom.
+                // Check if the WebView is scrolled to the top.
+                if (currentWebView!!.scrollY == 0) {  // The WebView is at the top; scroll to the bottom.  Using a large Y number is more efficient than trying to calculate the exact WebView length.
+                    currentWebView!!.scrollTo(0, 1_000_000_000)
+                } else {  // The WebView is not at the top; scroll to the top.
+                    currentWebView!!.scrollTo(0, 0)
                 }
             }
 
@@ -2246,7 +2326,6 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                 val domainsIntent = Intent(this, DomainsActivity::class.java)
 
                 // Add the extra information to the intent.
-                domainsIntent.putExtra(CURRENT_URL, currentWebView!!.url)
                 domainsIntent.putExtra(CURRENT_IP_ADDRESSES, currentWebView!!.currentIpAddresses)
 
                 // Get the current certificate.
@@ -2372,7 +2451,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                 // Add an open in new tab entry.
                 contextMenu.add(R.string.open_in_new_tab).setOnMenuItemClickListener {
                     // Load the link URL in a new tab and move to it.
-                    addNewTab(linkUrl, true)
+                    addNewPage(linkUrl, adjacent = true, moveToTab = true)
 
                     // Consume the event.
                     true
@@ -2381,7 +2460,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                 // Add an open in background entry.
                 contextMenu.add(R.string.open_in_background).setOnMenuItemClickListener {
                     // Load the link URL in a new tab but do not move to it.
-                    addNewTab(linkUrl, false)
+                    addNewPage(linkUrl, adjacent = true, moveToTab = false)
 
                     // Consume the event.
                     true
@@ -2421,7 +2500,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                 contextMenu.add(R.string.save_url).setOnMenuItemClickListener {
                     // Check the download preference.
                     if (downloadWithExternalApp)  // Download with an external app.
-                        downloadUrlWithExternalApp(linkUrl)
+                        saveWithExternalApp(linkUrl)
                     else  // Handle the download inside of Privacy Browser.  The dialog will be displayed once the file size and the content disposition have been acquired.
                         PrepareSaveDialogCoroutine.prepareSaveDialog(this, supportFragmentManager, linkUrl, currentWebView!!.settings.userAgentString, currentWebView!!.acceptCookies)
 
@@ -2429,6 +2508,27 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                     true
                 }
 
+                // Add a Share URL entry.
+                contextMenu.add(R.string.share_url).setOnMenuItemClickListener {
+                    // Create the share intent.
+                    val shareUrlIntent = Intent(Intent.ACTION_SEND)
+
+                    // Add the URL to the intent.
+                    shareUrlIntent.putExtra(Intent.EXTRA_TEXT, linkUrl)
+
+                    // Set the MIME type.
+                    shareUrlIntent.type = "text/plain"
+
+                    // Set the intent to open in a new task.
+                    shareUrlIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+
+                    //Make it so.
+                    startActivity(Intent.createChooser(shareUrlIntent, getString(R.string.share_url)))
+
+                    // Consume the event.
+                    true
+                }
+
                 // Add an empty cancel entry, which by default closes the context menu.
                 contextMenu.add(R.string.cancel)
             }
@@ -2447,7 +2547,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                 // Add an open in new tab entry.
                 contextMenu.add(R.string.open_image_in_new_tab).setOnMenuItemClickListener {
                     // Load the image in a new tab.
-                    addNewTab(imageUrl, true)
+                    addNewPage(imageUrl, adjacent = true, moveToTab = true)
 
                     // Consume the event.
                     true
@@ -2484,7 +2584,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                 contextMenu.add(R.string.save_image).setOnMenuItemClickListener {
                     // Check the download preference.
                     if (downloadWithExternalApp) {  // Download with an external app.
-                        downloadUrlWithExternalApp(imageUrl)
+                        saveWithExternalApp(imageUrl)
                     } else {  // Handle the download inside of Privacy Browser.  The dialog will be displayed once the file size and the content disposition have been acquired.
                         PrepareSaveDialogCoroutine.prepareSaveDialog(this, supportFragmentManager, imageUrl, currentWebView!!.settings.userAgentString, currentWebView!!.acceptCookies)
                     }
@@ -2505,6 +2605,27 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                     true
                 }
 
+                // Add a Share URL entry.
+                contextMenu.add(R.string.share_url).setOnMenuItemClickListener {
+                    // Create the share intent.
+                    val shareUrlIntent = Intent(Intent.ACTION_SEND)
+
+                    // Add the URL to the intent.
+                    shareUrlIntent.putExtra(Intent.EXTRA_TEXT, imageUrl)
+
+                    // Set the MIME type.
+                    shareUrlIntent.type = "text/plain"
+
+                    // Set the intent to open in a new task.
+                    shareUrlIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+
+                    //Make it so.
+                    startActivity(Intent.createChooser(shareUrlIntent, getString(R.string.share_url)))
+
+                    // Consume the event.
+                    true
+                }
+
                 // Add an empty cancel entry, which by default closes the context menu.
                 contextMenu.add(R.string.cancel)
             }
@@ -2532,7 +2653,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                 // Add an open in new tab entry.
                 contextMenu.add(R.string.open_in_new_tab).setOnMenuItemClickListener {
                     // Load the link URL in a new tab and move to it.
-                    addNewTab(linkUrl, true)
+                    addNewPage(linkUrl, adjacent = true, moveToTab = true)
 
                     // Consume the event.
                     true
@@ -2541,7 +2662,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                 // Add an open in background entry.
                 contextMenu.add(R.string.open_in_background).setOnMenuItemClickListener {
                     // Lod the link URL in a new tab but do not move to it.
-                    addNewTab(linkUrl, false)
+                    addNewPage(linkUrl, adjacent = true, moveToTab = false)
 
                     // Consume the event.
                     true
@@ -2550,7 +2671,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                 // Add an open image in new tab entry.
                 contextMenu.add(R.string.open_image_in_new_tab).setOnMenuItemClickListener {
                     // Load the image in a new tab and move to it.
-                    addNewTab(imageUrl, true)
+                    addNewPage(imageUrl, adjacent = true, moveToTab = true)
 
                     // Consume the event.
                     true
@@ -2587,7 +2708,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                 contextMenu.add(R.string.save_image).setOnMenuItemClickListener {
                     // Check the download preference.
                     if (downloadWithExternalApp)  // Download with an external app.
-                        downloadUrlWithExternalApp(imageUrl)
+                        saveWithExternalApp(imageUrl)
                     else  // Handle the download inside of Privacy Browser.  The dialog will be displayed once the file size and the content disposition have been acquired.
                         PrepareSaveDialogCoroutine.prepareSaveDialog(this, supportFragmentManager, imageUrl, currentWebView!!.settings.userAgentString, currentWebView!!.acceptCookies)
 
@@ -2595,6 +2716,27 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                     true
                 }
 
+                // Add a Share Image entry.
+                contextMenu.add(R.string.share_image).setOnMenuItemClickListener {
+                    // Create the share intent.
+                    val shareUrlIntent = Intent(Intent.ACTION_SEND)
+
+                    // Add the URL to the intent.
+                    shareUrlIntent.putExtra(Intent.EXTRA_TEXT, imageUrl)
+
+                    // Set the MIME type.
+                    shareUrlIntent.type = "text/plain"
+
+                    // Set the intent to open in a new task.
+                    shareUrlIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+
+                    //Make it so.
+                    startActivity(Intent.createChooser(shareUrlIntent, getString(R.string.share_url)))
+
+                    // Consume the event.
+                    true
+                }
+
                 // Add a copy URL entry.
                 contextMenu.add(R.string.copy_url).setOnMenuItemClickListener {
                     // Save the link URL in a clip data.
@@ -2611,7 +2753,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                 contextMenu.add(R.string.save_url).setOnMenuItemClickListener {
                     // Check the download preference.
                     if (downloadWithExternalApp)  // Download with an external app.
-                        downloadUrlWithExternalApp(linkUrl)
+                        saveWithExternalApp(linkUrl)
                     else  // Handle the download inside of Privacy Browser.  The dialog will be displayed once the file size and the content disposition have been acquired.
                         PrepareSaveDialogCoroutine.prepareSaveDialog(this, supportFragmentManager, linkUrl, currentWebView!!.settings.userAgentString, currentWebView!!.acceptCookies)
 
@@ -2619,6 +2761,27 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                     true
                 }
 
+                // Add a Share URL entry.
+                contextMenu.add(R.string.share_url).setOnMenuItemClickListener {
+                    // Create the share intent.
+                    val shareUrlIntent = Intent(Intent.ACTION_SEND)
+
+                    // Add the URL to the intent.
+                    shareUrlIntent.putExtra(Intent.EXTRA_TEXT, linkUrl)
+
+                    // Set the MIME type.
+                    shareUrlIntent.type = "text/plain"
+
+                    // Set the intent to open in a new task.
+                    shareUrlIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+
+                    //Make it so.
+                    startActivity(Intent.createChooser(shareUrlIntent, getString(R.string.share_url)))
+
+                    // Consume the event.
+                    true
+                }
+
                 // Add an empty cancel entry, which by default closes the context menu.
                 contextMenu.add(R.string.cancel)
             }
@@ -2674,39 +2837,104 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
     // The view parameter cannot be removed because it is called from the layout onClick.
     fun addTab(@Suppress("UNUSED_PARAMETER")view: View?) {
         // Add a new tab with a blank URL.
-        addNewTab("", true)
+        addNewPage(urlString = "", adjacent = true, moveToTab = true)
     }
 
-    private fun addNewTab(urlString: String, moveToTab: Boolean) {
+    private fun addNewPage(urlString: String, adjacent: Boolean, moveToTab: Boolean) {
         // Clear the focus from the URL edit text, so that it will be populated with the information from the new tab.
         urlEditText.clearFocus()
 
-        // Get the new page number.  The page numbers are 0 indexed, so the new page number will match the current count.
-        val newTabNumber = tabLayout.tabCount
+        // Add the new tab after the tab layout has quiesced.
+        // Otherwise, there can be problems when restoring a large number of tabs and processing a new intent at the same time.  <https://redmine.stoutner.com/issues/1136>
+        tabLayout.post {
+            // Get the new tab position.
+            val newTabPosition = if (adjacent)  // The new tab position is immediately to the right of the current tab position.
+                tabLayout.selectedTabPosition + 1
+            else  // The new tab position is at the end.  The tab positions are 0 indexed, so the new page number will match the current count.
+                tabLayout.tabCount
 
-        // Add a new tab.
-        tabLayout.addTab(tabLayout.newTab())
+            // Add the new WebView page.
+            webViewStateAdapter!!.addPage(newTabPosition, urlString)
 
-        // Get the new tab.
-        val newTab = tabLayout.getTabAt(newTabNumber)!!
+            // Add the new tab.
+            addNewTab(newTabPosition, moveToTab)
+        }
+    }
 
-        // Set a custom view on the new tab.
-        newTab.setCustomView(R.layout.tab_custom_view)
+    private fun addNewTab(newTabPosition: Int, moveToTab: Boolean) {
+        // Check to see if the new page is ready.
+        if (webViewStateAdapter!!.itemCount >= tabLayout.tabCount) {  // The new page is ready.
+            // Create a new tab.
+            val newTab = tabLayout.newTab()
 
-        // Add the new WebView page.
-        webViewStateAdapter!!.addPage(newTabNumber, webViewViewPager2, urlString, moveToTab)
+            // Set a custom view on the new tab.
+            newTab.setCustomView(R.layout.tab_custom_view)
 
-        // Show the app bar if it is at the bottom of the screen and the new tab is taking focus.
-        if (bottomAppBar && moveToTab && appBarLayout.translationY != 0f) {
-            // Animate the bottom app bar onto the screen.
-            objectAnimator = ObjectAnimator.ofFloat(appBarLayout, "translationY", 0f)
+            // Add the new tab.
+            tabLayout.addTab(newTab, newTabPosition, moveToTab)
 
-            // Make it so.
-            objectAnimator.start()
+            // Select the new tab if it is the first one.  For some odd reason, Android doesn't select the first tab if it is the only one, which causes problems with the new tab position logic above.
+            if (newTabPosition == 0)
+                tabLayout.selectTab(newTab)
+
+            // Scroll to the new tab position if moving to the new tab.
+            if (moveToTab)
+                tabLayout.post {
+                    tabLayout.setScrollPosition(newTabPosition, 0F, false, false)
+                }
+
+            // Show the app bar if it is at the bottom of the screen and the new tab is taking focus.
+            if (bottomAppBar && moveToTab && appBarLayout.translationY != 0f) {
+                // Animate the bottom app bar onto the screen.
+                objectAnimator = ObjectAnimator.ofFloat(appBarLayout, "translationY", 0f)
+
+                // Make it so.
+                objectAnimator.start()
+            }
+        } else {  // The new page is not ready.
+            // Create a new tab handler.
+            val newTabHandler = Handler(Looper.getMainLooper())
+
+            // Create a new tab runnable.
+            val newTabRunnable = Runnable {
+                // Create the new tab.
+                addNewTab(newTabPosition, moveToTab)
+            }
+
+            // Try adding the new tab again after 50 milliseconds.
+            newTabHandler.postDelayed(newTabRunnable, 50)
         }
     }
 
     private fun applyAppSettings() {
+        // Store the default preferences used in `applyDomainSettings()`.  These are done here so that expensive preference requests are not done each time a domain is loaded.
+        defaultJavaScript = sharedPreferences.getBoolean(getString(R.string.javascript_key), false)
+        defaultCookies = sharedPreferences.getBoolean(getString(R.string.cookies_key), false)
+        defaultDomStorage = sharedPreferences.getBoolean(getString(R.string.dom_storage_key), false)
+        defaultEasyList = sharedPreferences.getBoolean(getString(R.string.easylist_key), true)
+        defaultEasyPrivacy = sharedPreferences.getBoolean(getString(R.string.easyprivacy_key), true)
+        defaultFanboysAnnoyanceList = sharedPreferences.getBoolean(getString(R.string.fanboys_annoyance_list_key), true)
+        defaultFanboysSocialBlockingList = sharedPreferences.getBoolean(getString(R.string.fanboys_social_blocking_list_key), true)
+        defaultUltraList = sharedPreferences.getBoolean(getString(R.string.ultralist_key), true)
+        defaultUltraPrivacy = sharedPreferences.getBoolean(getString(R.string.ultraprivacy_key), true)
+        defaultBlockAllThirdPartyRequests = sharedPreferences.getBoolean(getString(R.string.block_all_third_party_requests_key), false)
+        defaultFontSizeString = sharedPreferences.getString(getString(R.string.font_size_key), getString(R.string.font_size_default_value))!!
+        defaultUserAgentName = sharedPreferences.getString(getString(R.string.user_agent_key), getString(R.string.user_agent_default_value))!!
+        defaultSwipeToRefresh = sharedPreferences.getBoolean(getString(R.string.swipe_to_refresh_key), true)
+        defaultWebViewTheme = sharedPreferences.getString(getString(R.string.webview_theme_key), getString(R.string.webview_theme_default_value))!!
+        defaultWideViewport = sharedPreferences.getBoolean(getString(R.string.wide_viewport_key), true)
+        defaultDisplayWebpageImages = sharedPreferences.getBoolean(getString(R.string.display_webpage_images_key), true)
+
+        // Get the string arrays.  These are done here so that expensive resource requests are not made each time a domain is loaded.
+        webViewThemeEntryValuesStringArray = resources.getStringArray(R.array.webview_theme_entry_values)
+        userAgentDataArray = resources.getStringArray(R.array.user_agent_data)
+        userAgentNamesArray = resources.getStringArray(R.array.user_agent_names)
+        val downloadProviderEntryValuesStringArray = resources.getStringArray(R.array.download_provider_entry_values)
+
+        // Get the user agent array adapters.  These are done here so that expensive resource requests are not made each time a domain is loaded.
+        userAgentDataArrayAdapter = ArrayAdapter.createFromResource(this, R.array.user_agent_data, R.layout.spinner_item)
+        userAgentNamesArrayAdapter = ArrayAdapter.createFromResource(this, R.array.user_agent_names, R.layout.spinner_item)
+
         // Store the values from the shared preferences in variables.
         incognitoModeEnabled = sharedPreferences.getBoolean(getString(R.string.incognito_mode_key), false)
         sanitizeTrackingQueries = sharedPreferences.getBoolean(getString(R.string.tracking_queries_key), true)
@@ -2714,8 +2942,11 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
         proxyMode = sharedPreferences.getString(getString(R.string.proxy_key), getString(R.string.proxy_default_value))!!
         fullScreenBrowsingModeEnabled = sharedPreferences.getBoolean(getString(R.string.full_screen_browsing_mode_key), false)
         hideAppBar = sharedPreferences.getBoolean(getString(R.string.hide_app_bar_key), true)
-        downloadWithExternalApp = sharedPreferences.getBoolean(getString(R.string.download_with_external_app_key), false)
-        scrollAppBar = sharedPreferences.getBoolean(getString(R.string.scroll_app_bar_key), true)
+        val downloadProvider = sharedPreferences.getString(getString(R.string.download_provider_key), getString(R.string.download_provider_default_value))!!
+        scrollAppBar = sharedPreferences.getBoolean(getString(R.string.scroll_app_bar_key), false)
+
+        // Determine if downloading should be handled by an external app.
+        downloadWithExternalApp = (downloadProvider == downloadProviderEntryValuesStringArray[2])
 
         // Apply the saved proxy mode if the app has been restarted.
         if (savedProxyMode != null) {
@@ -2861,7 +3092,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
             newHostName = ""
 
         // Apply the domain settings if a new domain is being loaded or if the new domain is blank.  This allows the user to set temporary settings for JavaScript, cookies, DOM storage, etc.
-        if (nestedScrollWebView.currentDomainName != newHostName || newHostName == "") {
+        if ((nestedScrollWebView.currentDomainName != newHostName) || (newHostName == "")) {  // A new domain is being loaded.
             // Set the new host name as the current domain name.
             nestedScrollWebView.currentDomainName = newHostName
 
@@ -2872,10 +3103,10 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
             nestedScrollWebView.clearPinnedSslCertificate()
             nestedScrollWebView.pinnedIpAddresses = ""
 
-            // Reset the favorite icon if specified.
+            // Reset the tab if specified.
             if (resetTab) {
                 // Initialize the favorite icon.
-                nestedScrollWebView.initializeFavoriteIcon()
+                nestedScrollWebView.resetFavoriteIcon()
 
                 // Get the current page position.
                 val currentPagePosition = webViewStateAdapter!!.getPositionForId(nestedScrollWebView.webViewFragmentId)
@@ -2892,8 +3123,12 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                     val tabFavoriteIconImageView = tabCustomView.findViewById<ImageView>(R.id.favorite_icon_imageview)
                     val tabTitleTextView = tabCustomView.findViewById<TextView>(R.id.title_textview)
 
+                    // Store the current values in case they need to be restored.
+                    nestedScrollWebView.previousFavoriteIconDrawable = tabFavoriteIconImageView.drawable
+                    nestedScrollWebView.previousWebpageTitle = tabTitleTextView.text.toString()
+
                     // Set the default favorite icon as the favorite icon for this tab.
-                    tabFavoriteIconImageView.setImageBitmap(Bitmap.createScaledBitmap(nestedScrollWebView.getFavoriteIcon(), 64, 64, true))
+                    tabFavoriteIconImageView.setImageBitmap(Bitmap.createScaledBitmap(nestedScrollWebView.getFavoriteIcon(), 128, 128, true))
 
                     // Set the loading title text.
                     tabTitleTextView.setText(R.string.loading)
@@ -2929,22 +3164,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                 newHostName = newHostName.substring(newHostName.indexOf(".") + 1)
             }
 
-            // Store the general preference information.
-            val defaultFontSizeString = sharedPreferences.getString(getString(R.string.font_size_key), getString(R.string.font_size_default_value))
-            val defaultUserAgentName = sharedPreferences.getString(getString(R.string.user_agent_key), getString(R.string.user_agent_default_value))
-            val defaultSwipeToRefresh = sharedPreferences.getBoolean(getString(R.string.swipe_to_refresh_key), true)
-            val webViewTheme = sharedPreferences.getString(getString(R.string.webview_theme_key), getString(R.string.webview_theme_default_value))
-            val wideViewport = sharedPreferences.getBoolean(getString(R.string.wide_viewport_key), true)
-            val displayWebpageImages = sharedPreferences.getBoolean(getString(R.string.display_webpage_images_key), true)
-
-            // Get the WebView theme entry values string array.
-            val webViewThemeEntryValuesStringArray = resources.getStringArray(R.array.webview_theme_entry_values)
-
-            // Initialize the user agent array adapter and string array.
-            val userAgentNamesArray = ArrayAdapter.createFromResource(this, R.array.user_agent_names, R.layout.spinner_item)
-            val userAgentDataArray = resources.getStringArray(R.array.user_agent_data)
-
-            // Apply either the domain settings for the default settings.
+            // Apply either the domain settings or the default settings.
             if (nestedScrollWebView.domainSettingsApplied) {  // The url has custom domain settings.
                 // Get a cursor for the current host.
                 val currentDomainSettingsCursor = domainsDatabaseHelper!!.getCursorForDomainName(domainNameInDatabase!!)
@@ -2953,91 +3173,130 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                 currentDomainSettingsCursor.moveToFirst()
 
                 // Get the settings from the cursor.
-                nestedScrollWebView.domainSettingsDatabaseId = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ID))
-                nestedScrollWebView.settings.javaScriptEnabled = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_JAVASCRIPT)) == 1
-                nestedScrollWebView.acceptCookies = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.COOKIES)) == 1
-                nestedScrollWebView.settings.domStorageEnabled = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_DOM_STORAGE)) == 1
-                // Form data can be removed once the minimum API >= 26.
-                val saveFormData = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_FORM_DATA)) == 1
-                nestedScrollWebView.easyListEnabled = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_EASYLIST)) == 1
-                nestedScrollWebView.easyPrivacyEnabled = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_EASYPRIVACY)) == 1
-                nestedScrollWebView.fanboysAnnoyanceListEnabled = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST)) == 1
-                nestedScrollWebView.fanboysSocialBlockingListEnabled =
-                    currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST)) == 1
-                nestedScrollWebView.ultraListEnabled = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ULTRALIST)) == 1
-                nestedScrollWebView.ultraPrivacyEnabled = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY)) == 1
-                nestedScrollWebView.blockAllThirdPartyRequests = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS)) == 1
-                val userAgentName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.USER_AGENT))
-                val fontSize = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.FONT_SIZE))
-                val swipeToRefreshInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SWIPE_TO_REFRESH))
-                val webViewThemeInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.WEBVIEW_THEME))
-                val wideViewportInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.WIDE_VIEWPORT))
-                val displayWebpageImagesInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.DISPLAY_IMAGES))
-                val pinnedSslCertificate = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.PINNED_SSL_CERTIFICATE)) == 1
-                val pinnedSslIssuedToCName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_TO_COMMON_NAME))
-                val pinnedSslIssuedToOName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATION))
-                val pinnedSslIssuedToUName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATIONAL_UNIT))
-                val pinnedSslIssuedByCName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_BY_COMMON_NAME))
-                val pinnedSslIssuedByOName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATION))
-                val pinnedSslIssuedByUName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATIONAL_UNIT))
-                val pinnedSslStartDate = Date(currentDomainSettingsCursor.getLong(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_START_DATE)))
-                val pinnedSslEndDate = Date(currentDomainSettingsCursor.getLong(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_END_DATE)))
-                val pinnedIpAddresses = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.PINNED_IP_ADDRESSES)) == 1
-                val pinnedHostIpAddresses = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.IP_ADDRESSES))
+                nestedScrollWebView.domainSettingsDatabaseId = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(ID))
+                val javaScriptInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(ENABLE_JAVASCRIPT))
+                val cookiesInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(COOKIES))
+                val domStorageInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(ENABLE_DOM_STORAGE))
+                val easyListInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(ENABLE_EASYLIST))
+                val easyPrivacyInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(ENABLE_EASYPRIVACY))
+                val fanboysAnnoyanceListInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(ENABLE_FANBOYS_ANNOYANCE_LIST))
+                val fanboysSocialBlockingListInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST))
+                val ultraListInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(com.stoutner.privacybrowser.helpers.ULTRALIST))
+                val ultraPrivacyInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(ENABLE_ULTRAPRIVACY))
+                val blockAllThirdPartyRequestsInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(com.stoutner.privacybrowser.helpers.BLOCK_ALL_THIRD_PARTY_REQUESTS))
+                val userAgentName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndexOrThrow(com.stoutner.privacybrowser.helpers.USER_AGENT))
+                val fontSize = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(FONT_SIZE))
+                val swipeToRefreshInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(SWIPE_TO_REFRESH))
+                val webViewThemeInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(WEBVIEW_THEME))
+                val wideViewportInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(WIDE_VIEWPORT))
+                val displayWebpageImagesInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DISPLAY_IMAGES))
+                val pinnedSslCertificate = (currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(PINNED_SSL_CERTIFICATE)) == 1)
+                val pinnedSslIssuedToCName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndexOrThrow(SSL_ISSUED_TO_COMMON_NAME))
+                val pinnedSslIssuedToOName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndexOrThrow(SSL_ISSUED_TO_ORGANIZATION))
+                val pinnedSslIssuedToUName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndexOrThrow(SSL_ISSUED_TO_ORGANIZATIONAL_UNIT))
+                val pinnedSslIssuedByCName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndexOrThrow(SSL_ISSUED_BY_COMMON_NAME))
+                val pinnedSslIssuedByOName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndexOrThrow(SSL_ISSUED_BY_ORGANIZATION))
+                val pinnedSslIssuedByUName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndexOrThrow(SSL_ISSUED_BY_ORGANIZATIONAL_UNIT))
+                val pinnedSslStartDate = Date(currentDomainSettingsCursor.getLong(currentDomainSettingsCursor.getColumnIndexOrThrow(com.stoutner.privacybrowser.helpers.SSL_START_DATE)))
+                val pinnedSslEndDate = Date(currentDomainSettingsCursor.getLong(currentDomainSettingsCursor.getColumnIndexOrThrow(com.stoutner.privacybrowser.helpers.SSL_END_DATE)))
+                val pinnedIpAddresses = (currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(PINNED_IP_ADDRESSES)) == 1)
+                val pinnedHostIpAddresses = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndexOrThrow(IP_ADDRESSES))
 
                 // Close the current host domain settings cursor.
                 currentDomainSettingsCursor.close()
 
-                // If there is a pinned SSL certificate, store it in the WebView.
-                if (pinnedSslCertificate)
-                    nestedScrollWebView.setPinnedSslCertificate(pinnedSslIssuedToCName, pinnedSslIssuedToOName, pinnedSslIssuedToUName, pinnedSslIssuedByCName, pinnedSslIssuedByOName, pinnedSslIssuedByUName,
-                        pinnedSslStartDate, pinnedSslEndDate)
+                // Set the JavaScript status.
+                when (javaScriptInt) {
+                    SYSTEM_DEFAULT -> nestedScrollWebView.settings.javaScriptEnabled = defaultJavaScript
+                    ENABLED -> nestedScrollWebView.settings.javaScriptEnabled = true
+                    DISABLED -> nestedScrollWebView.settings.javaScriptEnabled = false
+                }
 
-                // If there is a pinned IP address, store it in the WebView.
-                if (pinnedIpAddresses)
-                    nestedScrollWebView.pinnedIpAddresses = pinnedHostIpAddresses
+                // Store the cookies status.
+                when (cookiesInt) {
+                    SYSTEM_DEFAULT -> nestedScrollWebView.acceptCookies = defaultCookies
+                    ENABLED -> nestedScrollWebView.acceptCookies = true
+                    DISABLED -> nestedScrollWebView.acceptCookies = false
+                }
 
-                // Apply the cookie domain settings.
+                // Apply the cookies status.
                 cookieManager.setAcceptCookie(nestedScrollWebView.acceptCookies)
 
-                // Apply the form data setting if the API < 26.
-                @Suppress("DEPRECATION")
-                if (Build.VERSION.SDK_INT < 26)
-                    nestedScrollWebView.settings.saveFormData = saveFormData
+                // Set the DOM storage status.
+                when (domStorageInt) {
+                    SYSTEM_DEFAULT -> nestedScrollWebView.settings.domStorageEnabled = defaultDomStorage
+                    ENABLED -> nestedScrollWebView.settings.domStorageEnabled = true
+                    DISABLED -> nestedScrollWebView.settings.domStorageEnabled = false
+                }
 
-                // Apply the font size.
-                try {  // Try the specified font size to see if it is valid.
-                    if (fontSize == 0) {  // Apply the default font size.
-                        // Set the font size from the value in the app settings.
-                        nestedScrollWebView.settings.textZoom = defaultFontSizeString!!.toInt()
-                    } else {  // Apply the font size from domain settings.
-                        nestedScrollWebView.settings.textZoom = fontSize
-                    }
-                } catch (exception: Exception) {  // The specified font size is invalid
-                    // Set the font size to be 100%
-                    nestedScrollWebView.settings.textZoom = 100
+                // Set the EasyList status.
+                when (easyListInt) {
+                    SYSTEM_DEFAULT -> nestedScrollWebView.easyListEnabled = defaultEasyList
+                    ENABLED -> nestedScrollWebView.easyListEnabled = true
+                    DISABLED -> nestedScrollWebView.easyListEnabled = false
+                }
+
+                // Set the EasyPrivacy status.
+                when (easyPrivacyInt) {
+                    SYSTEM_DEFAULT -> nestedScrollWebView.easyPrivacyEnabled = defaultEasyPrivacy
+                    ENABLED -> nestedScrollWebView.easyPrivacyEnabled = true
+                    DISABLED -> nestedScrollWebView.easyPrivacyEnabled = false
+                }
+
+                // Set the Fanboy's Annoyance List status.
+                when (fanboysAnnoyanceListInt) {
+                    SYSTEM_DEFAULT -> nestedScrollWebView.fanboysAnnoyanceListEnabled = defaultFanboysAnnoyanceList
+                    ENABLED -> nestedScrollWebView.fanboysAnnoyanceListEnabled = true
+                    DISABLED -> nestedScrollWebView.fanboysAnnoyanceListEnabled = false
+                }
+
+                // Set the Fanboy's Social Blocking List status.
+                when (fanboysSocialBlockingListInt) {
+                    SYSTEM_DEFAULT -> nestedScrollWebView.fanboysSocialBlockingListEnabled = defaultFanboysSocialBlockingList
+                    ENABLED -> nestedScrollWebView.fanboysSocialBlockingListEnabled = true
+                    DISABLED -> nestedScrollWebView.fanboysSocialBlockingListEnabled = false
+                }
+
+                // Set the UltraList status.
+                when (ultraListInt) {
+                    SYSTEM_DEFAULT -> nestedScrollWebView.ultraListEnabled = defaultUltraList
+                    ENABLED -> nestedScrollWebView.ultraListEnabled = true
+                    DISABLED -> nestedScrollWebView.ultraListEnabled = false
+                }
+
+                // Set the UltraPrivacy status.
+                when (ultraPrivacyInt) {
+                    SYSTEM_DEFAULT -> nestedScrollWebView.ultraPrivacyEnabled = defaultUltraPrivacy
+                    ENABLED -> nestedScrollWebView.ultraPrivacyEnabled = true
+                    DISABLED -> nestedScrollWebView.ultraPrivacyEnabled = false
+                }
+
+                // Set the block all third-party requests status.
+                when (blockAllThirdPartyRequestsInt) {
+                    SYSTEM_DEFAULT -> nestedScrollWebView.blockAllThirdPartyRequests = defaultBlockAllThirdPartyRequests
+                    ENABLED -> nestedScrollWebView.blockAllThirdPartyRequests = true
+                    DISABLED -> nestedScrollWebView.blockAllThirdPartyRequests = false
                 }
 
                 // Set the user agent.
                 if (userAgentName == getString(R.string.system_default_user_agent)) {  // Use the system default user agent.
                     // Set the user agent according to the system default.
-                    when (val defaultUserAgentArrayPosition = userAgentNamesArray.getPosition(defaultUserAgentName)) {
-                        // This is probably because it was set in an older version of Privacy Browser before the switch to persistent user agent names.
-                        UNRECOGNIZED_USER_AGENT -> nestedScrollWebView.settings.userAgentString = defaultUserAgentName
+                    when (val defaultUserAgentArrayPosition = userAgentNamesArrayAdapter.getPosition(defaultUserAgentName)) {
+                        UNRECOGNIZED_USER_AGENT ->  // This is probably because it was set in an older version of Privacy Browser before the switch to persistent user agent names.
+                            nestedScrollWebView.settings.userAgentString = defaultUserAgentName
 
-                        // Set the user agent to `""`, which uses the default value.
-                        SETTINGS_WEBVIEW_DEFAULT_USER_AGENT -> nestedScrollWebView.settings.userAgentString = ""
+                        SETTINGS_WEBVIEW_DEFAULT_USER_AGENT ->  // Set the user agent to `""`, which uses the default value.
+                            nestedScrollWebView.settings.userAgentString = ""
 
-                        // Set the default custom user agent.
-                        SETTINGS_CUSTOM_USER_AGENT -> nestedScrollWebView.settings.userAgentString =
-                            sharedPreferences.getString(getString(R.string.custom_user_agent_key), getString(R.string.custom_user_agent_default_value))
+                        SETTINGS_CUSTOM_USER_AGENT ->  // Set the default custom user agent.
+                            nestedScrollWebView.settings.userAgentString = sharedPreferences.getString(getString(R.string.custom_user_agent_key), getString(R.string.custom_user_agent_default_value))
 
-                        // Get the user agent string from the user agent data array
-                        else -> nestedScrollWebView.settings.userAgentString = userAgentDataArray[defaultUserAgentArrayPosition]
+                        else ->  // Get the user agent string from the user agent data array
+                            nestedScrollWebView.settings.userAgentString = userAgentDataArray[defaultUserAgentArrayPosition]
                     }
                 } else {  // Set the user agent according to the stored name.
                     // Set the user agent.
-                    when (val userAgentArrayPosition = userAgentNamesArray.getPosition(userAgentName)) {
+                    when (val userAgentArrayPosition = userAgentNamesArrayAdapter.getPosition(userAgentName)) {
                         // This is probably because it was set in an older version of Privacy Browser before the switch to persistent user agent names.
                         UNRECOGNIZED_USER_AGENT ->
                             nestedScrollWebView.settings.userAgentString = userAgentName
@@ -3052,9 +3311,22 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                     }
                 }
 
+                // Apply the font size.
+                try {  // Try the specified font size to see if it is valid.
+                    if (fontSize == 0) {  // Apply the default font size.
+                        // Set the font size from the value in the app settings.
+                        nestedScrollWebView.settings.textZoom = defaultFontSizeString.toInt()
+                    } else {  // Apply the font size from domain settings.
+                        nestedScrollWebView.settings.textZoom = fontSize
+                    }
+                } catch (exception: Exception) {  // The specified font size is invalid
+                    // Set the font size to be 100%
+                    nestedScrollWebView.settings.textZoom = 100
+                }
+
                 // Set swipe to refresh.
                 when (swipeToRefreshInt) {
-                    DomainsDatabaseHelper.SYSTEM_DEFAULT -> {
+                    SYSTEM_DEFAULT -> {
                         // Store the swipe to refresh status in the nested scroll WebView.
                         nestedScrollWebView.swipeToRefresh = defaultSwipeToRefresh
 
@@ -3071,7 +3343,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                         }
                     }
 
-                    DomainsDatabaseHelper.ENABLED -> {
+                    ENABLED -> {
                         // Store the swipe to refresh status in the nested scroll WebView.
                         nestedScrollWebView.swipeToRefresh = true
 
@@ -3082,7 +3354,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                         }
                     }
 
-                    DomainsDatabaseHelper.DISABLED -> {
+                    DISABLED -> {
                         // Store the swipe to refresh status in the nested scroll WebView.
                         nestedScrollWebView.swipeToRefresh = false
 
@@ -3091,21 +3363,19 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                     }
                 }
 
-                // Set the WebView theme if device is running API >= 29 and algorithmic darkening is supported.
-                if ((Build.VERSION.SDK_INT >= 29) && WebViewFeature.isFeatureSupported(WebViewFeature.ALGORITHMIC_DARKENING)) {
+                // Set the WebView theme if algorithmic darkening is supported.
+                if (WebViewFeature.isFeatureSupported(WebViewFeature.ALGORITHMIC_DARKENING)) {
                     // Set the WebView theme.
                     when (webViewThemeInt) {
-                        // Set the WebView theme.
-                        DomainsDatabaseHelper.SYSTEM_DEFAULT ->
-                            when (webViewTheme) {
-                                // The light theme is selected.  Turn off algorithmic darkening.
-                                webViewThemeEntryValuesStringArray[1] -> WebSettingsCompat.setAlgorithmicDarkeningAllowed(nestedScrollWebView.settings, false)
+                        SYSTEM_DEFAULT ->  // Set the WebView theme.
+                            when (defaultWebViewTheme) {
+                                webViewThemeEntryValuesStringArray[1] ->  // The light theme is selected.  Turn off algorithmic darkening.
+                                    WebSettingsCompat.setAlgorithmicDarkeningAllowed(nestedScrollWebView.settings, false)
 
-                                // The dark theme is selected.  Turn on algorithmic darkening.
-                                webViewThemeEntryValuesStringArray[2] -> WebSettingsCompat.setAlgorithmicDarkeningAllowed(nestedScrollWebView.settings, true)
+                                webViewThemeEntryValuesStringArray[2] ->  // The dark theme is selected.  Turn on algorithmic darkening.
+                                    WebSettingsCompat.setAlgorithmicDarkeningAllowed(nestedScrollWebView.settings, true)
 
-                                // The system default theme is selected.
-                                else -> {
+                                else -> {  // The system default theme is selected.
                                     // Get the current system theme status.
                                     val currentThemeStatus = resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
 
@@ -3114,43 +3384,51 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                                 }
                             }
 
-                        // Turn off algorithmic darkening.
-                        DomainsDatabaseHelper.LIGHT_THEME -> WebSettingsCompat.setAlgorithmicDarkeningAllowed(nestedScrollWebView.settings, false)
+                        LIGHT_THEME ->  // Turn off algorithmic darkening.
+                            WebSettingsCompat.setAlgorithmicDarkeningAllowed(nestedScrollWebView.settings, false)
 
-                        // Turn on algorithmic darkening.
-                        DomainsDatabaseHelper.DARK_THEME -> WebSettingsCompat.setAlgorithmicDarkeningAllowed(nestedScrollWebView.settings, true)
+                        DARK_THEME ->  // Turn on algorithmic darkening.
+                            WebSettingsCompat.setAlgorithmicDarkeningAllowed(nestedScrollWebView.settings, true)
                     }
                 }
 
                 // Set the wide viewport status.
                 when (wideViewportInt) {
-                    DomainsDatabaseHelper.SYSTEM_DEFAULT -> nestedScrollWebView.settings.useWideViewPort = wideViewport
-                    DomainsDatabaseHelper.ENABLED -> nestedScrollWebView.settings.useWideViewPort = true
-                    DomainsDatabaseHelper.DISABLED -> nestedScrollWebView.settings.useWideViewPort = false
+                    SYSTEM_DEFAULT -> nestedScrollWebView.settings.useWideViewPort = defaultWideViewport
+                    ENABLED -> nestedScrollWebView.settings.useWideViewPort = true
+                    DISABLED -> nestedScrollWebView.settings.useWideViewPort = false
                 }
 
                 // Set the display webpage images status.
                 when (displayWebpageImagesInt) {
-                    DomainsDatabaseHelper.SYSTEM_DEFAULT -> nestedScrollWebView.settings.loadsImagesAutomatically = displayWebpageImages
-                    DomainsDatabaseHelper.ENABLED -> nestedScrollWebView.settings.loadsImagesAutomatically = true
-                    DomainsDatabaseHelper.DISABLED -> nestedScrollWebView.settings.loadsImagesAutomatically = false
+                    SYSTEM_DEFAULT -> nestedScrollWebView.settings.loadsImagesAutomatically = defaultDisplayWebpageImages
+                    ENABLED -> nestedScrollWebView.settings.loadsImagesAutomatically = true
+                    DISABLED -> nestedScrollWebView.settings.loadsImagesAutomatically = false
                 }
 
+                // If there is a pinned SSL certificate, store it in the WebView.
+                if (pinnedSslCertificate)
+                    nestedScrollWebView.setPinnedSslCertificate(pinnedSslIssuedToCName, pinnedSslIssuedToOName, pinnedSslIssuedToUName, pinnedSslIssuedByCName, pinnedSslIssuedByOName, pinnedSslIssuedByUName,
+                        pinnedSslStartDate, pinnedSslEndDate)
+
+                // If there is a pinned IP address, store it in the WebView.
+                if (pinnedIpAddresses)
+                    nestedScrollWebView.pinnedIpAddresses = pinnedHostIpAddresses
+
                 // Set a background on the URL relative layout to indicate that custom domain settings are being used.
                 urlRelativeLayout.background = AppCompatResources.getDrawable(this, R.drawable.domain_settings_url_background)
             } else {  // The new URL does not have custom domain settings.  Load the defaults.
                 // Store the values from the shared preferences.
-                nestedScrollWebView.settings.javaScriptEnabled = sharedPreferences.getBoolean(getString(R.string.javascript_key), false)
-                nestedScrollWebView.acceptCookies = sharedPreferences.getBoolean(getString(R.string.cookies_key), false)
-                nestedScrollWebView.settings.domStorageEnabled = sharedPreferences.getBoolean(getString(R.string.dom_storage_key), false)
-                val saveFormData = sharedPreferences.getBoolean(getString(R.string.save_form_data_key), false) // Form data can be removed once the minimum API >= 26.
-                nestedScrollWebView.easyListEnabled = sharedPreferences.getBoolean(getString(R.string.easylist_key), true)
-                nestedScrollWebView.easyPrivacyEnabled = sharedPreferences.getBoolean(getString(R.string.easyprivacy_key), true)
-                nestedScrollWebView.fanboysAnnoyanceListEnabled = sharedPreferences.getBoolean(getString(R.string.fanboys_annoyance_list_key), true)
-                nestedScrollWebView.fanboysSocialBlockingListEnabled = sharedPreferences.getBoolean(getString(R.string.fanboys_social_blocking_list_key), true)
-                nestedScrollWebView.ultraListEnabled = sharedPreferences.getBoolean(getString(R.string.ultralist_key), true)
-                nestedScrollWebView.ultraPrivacyEnabled = sharedPreferences.getBoolean(getString(R.string.ultraprivacy_key), true)
-                nestedScrollWebView.blockAllThirdPartyRequests = sharedPreferences.getBoolean(getString(R.string.block_all_third_party_requests_key), false)
+                nestedScrollWebView.settings.javaScriptEnabled = defaultJavaScript
+                nestedScrollWebView.acceptCookies = defaultCookies
+                nestedScrollWebView.settings.domStorageEnabled = defaultDomStorage
+                nestedScrollWebView.easyListEnabled = defaultEasyList
+                nestedScrollWebView.easyPrivacyEnabled = defaultEasyPrivacy
+                nestedScrollWebView.fanboysAnnoyanceListEnabled = defaultFanboysAnnoyanceList
+                nestedScrollWebView.fanboysSocialBlockingListEnabled = defaultFanboysSocialBlockingList
+                nestedScrollWebView.ultraListEnabled = defaultUltraList
+                nestedScrollWebView.ultraPrivacyEnabled = defaultUltraPrivacy
+                nestedScrollWebView.blockAllThirdPartyRequests = defaultBlockAllThirdPartyRequests
 
                 // Apply the default cookie setting.
                 cookieManager.setAcceptCookie(nestedScrollWebView.acceptCookies)
@@ -3158,17 +3436,12 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                 // Apply the default font size setting.
                 try {
                     // Try to set the font size from the value in the app settings.
-                    nestedScrollWebView.settings.textZoom = defaultFontSizeString!!.toInt()
+                    nestedScrollWebView.settings.textZoom = defaultFontSizeString.toInt()
                 } catch (exception: Exception) {
                     // If the app settings value is invalid, set the font size to 100%.
                     nestedScrollWebView.settings.textZoom = 100
                 }
 
-                // Apply the form data setting if the API < 26.
-                if (Build.VERSION.SDK_INT < 26)
-                    @Suppress("DEPRECATION")
-                    nestedScrollWebView.settings.saveFormData = saveFormData
-
                 // Store the swipe to refresh status in the nested scroll WebView.
                 nestedScrollWebView.swipeToRefresh = defaultSwipeToRefresh
 
@@ -3188,33 +3461,31 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                 nestedScrollWebView.domainSettingsDatabaseId = -1
 
                 // Set the user agent.
-                when (val userAgentArrayPosition = userAgentNamesArray.getPosition(defaultUserAgentName)) {
-                    // This is probably because it was set in an older version of Privacy Browser before the switch to persistent user agent names.
-                    UNRECOGNIZED_USER_AGENT -> nestedScrollWebView.settings.userAgentString = defaultUserAgentName
+                when (val userAgentArrayPosition = userAgentNamesArrayAdapter.getPosition(defaultUserAgentName)) {
+                    UNRECOGNIZED_USER_AGENT ->  // This is probably because it was set in an older version of Privacy Browser before the switch to persistent user agent names.
+                        nestedScrollWebView.settings.userAgentString = defaultUserAgentName
 
-                    // Set the user agent to `""`, which uses the default value.
-                    SETTINGS_WEBVIEW_DEFAULT_USER_AGENT -> nestedScrollWebView.settings.userAgentString = ""
+                    SETTINGS_WEBVIEW_DEFAULT_USER_AGENT ->  // Set the user agent to `""`, which uses the default value.
+                        nestedScrollWebView.settings.userAgentString = ""
 
-                    // Set the default custom user agent.
-                    SETTINGS_CUSTOM_USER_AGENT -> nestedScrollWebView.settings.userAgentString =
-                        sharedPreferences.getString(getString(R.string.custom_user_agent_key), getString(R.string.custom_user_agent_default_value))
+                    SETTINGS_CUSTOM_USER_AGENT ->  // Set the default custom user agent.
+                        nestedScrollWebView.settings.userAgentString = sharedPreferences.getString(getString(R.string.custom_user_agent_key), getString(R.string.custom_user_agent_default_value))
 
-                    // Get the user agent string from the user agent data array
-                    else -> nestedScrollWebView.settings.userAgentString = userAgentDataArray[userAgentArrayPosition]
+                    else ->  // Get the user agent string from the user agent data array
+                        nestedScrollWebView.settings.userAgentString = userAgentDataArray[userAgentArrayPosition]
                 }
 
-                // Set the WebView theme if the device is running API >= 29 and algorithmic darkening is supported.
-                if ((Build.VERSION.SDK_INT >= 29) && WebViewFeature.isFeatureSupported(WebViewFeature.ALGORITHMIC_DARKENING)) {
+                // Set the WebView theme if algorithmic darkening is supported.
+                if (WebViewFeature.isFeatureSupported(WebViewFeature.ALGORITHMIC_DARKENING)) {
                     // Set the WebView theme.
-                    when (webViewTheme) {
-                        // The light theme is selected.  Turn off algorithmic darkening.
-                        webViewThemeEntryValuesStringArray[1] -> WebSettingsCompat.setAlgorithmicDarkeningAllowed(nestedScrollWebView.settings, false)
+                    when (defaultWebViewTheme) {
+                        webViewThemeEntryValuesStringArray[1] ->  // The light theme is selected.  Turn off algorithmic darkening.
+                            WebSettingsCompat.setAlgorithmicDarkeningAllowed(nestedScrollWebView.settings, false)
 
-                        // The dark theme is selected.  Turn on algorithmic darkening.
-                        webViewThemeEntryValuesStringArray[2] -> WebSettingsCompat.setAlgorithmicDarkeningAllowed(nestedScrollWebView.settings, true)
+                        webViewThemeEntryValuesStringArray[2] ->  // The dark theme is selected.  Turn on algorithmic darkening.
+                            WebSettingsCompat.setAlgorithmicDarkeningAllowed(nestedScrollWebView.settings, true)
 
-                        // The system default theme is selected.  Get the current system theme status.
-                        else -> {
+                        else -> {  // The system default theme is selected.  Get the current system theme status.
                             // Get the current theme status.
                             val currentThemeStatus = resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
 
@@ -3225,10 +3496,10 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                 }
 
                 // Set the viewport.
-                nestedScrollWebView.settings.useWideViewPort = wideViewport
+                nestedScrollWebView.settings.useWideViewPort = defaultWideViewport
 
                 // Set the loading of webpage images.
-                nestedScrollWebView.settings.loadsImagesAutomatically = displayWebpageImages
+                nestedScrollWebView.settings.loadsImagesAutomatically = defaultDisplayWebpageImages
 
                 // Set a transparent background on the URL relative layout.
                 urlRelativeLayout.background = AppCompatResources.getDrawable(this, R.color.transparent)
@@ -3242,6 +3513,10 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
         if (reloadWebsite)
             nestedScrollWebView.reload()
 
+        // Disable the wide viewport if the source is being viewed.
+        if (url.startsWith("view-source:"))
+            nestedScrollWebView.settings.useWideViewPort = false
+
         // Load the URL if directed.  This makes sure that the domain settings are properly loaded before the URL.  By using `loadUrl()`, instead of `loadUrlFromBase()`, the Referer header will never be sent.
         if (loadUrl)
             nestedScrollWebView.loadUrl(url)
@@ -3279,8 +3554,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                     // Get the package manager.
                     val packageManager = packageManager
 
-                    // Check to see if Orbot is in the list.  This will throw an error and drop to the catch section if it isn't installed.  The deprecated method must be used until the minimum API >= 33.
-                    @Suppress("DEPRECATION")
+                    // Check to see if Orbot is in the list.  This will throw an error and drop to the catch section if it isn't installed.
                     packageManager.getPackageInfo("org.torproject.android", 0)
 
                     // Check to see if the proxy is ready.
@@ -3328,14 +3602,10 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                 // Check to see if I2P is installed.
                 try {
                     // Check to see if the F-Droid flavor is installed.  This will throw an error and drop to the catch section if it isn't installed.
-                    // The deprecated method must be used until the minimum API >= 33.
-                    @Suppress("DEPRECATION")
                     packageManager.getPackageInfo("net.i2p.android.router", 0)
                 } catch (fdroidException: PackageManager.NameNotFoundException) {  // The F-Droid flavor is not installed.
                     try {
                         // Check to see if the Google Play flavor is installed.  This will throw an error and drop to the catch section if it isn't installed.
-                        // The deprecated method must be used until the minimum API >= 33.
-                        @Suppress("DEPRECATION")
                         packageManager.getPackageInfo("net.i2p.android", 0)
                     } catch (googlePlayException: PackageManager.NameNotFoundException) {  // The Google Play flavor is not installed.
                         // Sow the I2P not installed dialog if it is not already displayed.
@@ -3385,18 +3655,27 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
 
     // The view parameter cannot be removed because it is called from the layout onClick.
     fun bookmarksBack(@Suppress("UNUSED_PARAMETER")view: View?) {
-        if (currentBookmarksFolder.isEmpty()) {  // The home folder is displayed.
+        if (currentBookmarksFolderId == HOME_FOLDER_ID) {  // The home folder is displayed.
             // close the bookmarks drawer.
             drawerLayout.closeDrawer(GravityCompat.END)
         } else {  // A subfolder is displayed.
             // Set the former parent folder as the current folder.
-            currentBookmarksFolder = bookmarksDatabaseHelper!!.getParentFolderName(currentBookmarksFolder)
+            currentBookmarksFolderId = bookmarksDatabaseHelper!!.getParentFolderId(currentBookmarksFolderId)
 
             // Load the new folder.
             loadBookmarksFolder()
         }
     }
 
+    private fun calculateSettingsInt(settingCurrentlyEnabled: Boolean, settingEnabledByDefault: Boolean): Int {
+        return if (settingCurrentlyEnabled == settingEnabledByDefault)  // The current system default is used.
+            SYSTEM_DEFAULT
+        else if (settingCurrentlyEnabled)  // The setting is enabled, which is different from the system default.
+            ENABLED
+        else  // The setting is disabled, which is different from the system default.
+            DISABLED
+    }
+
     private fun clearAndExit() {
         // Close the bookmarks cursor if it exists.
         bookmarksCursor?.close()
@@ -3464,26 +3743,6 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
             }
         }
 
-        // Clear form data if the API < 26.
-        if (Build.VERSION.SDK_INT < 26 && (clearEverything || sharedPreferences.getBoolean(getString(R.string.clear_form_data_key), true))) {
-            // Ask the WebView database to clear the form data.
-            @Suppress("DEPRECATION")
-            WebViewDatabase.getInstance(this).clearFormData()
-
-            // Manually delete the form data database, as the WebView database sometimes will not flush its changes to disk before system exit is run.
-            try {
-                // A string array must be used because the database contains a space and `Runtime.exec` will not otherwise escape the string correctly.
-                val deleteWebDataProcess = runtime.exec(arrayOf("rm", "-f", "$privateDataDirectoryString/app_webview/Web Data"))
-                val deleteWebDataJournalProcess = runtime.exec(arrayOf("rm", "-f", "$privateDataDirectoryString/app_webview/Web Data-journal"))
-
-                // Wait until the processes have finished.
-                deleteWebDataProcess.waitFor()
-                deleteWebDataJournalProcess.waitFor()
-            } catch (exception: Exception) {
-                // Do nothing if an error is thrown.
-            }
-        }
-
         // Clear the logcat.
         if (clearEverything || sharedPreferences.getBoolean(getString(R.string.clear_logcat_key), true)) {
             try {
@@ -3598,9 +3857,6 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
         // Show the toolbar.
         toolbar.visibility = View.VISIBLE
 
-        // Get a handle for the input method manager.
-        val inputMethodManager = (getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager)
-
         // Hide the keyboard.
         inputMethodManager.hideSoftInputFromWindow(toolbar.windowToken, 0)
     }
@@ -3624,17 +3880,32 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
         }
     }
 
-    override fun createBookmark(dialogFragment: DialogFragment, favoriteIconBitmap: Bitmap) {
+    override fun createBookmark(dialogFragment: DialogFragment) {
         // Get the dialog.
         val dialog = dialogFragment.dialog!!
 
         // Get the views from the dialog fragment.
-        val createBookmarkNameEditText = dialog.findViewById<EditText>(R.id.create_bookmark_name_edittext)
-        val createBookmarkUrlEditText = dialog.findViewById<EditText>(R.id.create_bookmark_url_edittext)
+        val webpageFavoriteIconRadioButton = dialog.findViewById<RadioButton>(R.id.webpage_favorite_icon_radiobutton)
+        val webpageFavoriteIconImageView = dialog.findViewById<ImageView>(R.id.webpage_favorite_icon_imageview)
+        val customIconImageView = dialog.findViewById<ImageView>(R.id.custom_icon_imageview)
+        val bookmarkNameEditText = dialog.findViewById<EditText>(R.id.bookmark_name_edittext)
+        val bookmarkUrlEditText = dialog.findViewById<EditText>(R.id.bookmark_url_edittext)
 
         // Extract the strings from the edit texts.
-        val bookmarkNameString = createBookmarkNameEditText.text.toString()
-        val bookmarkUrlString = createBookmarkUrlEditText.text.toString()
+        val bookmarkNameString = bookmarkNameEditText.text.toString()
+        val bookmarkUrlString = bookmarkUrlEditText.text.toString()
+
+        // Get the selected favorite icon drawable.
+        val favoriteIconDrawable = if (webpageFavoriteIconRadioButton.isChecked)  // Use the webpage favorite icon.
+            webpageFavoriteIconImageView.drawable
+        else  // Use the custom icon.
+            customIconImageView.drawable
+
+        // Cast the favorite icon bitmap to a bitmap drawable
+        val favoriteIconBitmapDrawable = favoriteIconDrawable as BitmapDrawable
+
+        // Convert the favorite icon bitmap drawable to a bitmap.
+        val favoriteIconBitmap = favoriteIconBitmapDrawable.bitmap
 
         // Create a favorite icon byte array output stream.
         val favoriteIconByteArrayOutputStream = ByteArrayOutputStream()
@@ -3649,10 +3920,10 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
         val newBookmarkDisplayOrder = bookmarksListView.count
 
         // Create the bookmark.
-        bookmarksDatabaseHelper!!.createBookmark(bookmarkNameString, bookmarkUrlString, currentBookmarksFolder, newBookmarkDisplayOrder, favoriteIconByteArray)
+        bookmarksDatabaseHelper!!.createBookmark(bookmarkNameString, bookmarkUrlString, currentBookmarksFolderId, newBookmarkDisplayOrder, favoriteIconByteArray)
 
         // Update the bookmarks cursor with the current contents of this folder.
-        bookmarksCursor = bookmarksDatabaseHelper!!.getBookmarksByDisplayOrder(currentBookmarksFolder)
+        bookmarksCursor = bookmarksDatabaseHelper!!.getBookmarksByDisplayOrder(currentBookmarksFolderId)
 
         // Update the list view.
         bookmarksCursorAdapter.changeCursor(bookmarksCursor)
@@ -3661,32 +3932,34 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
         bookmarksListView.setSelection(newBookmarkDisplayOrder)
     }
 
-    override fun createBookmarkFolder(dialogFragment: DialogFragment, favoriteIconBitmap: Bitmap) {
+    override fun createBookmarkFolder(dialogFragment: DialogFragment) {
         // Get the dialog.
         val dialog = dialogFragment.dialog!!
 
         // Get handles for the views in the dialog fragment.
+        val defaultFolderIconRadioButton = dialog.findViewById<RadioButton>(R.id.default_folder_icon_radiobutton)
+        val defaultFolderIconImageView = dialog.findViewById<ImageView>(R.id.default_folder_icon_imageview)
+        val webpageFavoriteIconRadioButton = dialog.findViewById<RadioButton>(R.id.webpage_favorite_icon_radiobutton)
+        val webpageFavoriteIconImageView = dialog.findViewById<ImageView>(R.id.webpage_favorite_icon_imageview)
+        val customIconImageView = dialog.findViewById<ImageView>(R.id.custom_icon_imageview)
         val folderNameEditText = dialog.findViewById<EditText>(R.id.folder_name_edittext)
-        val defaultIconRadioButton = dialog.findViewById<RadioButton>(R.id.default_icon_radiobutton)
-        val defaultIconImageView = dialog.findViewById<ImageView>(R.id.default_icon_imageview)
 
         // Get new folder name string.
         val folderNameString = folderNameEditText.text.toString()
 
         // Set the folder icon bitmap according to the dialog.
-        val folderIconBitmap: Bitmap = if (defaultIconRadioButton.isChecked) {  // Use the default folder icon.
-            // Get the default folder icon drawable.
-            val folderIconDrawable = defaultIconImageView.drawable
-
-            // Convert the folder icon drawable to a bitmap drawable.
-            val folderIconBitmapDrawable = folderIconDrawable as BitmapDrawable
-
-            // Convert the folder icon bitmap drawable to a bitmap.
-            folderIconBitmapDrawable.bitmap
-        } else {  // Use the WebView favorite icon.
-            // Copy the favorite icon bitmap to the folder icon bitmap.
-            favoriteIconBitmap
-        }
+        val folderIconDrawable = if (defaultFolderIconRadioButton.isChecked)  // Use the default folder icon.
+            defaultFolderIconImageView.drawable
+        else if (webpageFavoriteIconRadioButton.isChecked)  // Use the webpage favorite icon.
+            webpageFavoriteIconImageView.drawable
+        else  // Use the custom icon.
+            customIconImageView.drawable
+
+        // Cast the folder icon bitmap to a bitmap drawable.
+        val folderIconBitmapDrawable = folderIconDrawable as BitmapDrawable
+
+        // Convert the folder icon bitmap drawable to a bitmap.
+        val folderIconBitmap = folderIconBitmapDrawable.bitmap
 
         // Create a folder icon byte array output stream.
         val folderIconByteArrayOutputStream = ByteArrayOutputStream()
@@ -3703,14 +3976,14 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
             val databaseId = bookmarksListView.getItemIdAtPosition(i).toInt()
 
             // Move the bookmark down one slot.
-            bookmarksDatabaseHelper!!.updateDisplayOrder(databaseId, i + 1)
+            bookmarksDatabaseHelper!!.updateDisplayOrder(databaseId, displayOrder = i + 1)
         }
 
         // Create the folder, which will be placed at the top of the list view.
-        bookmarksDatabaseHelper!!.createFolder(folderNameString, currentBookmarksFolder, folderIconByteArray)
+        bookmarksDatabaseHelper!!.createFolder(folderNameString, currentBookmarksFolderId, displayOrder = 0, folderIconByteArray)
 
         // Update the bookmarks cursor with the current contents of this folder.
-        bookmarksCursor = bookmarksDatabaseHelper!!.getBookmarksByDisplayOrder(currentBookmarksFolder)
+        bookmarksCursor = bookmarksDatabaseHelper!!.getBookmarksByDisplayOrder(currentBookmarksFolderId)
 
         // Update the list view.
         bookmarksCursorAdapter.changeCursor(bookmarksCursor)
@@ -3719,20 +3992,6 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
         bookmarksListView.setSelection(0)
     }
 
-    private fun downloadUrlWithExternalApp(url: String) {
-        // Create a download intent.  Not specifying the action type will display the maximum number of options.
-        val downloadIntent = Intent()
-
-        // Set the URI and the mime type.
-        downloadIntent.setDataAndType(Uri.parse(url), "text/html")
-
-        // Flag the intent to open in a new task.
-        downloadIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
-
-        // Show the chooser.
-        startActivity(Intent.createChooser(downloadIntent, getString(R.string.download_with_external_app)))
-    }
-
     private fun exitFullScreenVideo() {
         // Re-enable the screen timeout.
         fullScreenVideoFrameLayout.keepScreenOn = false
@@ -3804,8 +4063,8 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
         // Check to see if the activity has been restarted with a saved state.
         if ((savedStateArrayList == null) || (savedStateArrayList!!.size == 0)) {  // The activity has not been restarted or it was restarted on start to change the theme.
             // Add the first tab.
-            addNewTab("", false)
-        } else {  // The activity has been restarted.
+            addNewPage(urlString = "", adjacent = false, moveToTab = false)
+        } else {  // The activity has been restarted with a saved state.
             // Restore each tab.
             for (i in savedStateArrayList!!.indices) {
                 // Add a new tab.
@@ -3825,15 +4084,6 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
             savedStateArrayList = null
             savedNestedScrollWebViewStateArrayList = null
 
-            // Restore the selected tab position.
-            if (savedTabPosition == 0) {  // The first tab is selected.
-                // Set the first page as the current WebView.
-                setCurrentWebView(0)
-            } else {  // The first tab is not selected.
-                // Move to the selected tab.
-                webViewViewPager2.currentItem = savedTabPosition
-            }
-
             // Get the intent that started the app.
             val intent = intent
 
@@ -3849,7 +4099,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
             val isWebSearch = (intentAction != null) && (intentAction == Intent.ACTION_WEB_SEARCH)
 
             // Only process the URI if it contains data or it is a web search.  If the user pressed the desktop icon after the app was already running the URI will be null.
-            if ((intentUriData != null) || (intentStringExtra != null) || isWebSearch) {
+            if ((intentUriData != null) || (intentStringExtra != null) || isWebSearch) {  // A new tab is being loaded.
                 // Get the URL string.
                 val urlString = if (isWebSearch) {  // The intent is a web search.
                     // Sanitize the search input.
@@ -3872,11 +4122,26 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                     loadingNewIntent = true
 
                     // Add a new tab.
-                    addNewTab(urlString, true)
+                    addNewPage(urlString, adjacent = false, moveToTab = true)
                 } else {  // Load the URL in the current tab.
                     // Make it so.
                     loadUrl(currentWebView!!, urlString)
                 }
+            } else {  // A new tab is not being loaded.
+                // Restore the selected tab position.
+                if (savedTabPosition == 0) {  // The first tab is selected.
+                    // Set the first page as the current WebView.
+                    setCurrentWebView(0)
+                } else {  // The first tab is not selected.
+                    // Select the tab when the layout has finished populating.
+                    tabLayout.post {
+                        // Get a handle for the tab.
+                        val tab = tabLayout.getTabAt(savedTabPosition)!!
+
+                        // Select the tab.
+                        tab.select()
+                    }
+                }
             }
         }
     }
@@ -3885,7 +4150,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
     @SuppressLint("ClickableViewAccessibility")
     private fun initializeApp() {
         // Get a handle for the input method.
-        val inputMethodManager = (getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager)
+        inputMethodManager = (getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager)
 
         // Initialize the color spans for highlighting the URLs.
         initialGrayColorSpan = ForegroundColorSpan(getColor(R.color.gray_500))
@@ -3982,8 +4247,8 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
             }
         }
 
-        // Register the Orbot status broadcast receiver.
-        registerReceiver(orbotStatusBroadcastReceiver, IntentFilter("org.torproject.android.intent.action.STATUS"))
+        // Register the Orbot status broadcast receiver.  `ContextCompat` must be used until the minimum API >= 34.
+        ContextCompat.registerReceiver(this, orbotStatusBroadcastReceiver, IntentFilter("org.torproject.android.intent.action.STATUS"), ContextCompat.RECEIVER_EXPORTED)
 
         // Get handles for views that need to be modified.
         val bookmarksHeaderLinearLayout = findViewById<LinearLayout>(R.id.bookmarks_header_linearlayout)
@@ -3991,44 +4256,36 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
         val createBookmarkFolderFab = findViewById<FloatingActionButton>(R.id.create_bookmark_folder_fab)
         val createBookmarkFab = findViewById<FloatingActionButton>(R.id.create_bookmark_fab)
 
-        // Update the WebView pager every time a tab is modified.
-        webViewViewPager2.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
-            override fun onPageSelected(position: Int) {
+        // Handle tab selections.
+        tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
+            override fun onTabSelected(tab: TabLayout.Tab) {
                 // Close the find on page bar if it is open.
                 closeFindOnPage(null)
 
-                // Set the current WebView.
-                setCurrentWebView(position)
+                // Update the view pager when it has quiesced.  Otherwise, if a page launched by a new intent on restart has not yet been created, the view pager will not be updated to match the tab layout.
+                webViewViewPager2.post {
+                    // Select the same page in the view pager.
+                    webViewViewPager2.currentItem = tab.position
 
-                // Select the corresponding tab if it does not match the currently selected page.  This will happen if the page was scrolled by creating a new tab.
-                if (tabLayout.selectedTabPosition != position) {
-                    // Wait until the new tab has been created.
+                    // Set the current WebView after the tab layout has quiesced (otherwise, sometimes the wong WebView might be used).  See <https://redmine.stoutner.com/issues/1136>
                     tabLayout.post {
-                        // Get a handle for the tab.
-                        val tab = tabLayout.getTabAt(position)!!
-
-                        // Select the tab.
-                        tab.select()
+                        setCurrentWebView(tab.position)
                     }
                 }
             }
-        })
-
-        // Handle tab selections.
-        tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
-            override fun onTabSelected(tab: TabLayout.Tab) {
-                // Select the same page in the view pager.
-                webViewViewPager2.currentItem = tab.position
-            }
 
             override fun onTabUnselected(tab: TabLayout.Tab) {}
 
             override fun onTabReselected(tab: TabLayout.Tab) {
-                // Instantiate the View SSL Certificate dialog.
-                val viewSslCertificateDialogFragment: DialogFragment = ViewSslCertificateDialog.displayDialog(currentWebView!!.webViewFragmentId, currentWebView!!.getFavoriteIcon())
-
-                // Display the View SSL Certificate dialog.
-                viewSslCertificateDialogFragment.show(supportFragmentManager, getString(R.string.view_ssl_certificate))
+                // Only display the view SSL certificate dialog if the current WebView is not null.
+                // This can happen if the tab is programmatically reselected while the app is being restarted and is not yet populated.
+                if (currentWebView != null) {
+                    // Instantiate the View SSL Certificate dialog.
+                    val viewSslCertificateDialogFragment: DialogFragment = ViewSslCertificateDialog.displayDialog(currentWebView!!.webViewFragmentId, currentWebView!!.getFavoriteIcon())
+
+                    // Display the View SSL Certificate dialog.
+                    viewSslCertificateDialogFragment.show(supportFragmentManager, getString(R.string.view_ssl_certificate))
+                }
             }
         })
 
@@ -4053,7 +4310,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
             val bookmarksIntent = Intent(applicationContext, BookmarksActivity::class.java)
 
             // Add the extra information to the intent.
-            bookmarksIntent.putExtra(CURRENT_FOLDER, currentBookmarksFolder)
+            bookmarksIntent.putExtra(CURRENT_FOLDER_ID, currentBookmarksFolderId)
             bookmarksIntent.putExtra(CURRENT_TITLE, currentWebView!!.title)
             bookmarksIntent.putExtra(CURRENT_URL, currentWebView!!.url)
             bookmarksIntent.putExtra(CURRENT_FAVORITE_ICON_BYTE_ARRAY, currentFavoriteIconByteArray)
@@ -4082,11 +4339,15 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
 
         // Search for the string on the page whenever a character changes in the find on page edit text.
         findOnPageEditText.addTextChangedListener(object : TextWatcher {
-            override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
+            override fun beforeTextChanged(charSequence: CharSequence, start: Int, count: Int, after: Int) {
+                // Do nothing.
+            }
 
-            override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
+            override fun onTextChanged(charSequence: CharSequence, start: Int, before: Int, count: Int) {
+                // Do nothing.
+            }
 
-            override fun afterTextChanged(s: Editable) {
+            override fun afterTextChanged(editable: Editable) {
                 // Search for the text in the WebView if it is not null.  Sometimes on resume after a period of non-use the WebView will be null.
                 currentWebView?.findAllAsync(findOnPageEditText.text.toString())
             }
@@ -4150,15 +4411,15 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
             bookmarkCursor.moveToFirst()
 
             // Act upon the bookmark according to the type.
-            if (bookmarkCursor.getInt(bookmarkCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.IS_FOLDER)) == 1) {  // The selected bookmark is a folder.
-                // Store the folder name.
-                currentBookmarksFolder = bookmarkCursor.getString(bookmarkCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_NAME))
+            if (bookmarkCursor.getInt(bookmarkCursor.getColumnIndexOrThrow(IS_FOLDER)) == 1) {  // The selected bookmark is a folder.
+                // Store the folder ID.
+                currentBookmarksFolderId = bookmarkCursor.getLong(bookmarkCursor.getColumnIndexOrThrow(FOLDER_ID))
 
                 // Load the new folder.
                 loadBookmarksFolder()
             } else {  // The selected bookmark is not a folder.
                 // Load the bookmark URL.
-                loadUrl(currentWebView!!, bookmarkCursor.getString(bookmarkCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_URL)))
+                loadUrl(currentWebView!!, bookmarkCursor.getString(bookmarkCursor.getColumnIndexOrThrow(BOOKMARK_URL)))
 
                 // Close the bookmarks drawer if it is not pinned.
                 if (!bookmarksDrawerPinned)
@@ -4176,8 +4437,11 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
 
             // Run the commands associated with the type.
             if (bookmarksDatabaseHelper!!.isFolder(databaseId)) {  // The bookmark is a folder.
+                // Get the folder ID.
+                val folderId = bookmarksDatabaseHelper!!.getFolderId(databaseId)
+
                 // Get a cursor of all the bookmarks in the folder.
-                val bookmarksCursor = bookmarksDatabaseHelper!!.getFolderBookmarks(databaseId)
+                val bookmarksCursor = bookmarksDatabaseHelper!!.getFolderBookmarks(folderId)
 
                 // Move to the first entry in the cursor.
                 bookmarksCursor.moveToFirst()
@@ -4185,7 +4449,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                 // Open each bookmark
                 for (i in 0 until bookmarksCursor.count) {
                     // Load the bookmark in a new tab, moving to the tab for the first bookmark if the drawer is not pinned.
-                    addNewTab(bookmarksCursor.getString(bookmarksCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_URL)), !bookmarksDrawerPinned && (i == 0))
+                    addNewPage(bookmarksCursor.getString(bookmarksCursor.getColumnIndexOrThrow(BOOKMARK_URL)), adjacent = false, moveToTab = !bookmarksDrawerPinned && (i == 0))
 
                     // Move to the next bookmark.
                     bookmarksCursor.moveToNext()
@@ -4201,7 +4465,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                 bookmarkCursor.moveToFirst()
 
                 // Load the bookmark in a new tab and move to the tab if the drawer is not pinned.
-                addNewTab(bookmarkCursor.getString(bookmarkCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_URL)), !bookmarksDrawerPinned)
+                addNewPage(bookmarkCursor.getString(bookmarkCursor.getColumnIndexOrThrow(BOOKMARK_URL)), adjacent = true, moveToTab = !bookmarksDrawerPinned)
 
                 // Close the cursor.
                 bookmarkCursor.close()
@@ -4221,18 +4485,34 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
 
             override fun onDrawerOpened(drawerView: View) {}
 
-            override fun onDrawerClosed(drawerView: View) {
-                // Reset the drawer icon when the drawer is closed.  Otherwise, it remains an arrow if the drawer is open when the app is restarted.
-                actionBarDrawerToggle!!.syncState()
-            }
+            override fun onDrawerClosed(drawerView: View) {}
 
             override fun onDrawerStateChanged(newState: Int) {
                 if (newState == DrawerLayout.STATE_SETTLING || newState == DrawerLayout.STATE_DRAGGING) {  // A drawer is opening or closing.
                     // Update the navigation menu items if the WebView is not null.
                     if (currentWebView != null) {
+                        // Set the enabled status of the menu items.
                         navigationBackMenuItem.isEnabled = currentWebView!!.canGoBack()
                         navigationForwardMenuItem.isEnabled = currentWebView!!.canGoForward()
+                        navigationScrollToBottomMenuItem.isEnabled = (currentWebView!!.canScrollVertically(-1) || currentWebView!!.canScrollVertically(1))
                         navigationHistoryMenuItem.isEnabled = currentWebView!!.canGoBack() || currentWebView!!.canGoForward()
+
+                        // Update the scroll menu item.
+                        if (currentWebView!!.scrollY == 0) {  // The WebView is scrolled to the top.
+                            // Set the title.
+                            navigationScrollToBottomMenuItem.title = getString(R.string.scroll_to_bottom)
+
+                            // Set the icon.
+                            navigationScrollToBottomMenuItem.icon = AppCompatResources.getDrawable(applicationContext, R.drawable.move_down_enabled)
+                        } else {  // The WebView is not scrolled to the top.
+                            // Set the title.
+                            navigationScrollToBottomMenuItem.title = getString(R.string.scroll_to_top)
+
+                            // Set the icon.
+                            navigationScrollToBottomMenuItem.icon = AppCompatResources.getDrawable(applicationContext, R.drawable.move_up_enabled)
+                        }
+
+                        // Display the number of blocked requests.
                         navigationRequestsMenuItem.title = getString(R.string.requests) + " - " + currentWebView!!.getRequestsCount(BLOCKED_REQUESTS)
 
                         // Hide the keyboard (if displayed).
@@ -4245,6 +4525,20 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                     // Clear the focus from from the WebView if it is not null, which can happen if a user opens a drawer while the browser is being resumed.
                     // Clearing the focus from the WebView removes any text selection markers and context menus, which otherwise draw above the open drawers.
                     currentWebView?.clearFocus()
+
+                    if (bottomAppBar && navigationDrawerFirstView) {
+                        // Reset the navigation drawer first view flag.
+                        navigationDrawerFirstView = false
+
+                        // Get a handle for the navigation recycler view.
+                        val navigationRecyclerView = navigationView.getChildAt(0) as RecyclerView
+
+                        // Get the navigation linear layout manager.
+                        val navigationLinearLayoutManager = navigationRecyclerView.layoutManager as LinearLayoutManager
+
+                        // Scroll the navigation drawer to the bottom.
+                        navigationLinearLayoutManager.scrollToPositionWithOffset(13, 0)
+                    }
                 }
             }
         })
@@ -4269,15 +4563,15 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
     }
 
     @SuppressLint("ClickableViewAccessibility")
-    override fun initializeWebView(nestedScrollWebView: NestedScrollWebView, pageNumber: Int, progressBar: ProgressBar, urlString: String, restoringState: Boolean) {
+    override fun initializeWebView(nestedScrollWebView: NestedScrollWebView, pagePosition: Int, progressBar: ProgressBar, urlString: String, restoringState: Boolean) {
         // Get the WebView theme.
         val webViewTheme = sharedPreferences.getString(getString(R.string.webview_theme_key), getString(R.string.webview_theme_default_value))
 
         // Get the WebView theme entry values string array.
         val webViewThemeEntryValuesStringArray = resources.getStringArray(R.array.webview_theme_entry_values)
 
-        // Set the WebView theme if device is running API >= 29 and algorithmic darkening is supported.
-        if (Build.VERSION.SDK_INT >= 29 && WebViewFeature.isFeatureSupported(WebViewFeature.ALGORITHMIC_DARKENING)) {
+        // Set the WebView theme if algorithmic darkening is supported.
+        if (WebViewFeature.isFeatureSupported(WebViewFeature.ALGORITHMIC_DARKENING)) {
             // Set the WebView them.  A switch statement cannot be used because the WebView theme entry values string array is not a compile time constant.
             if (webViewTheme == webViewThemeEntryValuesStringArray[1]) {  // The light theme is selected.
                 // Turn off algorithmic darkening.
@@ -4308,9 +4602,6 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
             }
         }
 
-        // Get a handle for the input method manager.
-        val inputMethodManager = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
-
         // Set the app bar scrolling.
         nestedScrollWebView.isNestedScrollingEnabled = scrollAppBar
 
@@ -4396,8 +4687,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
 
                         // The deprecated command can be switched to `WindowInsetsController` once the minimum API >= 30.
                         @Suppress("DEPRECATION")
-                        rootFrameLayout.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or
-                                View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
+                        rootFrameLayout.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
                     } else {  // Switch to normal viewing mode.
                         // Show the app bar if it was hidden.
                         if (hideAppBar) {
@@ -4448,9 +4738,9 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                 }
             }
 
-            override fun onFling(motionEvent1: MotionEvent, motionEvent2: MotionEvent, velocityX: Float, velocityY: Float): Boolean {
+            override fun onFling(motionEvent1: MotionEvent?, motionEvent2: MotionEvent, velocityX: Float, velocityY: Float): Boolean {
                 // Scroll the bottom app bar if enabled.
-                if (bottomAppBar && scrollAppBar && !objectAnimator.isRunning) {
+                if (bottomAppBar && scrollAppBar && !objectAnimator.isRunning && (motionEvent1 != null)) {
                     // Calculate the Y change.
                     val motionY = motionEvent2.y - motionEvent1.y
 
@@ -4485,13 +4775,12 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
         registerForContextMenu(nestedScrollWebView)
 
         // Allow the downloading of files.
-        nestedScrollWebView.setDownloadListener { downloadUrlString: String?, userAgent: String?, contentDisposition: String?, mimetype: String?, contentLength: Long ->
-            // Check the download preference.
+        nestedScrollWebView.setDownloadListener { downloadUrlString: String, userAgent: String, contentDisposition: String, mimetype: String, contentLength: Long ->
+            // Use the specified download provider.
             if (downloadWithExternalApp) {  // Download with an external app.
-                downloadUrlWithExternalApp(downloadUrlString!!)
-            } else {  // Handle the download inside of Privacy Browser.
-                // Define a formatted file size string.
-
+                // Download with an external app.
+                saveWithExternalApp(downloadUrlString)
+            } else {  // Download with Privacy Browser or Android's download manager.
                 // Process the content length if it contains data.
                 val formattedFileSizeString = if (contentLength > 0) {  // The content length is greater than 0.
                     // Format the content length as a string.
@@ -4502,10 +4791,10 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                 }
 
                 // Get the file name from the content disposition.
-                val fileNameString = UrlHelper.getFileName(this, contentDisposition, mimetype, downloadUrlString!!)
+                val fileNameString = UrlHelper.getFileName(this, contentDisposition, mimetype, downloadUrlString)
 
-                // Instantiate the save dialog.
-                val saveDialogFragment = SaveDialog.saveUrl(downloadUrlString, fileNameString, formattedFileSizeString, userAgent!!, nestedScrollWebView.acceptCookies)
+                // Instantiate the save dialog according.
+                val saveDialogFragment = SaveDialog.saveUrl(downloadUrlString, fileNameString, formattedFileSizeString, userAgent, nestedScrollWebView.acceptCookies)
 
                 // Try to show the dialog.  The download listener continues to function even when the WebView is paused.  Attempting to display a dialog in that state leads to a crash.
                 try {
@@ -4516,6 +4805,29 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                     pendingDialogsArrayList.add(PendingDialogDataClass(saveDialogFragment, getString(R.string.save_dialog)))
                 }
             }
+
+            // Get the current page position.
+            val currentPagePosition = webViewStateAdapter!!.getPositionForId(nestedScrollWebView.webViewFragmentId)
+
+            // Get the corresponding tab.
+            val tab = tabLayout.getTabAt(currentPagePosition)!!
+
+            // Get the tab custom view.
+            val tabCustomView = tab.customView!!
+
+            // Get the tab views.
+            val tabFavoriteIconImageView = tabCustomView.findViewById<ImageView>(R.id.favorite_icon_imageview)
+            val tabTitleTextView = tabCustomView.findViewById<TextView>(R.id.title_textview)
+
+            // Restore the previous webpage favorite icon and title if the title is currently set to `Loading...`.
+            if (tabTitleTextView.text.toString() == getString(R.string.loading)) {
+                // Restore the previous webpage title text.
+                tabTitleTextView.text = nestedScrollWebView.previousWebpageTitle
+
+                // Restore the previous webpage favorite icon if it is not null.
+                if (nestedScrollWebView.previousFavoriteIconDrawable != null)
+                    tabFavoriteIconImageView.setImageDrawable(nestedScrollWebView.previousFavoriteIconDrawable)
+            }
         }
 
         // Update the find on page count.
@@ -4608,7 +4920,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                             val tabFavoriteIconImageView = tabView.findViewById<ImageView>(R.id.favorite_icon_imageview)
 
                             // Display the favorite icon in the tab.
-                            tabFavoriteIconImageView.setImageBitmap(Bitmap.createScaledBitmap(icon, 64, 64, true))
+                            tabFavoriteIconImageView.setImageBitmap(Bitmap.createScaledBitmap(icon, 128, 128, true))
                         }
                     }
                 }
@@ -4900,7 +5212,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
 
                         // Increment the blocked requests counters.
                         nestedScrollWebView.incrementRequestsCount(BLOCKED_REQUESTS)
-                        nestedScrollWebView.incrementRequestsCount(ULTRALIST)
+                        nestedScrollWebView.incrementRequestsCount(com.stoutner.privacybrowser.views.ULTRALIST)
 
                         // Update the titles of the filter lists menu items if the WebView is currently displayed.
                         if (webViewDisplayed) {
@@ -4912,7 +5224,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                                 // Update the options menu if it has been populated.
                                 if (optionsMenu != null) {
                                     optionsFilterListsMenuItem.title = getString(R.string.filterlists) + " - " + nestedScrollWebView.getRequestsCount(BLOCKED_REQUESTS)
-                                    optionsUltraListMenuItem.title = nestedScrollWebView.getRequestsCount(ULTRALIST).toString() + " - " + getString(R.string.ultralist)
+                                    optionsUltraListMenuItem.title = nestedScrollWebView.getRequestsCount(com.stoutner.privacybrowser.views.ULTRALIST).toString() + " - " + getString(R.string.ultralist)
                                 }
                             }
                         }
@@ -5139,8 +5451,14 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                 // Instantiate an HTTP authentication dialog.
                 val httpAuthenticationDialogFragment = HttpAuthenticationDialog.displayDialog(host, realm, nestedScrollWebView.webViewFragmentId)
 
-                // Show the HTTP authentication dialog.
-                httpAuthenticationDialogFragment.show(supportFragmentManager, getString(R.string.http_authentication))
+                // Try to show the dialog.  WebView can receive an HTTP authentication request even after the app has been paused.  Attempting to display a dialog in that state leads to a crash.
+                try {
+                    // Show the HTTP authentication dialog.
+                    httpAuthenticationDialogFragment.show(supportFragmentManager, getString(R.string.http_authentication))
+                } catch (exception: Exception) {  // The dialog could not be shown.
+                    // Add the dialog to the pending dialog array list.  It will be displayed in `onStart()`.
+                    pendingDialogsArrayList.add(PendingDialogDataClass(httpAuthenticationDialogFragment, getString(R.string.http_authentication)))
+                }
             }
 
             override fun onPageStarted(webView: WebView, url: String, favicon: Bitmap?) {
@@ -5187,8 +5505,8 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
 
                 // Update the URL text bar if the page is currently selected and the URL edit text is not currently being edited.
                 if ((tabLayout.selectedTabPosition == currentPagePosition) && !urlEditText.hasFocus()) {
-                    // Display the formatted URL text.
-                    urlEditText.setText(url)
+                    // Display the formatted URL text.  The nested scroll WebView current URL preserves any initial `view-source:`, and opposed to the method URL variable.
+                    urlEditText.setText(nestedScrollWebView.currentUrl)
 
                     // Highlight the URL syntax.
                     UrlHelper.highlightSyntax(urlEditText, initialGrayColorSpan, finalGrayColorSpan, redColorSpan)
@@ -5378,7 +5696,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                     // Instantiate an SSL certificate error alert dialog.
                     val sslCertificateErrorDialogFragment = SslCertificateErrorDialog.displayDialog(error, nestedScrollWebView.webViewFragmentId)
 
-                    // Try to show the dialog.  The SSL error handler continues to function even when the WebView is paused.  Attempting to display a dialog in that state leads to a crash.
+                    // Try to show the dialog.  The SSL error handler continues to function even when the app has been stopped.  Attempting to display a dialog in that state leads to a crash.
                     try {
                         // Show the SSL certificate error dialog.
                         sslCertificateErrorDialogFragment.show(supportFragmentManager, getString(R.string.ssl_certificate_error))
@@ -5394,7 +5712,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
         if (restoringState) {  // The state is being restored.
             // Resume the nested scroll WebView JavaScript timers.
             nestedScrollWebView.resumeTimers()
-        } else if (pageNumber == 0) {  // The first page is being loaded.
+        } else if (pagePosition == 0) {  // The first page is being loaded.
             // Set this nested scroll WebView as the current WebView.
             currentWebView = nestedScrollWebView
 
@@ -5440,10 +5758,6 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
             } else {  // Load the URL.
                 loadUrl(nestedScrollWebView, urlToLoadString!!)
             }
-
-            // Reset the intent.  This prevents a duplicate tab from being created on a subsequent restart if loading an link from a new intent on restart.
-            // For example, this prevents a duplicate tab if a link is loaded from the Guide after changing the theme in the guide and then changing the theme again in the main activity.
-            intent = Intent()
         } else {  // This is not the first tab.
             // Load the URL.
             loadUrl(nestedScrollWebView, urlString)
@@ -5453,24 +5767,17 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                 // Request focus for the URL text box.
                 urlEditText.requestFocus()
 
-                // Create a display keyboard handler.
-                val displayKeyboardHandler = Handler(Looper.getMainLooper())
-
-                // Create a display keyboard runnable.
-                val displayKeyboardRunnable = Runnable {
-                    // Display the keyboard.
+                // Display the keyboard once the tab layout has settled.
+                tabLayout.post {
                     inputMethodManager.showSoftInput(urlEditText, 0)
                 }
-
-                // Display the keyboard after 100 milliseconds, which leaves enough time for the tab to transition.
-                displayKeyboardHandler.postDelayed(displayKeyboardRunnable, 100)
             }
         }
     }
 
     private fun loadBookmarksFolder() {
         // Update the bookmarks cursor with the contents of the bookmarks database for the current folder.
-        bookmarksCursor = bookmarksDatabaseHelper!!.getBookmarksByDisplayOrder(currentBookmarksFolder)
+        bookmarksCursor = bookmarksDatabaseHelper!!.getBookmarksByDisplayOrder(currentBookmarksFolderId)
 
         // Populate the bookmarks cursor adapter.
         bookmarksCursorAdapter = object : CursorAdapter(this, bookmarksCursor, false) {
@@ -5485,7 +5792,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                 val bookmarkNameTextView = view.findViewById<TextView>(R.id.bookmark_name)
 
                 // Get the favorite icon byte array from the cursor.
-                val favoriteIconByteArray = cursor.getBlob(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.FAVORITE_ICON))
+                val favoriteIconByteArray = cursor.getBlob(cursor.getColumnIndexOrThrow(FAVORITE_ICON))
 
                 // Convert the byte array to a bitmap beginning at the first byte and ending at the last.
                 val favoriteIconBitmap = BitmapFactory.decodeByteArray(favoriteIconByteArray, 0, favoriteIconByteArray.size)
@@ -5494,10 +5801,10 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                 bookmarkFavoriteIcon.setImageBitmap(favoriteIconBitmap)
 
                 // Display the bookmark name from the cursor in the bookmark name text view.
-                bookmarkNameTextView.text = cursor.getString(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_NAME))
+                bookmarkNameTextView.text = cursor.getString(cursor.getColumnIndexOrThrow(BOOKMARK_NAME))
 
                 // Make the font bold for folders.
-                if (cursor.getInt(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.IS_FOLDER)) == 1)
+                if (cursor.getInt(cursor.getColumnIndexOrThrow(IS_FOLDER)) == 1)
                     bookmarkNameTextView.typeface = Typeface.DEFAULT_BOLD
                 else  // Reset the font to default for normal bookmarks.
                     bookmarkNameTextView.typeface = Typeface.DEFAULT
@@ -5508,10 +5815,10 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
         bookmarksListView.adapter = bookmarksCursorAdapter
 
         // Set the bookmarks drawer title.
-        if (currentBookmarksFolder.isEmpty())
+        if (currentBookmarksFolderId == HOME_FOLDER_ID)  // The current bookmarks folder is the home folder.
             bookmarksTitleTextView.setText(R.string.bookmarks)
         else
-            bookmarksTitleTextView.text = currentBookmarksFolder
+            bookmarksTitleTextView.text = bookmarksDatabaseHelper!!.getFolderName(currentBookmarksFolderId)
     }
 
     private fun loadUrl(nestedScrollWebView: NestedScrollWebView, url: String) {
@@ -5530,7 +5837,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
         var urlString = ""
 
         // Check to see if the unformatted URL string is a valid URL.  Otherwise, convert it into a search.
-        if (unformattedUrlString.startsWith("content://")) {  // This is a content URL.
+        if (unformattedUrlString.startsWith("content://") || unformattedUrlString.startsWith("view-source:")) {  // This is a content or source URL.
             // Load the entire content URL.
             urlString = unformattedUrlString
         } else if (Patterns.WEB_URL.matcher(unformattedUrlString).matches() || unformattedUrlString.startsWith("http://") || unformattedUrlString.startsWith("https://") ||
@@ -5588,12 +5895,56 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
         loadUrl(currentWebView!!, urlString)
     }
 
-    override fun navigateHistory(url: String, steps: Int) {
+    override fun navigateHistory(steps: Int) {
+        // Get the current web back forward list.
+        val webBackForwardList = currentWebView!!.copyBackForwardList()
+
+        // Calculate the target index.
+        val targetIndex = webBackForwardList.currentIndex + steps
+
+        // Get the previous entry data.
+        val previousUrl = webBackForwardList.getItemAtIndex(targetIndex).url
+        val previousFavoriteIcon = webBackForwardList.getItemAtIndex(targetIndex).favicon
+
         // Apply the domain settings.
-        applyDomainSettings(currentWebView!!, url, resetTab = false, reloadWebsite = false, loadUrl = false)
+        applyDomainSettings(currentWebView!!, previousUrl, resetTab = false, reloadWebsite = false, loadUrl = false)
+
+        // Get the current tab.
+        val tab = tabLayout.getTabAt(tabLayout.selectedTabPosition)!!
+
+        // Get the custom view from the tab.
+        val tabView = tab.customView!!
+
+        // Get the favorite icon image view from the tab.
+        val tabFavoriteIconImageView = tabView.findViewById<ImageView>(R.id.favorite_icon_imageview)
+
+        // Store the previous favorite icon.
+        if (previousFavoriteIcon == null)
+            currentWebView!!.setFavoriteIcon(defaultFavoriteIconBitmap)
+        else
+            currentWebView!!.setFavoriteIcon(previousFavoriteIcon)
+
+        // Display the previous favorite icon in the tab.
+        tabFavoriteIconImageView.setImageBitmap(Bitmap.createScaledBitmap(currentWebView!!.getFavoriteIcon(), 128, 128, true))
 
         // Load the history entry.
         currentWebView!!.goBackOrForward(steps)
+
+        // Create a handler to update the URL edit box.
+        val urlEditTextUpdateHandler = Handler(Looper.getMainLooper())
+
+        // Create a runnable to update the URL edit box.
+        val urlEditTextUpdateRunnable = Runnable {
+            // Update the URL edit text.
+            urlEditText.setText(currentWebView!!.url)
+
+            // Disable the wide viewport if the source is being viewed.
+            if (currentWebView!!.url!!.startsWith("view-source:"))
+                currentWebView!!.settings.useWideViewPort = false
+        }
+
+        // Update the URL edit text after 50 milliseconds, so that the WebView has enough time to navigate to the new URL.
+        urlEditTextUpdateHandler.postDelayed(urlEditTextUpdateRunnable, 50)
     }
 
     override fun openFile(dialogFragment: DialogFragment) {
@@ -5650,6 +6001,11 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
             currentWebView!!.loadUrl(openFilePath)
         }
     }
+    // The view parameter cannot be removed because it is called from the layout onClick.
+    fun openNavigationDrawer(@Suppress("UNUSED_PARAMETER")view: View) {
+        // Open the navigation drawer.
+        drawerLayout.openDrawer(GravityCompat.START)
+    }
 
     private fun openWithApp(url: String) {
         // Create an open with app intent with `ACTION_VIEW`.
@@ -5693,17 +6049,8 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
     }
 
     override fun pinnedErrorGoBack() {
-        // Get the current web back forward list.
-        val webBackForwardList = currentWebView!!.copyBackForwardList()
-
-        // Get the previous entry URL.
-        val previousUrl = webBackForwardList.getItemAtIndex(webBackForwardList.currentIndex - 1).url
-
-        // Apply the domain settings.
-        applyDomainSettings(currentWebView!!, previousUrl, resetTab = false, reloadWebsite = false, loadUrl = false)
-
-        // Go back.
-        currentWebView!!.goBack()
+        // Navigate back one page.
+        navigateHistory(-1)
     }
 
     private fun sanitizeUrl(urlString: String): String {
@@ -5722,7 +6069,76 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
         return sanitizedUrlString
     }
 
-    override fun saveUrl(originalUrlString: String, fileNameString: String, dialogFragment: DialogFragment) {
+    override fun saveWithAndroidDownloadManager(dialogFragment: DialogFragment) {
+        // Get the dialog.
+        val dialog = dialogFragment.dialog!!
+
+        // Get handles for the dialog views.
+        val dialogUrlEditText = dialog.findViewById<EditText>(R.id.url_edittext)
+        val downloadDirectoryRadioGroup = dialog.findViewById<RadioGroup>(R.id.download_directory_radiogroup)
+        val dialogFileNameEditText = dialog.findViewById<EditText>(R.id.file_name_edittext)
+
+        // Get the string from the edit texts, which may have been modified by the user.
+        val saveUrlString = dialogUrlEditText.text.toString()
+        val fileNameString = dialogFileNameEditText.text.toString()
+
+        // Get a handle for the system download service.
+        val downloadManager = getSystemService(DOWNLOAD_SERVICE) as DownloadManager
+
+        // Parse the URL.
+        val downloadRequest = DownloadManager.Request(Uri.parse(saveUrlString))
+
+        // 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 (cookieManager.acceptCookie()) {
+            // Get the cookies for the URL.
+            val cookiesString = cookieManager.getCookie(saveUrlString)
+
+            // Add the cookies to the download request.  In the HTTP request header, cookies are named `Cookie`.
+            downloadRequest.addRequestHeader("Cookie", cookiesString)
+        }
+
+        // Get the download directory.
+        val downloadDirectory = when (downloadDirectoryRadioGroup.checkedRadioButtonId) {
+            R.id.downloads_radiobutton -> Environment.DIRECTORY_DOWNLOADS
+            R.id.documents_radiobutton -> Environment.DIRECTORY_DOCUMENTS
+            R.id.pictures_radiobutton -> Environment.DIRECTORY_PICTURES
+            else -> Environment.DIRECTORY_MUSIC
+        }
+
+        // Set the download destination.
+        downloadRequest.setDestinationInExternalPublicDir(downloadDirectory, fileNameString)
+
+        // Allow media scanner to index the download if it is a media file.  This is automatic for API >= 29.
+        @Suppress("DEPRECATION")
+        if (Build.VERSION.SDK_INT <= 28)
+            downloadRequest.allowScanningByMediaScanner()
+
+        // Add the URL as the description for the download.
+        downloadRequest.setDescription(saveUrlString)
+
+        // Show the download notification after the download is completed.
+        downloadRequest.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
+
+        // Initiate the download.
+        downloadManager.enqueue(downloadRequest)
+    }
+
+    private fun saveWithExternalApp(url: String) {
+        // Create a download intent.  Not specifying the action type will display the maximum number of options.
+        val downloadIntent = Intent()
+
+        // Set the URI and the mime type.
+        downloadIntent.setDataAndType(Uri.parse(url), "text/html")
+
+        // Flag the intent to open in a new task.
+        downloadIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
+
+        // Show the chooser.
+        startActivity(Intent.createChooser(downloadIntent, getString(R.string.download_with_external_app)))
+    }
+
+    override fun saveWithPrivacyBrowser(originalUrlString: String, fileNameString: String, dialogFragment: DialogFragment) {
         // Store the URL.  This will be used in the save URL activity result launcher.
         saveUrlString = if (originalUrlString.startsWith("data:")) {
             // Save the original URL.
@@ -5734,7 +6150,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
             // Get a handle for the dialog URL edit text.
             val dialogUrlEditText = dialog.findViewById<EditText>(R.id.url_edittext)
 
-            // Get the URL from the edit text, which may have been modified.
+            // Get the URL from the edit text, which may have been modified by the user.
             dialogUrlEditText.text.toString()
         }
 
@@ -5746,16 +6162,16 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
         // Stop the swipe to refresh indicator if it is running
         swipeRefreshLayout.isRefreshing = false
 
-        // Get the WebView tab fragment.
-        val webViewTabFragment = webViewStateAdapter!!.getPageFragment(pageNumber)
+        // Try to set the current WebView.  This will fail if the WebView has not yet been populated.
+        try {
+            // Get the WebView tab fragment.
+            val webViewTabFragment = webViewStateAdapter!!.getPageFragment(pageNumber)
 
-        // Get the fragment view.
-        val webViewFragmentView = webViewTabFragment.view
+            // Get the fragment view.
+            val webViewFragmentView = webViewTabFragment.view
 
-        // Set the current WebView if the fragment view is not null.
-        if (webViewFragmentView != null) {  // The fragment has been populated.
             // Store the current WebView.
-            currentWebView = webViewFragmentView.findViewById(R.id.nestedscroll_webview)
+            currentWebView = webViewFragmentView!!.findViewById(R.id.nestedscroll_webview)
 
             // Update the status of swipe to refresh.
             if (currentWebView!!.swipeToRefresh) {  // Swipe to refresh is enabled.
@@ -5772,9 +6188,6 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
             // Update the privacy icons.  `true` redraws the icons in the app bar.
             updatePrivacyIcons(true)
 
-            // Get a handle for the input method manager.
-            val inputMethodManager = (getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager)
-
             // Get the current URL.
             val urlString = currentWebView!!.url
 
@@ -5815,8 +6228,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                 // Remove any background on the URL relative layout.
                 urlRelativeLayout.background = AppCompatResources.getDrawable(this, R.color.transparent)
             }
-        } else if ((pageNumber == savedTabPosition) || (pageNumber == (webViewStateAdapter!!.itemCount - 1))) {  // The tab has not been populated yet.
-            //  Try again in 100 milliseconds if the app is being restored or the a new tab has been added (the last tab).
+        }  catch (exception: Exception) {  //  Try again in 10 milliseconds if the WebView has not yet been populated.
             // Create a handler to set the current WebView.
             val setCurrentWebViewHandler = Handler(Looper.getMainLooper())
 
@@ -5826,8 +6238,8 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                 setCurrentWebView(pageNumber)
             }
 
-            // Try setting the current WebView again after 100 milliseconds.
-            setCurrentWebViewHandler.postDelayed(setCurrentWebWebRunnable, 100)
+            // Try setting the current WebView again after 10 milliseconds.
+            setCurrentWebViewHandler.postDelayed(setCurrentWebWebRunnable, 10)
         }
     }
 
@@ -5859,7 +6271,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
         val domainsCount = domainsCursor.count
 
         // Get the domain name column index.
-        val domainNameColumnIndex = domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.DOMAIN_NAME)
+        val domainNameColumnIndex = domainsCursor.getColumnIndexOrThrow(DOMAIN_NAME)
 
         // Populate the domain settings set.
         for (i in 0 until domainsCount) {