2 * Copyright © 2017-2018 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 // We have to use `android.support.v4.app.Fragment` until minimum API >= 23. Otherwise we cannot call `getContext()`.
31 import android.preference.PreferenceManager;
32 import android.support.annotation.NonNull;
33 import android.support.v4.app.Fragment;
34 import android.text.Editable;
35 import android.text.SpannableStringBuilder;
36 import android.text.Spanned;
37 import android.text.TextWatcher;
38 import android.text.style.ForegroundColorSpan;
39 import android.view.LayoutInflater;
40 import android.view.View;
41 import android.view.ViewGroup;
42 import android.webkit.WebView;
43 import android.widget.AdapterView;
44 import android.widget.ArrayAdapter;
45 import android.widget.CompoundButton;
46 import android.widget.EditText;
47 import android.widget.ImageView;
48 import android.widget.LinearLayout;
49 import android.widget.RadioButton;
50 import android.widget.Spinner;
51 import android.widget.Switch;
52 import android.widget.TextView;
54 import com.stoutner.privacybrowser.R;
55 import com.stoutner.privacybrowser.activities.MainWebViewActivity;
56 import com.stoutner.privacybrowser.helpers.DomainsDatabaseHelper;
58 import java.text.DateFormat;
59 import java.util.Calendar;
60 import java.util.Date;
62 public class DomainSettingsFragment extends Fragment {
63 // `DATABASE_ID` is used by activities calling this fragment.
64 public static final String DATABASE_ID = "database_id";
66 // `databaseId` is public static so it can be accessed from `DomainsActivity`. It is also used in `onCreate()` and `onCreateView()`.
67 public static int databaseId;
70 public void onCreate(Bundle savedInstanceState) {
71 super.onCreate(savedInstanceState);
73 // Remove the lint warning that `getArguments` might be null.
74 assert getArguments() != null;
76 // Store the database id in `databaseId`.
77 databaseId = getArguments().getInt(DATABASE_ID);
80 // The deprecated `getDrawable()` must be used until the minimum API >= 21.
81 @SuppressWarnings("deprecation")
83 public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
84 // Inflate `domain_settings_fragment`. `false` does not attach it to the root `container`.
85 View domainSettingsView = inflater.inflate(R.layout.domain_settings_fragment, container, false);
87 // Get a handle for the `Context` and the `Resources`.
88 Context context = getContext();
89 final Resources resources = getResources();
91 // Get a handle for the shared preference.
92 SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
94 // Store the default settings.
95 final String defaultUserAgentName = sharedPreferences.getString("user_agent", "Privacy Browser");
96 final String defaultCustomUserAgentString = sharedPreferences.getString("custom_user_agent", "PrivacyBrowser/1.0");
97 String defaultFontSizeString = sharedPreferences.getString("default_font_size", "100");
98 boolean defaultSwipeToRefreshBoolean = sharedPreferences.getBoolean("swipe_to_refresh", true);
99 final boolean defaultNightModeBoolean = sharedPreferences.getBoolean("night_mode", false);
100 final boolean defaultDisplayWebpageImagesBoolean = sharedPreferences.getBoolean("display_website_images", true);
102 // Get handles for the views in the fragment.
103 final EditText domainNameEditText = domainSettingsView.findViewById(R.id.domain_settings_name_edittext);
104 final Switch javaScriptEnabledSwitch = domainSettingsView.findViewById(R.id.domain_settings_javascript_switch);
105 final ImageView javaScriptImageView = domainSettingsView.findViewById(R.id.domain_settings_javascript_imageview);
106 Switch firstPartyCookiesEnabledSwitch = domainSettingsView.findViewById(R.id.domain_settings_first_party_cookies_switch);
107 final ImageView firstPartyCookiesImageView = domainSettingsView.findViewById(R.id.domain_settings_first_party_cookies_imageview);
108 LinearLayout thirdPartyCookiesLinearLayout = domainSettingsView.findViewById(R.id.domain_settings_third_party_cookies_linearlayout);
109 final Switch thirdPartyCookiesEnabledSwitch = domainSettingsView.findViewById(R.id.domain_settings_third_party_cookies_switch);
110 final ImageView thirdPartyCookiesImageView = domainSettingsView.findViewById(R.id.domain_settings_third_party_cookies_imageview);
111 final Switch domStorageEnabledSwitch = domainSettingsView.findViewById(R.id.domain_settings_dom_storage_switch);
112 final ImageView domStorageImageView = domainSettingsView.findViewById(R.id.domain_settings_dom_storage_imageview);
113 Switch formDataEnabledSwitch = domainSettingsView.findViewById(R.id.domain_settings_form_data_switch); // The form data views can be remove once the minimum API >= 26.
114 final ImageView formDataImageView = domainSettingsView.findViewById(R.id.domain_settings_form_data_imageview); // The form data views can be remove once the minimum API >= 26.
115 Switch easyListSwitch = domainSettingsView.findViewById(R.id.domain_settings_easylist_switch);
116 ImageView easyListImageView = domainSettingsView.findViewById(R.id.domain_settings_easylist_imageview);
117 Switch easyPrivacySwitch = domainSettingsView.findViewById(R.id.domain_settings_easyprivacy_switch);
118 ImageView easyPrivacyImageView = domainSettingsView.findViewById(R.id.domain_settings_easyprivacy_imageview);
119 Switch fanboysAnnoyanceListSwitch = domainSettingsView.findViewById(R.id.domain_settings_fanboys_annoyance_list_switch);
120 ImageView fanboysAnnoyanceListImageView = domainSettingsView.findViewById(R.id.domain_settings_fanboys_annoyance_list_imageview);
121 Switch fanboysSocialBlockingListSwitch = domainSettingsView.findViewById(R.id.domain_settings_fanboys_social_blocking_list_switch);
122 ImageView fanboysSocialBlockingListImageView = domainSettingsView.findViewById(R.id.domain_settings_fanboys_social_blocking_list_imageview);
123 Switch blockAllThirdPartyRequestsSwitch = domainSettingsView.findViewById(R.id.domain_settings_block_all_third_party_requests_switch);
124 ImageView blockAllThirdPartyRequestsImageView = domainSettingsView.findViewById(R.id.domain_settings_block_all_third_party_requests_imageview);
125 final Spinner userAgentSpinner = domainSettingsView.findViewById(R.id.domain_settings_user_agent_spinner);
126 final TextView userAgentTextView = domainSettingsView.findViewById(R.id.domain_settings_user_agent_textview);
127 final EditText customUserAgentEditText = domainSettingsView.findViewById(R.id.domain_settings_custom_user_agent_edittext);
128 final Spinner fontSizeSpinner = domainSettingsView.findViewById(R.id.domain_settings_font_size_spinner);
129 final TextView fontSizeTextView = domainSettingsView.findViewById(R.id.domain_settings_font_size_textview);
130 final ImageView swipeToRefreshImageView = domainSettingsView.findViewById(R.id.domain_settings_swipe_to_refresh_imageview);
131 final Spinner swipeToRefreshSpinner = domainSettingsView.findViewById(R.id.domain_settings_swipe_to_refresh_spinner);
132 final TextView swipeToRefreshTextView = domainSettingsView.findViewById(R.id.domain_settings_swipe_to_refresh_textview);
133 final ImageView nightModeImageView = domainSettingsView.findViewById(R.id.domain_settings_night_mode_imageview);
134 final Spinner nightModeSpinner = domainSettingsView.findViewById(R.id.domain_settings_night_mode_spinner);
135 final TextView nightModeTextView = domainSettingsView.findViewById(R.id.domain_settings_night_mode_textview);
136 final ImageView displayWebpageImagesImageView = domainSettingsView.findViewById(R.id.domain_settings_display_webpage_images_imageview);
137 final Spinner displayWebpageImagesSpinner = domainSettingsView.findViewById(R.id.domain_settings_display_webpage_images_spinner);
138 final TextView displayImagesTextView = domainSettingsView.findViewById(R.id.domain_settings_display_webpage_images_textview);
139 final ImageView pinnedSslCertificateImageView = domainSettingsView.findViewById(R.id.domain_settings_pinned_ssl_certificate_imageview);
140 Switch pinnedSslCertificateSwitch = domainSettingsView.findViewById(R.id.domain_settings_pinned_ssl_certificate_switch);
141 final LinearLayout savedSslCertificateLinearLayout = domainSettingsView.findViewById(R.id.saved_ssl_certificate_linearlayout);
142 final RadioButton savedSslCertificateRadioButton = domainSettingsView.findViewById(R.id.saved_ssl_certificate_radiobutton);
143 final TextView savedSslCertificateIssuedToCNameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_to_cname);
144 TextView savedSslCertificateIssuedToONameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_to_oname);
145 TextView savedSslCertificateIssuedToUNameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_to_uname);
146 TextView savedSslCertificateIssuedByCNameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_by_cname);
147 TextView savedSslCertificateIssuedByONameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_by_oname);
148 TextView savedSslCertificateIssuedByUNameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_by_uname);
149 TextView savedSslCertificateStartDateTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_start_date);
150 TextView savedSslCertificateEndDateTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_end_date);
151 final LinearLayout currentWebsiteCertificateLinearLayout = domainSettingsView.findViewById(R.id.current_website_certificate_linearlayout);
152 final RadioButton currentWebsiteCertificateRadioButton = domainSettingsView.findViewById(R.id.current_website_certificate_radiobutton);
153 final TextView currentWebsiteCertificateIssuedToCNameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_to_cname);
154 TextView currentWebsiteCertificateIssuedToONameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_to_oname);
155 TextView currentWebsiteCertificateIssuedToUNameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_to_uname);
156 TextView currentWebsiteCertificateIssuedByCNameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_by_cname);
157 TextView currentWebsiteCertificateIssuedByONameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_by_oname);
158 TextView currentWebsiteCertificateIssuedByUNameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_by_uname);
159 TextView currentWebsiteCertificateStartDateTextView = domainSettingsView.findViewById(R.id.current_website_certificate_start_date);
160 TextView currentWebsiteCertificateEndDateTextView = domainSettingsView.findViewById(R.id.current_website_certificate_end_date);
161 final TextView noCurrentWebsiteCertificateTextView = domainSettingsView.findViewById(R.id.no_current_website_certificate);
163 // Setup the SSL certificate labels.
164 final String cNameLabel = getString(R.string.common_name) + " ";
165 String oNameLabel = getString(R.string.organization) + " ";
166 String uNameLabel = getString(R.string.organizational_unit) + " ";
167 String startDateLabel = getString(R.string.start_date) + " ";
168 String endDateLabel = getString(R.string.end_date) + " ";
170 // Get the current website SSL certificate
171 final SslCertificate currentWebsiteSslCertificate = MainWebViewActivity.sslCertificate;
173 // Initialize the database handler. The `0` specifies the database version, but that is ignored and set instead using a constant in `DomainsDatabaseHelper`.
174 DomainsDatabaseHelper domainsDatabaseHelper = new DomainsDatabaseHelper(context, null, null, 0);
176 // Get the database `Cursor` for this ID and move it to the first row.
177 Cursor domainCursor = domainsDatabaseHelper.getCursorForId(databaseId);
178 domainCursor.moveToFirst();
180 // Save the `Cursor` entries as variables.
181 String domainNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.DOMAIN_NAME));
182 final int javaScriptEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_JAVASCRIPT));
183 int firstPartyCookiesEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FIRST_PARTY_COOKIES));
184 int thirdPartyCookiesEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_THIRD_PARTY_COOKIES));
185 final int domStorageEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_DOM_STORAGE));
186 int formDataEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FORM_DATA)); // Form data can be remove once the minimum API >= 26.
187 int easyListEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYLIST));
188 int easyPrivacyEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYPRIVACY));
189 int fanboysAnnoyanceListInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST));
190 int fanboysSocialBlockingListInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST));
191 int blockAllThirdPartyRequestsInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS));
192 final String currentUserAgentName = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.USER_AGENT));
193 int fontSizeInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.FONT_SIZE));
194 int swipeToRefreshInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.SWIPE_TO_REFRESH));
195 int nightModeInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.NIGHT_MODE));
196 int displayImagesInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.DISPLAY_IMAGES));
197 int pinnedSslCertificateInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.PINNED_SSL_CERTIFICATE));
198 final String savedSslCertificateIssuedToCNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_COMMON_NAME));
199 String savedSslCertificateIssuedToONameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATION));
200 String savedSslCertificateIssuedToUNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATIONAL_UNIT));
201 String savedSslCertificateIssuedByCNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_COMMON_NAME));
202 String savedSslCertificateIssuedByONameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATION));
203 String savedSslCertificateIssuedByUNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATIONAL_UNIT));
205 // Initialize the saved SSL certificate date variables.
206 Date savedSslCertificateStartDate = null;
207 Date savedSslCertificateEndDate = null;
209 // Only get the saved SSL certificate dates from the cursor if they are not set to `0`.
210 if (domainCursor.getLong(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_START_DATE)) != 0) {
211 savedSslCertificateStartDate = new Date(domainCursor.getLong(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_START_DATE)));
214 if (domainCursor.getLong(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_END_DATE)) != 0) {
215 savedSslCertificateEndDate = new Date(domainCursor.getLong(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_END_DATE)));
218 // Create `ArrayAdapters` for the `Spinners`and their `entry values`.
219 ArrayAdapter<CharSequence> translatedUserAgentArrayAdapter = ArrayAdapter.createFromResource(context, R.array.translated_domain_settings_user_agent_names, R.layout.domain_settings_spinner_item);
220 ArrayAdapter<CharSequence> fontSizeArrayAdapter = ArrayAdapter.createFromResource(context, R.array.domain_settings_font_size_entries, R.layout.domain_settings_spinner_item);
221 ArrayAdapter<CharSequence> fontSizeEntryValuesArrayAdapter = ArrayAdapter.createFromResource(context, R.array.domain_settings_font_size_entry_values, R.layout.domain_settings_spinner_item);
222 ArrayAdapter<CharSequence> swipeToRefreshArrayAdapter = ArrayAdapter.createFromResource(context, R.array.swipe_to_refresh_array, R.layout.domain_settings_spinner_item);
223 ArrayAdapter<CharSequence> nightModeArrayAdapter = ArrayAdapter.createFromResource(context, R.array.night_mode_array, R.layout.domain_settings_spinner_item);
224 ArrayAdapter<CharSequence> displayImagesArrayAdapter = ArrayAdapter.createFromResource(context, R.array.display_webpage_images_array, R.layout.domain_settings_spinner_item);
226 // Set the `DropDownViewResource` on the `Spinners`.
227 translatedUserAgentArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items);
228 fontSizeArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items);
229 swipeToRefreshArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items);
230 nightModeArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items);
231 displayImagesArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items);
233 // Set the `ArrayAdapters` for the `Spinners`.
234 userAgentSpinner.setAdapter(translatedUserAgentArrayAdapter);
235 fontSizeSpinner.setAdapter(fontSizeArrayAdapter);
236 swipeToRefreshSpinner.setAdapter(swipeToRefreshArrayAdapter);
237 nightModeSpinner.setAdapter(nightModeArrayAdapter);
238 displayWebpageImagesSpinner.setAdapter(displayImagesArrayAdapter);
240 // Create a `SpannableStringBuilder` for each `TextView` that needs multiple colors of text.
241 SpannableStringBuilder savedSslCertificateIssuedToCNameStringBuilder = new SpannableStringBuilder(cNameLabel + savedSslCertificateIssuedToCNameString);
242 SpannableStringBuilder savedSslCertificateIssuedToONameStringBuilder = new SpannableStringBuilder(oNameLabel + savedSslCertificateIssuedToONameString);
243 SpannableStringBuilder savedSslCertificateIssuedToUNameStringBuilder = new SpannableStringBuilder(uNameLabel + savedSslCertificateIssuedToUNameString);
244 SpannableStringBuilder savedSslCertificateIssuedByCNameStringBuilder = new SpannableStringBuilder(cNameLabel + savedSslCertificateIssuedByCNameString);
245 SpannableStringBuilder savedSslCertificateIssuedByONameStringBuilder = new SpannableStringBuilder(oNameLabel + savedSslCertificateIssuedByONameString);
246 SpannableStringBuilder savedSslCertificateIssuedByUNameStringBuilder = new SpannableStringBuilder(uNameLabel + savedSslCertificateIssuedByUNameString);
248 // Initialize the `SpannableStringBuilders` for the SSL certificate dates.
249 SpannableStringBuilder savedSslCertificateStartDateStringBuilder;
250 SpannableStringBuilder savedSslCertificateEndDateStringBuilder;
252 // Leave the SSL certificate dates empty if they are `null`.
253 if (savedSslCertificateStartDate == null) {
254 savedSslCertificateStartDateStringBuilder = new SpannableStringBuilder(startDateLabel);
256 savedSslCertificateStartDateStringBuilder = new SpannableStringBuilder(startDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG).format(savedSslCertificateStartDate));
259 if (savedSslCertificateEndDate == null) {
260 savedSslCertificateEndDateStringBuilder = new SpannableStringBuilder(endDateLabel);
262 savedSslCertificateEndDateStringBuilder = new SpannableStringBuilder(endDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG).format(savedSslCertificateEndDate));
265 // Create a red `ForegroundColorSpan`. We have to use the deprecated `getColor` until API >= 23.
266 final ForegroundColorSpan redColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.red_a700));
268 // Create a blue `ForegroundColorSpan`.
269 final ForegroundColorSpan blueColorSpan;
271 // Set `blueColorSpan` according to the theme. We have to use the deprecated `getColor()` until API >= 23.
272 if (MainWebViewActivity.darkTheme) {
273 //noinspection deprecation
274 blueColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.blue_400));
276 //noinspection deprecation
277 blueColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.blue_700));
280 // Set the domain name from the the database cursor.
281 domainNameEditText.setText(domainNameString);
283 // Update the certificates' `Common Name` color when the domain name text changes.
284 domainNameEditText.addTextChangedListener(new TextWatcher() {
286 public void beforeTextChanged(CharSequence s, int start, int count, int after) {
291 public void onTextChanged(CharSequence s, int start, int before, int count) {
296 public void afterTextChanged(Editable s) {
297 // Get the new domain name.
298 String newDomainName = domainNameEditText.getText().toString();
300 // Check the saved SSL certificate against the new domain name.
301 boolean savedSslCertificateMatchesNewDomainName = checkDomainNameAgainstCertificate(newDomainName, savedSslCertificateIssuedToCNameString);
303 // Create a `SpannableStringBuilder` for the saved certificate `Common Name`.
304 SpannableStringBuilder savedSslCertificateCommonNameStringBuilder = new SpannableStringBuilder(cNameLabel + savedSslCertificateIssuedToCNameString);
306 // Format the saved certificate `Common Name` color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
307 if (savedSslCertificateMatchesNewDomainName) {
308 savedSslCertificateCommonNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), savedSslCertificateCommonNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
310 savedSslCertificateCommonNameStringBuilder.setSpan(redColorSpan, cNameLabel.length(), savedSslCertificateCommonNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
313 // Update `savedSslCertificateIssuedToCNameTextView`.
314 savedSslCertificateIssuedToCNameTextView.setText(savedSslCertificateCommonNameStringBuilder);
316 // Update the current website certificate if it exists.
317 if (currentWebsiteSslCertificate != null) {
318 // Get the current website certificate `Common Name`.
319 String currentWebsiteCertificateCommonName = currentWebsiteSslCertificate.getIssuedTo().getCName();
321 // Check the current website certificate against the new domain name.
322 boolean currentWebsiteCertificateMatchesNewDomainName = checkDomainNameAgainstCertificate(newDomainName, currentWebsiteCertificateCommonName);
324 // Create a `SpannableStringBuilder` for the current website certificate `Common Name`.
325 SpannableStringBuilder currentWebsiteCertificateCommonNameStringBuilder = new SpannableStringBuilder(cNameLabel + currentWebsiteCertificateCommonName);
327 // Format the current certificate `Common Name` color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
328 if (currentWebsiteCertificateMatchesNewDomainName) {
329 currentWebsiteCertificateCommonNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), currentWebsiteCertificateCommonNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
331 currentWebsiteCertificateCommonNameStringBuilder.setSpan(redColorSpan, cNameLabel.length(), currentWebsiteCertificateCommonNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
334 // Update `currentWebsiteCertificateIssuedToCNameTextView`.
335 currentWebsiteCertificateIssuedToCNameTextView.setText(currentWebsiteCertificateCommonNameStringBuilder);
340 // Create a `boolean` to track if night mode is enabled.
341 boolean nightModeEnabled = (nightModeInt == DomainsDatabaseHelper.NIGHT_MODE_ENABLED) || ((nightModeInt == DomainsDatabaseHelper.NIGHT_MODE_SYSTEM_DEFAULT) && defaultNightModeBoolean);
343 // Disable the JavaScript switch if night mode is enabled.
344 if (nightModeEnabled) {
345 javaScriptEnabledSwitch.setEnabled(false);
347 javaScriptEnabledSwitch.setEnabled(true);
350 // Set the JavaScript icon.
351 if ((javaScriptEnabledInt == 1) || nightModeEnabled) {
352 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.javascript_enabled));
354 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.privacy_mode));
357 // Set the JavaScript switch status.
358 if (javaScriptEnabledInt == 1) { // JavaScript is enabled.
359 javaScriptEnabledSwitch.setChecked(true);
360 } else { // JavaScript is disabled.
361 javaScriptEnabledSwitch.setChecked(false);
364 // 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.
365 if (firstPartyCookiesEnabledInt == 1) { // First-party cookies are enabled.
366 firstPartyCookiesEnabledSwitch.setChecked(true);
367 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_enabled));
368 } else { // First-party cookies are disabled.
369 firstPartyCookiesEnabledSwitch.setChecked(false);
371 // Set the icon according to the theme.
372 if (MainWebViewActivity.darkTheme) {
373 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_dark));
375 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_light));
379 // Only display third-party cookies if SDK_INT >= 21.
380 if (Build.VERSION.SDK_INT >= 21) { // Third-party cookies can be configured for API >= 21.
381 // Only enable third-party-cookies if first-party cookies are enabled.
382 if (firstPartyCookiesEnabledInt == 1) { // First-party cookies are enabled.
383 // 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.
384 if (thirdPartyCookiesEnabledInt == 1) { // Both first-party and third-party cookies are enabled.
385 thirdPartyCookiesEnabledSwitch.setChecked(true);
386 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_warning));
387 } else { // First party cookies are enabled but third-party cookies are disabled.
388 thirdPartyCookiesEnabledSwitch.setChecked(false);
390 // Set the icon according to the theme.
391 if (MainWebViewActivity.darkTheme) {
392 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_dark));
394 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_light));
397 } else { // First-party cookies are disabled.
398 // Set the status of third-party cookies.
399 if (thirdPartyCookiesEnabledInt == 1) {
400 thirdPartyCookiesEnabledSwitch.setChecked(true);
402 thirdPartyCookiesEnabledSwitch.setChecked(false);
405 // Disable the third-party cookies switch.
406 thirdPartyCookiesEnabledSwitch.setEnabled(false);
408 // Set the icon according to the theme.
409 if (MainWebViewActivity.darkTheme) {
410 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_ghosted_dark));
412 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_ghosted_light));
415 } else { // Third-party cookies cannot be configured for API <= 21.
416 // Hide the LinearLayout for third-party cookies.
417 thirdPartyCookiesLinearLayout.setVisibility(View.GONE);
420 // Only enable DOM storage if JavaScript is enabled.
421 if ((javaScriptEnabledInt == 1) || nightModeEnabled) { // JavaScript is enabled.
422 // Enable the DOM storage `Switch`.
423 domStorageEnabledSwitch.setEnabled(true);
425 // Set the DOM storage status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
426 if (domStorageEnabledInt == 1) { // Both JavaScript and DOM storage are enabled.
427 domStorageEnabledSwitch.setChecked(true);
428 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_enabled));
429 } else { // JavaScript is enabled but DOM storage is disabled.
430 // Set the DOM storage switch to off.
431 domStorageEnabledSwitch.setChecked(false);
433 // Set the icon according to the theme.
434 if (MainWebViewActivity.darkTheme) {
435 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_dark));
437 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_light));
440 } else { // JavaScript is disabled.
441 // Disable the DOM storage `Switch`.
442 domStorageEnabledSwitch.setEnabled(false);
444 // Set the checked status of DOM storage.
445 if (domStorageEnabledInt == 1) { // DOM storage is enabled but JavaScript is disabled.
446 domStorageEnabledSwitch.setChecked(true);
447 } else { // Both JavaScript and DOM storage are disabled.
448 domStorageEnabledSwitch.setChecked(false);
451 // Set the icon according to the theme.
452 if (MainWebViewActivity.darkTheme) {
453 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_dark));
455 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_light));
459 // 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.
460 if (Build.VERSION.SDK_INT >= 26) { // Form data no longer applies to newer versions of Android.
461 // Hide the form data switch.
462 formDataEnabledSwitch.setVisibility(View.GONE);
463 } else { // Form data should be displayed because this is an older version of Android.
464 if (formDataEnabledInt == 1) { // Form data is on.
465 formDataEnabledSwitch.setChecked(true);
466 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_enabled));
467 } else { // Form data is off.
468 // Turn the form data switch to off.
469 formDataEnabledSwitch.setChecked(false);
471 // Set the icon according to the theme.
472 if (MainWebViewActivity.darkTheme) {
473 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_disabled_dark));
475 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_disabled_light));
480 // Set the EasyList status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
481 if (easyListEnabledInt == 1) { // EasyList is on.
482 // Turn the switch on.
483 easyListSwitch.setChecked(true);
485 // Set the icon according to the theme.
486 if (MainWebViewActivity.darkTheme) {
487 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_dark));
489 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_light));
491 } else { // EasyList is off.
492 // Turn the switch off.
493 easyListSwitch.setChecked(false);
495 // Set the icon according to the theme.
496 if (MainWebViewActivity.darkTheme) {
497 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_dark));
499 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_light));
503 // Set the EasyPrivacy status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
504 if (easyPrivacyEnabledInt == 1) { // EasyPrivacy is on.
505 // Turn the switch on.
506 easyPrivacySwitch.setChecked(true);
508 // Set the icon according to the theme.
509 if (MainWebViewActivity.darkTheme) {
510 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_dark));
512 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_light));
514 } else { // EasyPrivacy is off.
515 // Turn the switch off.
516 easyPrivacySwitch.setChecked(false);
518 // Set the icon according to the theme.
519 if (MainWebViewActivity.darkTheme) {
520 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_dark));
522 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_light));
526 // 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.
527 if (fanboysAnnoyanceListInt == 1) { // Fanboy's Annoyance List is on.
528 // Turn the switch on.
529 fanboysAnnoyanceListSwitch.setChecked(true);
531 // Set the icon according to the theme.
532 if (MainWebViewActivity.darkTheme) {
533 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_dark));
535 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_light));
537 } else { // Fanboy's Annoyance List is off.
538 // Turn the switch off.
539 fanboysAnnoyanceListSwitch.setChecked(false);
541 // Set the icon according to the theme.
542 if (MainWebViewActivity.darkTheme) {
543 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_dark));
545 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_light));
549 // Only enable Fanboy's Social Blocking List if Fanboy's Annoyance List is off.
550 if (fanboysAnnoyanceListInt == 0) { // Fanboy's Annoyance List is on.
551 // 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.
552 if (fanboysSocialBlockingListInt == 1) { // Fanboy's Social Blocking List is on.
553 // Enable the switch and turn it on.
554 fanboysSocialBlockingListSwitch.setEnabled(true);
555 fanboysSocialBlockingListSwitch.setChecked(true);
557 // Set the icon according to the theme.
558 if (MainWebViewActivity.darkTheme) {
559 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_dark));
561 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_light));
563 } else { // Fanboy's Social Blocking List is off.
564 // Enable the switch but turn it off.
565 fanboysSocialBlockingListSwitch.setEnabled(true);
566 fanboysSocialBlockingListSwitch.setChecked(false);
568 // Set the icon according to the theme.
569 if (MainWebViewActivity.darkTheme) {
570 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_dark));
572 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_light));
575 } else { // Fanboy's Annoyance List is on.
576 // 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.
577 if (fanboysSocialBlockingListInt == 1) { // Fanboy's Social Blocking List is on.
578 // Disable the switch but turn it on.
579 fanboysSocialBlockingListSwitch.setEnabled(false);
580 fanboysSocialBlockingListSwitch.setChecked(true);
581 } else { // Fanboy's Social Blocking List is off.
582 // Disable the switch and turn it off.
583 fanboysSocialBlockingListSwitch.setEnabled(false);
584 fanboysSocialBlockingListSwitch.setChecked(false);
587 // Set the icon according to the theme.
588 if (MainWebViewActivity.darkTheme) {
589 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_ghosted_dark));
591 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_ghosted_light));
595 // 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.
596 if (blockAllThirdPartyRequestsInt == 1) { // Blocking all third-party requests is on.
597 // Turn the switch on.
598 blockAllThirdPartyRequestsSwitch.setChecked(true);
600 // Set the icon according to the theme.
601 if (MainWebViewActivity.darkTheme) {
602 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_enabled_dark));
604 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_enabled_light));
606 } else { // Blocking all third-party requests is off.
607 // Turn the switch off.
608 blockAllThirdPartyRequestsSwitch.setChecked(false);
610 // Set the icon according to the theme.
611 if (MainWebViewActivity.darkTheme) {
612 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_disabled_dark));
614 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_disabled_light));
618 // Inflated a WebView to get the default user agent.
619 // `@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.
620 @SuppressLint("InflateParams") View bareWebViewLayout = inflater.inflate(R.layout.bare_webview, null, false);
621 WebView bareWebView = bareWebViewLayout.findViewById(R.id.bare_webview);
622 final String webViewDefaultUserAgentString = bareWebView.getSettings().getUserAgentString();
624 // Get a handle for the user agent array adapter. This array does not contain the `System default` entry.
625 ArrayAdapter<CharSequence> userAgentNamesArray = ArrayAdapter.createFromResource(context, R.array.user_agent_names, R.layout.domain_settings_spinner_item);
627 // Get the positions of the user agent and the default user agent.
628 int userAgentArrayPosition = userAgentNamesArray.getPosition(currentUserAgentName);
629 int defaultUserAgentArrayPosition = userAgentNamesArray.getPosition(defaultUserAgentName);
631 // Get a handle for the user agent data array. This array does not contain the `System default` entry.
632 String[] userAgentDataArray = resources.getStringArray(R.array.user_agent_data);
634 // Set the user agent text.
635 if (currentUserAgentName.equals(getString(R.string.system_default_user_agent))) { // Use the system default user agent.
636 // Set the user agent according to the system default.
637 switch (defaultUserAgentArrayPosition) {
638 case MainWebViewActivity.UNRECOGNIZED_USER_AGENT: // The default user agent name is not on the canonical list.
639 // This is probably because it was set in an older version of Privacy Browser before the switch to persistent user agent names.
640 userAgentTextView.setText(defaultUserAgentName);
643 case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
644 // Display the `WebView` default user agent.
645 userAgentTextView.setText(webViewDefaultUserAgentString);
648 case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
649 // Display the custom user agent.
650 userAgentTextView.setText(defaultCustomUserAgentString);
654 // Get the user agent string from the user agent data array.
655 userAgentTextView.setText(userAgentDataArray[defaultUserAgentArrayPosition]);
657 } else if (userAgentArrayPosition == MainWebViewActivity.UNRECOGNIZED_USER_AGENT) { // A custom user agent is stored in the current user agent name.
658 // Set the user agent spinner to `Custom user agent`.
659 userAgentSpinner.setSelection(MainWebViewActivity.DOMAINS_CUSTOM_USER_AGENT);
661 // Hide the user agent TextView.
662 userAgentTextView.setVisibility(View.GONE);
664 // Show the custom user agent EditText and set the current user agent name as the text.
665 customUserAgentEditText.setVisibility(View.VISIBLE);
666 customUserAgentEditText.setText(currentUserAgentName);
667 } else { // The user agent name contains one of the canonical user agents.
668 // 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.
669 userAgentSpinner.setSelection(userAgentArrayPosition + 1);
671 // Show the user agent TextView.
672 userAgentTextView.setVisibility(View.VISIBLE);
674 // Hide the custom user agent EditText.
675 customUserAgentEditText.setVisibility(View.GONE);
677 // Set the user agent text.
678 switch (userAgentArrayPosition) {
679 case MainWebViewActivity.DOMAINS_WEBVIEW_DEFAULT_USER_AGENT:
680 // Display the WebView default user agent.
681 userAgentTextView.setText(webViewDefaultUserAgentString);
685 // 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.
686 userAgentTextView.setText(userAgentDataArray[userAgentArrayPosition + 1]);
690 // Open the user agent spinner when the TextView is clicked.
691 userAgentTextView.setOnClickListener((View v) -> {
692 // Open the user agent spinner.
693 userAgentSpinner.performClick();
696 // Set the selected font size.
697 int fontSizeArrayPosition = fontSizeEntryValuesArrayAdapter.getPosition(String.valueOf(fontSizeInt));
698 fontSizeSpinner.setSelection(fontSizeArrayPosition);
700 // Set the default font size text.
701 int defaultFontSizeArrayPosition = fontSizeEntryValuesArrayAdapter.getPosition(defaultFontSizeString);
702 fontSizeTextView.setText(fontSizeArrayAdapter.getItem(defaultFontSizeArrayPosition));
704 // Set the display options for the font size TextView.
705 if (fontSizeArrayPosition == 0) { // System default font size is selected. Display `fontSizeTextView`.
706 fontSizeTextView.setVisibility(View.VISIBLE);
707 } else { // A custom font size is specified. Hide `fontSizeTextView`.
708 fontSizeTextView.setVisibility(View.GONE);
711 // Open the font size spinner when the TextView is clicked.
712 fontSizeTextView.setOnClickListener((View v) -> {
713 // Open the user agent spinner.
714 fontSizeSpinner.performClick();
717 // Display the swipe to refresh selection in the spinner.
718 swipeToRefreshSpinner.setSelection(swipeToRefreshInt);
720 // Set the swipe to refresh text.
721 if (defaultSwipeToRefreshBoolean) {
722 swipeToRefreshTextView.setText(swipeToRefreshArrayAdapter.getItem(DomainsDatabaseHelper.SWIPE_TO_REFRESH_ENABLED));
724 swipeToRefreshTextView.setText(swipeToRefreshArrayAdapter.getItem(DomainsDatabaseHelper.SWIPE_TO_REFRESH_DISABLED));
727 // 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.
728 switch (swipeToRefreshInt) {
729 case DomainsDatabaseHelper.SWIPE_TO_REFRESH_SYSTEM_DEFAULT:
730 if (defaultSwipeToRefreshBoolean) { // Swipe to refresh is enabled by default.
731 // Set the icon according to the theme.
732 if (MainWebViewActivity.darkTheme) {
733 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_dark));
735 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_light));
737 } else { // Swipe to refresh is disabled by default
738 // Set the icon according to the theme.
739 if (MainWebViewActivity.darkTheme) {
740 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_dark));
742 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_light));
746 // Show the swipe to refresh TextView.
747 swipeToRefreshTextView.setVisibility(View.VISIBLE);
750 case DomainsDatabaseHelper.SWIPE_TO_REFRESH_ENABLED:
751 // Set the icon according to the theme.
752 if (MainWebViewActivity.darkTheme) {
753 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_dark));
755 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_light));
758 // Hide the swipe to refresh TextView.`
759 swipeToRefreshTextView.setVisibility(View.GONE);
762 case DomainsDatabaseHelper.SWIPE_TO_REFRESH_DISABLED:
763 // Set the icon according to the theme.
764 if (MainWebViewActivity.darkTheme) {
765 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_dark));
767 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_light));
770 // Hide the swipe to refresh TextView.
771 swipeToRefreshTextView.setVisibility(View.GONE);
774 // Open the swipe to refresh spinner when the TextView is clicked.
775 swipeToRefreshTextView.setOnClickListener((View v) -> {
776 // Open the swipe to refresh spinner.
777 swipeToRefreshSpinner.performClick();
780 // Display the night mode in the spinner.
781 nightModeSpinner.setSelection(nightModeInt);
783 // Set the default night mode text.
784 if (defaultNightModeBoolean) {
785 nightModeTextView.setText(nightModeArrayAdapter.getItem(DomainsDatabaseHelper.NIGHT_MODE_ENABLED));
787 nightModeTextView.setText(nightModeArrayAdapter.getItem(DomainsDatabaseHelper.NIGHT_MODE_DISABLED));
790 // 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.
791 switch (nightModeInt) {
792 case DomainsDatabaseHelper.NIGHT_MODE_SYSTEM_DEFAULT:
793 if (defaultNightModeBoolean) { // Night mode enabled by default.
794 // Set the icon according to the theme.
795 if (MainWebViewActivity.darkTheme) {
796 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_dark));
798 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_light));
800 } else { // Night mode disabled by default.
801 // Set the icon according to the theme.
802 if (MainWebViewActivity.darkTheme) {
803 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_dark));
805 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_light));
809 // Show night mode TextView.
810 nightModeTextView.setVisibility(View.VISIBLE);
813 case DomainsDatabaseHelper.NIGHT_MODE_ENABLED:
814 // Set the icon according to the theme.
815 if (MainWebViewActivity.darkTheme) {
816 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_dark));
818 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_light));
821 // Hide the night mode TextView.
822 nightModeTextView.setVisibility(View.GONE);
825 case DomainsDatabaseHelper.NIGHT_MODE_DISABLED:
826 // Set the icon according to the theme.
827 if (MainWebViewActivity.darkTheme) {
828 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_dark));
830 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_light));
833 // Hide the night mode TextView.
834 nightModeTextView.setVisibility(View.GONE);
838 // Open the night mode spinner when the TextView is clicked.
839 nightModeTextView.setOnClickListener((View v) -> {
840 // Open the night mode spinner.
841 nightModeSpinner.performClick();
844 // Display the website images mode in the spinner.
845 displayWebpageImagesSpinner.setSelection(displayImagesInt);
847 // Set the default display images text.
848 if (defaultDisplayWebpageImagesBoolean) {
849 displayImagesTextView.setText(displayImagesArrayAdapter.getItem(DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_ENABLED));
851 displayImagesTextView.setText(displayImagesArrayAdapter.getItem(DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_DISABLED));
854 // 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.
855 switch (displayImagesInt) {
856 case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_SYSTEM_DEFAULT:
857 if (defaultDisplayWebpageImagesBoolean) { // Display webpage images enabled by default.
858 // Set the icon according to the theme.
859 if (MainWebViewActivity.darkTheme) {
860 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_dark));
862 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_light));
864 } else { // Display webpage images disabled by default.
865 // Set the icon according to the theme.
866 if (MainWebViewActivity.darkTheme) {
867 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_dark));
869 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_light));
873 // Show the display images TextView.
874 displayImagesTextView.setVisibility(View.VISIBLE);
877 case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_ENABLED:
878 // Set the icon according to the theme.
879 if (MainWebViewActivity.darkTheme) {
880 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_dark));
882 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_light));
885 // Hide the display images TextView.
886 displayImagesTextView.setVisibility(View.GONE);
889 case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_DISABLED:
890 // Set the icon according to the theme.
891 if (MainWebViewActivity.darkTheme) {
892 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_dark));
894 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_light));
897 // Hide the display images TextView.
898 displayImagesTextView.setVisibility(View.GONE);
902 // Open the display images spinner when the TextView is clicked.
903 displayImagesTextView.setOnClickListener((View v) -> {
904 // Open the user agent spinner.
905 displayWebpageImagesSpinner.performClick();
908 // Set the pinned SSL certificate icon.
909 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.
911 pinnedSslCertificateSwitch.setChecked(true);
913 // Set the icon according to the theme.
914 if (MainWebViewActivity.darkTheme) {
915 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_dark));
917 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_light));
919 } else { // Pinned SSL certificate is disabled.
920 // Uncheck the switch.
921 pinnedSslCertificateSwitch.setChecked(false);
923 // Set the icon according to the theme.
924 if (MainWebViewActivity.darkTheme) {
925 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_dark));
927 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_light));
931 // Store the current date.
932 Date currentDate = Calendar.getInstance().getTime();
934 // Setup the `StringBuilders` to display the general certificate information in blue. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
935 savedSslCertificateIssuedToONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), savedSslCertificateIssuedToONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
936 savedSslCertificateIssuedToUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), savedSslCertificateIssuedToUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
937 savedSslCertificateIssuedByCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), savedSslCertificateIssuedByCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
938 savedSslCertificateIssuedByONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), savedSslCertificateIssuedByONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
939 savedSslCertificateIssuedByUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), savedSslCertificateIssuedByUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
941 // Check the certificate `Common Name` against the domain name.
942 boolean savedSSlCertificateCommonNameMatchesDomainName = checkDomainNameAgainstCertificate(domainNameString, savedSslCertificateIssuedToCNameString);
944 // Format the `issuedToCommonName` color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
945 if (savedSSlCertificateCommonNameMatchesDomainName) {
946 savedSslCertificateIssuedToCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), savedSslCertificateIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
948 savedSslCertificateIssuedToCNameStringBuilder.setSpan(redColorSpan, cNameLabel.length(), savedSslCertificateIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
951 // Format the start date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
952 if ((savedSslCertificateStartDate != null) && savedSslCertificateStartDate.after(currentDate)) { // The certificate start date is in the future.
953 savedSslCertificateStartDateStringBuilder.setSpan(redColorSpan, startDateLabel.length(), savedSslCertificateStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
954 } else { // The certificate start date is in the past.
955 savedSslCertificateStartDateStringBuilder.setSpan(blueColorSpan, startDateLabel.length(), savedSslCertificateStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
958 // Format the end date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
959 if ((savedSslCertificateEndDate != null) && savedSslCertificateEndDate.before(currentDate)) { // The certificate end date is in the past.
960 savedSslCertificateEndDateStringBuilder.setSpan(redColorSpan, endDateLabel.length(), savedSslCertificateEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
961 } else { // The certificate end date is in the future.
962 savedSslCertificateEndDateStringBuilder.setSpan(blueColorSpan, endDateLabel.length(), savedSslCertificateEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
965 // Display the current website SSL certificate strings.
966 savedSslCertificateIssuedToCNameTextView.setText(savedSslCertificateIssuedToCNameStringBuilder);
967 savedSslCertificateIssuedToONameTextView.setText(savedSslCertificateIssuedToONameStringBuilder);
968 savedSslCertificateIssuedToUNameTextView.setText(savedSslCertificateIssuedToUNameStringBuilder);
969 savedSslCertificateIssuedByCNameTextView.setText(savedSslCertificateIssuedByCNameStringBuilder);
970 savedSslCertificateIssuedByONameTextView.setText(savedSslCertificateIssuedByONameStringBuilder);
971 savedSslCertificateIssuedByUNameTextView.setText(savedSslCertificateIssuedByUNameStringBuilder);
972 savedSslCertificateStartDateTextView.setText(savedSslCertificateStartDateStringBuilder);
973 savedSslCertificateEndDateTextView.setText(savedSslCertificateEndDateStringBuilder);
975 // Populate the current website SSL certificate if there is one.
976 if (currentWebsiteSslCertificate != null) {
977 // Get the strings from the SSL certificate.
978 String currentWebsiteCertificateIssuedToCNameString = currentWebsiteSslCertificate.getIssuedTo().getCName();
979 String currentWebsiteCertificateIssuedToONameString = currentWebsiteSslCertificate.getIssuedTo().getOName();
980 String currentWebsiteCertificateIssuedToUNameString = currentWebsiteSslCertificate.getIssuedTo().getUName();
981 String currentWebsiteCertificateIssuedByCNameString = currentWebsiteSslCertificate.getIssuedBy().getCName();
982 String currentWebsiteCertificateIssuedByONameString = currentWebsiteSslCertificate.getIssuedBy().getOName();
983 String currentWebsiteCertificateIssuedByUNameString = currentWebsiteSslCertificate.getIssuedBy().getUName();
984 Date currentWebsiteCertificateStartDate = currentWebsiteSslCertificate.getValidNotBeforeDate();
985 Date currentWebsiteCertificateEndDate = currentWebsiteSslCertificate.getValidNotAfterDate();
987 // Create a `SpannableStringBuilder` for each `TextView` that needs multiple colors of text.
988 SpannableStringBuilder currentWebsiteCertificateIssuedToCNameStringBuilder = new SpannableStringBuilder(cNameLabel + currentWebsiteCertificateIssuedToCNameString);
989 SpannableStringBuilder currentWebsiteCertificateIssuedToONameStringBuilder = new SpannableStringBuilder(oNameLabel + currentWebsiteCertificateIssuedToONameString);
990 SpannableStringBuilder currentWebsiteCertificateIssuedToUNameStringBuilder = new SpannableStringBuilder(uNameLabel + currentWebsiteCertificateIssuedToUNameString);
991 SpannableStringBuilder currentWebsiteCertificateIssuedByCNameStringBuilder = new SpannableStringBuilder(cNameLabel + currentWebsiteCertificateIssuedByCNameString);
992 SpannableStringBuilder currentWebsiteCertificateIssuedByONameStringBuilder = new SpannableStringBuilder(oNameLabel + currentWebsiteCertificateIssuedByONameString);
993 SpannableStringBuilder currentWebsiteCertificateIssuedByUNameStringBuilder = new SpannableStringBuilder(uNameLabel + currentWebsiteCertificateIssuedByUNameString);
994 SpannableStringBuilder currentWebsiteCertificateStartDateStringBuilder = new SpannableStringBuilder(startDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG)
995 .format(currentWebsiteCertificateStartDate));
996 SpannableStringBuilder currentWebsiteCertificateEndDateStringBuilder = new SpannableStringBuilder(endDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG)
997 .format(currentWebsiteCertificateEndDate));
999 // Setup the `StringBuilders` to display the general certificate information in blue. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1000 currentWebsiteCertificateIssuedToONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), currentWebsiteCertificateIssuedToONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1001 currentWebsiteCertificateIssuedToUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), currentWebsiteCertificateIssuedToUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1002 currentWebsiteCertificateIssuedByCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), currentWebsiteCertificateIssuedByCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1003 currentWebsiteCertificateIssuedByONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), currentWebsiteCertificateIssuedByONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1004 currentWebsiteCertificateIssuedByUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), currentWebsiteCertificateIssuedByUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1006 // Check the certificate `Common Name` against the domain name.
1007 boolean currentWebsiteCertificateCommonNameMatchesDomainName = checkDomainNameAgainstCertificate(domainNameString, currentWebsiteCertificateIssuedToCNameString);
1009 // Format the `issuedToCommonName` color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1010 if (currentWebsiteCertificateCommonNameMatchesDomainName) {
1011 currentWebsiteCertificateIssuedToCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), currentWebsiteCertificateIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1013 currentWebsiteCertificateIssuedToCNameStringBuilder.setSpan(redColorSpan, cNameLabel.length(), currentWebsiteCertificateIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1016 // Format the start date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1017 if (currentWebsiteCertificateStartDate.after(currentDate)) { // The certificate start date is in the future.
1018 currentWebsiteCertificateStartDateStringBuilder.setSpan(redColorSpan, startDateLabel.length(), currentWebsiteCertificateStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1019 } else { // The certificate start date is in the past.
1020 currentWebsiteCertificateStartDateStringBuilder.setSpan(blueColorSpan, startDateLabel.length(), currentWebsiteCertificateStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1023 // Format the end date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1024 if (currentWebsiteCertificateEndDate.before(currentDate)) { // The certificate end date is in the past.
1025 currentWebsiteCertificateEndDateStringBuilder.setSpan(redColorSpan, endDateLabel.length(), currentWebsiteCertificateEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1026 } else { // The certificate end date is in the future.
1027 currentWebsiteCertificateEndDateStringBuilder.setSpan(blueColorSpan, endDateLabel.length(), currentWebsiteCertificateEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1030 // Display the current website SSL certificate strings.
1031 currentWebsiteCertificateIssuedToCNameTextView.setText(currentWebsiteCertificateIssuedToCNameStringBuilder);
1032 currentWebsiteCertificateIssuedToONameTextView.setText(currentWebsiteCertificateIssuedToONameStringBuilder);
1033 currentWebsiteCertificateIssuedToUNameTextView.setText(currentWebsiteCertificateIssuedToUNameStringBuilder);
1034 currentWebsiteCertificateIssuedByCNameTextView.setText(currentWebsiteCertificateIssuedByCNameStringBuilder);
1035 currentWebsiteCertificateIssuedByONameTextView.setText(currentWebsiteCertificateIssuedByONameStringBuilder);
1036 currentWebsiteCertificateIssuedByUNameTextView.setText(currentWebsiteCertificateIssuedByUNameStringBuilder);
1037 currentWebsiteCertificateStartDateTextView.setText(currentWebsiteCertificateStartDateStringBuilder);
1038 currentWebsiteCertificateEndDateTextView.setText(currentWebsiteCertificateEndDateStringBuilder);
1041 // Set the initial display status for the SSL certificates.
1042 if (pinnedSslCertificateSwitch.isChecked()) {
1043 // Set the visibility of the saved SSL certificate.
1044 if (savedSslCertificateIssuedToCNameString == null) {
1045 savedSslCertificateLinearLayout.setVisibility(View.GONE);
1047 savedSslCertificateLinearLayout.setVisibility(View.VISIBLE);
1050 // Set the visibility of the current website SSL certificate.
1051 if (currentWebsiteSslCertificate == null) {
1052 // Hide the SSL certificate.
1053 currentWebsiteCertificateLinearLayout.setVisibility(View.GONE);
1055 // Show the instruction.
1056 noCurrentWebsiteCertificateTextView.setVisibility(View.VISIBLE);
1058 // Show the SSL certificate.
1059 currentWebsiteCertificateLinearLayout.setVisibility(View.VISIBLE);
1061 // Hide the instruction.
1062 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
1065 // Set the status of the radio buttons.
1066 if (savedSslCertificateLinearLayout.getVisibility() == View.VISIBLE) { // The saved SSL certificate is displayed.
1067 savedSslCertificateRadioButton.setChecked(true);
1068 currentWebsiteCertificateRadioButton.setChecked(false);
1069 } else if (currentWebsiteCertificateLinearLayout.getVisibility() == View.VISIBLE) { // The saved SSL certificate is hidden but the current website SSL certificate is visible.
1070 currentWebsiteCertificateRadioButton.setChecked(true);
1071 savedSslCertificateRadioButton.setChecked(false);
1072 } else { // Neither SSL certificate is visible.
1073 savedSslCertificateRadioButton.setChecked(false);
1074 currentWebsiteCertificateRadioButton.setChecked(false);
1076 } else { // `pinnedSslCertificateSwitch` is not checked.
1077 // Hide the SSl certificates and instructions.
1078 savedSslCertificateLinearLayout.setVisibility(View.GONE);
1079 currentWebsiteCertificateLinearLayout.setVisibility(View.GONE);
1080 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
1082 // Uncheck the radio buttons.
1083 savedSslCertificateRadioButton.setChecked(false);
1084 currentWebsiteCertificateRadioButton.setChecked(false);
1088 // Set the JavaScript switch listener.
1089 javaScriptEnabledSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1090 if (isChecked) { // JavaScript is enabled.
1091 // Update the JavaScript icon.
1092 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.javascript_enabled));
1094 // Enable the DOM storage `Switch`.
1095 domStorageEnabledSwitch.setEnabled(true);
1097 // Update the DOM storage icon.
1098 if (domStorageEnabledSwitch.isChecked()) { // DOM storage is enabled.
1099 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_enabled));
1100 } else { // DOM storage is disabled.
1101 // Set the icon according to the theme.
1102 if (MainWebViewActivity.darkTheme) {
1103 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_dark));
1105 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_light));
1108 } else { // JavaScript is disabled.
1109 // Update the JavaScript icon.
1110 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.privacy_mode));
1112 // Disable the DOM storage `Switch`.
1113 domStorageEnabledSwitch.setEnabled(false);
1115 // Set the DOM storage icon according to the theme.
1116 if (MainWebViewActivity.darkTheme) {
1117 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_dark));
1119 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_light));
1124 // Set the first-party cookies switch listener.
1125 firstPartyCookiesEnabledSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1126 if (isChecked) { // First-party cookies are enabled.
1127 // Update the first-party cookies icon.
1128 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_enabled));
1130 // Enable the third-party cookies switch.
1131 thirdPartyCookiesEnabledSwitch.setEnabled(true);
1133 // Update the third-party cookies icon.
1134 if (thirdPartyCookiesEnabledSwitch.isChecked()) { // Third-party cookies are enabled.
1135 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_warning));
1136 } else { // Third-party cookies are disabled.
1137 // Set the third-party cookies icon according to the theme.
1138 if (MainWebViewActivity.darkTheme) {
1139 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_dark));
1141 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_light));
1144 } else { // First-party cookies are disabled.
1145 // Update the first-party cookies icon according to the theme.
1146 if (MainWebViewActivity.darkTheme) {
1147 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_dark));
1149 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_light));
1152 // Disable the third-party cookies switch.
1153 thirdPartyCookiesEnabledSwitch.setEnabled(false);
1155 // Set the third-party cookies icon according to the theme.
1156 if (MainWebViewActivity.darkTheme) {
1157 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_ghosted_dark));
1159 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_ghosted_light));
1164 // Set the third-party cookies switch listener.
1165 thirdPartyCookiesEnabledSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1168 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_warning));
1170 // Update the third-party cookies icon according to the theme.
1171 if (MainWebViewActivity.darkTheme) {
1172 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_dark));
1174 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_light));
1179 // Set the DOM Storage switch listener.
1180 domStorageEnabledSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1183 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_enabled));
1185 // Set the icon according to the theme.
1186 if (MainWebViewActivity.darkTheme) {
1187 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_dark));
1189 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_light));
1194 // Set the form data switch listener. It can be removed once the minimum API >= 26.
1195 if (Build.VERSION.SDK_INT < 26) {
1196 formDataEnabledSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1199 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_enabled));
1201 // Set the icon according to the theme.
1202 if (MainWebViewActivity.darkTheme) {
1203 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_disabled_dark));
1205 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_disabled_light));
1211 // Set the EasyList switch listener.
1212 easyListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1214 if (isChecked) { // EasyList is on.
1215 // Set the icon according to the theme.
1216 if (MainWebViewActivity.darkTheme) {
1217 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_dark));
1219 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_light));
1221 } else { // EasyList is off.
1222 // Set the icon according to the theme.
1223 if (MainWebViewActivity.darkTheme) {
1224 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_dark));
1226 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_light));
1231 // Set the EasyPrivacy switch listener.
1232 easyPrivacySwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1234 if (isChecked) { // EasyPrivacy is on.
1235 // Set the icon according to the theme.
1236 if (MainWebViewActivity.darkTheme) {
1237 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_dark));
1239 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_light));
1241 } else { // EasyPrivacy is off.
1242 // Set the icon according to the theme.
1243 if (MainWebViewActivity.darkTheme) {
1244 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_dark));
1246 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_light));
1251 // Set the Fanboy's Annoyance List switch listener.
1252 fanboysAnnoyanceListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1253 // Update the icon and Fanboy's Social Blocking List.
1254 if (isChecked) { // Fanboy's Annoyance List is on.
1255 // Set the icon according to the theme.
1256 if (MainWebViewActivity.darkTheme) {
1257 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_dark));
1259 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_light));
1262 // Disable the Fanboy's Social Blocking List switch.
1263 fanboysSocialBlockingListSwitch.setEnabled(false);
1265 // Update the Fanboy's Social Blocking List icon according to the theme.
1266 if (MainWebViewActivity.darkTheme) {
1267 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_ghosted_dark));
1269 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_ghosted_light));
1271 } else { // Fanboy's Annoyance List is off.
1272 // Set the icon according to the theme.
1273 if (MainWebViewActivity.darkTheme) {
1274 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_dark));
1276 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_light));
1279 // Enable the Fanboy's Social Blocking List switch.
1280 fanboysSocialBlockingListSwitch.setEnabled(true);
1282 // Update the Fanboy's Social Blocking List icon.
1283 if (fanboysSocialBlockingListSwitch.isChecked()) { // Fanboy's Social Blocking List is on.
1284 // Update the icon according to the theme.
1285 if (MainWebViewActivity.darkTheme) {
1286 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_dark));
1288 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_light));
1290 } else { // Fanboy's Social Blocking List is off.
1291 // Update the icon according to the theme.
1292 if (MainWebViewActivity.darkTheme) {
1293 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_dark));
1295 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_light));
1302 // Set the Fanboy's Social Blocking List switch listener.
1303 fanboysSocialBlockingListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1305 if (isChecked) { // Fanboy's Social Blocking List is on.
1306 // Set the icon according to the theme.
1307 if (MainWebViewActivity.darkTheme) {
1308 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_dark));
1310 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_light));
1312 } else { // Fanboy's Social Blocking List is off.
1313 // Set the icon according to the theme.
1314 if (MainWebViewActivity.darkTheme) {
1315 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_dark));
1317 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_light));
1322 // Set the block all third-party requests switch listener.
1323 blockAllThirdPartyRequestsSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1325 if (isChecked) { // Blocking all third-party requests is on.
1326 // Set the icon according to the theme.
1327 if (MainWebViewActivity.darkTheme) {
1328 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_enabled_dark));
1330 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_enabled_light));
1332 } else { // Blocking all third-party requests is off.
1333 // Set the icon according to the theme.
1334 if (MainWebViewActivity.darkTheme) {
1335 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_disabled_dark));
1337 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_disabled_light));
1342 // Set the user agent spinner listener.
1343 userAgentSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1345 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1346 // Set the new user agent.
1348 case MainWebViewActivity.DOMAINS_SYSTEM_DEFAULT_USER_AGENT:
1349 // Show the user agent TextView.
1350 userAgentTextView.setVisibility(View.VISIBLE);
1352 // Hide the custom user agent EditText.
1353 customUserAgentEditText.setVisibility(View.GONE);
1355 // Set the user text.
1356 switch (defaultUserAgentArrayPosition) {
1357 case MainWebViewActivity.UNRECOGNIZED_USER_AGENT: // The default user agent name is not on the canonical list.
1358 // This is probably because it was set in an older version of Privacy Browser before the switch to persistent user agent names.
1359 userAgentTextView.setText(defaultUserAgentName);
1362 case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
1363 // Display the `WebView` default user agent.
1364 userAgentTextView.setText(webViewDefaultUserAgentString);
1367 case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
1368 // Display the custom user agent.
1369 userAgentTextView.setText(defaultCustomUserAgentString);
1373 // Get the user agent string from the user agent data array.
1374 userAgentTextView.setText(userAgentDataArray[defaultUserAgentArrayPosition]);
1378 case MainWebViewActivity.DOMAINS_WEBVIEW_DEFAULT_USER_AGENT:
1379 // Show the user agent TextView and set the text.
1380 userAgentTextView.setVisibility(View.VISIBLE);
1381 userAgentTextView.setText(webViewDefaultUserAgentString);
1383 // Hide the custom user agent EditTex.
1384 customUserAgentEditText.setVisibility(View.GONE);
1387 case MainWebViewActivity.DOMAINS_CUSTOM_USER_AGENT:
1388 // Hide the user agent TextView.
1389 userAgentTextView.setVisibility(View.GONE);
1391 // Show the custom user agent EditText and set the current user agent name as the text.
1392 customUserAgentEditText.setVisibility(View.VISIBLE);
1393 customUserAgentEditText.setText(currentUserAgentName);
1397 // 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.
1398 userAgentTextView.setVisibility(View.VISIBLE);
1399 userAgentTextView.setText(userAgentDataArray[position - 1]);
1401 // Hide `customUserAgentEditText`.
1402 customUserAgentEditText.setVisibility(View.GONE);
1407 public void onNothingSelected(AdapterView<?> parent) {
1412 // Set the font size spinner listener.
1413 fontSizeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1415 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1416 // Update the display options for `fontSizeTextView`.
1417 if (position == 0) { // System default font size has been selected. Display `fontSizeTextView`.
1418 fontSizeTextView.setVisibility(View.VISIBLE);
1419 } else { // A custom font size has been selected. Hide `fontSizeTextView`.
1420 fontSizeTextView.setVisibility(View.GONE);
1425 public void onNothingSelected(AdapterView<?> parent) {
1430 // Set the swipe to refresh spinner listener.
1431 swipeToRefreshSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1433 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1434 // 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.
1436 case DomainsDatabaseHelper.SWIPE_TO_REFRESH_SYSTEM_DEFAULT:
1437 if (defaultSwipeToRefreshBoolean) { // Swipe to refresh enabled by default.
1438 // Set the icon according to the theme.
1439 if (MainWebViewActivity.darkTheme) {
1440 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_dark));
1442 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_light));
1444 } else { // Swipe to refresh disabled by default.
1445 // Set the icon according to the theme.
1446 if (MainWebViewActivity.darkTheme) {
1447 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_dark));
1449 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_light));
1453 // Show the swipe to refresh TextView.
1454 swipeToRefreshTextView.setVisibility(View.VISIBLE);
1457 case DomainsDatabaseHelper.SWIPE_TO_REFRESH_ENABLED:
1458 // Set the icon according to the theme.
1459 if (MainWebViewActivity.darkTheme) {
1460 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_dark));
1462 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_light));
1465 // Hide the swipe to refresh TextView.
1466 swipeToRefreshTextView.setVisibility(View.GONE);
1469 case DomainsDatabaseHelper.SWIPE_TO_REFRESH_DISABLED:
1470 // Set the icon according to the theme.
1471 if (MainWebViewActivity.darkTheme) {
1472 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_dark));
1474 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_light));
1477 // Hide the swipe to refresh TextView.
1478 swipeToRefreshTextView.setVisibility(View.GONE);
1483 public void onNothingSelected(AdapterView<?> parent) {
1488 // Set the night mode spinner listener.
1489 nightModeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1491 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1492 // 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.
1494 case DomainsDatabaseHelper.NIGHT_MODE_SYSTEM_DEFAULT:
1495 if (defaultNightModeBoolean) { // Night mode enabled by default.
1496 // Set the icon according to the theme.
1497 if (MainWebViewActivity.darkTheme) {
1498 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_dark));
1500 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_light));
1502 } else { // Night mode disabled by default.
1503 // Set the icon according to the theme.
1504 if (MainWebViewActivity.darkTheme) {
1505 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_dark));
1507 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_light));
1511 // Show the night mode TextView.
1512 nightModeTextView.setVisibility(View.VISIBLE);
1515 case DomainsDatabaseHelper.NIGHT_MODE_ENABLED:
1516 // Set the icon according to the theme.
1517 if (MainWebViewActivity.darkTheme) {
1518 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_dark));
1520 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_light));
1523 // Hide `nightModeTextView`.
1524 nightModeTextView.setVisibility(View.GONE);
1527 case DomainsDatabaseHelper.NIGHT_MODE_DISABLED:
1528 // Set the icon according to the theme.
1529 if (MainWebViewActivity.darkTheme) {
1530 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_dark));
1532 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_light));
1535 // Hide `nightModeTextView`.
1536 nightModeTextView.setVisibility(View.GONE);
1540 // Create a `boolean` to store the current night mode setting.
1541 boolean currentNightModeEnabled = (position == DomainsDatabaseHelper.NIGHT_MODE_ENABLED) || ((position == DomainsDatabaseHelper.NIGHT_MODE_SYSTEM_DEFAULT) && defaultNightModeBoolean);
1543 // Disable the JavaScript `Switch` if night mode is enabled.
1544 if (currentNightModeEnabled) {
1545 javaScriptEnabledSwitch.setEnabled(false);
1547 javaScriptEnabledSwitch.setEnabled(true);
1550 // Update the JavaScript icon.
1551 if ((javaScriptEnabledInt == 1) || currentNightModeEnabled) {
1552 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.javascript_enabled));
1554 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.privacy_mode));
1557 // Update the DOM storage status.
1558 if ((javaScriptEnabledInt == 1) || currentNightModeEnabled) { // JavaScript is enabled.
1559 // Enable the DOM storage `Switch`.
1560 domStorageEnabledSwitch.setEnabled(true);
1562 // Set the DOM storage status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
1563 if (domStorageEnabledInt == 1) { // Both JavaScript and DOM storage are enabled.
1564 domStorageEnabledSwitch.setChecked(true);
1565 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_enabled));
1566 } else { // JavaScript is enabled but DOM storage is disabled.
1567 // Set the DOM storage switch to off.
1568 domStorageEnabledSwitch.setChecked(false);
1570 // Set the icon according to the theme.
1571 if (MainWebViewActivity.darkTheme) {
1572 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_dark));
1574 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_light));
1577 } else { // JavaScript is disabled.
1578 // Disable the DOM storage `Switch`.
1579 domStorageEnabledSwitch.setEnabled(false);
1581 // Set the checked status of DOM storage.
1582 if (domStorageEnabledInt == 1) { // DOM storage is enabled but JavaScript is disabled.
1583 domStorageEnabledSwitch.setChecked(true);
1584 } else { // Both JavaScript and DOM storage are disabled.
1585 domStorageEnabledSwitch.setChecked(false);
1588 // Set the icon according to the theme.
1589 if (MainWebViewActivity.darkTheme) {
1590 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_dark));
1592 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_light));
1598 public void onNothingSelected(AdapterView<?> parent) {
1603 // Set the display webpage images spinner listener.
1604 displayWebpageImagesSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1606 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1607 // Update the icon and the visibility of `displayImagesTextView`.
1609 case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_SYSTEM_DEFAULT:
1610 if (defaultDisplayWebpageImagesBoolean) {
1611 // Set the icon according to the theme.
1612 if (MainWebViewActivity.darkTheme) {
1613 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_dark));
1615 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_light));
1618 // Set the icon according to the theme.
1619 if (MainWebViewActivity.darkTheme) {
1620 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_dark));
1622 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_light));
1626 // Show `displayImagesTextView`.
1627 displayImagesTextView.setVisibility(View.VISIBLE);
1630 case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_ENABLED:
1631 // Set the icon according to the theme.
1632 if (MainWebViewActivity.darkTheme) {
1633 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_dark));
1635 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_light));
1638 // Hide `displayImagesTextView`.
1639 displayImagesTextView.setVisibility(View.GONE);
1642 case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_DISABLED:
1643 // Set the icon according to the theme.
1644 if (MainWebViewActivity.darkTheme) {
1645 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_dark));
1647 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_light));
1650 // Hide `displayImagesTextView`.
1651 displayImagesTextView.setVisibility(View.GONE);
1657 public void onNothingSelected(AdapterView<?> parent) {
1662 // Set the pinned SSL certificate switch listener.
1663 pinnedSslCertificateSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1665 if (isChecked) { // Pinned SSL certificate is enabled.
1666 // Set the icon according to the theme.
1667 if (MainWebViewActivity.darkTheme) {
1668 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_dark));
1670 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_light));
1673 // Update the visibility of the saved SSL certificate.
1674 if (savedSslCertificateIssuedToCNameString == null) {
1675 savedSslCertificateLinearLayout.setVisibility(View.GONE);
1677 savedSslCertificateLinearLayout.setVisibility(View.VISIBLE);
1680 // Update the visibility of the current website SSL certificate.
1681 if (currentWebsiteSslCertificate == null) {
1682 // Hide the SSL certificate.
1683 currentWebsiteCertificateLinearLayout.setVisibility(View.GONE);
1685 // Show the instruction.
1686 noCurrentWebsiteCertificateTextView.setVisibility(View.VISIBLE);
1688 // Show the SSL certificate.
1689 currentWebsiteCertificateLinearLayout.setVisibility(View.VISIBLE);
1691 // Hide the instruction.
1692 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
1695 // Set the status of the radio buttons.
1696 if (savedSslCertificateLinearLayout.getVisibility() == View.VISIBLE) { // The saved SSL certificate is displayed.
1697 savedSslCertificateRadioButton.setChecked(true);
1698 currentWebsiteCertificateRadioButton.setChecked(false);
1699 } else if (currentWebsiteCertificateLinearLayout.getVisibility() == View.VISIBLE) { // The saved SSL certificate is hidden but the current website SSL certificate is visible.
1700 currentWebsiteCertificateRadioButton.setChecked(true);
1701 savedSslCertificateRadioButton.setChecked(false);
1702 } else { // Neither SSL certificate is visible.
1703 savedSslCertificateRadioButton.setChecked(false);
1704 currentWebsiteCertificateRadioButton.setChecked(false);
1706 } else { // Pinned SSL certificate is disabled.
1707 // Set the icon according to the theme.
1708 if (MainWebViewActivity.darkTheme) {
1709 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_dark));
1711 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_light));
1714 // Hide the SSl certificates and instructions.
1715 savedSslCertificateLinearLayout.setVisibility(View.GONE);
1716 currentWebsiteCertificateLinearLayout.setVisibility(View.GONE);
1717 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
1719 // Uncheck the radio buttons.
1720 savedSslCertificateRadioButton.setChecked(false);
1721 currentWebsiteCertificateRadioButton.setChecked(false);
1725 savedSslCertificateLinearLayout.setOnClickListener((View v) -> {
1726 savedSslCertificateRadioButton.setChecked(true);
1727 currentWebsiteCertificateRadioButton.setChecked(false);
1730 savedSslCertificateRadioButton.setOnClickListener((View v) -> {
1731 savedSslCertificateRadioButton.setChecked(true);
1732 currentWebsiteCertificateRadioButton.setChecked(false);
1735 currentWebsiteCertificateLinearLayout.setOnClickListener((View v) -> {
1736 currentWebsiteCertificateRadioButton.setChecked(true);
1737 savedSslCertificateRadioButton.setChecked(false);
1740 currentWebsiteCertificateRadioButton.setOnClickListener((View v) -> {
1741 currentWebsiteCertificateRadioButton.setChecked(true);
1742 savedSslCertificateRadioButton.setChecked(false);
1745 return domainSettingsView;
1748 private boolean checkDomainNameAgainstCertificate(String domainName, String certificateCommonName) {
1749 // Initialize `domainNamesMatch`.
1750 boolean domainNamesMatch = false;
1752 // Check various wildcard permutations if `domainName` and `certificateCommonName` are not empty.
1753 // `noinspection ConstantCondition` removes Android Studio's incorrect lint warning that `domainName` can never be `null`.
1754 //noinspection ConstantConditions
1755 if ((domainName != null) && (certificateCommonName != null)) {
1756 // Check if the domains match.
1757 if (domainName.equals(certificateCommonName)) {
1758 domainNamesMatch = true;
1761 // If `domainName` starts with a wildcard, check the base domain against all the subdomains of `certificateCommonName`.
1762 if (!domainNamesMatch && domainName.startsWith("*.") && (domainName.length() > 2)) {
1763 // Remove the initial `*.`.
1764 String baseDomainName = domainName.substring(2);
1766 // Setup a copy of `certificateCommonName` to test subdomains.
1767 String certificateCommonNameSubdomain = certificateCommonName;
1769 // Check all the subdomains in `certificateCommonNameSubdomain` against `baseDomainName`.
1770 while (!domainNamesMatch && certificateCommonNameSubdomain.contains(".")) { // Stop checking if we know that `domainNamesMatch` is `true` or if we run out of `.`.
1771 // Test the `certificateCommonNameSubdomain` against `baseDomainName`.
1772 if (certificateCommonNameSubdomain.equals(baseDomainName)) {
1773 domainNamesMatch = true;
1776 // Strip out the lowest subdomain of `certificateCommonNameSubdomain`.
1778 certificateCommonNameSubdomain = certificateCommonNameSubdomain.substring(certificateCommonNameSubdomain.indexOf(".") + 1);
1779 } catch (IndexOutOfBoundsException e) { // `certificateCommonNameSubdomain` ends with `.`.
1780 certificateCommonNameSubdomain = "";
1785 // If `certificateCommonName` starts with a wildcard, check the base common name against all the subdomains of `domainName`.
1786 if (!domainNamesMatch && certificateCommonName.startsWith("*.") && (certificateCommonName.length() > 2)) {
1787 // Remove the initial `*.`.
1788 String baseCertificateCommonName = certificateCommonName.substring(2);
1790 // Setup a copy of `domainName` to test subdomains.
1791 String domainNameSubdomain = domainName;
1793 // Check all the subdomains in `domainNameSubdomain` against `baseCertificateCommonName`.
1794 while (!domainNamesMatch && domainNameSubdomain.contains(".") && (domainNameSubdomain.length() > 2)) {
1795 // Test the `domainNameSubdomain` against `baseCertificateCommonName`.
1796 if (domainNameSubdomain.equals(baseCertificateCommonName)) {
1797 domainNamesMatch = true;
1800 // Strip out the lowest subdomain of `domainNameSubdomain`.
1802 domainNameSubdomain = domainNameSubdomain.substring(domainNameSubdomain.indexOf(".") + 1);
1803 } catch (IndexOutOfBoundsException e) { // `domainNameSubdomain` ends with `.`.
1804 domainNameSubdomain = "";
1809 // If both names start with a wildcard, check if the root of one contains the root of the other.
1810 if (!domainNamesMatch && domainName.startsWith("*.") && (domainName.length() > 2) && certificateCommonName.startsWith("*.") && (certificateCommonName.length() > 2)) {
1811 // Remove the wildcards.
1812 String rootDomainName = domainName.substring(2);
1813 String rootCertificateCommonName = certificateCommonName.substring(2);
1815 // Check if one name ends with the contents of the other. If so, there will be overlap in the their wildcard subdomains.
1816 if (rootDomainName.endsWith(rootCertificateCommonName) || rootCertificateCommonName.endsWith(rootDomainName)) {
1817 domainNamesMatch = true;
1822 return domainNamesMatch;