]> gitweb.stoutner.com Git - PrivacyBrowserAndroid.git/blobdiff - app/src/main/java/com/stoutner/privacybrowser/fragments/DomainSettingsFragment.java
Improve the layout of SSL certificates in Domain Settings. https://redmine.stoutner...
[PrivacyBrowserAndroid.git] / app / src / main / java / com / stoutner / privacybrowser / fragments / DomainSettingsFragment.java
index 477ab9e321976e676458757e4950b51bd47b97cc..aea9bf3ef13c3734169347b9df1a4751a57c1740 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2017-2018 Soren Stoutner <soren@stoutner.com>.
+ * Copyright © 2017-2019 Soren Stoutner <soren@stoutner.com>.
  *
  * This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
  *
@@ -27,10 +27,11 @@ import android.database.Cursor;
 import android.net.http.SslCertificate;
 import android.os.Build;
 import android.os.Bundle;
-// We have to use `android.support.v4.app.Fragment` until minimum API >= 23.  Otherwise we cannot call `getContext()`.
 import android.preference.PreferenceManager;
 import android.support.annotation.NonNull;
+// `android.support.v4.app.Fragment` must be used until minimum API >= 23.  Otherwise `getContext()` does not work.
 import android.support.v4.app.Fragment;
+import android.support.v7.widget.CardView;
 import android.text.Editable;
 import android.text.SpannableStringBuilder;
 import android.text.Spanned;
@@ -92,12 +93,12 @@ public class DomainSettingsFragment extends Fragment {
         SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
 
         // Store the default settings.
-        final String defaultUserAgentName = sharedPreferences.getString("user_agent", "Privacy Browser");
-        final String defaultCustomUserAgentString = sharedPreferences.getString("custom_user_agent", "PrivacyBrowser/1.0");
-        String defaultFontSizeString = sharedPreferences.getString("default_font_size", "100");
-        boolean defaultSwipeToRefreshBoolean = sharedPreferences.getBoolean("swipe_to_refresh", true);
-        final boolean defaultNightModeBoolean = sharedPreferences.getBoolean("night_mode", false);
-        final boolean defaultDisplayWebpageImagesBoolean = sharedPreferences.getBoolean("display_website_images", true);
+        final String defaultUserAgentName = sharedPreferences.getString("user_agent", getString(R.string.user_agent_default_value));
+        final String defaultCustomUserAgentString = sharedPreferences.getString("custom_user_agent", getString(R.string.custom_user_agent_default_value));
+        String defaultFontSizeString = sharedPreferences.getString("font_size", getString(R.string.font_size_default_value));
+        boolean defaultSwipeToRefresh = sharedPreferences.getBoolean("swipe_to_refresh", true);
+        final boolean defaultNightMode = sharedPreferences.getBoolean("night_mode", false);
+        final boolean defaultDisplayWebpageImages = sharedPreferences.getBoolean("display_webpage_images", true);
 
         // Get handles for the views in the fragment.
         final EditText domainNameEditText = domainSettingsView.findViewById(R.id.domain_settings_name_edittext);
@@ -120,6 +121,10 @@ public class DomainSettingsFragment extends Fragment {
         ImageView fanboysAnnoyanceListImageView = domainSettingsView.findViewById(R.id.domain_settings_fanboys_annoyance_list_imageview);
         Switch fanboysSocialBlockingListSwitch = domainSettingsView.findViewById(R.id.domain_settings_fanboys_social_blocking_list_switch);
         ImageView fanboysSocialBlockingListImageView = domainSettingsView.findViewById(R.id.domain_settings_fanboys_social_blocking_list_imageview);
+        Switch ultraPrivacySwitch = domainSettingsView.findViewById(R.id.domain_settings_ultraprivacy_switch);
+        ImageView ultraPrivacyImageView = domainSettingsView.findViewById(R.id.domain_settings_ultraprivacy_imageview);
+        Switch blockAllThirdPartyRequestsSwitch = domainSettingsView.findViewById(R.id.domain_settings_block_all_third_party_requests_switch);
+        ImageView blockAllThirdPartyRequestsImageView = domainSettingsView.findViewById(R.id.domain_settings_block_all_third_party_requests_imageview);
         final Spinner userAgentSpinner = domainSettingsView.findViewById(R.id.domain_settings_user_agent_spinner);
         final TextView userAgentTextView = domainSettingsView.findViewById(R.id.domain_settings_user_agent_textview);
         final EditText customUserAgentEditText = domainSettingsView.findViewById(R.id.domain_settings_custom_user_agent_edittext);
@@ -136,7 +141,8 @@ public class DomainSettingsFragment extends Fragment {
         final TextView displayImagesTextView = domainSettingsView.findViewById(R.id.domain_settings_display_webpage_images_textview);
         final ImageView pinnedSslCertificateImageView = domainSettingsView.findViewById(R.id.domain_settings_pinned_ssl_certificate_imageview);
         Switch pinnedSslCertificateSwitch = domainSettingsView.findViewById(R.id.domain_settings_pinned_ssl_certificate_switch);
-        final LinearLayout savedSslCertificateLinearLayout = domainSettingsView.findViewById(R.id.saved_ssl_certificate_linearlayout);
+        final CardView savedSslCertificateCardView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_cardview);
+        LinearLayout savedSslCertificateLinearLayout = domainSettingsView.findViewById(R.id.saved_ssl_certificate_linearlayout);
         final RadioButton savedSslCertificateRadioButton = domainSettingsView.findViewById(R.id.saved_ssl_certificate_radiobutton);
         final TextView savedSslCertificateIssuedToCNameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_to_cname);
         TextView savedSslCertificateIssuedToONameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_to_oname);
@@ -146,7 +152,8 @@ public class DomainSettingsFragment extends Fragment {
         TextView savedSslCertificateIssuedByUNameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_by_uname);
         TextView savedSslCertificateStartDateTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_start_date);
         TextView savedSslCertificateEndDateTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_end_date);
-        final LinearLayout currentWebsiteCertificateLinearLayout = domainSettingsView.findViewById(R.id.current_website_certificate_linearlayout);
+        final CardView currentWebsiteCertificateCardView = domainSettingsView.findViewById(R.id.current_website_certificate_cardview);
+        LinearLayout currentWebsiteCertificateLinearLayout = domainSettingsView.findViewById(R.id.current_website_certificate_linearlayout);
         final RadioButton currentWebsiteCertificateRadioButton = domainSettingsView.findViewById(R.id.current_website_certificate_radiobutton);
         final TextView currentWebsiteCertificateIssuedToCNameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_to_cname);
         TextView currentWebsiteCertificateIssuedToONameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_to_oname);
@@ -186,6 +193,8 @@ public class DomainSettingsFragment extends Fragment {
         int easyPrivacyEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYPRIVACY));
         int fanboysAnnoyanceListInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST));
         int fanboysSocialBlockingListInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST));
+        int ultraPrivacyEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY));
+        int blockAllThirdPartyRequestsInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS));
         final String currentUserAgentName = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.USER_AGENT));
         int fontSizeInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.FONT_SIZE));
         int swipeToRefreshInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.SWIPE_TO_REFRESH));
@@ -212,29 +221,29 @@ public class DomainSettingsFragment extends Fragment {
             savedSslCertificateEndDate = new Date(domainCursor.getLong(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_END_DATE)));
         }
 
-        // Create `ArrayAdapters` for the `Spinners`and their `entry values`.
-        ArrayAdapter<CharSequence> translatedUserAgentArrayAdapter = ArrayAdapter.createFromResource(context, R.array.translated_domain_settings_user_agent_names, R.layout.domain_settings_spinner_item);
-        ArrayAdapter<CharSequence> fontSizeArrayAdapter = ArrayAdapter.createFromResource(context, R.array.domain_settings_font_size_entries, R.layout.domain_settings_spinner_item);
-        ArrayAdapter<CharSequence> fontSizeEntryValuesArrayAdapter = ArrayAdapter.createFromResource(context, R.array.domain_settings_font_size_entry_values, R.layout.domain_settings_spinner_item);
-        ArrayAdapter<CharSequence> swipeToRefreshArrayAdapter = ArrayAdapter.createFromResource(context, R.array.swipe_to_refresh_array, R.layout.domain_settings_spinner_item);
-        ArrayAdapter<CharSequence> nightModeArrayAdapter = ArrayAdapter.createFromResource(context, R.array.night_mode_array, R.layout.domain_settings_spinner_item);
-        ArrayAdapter<CharSequence> displayImagesArrayAdapter = ArrayAdapter.createFromResource(context, R.array.display_webpage_images_array, R.layout.domain_settings_spinner_item);
+        // Create array adapters for the spinners.
+        ArrayAdapter<CharSequence> translatedUserAgentArrayAdapter = ArrayAdapter.createFromResource(context, R.array.translated_domain_settings_user_agent_names, R.layout.spinner_item);
+        ArrayAdapter<CharSequence> fontSizeArrayAdapter = ArrayAdapter.createFromResource(context, R.array.domain_settings_font_size_entries, R.layout.spinner_item);
+        ArrayAdapter<CharSequence> fontSizeEntryValuesArrayAdapter = ArrayAdapter.createFromResource(context, R.array.domain_settings_font_size_entry_values, R.layout.spinner_item);
+        ArrayAdapter<CharSequence> swipeToRefreshArrayAdapter = ArrayAdapter.createFromResource(context, R.array.swipe_to_refresh_array, R.layout.spinner_item);
+        ArrayAdapter<CharSequence> nightModeArrayAdapter = ArrayAdapter.createFromResource(context, R.array.night_mode_array, R.layout.spinner_item);
+        ArrayAdapter<CharSequence> displayImagesArrayAdapter = ArrayAdapter.createFromResource(context, R.array.display_webpage_images_array, R.layout.spinner_item);
 
-        // Set the `DropDownViewResource` on the `Spinners`.
+        // Set the drop down view resource on the spinners.
         translatedUserAgentArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items);
         fontSizeArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items);
         swipeToRefreshArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items);
         nightModeArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items);
         displayImagesArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items);
 
-        // Set the `ArrayAdapters` for the `Spinners`.
+        // Set the array adapters for the spinners.
         userAgentSpinner.setAdapter(translatedUserAgentArrayAdapter);
         fontSizeSpinner.setAdapter(fontSizeArrayAdapter);
         swipeToRefreshSpinner.setAdapter(swipeToRefreshArrayAdapter);
         nightModeSpinner.setAdapter(nightModeArrayAdapter);
         displayWebpageImagesSpinner.setAdapter(displayImagesArrayAdapter);
 
-        // Create a `SpannableStringBuilder` for each `TextView` that needs multiple colors of text.
+        // Create a spannable string builder for each TextView that needs multiple colors of text.
         SpannableStringBuilder savedSslCertificateIssuedToCNameStringBuilder = new SpannableStringBuilder(cNameLabel + savedSslCertificateIssuedToCNameString);
         SpannableStringBuilder savedSslCertificateIssuedToONameStringBuilder = new SpannableStringBuilder(oNameLabel + savedSslCertificateIssuedToONameString);
         SpannableStringBuilder savedSslCertificateIssuedToUNameStringBuilder = new SpannableStringBuilder(uNameLabel + savedSslCertificateIssuedToUNameString);
@@ -335,7 +344,7 @@ public class DomainSettingsFragment extends Fragment {
         });
 
         // Create a `boolean` to track if night mode is enabled.
-        boolean nightModeEnabled = (nightModeInt == DomainsDatabaseHelper.NIGHT_MODE_ENABLED) || ((nightModeInt == DomainsDatabaseHelper.NIGHT_MODE_SYSTEM_DEFAULT) && defaultNightModeBoolean);
+        boolean nightModeEnabled = (nightModeInt == DomainsDatabaseHelper.NIGHT_MODE_ENABLED) || ((nightModeInt == DomainsDatabaseHelper.NIGHT_MODE_SYSTEM_DEFAULT) && defaultNightMode);
 
         // Disable the JavaScript switch if night mode is enabled.
         if (nightModeEnabled) {
@@ -589,6 +598,52 @@ public class DomainSettingsFragment extends Fragment {
             }
         }
 
+        // Set the UltraPrivacy status.  Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
+        if (ultraPrivacyEnabledInt == 1) {  // UltraPrivacy is on.
+            // Turn the switch on.
+            ultraPrivacySwitch.setChecked(true);
+
+            // Set the icon according to the theme.
+            if (MainWebViewActivity.darkTheme) {
+                ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_dark));
+            } else {
+                ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_light));
+            }
+        } else {  // EasyPrivacy is off.
+            // Turn the switch off.
+            ultraPrivacySwitch.setChecked(false);
+
+            // Set the icon according to the theme.
+            if (MainWebViewActivity.darkTheme) {
+                ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_dark));
+            } else {
+                ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_light));
+            }
+        }
+
+        // Set the third-party resource blocking status.  Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
+        if (blockAllThirdPartyRequestsInt == 1) {  // Blocking all third-party requests is on.
+            // Turn the switch on.
+            blockAllThirdPartyRequestsSwitch.setChecked(true);
+
+            // Set the icon according to the theme.
+            if (MainWebViewActivity.darkTheme) {
+                blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_enabled_dark));
+            } else {
+                blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_enabled_light));
+            }
+        } else {  // Blocking all third-party requests is off.
+            // Turn the switch off.
+            blockAllThirdPartyRequestsSwitch.setChecked(false);
+
+            // Set the icon according to the theme.
+            if (MainWebViewActivity.darkTheme) {
+                blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_disabled_dark));
+            } else {
+                blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_disabled_light));
+            }
+        }
+
         // Inflated a WebView to get the default user agent.
         // `@SuppressLint("InflateParams")` removes the warning about using `null` as the `ViewGroup`, which in this case makes sense because the bare WebView should not be displayed on the screen.
         @SuppressLint("InflateParams") View bareWebViewLayout = inflater.inflate(R.layout.bare_webview, null, false);
@@ -596,7 +651,7 @@ public class DomainSettingsFragment extends Fragment {
         final String webViewDefaultUserAgentString = bareWebView.getSettings().getUserAgentString();
 
         // Get a handle for the user agent array adapter.  This array does not contain the `System default` entry.
-        ArrayAdapter<CharSequence> userAgentNamesArray = ArrayAdapter.createFromResource(context, R.array.user_agent_names, R.layout.domain_settings_spinner_item);
+        ArrayAdapter<CharSequence> userAgentNamesArray = ArrayAdapter.createFromResource(context, R.array.user_agent_names, R.layout.spinner_item);
 
         // Get the positions of the user agent and the default user agent.
         int userAgentArrayPosition = userAgentNamesArray.getPosition(currentUserAgentName);
@@ -692,7 +747,7 @@ public class DomainSettingsFragment extends Fragment {
         swipeToRefreshSpinner.setSelection(swipeToRefreshInt);
 
         // Set the swipe to refresh text.
-        if (defaultSwipeToRefreshBoolean) {
+        if (defaultSwipeToRefresh) {
             swipeToRefreshTextView.setText(swipeToRefreshArrayAdapter.getItem(DomainsDatabaseHelper.SWIPE_TO_REFRESH_ENABLED));
         } else {
             swipeToRefreshTextView.setText(swipeToRefreshArrayAdapter.getItem(DomainsDatabaseHelper.SWIPE_TO_REFRESH_DISABLED));
@@ -701,7 +756,7 @@ public class DomainSettingsFragment extends Fragment {
         // Set the swipe to refresh icon and TextView settings.  Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
         switch (swipeToRefreshInt) {
             case DomainsDatabaseHelper.SWIPE_TO_REFRESH_SYSTEM_DEFAULT:
-                if (defaultSwipeToRefreshBoolean) {  // Swipe to refresh is enabled by default.
+                if (defaultSwipeToRefresh) {  // Swipe to refresh is enabled by default.
                     // Set the icon according to the theme.
                     if (MainWebViewActivity.darkTheme) {
                         swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_dark));
@@ -755,7 +810,7 @@ public class DomainSettingsFragment extends Fragment {
         nightModeSpinner.setSelection(nightModeInt);
 
         // Set the default night mode text.
-        if (defaultNightModeBoolean) {
+        if (defaultNightMode) {
             nightModeTextView.setText(nightModeArrayAdapter.getItem(DomainsDatabaseHelper.NIGHT_MODE_ENABLED));
         } else {
             nightModeTextView.setText(nightModeArrayAdapter.getItem(DomainsDatabaseHelper.NIGHT_MODE_DISABLED));
@@ -764,7 +819,7 @@ public class DomainSettingsFragment extends Fragment {
         // Set the night mode icon and TextView settings.  Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
         switch (nightModeInt) {
             case DomainsDatabaseHelper.NIGHT_MODE_SYSTEM_DEFAULT:
-                if (defaultNightModeBoolean) {  // Night mode enabled by default.
+                if (defaultNightMode) {  // Night mode enabled by default.
                     // Set the icon according to the theme.
                     if (MainWebViewActivity.darkTheme) {
                         nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_dark));
@@ -819,7 +874,7 @@ public class DomainSettingsFragment extends Fragment {
         displayWebpageImagesSpinner.setSelection(displayImagesInt);
 
         // Set the default display images text.
-        if (defaultDisplayWebpageImagesBoolean) {
+        if (defaultDisplayWebpageImages) {
             displayImagesTextView.setText(displayImagesArrayAdapter.getItem(DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_ENABLED));
         } else {
             displayImagesTextView.setText(displayImagesArrayAdapter.getItem(DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_DISABLED));
@@ -828,7 +883,7 @@ public class DomainSettingsFragment extends Fragment {
         // Set the display website images icon and TextView settings.  Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
         switch (displayImagesInt) {
             case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_SYSTEM_DEFAULT:
-                if (defaultDisplayWebpageImagesBoolean) {  // Display webpage images enabled by default.
+                if (defaultDisplayWebpageImages) {  // Display webpage images enabled by default.
                     // Set the icon according to the theme.
                     if (MainWebViewActivity.darkTheme) {
                         displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_dark));
@@ -1016,41 +1071,62 @@ public class DomainSettingsFragment extends Fragment {
         if (pinnedSslCertificateSwitch.isChecked()) {
             // Set the visibility of the saved SSL certificate.
             if (savedSslCertificateIssuedToCNameString == null) {
-                savedSslCertificateLinearLayout.setVisibility(View.GONE);
+                savedSslCertificateCardView.setVisibility(View.GONE);
             } else {
-                savedSslCertificateLinearLayout.setVisibility(View.VISIBLE);
+                savedSslCertificateCardView.setVisibility(View.VISIBLE);
             }
 
             // Set the visibility of the current website SSL certificate.
             if (currentWebsiteSslCertificate == null) {
                 // Hide the SSL certificate.
-                currentWebsiteCertificateLinearLayout.setVisibility(View.GONE);
+                currentWebsiteCertificateCardView.setVisibility(View.GONE);
 
                 // Show the instruction.
                 noCurrentWebsiteCertificateTextView.setVisibility(View.VISIBLE);
             } else {
                 // Show the SSL certificate.
-                currentWebsiteCertificateLinearLayout.setVisibility(View.VISIBLE);
+                currentWebsiteCertificateCardView.setVisibility(View.VISIBLE);
 
                 // Hide the instruction.
                 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
             }
 
             // Set the status of the radio buttons.
-            if (savedSslCertificateLinearLayout.getVisibility() == View.VISIBLE) {  // The saved SSL certificate is displayed.
+            if (savedSslCertificateCardView.getVisibility() == View.VISIBLE) {  // The saved SSL certificate is displayed.
+                // Check the saved SSL certificate radio button.
                 savedSslCertificateRadioButton.setChecked(true);
+
+                // Uncheck the current website SSL certificate radio button.
                 currentWebsiteCertificateRadioButton.setChecked(false);
-            } else if (currentWebsiteCertificateLinearLayout.getVisibility() == View.VISIBLE) {  // The saved SSL certificate is hidden but the current website SSL certificate is visible.
+
+                // Darken the background of the current website SSL certificate linear layout according to the theme.
+                if (MainWebViewActivity.darkTheme) {
+                    currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
+                } else {
+                    currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
+                }
+            } else if (currentWebsiteCertificateCardView.getVisibility() == View.VISIBLE) {  // The saved SSL certificate is hidden but the current website SSL certificate is visible.
+                // Check the current website SSL certificate radio button.
                 currentWebsiteCertificateRadioButton.setChecked(true);
+
+                // Uncheck the saved SSL certificate radio button.
                 savedSslCertificateRadioButton.setChecked(false);
+
+                // Darken the background of the saved SSL certificate linear layout according to the theme.
+                if (MainWebViewActivity.darkTheme) {
+                    savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
+                } else {
+                    savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
+                }
             } else {  // Neither SSL certificate is visible.
+                // Uncheck both radio buttons.
                 savedSslCertificateRadioButton.setChecked(false);
                 currentWebsiteCertificateRadioButton.setChecked(false);
             }
         } else {  // `pinnedSslCertificateSwitch` is not checked.
             // Hide the SSl certificates and instructions.
-            savedSslCertificateLinearLayout.setVisibility(View.GONE);
-            currentWebsiteCertificateLinearLayout.setVisibility(View.GONE);
+            savedSslCertificateCardView.setVisibility(View.GONE);
+            currentWebsiteCertificateCardView.setVisibility(View.GONE);
             noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
 
             // Uncheck the radio buttons.
@@ -1293,6 +1369,46 @@ public class DomainSettingsFragment extends Fragment {
             }
         });
 
+        // Set the UltraPrivacy switch listener.
+        ultraPrivacySwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
+            // Update the icon.
+            if (isChecked) {  // UltraPrivacy is on.
+                // Set the icon according to the theme.
+                if (MainWebViewActivity.darkTheme) {
+                    ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_dark));
+                } else {
+                    ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_light));
+                }
+            } else {  // UltraPrivacy is off.
+                // Set the icon according to the theme.
+                if (MainWebViewActivity.darkTheme) {
+                    ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_dark));
+                } else {
+                    ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_light));
+                }
+            }
+        });
+
+        // Set the block all third-party requests switch listener.
+        blockAllThirdPartyRequestsSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
+            // Update the icon.
+            if (isChecked) {  // Blocking all third-party requests is on.
+                // Set the icon according to the theme.
+                if (MainWebViewActivity.darkTheme) {
+                    blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_enabled_dark));
+                } else {
+                    blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_enabled_light));
+                }
+            } else {  // Blocking all third-party requests is off.
+                // Set the icon according to the theme.
+                if (MainWebViewActivity.darkTheme) {
+                    blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_disabled_dark));
+                } else {
+                    blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_disabled_light));
+                }
+            }
+        });
+
         // Set the user agent spinner listener.
         userAgentSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
             @Override
@@ -1388,7 +1504,7 @@ public class DomainSettingsFragment extends Fragment {
                 // Update the icon and the visibility of `nightModeTextView`.  Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
                 switch (position) {
                     case DomainsDatabaseHelper.SWIPE_TO_REFRESH_SYSTEM_DEFAULT:
-                        if (defaultSwipeToRefreshBoolean) {  // Swipe to refresh enabled by default.
+                        if (defaultSwipeToRefresh) {  // Swipe to refresh enabled by default.
                             // Set the icon according to the theme.
                             if (MainWebViewActivity.darkTheme) {
                                 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_dark));
@@ -1446,7 +1562,7 @@ public class DomainSettingsFragment extends Fragment {
                 // Update the icon and the visibility of `nightModeTextView`.  Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
                 switch (position) {
                     case DomainsDatabaseHelper.NIGHT_MODE_SYSTEM_DEFAULT:
-                        if (defaultNightModeBoolean) {  // Night mode enabled by default.
+                        if (defaultNightMode) {  // Night mode enabled by default.
                             // Set the icon according to the theme.
                             if (MainWebViewActivity.darkTheme) {
                                 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_dark));
@@ -1492,7 +1608,7 @@ public class DomainSettingsFragment extends Fragment {
                 }
 
                 // Create a `boolean` to store the current night mode setting.
-                boolean currentNightModeEnabled = (position == DomainsDatabaseHelper.NIGHT_MODE_ENABLED) || ((position == DomainsDatabaseHelper.NIGHT_MODE_SYSTEM_DEFAULT) && defaultNightModeBoolean);
+                boolean currentNightModeEnabled = (position == DomainsDatabaseHelper.NIGHT_MODE_ENABLED) || ((position == DomainsDatabaseHelper.NIGHT_MODE_SYSTEM_DEFAULT) && defaultNightMode);
 
                 // Disable the JavaScript `Switch` if night mode is enabled.
                 if (currentNightModeEnabled) {
@@ -1561,7 +1677,7 @@ public class DomainSettingsFragment extends Fragment {
                 // Update the icon and the visibility of `displayImagesTextView`.
                 switch (position) {
                     case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_SYSTEM_DEFAULT:
-                        if (defaultDisplayWebpageImagesBoolean) {
+                        if (defaultDisplayWebpageImages) {
                             // Set the icon according to the theme.
                             if (MainWebViewActivity.darkTheme) {
                                 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_dark));
@@ -1626,34 +1742,61 @@ public class DomainSettingsFragment extends Fragment {
 
                 // Update the visibility of the saved SSL certificate.
                 if (savedSslCertificateIssuedToCNameString == null) {
-                    savedSslCertificateLinearLayout.setVisibility(View.GONE);
+                    savedSslCertificateCardView.setVisibility(View.GONE);
                 } else {
-                    savedSslCertificateLinearLayout.setVisibility(View.VISIBLE);
+                    savedSslCertificateCardView.setVisibility(View.VISIBLE);
                 }
 
                 // Update the visibility of the current website SSL certificate.
                 if (currentWebsiteSslCertificate == null) {
                     // Hide the SSL certificate.
-                    currentWebsiteCertificateLinearLayout.setVisibility(View.GONE);
+                    currentWebsiteCertificateCardView.setVisibility(View.GONE);
 
                     // Show the instruction.
                     noCurrentWebsiteCertificateTextView.setVisibility(View.VISIBLE);
                 } else {
                     // Show the SSL certificate.
-                    currentWebsiteCertificateLinearLayout.setVisibility(View.VISIBLE);
+                    currentWebsiteCertificateCardView.setVisibility(View.VISIBLE);
 
                     // Hide the instruction.
                     noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
                 }
 
                 // Set the status of the radio buttons.
-                if (savedSslCertificateLinearLayout.getVisibility() == View.VISIBLE) {  // The saved SSL certificate is displayed.
+                if (savedSslCertificateCardView.getVisibility() == View.VISIBLE) {  // The saved SSL certificate is displayed.
+                    // Check the saved SSL certificate radio button.
                     savedSslCertificateRadioButton.setChecked(true);
+
+                    // Uncheck the current website SSL certificate radio button.
                     currentWebsiteCertificateRadioButton.setChecked(false);
-                } else if (currentWebsiteCertificateLinearLayout.getVisibility() == View.VISIBLE) {  // The saved SSL certificate is hidden but the current website SSL certificate is visible.
+
+                    // Set the background of the saved SSL certificate linear layout to be transparent.
+                    savedSslCertificateLinearLayout.setBackgroundResource(R.color.transparent);
+
+                    // Darken the background of the current website SSL certificate linear layout according to the theme.
+                    if (MainWebViewActivity.darkTheme) {
+                        currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
+                    } else {
+                        currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
+                    }
+                } else if (currentWebsiteCertificateCardView.getVisibility() == View.VISIBLE) {  // The saved SSL certificate is hidden but the current website SSL certificate is visible.
+                    // Check the current website SSL certificate radio button.
                     currentWebsiteCertificateRadioButton.setChecked(true);
+
+                    // Uncheck the saved SSL certificate radio button.
                     savedSslCertificateRadioButton.setChecked(false);
+
+                    // Set the background of the current website SSL certificate linear layout to be transparent.
+                    currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.transparent);
+
+                    // Darken the background of the saved SSL certificate linear layout according to the theme.
+                    if (MainWebViewActivity.darkTheme) {
+                        savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
+                    } else {
+                        savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
+                    }
                 } else {  // Neither SSL certificate is visible.
+                    // Uncheck both radio buttons.
                     savedSslCertificateRadioButton.setChecked(false);
                     currentWebsiteCertificateRadioButton.setChecked(false);
                 }
@@ -1666,8 +1809,8 @@ public class DomainSettingsFragment extends Fragment {
                 }
 
                 // Hide the SSl certificates and instructions.
-                savedSslCertificateLinearLayout.setVisibility(View.GONE);
-                currentWebsiteCertificateLinearLayout.setVisibility(View.GONE);
+                savedSslCertificateCardView.setVisibility(View.GONE);
+                currentWebsiteCertificateCardView.setVisibility(View.GONE);
                 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
 
                 // Uncheck the radio buttons.
@@ -1676,24 +1819,76 @@ public class DomainSettingsFragment extends Fragment {
             }
         });
 
-        savedSslCertificateLinearLayout.setOnClickListener((View v) -> {
+        savedSslCertificateCardView.setOnClickListener((View v) -> {
+            // Check the saved SSL certificate radio button.
             savedSslCertificateRadioButton.setChecked(true);
+
+            // Uncheck the current website SSL certificate radio button.
             currentWebsiteCertificateRadioButton.setChecked(false);
+
+            // Set the background of the saved SSL certificate linear layout to be transparent.
+            savedSslCertificateLinearLayout.setBackgroundResource(R.color.transparent);
+
+            // Darken the background of the current website SSL certificate linear layout according to the theme.
+            if (MainWebViewActivity.darkTheme) {
+                currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
+            } else {
+                currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
+            }
         });
 
         savedSslCertificateRadioButton.setOnClickListener((View v) -> {
+            // Check the saved SSL certificate radio button.
             savedSslCertificateRadioButton.setChecked(true);
+
+            // Uncheck the current website SSL certificate radio button.
             currentWebsiteCertificateRadioButton.setChecked(false);
+
+            // Set the background of the saved SSL certificate linear layout to be transparent.
+            savedSslCertificateLinearLayout.setBackgroundResource(R.color.transparent);
+
+            // Darken the background of the current website SSL certificate linear layout according to the theme.
+            if (MainWebViewActivity.darkTheme) {
+                currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
+            } else {
+                currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
+            }
         });
 
-        currentWebsiteCertificateLinearLayout.setOnClickListener((View v) -> {
+        currentWebsiteCertificateCardView.setOnClickListener((View v) -> {
+            // Check the current website SSL certificate radio button.
             currentWebsiteCertificateRadioButton.setChecked(true);
+
+            // Uncheck the saved SSL certificate radio button.
             savedSslCertificateRadioButton.setChecked(false);
+
+            // Set the background of the current website SSL certificate linear layout to be transparent.
+            currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.transparent);
+
+            // Darken the background of the saved SSL certificate linear layout according to the theme.
+            if (MainWebViewActivity.darkTheme) {
+                savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
+            } else {
+                savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
+            }
         });
 
         currentWebsiteCertificateRadioButton.setOnClickListener((View v) -> {
+            // Check the current website SSL certificate radio button.
             currentWebsiteCertificateRadioButton.setChecked(true);
+
+            // Uncheck the saved SSL certificate radio button.
             savedSslCertificateRadioButton.setChecked(false);
+
+            // Set the background of the current website SSL certificate linear layout to be transparent.
+            currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.transparent);
+
+            // Darken the background of the saved SSL certificate linear layout according to the theme.
+            if (MainWebViewActivity.darkTheme) {
+                savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
+            } else {
+                savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
+            }
         });
 
         return domainSettingsView;
@@ -1703,15 +1898,15 @@ public class DomainSettingsFragment extends Fragment {
         // Initialize `domainNamesMatch`.
         boolean domainNamesMatch = false;
 
-        // Check if the domains match.
-        if (domainName.equals(certificateCommonName)) {
-            domainNamesMatch = true;
-        }
-
         // Check various wildcard permutations if `domainName` and `certificateCommonName` are not empty.
         // `noinspection ConstantCondition` removes Android Studio's incorrect lint warning that `domainName` can never be `null`.
         //noinspection ConstantConditions
         if ((domainName != null) && (certificateCommonName != null)) {
+            // Check if the domains match.
+            if (domainName.equals(certificateCommonName)) {
+                domainNamesMatch = true;
+            }
+
             // If `domainName` starts with a wildcard, check the base domain against all the subdomains of `certificateCommonName`.
             if (!domainNamesMatch && domainName.startsWith("*.") && (domainName.length() > 2)) {
                 // Remove the initial `*.`.