]> gitweb.stoutner.com Git - PrivacyBrowserAndroid.git/blobdiff - app/src/main/java/com/stoutner/privacybrowser/fragments/DomainSettingsFragment.java
Implement IP Address Pinning. https://redmine.stoutner.com/issues/212
[PrivacyBrowserAndroid.git] / app / src / main / java / com / stoutner / privacybrowser / fragments / DomainSettingsFragment.java
index dd1385956d5afa1f87473537bf12a5789b1e02d4..614bb374e80278243f42043b5b5adb05f196af1d 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;
@@ -78,13 +79,12 @@ public class DomainSettingsFragment extends Fragment {
     }
 
     // The deprecated `getDrawable()` must be used until the minimum API >= 21.
-    @SuppressWarnings("deprecation")
     @Override
     public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
         // Inflate `domain_settings_fragment`.  `false` does not attach it to the root `container`.
         View domainSettingsView = inflater.inflate(R.layout.domain_settings_fragment, container, false);
 
-        // Get a handle for the `Context` and the `Resources`.
+        // Get a handle for the context and the resources.
         Context context = getContext();
         final Resources resources = getResources();
 
@@ -92,47 +92,56 @@ 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");
-        final boolean defaultDisplayWebpageImagesBoolean = sharedPreferences.getBoolean("display_website_images", true);
-        final boolean defaultNightModeBoolean = sharedPreferences.getBoolean("night_mode", false);
+        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);
-        final Switch javaScriptEnabledSwitch = domainSettingsView.findViewById(R.id.domain_settings_javascript_switch);
-        final ImageView javaScriptImageView = domainSettingsView.findViewById(R.id.domain_settings_javascript_imageview);
-        Switch firstPartyCookiesEnabledSwitch = domainSettingsView.findViewById(R.id.domain_settings_first_party_cookies_switch);
-        final ImageView firstPartyCookiesImageView = domainSettingsView.findViewById(R.id.domain_settings_first_party_cookies_imageview);
-        LinearLayout thirdPartyCookiesLinearLayout = domainSettingsView.findViewById(R.id.domain_settings_third_party_cookies_linearlayout);
-        final Switch thirdPartyCookiesEnabledSwitch = domainSettingsView.findViewById(R.id.domain_settings_third_party_cookies_switch);
-        final ImageView thirdPartyCookiesImageView = domainSettingsView.findViewById(R.id.domain_settings_third_party_cookies_imageview);
-        final Switch domStorageEnabledSwitch = domainSettingsView.findViewById(R.id.domain_settings_dom_storage_switch);
-        final ImageView domStorageImageView = domainSettingsView.findViewById(R.id.domain_settings_dom_storage_imageview);
-        Switch formDataEnabledSwitch = domainSettingsView.findViewById(R.id.domain_settings_form_data_switch);
-        final ImageView formDataImageView = domainSettingsView.findViewById(R.id.domain_settings_form_data_imageview);
-        Switch easyListSwitch = domainSettingsView.findViewById(R.id.domain_settings_easylist_switch);
-        ImageView easyListImageView = domainSettingsView.findViewById(R.id.domain_settings_easylist_imageview);
-        Switch easyPrivacySwitch = domainSettingsView.findViewById(R.id.domain_settings_easyprivacy_switch);
-        ImageView easyPrivacyImageView = domainSettingsView.findViewById(R.id.domain_settings_easyprivacy_imageview);
-        Switch fanboysAnnoyanceListSwitch = domainSettingsView.findViewById(R.id.domain_settings_fanboys_annoyance_list_switch);
-        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);
-        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);
-        final Spinner fontSizeSpinner = domainSettingsView.findViewById(R.id.domain_settings_font_size_spinner);
-        final TextView fontSizeTextView = domainSettingsView.findViewById(R.id.domain_settings_font_size_textview);
-        final ImageView displayWebpageImagesImageView = domainSettingsView.findViewById(R.id.domain_settings_display_webpage_images_imageview);
-        final Spinner displayWebpageImagesSpinner = domainSettingsView.findViewById(R.id.domain_settings_display_webpage_images_spinner);
-        final TextView displayImagesTextView = domainSettingsView.findViewById(R.id.domain_settings_display_webpage_images_textview);
-        final ImageView nightModeImageView = domainSettingsView.findViewById(R.id.domain_settings_night_mode_imageview);
-        final Spinner nightModeSpinner = domainSettingsView.findViewById(R.id.domain_settings_night_mode_spinner);
-        final TextView nightModeTextView = domainSettingsView.findViewById(R.id.domain_settings_night_mode_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 Switch javaScriptEnabledSwitch = domainSettingsView.findViewById(R.id.javascript_switch);
+        final ImageView javaScriptImageView = domainSettingsView.findViewById(R.id.javascript_imageview);
+        Switch firstPartyCookiesEnabledSwitch = domainSettingsView.findViewById(R.id.first_party_cookies_switch);
+        final ImageView firstPartyCookiesImageView = domainSettingsView.findViewById(R.id.first_party_cookies_imageview);
+        LinearLayout thirdPartyCookiesLinearLayout = domainSettingsView.findViewById(R.id.third_party_cookies_linearlayout);
+        final Switch thirdPartyCookiesEnabledSwitch = domainSettingsView.findViewById(R.id.third_party_cookies_switch);
+        final ImageView thirdPartyCookiesImageView = domainSettingsView.findViewById(R.id.third_party_cookies_imageview);
+        final Switch domStorageEnabledSwitch = domainSettingsView.findViewById(R.id.dom_storage_switch);
+        final ImageView domStorageImageView = domainSettingsView.findViewById(R.id.dom_storage_imageview);
+        Switch formDataEnabledSwitch = domainSettingsView.findViewById(R.id.form_data_switch);  // The form data views can be remove once the minimum API >= 26.
+        final ImageView formDataImageView = domainSettingsView.findViewById(R.id.form_data_imageview);  // The form data views can be remove once the minimum API >= 26.
+        Switch easyListSwitch = domainSettingsView.findViewById(R.id.easylist_switch);
+        ImageView easyListImageView = domainSettingsView.findViewById(R.id.easylist_imageview);
+        Switch easyPrivacySwitch = domainSettingsView.findViewById(R.id.easyprivacy_switch);
+        ImageView easyPrivacyImageView = domainSettingsView.findViewById(R.id.easyprivacy_imageview);
+        Switch fanboysAnnoyanceListSwitch = domainSettingsView.findViewById(R.id.fanboys_annoyance_list_switch);
+        ImageView fanboysAnnoyanceListImageView = domainSettingsView.findViewById(R.id.fanboys_annoyance_list_imageview);
+        Switch fanboysSocialBlockingListSwitch = domainSettingsView.findViewById(R.id.fanboys_social_blocking_list_switch);
+        ImageView fanboysSocialBlockingListImageView = domainSettingsView.findViewById(R.id.fanboys_social_blocking_list_imageview);
+        Switch ultraPrivacySwitch = domainSettingsView.findViewById(R.id.ultraprivacy_switch);
+        ImageView ultraPrivacyImageView = domainSettingsView.findViewById(R.id.ultraprivacy_imageview);
+        Switch blockAllThirdPartyRequestsSwitch = domainSettingsView.findViewById(R.id.block_all_third_party_requests_switch);
+        ImageView blockAllThirdPartyRequestsImageView = domainSettingsView.findViewById(R.id.block_all_third_party_requests_imageview);
+        final Spinner userAgentSpinner = domainSettingsView.findViewById(R.id.user_agent_spinner);
+        final TextView userAgentTextView = domainSettingsView.findViewById(R.id.user_agent_textview);
+        final EditText customUserAgentEditText = domainSettingsView.findViewById(R.id.custom_user_agent_edittext);
+        final Spinner fontSizeSpinner = domainSettingsView.findViewById(R.id.font_size_spinner);
+        final TextView fontSizeTextView = domainSettingsView.findViewById(R.id.font_size_textview);
+        final ImageView swipeToRefreshImageView = domainSettingsView.findViewById(R.id.swipe_to_refresh_imageview);
+        final Spinner swipeToRefreshSpinner = domainSettingsView.findViewById(R.id.swipe_to_refresh_spinner);
+        final TextView swipeToRefreshTextView = domainSettingsView.findViewById(R.id.swipe_to_refresh_textview);
+        final ImageView nightModeImageView = domainSettingsView.findViewById(R.id.night_mode_imageview);
+        final Spinner nightModeSpinner = domainSettingsView.findViewById(R.id.night_mode_spinner);
+        final TextView nightModeTextView = domainSettingsView.findViewById(R.id.night_mode_textview);
+        final ImageView displayWebpageImagesImageView = domainSettingsView.findViewById(R.id.display_webpage_images_imageview);
+        final Spinner displayWebpageImagesSpinner = domainSettingsView.findViewById(R.id.display_webpage_images_spinner);
+        final TextView displayImagesTextView = domainSettingsView.findViewById(R.id.display_webpage_images_textview);
+        final ImageView pinnedSslCertificateImageView = domainSettingsView.findViewById(R.id.pinned_ssl_certificate_imageview);
+        Switch pinnedSslCertificateSwitch = domainSettingsView.findViewById(R.id.pinned_ssl_certificate_switch);
+        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);
@@ -142,7 +151,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);
@@ -153,9 +163,19 @@ public class DomainSettingsFragment extends Fragment {
         TextView currentWebsiteCertificateStartDateTextView = domainSettingsView.findViewById(R.id.current_website_certificate_start_date);
         TextView currentWebsiteCertificateEndDateTextView = domainSettingsView.findViewById(R.id.current_website_certificate_end_date);
         final TextView noCurrentWebsiteCertificateTextView = domainSettingsView.findViewById(R.id.no_current_website_certificate);
-
-        // Setup the SSL certificate labels.
-        final String cNameLabel = getString(R.string.common_name) + "  ";
+        ImageView pinnedIpAddressesImageView = domainSettingsView.findViewById(R.id.pinned_ip_addresses_imageview);
+        Switch pinnedIpAddressesSwitch = domainSettingsView.findViewById(R.id.pinned_ip_addresses_switch);
+        CardView savedIpAddressesCardView = domainSettingsView.findViewById(R.id.saved_ip_addresses_cardview);
+        LinearLayout savedIpAddressesLinearLayout = domainSettingsView.findViewById(R.id.saved_ip_addresses_linearlayout);
+        RadioButton savedIpAddressesRadioButton = domainSettingsView.findViewById(R.id.saved_ip_addresses_radiobutton);
+        TextView savedIpAddressesTextView = domainSettingsView.findViewById(R.id.saved_ip_addresses_textview);
+        CardView currentIpAddressesCardView = domainSettingsView.findViewById(R.id.current_ip_addresses_cardview);
+        LinearLayout currentIpAddressesLinearLayout = domainSettingsView.findViewById(R.id.current_ip_addresses_linearlayout);
+        RadioButton currentIpAddressesRadioButton = domainSettingsView.findViewById(R.id.current_ip_addresses_radiobutton);
+        TextView currentIpAddressesTextView = domainSettingsView.findViewById(R.id.current_ip_addresses_textview);
+
+        // Setup the pinned labels.
+        String cNameLabel = getString(R.string.common_name) + "  ";
         String oNameLabel = getString(R.string.organization) + "  ";
         String uNameLabel = getString(R.string.organizational_unit) + "  ";
         String startDateLabel = getString(R.string.start_date) + "  ";
@@ -167,32 +187,37 @@ public class DomainSettingsFragment extends Fragment {
         // 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(context, null, null, 0);
 
-        // Get the database `Cursor` for this ID and move it to the first row.
+        // Get the database cursor for this ID and move it to the first row.
         Cursor domainCursor = domainsDatabaseHelper.getCursorForId(databaseId);
         domainCursor.moveToFirst();
 
-        // Save the `Cursor` entries as variables.
+        // Save the cursor entries as variables.
         String domainNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.DOMAIN_NAME));
         final int javaScriptEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_JAVASCRIPT));
         int firstPartyCookiesEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FIRST_PARTY_COOKIES));
         int thirdPartyCookiesEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_THIRD_PARTY_COOKIES));
         final int domStorageEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_DOM_STORAGE));
-        int formDataEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FORM_DATA));
+        int formDataEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FORM_DATA));  // Form data can be remove once the minimum API >= 26.
         int easyListEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYLIST));
         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 displayImagesInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.DISPLAY_IMAGES));
+        int swipeToRefreshInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.SWIPE_TO_REFRESH));
         int nightModeInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.NIGHT_MODE));
+        int displayImagesInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.DISPLAY_IMAGES));
         int pinnedSslCertificateInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.PINNED_SSL_CERTIFICATE));
-        final String savedSslCertificateIssuedToCNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_COMMON_NAME));
+        String savedSslCertificateIssuedToCNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_COMMON_NAME));
         String savedSslCertificateIssuedToONameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATION));
         String savedSslCertificateIssuedToUNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATIONAL_UNIT));
         String savedSslCertificateIssuedByCNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_COMMON_NAME));
         String savedSslCertificateIssuedByONameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATION));
         String savedSslCertificateIssuedByUNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATIONAL_UNIT));
+        int pinnedIpAddressesInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.PINNED_IP_ADDRESSES));
+        String savedIpAddresses = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.IP_ADDRESSES));
 
         // Initialize the saved SSL certificate date variables.
         Date savedSslCertificateStartDate = null;
@@ -207,26 +232,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);
-        final ArrayAdapter<CharSequence> displayImagesArrayAdapter = ArrayAdapter.createFromResource(context, R.array.display_webpage_images_array, R.layout.domain_settings_spinner_item);
-        ArrayAdapter<CharSequence> nightModeArrayAdapter = ArrayAdapter.createFromResource(context, R.array.night_mode_array, R.layout.domain_settings_spinner_item);
-
-        // Set the `DropDownViewResource` on the `Spinners`.
-        translatedUserAgentArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_item);
-        fontSizeArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_item);
-        displayImagesArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_item);
-        nightModeArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_item);
-
-        // Set the `ArrayAdapters` for the `Spinners`.
+        // 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 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 array adapters for the spinners.
         userAgentSpinner.setAdapter(translatedUserAgentArrayAdapter);
         fontSizeSpinner.setAdapter(fontSizeArrayAdapter);
-        displayWebpageImagesSpinner.setAdapter(displayImagesArrayAdapter);
+        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);
@@ -234,7 +262,7 @@ public class DomainSettingsFragment extends Fragment {
         SpannableStringBuilder savedSslCertificateIssuedByONameStringBuilder = new SpannableStringBuilder(oNameLabel + savedSslCertificateIssuedByONameString);
         SpannableStringBuilder savedSslCertificateIssuedByUNameStringBuilder = new SpannableStringBuilder(uNameLabel + savedSslCertificateIssuedByUNameString);
 
-        // Initialize the `SpannableStringBuilders` for the SSL certificate dates.
+        // Initialize the spannable string builders for the SSL certificate dates.
         SpannableStringBuilder savedSslCertificateStartDateStringBuilder;
         SpannableStringBuilder savedSslCertificateEndDateStringBuilder;
 
@@ -251,19 +279,19 @@ public class DomainSettingsFragment extends Fragment {
             savedSslCertificateEndDateStringBuilder = new SpannableStringBuilder(endDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG).format(savedSslCertificateEndDate));
         }
 
-        // Create a red `ForegroundColorSpan`.  We have to use the deprecated `getColor` until API >= 23.
-        final ForegroundColorSpan redColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.red_a700));
+        // Create a red foreground color span.  The deprecated `resources.getColor` must be used until the minimum API >= 23.
+        final ForegroundColorSpan redColorSpan = new ForegroundColorSpan(resources.getColor(R.color.red_a700));
 
-        // Create a blue `ForegroundColorSpan`.
+        // Create a blue foreground color span.
         final ForegroundColorSpan blueColorSpan;
 
-        // Set `blueColorSpan` according to the theme.  We have to use the deprecated `getColor()` until API >= 23.
+        // Set the blue color span according to the theme.  The deprecated `resources.getColor` must be used until the minimum API >= 23.
         if (MainWebViewActivity.darkTheme) {
             //noinspection deprecation
-            blueColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.blue_400));
+            blueColorSpan = new ForegroundColorSpan(resources.getColor(R.color.blue_400));
         } else {
             //noinspection deprecation
-            blueColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.blue_700));
+            blueColorSpan = new ForegroundColorSpan(resources.getColor(R.color.blue_700));
         }
 
         // Set the domain name from the the database cursor.
@@ -326,10 +354,10 @@ 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);
+        // Create a boolean to track if night mode is enabled.
+        boolean nightModeEnabled = (nightModeInt == DomainsDatabaseHelper.NIGHT_MODE_ENABLED) || ((nightModeInt == DomainsDatabaseHelper.NIGHT_MODE_SYSTEM_DEFAULT) && defaultNightMode);
 
-        // Disable the JavaScript `Switch` if night mode is enabled.
+        // Disable the JavaScript switch if night mode is enabled.
         if (nightModeEnabled) {
             javaScriptEnabledSwitch.setEnabled(false);
         } else {
@@ -343,7 +371,7 @@ public class DomainSettingsFragment extends Fragment {
             javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.privacy_mode));
         }
 
-        // Set the JavaScript `Switch` status.
+        // Set the JavaScript switch status.
         if (javaScriptEnabledInt == 1) {  // JavaScript is enabled.
             javaScriptEnabledSwitch.setChecked(true);
         } else {  // JavaScript is disabled.
@@ -402,7 +430,7 @@ public class DomainSettingsFragment extends Fragment {
                 }
             }
         } else {  // Third-party cookies cannot be configured for API <= 21.
-            // Hide the `LinearLayout` for third-party cookies.
+            // Hide the LinearLayout for third-party cookies.
             thirdPartyCookiesLinearLayout.setVisibility(View.GONE);
         }
 
@@ -445,19 +473,24 @@ public class DomainSettingsFragment extends Fragment {
             }
         }
 
-        // Set the form data status.  Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
-        if (formDataEnabledInt == 1) {  // Form data is on.
-            formDataEnabledSwitch.setChecked(true);
-            formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_enabled));
-        } else {  // Form data is off.
-            // Turn the form data switch to off.
-            formDataEnabledSwitch.setChecked(false);
+        // Set the form data status.  Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.  Form data can be removed once the minimum API >= 26.
+        if (Build.VERSION.SDK_INT >= 26) {  // Form data no longer applies to newer versions of Android.
+            // Hide the form data switch.
+            formDataEnabledSwitch.setVisibility(View.GONE);
+        } else {  // Form data should be displayed because this is an older version of Android.
+            if (formDataEnabledInt == 1) {  // Form data is on.
+                formDataEnabledSwitch.setChecked(true);
+                formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_enabled));
+            } else {  // Form data is off.
+                // Turn the form data switch to off.
+                formDataEnabledSwitch.setChecked(false);
 
-            // Set the icon according to the theme.
-            if (MainWebViewActivity.darkTheme) {
-                formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_disabled_dark));
-            } else {
-                formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_disabled_light));
+                // Set the icon according to the theme.
+                if (MainWebViewActivity.darkTheme) {
+                    formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_disabled_dark));
+                } else {
+                    formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_disabled_light));
+                }
             }
         }
 
@@ -576,6 +609,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);
@@ -583,7 +662,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);
@@ -648,7 +727,7 @@ public class DomainSettingsFragment extends Fragment {
             }
         }
 
-        // Open the user agent spinner when the `TextView` is clicked.
+        // Open the user agent spinner when the TextView is clicked.
         userAgentTextView.setOnClickListener((View v) -> {
             // Open the user agent spinner.
             userAgentSpinner.performClick();
@@ -662,97 +741,96 @@ public class DomainSettingsFragment extends Fragment {
         int defaultFontSizeArrayPosition = fontSizeEntryValuesArrayAdapter.getPosition(defaultFontSizeString);
         fontSizeTextView.setText(fontSizeArrayAdapter.getItem(defaultFontSizeArrayPosition));
 
-        // Set the display options for `fontSizeTextView`.
+        // Set the display options for the font size TextView.
         if (fontSizeArrayPosition == 0) {  // System default font size is selected.  Display `fontSizeTextView`.
             fontSizeTextView.setVisibility(View.VISIBLE);
         } else {  // A custom font size is specified.  Hide `fontSizeTextView`.
             fontSizeTextView.setVisibility(View.GONE);
         }
 
-        // Open the font size spinner when the `TextView` is clicked.
+        // Open the font size spinner when the TextView is clicked.
         fontSizeTextView.setOnClickListener((View v) -> {
             // Open the user agent spinner.
             fontSizeSpinner.performClick();
         });
 
-        // Display the website images mode in the spinner.
-        displayWebpageImagesSpinner.setSelection(displayImagesInt);
+        // Display the swipe to refresh selection in the spinner.
+        swipeToRefreshSpinner.setSelection(swipeToRefreshInt);
 
-        // Set the default display images text.
-        if (defaultDisplayWebpageImagesBoolean) {
-            displayImagesTextView.setText(displayImagesArrayAdapter.getItem(DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_ENABLED));
+        // Set the swipe to refresh text.
+        if (defaultSwipeToRefresh) {
+            swipeToRefreshTextView.setText(swipeToRefreshArrayAdapter.getItem(DomainsDatabaseHelper.SWIPE_TO_REFRESH_ENABLED));
         } else {
-            displayImagesTextView.setText(displayImagesArrayAdapter.getItem(DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_DISABLED));
+            swipeToRefreshTextView.setText(swipeToRefreshArrayAdapter.getItem(DomainsDatabaseHelper.SWIPE_TO_REFRESH_DISABLED));
         }
 
-        // 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.
+        // 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 (defaultSwipeToRefresh) {  // Swipe to refresh is enabled by default.
                     // Set the icon according to the theme.
                     if (MainWebViewActivity.darkTheme) {
-                        displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_dark));
+                        swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_dark));
                     } else {
-                        displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_light));
+                        swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_light));
                     }
-                } else {  // Display webpage images disabled by default.
+                } else {  // Swipe to refresh is disabled by default
                     // Set the icon according to the theme.
                     if (MainWebViewActivity.darkTheme) {
-                        displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_dark));
+                        swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_dark));
                     } else {
-                        displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_light));
+                        swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_light));
                     }
                 }
 
-                // Show `displayImagesTextView`.
-                displayImagesTextView.setVisibility(View.VISIBLE);
+                // Show the swipe to refresh TextView.
+                swipeToRefreshTextView.setVisibility(View.VISIBLE);
                 break;
 
-            case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_ENABLED:
+            case DomainsDatabaseHelper.SWIPE_TO_REFRESH_ENABLED:
                 // Set the icon according to the theme.
                 if (MainWebViewActivity.darkTheme) {
-                    displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_dark));
+                    swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_dark));
                 } else {
-                    displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_light));
+                    swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_light));
                 }
 
-                // Hide `displayImagesTextView`.
-                displayImagesTextView.setVisibility(View.GONE);
+                // Hide the swipe to refresh TextView.`
+                swipeToRefreshTextView.setVisibility(View.GONE);
                 break;
 
-            case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_DISABLED:
+            case DomainsDatabaseHelper.SWIPE_TO_REFRESH_DISABLED:
                 // Set the icon according to the theme.
                 if (MainWebViewActivity.darkTheme) {
-                    displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_dark));
+                    swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_dark));
                 } else {
-                    displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_light));
+                    swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_light));
                 }
 
-                // Hide `displayImagesTextView`.
-                displayImagesTextView.setVisibility(View.GONE);
-                break;
+                // Hide the swipe to refresh TextView.
+                swipeToRefreshTextView.setVisibility(View.GONE);
         }
 
-        // Open the display images spinner when the `TextView` is clicked.
-        displayImagesTextView.setOnClickListener((View v) -> {
-            // Open the user agent spinner.
-            displayWebpageImagesSpinner.performClick();
+        // Open the swipe to refresh spinner when the TextView is clicked.
+        swipeToRefreshTextView.setOnClickListener((View v) -> {
+            // Open the swipe to refresh spinner.
+            swipeToRefreshSpinner.performClick();
         });
 
         // Display the night mode in the spinner.
         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));
         }
 
-        // 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 (displayImagesInt) {
+        // 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));
@@ -768,7 +846,7 @@ public class DomainSettingsFragment extends Fragment {
                     }
                 }
 
-                // Show `nightModeTextView`.
+                // Show night mode TextView.
                 nightModeTextView.setVisibility(View.VISIBLE);
                 break;
 
@@ -780,7 +858,7 @@ public class DomainSettingsFragment extends Fragment {
                     nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_light));
                 }
 
-                // Hide `nightModeTextView`.
+                // Hide the night mode TextView.
                 nightModeTextView.setVisibility(View.GONE);
                 break;
 
@@ -792,16 +870,80 @@ public class DomainSettingsFragment extends Fragment {
                     nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_light));
                 }
 
-                // Hide `nightModeTextView`.
+                // Hide the night mode TextView.
                 nightModeTextView.setVisibility(View.GONE);
                 break;
         }
 
-        // Open the night mode spinner when the `TextView` is clicked.
+        // Open the night mode spinner when the TextView is clicked.
         nightModeTextView.setOnClickListener((View v) -> {
-            // Open the user agent spinner.
+            // Open the night mode spinner.
             nightModeSpinner.performClick();
         });
+
+        // Display the website images mode in the spinner.
+        displayWebpageImagesSpinner.setSelection(displayImagesInt);
+
+        // Set the default display images text.
+        if (defaultDisplayWebpageImages) {
+            displayImagesTextView.setText(displayImagesArrayAdapter.getItem(DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_ENABLED));
+        } else {
+            displayImagesTextView.setText(displayImagesArrayAdapter.getItem(DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_DISABLED));
+        }
+
+        // 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 (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));
+                    } else {
+                        displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_light));
+                    }
+                } else {  // Display webpage images disabled by default.
+                    // Set the icon according to the theme.
+                    if (MainWebViewActivity.darkTheme) {
+                        displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_dark));
+                    } else {
+                        displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_light));
+                    }
+                }
+
+                // Show the display images TextView.
+                displayImagesTextView.setVisibility(View.VISIBLE);
+                break;
+
+            case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_ENABLED:
+                // Set the icon according to the theme.
+                if (MainWebViewActivity.darkTheme) {
+                    displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_dark));
+                } else {
+                    displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_light));
+                }
+
+                // Hide the display images TextView.
+                displayImagesTextView.setVisibility(View.GONE);
+                break;
+
+            case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_DISABLED:
+                // Set the icon according to the theme.
+                if (MainWebViewActivity.darkTheme) {
+                    displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_dark));
+                } else {
+                    displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_light));
+                }
+
+                // Hide the display images TextView.
+                displayImagesTextView.setVisibility(View.GONE);
+                break;
+        }
+
+        // Open the display images spinner when the TextView is clicked.
+        displayImagesTextView.setOnClickListener((View v) -> {
+            // Open the user agent spinner.
+            displayWebpageImagesSpinner.performClick();
+        });
         
         // Set the pinned SSL certificate icon.
         if (pinnedSslCertificateInt == 1) {  // Pinned SSL certificate is enabled.  Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
@@ -829,17 +971,17 @@ public class DomainSettingsFragment extends Fragment {
         // Store the current date.
         Date currentDate = Calendar.getInstance().getTime();
 
-        // Setup the `StringBuilders` to display the general certificate information in blue.  `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
+        // Setup the string builders to display the general certificate information in blue.  `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
         savedSslCertificateIssuedToONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), savedSslCertificateIssuedToONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
         savedSslCertificateIssuedToUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), savedSslCertificateIssuedToUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
         savedSslCertificateIssuedByCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), savedSslCertificateIssuedByCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
         savedSslCertificateIssuedByONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), savedSslCertificateIssuedByONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
         savedSslCertificateIssuedByUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), savedSslCertificateIssuedByUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
 
-        // Check the certificate `Common Name` against the domain name.
+        // Check the certificate Common Name against the domain name.
         boolean savedSSlCertificateCommonNameMatchesDomainName = checkDomainNameAgainstCertificate(domainNameString, savedSslCertificateIssuedToCNameString);
 
-        // Format the `issuedToCommonName` color.  `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
+        // Format the issued to Common Name color.  `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
         if (savedSSlCertificateCommonNameMatchesDomainName) {
             savedSslCertificateIssuedToCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), savedSslCertificateIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
         } else {
@@ -860,7 +1002,7 @@ public class DomainSettingsFragment extends Fragment {
             savedSslCertificateEndDateStringBuilder.setSpan(blueColorSpan, endDateLabel.length(), savedSslCertificateEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
         }
 
-        // Display the current website SSL certificate strings.
+        // Display the saved website SSL certificate strings.
         savedSslCertificateIssuedToCNameTextView.setText(savedSslCertificateIssuedToCNameStringBuilder);
         savedSslCertificateIssuedToONameTextView.setText(savedSslCertificateIssuedToONameStringBuilder);
         savedSslCertificateIssuedToUNameTextView.setText(savedSslCertificateIssuedToUNameStringBuilder);
@@ -882,7 +1024,7 @@ public class DomainSettingsFragment extends Fragment {
             Date currentWebsiteCertificateStartDate = currentWebsiteSslCertificate.getValidNotBeforeDate();
             Date currentWebsiteCertificateEndDate = currentWebsiteSslCertificate.getValidNotAfterDate();
 
-            // Create a `SpannableStringBuilder` for each `TextView` that needs multiple colors of text.
+            // Create a spannable string builder for each text view that needs multiple colors of text.
             SpannableStringBuilder currentWebsiteCertificateIssuedToCNameStringBuilder = new SpannableStringBuilder(cNameLabel + currentWebsiteCertificateIssuedToCNameString);
             SpannableStringBuilder currentWebsiteCertificateIssuedToONameStringBuilder = new SpannableStringBuilder(oNameLabel + currentWebsiteCertificateIssuedToONameString);
             SpannableStringBuilder currentWebsiteCertificateIssuedToUNameStringBuilder = new SpannableStringBuilder(uNameLabel + currentWebsiteCertificateIssuedToUNameString);
@@ -894,17 +1036,17 @@ public class DomainSettingsFragment extends Fragment {
             SpannableStringBuilder currentWebsiteCertificateEndDateStringBuilder = new SpannableStringBuilder(endDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG)
                     .format(currentWebsiteCertificateEndDate));
 
-            // Setup the `StringBuilders` to display the general certificate information in blue.  `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
+            // Setup the string builders to display the general certificate information in blue.  `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
             currentWebsiteCertificateIssuedToONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), currentWebsiteCertificateIssuedToONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
             currentWebsiteCertificateIssuedToUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), currentWebsiteCertificateIssuedToUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
             currentWebsiteCertificateIssuedByCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), currentWebsiteCertificateIssuedByCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
             currentWebsiteCertificateIssuedByONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), currentWebsiteCertificateIssuedByONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
             currentWebsiteCertificateIssuedByUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), currentWebsiteCertificateIssuedByUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
 
-            // Check the certificate `Common Name` against the domain name.
+            // Check the certificate Common Name against the domain name.
             boolean currentWebsiteCertificateCommonNameMatchesDomainName = checkDomainNameAgainstCertificate(domainNameString, currentWebsiteCertificateIssuedToCNameString);
 
-            // Format the `issuedToCommonName` color.  `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
+            // Format the issued to Common Name color.  `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
             if (currentWebsiteCertificateCommonNameMatchesDomainName) {
                 currentWebsiteCertificateIssuedToCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), currentWebsiteCertificateIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
             } else {
@@ -936,45 +1078,59 @@ public class DomainSettingsFragment extends Fragment {
             currentWebsiteCertificateEndDateTextView.setText(currentWebsiteCertificateEndDateStringBuilder);
         }
 
-        // Set the initial display status for the SSL certificates.
-        if (pinnedSslCertificateSwitch.isChecked()) {
+        // Set the initial display status of the SSL certificates card views.
+        if (pinnedSslCertificateSwitch.isChecked()) {  // An SSL certificate is pinned.
             // 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) {
+            if (currentWebsiteSslCertificate == null) {  // There is no current SSL certificate.
                 // Hide the SSL certificate.
-                currentWebsiteCertificateLinearLayout.setVisibility(View.GONE);
+                currentWebsiteCertificateCardView.setVisibility(View.GONE);
 
                 // Show the instruction.
                 noCurrentWebsiteCertificateTextView.setVisibility(View.VISIBLE);
-            } else {
+            } else {  // There is a current SSL certificate.
                 // 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.
+            // Set the status of the radio buttons and the card view backgrounds.
+            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);
             } else {  // Neither SSL certificate is visible.
+                // Uncheck both radio buttons.
                 savedSslCertificateRadioButton.setChecked(false);
                 currentWebsiteCertificateRadioButton.setChecked(false);
             }
-        } else {  // `pinnedSslCertificateSwitch` is not checked.
+        } else {  // An SSL certificate is not pinned.
             // 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.
@@ -982,6 +1138,76 @@ public class DomainSettingsFragment extends Fragment {
             currentWebsiteCertificateRadioButton.setChecked(false);
         }
 
+        // Set the pinned IP addresses icon.
+        if (pinnedIpAddressesInt == 1) {  // Pinned IP addresses is enabled.  Once the minimum API >= 21 a selector can be sued as the tint mode instead of specifying different icons.
+            // Check the switch.
+            pinnedIpAddressesSwitch.setChecked(true);
+
+            // Set the icon according to the theme.
+            if (MainWebViewActivity.darkTheme) {
+                pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_dark));
+            } else {
+                pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_light));
+            }
+        } else {  // Pinned IP Addresses is disabled.
+            // Uncheck the switch.
+            pinnedIpAddressesSwitch.setChecked(false);
+
+            // Set the icon according to the theme.
+            if (MainWebViewActivity.darkTheme) {
+                pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_dark));
+            } else {
+                pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_light));
+            }
+        }
+
+        // Populate the saved and current IP addresses.
+        savedIpAddressesTextView.setText(savedIpAddresses);
+        currentIpAddressesTextView.setText(MainWebViewActivity.currentHostIpAddresses);
+
+        // Set the initial display status of the IP addresses card views.
+        if (pinnedIpAddressesSwitch.isChecked()) {  // IP addresses are pinned.
+            // Set the visibility of the saved IP addresses.
+            if (savedIpAddresses == null) {  // There are no saved IP addresses.
+                savedIpAddressesCardView.setVisibility(View.GONE);
+            } else {  // There are saved IP addresses.
+                savedIpAddressesCardView.setVisibility(View.VISIBLE);
+            }
+
+            // Set the visibility of the current IP addresses.
+            currentIpAddressesCardView.setVisibility(View.VISIBLE);
+
+            // Set the status of the radio buttons and the card view backgrounds.
+            if (savedIpAddressesCardView.getVisibility() == View.VISIBLE) {  // The saved IP addresses are displayed.
+                // Check the saved IP addresses radio button.
+                savedIpAddressesRadioButton.setChecked(true);
+
+                // Uncheck the current IP addresses radio button.
+                currentIpAddressesRadioButton.setChecked(false);
+
+                // Darken the background of the current IP addresses linear layout according to the theme.
+                if (MainWebViewActivity.darkTheme) {
+                    currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
+                } else {
+                    currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
+                }
+            } else {  // The saved IP addresses are hidden.
+                // Check the current IP addresses radio button.
+                currentIpAddressesRadioButton.setChecked(true);
+
+                // Uncheck the saved IP addresses radio button.
+                savedIpAddressesRadioButton.setChecked(false);
+            }
+        } else {  // IP addresses are not pinned.
+            // Hide the IP addresses card views.
+            savedIpAddressesCardView.setVisibility(View.GONE);
+            currentIpAddressesCardView.setVisibility(View.GONE);
+
+            // Uncheck the radio buttons.
+            savedIpAddressesRadioButton.setChecked(false);
+            currentIpAddressesRadioButton.setChecked(false);
+        }
+
 
         // Set the JavaScript switch listener.
         javaScriptEnabledSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
@@ -1089,20 +1315,22 @@ public class DomainSettingsFragment extends Fragment {
             }
         });
 
-        // Set the form data switch listener.
-        formDataEnabledSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
-            // Update the icon.
-            if (isChecked) {
-                formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_enabled));
-            } else {
-                // Set the icon according to the theme.
-                if (MainWebViewActivity.darkTheme) {
-                    formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_disabled_dark));
+        // Set the form data switch listener.  It can be removed once the minimum API >= 26.
+        if (Build.VERSION.SDK_INT < 26) {
+            formDataEnabledSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
+                // Update the icon.
+                if (isChecked) {
+                    formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_enabled));
                 } else {
-                    formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_disabled_light));
+                    // Set the icon according to the theme.
+                    if (MainWebViewActivity.darkTheme) {
+                        formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_disabled_dark));
+                    } else {
+                        formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_disabled_light));
+                    }
                 }
-            }
-        });
+            });
+        }
 
         // Set the EasyList switch listener.
         easyListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
@@ -1215,6 +1443,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
@@ -1303,56 +1571,55 @@ public class DomainSettingsFragment extends Fragment {
             }
         });
 
-        // Set the display webpage images spinner listener.
-        displayWebpageImagesSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+        // Set the swipe to refresh spinner listener.
+        swipeToRefreshSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
             @Override
             public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
-                // Update the icon and the visibility of `displayImagesTextView`.
+                // 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.DISPLAY_WEBPAGE_IMAGES_SYSTEM_DEFAULT:
-                        if (defaultDisplayWebpageImagesBoolean) {
+                    case DomainsDatabaseHelper.SWIPE_TO_REFRESH_SYSTEM_DEFAULT:
+                        if (defaultSwipeToRefresh) {  // Swipe to refresh enabled by default.
                             // Set the icon according to the theme.
                             if (MainWebViewActivity.darkTheme) {
-                                displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_dark));
+                                swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_dark));
                             } else {
-                                displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_light));
+                                swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_light));
                             }
-                        } else {
+                        } else {  // Swipe to refresh disabled by default.
                             // Set the icon according to the theme.
                             if (MainWebViewActivity.darkTheme) {
-                                displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_dark));
+                                swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_dark));
                             } else {
-                                displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_light));
+                                swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_light));
                             }
                         }
 
-                        // Show `displayImagesTextView`.
-                        displayImagesTextView.setVisibility(View.VISIBLE);
+                        // Show the swipe to refresh TextView.
+                        swipeToRefreshTextView.setVisibility(View.VISIBLE);
                         break;
 
-                    case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_ENABLED:
+                    case DomainsDatabaseHelper.SWIPE_TO_REFRESH_ENABLED:
                         // Set the icon according to the theme.
                         if (MainWebViewActivity.darkTheme) {
-                            displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_dark));
+                            swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_dark));
                         } else {
-                            displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_light));
+                            swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_light));
                         }
 
-                        // Hide `displayImagesTextView`.
-                        displayImagesTextView.setVisibility(View.GONE);
+                        // Hide the swipe to refresh TextView.
+                        swipeToRefreshTextView.setVisibility(View.GONE);
                         break;
 
-                    case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_DISABLED:
+                    case DomainsDatabaseHelper.SWIPE_TO_REFRESH_DISABLED:
                         // Set the icon according to the theme.
                         if (MainWebViewActivity.darkTheme) {
-                            displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_dark));
+                            swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_dark));
                         } else {
-                            displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_light));
+                            swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_light));
                         }
 
-                        // Hide `displayImagesTextView`.
-                        displayImagesTextView.setVisibility(View.GONE);
-                        break;
+                        // Hide the swipe to refresh TextView.
+                        swipeToRefreshTextView.setVisibility(View.GONE);
                 }
             }
 
@@ -1369,7 +1636,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));
@@ -1385,7 +1652,7 @@ public class DomainSettingsFragment extends Fragment {
                             }
                         }
 
-                        // Show `nightModeTextView`.
+                        // Show the night mode TextView.
                         nightModeTextView.setVisibility(View.VISIBLE);
                         break;
 
@@ -1415,7 +1682,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) {
@@ -1476,11 +1743,70 @@ public class DomainSettingsFragment extends Fragment {
                 // Do nothing.
             }
         });
+
+        // Set the display webpage images spinner listener.
+        displayWebpageImagesSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+            @Override
+            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+                // Update the icon and the visibility of `displayImagesTextView`.
+                switch (position) {
+                    case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_SYSTEM_DEFAULT:
+                        if (defaultDisplayWebpageImages) {
+                            // Set the icon according to the theme.
+                            if (MainWebViewActivity.darkTheme) {
+                                displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_dark));
+                            } else {
+                                displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_light));
+                            }
+                        } else {
+                            // Set the icon according to the theme.
+                            if (MainWebViewActivity.darkTheme) {
+                                displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_dark));
+                            } else {
+                                displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_light));
+                            }
+                        }
+
+                        // Show `displayImagesTextView`.
+                        displayImagesTextView.setVisibility(View.VISIBLE);
+                        break;
+
+                    case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_ENABLED:
+                        // Set the icon according to the theme.
+                        if (MainWebViewActivity.darkTheme) {
+                            displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_dark));
+                        } else {
+                            displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_light));
+                        }
+
+                        // Hide `displayImagesTextView`.
+                        displayImagesTextView.setVisibility(View.GONE);
+                        break;
+
+                    case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_DISABLED:
+                        // Set the icon according to the theme.
+                        if (MainWebViewActivity.darkTheme) {
+                            displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_dark));
+                        } else {
+                            displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_light));
+                        }
+
+                        // Hide `displayImagesTextView`.
+                        displayImagesTextView.setVisibility(View.GONE);
+                        break;
+                }
+            }
+
+            @Override
+            public void onNothingSelected(AdapterView<?> parent) {
+                // Do nothing.
+            }
+        });
         
         // Set the pinned SSL certificate switch listener.
         pinnedSslCertificateSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
-            // Update the icon
-            if (isChecked) {  // Pinned SSL certificate is enabled.
+            // Update the icon.
+            if (isChecked) {  // SSL certificate pinning is enabled.
                 // Set the icon according to the theme.
                 if (MainWebViewActivity.darkTheme) {
                     pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_dark));
@@ -1490,38 +1816,74 @@ 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);
+                    }
+
+                    // Scroll to the current website SSL certificate card.
+                    savedSslCertificateCardView.getParent().requestChildFocus(savedSslCertificateCardView, savedSslCertificateCardView);
+                } 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);
+                    }
+
+                    // Scroll to the current website SSL certificate card.
+                    currentWebsiteCertificateCardView.getParent().requestChildFocus(currentWebsiteCertificateCardView, currentWebsiteCertificateCardView);
                 } else {  // Neither SSL certificate is visible.
+                    // Uncheck both radio buttons.
                     savedSslCertificateRadioButton.setChecked(false);
                     currentWebsiteCertificateRadioButton.setChecked(false);
+
+                    // Scroll to the current website SSL certificate card.
+                    noCurrentWebsiteCertificateTextView.getParent().requestChildFocus(noCurrentWebsiteCertificateTextView, noCurrentWebsiteCertificateTextView);
                 }
-            } else {  // Pinned SSL certificate is disabled.
+            } else {  // SSL certificate pinning is disabled.
                 // Set the icon according to the theme.
                 if (MainWebViewActivity.darkTheme) {
                     pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_dark));
@@ -1530,8 +1892,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.
@@ -1540,24 +1902,224 @@ public class DomainSettingsFragment extends Fragment {
             }
         });
 
-        savedSslCertificateLinearLayout.setOnClickListener((View v) -> {
+        savedSslCertificateCardView.setOnClickListener((View view) -> {
+            // 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) -> {
+        savedSslCertificateRadioButton.setOnClickListener((View view) -> {
+            // 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 view) -> {
+            // 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) -> {
+        currentWebsiteCertificateRadioButton.setOnClickListener((View view) -> {
+            // 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);
+            }
+        });
+
+        // Set the pinned IP addresses switch listener.
+        pinnedIpAddressesSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
+            // Update the icon.
+            if (isChecked) {  // IP addresses pinning is enabled.
+                // Set the icon according to the theme.
+                if (MainWebViewActivity.darkTheme) {
+                    pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_dark));
+                } else {
+                    pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_light));
+                }
+
+                // Update the visibility of the saved IP addresses card view.
+                if (savedIpAddresses == null) {  // There are no saved IP addresses.
+                    savedIpAddressesCardView.setVisibility(View.GONE);
+                } else {  // There are saved IP addresses.
+                    savedIpAddressesCardView.setVisibility(View.VISIBLE);
+                }
+
+                // Show the current IP addresses card view.
+                currentIpAddressesCardView.setVisibility(View.VISIBLE);
+
+                // Set the status of the radio buttons.
+                if (savedIpAddressesCardView.getVisibility() == View.VISIBLE) {  // The saved IP addresses are visible.
+                    // Check the saved IP addresses radio button.
+                    savedIpAddressesRadioButton.setChecked(true);
+
+                    // Uncheck the current IP addresses radio button.
+                    currentIpAddressesRadioButton.setChecked(false);
+
+                    // Set the background of the saved IP addresses linear layout to be transparent.
+                    savedSslCertificateLinearLayout.setBackgroundResource(R.color.transparent);
+
+                    // Darken the background of the current IP addresses linear layout according to the theme.
+                    if (MainWebViewActivity.darkTheme) {
+                        currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
+                    } else {
+                        currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
+                    }
+                } else {  // The saved IP addresses are not visible.
+                    // Check the current IP addresses radio button.
+                    currentIpAddressesRadioButton.setChecked(true);
+
+                    // Uncheck the saved IP addresses radio button.
+                    savedIpAddressesRadioButton.setChecked(false);
+
+                    // Set the background of the current IP addresses linear layout to be transparent.
+                    currentIpAddressesLinearLayout.setBackgroundResource(R.color.transparent);
+
+                    // Darken the background of the saved IP addresses linear layout according to the theme.
+                    if (MainWebViewActivity.darkTheme) {
+                        savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
+                    } else {
+                        savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
+                    }
+                }
+
+                // Scroll to the bottom of the card views.
+                currentIpAddressesCardView.getParent().requestChildFocus(currentIpAddressesCardView, currentIpAddressesCardView);
+            } else {  // IP addresses pinning is disabled.
+                // Set the icon according to the theme.
+                if (MainWebViewActivity.darkTheme) {
+                    pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_dark));
+                } else {
+                    pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_light));
+                }
+
+                // Hide the IP addresses card views.
+                savedIpAddressesCardView.setVisibility(View.GONE);
+                currentIpAddressesCardView.setVisibility(View.GONE);
+
+                // Uncheck the radio buttons.
+                savedIpAddressesRadioButton.setChecked(false);
+                currentIpAddressesRadioButton.setChecked(false);
+            }
+        });
+
+        savedIpAddressesCardView.setOnClickListener((View view) -> {
+            // Check the saved IP addresses radio button.
+            savedIpAddressesRadioButton.setChecked(true);
+
+            // Uncheck the current website IP addresses radio button.
+            currentIpAddressesRadioButton.setChecked(false);
+
+            // Set the background of the saved IP addresses linear layout to be transparent.
+            savedIpAddressesLinearLayout.setBackgroundResource(R.color.transparent);
+
+            // Darken the background of the current IP addresses linear layout according to the theme.
+            if (MainWebViewActivity.darkTheme) {
+                currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
+            } else {
+                currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
+            }
+        });
+
+        savedIpAddressesRadioButton.setOnClickListener((View view) -> {
+            // Check the saved IP addresses radio button.
+            savedIpAddressesRadioButton.setChecked(true);
+
+            // Uncheck the current website IP addresses radio button.
+            currentIpAddressesRadioButton.setChecked(false);
+
+            // Set the background of the saved IP addresses linear layout to be transparent.
+            savedIpAddressesLinearLayout.setBackgroundResource(R.color.transparent);
+
+            // Darken the background of the current IP addresses linear layout according to the theme.
+            if (MainWebViewActivity.darkTheme) {
+                currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
+            } else {
+                currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
+            }
+        });
+
+        currentIpAddressesCardView.setOnClickListener((View view) -> {
+            // Check the current IP addresses radio button.
+            currentIpAddressesRadioButton.setChecked(true);
+
+            // Uncheck the saved IP addresses radio button.
+            savedIpAddressesRadioButton.setChecked(false);
+
+            // Set the background of the current IP addresses linear layout to be transparent.
+            currentIpAddressesLinearLayout.setBackgroundResource(R.color.transparent);
+
+            // Darken the background of the saved IP addresses linear layout according to the theme.
+            if (MainWebViewActivity.darkTheme) {
+                savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
+            } else {
+                savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
+            }
+        });
+
+        currentIpAddressesRadioButton.setOnClickListener((View view) -> {
+            // Check the current IP addresses radio button.
+            currentIpAddressesRadioButton.setChecked(true);
+
+            // Uncheck the saved IP addresses radio button.
+            savedIpAddressesRadioButton.setChecked(false);
+
+            // Set the background of the current IP addresses linear layout to be transparent.
+            currentIpAddressesLinearLayout.setBackgroundResource(R.color.transparent);
+
+            // Darken the background of the saved IP addresses linear layout according to the theme.
+            if (MainWebViewActivity.darkTheme) {
+                savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
+            } else {
+                savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
+            }
         });
 
         return domainSettingsView;
@@ -1567,15 +2129,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 `*.`.