2 * Copyright © 2017-2019 Soren Stoutner <soren@stoutner.com>.
4 * This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
6 * Privacy Browser is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * Privacy Browser is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with Privacy Browser. If not, see <http://www.gnu.org/licenses/>.
20 package com.stoutner.privacybrowser.fragments;
22 import android.annotation.SuppressLint;
23 import android.content.Context;
24 import android.content.SharedPreferences;
25 import android.content.res.Resources;
26 import android.database.Cursor;
27 import android.net.http.SslCertificate;
28 import android.os.Build;
29 import android.os.Bundle;
30 import android.preference.PreferenceManager;
31 import android.support.annotation.NonNull;
32 // `android.support.v4.app.Fragment` must be used until minimum API >= 23. Otherwise `getContext()` does not work.
33 import android.support.v4.app.Fragment;
34 import android.support.v7.widget.CardView;
35 import android.text.Editable;
36 import android.text.SpannableStringBuilder;
37 import android.text.Spanned;
38 import android.text.TextWatcher;
39 import android.text.style.ForegroundColorSpan;
40 import android.view.LayoutInflater;
41 import android.view.View;
42 import android.view.ViewGroup;
43 import android.webkit.WebView;
44 import android.widget.AdapterView;
45 import android.widget.ArrayAdapter;
46 import android.widget.CompoundButton;
47 import android.widget.EditText;
48 import android.widget.ImageView;
49 import android.widget.LinearLayout;
50 import android.widget.RadioButton;
51 import android.widget.Spinner;
52 import android.widget.Switch;
53 import android.widget.TextView;
55 import com.stoutner.privacybrowser.R;
56 import com.stoutner.privacybrowser.activities.MainWebViewActivity;
57 import com.stoutner.privacybrowser.helpers.DomainsDatabaseHelper;
59 import java.text.DateFormat;
60 import java.util.Calendar;
61 import java.util.Date;
63 public class DomainSettingsFragment extends Fragment {
64 // `DATABASE_ID` is used by activities calling this fragment.
65 public static final String DATABASE_ID = "database_id";
67 // `databaseId` is public static so it can be accessed from `DomainsActivity`. It is also used in `onCreate()` and `onCreateView()`.
68 public static int databaseId;
71 public void onCreate(Bundle savedInstanceState) {
72 super.onCreate(savedInstanceState);
74 // Remove the lint warning that `getArguments` might be null.
75 assert getArguments() != null;
77 // Store the database id in `databaseId`.
78 databaseId = getArguments().getInt(DATABASE_ID);
81 // The deprecated `getDrawable()` must be used until the minimum API >= 21.
82 @SuppressWarnings("deprecation")
84 public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
85 // Inflate `domain_settings_fragment`. `false` does not attach it to the root `container`.
86 View domainSettingsView = inflater.inflate(R.layout.domain_settings_fragment, container, false);
88 // Get a handle for the `Context` and the `Resources`.
89 Context context = getContext();
90 final Resources resources = getResources();
92 // Get a handle for the shared preference.
93 SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
95 // Store the default settings.
96 final String defaultUserAgentName = sharedPreferences.getString("user_agent", getString(R.string.user_agent_default_value));
97 final String defaultCustomUserAgentString = sharedPreferences.getString("custom_user_agent", getString(R.string.custom_user_agent_default_value));
98 String defaultFontSizeString = sharedPreferences.getString("font_size", getString(R.string.font_size_default_value));
99 boolean defaultSwipeToRefresh = sharedPreferences.getBoolean("swipe_to_refresh", true);
100 final boolean defaultNightMode = sharedPreferences.getBoolean("night_mode", false);
101 final boolean defaultDisplayWebpageImages = sharedPreferences.getBoolean("display_webpage_images", true);
103 // Get handles for the views in the fragment.
104 final EditText domainNameEditText = domainSettingsView.findViewById(R.id.domain_settings_name_edittext);
105 final Switch javaScriptEnabledSwitch = domainSettingsView.findViewById(R.id.domain_settings_javascript_switch);
106 final ImageView javaScriptImageView = domainSettingsView.findViewById(R.id.domain_settings_javascript_imageview);
107 Switch firstPartyCookiesEnabledSwitch = domainSettingsView.findViewById(R.id.domain_settings_first_party_cookies_switch);
108 final ImageView firstPartyCookiesImageView = domainSettingsView.findViewById(R.id.domain_settings_first_party_cookies_imageview);
109 LinearLayout thirdPartyCookiesLinearLayout = domainSettingsView.findViewById(R.id.domain_settings_third_party_cookies_linearlayout);
110 final Switch thirdPartyCookiesEnabledSwitch = domainSettingsView.findViewById(R.id.domain_settings_third_party_cookies_switch);
111 final ImageView thirdPartyCookiesImageView = domainSettingsView.findViewById(R.id.domain_settings_third_party_cookies_imageview);
112 final Switch domStorageEnabledSwitch = domainSettingsView.findViewById(R.id.domain_settings_dom_storage_switch);
113 final ImageView domStorageImageView = domainSettingsView.findViewById(R.id.domain_settings_dom_storage_imageview);
114 Switch formDataEnabledSwitch = domainSettingsView.findViewById(R.id.domain_settings_form_data_switch); // The form data views can be remove once the minimum API >= 26.
115 final ImageView formDataImageView = domainSettingsView.findViewById(R.id.domain_settings_form_data_imageview); // The form data views can be remove once the minimum API >= 26.
116 Switch easyListSwitch = domainSettingsView.findViewById(R.id.domain_settings_easylist_switch);
117 ImageView easyListImageView = domainSettingsView.findViewById(R.id.domain_settings_easylist_imageview);
118 Switch easyPrivacySwitch = domainSettingsView.findViewById(R.id.domain_settings_easyprivacy_switch);
119 ImageView easyPrivacyImageView = domainSettingsView.findViewById(R.id.domain_settings_easyprivacy_imageview);
120 Switch fanboysAnnoyanceListSwitch = domainSettingsView.findViewById(R.id.domain_settings_fanboys_annoyance_list_switch);
121 ImageView fanboysAnnoyanceListImageView = domainSettingsView.findViewById(R.id.domain_settings_fanboys_annoyance_list_imageview);
122 Switch fanboysSocialBlockingListSwitch = domainSettingsView.findViewById(R.id.domain_settings_fanboys_social_blocking_list_switch);
123 ImageView fanboysSocialBlockingListImageView = domainSettingsView.findViewById(R.id.domain_settings_fanboys_social_blocking_list_imageview);
124 Switch ultraPrivacySwitch = domainSettingsView.findViewById(R.id.domain_settings_ultraprivacy_switch);
125 ImageView ultraPrivacyImageView = domainSettingsView.findViewById(R.id.domain_settings_ultraprivacy_imageview);
126 Switch blockAllThirdPartyRequestsSwitch = domainSettingsView.findViewById(R.id.domain_settings_block_all_third_party_requests_switch);
127 ImageView blockAllThirdPartyRequestsImageView = domainSettingsView.findViewById(R.id.domain_settings_block_all_third_party_requests_imageview);
128 final Spinner userAgentSpinner = domainSettingsView.findViewById(R.id.domain_settings_user_agent_spinner);
129 final TextView userAgentTextView = domainSettingsView.findViewById(R.id.domain_settings_user_agent_textview);
130 final EditText customUserAgentEditText = domainSettingsView.findViewById(R.id.domain_settings_custom_user_agent_edittext);
131 final Spinner fontSizeSpinner = domainSettingsView.findViewById(R.id.domain_settings_font_size_spinner);
132 final TextView fontSizeTextView = domainSettingsView.findViewById(R.id.domain_settings_font_size_textview);
133 final ImageView swipeToRefreshImageView = domainSettingsView.findViewById(R.id.domain_settings_swipe_to_refresh_imageview);
134 final Spinner swipeToRefreshSpinner = domainSettingsView.findViewById(R.id.domain_settings_swipe_to_refresh_spinner);
135 final TextView swipeToRefreshTextView = domainSettingsView.findViewById(R.id.domain_settings_swipe_to_refresh_textview);
136 final ImageView nightModeImageView = domainSettingsView.findViewById(R.id.domain_settings_night_mode_imageview);
137 final Spinner nightModeSpinner = domainSettingsView.findViewById(R.id.domain_settings_night_mode_spinner);
138 final TextView nightModeTextView = domainSettingsView.findViewById(R.id.domain_settings_night_mode_textview);
139 final ImageView displayWebpageImagesImageView = domainSettingsView.findViewById(R.id.domain_settings_display_webpage_images_imageview);
140 final Spinner displayWebpageImagesSpinner = domainSettingsView.findViewById(R.id.domain_settings_display_webpage_images_spinner);
141 final TextView displayImagesTextView = domainSettingsView.findViewById(R.id.domain_settings_display_webpage_images_textview);
142 final ImageView pinnedSslCertificateImageView = domainSettingsView.findViewById(R.id.domain_settings_pinned_ssl_certificate_imageview);
143 Switch pinnedSslCertificateSwitch = domainSettingsView.findViewById(R.id.domain_settings_pinned_ssl_certificate_switch);
144 final CardView savedSslCertificateCardView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_cardview);
145 LinearLayout savedSslCertificateLinearLayout = domainSettingsView.findViewById(R.id.saved_ssl_certificate_linearlayout);
146 final RadioButton savedSslCertificateRadioButton = domainSettingsView.findViewById(R.id.saved_ssl_certificate_radiobutton);
147 final TextView savedSslCertificateIssuedToCNameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_to_cname);
148 TextView savedSslCertificateIssuedToONameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_to_oname);
149 TextView savedSslCertificateIssuedToUNameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_to_uname);
150 TextView savedSslCertificateIssuedByCNameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_by_cname);
151 TextView savedSslCertificateIssuedByONameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_by_oname);
152 TextView savedSslCertificateIssuedByUNameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_by_uname);
153 TextView savedSslCertificateStartDateTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_start_date);
154 TextView savedSslCertificateEndDateTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_end_date);
155 final CardView currentWebsiteCertificateCardView = domainSettingsView.findViewById(R.id.current_website_certificate_cardview);
156 LinearLayout currentWebsiteCertificateLinearLayout = domainSettingsView.findViewById(R.id.current_website_certificate_linearlayout);
157 final RadioButton currentWebsiteCertificateRadioButton = domainSettingsView.findViewById(R.id.current_website_certificate_radiobutton);
158 final TextView currentWebsiteCertificateIssuedToCNameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_to_cname);
159 TextView currentWebsiteCertificateIssuedToONameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_to_oname);
160 TextView currentWebsiteCertificateIssuedToUNameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_to_uname);
161 TextView currentWebsiteCertificateIssuedByCNameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_by_cname);
162 TextView currentWebsiteCertificateIssuedByONameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_by_oname);
163 TextView currentWebsiteCertificateIssuedByUNameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_by_uname);
164 TextView currentWebsiteCertificateStartDateTextView = domainSettingsView.findViewById(R.id.current_website_certificate_start_date);
165 TextView currentWebsiteCertificateEndDateTextView = domainSettingsView.findViewById(R.id.current_website_certificate_end_date);
166 final TextView noCurrentWebsiteCertificateTextView = domainSettingsView.findViewById(R.id.no_current_website_certificate);
168 // Setup the SSL certificate labels.
169 final String cNameLabel = getString(R.string.common_name) + " ";
170 String oNameLabel = getString(R.string.organization) + " ";
171 String uNameLabel = getString(R.string.organizational_unit) + " ";
172 String startDateLabel = getString(R.string.start_date) + " ";
173 String endDateLabel = getString(R.string.end_date) + " ";
175 // Get the current website SSL certificate
176 final SslCertificate currentWebsiteSslCertificate = MainWebViewActivity.sslCertificate;
178 // Initialize the database handler. The `0` specifies the database version, but that is ignored and set instead using a constant in `DomainsDatabaseHelper`.
179 DomainsDatabaseHelper domainsDatabaseHelper = new DomainsDatabaseHelper(context, null, null, 0);
181 // Get the database `Cursor` for this ID and move it to the first row.
182 Cursor domainCursor = domainsDatabaseHelper.getCursorForId(databaseId);
183 domainCursor.moveToFirst();
185 // Save the `Cursor` entries as variables.
186 String domainNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.DOMAIN_NAME));
187 final int javaScriptEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_JAVASCRIPT));
188 int firstPartyCookiesEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FIRST_PARTY_COOKIES));
189 int thirdPartyCookiesEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_THIRD_PARTY_COOKIES));
190 final int domStorageEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_DOM_STORAGE));
191 int formDataEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FORM_DATA)); // Form data can be remove once the minimum API >= 26.
192 int easyListEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYLIST));
193 int easyPrivacyEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYPRIVACY));
194 int fanboysAnnoyanceListInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST));
195 int fanboysSocialBlockingListInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST));
196 int ultraPrivacyEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY));
197 int blockAllThirdPartyRequestsInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS));
198 final String currentUserAgentName = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.USER_AGENT));
199 int fontSizeInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.FONT_SIZE));
200 int swipeToRefreshInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.SWIPE_TO_REFRESH));
201 int nightModeInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.NIGHT_MODE));
202 int displayImagesInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.DISPLAY_IMAGES));
203 int pinnedSslCertificateInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.PINNED_SSL_CERTIFICATE));
204 final String savedSslCertificateIssuedToCNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_COMMON_NAME));
205 String savedSslCertificateIssuedToONameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATION));
206 String savedSslCertificateIssuedToUNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATIONAL_UNIT));
207 String savedSslCertificateIssuedByCNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_COMMON_NAME));
208 String savedSslCertificateIssuedByONameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATION));
209 String savedSslCertificateIssuedByUNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATIONAL_UNIT));
211 // Initialize the saved SSL certificate date variables.
212 Date savedSslCertificateStartDate = null;
213 Date savedSslCertificateEndDate = null;
215 // Only get the saved SSL certificate dates from the cursor if they are not set to `0`.
216 if (domainCursor.getLong(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_START_DATE)) != 0) {
217 savedSslCertificateStartDate = new Date(domainCursor.getLong(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_START_DATE)));
220 if (domainCursor.getLong(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_END_DATE)) != 0) {
221 savedSslCertificateEndDate = new Date(domainCursor.getLong(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_END_DATE)));
224 // Create array adapters for the spinners.
225 ArrayAdapter<CharSequence> translatedUserAgentArrayAdapter = ArrayAdapter.createFromResource(context, R.array.translated_domain_settings_user_agent_names, R.layout.spinner_item);
226 ArrayAdapter<CharSequence> fontSizeArrayAdapter = ArrayAdapter.createFromResource(context, R.array.domain_settings_font_size_entries, R.layout.spinner_item);
227 ArrayAdapter<CharSequence> fontSizeEntryValuesArrayAdapter = ArrayAdapter.createFromResource(context, R.array.domain_settings_font_size_entry_values, R.layout.spinner_item);
228 ArrayAdapter<CharSequence> swipeToRefreshArrayAdapter = ArrayAdapter.createFromResource(context, R.array.swipe_to_refresh_array, R.layout.spinner_item);
229 ArrayAdapter<CharSequence> nightModeArrayAdapter = ArrayAdapter.createFromResource(context, R.array.night_mode_array, R.layout.spinner_item);
230 ArrayAdapter<CharSequence> displayImagesArrayAdapter = ArrayAdapter.createFromResource(context, R.array.display_webpage_images_array, R.layout.spinner_item);
232 // Set the drop down view resource on the spinners.
233 translatedUserAgentArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items);
234 fontSizeArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items);
235 swipeToRefreshArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items);
236 nightModeArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items);
237 displayImagesArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items);
239 // Set the array adapters for the spinners.
240 userAgentSpinner.setAdapter(translatedUserAgentArrayAdapter);
241 fontSizeSpinner.setAdapter(fontSizeArrayAdapter);
242 swipeToRefreshSpinner.setAdapter(swipeToRefreshArrayAdapter);
243 nightModeSpinner.setAdapter(nightModeArrayAdapter);
244 displayWebpageImagesSpinner.setAdapter(displayImagesArrayAdapter);
246 // Create a spannable string builder for each TextView that needs multiple colors of text.
247 SpannableStringBuilder savedSslCertificateIssuedToCNameStringBuilder = new SpannableStringBuilder(cNameLabel + savedSslCertificateIssuedToCNameString);
248 SpannableStringBuilder savedSslCertificateIssuedToONameStringBuilder = new SpannableStringBuilder(oNameLabel + savedSslCertificateIssuedToONameString);
249 SpannableStringBuilder savedSslCertificateIssuedToUNameStringBuilder = new SpannableStringBuilder(uNameLabel + savedSslCertificateIssuedToUNameString);
250 SpannableStringBuilder savedSslCertificateIssuedByCNameStringBuilder = new SpannableStringBuilder(cNameLabel + savedSslCertificateIssuedByCNameString);
251 SpannableStringBuilder savedSslCertificateIssuedByONameStringBuilder = new SpannableStringBuilder(oNameLabel + savedSslCertificateIssuedByONameString);
252 SpannableStringBuilder savedSslCertificateIssuedByUNameStringBuilder = new SpannableStringBuilder(uNameLabel + savedSslCertificateIssuedByUNameString);
254 // Initialize the `SpannableStringBuilders` for the SSL certificate dates.
255 SpannableStringBuilder savedSslCertificateStartDateStringBuilder;
256 SpannableStringBuilder savedSslCertificateEndDateStringBuilder;
258 // Leave the SSL certificate dates empty if they are `null`.
259 if (savedSslCertificateStartDate == null) {
260 savedSslCertificateStartDateStringBuilder = new SpannableStringBuilder(startDateLabel);
262 savedSslCertificateStartDateStringBuilder = new SpannableStringBuilder(startDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG).format(savedSslCertificateStartDate));
265 if (savedSslCertificateEndDate == null) {
266 savedSslCertificateEndDateStringBuilder = new SpannableStringBuilder(endDateLabel);
268 savedSslCertificateEndDateStringBuilder = new SpannableStringBuilder(endDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG).format(savedSslCertificateEndDate));
271 // Create a red `ForegroundColorSpan`. We have to use the deprecated `getColor` until API >= 23.
272 final ForegroundColorSpan redColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.red_a700));
274 // Create a blue `ForegroundColorSpan`.
275 final ForegroundColorSpan blueColorSpan;
277 // Set `blueColorSpan` according to the theme. We have to use the deprecated `getColor()` until API >= 23.
278 if (MainWebViewActivity.darkTheme) {
279 //noinspection deprecation
280 blueColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.blue_400));
282 //noinspection deprecation
283 blueColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.blue_700));
286 // Set the domain name from the the database cursor.
287 domainNameEditText.setText(domainNameString);
289 // Update the certificates' `Common Name` color when the domain name text changes.
290 domainNameEditText.addTextChangedListener(new TextWatcher() {
292 public void beforeTextChanged(CharSequence s, int start, int count, int after) {
297 public void onTextChanged(CharSequence s, int start, int before, int count) {
302 public void afterTextChanged(Editable s) {
303 // Get the new domain name.
304 String newDomainName = domainNameEditText.getText().toString();
306 // Check the saved SSL certificate against the new domain name.
307 boolean savedSslCertificateMatchesNewDomainName = checkDomainNameAgainstCertificate(newDomainName, savedSslCertificateIssuedToCNameString);
309 // Create a `SpannableStringBuilder` for the saved certificate `Common Name`.
310 SpannableStringBuilder savedSslCertificateCommonNameStringBuilder = new SpannableStringBuilder(cNameLabel + savedSslCertificateIssuedToCNameString);
312 // Format the saved certificate `Common Name` color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
313 if (savedSslCertificateMatchesNewDomainName) {
314 savedSslCertificateCommonNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), savedSslCertificateCommonNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
316 savedSslCertificateCommonNameStringBuilder.setSpan(redColorSpan, cNameLabel.length(), savedSslCertificateCommonNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
319 // Update `savedSslCertificateIssuedToCNameTextView`.
320 savedSslCertificateIssuedToCNameTextView.setText(savedSslCertificateCommonNameStringBuilder);
322 // Update the current website certificate if it exists.
323 if (currentWebsiteSslCertificate != null) {
324 // Get the current website certificate `Common Name`.
325 String currentWebsiteCertificateCommonName = currentWebsiteSslCertificate.getIssuedTo().getCName();
327 // Check the current website certificate against the new domain name.
328 boolean currentWebsiteCertificateMatchesNewDomainName = checkDomainNameAgainstCertificate(newDomainName, currentWebsiteCertificateCommonName);
330 // Create a `SpannableStringBuilder` for the current website certificate `Common Name`.
331 SpannableStringBuilder currentWebsiteCertificateCommonNameStringBuilder = new SpannableStringBuilder(cNameLabel + currentWebsiteCertificateCommonName);
333 // Format the current certificate `Common Name` color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
334 if (currentWebsiteCertificateMatchesNewDomainName) {
335 currentWebsiteCertificateCommonNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), currentWebsiteCertificateCommonNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
337 currentWebsiteCertificateCommonNameStringBuilder.setSpan(redColorSpan, cNameLabel.length(), currentWebsiteCertificateCommonNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
340 // Update `currentWebsiteCertificateIssuedToCNameTextView`.
341 currentWebsiteCertificateIssuedToCNameTextView.setText(currentWebsiteCertificateCommonNameStringBuilder);
346 // Create a `boolean` to track if night mode is enabled.
347 boolean nightModeEnabled = (nightModeInt == DomainsDatabaseHelper.NIGHT_MODE_ENABLED) || ((nightModeInt == DomainsDatabaseHelper.NIGHT_MODE_SYSTEM_DEFAULT) && defaultNightMode);
349 // Disable the JavaScript switch if night mode is enabled.
350 if (nightModeEnabled) {
351 javaScriptEnabledSwitch.setEnabled(false);
353 javaScriptEnabledSwitch.setEnabled(true);
356 // Set the JavaScript icon.
357 if ((javaScriptEnabledInt == 1) || nightModeEnabled) {
358 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.javascript_enabled));
360 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.privacy_mode));
363 // Set the JavaScript switch status.
364 if (javaScriptEnabledInt == 1) { // JavaScript is enabled.
365 javaScriptEnabledSwitch.setChecked(true);
366 } else { // JavaScript is disabled.
367 javaScriptEnabledSwitch.setChecked(false);
370 // Set the first-party cookies status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
371 if (firstPartyCookiesEnabledInt == 1) { // First-party cookies are enabled.
372 firstPartyCookiesEnabledSwitch.setChecked(true);
373 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_enabled));
374 } else { // First-party cookies are disabled.
375 firstPartyCookiesEnabledSwitch.setChecked(false);
377 // Set the icon according to the theme.
378 if (MainWebViewActivity.darkTheme) {
379 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_dark));
381 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_light));
385 // Only display third-party cookies if SDK_INT >= 21.
386 if (Build.VERSION.SDK_INT >= 21) { // Third-party cookies can be configured for API >= 21.
387 // Only enable third-party-cookies if first-party cookies are enabled.
388 if (firstPartyCookiesEnabledInt == 1) { // First-party cookies are enabled.
389 // Set the third-party cookies status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
390 if (thirdPartyCookiesEnabledInt == 1) { // Both first-party and third-party cookies are enabled.
391 thirdPartyCookiesEnabledSwitch.setChecked(true);
392 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_warning));
393 } else { // First party cookies are enabled but third-party cookies are disabled.
394 thirdPartyCookiesEnabledSwitch.setChecked(false);
396 // Set the icon according to the theme.
397 if (MainWebViewActivity.darkTheme) {
398 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_dark));
400 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_light));
403 } else { // First-party cookies are disabled.
404 // Set the status of third-party cookies.
405 if (thirdPartyCookiesEnabledInt == 1) {
406 thirdPartyCookiesEnabledSwitch.setChecked(true);
408 thirdPartyCookiesEnabledSwitch.setChecked(false);
411 // Disable the third-party cookies switch.
412 thirdPartyCookiesEnabledSwitch.setEnabled(false);
414 // Set the icon according to the theme.
415 if (MainWebViewActivity.darkTheme) {
416 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_ghosted_dark));
418 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_ghosted_light));
421 } else { // Third-party cookies cannot be configured for API <= 21.
422 // Hide the LinearLayout for third-party cookies.
423 thirdPartyCookiesLinearLayout.setVisibility(View.GONE);
426 // Only enable DOM storage if JavaScript is enabled.
427 if ((javaScriptEnabledInt == 1) || nightModeEnabled) { // JavaScript is enabled.
428 // Enable the DOM storage `Switch`.
429 domStorageEnabledSwitch.setEnabled(true);
431 // Set the DOM storage status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
432 if (domStorageEnabledInt == 1) { // Both JavaScript and DOM storage are enabled.
433 domStorageEnabledSwitch.setChecked(true);
434 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_enabled));
435 } else { // JavaScript is enabled but DOM storage is disabled.
436 // Set the DOM storage switch to off.
437 domStorageEnabledSwitch.setChecked(false);
439 // Set the icon according to the theme.
440 if (MainWebViewActivity.darkTheme) {
441 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_dark));
443 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_light));
446 } else { // JavaScript is disabled.
447 // Disable the DOM storage `Switch`.
448 domStorageEnabledSwitch.setEnabled(false);
450 // Set the checked status of DOM storage.
451 if (domStorageEnabledInt == 1) { // DOM storage is enabled but JavaScript is disabled.
452 domStorageEnabledSwitch.setChecked(true);
453 } else { // Both JavaScript and DOM storage are disabled.
454 domStorageEnabledSwitch.setChecked(false);
457 // Set the icon according to the theme.
458 if (MainWebViewActivity.darkTheme) {
459 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_dark));
461 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_light));
465 // 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.
466 if (Build.VERSION.SDK_INT >= 26) { // Form data no longer applies to newer versions of Android.
467 // Hide the form data switch.
468 formDataEnabledSwitch.setVisibility(View.GONE);
469 } else { // Form data should be displayed because this is an older version of Android.
470 if (formDataEnabledInt == 1) { // Form data is on.
471 formDataEnabledSwitch.setChecked(true);
472 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_enabled));
473 } else { // Form data is off.
474 // Turn the form data switch to off.
475 formDataEnabledSwitch.setChecked(false);
477 // Set the icon according to the theme.
478 if (MainWebViewActivity.darkTheme) {
479 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_disabled_dark));
481 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_disabled_light));
486 // Set the EasyList status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
487 if (easyListEnabledInt == 1) { // EasyList is on.
488 // Turn the switch on.
489 easyListSwitch.setChecked(true);
491 // Set the icon according to the theme.
492 if (MainWebViewActivity.darkTheme) {
493 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_dark));
495 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_light));
497 } else { // EasyList is off.
498 // Turn the switch off.
499 easyListSwitch.setChecked(false);
501 // Set the icon according to the theme.
502 if (MainWebViewActivity.darkTheme) {
503 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_dark));
505 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_light));
509 // Set the EasyPrivacy status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
510 if (easyPrivacyEnabledInt == 1) { // EasyPrivacy is on.
511 // Turn the switch on.
512 easyPrivacySwitch.setChecked(true);
514 // Set the icon according to the theme.
515 if (MainWebViewActivity.darkTheme) {
516 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_dark));
518 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_light));
520 } else { // EasyPrivacy is off.
521 // Turn the switch off.
522 easyPrivacySwitch.setChecked(false);
524 // Set the icon according to the theme.
525 if (MainWebViewActivity.darkTheme) {
526 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_dark));
528 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_light));
532 // Set the Fanboy's Annoyance List status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
533 if (fanboysAnnoyanceListInt == 1) { // Fanboy's Annoyance List is on.
534 // Turn the switch on.
535 fanboysAnnoyanceListSwitch.setChecked(true);
537 // Set the icon according to the theme.
538 if (MainWebViewActivity.darkTheme) {
539 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_dark));
541 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_light));
543 } else { // Fanboy's Annoyance List is off.
544 // Turn the switch off.
545 fanboysAnnoyanceListSwitch.setChecked(false);
547 // Set the icon according to the theme.
548 if (MainWebViewActivity.darkTheme) {
549 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_dark));
551 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_light));
555 // Only enable Fanboy's Social Blocking List if Fanboy's Annoyance List is off.
556 if (fanboysAnnoyanceListInt == 0) { // Fanboy's Annoyance List is on.
557 // Enable Fanboy's Social Blocking List. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
558 if (fanboysSocialBlockingListInt == 1) { // Fanboy's Social Blocking List is on.
559 // Enable the switch and turn it on.
560 fanboysSocialBlockingListSwitch.setEnabled(true);
561 fanboysSocialBlockingListSwitch.setChecked(true);
563 // Set the icon according to the theme.
564 if (MainWebViewActivity.darkTheme) {
565 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_dark));
567 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_light));
569 } else { // Fanboy's Social Blocking List is off.
570 // Enable the switch but turn it off.
571 fanboysSocialBlockingListSwitch.setEnabled(true);
572 fanboysSocialBlockingListSwitch.setChecked(false);
574 // Set the icon according to the theme.
575 if (MainWebViewActivity.darkTheme) {
576 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_dark));
578 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_light));
581 } else { // Fanboy's Annoyance List is on.
582 // Disable Fanboy's Social Blocking List. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
583 if (fanboysSocialBlockingListInt == 1) { // Fanboy's Social Blocking List is on.
584 // Disable the switch but turn it on.
585 fanboysSocialBlockingListSwitch.setEnabled(false);
586 fanboysSocialBlockingListSwitch.setChecked(true);
587 } else { // Fanboy's Social Blocking List is off.
588 // Disable the switch and turn it off.
589 fanboysSocialBlockingListSwitch.setEnabled(false);
590 fanboysSocialBlockingListSwitch.setChecked(false);
593 // Set the icon according to the theme.
594 if (MainWebViewActivity.darkTheme) {
595 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_ghosted_dark));
597 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_ghosted_light));
601 // Set the UltraPrivacy status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
602 if (ultraPrivacyEnabledInt == 1) { // UltraPrivacy is on.
603 // Turn the switch on.
604 ultraPrivacySwitch.setChecked(true);
606 // Set the icon according to the theme.
607 if (MainWebViewActivity.darkTheme) {
608 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_dark));
610 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_light));
612 } else { // EasyPrivacy is off.
613 // Turn the switch off.
614 ultraPrivacySwitch.setChecked(false);
616 // Set the icon according to the theme.
617 if (MainWebViewActivity.darkTheme) {
618 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_dark));
620 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_light));
624 // 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.
625 if (blockAllThirdPartyRequestsInt == 1) { // Blocking all third-party requests is on.
626 // Turn the switch on.
627 blockAllThirdPartyRequestsSwitch.setChecked(true);
629 // Set the icon according to the theme.
630 if (MainWebViewActivity.darkTheme) {
631 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_enabled_dark));
633 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_enabled_light));
635 } else { // Blocking all third-party requests is off.
636 // Turn the switch off.
637 blockAllThirdPartyRequestsSwitch.setChecked(false);
639 // Set the icon according to the theme.
640 if (MainWebViewActivity.darkTheme) {
641 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_disabled_dark));
643 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_disabled_light));
647 // Inflated a WebView to get the default user agent.
648 // `@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.
649 @SuppressLint("InflateParams") View bareWebViewLayout = inflater.inflate(R.layout.bare_webview, null, false);
650 WebView bareWebView = bareWebViewLayout.findViewById(R.id.bare_webview);
651 final String webViewDefaultUserAgentString = bareWebView.getSettings().getUserAgentString();
653 // Get a handle for the user agent array adapter. This array does not contain the `System default` entry.
654 ArrayAdapter<CharSequence> userAgentNamesArray = ArrayAdapter.createFromResource(context, R.array.user_agent_names, R.layout.spinner_item);
656 // Get the positions of the user agent and the default user agent.
657 int userAgentArrayPosition = userAgentNamesArray.getPosition(currentUserAgentName);
658 int defaultUserAgentArrayPosition = userAgentNamesArray.getPosition(defaultUserAgentName);
660 // Get a handle for the user agent data array. This array does not contain the `System default` entry.
661 String[] userAgentDataArray = resources.getStringArray(R.array.user_agent_data);
663 // Set the user agent text.
664 if (currentUserAgentName.equals(getString(R.string.system_default_user_agent))) { // Use the system default user agent.
665 // Set the user agent according to the system default.
666 switch (defaultUserAgentArrayPosition) {
667 case MainWebViewActivity.UNRECOGNIZED_USER_AGENT: // The default user agent name is not on the canonical list.
668 // This is probably because it was set in an older version of Privacy Browser before the switch to persistent user agent names.
669 userAgentTextView.setText(defaultUserAgentName);
672 case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
673 // Display the `WebView` default user agent.
674 userAgentTextView.setText(webViewDefaultUserAgentString);
677 case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
678 // Display the custom user agent.
679 userAgentTextView.setText(defaultCustomUserAgentString);
683 // Get the user agent string from the user agent data array.
684 userAgentTextView.setText(userAgentDataArray[defaultUserAgentArrayPosition]);
686 } else if (userAgentArrayPosition == MainWebViewActivity.UNRECOGNIZED_USER_AGENT) { // A custom user agent is stored in the current user agent name.
687 // Set the user agent spinner to `Custom user agent`.
688 userAgentSpinner.setSelection(MainWebViewActivity.DOMAINS_CUSTOM_USER_AGENT);
690 // Hide the user agent TextView.
691 userAgentTextView.setVisibility(View.GONE);
693 // Show the custom user agent EditText and set the current user agent name as the text.
694 customUserAgentEditText.setVisibility(View.VISIBLE);
695 customUserAgentEditText.setText(currentUserAgentName);
696 } else { // The user agent name contains one of the canonical user agents.
697 // Set the user agent spinner selection. The spinner has one more entry at the beginning than the user agent data array, so the position must be incremented.
698 userAgentSpinner.setSelection(userAgentArrayPosition + 1);
700 // Show the user agent TextView.
701 userAgentTextView.setVisibility(View.VISIBLE);
703 // Hide the custom user agent EditText.
704 customUserAgentEditText.setVisibility(View.GONE);
706 // Set the user agent text.
707 switch (userAgentArrayPosition) {
708 case MainWebViewActivity.DOMAINS_WEBVIEW_DEFAULT_USER_AGENT:
709 // Display the WebView default user agent.
710 userAgentTextView.setText(webViewDefaultUserAgentString);
714 // Get the user agent string from the user agent data array. The spinner has one more entry at the beginning than the user agent data array, so the position must be incremented.
715 userAgentTextView.setText(userAgentDataArray[userAgentArrayPosition + 1]);
719 // Open the user agent spinner when the TextView is clicked.
720 userAgentTextView.setOnClickListener((View v) -> {
721 // Open the user agent spinner.
722 userAgentSpinner.performClick();
725 // Set the selected font size.
726 int fontSizeArrayPosition = fontSizeEntryValuesArrayAdapter.getPosition(String.valueOf(fontSizeInt));
727 fontSizeSpinner.setSelection(fontSizeArrayPosition);
729 // Set the default font size text.
730 int defaultFontSizeArrayPosition = fontSizeEntryValuesArrayAdapter.getPosition(defaultFontSizeString);
731 fontSizeTextView.setText(fontSizeArrayAdapter.getItem(defaultFontSizeArrayPosition));
733 // Set the display options for the font size TextView.
734 if (fontSizeArrayPosition == 0) { // System default font size is selected. Display `fontSizeTextView`.
735 fontSizeTextView.setVisibility(View.VISIBLE);
736 } else { // A custom font size is specified. Hide `fontSizeTextView`.
737 fontSizeTextView.setVisibility(View.GONE);
740 // Open the font size spinner when the TextView is clicked.
741 fontSizeTextView.setOnClickListener((View v) -> {
742 // Open the user agent spinner.
743 fontSizeSpinner.performClick();
746 // Display the swipe to refresh selection in the spinner.
747 swipeToRefreshSpinner.setSelection(swipeToRefreshInt);
749 // Set the swipe to refresh text.
750 if (defaultSwipeToRefresh) {
751 swipeToRefreshTextView.setText(swipeToRefreshArrayAdapter.getItem(DomainsDatabaseHelper.SWIPE_TO_REFRESH_ENABLED));
753 swipeToRefreshTextView.setText(swipeToRefreshArrayAdapter.getItem(DomainsDatabaseHelper.SWIPE_TO_REFRESH_DISABLED));
756 // 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.
757 switch (swipeToRefreshInt) {
758 case DomainsDatabaseHelper.SWIPE_TO_REFRESH_SYSTEM_DEFAULT:
759 if (defaultSwipeToRefresh) { // Swipe to refresh is enabled by default.
760 // Set the icon according to the theme.
761 if (MainWebViewActivity.darkTheme) {
762 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_dark));
764 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_light));
766 } else { // Swipe to refresh is disabled by default
767 // Set the icon according to the theme.
768 if (MainWebViewActivity.darkTheme) {
769 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_dark));
771 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_light));
775 // Show the swipe to refresh TextView.
776 swipeToRefreshTextView.setVisibility(View.VISIBLE);
779 case DomainsDatabaseHelper.SWIPE_TO_REFRESH_ENABLED:
780 // Set the icon according to the theme.
781 if (MainWebViewActivity.darkTheme) {
782 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_dark));
784 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_light));
787 // Hide the swipe to refresh TextView.`
788 swipeToRefreshTextView.setVisibility(View.GONE);
791 case DomainsDatabaseHelper.SWIPE_TO_REFRESH_DISABLED:
792 // Set the icon according to the theme.
793 if (MainWebViewActivity.darkTheme) {
794 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_dark));
796 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_light));
799 // Hide the swipe to refresh TextView.
800 swipeToRefreshTextView.setVisibility(View.GONE);
803 // Open the swipe to refresh spinner when the TextView is clicked.
804 swipeToRefreshTextView.setOnClickListener((View v) -> {
805 // Open the swipe to refresh spinner.
806 swipeToRefreshSpinner.performClick();
809 // Display the night mode in the spinner.
810 nightModeSpinner.setSelection(nightModeInt);
812 // Set the default night mode text.
813 if (defaultNightMode) {
814 nightModeTextView.setText(nightModeArrayAdapter.getItem(DomainsDatabaseHelper.NIGHT_MODE_ENABLED));
816 nightModeTextView.setText(nightModeArrayAdapter.getItem(DomainsDatabaseHelper.NIGHT_MODE_DISABLED));
819 // 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.
820 switch (nightModeInt) {
821 case DomainsDatabaseHelper.NIGHT_MODE_SYSTEM_DEFAULT:
822 if (defaultNightMode) { // Night mode enabled by default.
823 // Set the icon according to the theme.
824 if (MainWebViewActivity.darkTheme) {
825 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_dark));
827 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_light));
829 } else { // Night mode disabled by default.
830 // Set the icon according to the theme.
831 if (MainWebViewActivity.darkTheme) {
832 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_dark));
834 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_light));
838 // Show night mode TextView.
839 nightModeTextView.setVisibility(View.VISIBLE);
842 case DomainsDatabaseHelper.NIGHT_MODE_ENABLED:
843 // Set the icon according to the theme.
844 if (MainWebViewActivity.darkTheme) {
845 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_dark));
847 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_light));
850 // Hide the night mode TextView.
851 nightModeTextView.setVisibility(View.GONE);
854 case DomainsDatabaseHelper.NIGHT_MODE_DISABLED:
855 // Set the icon according to the theme.
856 if (MainWebViewActivity.darkTheme) {
857 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_dark));
859 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_light));
862 // Hide the night mode TextView.
863 nightModeTextView.setVisibility(View.GONE);
867 // Open the night mode spinner when the TextView is clicked.
868 nightModeTextView.setOnClickListener((View v) -> {
869 // Open the night mode spinner.
870 nightModeSpinner.performClick();
873 // Display the website images mode in the spinner.
874 displayWebpageImagesSpinner.setSelection(displayImagesInt);
876 // Set the default display images text.
877 if (defaultDisplayWebpageImages) {
878 displayImagesTextView.setText(displayImagesArrayAdapter.getItem(DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_ENABLED));
880 displayImagesTextView.setText(displayImagesArrayAdapter.getItem(DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_DISABLED));
883 // 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.
884 switch (displayImagesInt) {
885 case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_SYSTEM_DEFAULT:
886 if (defaultDisplayWebpageImages) { // Display webpage images enabled by default.
887 // Set the icon according to the theme.
888 if (MainWebViewActivity.darkTheme) {
889 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_dark));
891 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_light));
893 } else { // Display webpage images disabled by default.
894 // Set the icon according to the theme.
895 if (MainWebViewActivity.darkTheme) {
896 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_dark));
898 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_light));
902 // Show the display images TextView.
903 displayImagesTextView.setVisibility(View.VISIBLE);
906 case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_ENABLED:
907 // Set the icon according to the theme.
908 if (MainWebViewActivity.darkTheme) {
909 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_dark));
911 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_light));
914 // Hide the display images TextView.
915 displayImagesTextView.setVisibility(View.GONE);
918 case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_DISABLED:
919 // Set the icon according to the theme.
920 if (MainWebViewActivity.darkTheme) {
921 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_dark));
923 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_light));
926 // Hide the display images TextView.
927 displayImagesTextView.setVisibility(View.GONE);
931 // Open the display images spinner when the TextView is clicked.
932 displayImagesTextView.setOnClickListener((View v) -> {
933 // Open the user agent spinner.
934 displayWebpageImagesSpinner.performClick();
937 // Set the pinned SSL certificate icon.
938 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.
940 pinnedSslCertificateSwitch.setChecked(true);
942 // Set the icon according to the theme.
943 if (MainWebViewActivity.darkTheme) {
944 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_dark));
946 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_light));
948 } else { // Pinned SSL certificate is disabled.
949 // Uncheck the switch.
950 pinnedSslCertificateSwitch.setChecked(false);
952 // Set the icon according to the theme.
953 if (MainWebViewActivity.darkTheme) {
954 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_dark));
956 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_light));
960 // Store the current date.
961 Date currentDate = Calendar.getInstance().getTime();
963 // Setup the `StringBuilders` to display the general certificate information in blue. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
964 savedSslCertificateIssuedToONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), savedSslCertificateIssuedToONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
965 savedSslCertificateIssuedToUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), savedSslCertificateIssuedToUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
966 savedSslCertificateIssuedByCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), savedSslCertificateIssuedByCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
967 savedSslCertificateIssuedByONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), savedSslCertificateIssuedByONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
968 savedSslCertificateIssuedByUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), savedSslCertificateIssuedByUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
970 // Check the certificate `Common Name` against the domain name.
971 boolean savedSSlCertificateCommonNameMatchesDomainName = checkDomainNameAgainstCertificate(domainNameString, savedSslCertificateIssuedToCNameString);
973 // Format the `issuedToCommonName` color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
974 if (savedSSlCertificateCommonNameMatchesDomainName) {
975 savedSslCertificateIssuedToCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), savedSslCertificateIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
977 savedSslCertificateIssuedToCNameStringBuilder.setSpan(redColorSpan, cNameLabel.length(), savedSslCertificateIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
980 // Format the start date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
981 if ((savedSslCertificateStartDate != null) && savedSslCertificateStartDate.after(currentDate)) { // The certificate start date is in the future.
982 savedSslCertificateStartDateStringBuilder.setSpan(redColorSpan, startDateLabel.length(), savedSslCertificateStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
983 } else { // The certificate start date is in the past.
984 savedSslCertificateStartDateStringBuilder.setSpan(blueColorSpan, startDateLabel.length(), savedSslCertificateStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
987 // Format the end date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
988 if ((savedSslCertificateEndDate != null) && savedSslCertificateEndDate.before(currentDate)) { // The certificate end date is in the past.
989 savedSslCertificateEndDateStringBuilder.setSpan(redColorSpan, endDateLabel.length(), savedSslCertificateEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
990 } else { // The certificate end date is in the future.
991 savedSslCertificateEndDateStringBuilder.setSpan(blueColorSpan, endDateLabel.length(), savedSslCertificateEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
994 // Display the current website SSL certificate strings.
995 savedSslCertificateIssuedToCNameTextView.setText(savedSslCertificateIssuedToCNameStringBuilder);
996 savedSslCertificateIssuedToONameTextView.setText(savedSslCertificateIssuedToONameStringBuilder);
997 savedSslCertificateIssuedToUNameTextView.setText(savedSslCertificateIssuedToUNameStringBuilder);
998 savedSslCertificateIssuedByCNameTextView.setText(savedSslCertificateIssuedByCNameStringBuilder);
999 savedSslCertificateIssuedByONameTextView.setText(savedSslCertificateIssuedByONameStringBuilder);
1000 savedSslCertificateIssuedByUNameTextView.setText(savedSslCertificateIssuedByUNameStringBuilder);
1001 savedSslCertificateStartDateTextView.setText(savedSslCertificateStartDateStringBuilder);
1002 savedSslCertificateEndDateTextView.setText(savedSslCertificateEndDateStringBuilder);
1004 // Populate the current website SSL certificate if there is one.
1005 if (currentWebsiteSslCertificate != null) {
1006 // Get the strings from the SSL certificate.
1007 String currentWebsiteCertificateIssuedToCNameString = currentWebsiteSslCertificate.getIssuedTo().getCName();
1008 String currentWebsiteCertificateIssuedToONameString = currentWebsiteSslCertificate.getIssuedTo().getOName();
1009 String currentWebsiteCertificateIssuedToUNameString = currentWebsiteSslCertificate.getIssuedTo().getUName();
1010 String currentWebsiteCertificateIssuedByCNameString = currentWebsiteSslCertificate.getIssuedBy().getCName();
1011 String currentWebsiteCertificateIssuedByONameString = currentWebsiteSslCertificate.getIssuedBy().getOName();
1012 String currentWebsiteCertificateIssuedByUNameString = currentWebsiteSslCertificate.getIssuedBy().getUName();
1013 Date currentWebsiteCertificateStartDate = currentWebsiteSslCertificate.getValidNotBeforeDate();
1014 Date currentWebsiteCertificateEndDate = currentWebsiteSslCertificate.getValidNotAfterDate();
1016 // Create a `SpannableStringBuilder` for each `TextView` that needs multiple colors of text.
1017 SpannableStringBuilder currentWebsiteCertificateIssuedToCNameStringBuilder = new SpannableStringBuilder(cNameLabel + currentWebsiteCertificateIssuedToCNameString);
1018 SpannableStringBuilder currentWebsiteCertificateIssuedToONameStringBuilder = new SpannableStringBuilder(oNameLabel + currentWebsiteCertificateIssuedToONameString);
1019 SpannableStringBuilder currentWebsiteCertificateIssuedToUNameStringBuilder = new SpannableStringBuilder(uNameLabel + currentWebsiteCertificateIssuedToUNameString);
1020 SpannableStringBuilder currentWebsiteCertificateIssuedByCNameStringBuilder = new SpannableStringBuilder(cNameLabel + currentWebsiteCertificateIssuedByCNameString);
1021 SpannableStringBuilder currentWebsiteCertificateIssuedByONameStringBuilder = new SpannableStringBuilder(oNameLabel + currentWebsiteCertificateIssuedByONameString);
1022 SpannableStringBuilder currentWebsiteCertificateIssuedByUNameStringBuilder = new SpannableStringBuilder(uNameLabel + currentWebsiteCertificateIssuedByUNameString);
1023 SpannableStringBuilder currentWebsiteCertificateStartDateStringBuilder = new SpannableStringBuilder(startDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG)
1024 .format(currentWebsiteCertificateStartDate));
1025 SpannableStringBuilder currentWebsiteCertificateEndDateStringBuilder = new SpannableStringBuilder(endDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG)
1026 .format(currentWebsiteCertificateEndDate));
1028 // Setup the `StringBuilders` to display the general certificate information in blue. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1029 currentWebsiteCertificateIssuedToONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), currentWebsiteCertificateIssuedToONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1030 currentWebsiteCertificateIssuedToUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), currentWebsiteCertificateIssuedToUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1031 currentWebsiteCertificateIssuedByCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), currentWebsiteCertificateIssuedByCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1032 currentWebsiteCertificateIssuedByONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), currentWebsiteCertificateIssuedByONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1033 currentWebsiteCertificateIssuedByUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), currentWebsiteCertificateIssuedByUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1035 // Check the certificate `Common Name` against the domain name.
1036 boolean currentWebsiteCertificateCommonNameMatchesDomainName = checkDomainNameAgainstCertificate(domainNameString, currentWebsiteCertificateIssuedToCNameString);
1038 // Format the `issuedToCommonName` color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1039 if (currentWebsiteCertificateCommonNameMatchesDomainName) {
1040 currentWebsiteCertificateIssuedToCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), currentWebsiteCertificateIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1042 currentWebsiteCertificateIssuedToCNameStringBuilder.setSpan(redColorSpan, cNameLabel.length(), currentWebsiteCertificateIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1045 // Format the start date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1046 if (currentWebsiteCertificateStartDate.after(currentDate)) { // The certificate start date is in the future.
1047 currentWebsiteCertificateStartDateStringBuilder.setSpan(redColorSpan, startDateLabel.length(), currentWebsiteCertificateStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1048 } else { // The certificate start date is in the past.
1049 currentWebsiteCertificateStartDateStringBuilder.setSpan(blueColorSpan, startDateLabel.length(), currentWebsiteCertificateStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1052 // Format the end date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1053 if (currentWebsiteCertificateEndDate.before(currentDate)) { // The certificate end date is in the past.
1054 currentWebsiteCertificateEndDateStringBuilder.setSpan(redColorSpan, endDateLabel.length(), currentWebsiteCertificateEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1055 } else { // The certificate end date is in the future.
1056 currentWebsiteCertificateEndDateStringBuilder.setSpan(blueColorSpan, endDateLabel.length(), currentWebsiteCertificateEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1059 // Display the current website SSL certificate strings.
1060 currentWebsiteCertificateIssuedToCNameTextView.setText(currentWebsiteCertificateIssuedToCNameStringBuilder);
1061 currentWebsiteCertificateIssuedToONameTextView.setText(currentWebsiteCertificateIssuedToONameStringBuilder);
1062 currentWebsiteCertificateIssuedToUNameTextView.setText(currentWebsiteCertificateIssuedToUNameStringBuilder);
1063 currentWebsiteCertificateIssuedByCNameTextView.setText(currentWebsiteCertificateIssuedByCNameStringBuilder);
1064 currentWebsiteCertificateIssuedByONameTextView.setText(currentWebsiteCertificateIssuedByONameStringBuilder);
1065 currentWebsiteCertificateIssuedByUNameTextView.setText(currentWebsiteCertificateIssuedByUNameStringBuilder);
1066 currentWebsiteCertificateStartDateTextView.setText(currentWebsiteCertificateStartDateStringBuilder);
1067 currentWebsiteCertificateEndDateTextView.setText(currentWebsiteCertificateEndDateStringBuilder);
1070 // Set the initial display status for the SSL certificates.
1071 if (pinnedSslCertificateSwitch.isChecked()) {
1072 // Set the visibility of the saved SSL certificate.
1073 if (savedSslCertificateIssuedToCNameString == null) {
1074 savedSslCertificateCardView.setVisibility(View.GONE);
1076 savedSslCertificateCardView.setVisibility(View.VISIBLE);
1079 // Set the visibility of the current website SSL certificate.
1080 if (currentWebsiteSslCertificate == null) {
1081 // Hide the SSL certificate.
1082 currentWebsiteCertificateCardView.setVisibility(View.GONE);
1084 // Show the instruction.
1085 noCurrentWebsiteCertificateTextView.setVisibility(View.VISIBLE);
1087 // Show the SSL certificate.
1088 currentWebsiteCertificateCardView.setVisibility(View.VISIBLE);
1090 // Hide the instruction.
1091 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
1094 // Set the status of the radio buttons.
1095 if (savedSslCertificateCardView.getVisibility() == View.VISIBLE) { // The saved SSL certificate is displayed.
1096 // Check the saved SSL certificate radio button.
1097 savedSslCertificateRadioButton.setChecked(true);
1099 // Uncheck the current website SSL certificate radio button.
1100 currentWebsiteCertificateRadioButton.setChecked(false);
1102 // Darken the background of the current website SSL certificate linear layout according to the theme.
1103 if (MainWebViewActivity.darkTheme) {
1104 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
1106 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
1108 } else if (currentWebsiteCertificateCardView.getVisibility() == View.VISIBLE) { // The saved SSL certificate is hidden but the current website SSL certificate is visible.
1109 // Check the current website SSL certificate radio button.
1110 currentWebsiteCertificateRadioButton.setChecked(true);
1112 // Uncheck the saved SSL certificate radio button.
1113 savedSslCertificateRadioButton.setChecked(false);
1115 // Darken the background of the saved SSL certificate linear layout according to the theme.
1116 if (MainWebViewActivity.darkTheme) {
1117 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
1119 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
1121 } else { // Neither SSL certificate is visible.
1122 // Uncheck both radio buttons.
1123 savedSslCertificateRadioButton.setChecked(false);
1124 currentWebsiteCertificateRadioButton.setChecked(false);
1126 } else { // `pinnedSslCertificateSwitch` is not checked.
1127 // Hide the SSl certificates and instructions.
1128 savedSslCertificateCardView.setVisibility(View.GONE);
1129 currentWebsiteCertificateCardView.setVisibility(View.GONE);
1130 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
1132 // Uncheck the radio buttons.
1133 savedSslCertificateRadioButton.setChecked(false);
1134 currentWebsiteCertificateRadioButton.setChecked(false);
1138 // Set the JavaScript switch listener.
1139 javaScriptEnabledSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1140 if (isChecked) { // JavaScript is enabled.
1141 // Update the JavaScript icon.
1142 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.javascript_enabled));
1144 // Enable the DOM storage `Switch`.
1145 domStorageEnabledSwitch.setEnabled(true);
1147 // Update the DOM storage icon.
1148 if (domStorageEnabledSwitch.isChecked()) { // DOM storage is enabled.
1149 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_enabled));
1150 } else { // DOM storage is disabled.
1151 // Set the icon according to the theme.
1152 if (MainWebViewActivity.darkTheme) {
1153 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_dark));
1155 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_light));
1158 } else { // JavaScript is disabled.
1159 // Update the JavaScript icon.
1160 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.privacy_mode));
1162 // Disable the DOM storage `Switch`.
1163 domStorageEnabledSwitch.setEnabled(false);
1165 // Set the DOM storage icon according to the theme.
1166 if (MainWebViewActivity.darkTheme) {
1167 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_dark));
1169 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_light));
1174 // Set the first-party cookies switch listener.
1175 firstPartyCookiesEnabledSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1176 if (isChecked) { // First-party cookies are enabled.
1177 // Update the first-party cookies icon.
1178 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_enabled));
1180 // Enable the third-party cookies switch.
1181 thirdPartyCookiesEnabledSwitch.setEnabled(true);
1183 // Update the third-party cookies icon.
1184 if (thirdPartyCookiesEnabledSwitch.isChecked()) { // Third-party cookies are enabled.
1185 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_warning));
1186 } else { // Third-party cookies are disabled.
1187 // Set the third-party cookies icon according to the theme.
1188 if (MainWebViewActivity.darkTheme) {
1189 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_dark));
1191 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_light));
1194 } else { // First-party cookies are disabled.
1195 // Update the first-party cookies icon according to the theme.
1196 if (MainWebViewActivity.darkTheme) {
1197 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_dark));
1199 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_light));
1202 // Disable the third-party cookies switch.
1203 thirdPartyCookiesEnabledSwitch.setEnabled(false);
1205 // Set the third-party cookies icon according to the theme.
1206 if (MainWebViewActivity.darkTheme) {
1207 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_ghosted_dark));
1209 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_ghosted_light));
1214 // Set the third-party cookies switch listener.
1215 thirdPartyCookiesEnabledSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1218 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_warning));
1220 // Update the third-party cookies icon according to the theme.
1221 if (MainWebViewActivity.darkTheme) {
1222 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_dark));
1224 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_light));
1229 // Set the DOM Storage switch listener.
1230 domStorageEnabledSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1233 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_enabled));
1235 // Set the icon according to the theme.
1236 if (MainWebViewActivity.darkTheme) {
1237 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_dark));
1239 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_light));
1244 // Set the form data switch listener. It can be removed once the minimum API >= 26.
1245 if (Build.VERSION.SDK_INT < 26) {
1246 formDataEnabledSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1249 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_enabled));
1251 // Set the icon according to the theme.
1252 if (MainWebViewActivity.darkTheme) {
1253 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_disabled_dark));
1255 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_disabled_light));
1261 // Set the EasyList switch listener.
1262 easyListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1264 if (isChecked) { // EasyList is on.
1265 // Set the icon according to the theme.
1266 if (MainWebViewActivity.darkTheme) {
1267 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_dark));
1269 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_light));
1271 } else { // EasyList is off.
1272 // Set the icon according to the theme.
1273 if (MainWebViewActivity.darkTheme) {
1274 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_dark));
1276 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_light));
1281 // Set the EasyPrivacy switch listener.
1282 easyPrivacySwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1284 if (isChecked) { // EasyPrivacy is on.
1285 // Set the icon according to the theme.
1286 if (MainWebViewActivity.darkTheme) {
1287 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_dark));
1289 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_light));
1291 } else { // EasyPrivacy is off.
1292 // Set the icon according to the theme.
1293 if (MainWebViewActivity.darkTheme) {
1294 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_dark));
1296 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_light));
1301 // Set the Fanboy's Annoyance List switch listener.
1302 fanboysAnnoyanceListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1303 // Update the icon and Fanboy's Social Blocking List.
1304 if (isChecked) { // Fanboy's Annoyance List is on.
1305 // Set the icon according to the theme.
1306 if (MainWebViewActivity.darkTheme) {
1307 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_dark));
1309 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_light));
1312 // Disable the Fanboy's Social Blocking List switch.
1313 fanboysSocialBlockingListSwitch.setEnabled(false);
1315 // Update the Fanboy's Social Blocking List icon according to the theme.
1316 if (MainWebViewActivity.darkTheme) {
1317 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_ghosted_dark));
1319 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_ghosted_light));
1321 } else { // Fanboy's Annoyance List is off.
1322 // Set the icon according to the theme.
1323 if (MainWebViewActivity.darkTheme) {
1324 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_dark));
1326 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_light));
1329 // Enable the Fanboy's Social Blocking List switch.
1330 fanboysSocialBlockingListSwitch.setEnabled(true);
1332 // Update the Fanboy's Social Blocking List icon.
1333 if (fanboysSocialBlockingListSwitch.isChecked()) { // Fanboy's Social Blocking List is on.
1334 // Update the icon according to the theme.
1335 if (MainWebViewActivity.darkTheme) {
1336 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_dark));
1338 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_light));
1340 } else { // Fanboy's Social Blocking List is off.
1341 // Update the icon according to the theme.
1342 if (MainWebViewActivity.darkTheme) {
1343 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_dark));
1345 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_light));
1352 // Set the Fanboy's Social Blocking List switch listener.
1353 fanboysSocialBlockingListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1355 if (isChecked) { // Fanboy's Social Blocking List is on.
1356 // Set the icon according to the theme.
1357 if (MainWebViewActivity.darkTheme) {
1358 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_dark));
1360 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_light));
1362 } else { // Fanboy's Social Blocking List is off.
1363 // Set the icon according to the theme.
1364 if (MainWebViewActivity.darkTheme) {
1365 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_dark));
1367 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_light));
1372 // Set the UltraPrivacy switch listener.
1373 ultraPrivacySwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1375 if (isChecked) { // UltraPrivacy is on.
1376 // Set the icon according to the theme.
1377 if (MainWebViewActivity.darkTheme) {
1378 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_dark));
1380 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_light));
1382 } else { // UltraPrivacy is off.
1383 // Set the icon according to the theme.
1384 if (MainWebViewActivity.darkTheme) {
1385 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_dark));
1387 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_light));
1392 // Set the block all third-party requests switch listener.
1393 blockAllThirdPartyRequestsSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1395 if (isChecked) { // Blocking all third-party requests is on.
1396 // Set the icon according to the theme.
1397 if (MainWebViewActivity.darkTheme) {
1398 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_enabled_dark));
1400 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_enabled_light));
1402 } else { // Blocking all third-party requests is off.
1403 // Set the icon according to the theme.
1404 if (MainWebViewActivity.darkTheme) {
1405 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_disabled_dark));
1407 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_disabled_light));
1412 // Set the user agent spinner listener.
1413 userAgentSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1415 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1416 // Set the new user agent.
1418 case MainWebViewActivity.DOMAINS_SYSTEM_DEFAULT_USER_AGENT:
1419 // Show the user agent TextView.
1420 userAgentTextView.setVisibility(View.VISIBLE);
1422 // Hide the custom user agent EditText.
1423 customUserAgentEditText.setVisibility(View.GONE);
1425 // Set the user text.
1426 switch (defaultUserAgentArrayPosition) {
1427 case MainWebViewActivity.UNRECOGNIZED_USER_AGENT: // The default user agent name is not on the canonical list.
1428 // This is probably because it was set in an older version of Privacy Browser before the switch to persistent user agent names.
1429 userAgentTextView.setText(defaultUserAgentName);
1432 case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
1433 // Display the `WebView` default user agent.
1434 userAgentTextView.setText(webViewDefaultUserAgentString);
1437 case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
1438 // Display the custom user agent.
1439 userAgentTextView.setText(defaultCustomUserAgentString);
1443 // Get the user agent string from the user agent data array.
1444 userAgentTextView.setText(userAgentDataArray[defaultUserAgentArrayPosition]);
1448 case MainWebViewActivity.DOMAINS_WEBVIEW_DEFAULT_USER_AGENT:
1449 // Show the user agent TextView and set the text.
1450 userAgentTextView.setVisibility(View.VISIBLE);
1451 userAgentTextView.setText(webViewDefaultUserAgentString);
1453 // Hide the custom user agent EditTex.
1454 customUserAgentEditText.setVisibility(View.GONE);
1457 case MainWebViewActivity.DOMAINS_CUSTOM_USER_AGENT:
1458 // Hide the user agent TextView.
1459 userAgentTextView.setVisibility(View.GONE);
1461 // Show the custom user agent EditText and set the current user agent name as the text.
1462 customUserAgentEditText.setVisibility(View.VISIBLE);
1463 customUserAgentEditText.setText(currentUserAgentName);
1467 // Show the user agent TextView and set the text from the user agent data array, which has one less entry than the spinner, so the position must be decremented.
1468 userAgentTextView.setVisibility(View.VISIBLE);
1469 userAgentTextView.setText(userAgentDataArray[position - 1]);
1471 // Hide `customUserAgentEditText`.
1472 customUserAgentEditText.setVisibility(View.GONE);
1477 public void onNothingSelected(AdapterView<?> parent) {
1482 // Set the font size spinner listener.
1483 fontSizeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1485 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1486 // Update the display options for `fontSizeTextView`.
1487 if (position == 0) { // System default font size has been selected. Display `fontSizeTextView`.
1488 fontSizeTextView.setVisibility(View.VISIBLE);
1489 } else { // A custom font size has been selected. Hide `fontSizeTextView`.
1490 fontSizeTextView.setVisibility(View.GONE);
1495 public void onNothingSelected(AdapterView<?> parent) {
1500 // Set the swipe to refresh spinner listener.
1501 swipeToRefreshSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1503 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1504 // 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.
1506 case DomainsDatabaseHelper.SWIPE_TO_REFRESH_SYSTEM_DEFAULT:
1507 if (defaultSwipeToRefresh) { // Swipe to refresh enabled by default.
1508 // Set the icon according to the theme.
1509 if (MainWebViewActivity.darkTheme) {
1510 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_dark));
1512 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_light));
1514 } else { // Swipe to refresh disabled by default.
1515 // Set the icon according to the theme.
1516 if (MainWebViewActivity.darkTheme) {
1517 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_dark));
1519 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_light));
1523 // Show the swipe to refresh TextView.
1524 swipeToRefreshTextView.setVisibility(View.VISIBLE);
1527 case DomainsDatabaseHelper.SWIPE_TO_REFRESH_ENABLED:
1528 // Set the icon according to the theme.
1529 if (MainWebViewActivity.darkTheme) {
1530 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_dark));
1532 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_light));
1535 // Hide the swipe to refresh TextView.
1536 swipeToRefreshTextView.setVisibility(View.GONE);
1539 case DomainsDatabaseHelper.SWIPE_TO_REFRESH_DISABLED:
1540 // Set the icon according to the theme.
1541 if (MainWebViewActivity.darkTheme) {
1542 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_dark));
1544 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_light));
1547 // Hide the swipe to refresh TextView.
1548 swipeToRefreshTextView.setVisibility(View.GONE);
1553 public void onNothingSelected(AdapterView<?> parent) {
1558 // Set the night mode spinner listener.
1559 nightModeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1561 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1562 // 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.
1564 case DomainsDatabaseHelper.NIGHT_MODE_SYSTEM_DEFAULT:
1565 if (defaultNightMode) { // Night mode enabled by default.
1566 // Set the icon according to the theme.
1567 if (MainWebViewActivity.darkTheme) {
1568 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_dark));
1570 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_light));
1572 } else { // Night mode disabled by default.
1573 // Set the icon according to the theme.
1574 if (MainWebViewActivity.darkTheme) {
1575 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_dark));
1577 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_light));
1581 // Show the night mode TextView.
1582 nightModeTextView.setVisibility(View.VISIBLE);
1585 case DomainsDatabaseHelper.NIGHT_MODE_ENABLED:
1586 // Set the icon according to the theme.
1587 if (MainWebViewActivity.darkTheme) {
1588 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_dark));
1590 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_light));
1593 // Hide `nightModeTextView`.
1594 nightModeTextView.setVisibility(View.GONE);
1597 case DomainsDatabaseHelper.NIGHT_MODE_DISABLED:
1598 // Set the icon according to the theme.
1599 if (MainWebViewActivity.darkTheme) {
1600 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_dark));
1602 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_light));
1605 // Hide `nightModeTextView`.
1606 nightModeTextView.setVisibility(View.GONE);
1610 // Create a `boolean` to store the current night mode setting.
1611 boolean currentNightModeEnabled = (position == DomainsDatabaseHelper.NIGHT_MODE_ENABLED) || ((position == DomainsDatabaseHelper.NIGHT_MODE_SYSTEM_DEFAULT) && defaultNightMode);
1613 // Disable the JavaScript `Switch` if night mode is enabled.
1614 if (currentNightModeEnabled) {
1615 javaScriptEnabledSwitch.setEnabled(false);
1617 javaScriptEnabledSwitch.setEnabled(true);
1620 // Update the JavaScript icon.
1621 if ((javaScriptEnabledInt == 1) || currentNightModeEnabled) {
1622 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.javascript_enabled));
1624 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.privacy_mode));
1627 // Update the DOM storage status.
1628 if ((javaScriptEnabledInt == 1) || currentNightModeEnabled) { // JavaScript is enabled.
1629 // Enable the DOM storage `Switch`.
1630 domStorageEnabledSwitch.setEnabled(true);
1632 // Set the DOM storage status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
1633 if (domStorageEnabledInt == 1) { // Both JavaScript and DOM storage are enabled.
1634 domStorageEnabledSwitch.setChecked(true);
1635 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_enabled));
1636 } else { // JavaScript is enabled but DOM storage is disabled.
1637 // Set the DOM storage switch to off.
1638 domStorageEnabledSwitch.setChecked(false);
1640 // Set the icon according to the theme.
1641 if (MainWebViewActivity.darkTheme) {
1642 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_dark));
1644 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_light));
1647 } else { // JavaScript is disabled.
1648 // Disable the DOM storage `Switch`.
1649 domStorageEnabledSwitch.setEnabled(false);
1651 // Set the checked status of DOM storage.
1652 if (domStorageEnabledInt == 1) { // DOM storage is enabled but JavaScript is disabled.
1653 domStorageEnabledSwitch.setChecked(true);
1654 } else { // Both JavaScript and DOM storage are disabled.
1655 domStorageEnabledSwitch.setChecked(false);
1658 // Set the icon according to the theme.
1659 if (MainWebViewActivity.darkTheme) {
1660 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_dark));
1662 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_light));
1668 public void onNothingSelected(AdapterView<?> parent) {
1673 // Set the display webpage images spinner listener.
1674 displayWebpageImagesSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1676 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1677 // Update the icon and the visibility of `displayImagesTextView`.
1679 case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_SYSTEM_DEFAULT:
1680 if (defaultDisplayWebpageImages) {
1681 // Set the icon according to the theme.
1682 if (MainWebViewActivity.darkTheme) {
1683 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_dark));
1685 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_light));
1688 // Set the icon according to the theme.
1689 if (MainWebViewActivity.darkTheme) {
1690 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_dark));
1692 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_light));
1696 // Show `displayImagesTextView`.
1697 displayImagesTextView.setVisibility(View.VISIBLE);
1700 case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_ENABLED:
1701 // Set the icon according to the theme.
1702 if (MainWebViewActivity.darkTheme) {
1703 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_dark));
1705 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_light));
1708 // Hide `displayImagesTextView`.
1709 displayImagesTextView.setVisibility(View.GONE);
1712 case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_DISABLED:
1713 // Set the icon according to the theme.
1714 if (MainWebViewActivity.darkTheme) {
1715 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_dark));
1717 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_light));
1720 // Hide `displayImagesTextView`.
1721 displayImagesTextView.setVisibility(View.GONE);
1727 public void onNothingSelected(AdapterView<?> parent) {
1732 // Set the pinned SSL certificate switch listener.
1733 pinnedSslCertificateSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1735 if (isChecked) { // Pinned SSL certificate is enabled.
1736 // Set the icon according to the theme.
1737 if (MainWebViewActivity.darkTheme) {
1738 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_dark));
1740 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_light));
1743 // Update the visibility of the saved SSL certificate.
1744 if (savedSslCertificateIssuedToCNameString == null) {
1745 savedSslCertificateCardView.setVisibility(View.GONE);
1747 savedSslCertificateCardView.setVisibility(View.VISIBLE);
1750 // Update the visibility of the current website SSL certificate.
1751 if (currentWebsiteSslCertificate == null) {
1752 // Hide the SSL certificate.
1753 currentWebsiteCertificateCardView.setVisibility(View.GONE);
1755 // Show the instruction.
1756 noCurrentWebsiteCertificateTextView.setVisibility(View.VISIBLE);
1758 // Show the SSL certificate.
1759 currentWebsiteCertificateCardView.setVisibility(View.VISIBLE);
1761 // Hide the instruction.
1762 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
1765 // Set the status of the radio buttons.
1766 if (savedSslCertificateCardView.getVisibility() == View.VISIBLE) { // The saved SSL certificate is displayed.
1767 // Check the saved SSL certificate radio button.
1768 savedSslCertificateRadioButton.setChecked(true);
1770 // Uncheck the current website SSL certificate radio button.
1771 currentWebsiteCertificateRadioButton.setChecked(false);
1773 // Set the background of the saved SSL certificate linear layout to be transparent.
1774 savedSslCertificateLinearLayout.setBackgroundResource(R.color.transparent);
1776 // Darken the background of the current website SSL certificate linear layout according to the theme.
1777 if (MainWebViewActivity.darkTheme) {
1778 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
1780 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
1782 } else if (currentWebsiteCertificateCardView.getVisibility() == View.VISIBLE) { // The saved SSL certificate is hidden but the current website SSL certificate is visible.
1783 // Check the current website SSL certificate radio button.
1784 currentWebsiteCertificateRadioButton.setChecked(true);
1786 // Uncheck the saved SSL certificate radio button.
1787 savedSslCertificateRadioButton.setChecked(false);
1789 // Set the background of the current website SSL certificate linear layout to be transparent.
1790 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.transparent);
1792 // Darken the background of the saved SSL certificate linear layout according to the theme.
1793 if (MainWebViewActivity.darkTheme) {
1794 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
1796 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
1798 } else { // Neither SSL certificate is visible.
1799 // Uncheck both radio buttons.
1800 savedSslCertificateRadioButton.setChecked(false);
1801 currentWebsiteCertificateRadioButton.setChecked(false);
1803 } else { // Pinned SSL certificate is disabled.
1804 // Set the icon according to the theme.
1805 if (MainWebViewActivity.darkTheme) {
1806 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_dark));
1808 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_light));
1811 // Hide the SSl certificates and instructions.
1812 savedSslCertificateCardView.setVisibility(View.GONE);
1813 currentWebsiteCertificateCardView.setVisibility(View.GONE);
1814 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
1816 // Uncheck the radio buttons.
1817 savedSslCertificateRadioButton.setChecked(false);
1818 currentWebsiteCertificateRadioButton.setChecked(false);
1822 savedSslCertificateCardView.setOnClickListener((View v) -> {
1823 // Check the saved SSL certificate radio button.
1824 savedSslCertificateRadioButton.setChecked(true);
1826 // Uncheck the current website SSL certificate radio button.
1827 currentWebsiteCertificateRadioButton.setChecked(false);
1829 // Set the background of the saved SSL certificate linear layout to be transparent.
1830 savedSslCertificateLinearLayout.setBackgroundResource(R.color.transparent);
1832 // Darken the background of the current website SSL certificate linear layout according to the theme.
1833 if (MainWebViewActivity.darkTheme) {
1834 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
1836 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
1840 savedSslCertificateRadioButton.setOnClickListener((View v) -> {
1841 // Check the saved SSL certificate radio button.
1842 savedSslCertificateRadioButton.setChecked(true);
1844 // Uncheck the current website SSL certificate radio button.
1845 currentWebsiteCertificateRadioButton.setChecked(false);
1847 // Set the background of the saved SSL certificate linear layout to be transparent.
1848 savedSslCertificateLinearLayout.setBackgroundResource(R.color.transparent);
1850 // Darken the background of the current website SSL certificate linear layout according to the theme.
1851 if (MainWebViewActivity.darkTheme) {
1852 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
1854 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
1858 currentWebsiteCertificateCardView.setOnClickListener((View v) -> {
1859 // Check the current website SSL certificate radio button.
1860 currentWebsiteCertificateRadioButton.setChecked(true);
1862 // Uncheck the saved SSL certificate radio button.
1863 savedSslCertificateRadioButton.setChecked(false);
1865 // Set the background of the current website SSL certificate linear layout to be transparent.
1866 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.transparent);
1868 // Darken the background of the saved SSL certificate linear layout according to the theme.
1869 if (MainWebViewActivity.darkTheme) {
1870 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
1872 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
1876 currentWebsiteCertificateRadioButton.setOnClickListener((View v) -> {
1877 // Check the current website SSL certificate radio button.
1878 currentWebsiteCertificateRadioButton.setChecked(true);
1880 // Uncheck the saved SSL certificate radio button.
1881 savedSslCertificateRadioButton.setChecked(false);
1883 // Set the background of the current website SSL certificate linear layout to be transparent.
1884 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.transparent);
1886 // Darken the background of the saved SSL certificate linear layout according to the theme.
1887 if (MainWebViewActivity.darkTheme) {
1888 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
1890 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
1894 return domainSettingsView;
1897 private boolean checkDomainNameAgainstCertificate(String domainName, String certificateCommonName) {
1898 // Initialize `domainNamesMatch`.
1899 boolean domainNamesMatch = false;
1901 // Check various wildcard permutations if `domainName` and `certificateCommonName` are not empty.
1902 // `noinspection ConstantCondition` removes Android Studio's incorrect lint warning that `domainName` can never be `null`.
1903 //noinspection ConstantConditions
1904 if ((domainName != null) && (certificateCommonName != null)) {
1905 // Check if the domains match.
1906 if (domainName.equals(certificateCommonName)) {
1907 domainNamesMatch = true;
1910 // If `domainName` starts with a wildcard, check the base domain against all the subdomains of `certificateCommonName`.
1911 if (!domainNamesMatch && domainName.startsWith("*.") && (domainName.length() > 2)) {
1912 // Remove the initial `*.`.
1913 String baseDomainName = domainName.substring(2);
1915 // Setup a copy of `certificateCommonName` to test subdomains.
1916 String certificateCommonNameSubdomain = certificateCommonName;
1918 // Check all the subdomains in `certificateCommonNameSubdomain` against `baseDomainName`.
1919 while (!domainNamesMatch && certificateCommonNameSubdomain.contains(".")) { // Stop checking if we know that `domainNamesMatch` is `true` or if we run out of `.`.
1920 // Test the `certificateCommonNameSubdomain` against `baseDomainName`.
1921 if (certificateCommonNameSubdomain.equals(baseDomainName)) {
1922 domainNamesMatch = true;
1925 // Strip out the lowest subdomain of `certificateCommonNameSubdomain`.
1927 certificateCommonNameSubdomain = certificateCommonNameSubdomain.substring(certificateCommonNameSubdomain.indexOf(".") + 1);
1928 } catch (IndexOutOfBoundsException e) { // `certificateCommonNameSubdomain` ends with `.`.
1929 certificateCommonNameSubdomain = "";
1934 // If `certificateCommonName` starts with a wildcard, check the base common name against all the subdomains of `domainName`.
1935 if (!domainNamesMatch && certificateCommonName.startsWith("*.") && (certificateCommonName.length() > 2)) {
1936 // Remove the initial `*.`.
1937 String baseCertificateCommonName = certificateCommonName.substring(2);
1939 // Setup a copy of `domainName` to test subdomains.
1940 String domainNameSubdomain = domainName;
1942 // Check all the subdomains in `domainNameSubdomain` against `baseCertificateCommonName`.
1943 while (!domainNamesMatch && domainNameSubdomain.contains(".") && (domainNameSubdomain.length() > 2)) {
1944 // Test the `domainNameSubdomain` against `baseCertificateCommonName`.
1945 if (domainNameSubdomain.equals(baseCertificateCommonName)) {
1946 domainNamesMatch = true;
1949 // Strip out the lowest subdomain of `domainNameSubdomain`.
1951 domainNameSubdomain = domainNameSubdomain.substring(domainNameSubdomain.indexOf(".") + 1);
1952 } catch (IndexOutOfBoundsException e) { // `domainNameSubdomain` ends with `.`.
1953 domainNameSubdomain = "";
1958 // If both names start with a wildcard, check if the root of one contains the root of the other.
1959 if (!domainNamesMatch && domainName.startsWith("*.") && (domainName.length() > 2) && certificateCommonName.startsWith("*.") && (certificateCommonName.length() > 2)) {
1960 // Remove the wildcards.
1961 String rootDomainName = domainName.substring(2);
1962 String rootCertificateCommonName = certificateCommonName.substring(2);
1964 // Check if one name ends with the contents of the other. If so, there will be overlap in the their wildcard subdomains.
1965 if (rootDomainName.endsWith(rootCertificateCommonName) || rootCertificateCommonName.endsWith(rootDomainName)) {
1966 domainNamesMatch = true;
1971 return domainNamesMatch;