+ if (nestedScrollWebView.getDomainSettingsApplied()) { // The url has custom domain settings.
+ // Get a cursor for the current host and move it to the first position.
+ Cursor currentDomainSettingsCursor = domainsDatabaseHelper.getCursorForDomainName(domainNameInDatabase);
+ currentDomainSettingsCursor.moveToFirst();
+
+ // Get the settings from the cursor.
+ nestedScrollWebView.setDomainSettingsDatabaseId(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper._ID)));
+ nestedScrollWebView.setDomainSettingsJavaScriptEnabled(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_JAVASCRIPT)) == 1);
+ nestedScrollWebView.setAcceptFirstPartyCookies(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FIRST_PARTY_COOKIES)) == 1);
+ boolean domainThirdPartyCookiesEnabled = (currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_THIRD_PARTY_COOKIES)) == 1);
+ nestedScrollWebView.getSettings().setDomStorageEnabled(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_DOM_STORAGE)) == 1);
+ // Form data can be removed once the minimum API >= 26.
+ boolean saveFormData = (currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FORM_DATA)) == 1);
+ nestedScrollWebView.enableBlocklist(NestedScrollWebView.EASY_LIST,
+ currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYLIST)) == 1);
+ nestedScrollWebView.enableBlocklist(NestedScrollWebView.EASY_PRIVACY,
+ currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYPRIVACY)) == 1);
+ nestedScrollWebView.enableBlocklist(NestedScrollWebView.FANBOYS_ANNOYANCE_LIST,
+ currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST)) == 1);
+ nestedScrollWebView.enableBlocklist(NestedScrollWebView.FANBOYS_SOCIAL_BLOCKING_LIST,
+ currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST)) == 1);
+ nestedScrollWebView.enableBlocklist(NestedScrollWebView.ULTRA_PRIVACY,
+ currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY)) == 1);
+ nestedScrollWebView.enableBlocklist(NestedScrollWebView.THIRD_PARTY_REQUESTS,
+ currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS)) == 1);
+ String userAgentName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.USER_AGENT));
+ int fontSize = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.FONT_SIZE));
+ int swipeToRefreshInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SWIPE_TO_REFRESH));
+ int nightModeInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.NIGHT_MODE));
+ int displayWebpageImagesInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.DISPLAY_IMAGES));
+ boolean pinnedSslCertificate = (currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.PINNED_SSL_CERTIFICATE)) == 1);
+ String pinnedSslIssuedToCName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_COMMON_NAME));
+ String pinnedSslIssuedToOName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATION));
+ String pinnedSslIssuedToUName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATIONAL_UNIT));
+ String pinnedSslIssuedByCName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_COMMON_NAME));
+ String pinnedSslIssuedByOName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATION));
+ String pinnedSslIssuedByUName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATIONAL_UNIT));
+ boolean pinnedIpAddresses = (currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.PINNED_IP_ADDRESSES)) == 1);
+ String pinnedHostIpAddresses = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.IP_ADDRESSES));
+
+ // Create the pinned SSL date variables.
+ Date pinnedSslStartDate;
+ Date pinnedSslEndDate;
+
+ // Set the pinned SSL certificate start date to `null` if the saved date `long` is 0 because creating a new Date results in an error if the input is 0.
+ if (currentDomainSettingsCursor.getLong(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_START_DATE)) == 0) {
+ pinnedSslStartDate = null;
+ } else {
+ pinnedSslStartDate = new Date(currentDomainSettingsCursor.getLong(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_START_DATE)));
+ }
+
+ // Set the pinned SSL certificate end date to `null` if the saved date `long` is 0 because creating a new Date results in an error if the input is 0.
+ if (currentDomainSettingsCursor.getLong(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_END_DATE)) == 0) {
+ pinnedSslEndDate = null;
+ } else {
+ pinnedSslEndDate = new Date(currentDomainSettingsCursor.getLong(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_END_DATE)));
+ }
+
+ // 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.setPinnedIpAddresses(pinnedHostIpAddresses);
+ }
+
+ // Set night mode according to the night mode int.
+ switch (nightModeInt) {
+ case DomainsDatabaseHelper.NIGHT_MODE_SYSTEM_DEFAULT:
+ // Set night mode according to the current default.
+ nestedScrollWebView.setNightMode(sharedPreferences.getBoolean("night_mode", false));
+ break;
+
+ case DomainsDatabaseHelper.NIGHT_MODE_ENABLED:
+ // Enable night mode.
+ nestedScrollWebView.setNightMode(true);
+ break;
+
+ case DomainsDatabaseHelper.NIGHT_MODE_DISABLED:
+ // Disable night mode.
+ nestedScrollWebView.setNightMode(false);
+ break;
+ }
+
+ // Enable JavaScript if night mode is enabled.
+ if (nestedScrollWebView.getNightMode()) {
+ // Enable JavaScript.
+ nestedScrollWebView.getSettings().setJavaScriptEnabled(true);
+ } else {
+ // Set JavaScript according to the domain settings.
+ nestedScrollWebView.getSettings().setJavaScriptEnabled(nestedScrollWebView.getDomainSettingsJavaScriptEnabled());
+ }
+
+ // Close the current host domain settings cursor.
+ currentDomainSettingsCursor.close();
+
+ // Apply the domain settings.
+ cookieManager.setAcceptCookie(nestedScrollWebView.getAcceptFirstPartyCookies());
+
+ // Set third-party cookies status if API >= 21.
+ if (Build.VERSION.SDK_INT >= 21) {
+ cookieManager.setAcceptThirdPartyCookies(nestedScrollWebView, domainThirdPartyCookiesEnabled);
+ }
+
+ // Apply the form data setting if the API < 26.
+ if (Build.VERSION.SDK_INT < 26) {
+ nestedScrollWebView.getSettings().setSaveFormData(saveFormData);
+ }
+
+ // Apply the font size.
+ if (fontSize == 0) { // Apply the default font size.
+ nestedScrollWebView.getSettings().setTextZoom(Integer.valueOf(defaultFontSizeString));
+ } else { // Apply the specified font size.
+ nestedScrollWebView.getSettings().setTextZoom(fontSize);
+ }
+
+ // Only set the user agent if the webpage is not currently loading. Otherwise, changing the user agent on redirects can cause the original website to reload.
+ // <https://redmine.stoutner.com/issues/160>
+ if (nestedScrollWebView.getProgress() == 100) { // A URL is not loading.
+ // Set the user agent.
+ if (userAgentName.equals(getString(R.string.system_default_user_agent))) { // Use the system default user agent.
+ // Get the array position of the default user agent name.
+ int defaultUserAgentArrayPosition = userAgentNamesArray.getPosition(defaultUserAgentName);
+
+ // Set the user agent according to the system default.
+ switch (defaultUserAgentArrayPosition) {
+ case UNRECOGNIZED_USER_AGENT: // The default user agent name is not on the canonical list.
+ // This is probably because it was set in an older version of Privacy Browser before the switch to persistent user agent names.
+ nestedScrollWebView.getSettings().setUserAgentString(defaultUserAgentName);
+ break;
+
+ case SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
+ // Set the user agent to `""`, which uses the default value.
+ nestedScrollWebView.getSettings().setUserAgentString("");
+ break;
+
+ case SETTINGS_CUSTOM_USER_AGENT:
+ // Set the default custom user agent.
+ nestedScrollWebView.getSettings().setUserAgentString(sharedPreferences.getString("custom_user_agent", getString(R.string.custom_user_agent_default_value)));
+ break;
+
+ default:
+ // Get the user agent string from the user agent data array
+ nestedScrollWebView.getSettings().setUserAgentString(userAgentDataArray[defaultUserAgentArrayPosition]);
+ }
+ } else { // Set the user agent according to the stored name.
+ // Get the array position of the user agent name.
+ int userAgentArrayPosition = userAgentNamesArray.getPosition(userAgentName);
+
+ switch (userAgentArrayPosition) {
+ case UNRECOGNIZED_USER_AGENT: // The user agent name contains a custom user agent.
+ nestedScrollWebView.getSettings().setUserAgentString(userAgentName);
+ break;
+
+ case SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
+ // Set the user agent to `""`, which uses the default value.
+ nestedScrollWebView.getSettings().setUserAgentString("");
+ break;
+
+ default:
+ // Get the user agent string from the user agent data array.
+ nestedScrollWebView.getSettings().setUserAgentString(userAgentDataArray[userAgentArrayPosition]);
+ }
+ }
+ }
+
+ // Set swipe to refresh.
+ switch (swipeToRefreshInt) {
+ case DomainsDatabaseHelper.SWIPE_TO_REFRESH_SYSTEM_DEFAULT:
+ // Store the swipe to refresh status in the nested scroll WebView.
+ nestedScrollWebView.setSwipeToRefresh(defaultSwipeToRefresh);
+
+ // Apply swipe to refresh according to the default. This can be removed once the minimum API >= 23 because it is continuously set by an on scroll change listener.
+ swipeRefreshLayout.setEnabled(defaultSwipeToRefresh);
+ break;
+
+ case DomainsDatabaseHelper.SWIPE_TO_REFRESH_ENABLED:
+ // Store the swipe to refresh status in the nested scroll WebView.
+ nestedScrollWebView.setSwipeToRefresh(true);
+
+ // Enable swipe to refresh. This can be removed once the minimum API >= 23 because it is continuously set by an on scroll change listener.
+ swipeRefreshLayout.setEnabled(true);
+ break;
+
+ case DomainsDatabaseHelper.SWIPE_TO_REFRESH_DISABLED:
+ // Store the swipe to refresh status in the nested scroll WebView.
+ nestedScrollWebView.setSwipeToRefresh(false);
+
+ // Disable swipe to refresh. This can be removed once the minimum API >= 23 because it is continuously set by an on scroll change listener.
+ swipeRefreshLayout.setEnabled(false);
+ }
+
+ // Set the loading of webpage images.
+ switch (displayWebpageImagesInt) {
+ case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_SYSTEM_DEFAULT:
+ nestedScrollWebView.getSettings().setLoadsImagesAutomatically(displayWebpageImages);
+ break;
+
+ case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_ENABLED:
+ nestedScrollWebView.getSettings().setLoadsImagesAutomatically(true);
+ break;
+
+ case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_DISABLED:
+ nestedScrollWebView.getSettings().setLoadsImagesAutomatically(false);
+ break;
+ }
+
+ // Set a green background on the URL relative layout to indicate that custom domain settings are being used. The deprecated `.getDrawable()` must be used until the minimum API >= 21.
+ if (darkTheme) {
+ urlRelativeLayout.setBackground(getResources().getDrawable(R.drawable.url_bar_background_dark_blue));
+ } else {
+ urlRelativeLayout.setBackground(getResources().getDrawable(R.drawable.url_bar_background_light_green));
+ }
+ } else { // The new URL does not have custom domain settings. Load the defaults.
+ // Store the values from the shared preferences.
+ boolean defaultJavaScriptEnabled = sharedPreferences.getBoolean("javascript", false);
+ nestedScrollWebView.setAcceptFirstPartyCookies(sharedPreferences.getBoolean("first_party_cookies", false));
+ boolean defaultThirdPartyCookiesEnabled = sharedPreferences.getBoolean("third_party_cookies", false);
+ nestedScrollWebView.getSettings().setDomStorageEnabled(sharedPreferences.getBoolean("dom_storage", false));
+ boolean saveFormData = sharedPreferences.getBoolean("save_form_data", false); // Form data can be removed once the minimum API >= 26.
+ nestedScrollWebView.enableBlocklist(NestedScrollWebView.EASY_LIST, sharedPreferences.getBoolean("easylist", true));
+ nestedScrollWebView.enableBlocklist(NestedScrollWebView.EASY_PRIVACY, sharedPreferences.getBoolean("easyprivacy", true));
+ nestedScrollWebView.enableBlocklist(NestedScrollWebView.FANBOYS_ANNOYANCE_LIST, sharedPreferences.getBoolean("fanboys_annoyance_list", true));
+ nestedScrollWebView.enableBlocklist(NestedScrollWebView.FANBOYS_SOCIAL_BLOCKING_LIST, sharedPreferences.getBoolean("fanboys_social_blocking_list", true));
+ nestedScrollWebView.enableBlocklist(NestedScrollWebView.ULTRA_PRIVACY, sharedPreferences.getBoolean("ultraprivacy", true));
+ nestedScrollWebView.enableBlocklist(NestedScrollWebView.THIRD_PARTY_REQUESTS, sharedPreferences.getBoolean("block_all_third_party_requests", false));
+ nestedScrollWebView.setNightMode(sharedPreferences.getBoolean("night_mode", false));
+
+ // Enable JavaScript if night mode is enabled.
+ if (nestedScrollWebView.getNightMode()) {
+ // Enable JavaScript.
+ nestedScrollWebView.getSettings().setJavaScriptEnabled(true);
+ } else {
+ // Set JavaScript according to the domain settings.
+ nestedScrollWebView.getSettings().setJavaScriptEnabled(defaultJavaScriptEnabled);
+ }
+
+ // Apply the default settings.
+ cookieManager.setAcceptCookie(nestedScrollWebView.getAcceptFirstPartyCookies());
+ nestedScrollWebView.getSettings().setTextZoom(Integer.valueOf(defaultFontSizeString));
+
+ // Apply the form data setting if the API < 26.
+ if (Build.VERSION.SDK_INT < 26) {
+ nestedScrollWebView.getSettings().setSaveFormData(saveFormData);
+ }
+
+ // Store the swipe to refresh status in the nested scroll WebView.
+ nestedScrollWebView.setSwipeToRefresh(defaultSwipeToRefresh);
+
+ // Apply swipe to refresh according to the default.
+ swipeRefreshLayout.setEnabled(defaultSwipeToRefresh);
+
+ // Reset the pinned variables.
+ nestedScrollWebView.setDomainSettingsDatabaseId(-1);
+
+ // Set third-party cookies status if API >= 21.
+ if (Build.VERSION.SDK_INT >= 21) {
+ cookieManager.setAcceptThirdPartyCookies(nestedScrollWebView, defaultThirdPartyCookiesEnabled);
+ }
+
+ // Only set the user agent if the webpage is not currently loading. Otherwise, changing the user agent on redirects can cause the original website to reload.
+ // <https://redmine.stoutner.com/issues/160>
+ if (nestedScrollWebView.getProgress() == 100) { // A URL is not loading.
+ // Get the array position of the user agent name.
+ int userAgentArrayPosition = userAgentNamesArray.getPosition(defaultUserAgentName);
+
+ // Set the user agent.
+ switch (userAgentArrayPosition) {
+ case UNRECOGNIZED_USER_AGENT: // The default user agent name is not on the canonical list.
+ // This is probably because it was set in an older version of Privacy Browser before the switch to persistent user agent names.
+ nestedScrollWebView.getSettings().setUserAgentString(defaultUserAgentName);
+ break;
+
+ case SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
+ // Set the user agent to `""`, which uses the default value.
+ nestedScrollWebView.getSettings().setUserAgentString("");
+ break;
+
+ case SETTINGS_CUSTOM_USER_AGENT:
+ // Set the default custom user agent.
+ nestedScrollWebView.getSettings().setUserAgentString(sharedPreferences.getString("custom_user_agent", getString(R.string.custom_user_agent_default_value)));
+ break;
+
+ default:
+ // Get the user agent string from the user agent data array
+ nestedScrollWebView.getSettings().setUserAgentString(userAgentDataArray[userAgentArrayPosition]);
+ }
+ }
+
+ // Set the loading of webpage images.
+ nestedScrollWebView.getSettings().setLoadsImagesAutomatically(displayWebpageImages);
+
+ // Set a transparent background on URL edit text. The deprecated `getResources().getDrawable()` must be used until the minimum API >= 21.
+ urlRelativeLayout.setBackground(getResources().getDrawable(R.color.transparent));
+ }
+
+ // Close the domains database helper.
+ domainsDatabaseHelper.close();
+
+ // Update the privacy icons.
+ updatePrivacyIcons(true);
+ }
+
+ // Reload the website if returning from the Domains activity.
+ if (reloadWebsite) {
+ nestedScrollWebView.reload();
+ }
+
+ // Return the user agent changed status.
+ return !nestedScrollWebView.getSettings().getUserAgentString().equals(initialUserAgent);