+ // Get the current user agent.
+ String initialUserAgent = currentWebView.getSettings().getUserAgentString();
+
+ // Initialize a variable to track if the user agent changes.
+ boolean userAgentChanged = false;
+
+ // Parse the URL into a URI.
+ Uri uri = Uri.parse(url);
+
+ // Extract the domain from `uri`.
+ String hostName = uri.getHost();
+
+ // Initialize `loadingNewDomainName`.
+ boolean loadingNewDomainName;
+
+ // If either `hostName` or `currentDomainName` are `null`, run the options for loading a new domain name.
+ // The lint suggestion to simplify the `if` statement is incorrect, because `hostName.equals(currentDomainName)` can produce a `null object reference.`
+ //noinspection SimplifiableIfStatement
+ if ((hostName == null) || (currentDomainName == null)) {
+ loadingNewDomainName = true;
+ } else { // Determine if `hostName` equals `currentDomainName`.
+ loadingNewDomainName = !hostName.equals(currentDomainName);
+ }
+
+ // Strings don't like to be null.
+ if (hostName == null) {
+ hostName = "";
+ }
+
+ // Only apply the domain settings if a new domain is being loaded. This allows the user to set temporary settings for JavaScript, cookies, DOM storage, etc.
+ if (loadingNewDomainName) {
+ // Set the new `hostname` as the `currentDomainName`.
+ currentDomainName = hostName;
+
+ // Reset the ignoring of pinned domain information.
+ ignorePinnedDomainInformation = false;
+
+ // Reset the favorite icon if specified.
+ if (resetFavoriteIcon) {
+ // Store the favorite icon bitmap.
+ favoriteIconBitmap = favoriteIconDefaultBitmap;
+
+ // Get a handle for the tab layout.
+ TabLayout tabLayout = findViewById(R.id.tablayout);
+
+ // Get the current tab.
+ TabLayout.Tab currentTab = tabLayout.getTabAt(tabLayout.getSelectedTabPosition());
+
+ // Remove the warning below that the current tab might be null.
+ assert currentTab != null;
+
+ // Get the current tab custom view.
+ View currentTabCustomView = currentTab.getCustomView();
+
+ // Remove the warning below that the current tab custom view might be null.
+ assert currentTabCustomView != null;
+
+ // Get the current tab favorite icon image view.
+ ImageView currentTabFavoriteIconImageView = currentTabCustomView.findViewById(R.id.favorite_icon_imageview);
+
+ // Set the default favorite icon as the favorite icon for this tab.
+ currentTabFavoriteIconImageView.setImageBitmap(Bitmap.createScaledBitmap(favoriteIconBitmap, 64, 64, true));
+ }
+
+ // Get a handle for the swipe refresh layout.
+ SwipeRefreshLayout swipeRefreshLayout = findViewById(R.id.swiperefreshlayout);
+
+ // Initialize the database handler. The `0` specifies the database version, but that is ignored and set instead using a constant in `DomainsDatabaseHelper`.
+ DomainsDatabaseHelper domainsDatabaseHelper = new DomainsDatabaseHelper(this, null, null, 0);
+
+ // Get a full cursor from `domainsDatabaseHelper`.
+ Cursor domainNameCursor = domainsDatabaseHelper.getDomainNameCursorOrderedByDomain();
+
+ // Initialize `domainSettingsSet`.
+ Set<String> domainSettingsSet = new HashSet<>();
+
+ // Get the domain name column index.
+ int domainNameColumnIndex = domainNameCursor.getColumnIndex(DomainsDatabaseHelper.DOMAIN_NAME);
+
+ // Populate `domainSettingsSet`.
+ for (int i = 0; i < domainNameCursor.getCount(); i++) {
+ // Move `domainsCursor` to the current row.
+ domainNameCursor.moveToPosition(i);
+
+ // Store the domain name in `domainSettingsSet`.
+ domainSettingsSet.add(domainNameCursor.getString(domainNameColumnIndex));
+ }
+
+ // Close `domainNameCursor.
+ domainNameCursor.close();
+
+ // Initialize the domain name in database variable.
+ String domainNameInDatabase = null;
+
+ // Check the hostname against the domain settings set.
+ if (domainSettingsSet.contains(hostName)) { // The hostname is contained in the domain settings set.
+ // Record the domain name in the database.
+ domainNameInDatabase = hostName;
+
+ // Set the domain settings applied tracker to true.
+ currentWebView.setDomainSettingsApplied(true);
+ } else { // The hostname is not contained in the domain settings set.
+ // Set the domain settings applied tracker to false.
+ currentWebView.setDomainSettingsApplied(false);
+ }
+
+ // Check all the subdomains of the host name against wildcard domains in the domain cursor.
+ while (!currentWebView.getDomainSettingsApplied() && hostName.contains(".")) { // Stop checking if domain settings are already applied or there are no more `.` in the host name.
+ if (domainSettingsSet.contains("*." + hostName)) { // Check the host name prepended by `*.`.
+ // Set the domain settings applied tracker to true.
+ currentWebView.setDomainSettingsApplied(true);
+
+ // Store the applied domain names as it appears in the database.
+ domainNameInDatabase = "*." + hostName;
+ }
+
+ // Strip out the lowest subdomain of of the host name.
+ hostName = hostName.substring(hostName.indexOf(".") + 1);
+ }
+
+
+ // Get a handle for the shared preference.
+ SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
+
+ // Store the general preference information.
+ String defaultFontSizeString = sharedPreferences.getString("font_size", getString(R.string.font_size_default_value));
+ String defaultUserAgentName = sharedPreferences.getString("user_agent", getString(R.string.user_agent_default_value));
+ defaultCustomUserAgentString = sharedPreferences.getString("custom_user_agent", getString(R.string.custom_user_agent_default_value));
+ boolean defaultSwipeToRefresh = sharedPreferences.getBoolean("swipe_to_refresh", true);
+ nightMode = sharedPreferences.getBoolean("night_mode", false);
+ boolean displayWebpageImages = sharedPreferences.getBoolean("display_webpage_images", true);
+
+ if (currentWebView.getDomainSettingsApplied()) { // The url has custom domain settings.
+ // Get a cursor for the current host and move it to the first position.
+ Cursor currentHostDomainSettingsCursor = domainsDatabaseHelper.getCursorForDomainName(domainNameInDatabase);
+ currentHostDomainSettingsCursor.moveToFirst();
+
+ // Get the settings from the cursor.
+ currentWebView.setDomainSettingsDatabaseId(currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper._ID)));
+ javaScriptEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_JAVASCRIPT)) == 1);
+ firstPartyCookiesEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FIRST_PARTY_COOKIES)) == 1);
+ thirdPartyCookiesEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_THIRD_PARTY_COOKIES)) == 1);
+ domStorageEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_DOM_STORAGE)) == 1);
+ // Form data can be removed once the minimum API >= 26.
+ saveFormDataEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FORM_DATA)) == 1);
+ easyListEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYLIST)) == 1);
+ easyPrivacyEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYPRIVACY)) == 1);
+ fanboysAnnoyanceListEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST)) == 1);
+ fanboysSocialBlockingListEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST)) == 1);
+ ultraPrivacyEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY)) == 1);
+ blockAllThirdPartyRequests = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS)) == 1);
+ String userAgentName = currentHostDomainSettingsCursor.getString(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.USER_AGENT));
+ int fontSize = currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.FONT_SIZE));
+ int swipeToRefreshInt = currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SWIPE_TO_REFRESH));
+ int nightModeInt = currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.NIGHT_MODE));
+ int displayWebpageImagesInt = currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.DISPLAY_IMAGES));
+ pinnedSslCertificate = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.PINNED_SSL_CERTIFICATE)) == 1);
+ pinnedSslIssuedToCName = currentHostDomainSettingsCursor.getString(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_COMMON_NAME));
+ pinnedSslIssuedToOName = currentHostDomainSettingsCursor.getString(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATION));
+ pinnedSslIssuedToUName = currentHostDomainSettingsCursor.getString(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATIONAL_UNIT));
+ pinnedSslIssuedByCName = currentHostDomainSettingsCursor.getString(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_COMMON_NAME));
+ pinnedSslIssuedByOName = currentHostDomainSettingsCursor.getString(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATION));
+ pinnedSslIssuedByUName = currentHostDomainSettingsCursor.getString(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATIONAL_UNIT));
+ pinnedIpAddresses = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.PINNED_IP_ADDRESSES)) == 1);
+ pinnedHostIpAddresses = currentHostDomainSettingsCursor.getString(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.IP_ADDRESSES));
+
+ // Set `nightMode` according to `nightModeInt`. If `nightModeInt` is `DomainsDatabaseHelper.NIGHT_MODE_SYSTEM_DEFAULT` the current setting from `sharedPreferences` will be used.
+ switch (nightModeInt) {
+ case DomainsDatabaseHelper.NIGHT_MODE_ENABLED:
+ nightMode = true;
+ break;
+
+ case DomainsDatabaseHelper.NIGHT_MODE_DISABLED:
+ nightMode = false;
+ break;
+ }
+
+ // Store the domain JavaScript status. This is used by the options menu night mode toggle.
+ domainSettingsJavaScriptEnabled = javaScriptEnabled;
+
+ // Enable JavaScript if night mode is enabled.
+ if (nightMode) {
+ javaScriptEnabled = true;
+ }
+
+ // Set the pinned SSL certificate start date to `null` if the saved date `long` is 0.
+ if (currentHostDomainSettingsCursor.getLong(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_START_DATE)) == 0) {
+ pinnedSslStartDate = null;