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);
114 final ImageView formDataImageView = domainSettingsView.findViewById(R.id.domain_settings_form_data_imageview);
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 final Spinner userAgentSpinner = domainSettingsView.findViewById(R.id.domain_settings_user_agent_spinner);
124 final TextView userAgentTextView = domainSettingsView.findViewById(R.id.domain_settings_user_agent_textview);
125 final EditText customUserAgentEditText = domainSettingsView.findViewById(R.id.domain_settings_custom_user_agent_edittext);
126 final Spinner fontSizeSpinner = domainSettingsView.findViewById(R.id.domain_settings_font_size_spinner);
127 final TextView fontSizeTextView = domainSettingsView.findViewById(R.id.domain_settings_font_size_textview);
128 final ImageView swipeToRefreshImageView = domainSettingsView.findViewById(R.id.domain_settings_swipe_to_refresh_imageview);
129 final Spinner swipeToRefreshSpinner = domainSettingsView.findViewById(R.id.domain_settings_swipe_to_refresh_spinner);
130 final TextView swipeToRefreshTextView = domainSettingsView.findViewById(R.id.domain_settings_swipe_to_refresh_textview);
131 final ImageView nightModeImageView = domainSettingsView.findViewById(R.id.domain_settings_night_mode_imageview);
132 final Spinner nightModeSpinner = domainSettingsView.findViewById(R.id.domain_settings_night_mode_spinner);
133 final TextView nightModeTextView = domainSettingsView.findViewById(R.id.domain_settings_night_mode_textview);
134 final ImageView displayWebpageImagesImageView = domainSettingsView.findViewById(R.id.domain_settings_display_webpage_images_imageview);
135 final Spinner displayWebpageImagesSpinner = domainSettingsView.findViewById(R.id.domain_settings_display_webpage_images_spinner);
136 final TextView displayImagesTextView = domainSettingsView.findViewById(R.id.domain_settings_display_webpage_images_textview);
137 final ImageView pinnedSslCertificateImageView = domainSettingsView.findViewById(R.id.domain_settings_pinned_ssl_certificate_imageview);
138 Switch pinnedSslCertificateSwitch = domainSettingsView.findViewById(R.id.domain_settings_pinned_ssl_certificate_switch);
139 final LinearLayout savedSslCertificateLinearLayout = domainSettingsView.findViewById(R.id.saved_ssl_certificate_linearlayout);
140 final RadioButton savedSslCertificateRadioButton = domainSettingsView.findViewById(R.id.saved_ssl_certificate_radiobutton);
141 final TextView savedSslCertificateIssuedToCNameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_to_cname);
142 TextView savedSslCertificateIssuedToONameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_to_oname);
143 TextView savedSslCertificateIssuedToUNameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_to_uname);
144 TextView savedSslCertificateIssuedByCNameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_by_cname);
145 TextView savedSslCertificateIssuedByONameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_by_oname);
146 TextView savedSslCertificateIssuedByUNameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_by_uname);
147 TextView savedSslCertificateStartDateTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_start_date);
148 TextView savedSslCertificateEndDateTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_end_date);
149 final LinearLayout currentWebsiteCertificateLinearLayout = domainSettingsView.findViewById(R.id.current_website_certificate_linearlayout);
150 final RadioButton currentWebsiteCertificateRadioButton = domainSettingsView.findViewById(R.id.current_website_certificate_radiobutton);
151 final TextView currentWebsiteCertificateIssuedToCNameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_to_cname);
152 TextView currentWebsiteCertificateIssuedToONameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_to_oname);
153 TextView currentWebsiteCertificateIssuedToUNameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_to_uname);
154 TextView currentWebsiteCertificateIssuedByCNameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_by_cname);
155 TextView currentWebsiteCertificateIssuedByONameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_by_oname);
156 TextView currentWebsiteCertificateIssuedByUNameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_by_uname);
157 TextView currentWebsiteCertificateStartDateTextView = domainSettingsView.findViewById(R.id.current_website_certificate_start_date);
158 TextView currentWebsiteCertificateEndDateTextView = domainSettingsView.findViewById(R.id.current_website_certificate_end_date);
159 final TextView noCurrentWebsiteCertificateTextView = domainSettingsView.findViewById(R.id.no_current_website_certificate);
161 // Setup the SSL certificate labels.
162 final String cNameLabel = getString(R.string.common_name) + " ";
163 String oNameLabel = getString(R.string.organization) + " ";
164 String uNameLabel = getString(R.string.organizational_unit) + " ";
165 String startDateLabel = getString(R.string.start_date) + " ";
166 String endDateLabel = getString(R.string.end_date) + " ";
168 // Get the current website SSL certificate
169 final SslCertificate currentWebsiteSslCertificate = MainWebViewActivity.sslCertificate;
171 // Initialize the database handler. The `0` specifies the database version, but that is ignored and set instead using a constant in `DomainsDatabaseHelper`.
172 DomainsDatabaseHelper domainsDatabaseHelper = new DomainsDatabaseHelper(context, null, null, 0);
174 // Get the database `Cursor` for this ID and move it to the first row.
175 Cursor domainCursor = domainsDatabaseHelper.getCursorForId(databaseId);
176 domainCursor.moveToFirst();
178 // Save the `Cursor` entries as variables.
179 String domainNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.DOMAIN_NAME));
180 final int javaScriptEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_JAVASCRIPT));
181 int firstPartyCookiesEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FIRST_PARTY_COOKIES));
182 int thirdPartyCookiesEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_THIRD_PARTY_COOKIES));
183 final int domStorageEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_DOM_STORAGE));
184 int formDataEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FORM_DATA));
185 int easyListEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYLIST));
186 int easyPrivacyEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYPRIVACY));
187 int fanboysAnnoyanceListInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST));
188 int fanboysSocialBlockingListInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST));
189 final String currentUserAgentName = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.USER_AGENT));
190 int fontSizeInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.FONT_SIZE));
191 int swipeToRefreshInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.SWIPE_TO_REFRESH));
192 int nightModeInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.NIGHT_MODE));
193 int displayImagesInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.DISPLAY_IMAGES));
194 int pinnedSslCertificateInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.PINNED_SSL_CERTIFICATE));
195 final String savedSslCertificateIssuedToCNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_COMMON_NAME));
196 String savedSslCertificateIssuedToONameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATION));
197 String savedSslCertificateIssuedToUNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATIONAL_UNIT));
198 String savedSslCertificateIssuedByCNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_COMMON_NAME));
199 String savedSslCertificateIssuedByONameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATION));
200 String savedSslCertificateIssuedByUNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATIONAL_UNIT));
202 // Initialize the saved SSL certificate date variables.
203 Date savedSslCertificateStartDate = null;
204 Date savedSslCertificateEndDate = null;
206 // Only get the saved SSL certificate dates from the cursor if they are not set to `0`.
207 if (domainCursor.getLong(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_START_DATE)) != 0) {
208 savedSslCertificateStartDate = new Date(domainCursor.getLong(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_START_DATE)));
211 if (domainCursor.getLong(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_END_DATE)) != 0) {
212 savedSslCertificateEndDate = new Date(domainCursor.getLong(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_END_DATE)));
215 // Create `ArrayAdapters` for the `Spinners`and their `entry values`.
216 ArrayAdapter<CharSequence> translatedUserAgentArrayAdapter = ArrayAdapter.createFromResource(context, R.array.translated_domain_settings_user_agent_names, R.layout.domain_settings_spinner_item);
217 ArrayAdapter<CharSequence> fontSizeArrayAdapter = ArrayAdapter.createFromResource(context, R.array.domain_settings_font_size_entries, R.layout.domain_settings_spinner_item);
218 ArrayAdapter<CharSequence> fontSizeEntryValuesArrayAdapter = ArrayAdapter.createFromResource(context, R.array.domain_settings_font_size_entry_values, R.layout.domain_settings_spinner_item);
219 ArrayAdapter<CharSequence> swipeToRefreshArrayAdapter = ArrayAdapter.createFromResource(context, R.array.swipe_to_refresh_array, R.layout.domain_settings_spinner_item);
220 ArrayAdapter<CharSequence> nightModeArrayAdapter = ArrayAdapter.createFromResource(context, R.array.night_mode_array, R.layout.domain_settings_spinner_item);
221 ArrayAdapter<CharSequence> displayImagesArrayAdapter = ArrayAdapter.createFromResource(context, R.array.display_webpage_images_array, R.layout.domain_settings_spinner_item);
223 // Set the `DropDownViewResource` on the `Spinners`.
224 translatedUserAgentArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items);
225 fontSizeArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items);
226 swipeToRefreshArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items);
227 nightModeArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items);
228 displayImagesArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items);
230 // Set the `ArrayAdapters` for the `Spinners`.
231 userAgentSpinner.setAdapter(translatedUserAgentArrayAdapter);
232 fontSizeSpinner.setAdapter(fontSizeArrayAdapter);
233 swipeToRefreshSpinner.setAdapter(swipeToRefreshArrayAdapter);
234 nightModeSpinner.setAdapter(nightModeArrayAdapter);
235 displayWebpageImagesSpinner.setAdapter(displayImagesArrayAdapter);
237 // Create a `SpannableStringBuilder` for each `TextView` that needs multiple colors of text.
238 SpannableStringBuilder savedSslCertificateIssuedToCNameStringBuilder = new SpannableStringBuilder(cNameLabel + savedSslCertificateIssuedToCNameString);
239 SpannableStringBuilder savedSslCertificateIssuedToONameStringBuilder = new SpannableStringBuilder(oNameLabel + savedSslCertificateIssuedToONameString);
240 SpannableStringBuilder savedSslCertificateIssuedToUNameStringBuilder = new SpannableStringBuilder(uNameLabel + savedSslCertificateIssuedToUNameString);
241 SpannableStringBuilder savedSslCertificateIssuedByCNameStringBuilder = new SpannableStringBuilder(cNameLabel + savedSslCertificateIssuedByCNameString);
242 SpannableStringBuilder savedSslCertificateIssuedByONameStringBuilder = new SpannableStringBuilder(oNameLabel + savedSslCertificateIssuedByONameString);
243 SpannableStringBuilder savedSslCertificateIssuedByUNameStringBuilder = new SpannableStringBuilder(uNameLabel + savedSslCertificateIssuedByUNameString);
245 // Initialize the `SpannableStringBuilders` for the SSL certificate dates.
246 SpannableStringBuilder savedSslCertificateStartDateStringBuilder;
247 SpannableStringBuilder savedSslCertificateEndDateStringBuilder;
249 // Leave the SSL certificate dates empty if they are `null`.
250 if (savedSslCertificateStartDate == null) {
251 savedSslCertificateStartDateStringBuilder = new SpannableStringBuilder(startDateLabel);
253 savedSslCertificateStartDateStringBuilder = new SpannableStringBuilder(startDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG).format(savedSslCertificateStartDate));
256 if (savedSslCertificateEndDate == null) {
257 savedSslCertificateEndDateStringBuilder = new SpannableStringBuilder(endDateLabel);
259 savedSslCertificateEndDateStringBuilder = new SpannableStringBuilder(endDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG).format(savedSslCertificateEndDate));
262 // Create a red `ForegroundColorSpan`. We have to use the deprecated `getColor` until API >= 23.
263 final ForegroundColorSpan redColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.red_a700));
265 // Create a blue `ForegroundColorSpan`.
266 final ForegroundColorSpan blueColorSpan;
268 // Set `blueColorSpan` according to the theme. We have to use the deprecated `getColor()` until API >= 23.
269 if (MainWebViewActivity.darkTheme) {
270 //noinspection deprecation
271 blueColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.blue_400));
273 //noinspection deprecation
274 blueColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.blue_700));
277 // Set the domain name from the the database cursor.
278 domainNameEditText.setText(domainNameString);
280 // Update the certificates' `Common Name` color when the domain name text changes.
281 domainNameEditText.addTextChangedListener(new TextWatcher() {
283 public void beforeTextChanged(CharSequence s, int start, int count, int after) {
288 public void onTextChanged(CharSequence s, int start, int before, int count) {
293 public void afterTextChanged(Editable s) {
294 // Get the new domain name.
295 String newDomainName = domainNameEditText.getText().toString();
297 // Check the saved SSL certificate against the new domain name.
298 boolean savedSslCertificateMatchesNewDomainName = checkDomainNameAgainstCertificate(newDomainName, savedSslCertificateIssuedToCNameString);
300 // Create a `SpannableStringBuilder` for the saved certificate `Common Name`.
301 SpannableStringBuilder savedSslCertificateCommonNameStringBuilder = new SpannableStringBuilder(cNameLabel + savedSslCertificateIssuedToCNameString);
303 // Format the saved certificate `Common Name` color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
304 if (savedSslCertificateMatchesNewDomainName) {
305 savedSslCertificateCommonNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), savedSslCertificateCommonNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
307 savedSslCertificateCommonNameStringBuilder.setSpan(redColorSpan, cNameLabel.length(), savedSslCertificateCommonNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
310 // Update `savedSslCertificateIssuedToCNameTextView`.
311 savedSslCertificateIssuedToCNameTextView.setText(savedSslCertificateCommonNameStringBuilder);
313 // Update the current website certificate if it exists.
314 if (currentWebsiteSslCertificate != null) {
315 // Get the current website certificate `Common Name`.
316 String currentWebsiteCertificateCommonName = currentWebsiteSslCertificate.getIssuedTo().getCName();
318 // Check the current website certificate against the new domain name.
319 boolean currentWebsiteCertificateMatchesNewDomainName = checkDomainNameAgainstCertificate(newDomainName, currentWebsiteCertificateCommonName);
321 // Create a `SpannableStringBuilder` for the current website certificate `Common Name`.
322 SpannableStringBuilder currentWebsiteCertificateCommonNameStringBuilder = new SpannableStringBuilder(cNameLabel + currentWebsiteCertificateCommonName);
324 // Format the current certificate `Common Name` color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
325 if (currentWebsiteCertificateMatchesNewDomainName) {
326 currentWebsiteCertificateCommonNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), currentWebsiteCertificateCommonNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
328 currentWebsiteCertificateCommonNameStringBuilder.setSpan(redColorSpan, cNameLabel.length(), currentWebsiteCertificateCommonNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
331 // Update `currentWebsiteCertificateIssuedToCNameTextView`.
332 currentWebsiteCertificateIssuedToCNameTextView.setText(currentWebsiteCertificateCommonNameStringBuilder);
337 // Create a `boolean` to track if night mode is enabled.
338 boolean nightModeEnabled = (nightModeInt == DomainsDatabaseHelper.NIGHT_MODE_ENABLED) || ((nightModeInt == DomainsDatabaseHelper.NIGHT_MODE_SYSTEM_DEFAULT) && defaultNightModeBoolean);
340 // Disable the JavaScript switch if night mode is enabled.
341 if (nightModeEnabled) {
342 javaScriptEnabledSwitch.setEnabled(false);
344 javaScriptEnabledSwitch.setEnabled(true);
347 // Set the JavaScript icon.
348 if ((javaScriptEnabledInt == 1) || nightModeEnabled) {
349 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.javascript_enabled));
351 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.privacy_mode));
354 // Set the JavaScript switch status.
355 if (javaScriptEnabledInt == 1) { // JavaScript is enabled.
356 javaScriptEnabledSwitch.setChecked(true);
357 } else { // JavaScript is disabled.
358 javaScriptEnabledSwitch.setChecked(false);
361 // 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.
362 if (firstPartyCookiesEnabledInt == 1) { // First-party cookies are enabled.
363 firstPartyCookiesEnabledSwitch.setChecked(true);
364 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_enabled));
365 } else { // First-party cookies are disabled.
366 firstPartyCookiesEnabledSwitch.setChecked(false);
368 // Set the icon according to the theme.
369 if (MainWebViewActivity.darkTheme) {
370 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_dark));
372 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_light));
376 // Only display third-party cookies if SDK_INT >= 21.
377 if (Build.VERSION.SDK_INT >= 21) { // Third-party cookies can be configured for API >= 21.
378 // Only enable third-party-cookies if first-party cookies are enabled.
379 if (firstPartyCookiesEnabledInt == 1) { // First-party cookies are enabled.
380 // 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.
381 if (thirdPartyCookiesEnabledInt == 1) { // Both first-party and third-party cookies are enabled.
382 thirdPartyCookiesEnabledSwitch.setChecked(true);
383 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_warning));
384 } else { // First party cookies are enabled but third-party cookies are disabled.
385 thirdPartyCookiesEnabledSwitch.setChecked(false);
387 // Set the icon according to the theme.
388 if (MainWebViewActivity.darkTheme) {
389 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_dark));
391 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_light));
394 } else { // First-party cookies are disabled.
395 // Set the status of third-party cookies.
396 if (thirdPartyCookiesEnabledInt == 1) {
397 thirdPartyCookiesEnabledSwitch.setChecked(true);
399 thirdPartyCookiesEnabledSwitch.setChecked(false);
402 // Disable the third-party cookies switch.
403 thirdPartyCookiesEnabledSwitch.setEnabled(false);
405 // Set the icon according to the theme.
406 if (MainWebViewActivity.darkTheme) {
407 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_ghosted_dark));
409 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_ghosted_light));
412 } else { // Third-party cookies cannot be configured for API <= 21.
413 // Hide the LinearLayout for third-party cookies.
414 thirdPartyCookiesLinearLayout.setVisibility(View.GONE);
417 // Only enable DOM storage if JavaScript is enabled.
418 if ((javaScriptEnabledInt == 1) || nightModeEnabled) { // JavaScript is enabled.
419 // Enable the DOM storage `Switch`.
420 domStorageEnabledSwitch.setEnabled(true);
422 // Set the DOM storage status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
423 if (domStorageEnabledInt == 1) { // Both JavaScript and DOM storage are enabled.
424 domStorageEnabledSwitch.setChecked(true);
425 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_enabled));
426 } else { // JavaScript is enabled but DOM storage is disabled.
427 // Set the DOM storage switch to off.
428 domStorageEnabledSwitch.setChecked(false);
430 // Set the icon according to the theme.
431 if (MainWebViewActivity.darkTheme) {
432 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_dark));
434 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_light));
437 } else { // JavaScript is disabled.
438 // Disable the DOM storage `Switch`.
439 domStorageEnabledSwitch.setEnabled(false);
441 // Set the checked status of DOM storage.
442 if (domStorageEnabledInt == 1) { // DOM storage is enabled but JavaScript is disabled.
443 domStorageEnabledSwitch.setChecked(true);
444 } else { // Both JavaScript and DOM storage are disabled.
445 domStorageEnabledSwitch.setChecked(false);
448 // Set the icon according to the theme.
449 if (MainWebViewActivity.darkTheme) {
450 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_dark));
452 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_light));
456 // Set the form data status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
457 if (formDataEnabledInt == 1) { // Form data is on.
458 formDataEnabledSwitch.setChecked(true);
459 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_enabled));
460 } else { // Form data is off.
461 // Turn the form data switch to off.
462 formDataEnabledSwitch.setChecked(false);
464 // Set the icon according to the theme.
465 if (MainWebViewActivity.darkTheme) {
466 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_disabled_dark));
468 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_disabled_light));
472 // Set the EasyList status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
473 if (easyListEnabledInt == 1) { // EasyList is on.
474 // Turn the switch on.
475 easyListSwitch.setChecked(true);
477 // Set the icon according to the theme.
478 if (MainWebViewActivity.darkTheme) {
479 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_dark));
481 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_light));
483 } else { // EasyList is off.
484 // Turn the switch off.
485 easyListSwitch.setChecked(false);
487 // Set the icon according to the theme.
488 if (MainWebViewActivity.darkTheme) {
489 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_dark));
491 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_light));
495 // Set the EasyPrivacy status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
496 if (easyPrivacyEnabledInt == 1) { // EasyPrivacy is on.
497 // Turn the switch on.
498 easyPrivacySwitch.setChecked(true);
500 // Set the icon according to the theme.
501 if (MainWebViewActivity.darkTheme) {
502 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_dark));
504 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_light));
506 } else { // EasyPrivacy is off.
507 // Turn the switch off.
508 easyPrivacySwitch.setChecked(false);
510 // Set the icon according to the theme.
511 if (MainWebViewActivity.darkTheme) {
512 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_dark));
514 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_light));
518 // 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.
519 if (fanboysAnnoyanceListInt == 1) { // Fanboy's Annoyance List is on.
520 // Turn the switch on.
521 fanboysAnnoyanceListSwitch.setChecked(true);
523 // Set the icon according to the theme.
524 if (MainWebViewActivity.darkTheme) {
525 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_dark));
527 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_light));
529 } else { // Fanboy's Annoyance List is off.
530 // Turn the switch off.
531 fanboysAnnoyanceListSwitch.setChecked(false);
533 // Set the icon according to the theme.
534 if (MainWebViewActivity.darkTheme) {
535 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_dark));
537 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_light));
541 // Only enable Fanboy's Social Blocking List if Fanboy's Annoyance List is off.
542 if (fanboysAnnoyanceListInt == 0) { // Fanboy's Annoyance List is on.
543 // 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.
544 if (fanboysSocialBlockingListInt == 1) { // Fanboy's Social Blocking List is on.
545 // Enable the switch and turn it on.
546 fanboysSocialBlockingListSwitch.setEnabled(true);
547 fanboysSocialBlockingListSwitch.setChecked(true);
549 // Set the icon according to the theme.
550 if (MainWebViewActivity.darkTheme) {
551 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_dark));
553 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_light));
555 } else { // Fanboy's Social Blocking List is off.
556 // Enable the switch but turn it off.
557 fanboysSocialBlockingListSwitch.setEnabled(true);
558 fanboysSocialBlockingListSwitch.setChecked(false);
560 // Set the icon according to the theme.
561 if (MainWebViewActivity.darkTheme) {
562 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_dark));
564 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_light));
567 } else { // Fanboy's Annoyance List is on.
568 // 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.
569 if (fanboysSocialBlockingListInt == 1) { // Fanboy's Social Blocking List is on.
570 // Disable the switch but turn it on.
571 fanboysSocialBlockingListSwitch.setEnabled(false);
572 fanboysSocialBlockingListSwitch.setChecked(true);
573 } else { // Fanboy's Social Blocking List is off.
574 // Disable the switch and turn it off.
575 fanboysSocialBlockingListSwitch.setEnabled(false);
576 fanboysSocialBlockingListSwitch.setChecked(false);
579 // Set the icon according to the theme.
580 if (MainWebViewActivity.darkTheme) {
581 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_ghosted_dark));
583 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_ghosted_light));
587 // Inflated a WebView to get the default user agent.
588 // `@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.
589 @SuppressLint("InflateParams") View bareWebViewLayout = inflater.inflate(R.layout.bare_webview, null, false);
590 WebView bareWebView = bareWebViewLayout.findViewById(R.id.bare_webview);
591 final String webViewDefaultUserAgentString = bareWebView.getSettings().getUserAgentString();
593 // Get a handle for the user agent array adapter. This array does not contain the `System default` entry.
594 ArrayAdapter<CharSequence> userAgentNamesArray = ArrayAdapter.createFromResource(context, R.array.user_agent_names, R.layout.domain_settings_spinner_item);
596 // Get the positions of the user agent and the default user agent.
597 int userAgentArrayPosition = userAgentNamesArray.getPosition(currentUserAgentName);
598 int defaultUserAgentArrayPosition = userAgentNamesArray.getPosition(defaultUserAgentName);
600 // Get a handle for the user agent data array. This array does not contain the `System default` entry.
601 String[] userAgentDataArray = resources.getStringArray(R.array.user_agent_data);
603 // Set the user agent text.
604 if (currentUserAgentName.equals(getString(R.string.system_default_user_agent))) { // Use the system default user agent.
605 // Set the user agent according to the system default.
606 switch (defaultUserAgentArrayPosition) {
607 case MainWebViewActivity.UNRECOGNIZED_USER_AGENT: // The default user agent name is not on the canonical list.
608 // This is probably because it was set in an older version of Privacy Browser before the switch to persistent user agent names.
609 userAgentTextView.setText(defaultUserAgentName);
612 case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
613 // Display the `WebView` default user agent.
614 userAgentTextView.setText(webViewDefaultUserAgentString);
617 case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
618 // Display the custom user agent.
619 userAgentTextView.setText(defaultCustomUserAgentString);
623 // Get the user agent string from the user agent data array.
624 userAgentTextView.setText(userAgentDataArray[defaultUserAgentArrayPosition]);
626 } else if (userAgentArrayPosition == MainWebViewActivity.UNRECOGNIZED_USER_AGENT) { // A custom user agent is stored in the current user agent name.
627 // Set the user agent spinner to `Custom user agent`.
628 userAgentSpinner.setSelection(MainWebViewActivity.DOMAINS_CUSTOM_USER_AGENT);
630 // Hide the user agent TextView.
631 userAgentTextView.setVisibility(View.GONE);
633 // Show the custom user agent EditText and set the current user agent name as the text.
634 customUserAgentEditText.setVisibility(View.VISIBLE);
635 customUserAgentEditText.setText(currentUserAgentName);
636 } else { // The user agent name contains one of the canonical user agents.
637 // 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.
638 userAgentSpinner.setSelection(userAgentArrayPosition + 1);
640 // Show the user agent TextView.
641 userAgentTextView.setVisibility(View.VISIBLE);
643 // Hide the custom user agent EditText.
644 customUserAgentEditText.setVisibility(View.GONE);
646 // Set the user agent text.
647 switch (userAgentArrayPosition) {
648 case MainWebViewActivity.DOMAINS_WEBVIEW_DEFAULT_USER_AGENT:
649 // Display the WebView default user agent.
650 userAgentTextView.setText(webViewDefaultUserAgentString);
654 // 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.
655 userAgentTextView.setText(userAgentDataArray[userAgentArrayPosition + 1]);
659 // Open the user agent spinner when the TextView is clicked.
660 userAgentTextView.setOnClickListener((View v) -> {
661 // Open the user agent spinner.
662 userAgentSpinner.performClick();
665 // Set the selected font size.
666 int fontSizeArrayPosition = fontSizeEntryValuesArrayAdapter.getPosition(String.valueOf(fontSizeInt));
667 fontSizeSpinner.setSelection(fontSizeArrayPosition);
669 // Set the default font size text.
670 int defaultFontSizeArrayPosition = fontSizeEntryValuesArrayAdapter.getPosition(defaultFontSizeString);
671 fontSizeTextView.setText(fontSizeArrayAdapter.getItem(defaultFontSizeArrayPosition));
673 // Set the display options for the font size TextView.
674 if (fontSizeArrayPosition == 0) { // System default font size is selected. Display `fontSizeTextView`.
675 fontSizeTextView.setVisibility(View.VISIBLE);
676 } else { // A custom font size is specified. Hide `fontSizeTextView`.
677 fontSizeTextView.setVisibility(View.GONE);
680 // Open the font size spinner when the TextView is clicked.
681 fontSizeTextView.setOnClickListener((View v) -> {
682 // Open the user agent spinner.
683 fontSizeSpinner.performClick();
686 // Display the swipe to refresh selection in the spinner.
687 swipeToRefreshSpinner.setSelection(swipeToRefreshInt);
689 // Set the swipe to refresh text.
690 if (defaultSwipeToRefreshBoolean) {
691 swipeToRefreshTextView.setText(swipeToRefreshArrayAdapter.getItem(DomainsDatabaseHelper.SWIPE_TO_REFRESH_ENABLED));
693 swipeToRefreshTextView.setText(swipeToRefreshArrayAdapter.getItem(DomainsDatabaseHelper.SWIPE_TO_REFRESH_DISABLED));
696 // 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.
697 switch (swipeToRefreshInt) {
698 case DomainsDatabaseHelper.SWIPE_TO_REFRESH_SYSTEM_DEFAULT:
699 if (defaultSwipeToRefreshBoolean) { // Swipe to refresh is enabled by default.
700 // Set the icon according to the theme.
701 if (MainWebViewActivity.darkTheme) {
702 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_dark));
704 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_light));
706 } else { // Swipe to refresh is disabled by default
707 // Set the icon according to the theme.
708 if (MainWebViewActivity.darkTheme) {
709 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_dark));
711 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_light));
715 // Show the swipe to refresh TextView.
716 swipeToRefreshTextView.setVisibility(View.VISIBLE);
719 case DomainsDatabaseHelper.SWIPE_TO_REFRESH_ENABLED:
720 // Set the icon according to the theme.
721 if (MainWebViewActivity.darkTheme) {
722 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_dark));
724 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_light));
727 // Hide the swipe to refresh TextView.`
728 swipeToRefreshTextView.setVisibility(View.GONE);
731 case DomainsDatabaseHelper.SWIPE_TO_REFRESH_DISABLED:
732 // Set the icon according to the theme.
733 if (MainWebViewActivity.darkTheme) {
734 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_dark));
736 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_light));
739 // Hide the swipe to refresh TextView.
740 swipeToRefreshTextView.setVisibility(View.GONE);
743 // Open the swipe to refresh spinner when the TextView is clicked.
744 swipeToRefreshTextView.setOnClickListener((View v) -> {
745 // Open the swipe to refresh spinner.
746 swipeToRefreshSpinner.performClick();
749 // Display the night mode in the spinner.
750 nightModeSpinner.setSelection(nightModeInt);
752 // Set the default night mode text.
753 if (defaultNightModeBoolean) {
754 nightModeTextView.setText(nightModeArrayAdapter.getItem(DomainsDatabaseHelper.NIGHT_MODE_ENABLED));
756 nightModeTextView.setText(nightModeArrayAdapter.getItem(DomainsDatabaseHelper.NIGHT_MODE_DISABLED));
759 // 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.
760 switch (nightModeInt) {
761 case DomainsDatabaseHelper.NIGHT_MODE_SYSTEM_DEFAULT:
762 if (defaultNightModeBoolean) { // Night mode enabled by default.
763 // Set the icon according to the theme.
764 if (MainWebViewActivity.darkTheme) {
765 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_dark));
767 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_light));
769 } else { // Night mode disabled by default.
770 // Set the icon according to the theme.
771 if (MainWebViewActivity.darkTheme) {
772 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_dark));
774 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_light));
778 // Show night mode TextView.
779 nightModeTextView.setVisibility(View.VISIBLE);
782 case DomainsDatabaseHelper.NIGHT_MODE_ENABLED:
783 // Set the icon according to the theme.
784 if (MainWebViewActivity.darkTheme) {
785 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_dark));
787 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_light));
790 // Hide the night mode TextView.
791 nightModeTextView.setVisibility(View.GONE);
794 case DomainsDatabaseHelper.NIGHT_MODE_DISABLED:
795 // Set the icon according to the theme.
796 if (MainWebViewActivity.darkTheme) {
797 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_dark));
799 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_light));
802 // Hide the night mode TextView.
803 nightModeTextView.setVisibility(View.GONE);
807 // Open the night mode spinner when the TextView is clicked.
808 nightModeTextView.setOnClickListener((View v) -> {
809 // Open the night mode spinner.
810 nightModeSpinner.performClick();
813 // Display the website images mode in the spinner.
814 displayWebpageImagesSpinner.setSelection(displayImagesInt);
816 // Set the default display images text.
817 if (defaultDisplayWebpageImagesBoolean) {
818 displayImagesTextView.setText(displayImagesArrayAdapter.getItem(DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_ENABLED));
820 displayImagesTextView.setText(displayImagesArrayAdapter.getItem(DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_DISABLED));
823 // 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.
824 switch (displayImagesInt) {
825 case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_SYSTEM_DEFAULT:
826 if (defaultDisplayWebpageImagesBoolean) { // Display webpage images enabled by default.
827 // Set the icon according to the theme.
828 if (MainWebViewActivity.darkTheme) {
829 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_dark));
831 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_light));
833 } else { // Display webpage images disabled by default.
834 // Set the icon according to the theme.
835 if (MainWebViewActivity.darkTheme) {
836 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_dark));
838 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_light));
842 // Show the display images TextView.
843 displayImagesTextView.setVisibility(View.VISIBLE);
846 case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_ENABLED:
847 // Set the icon according to the theme.
848 if (MainWebViewActivity.darkTheme) {
849 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_dark));
851 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_light));
854 // Hide the display images TextView.
855 displayImagesTextView.setVisibility(View.GONE);
858 case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_DISABLED:
859 // Set the icon according to the theme.
860 if (MainWebViewActivity.darkTheme) {
861 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_dark));
863 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_light));
866 // Hide the display images TextView.
867 displayImagesTextView.setVisibility(View.GONE);
871 // Open the display images spinner when the TextView is clicked.
872 displayImagesTextView.setOnClickListener((View v) -> {
873 // Open the user agent spinner.
874 displayWebpageImagesSpinner.performClick();
877 // Set the pinned SSL certificate icon.
878 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.
880 pinnedSslCertificateSwitch.setChecked(true);
882 // Set the icon according to the theme.
883 if (MainWebViewActivity.darkTheme) {
884 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_dark));
886 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_light));
888 } else { // Pinned SSL certificate is disabled.
889 // Uncheck the switch.
890 pinnedSslCertificateSwitch.setChecked(false);
892 // Set the icon according to the theme.
893 if (MainWebViewActivity.darkTheme) {
894 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_dark));
896 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_light));
900 // Store the current date.
901 Date currentDate = Calendar.getInstance().getTime();
903 // Setup the `StringBuilders` to display the general certificate information in blue. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
904 savedSslCertificateIssuedToONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), savedSslCertificateIssuedToONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
905 savedSslCertificateIssuedToUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), savedSslCertificateIssuedToUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
906 savedSslCertificateIssuedByCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), savedSslCertificateIssuedByCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
907 savedSslCertificateIssuedByONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), savedSslCertificateIssuedByONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
908 savedSslCertificateIssuedByUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), savedSslCertificateIssuedByUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
910 // Check the certificate `Common Name` against the domain name.
911 boolean savedSSlCertificateCommonNameMatchesDomainName = checkDomainNameAgainstCertificate(domainNameString, savedSslCertificateIssuedToCNameString);
913 // Format the `issuedToCommonName` color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
914 if (savedSSlCertificateCommonNameMatchesDomainName) {
915 savedSslCertificateIssuedToCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), savedSslCertificateIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
917 savedSslCertificateIssuedToCNameStringBuilder.setSpan(redColorSpan, cNameLabel.length(), savedSslCertificateIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
920 // Format the start date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
921 if ((savedSslCertificateStartDate != null) && savedSslCertificateStartDate.after(currentDate)) { // The certificate start date is in the future.
922 savedSslCertificateStartDateStringBuilder.setSpan(redColorSpan, startDateLabel.length(), savedSslCertificateStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
923 } else { // The certificate start date is in the past.
924 savedSslCertificateStartDateStringBuilder.setSpan(blueColorSpan, startDateLabel.length(), savedSslCertificateStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
927 // Format the end date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
928 if ((savedSslCertificateEndDate != null) && savedSslCertificateEndDate.before(currentDate)) { // The certificate end date is in the past.
929 savedSslCertificateEndDateStringBuilder.setSpan(redColorSpan, endDateLabel.length(), savedSslCertificateEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
930 } else { // The certificate end date is in the future.
931 savedSslCertificateEndDateStringBuilder.setSpan(blueColorSpan, endDateLabel.length(), savedSslCertificateEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
934 // Display the current website SSL certificate strings.
935 savedSslCertificateIssuedToCNameTextView.setText(savedSslCertificateIssuedToCNameStringBuilder);
936 savedSslCertificateIssuedToONameTextView.setText(savedSslCertificateIssuedToONameStringBuilder);
937 savedSslCertificateIssuedToUNameTextView.setText(savedSslCertificateIssuedToUNameStringBuilder);
938 savedSslCertificateIssuedByCNameTextView.setText(savedSslCertificateIssuedByCNameStringBuilder);
939 savedSslCertificateIssuedByONameTextView.setText(savedSslCertificateIssuedByONameStringBuilder);
940 savedSslCertificateIssuedByUNameTextView.setText(savedSslCertificateIssuedByUNameStringBuilder);
941 savedSslCertificateStartDateTextView.setText(savedSslCertificateStartDateStringBuilder);
942 savedSslCertificateEndDateTextView.setText(savedSslCertificateEndDateStringBuilder);
944 // Populate the current website SSL certificate if there is one.
945 if (currentWebsiteSslCertificate != null) {
946 // Get the strings from the SSL certificate.
947 String currentWebsiteCertificateIssuedToCNameString = currentWebsiteSslCertificate.getIssuedTo().getCName();
948 String currentWebsiteCertificateIssuedToONameString = currentWebsiteSslCertificate.getIssuedTo().getOName();
949 String currentWebsiteCertificateIssuedToUNameString = currentWebsiteSslCertificate.getIssuedTo().getUName();
950 String currentWebsiteCertificateIssuedByCNameString = currentWebsiteSslCertificate.getIssuedBy().getCName();
951 String currentWebsiteCertificateIssuedByONameString = currentWebsiteSslCertificate.getIssuedBy().getOName();
952 String currentWebsiteCertificateIssuedByUNameString = currentWebsiteSslCertificate.getIssuedBy().getUName();
953 Date currentWebsiteCertificateStartDate = currentWebsiteSslCertificate.getValidNotBeforeDate();
954 Date currentWebsiteCertificateEndDate = currentWebsiteSslCertificate.getValidNotAfterDate();
956 // Create a `SpannableStringBuilder` for each `TextView` that needs multiple colors of text.
957 SpannableStringBuilder currentWebsiteCertificateIssuedToCNameStringBuilder = new SpannableStringBuilder(cNameLabel + currentWebsiteCertificateIssuedToCNameString);
958 SpannableStringBuilder currentWebsiteCertificateIssuedToONameStringBuilder = new SpannableStringBuilder(oNameLabel + currentWebsiteCertificateIssuedToONameString);
959 SpannableStringBuilder currentWebsiteCertificateIssuedToUNameStringBuilder = new SpannableStringBuilder(uNameLabel + currentWebsiteCertificateIssuedToUNameString);
960 SpannableStringBuilder currentWebsiteCertificateIssuedByCNameStringBuilder = new SpannableStringBuilder(cNameLabel + currentWebsiteCertificateIssuedByCNameString);
961 SpannableStringBuilder currentWebsiteCertificateIssuedByONameStringBuilder = new SpannableStringBuilder(oNameLabel + currentWebsiteCertificateIssuedByONameString);
962 SpannableStringBuilder currentWebsiteCertificateIssuedByUNameStringBuilder = new SpannableStringBuilder(uNameLabel + currentWebsiteCertificateIssuedByUNameString);
963 SpannableStringBuilder currentWebsiteCertificateStartDateStringBuilder = new SpannableStringBuilder(startDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG)
964 .format(currentWebsiteCertificateStartDate));
965 SpannableStringBuilder currentWebsiteCertificateEndDateStringBuilder = new SpannableStringBuilder(endDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG)
966 .format(currentWebsiteCertificateEndDate));
968 // Setup the `StringBuilders` to display the general certificate information in blue. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
969 currentWebsiteCertificateIssuedToONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), currentWebsiteCertificateIssuedToONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
970 currentWebsiteCertificateIssuedToUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), currentWebsiteCertificateIssuedToUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
971 currentWebsiteCertificateIssuedByCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), currentWebsiteCertificateIssuedByCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
972 currentWebsiteCertificateIssuedByONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), currentWebsiteCertificateIssuedByONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
973 currentWebsiteCertificateIssuedByUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), currentWebsiteCertificateIssuedByUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
975 // Check the certificate `Common Name` against the domain name.
976 boolean currentWebsiteCertificateCommonNameMatchesDomainName = checkDomainNameAgainstCertificate(domainNameString, currentWebsiteCertificateIssuedToCNameString);
978 // Format the `issuedToCommonName` color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
979 if (currentWebsiteCertificateCommonNameMatchesDomainName) {
980 currentWebsiteCertificateIssuedToCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), currentWebsiteCertificateIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
982 currentWebsiteCertificateIssuedToCNameStringBuilder.setSpan(redColorSpan, cNameLabel.length(), currentWebsiteCertificateIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
985 // Format the start date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
986 if (currentWebsiteCertificateStartDate.after(currentDate)) { // The certificate start date is in the future.
987 currentWebsiteCertificateStartDateStringBuilder.setSpan(redColorSpan, startDateLabel.length(), currentWebsiteCertificateStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
988 } else { // The certificate start date is in the past.
989 currentWebsiteCertificateStartDateStringBuilder.setSpan(blueColorSpan, startDateLabel.length(), currentWebsiteCertificateStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
992 // Format the end date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
993 if (currentWebsiteCertificateEndDate.before(currentDate)) { // The certificate end date is in the past.
994 currentWebsiteCertificateEndDateStringBuilder.setSpan(redColorSpan, endDateLabel.length(), currentWebsiteCertificateEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
995 } else { // The certificate end date is in the future.
996 currentWebsiteCertificateEndDateStringBuilder.setSpan(blueColorSpan, endDateLabel.length(), currentWebsiteCertificateEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
999 // Display the current website SSL certificate strings.
1000 currentWebsiteCertificateIssuedToCNameTextView.setText(currentWebsiteCertificateIssuedToCNameStringBuilder);
1001 currentWebsiteCertificateIssuedToONameTextView.setText(currentWebsiteCertificateIssuedToONameStringBuilder);
1002 currentWebsiteCertificateIssuedToUNameTextView.setText(currentWebsiteCertificateIssuedToUNameStringBuilder);
1003 currentWebsiteCertificateIssuedByCNameTextView.setText(currentWebsiteCertificateIssuedByCNameStringBuilder);
1004 currentWebsiteCertificateIssuedByONameTextView.setText(currentWebsiteCertificateIssuedByONameStringBuilder);
1005 currentWebsiteCertificateIssuedByUNameTextView.setText(currentWebsiteCertificateIssuedByUNameStringBuilder);
1006 currentWebsiteCertificateStartDateTextView.setText(currentWebsiteCertificateStartDateStringBuilder);
1007 currentWebsiteCertificateEndDateTextView.setText(currentWebsiteCertificateEndDateStringBuilder);
1010 // Set the initial display status for the SSL certificates.
1011 if (pinnedSslCertificateSwitch.isChecked()) {
1012 // Set the visibility of the saved SSL certificate.
1013 if (savedSslCertificateIssuedToCNameString == null) {
1014 savedSslCertificateLinearLayout.setVisibility(View.GONE);
1016 savedSslCertificateLinearLayout.setVisibility(View.VISIBLE);
1019 // Set the visibility of the current website SSL certificate.
1020 if (currentWebsiteSslCertificate == null) {
1021 // Hide the SSL certificate.
1022 currentWebsiteCertificateLinearLayout.setVisibility(View.GONE);
1024 // Show the instruction.
1025 noCurrentWebsiteCertificateTextView.setVisibility(View.VISIBLE);
1027 // Show the SSL certificate.
1028 currentWebsiteCertificateLinearLayout.setVisibility(View.VISIBLE);
1030 // Hide the instruction.
1031 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
1034 // Set the status of the radio buttons.
1035 if (savedSslCertificateLinearLayout.getVisibility() == View.VISIBLE) { // The saved SSL certificate is displayed.
1036 savedSslCertificateRadioButton.setChecked(true);
1037 currentWebsiteCertificateRadioButton.setChecked(false);
1038 } else if (currentWebsiteCertificateLinearLayout.getVisibility() == View.VISIBLE) { // The saved SSL certificate is hidden but the current website SSL certificate is visible.
1039 currentWebsiteCertificateRadioButton.setChecked(true);
1040 savedSslCertificateRadioButton.setChecked(false);
1041 } else { // Neither SSL certificate is visible.
1042 savedSslCertificateRadioButton.setChecked(false);
1043 currentWebsiteCertificateRadioButton.setChecked(false);
1045 } else { // `pinnedSslCertificateSwitch` is not checked.
1046 // Hide the SSl certificates and instructions.
1047 savedSslCertificateLinearLayout.setVisibility(View.GONE);
1048 currentWebsiteCertificateLinearLayout.setVisibility(View.GONE);
1049 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
1051 // Uncheck the radio buttons.
1052 savedSslCertificateRadioButton.setChecked(false);
1053 currentWebsiteCertificateRadioButton.setChecked(false);
1057 // Set the JavaScript switch listener.
1058 javaScriptEnabledSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1059 if (isChecked) { // JavaScript is enabled.
1060 // Update the JavaScript icon.
1061 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.javascript_enabled));
1063 // Enable the DOM storage `Switch`.
1064 domStorageEnabledSwitch.setEnabled(true);
1066 // Update the DOM storage icon.
1067 if (domStorageEnabledSwitch.isChecked()) { // DOM storage is enabled.
1068 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_enabled));
1069 } else { // DOM storage is disabled.
1070 // Set the icon according to the theme.
1071 if (MainWebViewActivity.darkTheme) {
1072 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_dark));
1074 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_light));
1077 } else { // JavaScript is disabled.
1078 // Update the JavaScript icon.
1079 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.privacy_mode));
1081 // Disable the DOM storage `Switch`.
1082 domStorageEnabledSwitch.setEnabled(false);
1084 // Set the DOM storage icon according to the theme.
1085 if (MainWebViewActivity.darkTheme) {
1086 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_dark));
1088 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_light));
1093 // Set the first-party cookies switch listener.
1094 firstPartyCookiesEnabledSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1095 if (isChecked) { // First-party cookies are enabled.
1096 // Update the first-party cookies icon.
1097 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_enabled));
1099 // Enable the third-party cookies switch.
1100 thirdPartyCookiesEnabledSwitch.setEnabled(true);
1102 // Update the third-party cookies icon.
1103 if (thirdPartyCookiesEnabledSwitch.isChecked()) { // Third-party cookies are enabled.
1104 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_warning));
1105 } else { // Third-party cookies are disabled.
1106 // Set the third-party cookies icon according to the theme.
1107 if (MainWebViewActivity.darkTheme) {
1108 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_dark));
1110 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_light));
1113 } else { // First-party cookies are disabled.
1114 // Update the first-party cookies icon according to the theme.
1115 if (MainWebViewActivity.darkTheme) {
1116 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_dark));
1118 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_light));
1121 // Disable the third-party cookies switch.
1122 thirdPartyCookiesEnabledSwitch.setEnabled(false);
1124 // Set the third-party cookies icon according to the theme.
1125 if (MainWebViewActivity.darkTheme) {
1126 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_ghosted_dark));
1128 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_ghosted_light));
1133 // Set the third-party cookies switch listener.
1134 thirdPartyCookiesEnabledSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1137 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_warning));
1139 // Update the third-party cookies icon according to the theme.
1140 if (MainWebViewActivity.darkTheme) {
1141 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_dark));
1143 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_light));
1148 // Set the DOM Storage switch listener.
1149 domStorageEnabledSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1152 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_enabled));
1154 // Set the icon according to the theme.
1155 if (MainWebViewActivity.darkTheme) {
1156 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_dark));
1158 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_light));
1163 // Set the form data switch listener.
1164 formDataEnabledSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1167 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_enabled));
1169 // Set the icon according to the theme.
1170 if (MainWebViewActivity.darkTheme) {
1171 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_disabled_dark));
1173 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_disabled_light));
1178 // Set the EasyList switch listener.
1179 easyListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1181 if (isChecked) { // EasyList is on.
1182 // Set the icon according to the theme.
1183 if (MainWebViewActivity.darkTheme) {
1184 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_dark));
1186 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_light));
1188 } else { // EasyList is off.
1189 // Set the icon according to the theme.
1190 if (MainWebViewActivity.darkTheme) {
1191 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_dark));
1193 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_light));
1198 // Set the EasyPrivacy switch listener.
1199 easyPrivacySwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1201 if (isChecked) { // EasyPrivacy is on.
1202 // Set the icon according to the theme.
1203 if (MainWebViewActivity.darkTheme) {
1204 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_dark));
1206 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_light));
1208 } else { // EasyPrivacy is off.
1209 // Set the icon according to the theme.
1210 if (MainWebViewActivity.darkTheme) {
1211 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_dark));
1213 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_light));
1218 // Set the Fanboy's Annoyance List switch listener.
1219 fanboysAnnoyanceListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1220 // Update the icon and Fanboy's Social Blocking List.
1221 if (isChecked) { // Fanboy's Annoyance List is on.
1222 // Set the icon according to the theme.
1223 if (MainWebViewActivity.darkTheme) {
1224 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_dark));
1226 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_light));
1229 // Disable the Fanboy's Social Blocking List switch.
1230 fanboysSocialBlockingListSwitch.setEnabled(false);
1232 // Update the Fanboy's Social Blocking List icon according to the theme.
1233 if (MainWebViewActivity.darkTheme) {
1234 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_ghosted_dark));
1236 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_ghosted_light));
1238 } else { // Fanboy's Annoyance List is off.
1239 // Set the icon according to the theme.
1240 if (MainWebViewActivity.darkTheme) {
1241 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_dark));
1243 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_light));
1246 // Enable the Fanboy's Social Blocking List switch.
1247 fanboysSocialBlockingListSwitch.setEnabled(true);
1249 // Update the Fanboy's Social Blocking List icon.
1250 if (fanboysSocialBlockingListSwitch.isChecked()) { // Fanboy's Social Blocking List is on.
1251 // Update the icon according to the theme.
1252 if (MainWebViewActivity.darkTheme) {
1253 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_dark));
1255 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_light));
1257 } else { // Fanboy's Social Blocking List is off.
1258 // Update the icon according to the theme.
1259 if (MainWebViewActivity.darkTheme) {
1260 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_dark));
1262 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_light));
1269 // Set the Fanboy's Social Blocking List switch listener.
1270 fanboysSocialBlockingListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1272 if (isChecked) { // Fanboy's Social Blocking List is on.
1273 // Set the icon according to the theme.
1274 if (MainWebViewActivity.darkTheme) {
1275 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_dark));
1277 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_light));
1279 } else { // Fanboy's Social Blocking List is off.
1280 // Set the icon according to the theme.
1281 if (MainWebViewActivity.darkTheme) {
1282 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_dark));
1284 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_light));
1289 // Set the user agent spinner listener.
1290 userAgentSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1292 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1293 // Set the new user agent.
1295 case MainWebViewActivity.DOMAINS_SYSTEM_DEFAULT_USER_AGENT:
1296 // Show the user agent TextView.
1297 userAgentTextView.setVisibility(View.VISIBLE);
1299 // Hide the custom user agent EditText.
1300 customUserAgentEditText.setVisibility(View.GONE);
1302 // Set the user text.
1303 switch (defaultUserAgentArrayPosition) {
1304 case MainWebViewActivity.UNRECOGNIZED_USER_AGENT: // The default user agent name is not on the canonical list.
1305 // This is probably because it was set in an older version of Privacy Browser before the switch to persistent user agent names.
1306 userAgentTextView.setText(defaultUserAgentName);
1309 case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
1310 // Display the `WebView` default user agent.
1311 userAgentTextView.setText(webViewDefaultUserAgentString);
1314 case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
1315 // Display the custom user agent.
1316 userAgentTextView.setText(defaultCustomUserAgentString);
1320 // Get the user agent string from the user agent data array.
1321 userAgentTextView.setText(userAgentDataArray[defaultUserAgentArrayPosition]);
1325 case MainWebViewActivity.DOMAINS_WEBVIEW_DEFAULT_USER_AGENT:
1326 // Show the user agent TextView and set the text.
1327 userAgentTextView.setVisibility(View.VISIBLE);
1328 userAgentTextView.setText(webViewDefaultUserAgentString);
1330 // Hide the custom user agent EditTex.
1331 customUserAgentEditText.setVisibility(View.GONE);
1334 case MainWebViewActivity.DOMAINS_CUSTOM_USER_AGENT:
1335 // Hide the user agent TextView.
1336 userAgentTextView.setVisibility(View.GONE);
1338 // Show the custom user agent EditText and set the current user agent name as the text.
1339 customUserAgentEditText.setVisibility(View.VISIBLE);
1340 customUserAgentEditText.setText(currentUserAgentName);
1344 // 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.
1345 userAgentTextView.setVisibility(View.VISIBLE);
1346 userAgentTextView.setText(userAgentDataArray[position - 1]);
1348 // Hide `customUserAgentEditText`.
1349 customUserAgentEditText.setVisibility(View.GONE);
1354 public void onNothingSelected(AdapterView<?> parent) {
1359 // Set the font size spinner listener.
1360 fontSizeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1362 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1363 // Update the display options for `fontSizeTextView`.
1364 if (position == 0) { // System default font size has been selected. Display `fontSizeTextView`.
1365 fontSizeTextView.setVisibility(View.VISIBLE);
1366 } else { // A custom font size has been selected. Hide `fontSizeTextView`.
1367 fontSizeTextView.setVisibility(View.GONE);
1372 public void onNothingSelected(AdapterView<?> parent) {
1377 // Set the swipe to refresh spinner listener.
1378 swipeToRefreshSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1380 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1381 // 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.
1383 case DomainsDatabaseHelper.SWIPE_TO_REFRESH_SYSTEM_DEFAULT:
1384 if (defaultSwipeToRefreshBoolean) { // Swipe to refresh enabled by default.
1385 // Set the icon according to the theme.
1386 if (MainWebViewActivity.darkTheme) {
1387 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_dark));
1389 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_light));
1391 } else { // Swipe to refresh disabled by default.
1392 // Set the icon according to the theme.
1393 if (MainWebViewActivity.darkTheme) {
1394 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_dark));
1396 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_light));
1400 // Show the swipe to refresh TextView.
1401 swipeToRefreshTextView.setVisibility(View.VISIBLE);
1404 case DomainsDatabaseHelper.SWIPE_TO_REFRESH_ENABLED:
1405 // Set the icon according to the theme.
1406 if (MainWebViewActivity.darkTheme) {
1407 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_dark));
1409 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_light));
1412 // Hide the swipe to refresh TextView.
1413 swipeToRefreshTextView.setVisibility(View.GONE);
1416 case DomainsDatabaseHelper.SWIPE_TO_REFRESH_DISABLED:
1417 // Set the icon according to the theme.
1418 if (MainWebViewActivity.darkTheme) {
1419 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_dark));
1421 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_light));
1424 // Hide the swipe to refresh TextView.
1425 swipeToRefreshTextView.setVisibility(View.GONE);
1430 public void onNothingSelected(AdapterView<?> parent) {
1435 // Set the night mode spinner listener.
1436 nightModeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1438 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1439 // 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.
1441 case DomainsDatabaseHelper.NIGHT_MODE_SYSTEM_DEFAULT:
1442 if (defaultNightModeBoolean) { // Night mode enabled by default.
1443 // Set the icon according to the theme.
1444 if (MainWebViewActivity.darkTheme) {
1445 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_dark));
1447 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_light));
1449 } else { // Night mode disabled by default.
1450 // Set the icon according to the theme.
1451 if (MainWebViewActivity.darkTheme) {
1452 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_dark));
1454 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_light));
1458 // Show the night mode TextView.
1459 nightModeTextView.setVisibility(View.VISIBLE);
1462 case DomainsDatabaseHelper.NIGHT_MODE_ENABLED:
1463 // Set the icon according to the theme.
1464 if (MainWebViewActivity.darkTheme) {
1465 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_dark));
1467 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_light));
1470 // Hide `nightModeTextView`.
1471 nightModeTextView.setVisibility(View.GONE);
1474 case DomainsDatabaseHelper.NIGHT_MODE_DISABLED:
1475 // Set the icon according to the theme.
1476 if (MainWebViewActivity.darkTheme) {
1477 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_dark));
1479 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_light));
1482 // Hide `nightModeTextView`.
1483 nightModeTextView.setVisibility(View.GONE);
1487 // Create a `boolean` to store the current night mode setting.
1488 boolean currentNightModeEnabled = (position == DomainsDatabaseHelper.NIGHT_MODE_ENABLED) || ((position == DomainsDatabaseHelper.NIGHT_MODE_SYSTEM_DEFAULT) && defaultNightModeBoolean);
1490 // Disable the JavaScript `Switch` if night mode is enabled.
1491 if (currentNightModeEnabled) {
1492 javaScriptEnabledSwitch.setEnabled(false);
1494 javaScriptEnabledSwitch.setEnabled(true);
1497 // Update the JavaScript icon.
1498 if ((javaScriptEnabledInt == 1) || currentNightModeEnabled) {
1499 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.javascript_enabled));
1501 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.privacy_mode));
1504 // Update the DOM storage status.
1505 if ((javaScriptEnabledInt == 1) || currentNightModeEnabled) { // JavaScript is enabled.
1506 // Enable the DOM storage `Switch`.
1507 domStorageEnabledSwitch.setEnabled(true);
1509 // Set the DOM storage status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
1510 if (domStorageEnabledInt == 1) { // Both JavaScript and DOM storage are enabled.
1511 domStorageEnabledSwitch.setChecked(true);
1512 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_enabled));
1513 } else { // JavaScript is enabled but DOM storage is disabled.
1514 // Set the DOM storage switch to off.
1515 domStorageEnabledSwitch.setChecked(false);
1517 // Set the icon according to the theme.
1518 if (MainWebViewActivity.darkTheme) {
1519 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_dark));
1521 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_light));
1524 } else { // JavaScript is disabled.
1525 // Disable the DOM storage `Switch`.
1526 domStorageEnabledSwitch.setEnabled(false);
1528 // Set the checked status of DOM storage.
1529 if (domStorageEnabledInt == 1) { // DOM storage is enabled but JavaScript is disabled.
1530 domStorageEnabledSwitch.setChecked(true);
1531 } else { // Both JavaScript and DOM storage are disabled.
1532 domStorageEnabledSwitch.setChecked(false);
1535 // Set the icon according to the theme.
1536 if (MainWebViewActivity.darkTheme) {
1537 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_dark));
1539 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_light));
1545 public void onNothingSelected(AdapterView<?> parent) {
1550 // Set the display webpage images spinner listener.
1551 displayWebpageImagesSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1553 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1554 // Update the icon and the visibility of `displayImagesTextView`.
1556 case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_SYSTEM_DEFAULT:
1557 if (defaultDisplayWebpageImagesBoolean) {
1558 // Set the icon according to the theme.
1559 if (MainWebViewActivity.darkTheme) {
1560 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_dark));
1562 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_light));
1565 // Set the icon according to the theme.
1566 if (MainWebViewActivity.darkTheme) {
1567 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_dark));
1569 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_light));
1573 // Show `displayImagesTextView`.
1574 displayImagesTextView.setVisibility(View.VISIBLE);
1577 case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_ENABLED:
1578 // Set the icon according to the theme.
1579 if (MainWebViewActivity.darkTheme) {
1580 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_dark));
1582 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_light));
1585 // Hide `displayImagesTextView`.
1586 displayImagesTextView.setVisibility(View.GONE);
1589 case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_DISABLED:
1590 // Set the icon according to the theme.
1591 if (MainWebViewActivity.darkTheme) {
1592 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_dark));
1594 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_light));
1597 // Hide `displayImagesTextView`.
1598 displayImagesTextView.setVisibility(View.GONE);
1604 public void onNothingSelected(AdapterView<?> parent) {
1609 // Set the pinned SSL certificate switch listener.
1610 pinnedSslCertificateSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1612 if (isChecked) { // Pinned SSL certificate is enabled.
1613 // Set the icon according to the theme.
1614 if (MainWebViewActivity.darkTheme) {
1615 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_dark));
1617 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_light));
1620 // Update the visibility of the saved SSL certificate.
1621 if (savedSslCertificateIssuedToCNameString == null) {
1622 savedSslCertificateLinearLayout.setVisibility(View.GONE);
1624 savedSslCertificateLinearLayout.setVisibility(View.VISIBLE);
1627 // Update the visibility of the current website SSL certificate.
1628 if (currentWebsiteSslCertificate == null) {
1629 // Hide the SSL certificate.
1630 currentWebsiteCertificateLinearLayout.setVisibility(View.GONE);
1632 // Show the instruction.
1633 noCurrentWebsiteCertificateTextView.setVisibility(View.VISIBLE);
1635 // Show the SSL certificate.
1636 currentWebsiteCertificateLinearLayout.setVisibility(View.VISIBLE);
1638 // Hide the instruction.
1639 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
1642 // Set the status of the radio buttons.
1643 if (savedSslCertificateLinearLayout.getVisibility() == View.VISIBLE) { // The saved SSL certificate is displayed.
1644 savedSslCertificateRadioButton.setChecked(true);
1645 currentWebsiteCertificateRadioButton.setChecked(false);
1646 } else if (currentWebsiteCertificateLinearLayout.getVisibility() == View.VISIBLE) { // The saved SSL certificate is hidden but the current website SSL certificate is visible.
1647 currentWebsiteCertificateRadioButton.setChecked(true);
1648 savedSslCertificateRadioButton.setChecked(false);
1649 } else { // Neither SSL certificate is visible.
1650 savedSslCertificateRadioButton.setChecked(false);
1651 currentWebsiteCertificateRadioButton.setChecked(false);
1653 } else { // Pinned SSL certificate is disabled.
1654 // Set the icon according to the theme.
1655 if (MainWebViewActivity.darkTheme) {
1656 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_dark));
1658 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_light));
1661 // Hide the SSl certificates and instructions.
1662 savedSslCertificateLinearLayout.setVisibility(View.GONE);
1663 currentWebsiteCertificateLinearLayout.setVisibility(View.GONE);
1664 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
1666 // Uncheck the radio buttons.
1667 savedSslCertificateRadioButton.setChecked(false);
1668 currentWebsiteCertificateRadioButton.setChecked(false);
1672 savedSslCertificateLinearLayout.setOnClickListener((View v) -> {
1673 savedSslCertificateRadioButton.setChecked(true);
1674 currentWebsiteCertificateRadioButton.setChecked(false);
1677 savedSslCertificateRadioButton.setOnClickListener((View v) -> {
1678 savedSslCertificateRadioButton.setChecked(true);
1679 currentWebsiteCertificateRadioButton.setChecked(false);
1682 currentWebsiteCertificateLinearLayout.setOnClickListener((View v) -> {
1683 currentWebsiteCertificateRadioButton.setChecked(true);
1684 savedSslCertificateRadioButton.setChecked(false);
1687 currentWebsiteCertificateRadioButton.setOnClickListener((View v) -> {
1688 currentWebsiteCertificateRadioButton.setChecked(true);
1689 savedSslCertificateRadioButton.setChecked(false);
1692 return domainSettingsView;
1695 private boolean checkDomainNameAgainstCertificate(String domainName, String certificateCommonName) {
1696 // Initialize `domainNamesMatch`.
1697 boolean domainNamesMatch = false;
1699 // Check if the domains match.
1700 if (domainName.equals(certificateCommonName)) {
1701 domainNamesMatch = true;
1704 // Check various wildcard permutations if `domainName` and `certificateCommonName` are not empty.
1705 // `noinspection ConstantCondition` removes Android Studio's incorrect lint warning that `domainName` can never be `null`.
1706 //noinspection ConstantConditions
1707 if ((domainName != null) && (certificateCommonName != null)) {
1708 // If `domainName` starts with a wildcard, check the base domain against all the subdomains of `certificateCommonName`.
1709 if (!domainNamesMatch && domainName.startsWith("*.") && (domainName.length() > 2)) {
1710 // Remove the initial `*.`.
1711 String baseDomainName = domainName.substring(2);
1713 // Setup a copy of `certificateCommonName` to test subdomains.
1714 String certificateCommonNameSubdomain = certificateCommonName;
1716 // Check all the subdomains in `certificateCommonNameSubdomain` against `baseDomainName`.
1717 while (!domainNamesMatch && certificateCommonNameSubdomain.contains(".")) { // Stop checking if we know that `domainNamesMatch` is `true` or if we run out of `.`.
1718 // Test the `certificateCommonNameSubdomain` against `baseDomainName`.
1719 if (certificateCommonNameSubdomain.equals(baseDomainName)) {
1720 domainNamesMatch = true;
1723 // Strip out the lowest subdomain of `certificateCommonNameSubdomain`.
1725 certificateCommonNameSubdomain = certificateCommonNameSubdomain.substring(certificateCommonNameSubdomain.indexOf(".") + 1);
1726 } catch (IndexOutOfBoundsException e) { // `certificateCommonNameSubdomain` ends with `.`.
1727 certificateCommonNameSubdomain = "";
1732 // If `certificateCommonName` starts with a wildcard, check the base common name against all the subdomains of `domainName`.
1733 if (!domainNamesMatch && certificateCommonName.startsWith("*.") && (certificateCommonName.length() > 2)) {
1734 // Remove the initial `*.`.
1735 String baseCertificateCommonName = certificateCommonName.substring(2);
1737 // Setup a copy of `domainName` to test subdomains.
1738 String domainNameSubdomain = domainName;
1740 // Check all the subdomains in `domainNameSubdomain` against `baseCertificateCommonName`.
1741 while (!domainNamesMatch && domainNameSubdomain.contains(".") && (domainNameSubdomain.length() > 2)) {
1742 // Test the `domainNameSubdomain` against `baseCertificateCommonName`.
1743 if (domainNameSubdomain.equals(baseCertificateCommonName)) {
1744 domainNamesMatch = true;
1747 // Strip out the lowest subdomain of `domainNameSubdomain`.
1749 domainNameSubdomain = domainNameSubdomain.substring(domainNameSubdomain.indexOf(".") + 1);
1750 } catch (IndexOutOfBoundsException e) { // `domainNameSubdomain` ends with `.`.
1751 domainNameSubdomain = "";
1756 // If both names start with a wildcard, check if the root of one contains the root of the other.
1757 if (!domainNamesMatch && domainName.startsWith("*.") && (domainName.length() > 2) && certificateCommonName.startsWith("*.") && (certificateCommonName.length() > 2)) {
1758 // Remove the wildcards.
1759 String rootDomainName = domainName.substring(2);
1760 String rootCertificateCommonName = certificateCommonName.substring(2);
1762 // Check if one name ends with the contents of the other. If so, there will be overlap in the their wildcard subdomains.
1763 if (rootDomainName.endsWith(rootCertificateCommonName) || rootCertificateCommonName.endsWith(rootDomainName)) {
1764 domainNamesMatch = true;
1769 return domainNamesMatch;