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 defaultUserAgentString = sharedPreferences.getString("user_agent", "PrivacyBrowser/1.0");
96 final String defaultCustomUserAgentString = sharedPreferences.getString("custom_user_agent", "PrivacyBrowser/1.0");
97 String defaultFontSizeString = sharedPreferences.getString("default_font_size", "100");
98 final boolean defaultDisplayWebpageImagesBoolean = sharedPreferences.getBoolean("display_website_images", true);
99 final boolean defaultNightModeBoolean = sharedPreferences.getBoolean("night_mode", false);
101 // Get handles for the views in the fragment.
102 final EditText domainNameEditText = domainSettingsView.findViewById(R.id.domain_settings_name_edittext);
103 final Switch javaScriptEnabledSwitch = domainSettingsView.findViewById(R.id.domain_settings_javascript_switch);
104 final ImageView javaScriptImageView = domainSettingsView.findViewById(R.id.domain_settings_javascript_imageview);
105 Switch firstPartyCookiesEnabledSwitch = domainSettingsView.findViewById(R.id.domain_settings_first_party_cookies_switch);
106 final ImageView firstPartyCookiesImageView = domainSettingsView.findViewById(R.id.domain_settings_first_party_cookies_imageview);
107 LinearLayout thirdPartyCookiesLinearLayout = domainSettingsView.findViewById(R.id.domain_settings_third_party_cookies_linearlayout);
108 final Switch thirdPartyCookiesEnabledSwitch = domainSettingsView.findViewById(R.id.domain_settings_third_party_cookies_switch);
109 final ImageView thirdPartyCookiesImageView = domainSettingsView.findViewById(R.id.domain_settings_third_party_cookies_imageview);
110 final Switch domStorageEnabledSwitch = domainSettingsView.findViewById(R.id.domain_settings_dom_storage_switch);
111 final ImageView domStorageImageView = domainSettingsView.findViewById(R.id.domain_settings_dom_storage_imageview);
112 Switch formDataEnabledSwitch = domainSettingsView.findViewById(R.id.domain_settings_form_data_switch);
113 final ImageView formDataImageView = domainSettingsView.findViewById(R.id.domain_settings_form_data_imageview);
114 Switch easyListSwitch = domainSettingsView.findViewById(R.id.domain_settings_easylist_switch);
115 ImageView easyListImageView = domainSettingsView.findViewById(R.id.domain_settings_easylist_imageview);
116 Switch easyPrivacySwitch = domainSettingsView.findViewById(R.id.domain_settings_easyprivacy_switch);
117 ImageView easyPrivacyImageView = domainSettingsView.findViewById(R.id.domain_settings_easyprivacy_imageview);
118 Switch fanboysAnnoyanceListSwitch = domainSettingsView.findViewById(R.id.domain_settings_fanboys_annoyance_list_switch);
119 ImageView fanboysAnnoyanceListImageView = domainSettingsView.findViewById(R.id.domain_settings_fanboys_annoyance_list_imageview);
120 Switch fanboysSocialBlockingListSwitch = domainSettingsView.findViewById(R.id.domain_settings_fanboys_social_blocking_list_switch);
121 ImageView fanboysSocialBlockingListImageView = domainSettingsView.findViewById(R.id.domain_settings_fanboys_social_blocking_list_imageview);
122 final Spinner userAgentSpinner = domainSettingsView.findViewById(R.id.domain_settings_user_agent_spinner);
123 final TextView userAgentTextView = domainSettingsView.findViewById(R.id.domain_settings_user_agent_textview);
124 final EditText customUserAgentEditText = domainSettingsView.findViewById(R.id.domain_settings_custom_user_agent_edittext);
125 final Spinner fontSizeSpinner = domainSettingsView.findViewById(R.id.domain_settings_font_size_spinner);
126 final TextView fontSizeTextView = domainSettingsView.findViewById(R.id.domain_settings_font_size_textview);
127 final ImageView displayWebpageImagesImageView = domainSettingsView.findViewById(R.id.domain_settings_display_webpage_images_imageview);
128 final Spinner displayWebpageImagesSpinner = domainSettingsView.findViewById(R.id.domain_settings_display_webpage_images_spinner);
129 final TextView displayImagesTextView = domainSettingsView.findViewById(R.id.domain_settings_display_webpage_images_textview);
130 final ImageView nightModeImageView = domainSettingsView.findViewById(R.id.domain_settings_night_mode_imageview);
131 final Spinner nightModeSpinner = domainSettingsView.findViewById(R.id.domain_settings_night_mode_spinner);
132 final TextView nightModeTextView = domainSettingsView.findViewById(R.id.domain_settings_night_mode_textview);
133 final ImageView pinnedSslCertificateImageView = domainSettingsView.findViewById(R.id.domain_settings_pinned_ssl_certificate_imageview);
134 Switch pinnedSslCertificateSwitch = domainSettingsView.findViewById(R.id.domain_settings_pinned_ssl_certificate_switch);
135 final LinearLayout savedSslCertificateLinearLayout = domainSettingsView.findViewById(R.id.saved_ssl_certificate_linearlayout);
136 final RadioButton savedSslCertificateRadioButton = domainSettingsView.findViewById(R.id.saved_ssl_certificate_radiobutton);
137 final TextView savedSslCertificateIssuedToCNameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_to_cname);
138 TextView savedSslCertificateIssuedToONameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_to_oname);
139 TextView savedSslCertificateIssuedToUNameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_to_uname);
140 TextView savedSslCertificateIssuedByCNameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_by_cname);
141 TextView savedSslCertificateIssuedByONameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_by_oname);
142 TextView savedSslCertificateIssuedByUNameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_by_uname);
143 TextView savedSslCertificateStartDateTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_start_date);
144 TextView savedSslCertificateEndDateTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_end_date);
145 final LinearLayout currentWebsiteCertificateLinearLayout = domainSettingsView.findViewById(R.id.current_website_certificate_linearlayout);
146 final RadioButton currentWebsiteCertificateRadioButton = domainSettingsView.findViewById(R.id.current_website_certificate_radiobutton);
147 final TextView currentWebsiteCertificateIssuedToCNameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_to_cname);
148 TextView currentWebsiteCertificateIssuedToONameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_to_oname);
149 TextView currentWebsiteCertificateIssuedToUNameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_to_uname);
150 TextView currentWebsiteCertificateIssuedByCNameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_by_cname);
151 TextView currentWebsiteCertificateIssuedByONameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_by_oname);
152 TextView currentWebsiteCertificateIssuedByUNameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_by_uname);
153 TextView currentWebsiteCertificateStartDateTextView = domainSettingsView.findViewById(R.id.current_website_certificate_start_date);
154 TextView currentWebsiteCertificateEndDateTextView = domainSettingsView.findViewById(R.id.current_website_certificate_end_date);
155 final TextView noCurrentWebsiteCertificateTextView = domainSettingsView.findViewById(R.id.no_current_website_certificate);
157 // Setup the SSL certificate labels.
158 final String cNameLabel = getString(R.string.common_name) + " ";
159 String oNameLabel = getString(R.string.organization) + " ";
160 String uNameLabel = getString(R.string.organizational_unit) + " ";
161 String startDateLabel = getString(R.string.start_date) + " ";
162 String endDateLabel = getString(R.string.end_date) + " ";
164 // Get the current website SSL certificate
165 final SslCertificate currentWebsiteSslCertificate = MainWebViewActivity.sslCertificate;
167 // Initialize the database handler. The `0` specifies the database version, but that is ignored and set instead using a constant in `DomainsDatabaseHelper`.
168 DomainsDatabaseHelper domainsDatabaseHelper = new DomainsDatabaseHelper(context, null, null, 0);
170 // Get the database `Cursor` for this ID and move it to the first row.
171 Cursor domainCursor = domainsDatabaseHelper.getCursorForId(databaseId);
172 domainCursor.moveToFirst();
174 // Save the `Cursor` entries as variables.
175 String domainNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.DOMAIN_NAME));
176 final int javaScriptEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_JAVASCRIPT));
177 int firstPartyCookiesEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FIRST_PARTY_COOKIES));
178 int thirdPartyCookiesEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_THIRD_PARTY_COOKIES));
179 final int domStorageEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_DOM_STORAGE));
180 int formDataEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FORM_DATA));
181 int easyListEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYLIST));
182 int easyPrivacyEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYPRIVACY));
183 int fanboysAnnoyanceListInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST));
184 int fanboysSocialBlockingListInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST));
185 final String currentUserAgentString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.USER_AGENT));
186 int fontSizeInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.FONT_SIZE));
187 int displayImagesInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.DISPLAY_IMAGES));
188 int nightModeInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.NIGHT_MODE));
189 int pinnedSslCertificateInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.PINNED_SSL_CERTIFICATE));
190 final String savedSslCertificateIssuedToCNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_COMMON_NAME));
191 String savedSslCertificateIssuedToONameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATION));
192 String savedSslCertificateIssuedToUNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATIONAL_UNIT));
193 String savedSslCertificateIssuedByCNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_COMMON_NAME));
194 String savedSslCertificateIssuedByONameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATION));
195 String savedSslCertificateIssuedByUNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATIONAL_UNIT));
197 // Initialize the saved SSL certificate date variables.
198 Date savedSslCertificateStartDate = null;
199 Date savedSslCertificateEndDate = null;
201 // Only get the saved SSL certificate dates from the cursor if they are not set to `0`.
202 if (domainCursor.getLong(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_START_DATE)) != 0) {
203 savedSslCertificateStartDate = new Date(domainCursor.getLong(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_START_DATE)));
206 if (domainCursor.getLong(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_END_DATE)) != 0) {
207 savedSslCertificateEndDate = new Date(domainCursor.getLong(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_END_DATE)));
210 // Create `ArrayAdapters` for the `Spinners`and their `entry values`.
211 ArrayAdapter<CharSequence> userAgentArrayAdapter = ArrayAdapter.createFromResource(context, R.array.domain_settings_user_agent_entries, R.layout.domain_settings_spinner_item);
212 final ArrayAdapter<CharSequence> userAgentEntryValuesArrayAdapter = ArrayAdapter.createFromResource(context, R.array.domain_settings_user_agent_entry_values, R.layout.domain_settings_spinner_item);
213 ArrayAdapter<CharSequence> fontSizeArrayAdapter = ArrayAdapter.createFromResource(context, R.array.domain_settings_font_size_entries, R.layout.domain_settings_spinner_item);
214 ArrayAdapter<CharSequence> fontSizeEntryValuesArrayAdapter = ArrayAdapter.createFromResource(context, R.array.domain_settings_font_size_entry_values, R.layout.domain_settings_spinner_item);
215 final ArrayAdapter<CharSequence> displayImagesArrayAdapter = ArrayAdapter.createFromResource(context, R.array.display_webpage_images_array, R.layout.domain_settings_spinner_item);
216 ArrayAdapter<CharSequence> nightModeArrayAdapter = ArrayAdapter.createFromResource(context, R.array.night_mode_array, R.layout.domain_settings_spinner_item);
218 // Set the `DropDownViewResource` on the `Spinners`.
219 userAgentArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_item);
220 fontSizeArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_item);
221 displayImagesArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_item);
222 nightModeArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_item);
224 // Set the `ArrayAdapters` for the `Spinners`.
225 userAgentSpinner.setAdapter(userAgentArrayAdapter);
226 fontSizeSpinner.setAdapter(fontSizeArrayAdapter);
227 displayWebpageImagesSpinner.setAdapter(displayImagesArrayAdapter);
228 nightModeSpinner.setAdapter(nightModeArrayAdapter);
230 // Create a `SpannableStringBuilder` for each `TextView` that needs multiple colors of text.
231 SpannableStringBuilder savedSslCertificateIssuedToCNameStringBuilder = new SpannableStringBuilder(cNameLabel + savedSslCertificateIssuedToCNameString);
232 SpannableStringBuilder savedSslCertificateIssuedToONameStringBuilder = new SpannableStringBuilder(oNameLabel + savedSslCertificateIssuedToONameString);
233 SpannableStringBuilder savedSslCertificateIssuedToUNameStringBuilder = new SpannableStringBuilder(uNameLabel + savedSslCertificateIssuedToUNameString);
234 SpannableStringBuilder savedSslCertificateIssuedByCNameStringBuilder = new SpannableStringBuilder(cNameLabel + savedSslCertificateIssuedByCNameString);
235 SpannableStringBuilder savedSslCertificateIssuedByONameStringBuilder = new SpannableStringBuilder(oNameLabel + savedSslCertificateIssuedByONameString);
236 SpannableStringBuilder savedSslCertificateIssuedByUNameStringBuilder = new SpannableStringBuilder(uNameLabel + savedSslCertificateIssuedByUNameString);
238 // Initialize the `SpannableStringBuilders` for the SSL certificate dates.
239 SpannableStringBuilder savedSslCertificateStartDateStringBuilder;
240 SpannableStringBuilder savedSslCertificateEndDateStringBuilder;
242 // Leave the SSL certificate dates empty if they are `null`.
243 if (savedSslCertificateStartDate == null) {
244 savedSslCertificateStartDateStringBuilder = new SpannableStringBuilder(startDateLabel);
246 savedSslCertificateStartDateStringBuilder = new SpannableStringBuilder(startDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG).format(savedSslCertificateStartDate));
249 if (savedSslCertificateEndDate == null) {
250 savedSslCertificateEndDateStringBuilder = new SpannableStringBuilder(endDateLabel);
252 savedSslCertificateEndDateStringBuilder = new SpannableStringBuilder(endDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG).format(savedSslCertificateEndDate));
255 // Create a red `ForegroundColorSpan`. We have to use the deprecated `getColor` until API >= 23.
256 final ForegroundColorSpan redColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.red_a700));
258 // Create a blue `ForegroundColorSpan`.
259 final ForegroundColorSpan blueColorSpan;
261 // Set `blueColorSpan` according to the theme. We have to use the deprecated `getColor()` until API >= 23.
262 if (MainWebViewActivity.darkTheme) {
263 //noinspection deprecation
264 blueColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.blue_400));
266 //noinspection deprecation
267 blueColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.blue_700));
270 // Set the domain name from the the database cursor.
271 domainNameEditText.setText(domainNameString);
273 // Update the certificates' `Common Name` color when the domain name text changes.
274 domainNameEditText.addTextChangedListener(new TextWatcher() {
276 public void beforeTextChanged(CharSequence s, int start, int count, int after) {
281 public void onTextChanged(CharSequence s, int start, int before, int count) {
286 public void afterTextChanged(Editable s) {
287 // Get the new domain name.
288 String newDomainName = domainNameEditText.getText().toString();
290 // Check the saved SSL certificate against the new domain name.
291 boolean savedSslCertificateMatchesNewDomainName = checkDomainNameAgainstCertificate(newDomainName, savedSslCertificateIssuedToCNameString);
293 // Create a `SpannableStringBuilder` for the saved certificate `Common Name`.
294 SpannableStringBuilder savedSslCertificateCommonNameStringBuilder = new SpannableStringBuilder(cNameLabel + savedSslCertificateIssuedToCNameString);
296 // Format the saved certificate `Common Name` color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
297 if (savedSslCertificateMatchesNewDomainName) {
298 savedSslCertificateCommonNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), savedSslCertificateCommonNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
300 savedSslCertificateCommonNameStringBuilder.setSpan(redColorSpan, cNameLabel.length(), savedSslCertificateCommonNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
303 // Update `savedSslCertificateIssuedToCNameTextView`.
304 savedSslCertificateIssuedToCNameTextView.setText(savedSslCertificateCommonNameStringBuilder);
306 // Update the current website certificate if it exists.
307 if (currentWebsiteSslCertificate != null) {
308 // Get the current website certificate `Common Name`.
309 String currentWebsiteCertificateCommonName = currentWebsiteSslCertificate.getIssuedTo().getCName();
311 // Check the current website certificate against the new domain name.
312 boolean currentWebsiteCertificateMatchesNewDomainName = checkDomainNameAgainstCertificate(newDomainName, currentWebsiteCertificateCommonName);
314 // Create a `SpannableStringBuilder` for the current website certificate `Common Name`.
315 SpannableStringBuilder currentWebsiteCertificateCommonNameStringBuilder = new SpannableStringBuilder(cNameLabel + currentWebsiteCertificateCommonName);
317 // Format the current certificate `Common Name` color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
318 if (currentWebsiteCertificateMatchesNewDomainName) {
319 currentWebsiteCertificateCommonNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), currentWebsiteCertificateCommonNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
321 currentWebsiteCertificateCommonNameStringBuilder.setSpan(redColorSpan, cNameLabel.length(), currentWebsiteCertificateCommonNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
324 // Update `currentWebsiteCertificateIssuedToCNameTextView`.
325 currentWebsiteCertificateIssuedToCNameTextView.setText(currentWebsiteCertificateCommonNameStringBuilder);
330 // Create a `boolean` to track if night mode is enabled.
331 boolean nightModeEnabled = (nightModeInt == DomainsDatabaseHelper.NIGHT_MODE_ENABLED) || ((nightModeInt == DomainsDatabaseHelper.NIGHT_MODE_SYSTEM_DEFAULT) && defaultNightModeBoolean);
333 // Disable the JavaScript `Switch` if night mode is enabled.
334 if (nightModeEnabled) {
335 javaScriptEnabledSwitch.setEnabled(false);
337 javaScriptEnabledSwitch.setEnabled(true);
340 // Set the JavaScript icon.
341 if ((javaScriptEnabledInt == 1) || nightModeEnabled) {
342 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.javascript_enabled));
344 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.privacy_mode));
347 // Set the JavaScript `Switch` status.
348 if (javaScriptEnabledInt == 1) { // JavaScript is enabled.
349 javaScriptEnabledSwitch.setChecked(true);
350 } else { // JavaScript is disabled.
351 javaScriptEnabledSwitch.setChecked(false);
354 // 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.
355 if (firstPartyCookiesEnabledInt == 1) { // First-party cookies are enabled.
356 firstPartyCookiesEnabledSwitch.setChecked(true);
357 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_enabled));
358 } else { // First-party cookies are disabled.
359 firstPartyCookiesEnabledSwitch.setChecked(false);
361 // Set the icon according to the theme.
362 if (MainWebViewActivity.darkTheme) {
363 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_dark));
365 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_light));
369 // Only display third-party cookies if SDK_INT >= 21.
370 if (Build.VERSION.SDK_INT >= 21) { // Third-party cookies can be configured for API >= 21.
371 // Only enable third-party-cookies if first-party cookies are enabled.
372 if (firstPartyCookiesEnabledInt == 1) { // First-party cookies are enabled.
373 // 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.
374 if (thirdPartyCookiesEnabledInt == 1) { // Both first-party and third-party cookies are enabled.
375 thirdPartyCookiesEnabledSwitch.setChecked(true);
376 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_warning));
377 } else { // First party cookies are enabled but third-party cookies are disabled.
378 thirdPartyCookiesEnabledSwitch.setChecked(false);
380 // Set the icon according to the theme.
381 if (MainWebViewActivity.darkTheme) {
382 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_dark));
384 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_light));
387 } else { // First-party cookies are disabled.
388 // Set the status of third-party cookies.
389 if (thirdPartyCookiesEnabledInt == 1) {
390 thirdPartyCookiesEnabledSwitch.setChecked(true);
392 thirdPartyCookiesEnabledSwitch.setChecked(false);
395 // Disable the third-party cookies switch.
396 thirdPartyCookiesEnabledSwitch.setEnabled(false);
398 // Set the icon according to the theme.
399 if (MainWebViewActivity.darkTheme) {
400 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_ghosted_dark));
402 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_ghosted_light));
405 } else { // Third-party cookies cannot be configured for API <= 21.
406 // Hide the `LinearLayout` for third-party cookies.
407 thirdPartyCookiesLinearLayout.setVisibility(View.GONE);
410 // Only enable DOM storage if JavaScript is enabled.
411 if ((javaScriptEnabledInt == 1) || nightModeEnabled) { // JavaScript is enabled.
412 // Enable the DOM storage `Switch`.
413 domStorageEnabledSwitch.setEnabled(true);
415 // Set the DOM storage status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
416 if (domStorageEnabledInt == 1) { // Both JavaScript and DOM storage are enabled.
417 domStorageEnabledSwitch.setChecked(true);
418 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_enabled));
419 } else { // JavaScript is enabled but DOM storage is disabled.
420 // Set the DOM storage switch to off.
421 domStorageEnabledSwitch.setChecked(false);
423 // Set the icon according to the theme.
424 if (MainWebViewActivity.darkTheme) {
425 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_dark));
427 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_light));
430 } else { // JavaScript is disabled.
431 // Disable the DOM storage `Switch`.
432 domStorageEnabledSwitch.setEnabled(false);
434 // Set the checked status of DOM storage.
435 if (domStorageEnabledInt == 1) { // DOM storage is enabled but JavaScript is disabled.
436 domStorageEnabledSwitch.setChecked(true);
437 } else { // Both JavaScript and DOM storage are disabled.
438 domStorageEnabledSwitch.setChecked(false);
441 // Set the icon according to the theme.
442 if (MainWebViewActivity.darkTheme) {
443 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_dark));
445 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_light));
449 // Set the form data status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
450 if (formDataEnabledInt == 1) { // Form data is on.
451 formDataEnabledSwitch.setChecked(true);
452 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_enabled));
453 } else { // Form data is off.
454 // Turn the form data switch to off.
455 formDataEnabledSwitch.setChecked(false);
457 // Set the icon according to the theme.
458 if (MainWebViewActivity.darkTheme) {
459 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_disabled_dark));
461 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_disabled_light));
465 // Set the EasyList status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
466 if (easyListEnabledInt == 1) { // EasyList is on.
467 // Turn the switch on.
468 easyListSwitch.setChecked(true);
470 // Set the icon according to the theme.
471 if (MainWebViewActivity.darkTheme) {
472 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_dark));
474 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_light));
476 } else { // EasyList is off.
477 // Turn the switch off.
478 easyListSwitch.setChecked(false);
480 // Set the icon according to the theme.
481 if (MainWebViewActivity.darkTheme) {
482 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_dark));
484 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_light));
488 // Set the EasyPrivacy status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
489 if (easyPrivacyEnabledInt == 1) { // EasyPrivacy is on.
490 // Turn the switch on.
491 easyPrivacySwitch.setChecked(true);
493 // Set the icon according to the theme.
494 if (MainWebViewActivity.darkTheme) {
495 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_dark));
497 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_light));
499 } else { // EasyPrivacy is off.
500 // Turn the switch off.
501 easyPrivacySwitch.setChecked(false);
503 // Set the icon according to the theme.
504 if (MainWebViewActivity.darkTheme) {
505 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_dark));
507 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_light));
511 // 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.
512 if (fanboysAnnoyanceListInt == 1) { // Fanboy's Annoyance List is on.
513 // Turn the switch on.
514 fanboysAnnoyanceListSwitch.setChecked(true);
516 // Set the icon according to the theme.
517 if (MainWebViewActivity.darkTheme) {
518 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_dark));
520 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_light));
522 } else { // Fanboy's Annoyance List is off.
523 // Turn the switch off.
524 fanboysAnnoyanceListSwitch.setChecked(false);
526 // Set the icon according to the theme.
527 if (MainWebViewActivity.darkTheme) {
528 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_dark));
530 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_light));
534 // Only enable Fanboy's Social Blocking List if Fanboy's Annoyance List is off.
535 if (fanboysAnnoyanceListInt == 0) { // Fanboy's Annoyance List is on.
536 // 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.
537 if (fanboysSocialBlockingListInt == 1) { // Fanboy's Social Blocking List is on.
538 // Enable the switch and turn it on.
539 fanboysSocialBlockingListSwitch.setEnabled(true);
540 fanboysSocialBlockingListSwitch.setChecked(true);
542 // Set the icon according to the theme.
543 if (MainWebViewActivity.darkTheme) {
544 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_dark));
546 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_light));
548 } else { // Fanboy's Social Blocking List is off.
549 // Enable the switch but turn it off.
550 fanboysSocialBlockingListSwitch.setEnabled(true);
551 fanboysSocialBlockingListSwitch.setChecked(false);
553 // Set the icon according to the theme.
554 if (MainWebViewActivity.darkTheme) {
555 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_dark));
557 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_light));
560 } else { // Fanboy's Annoyance List is on.
561 // 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.
562 if (fanboysSocialBlockingListInt == 1) { // Fanboy's Social Blocking List is on.
563 // Disable the switch but turn it on.
564 fanboysSocialBlockingListSwitch.setEnabled(false);
565 fanboysSocialBlockingListSwitch.setChecked(true);
566 } else { // Fanboy's Social Blocking List is off.
567 // Disable the switch and turn it off.
568 fanboysSocialBlockingListSwitch.setEnabled(false);
569 fanboysSocialBlockingListSwitch.setChecked(false);
572 // Set the icon according to the theme.
573 if (MainWebViewActivity.darkTheme) {
574 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_ghosted_dark));
576 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_ghosted_light));
580 // Inflated a WebView to get the default user agent.
581 // `@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.
582 @SuppressLint("InflateParams") View bareWebViewLayout = inflater.inflate(R.layout.bare_webview, null, false);
583 WebView bareWebView = bareWebViewLayout.findViewById(R.id.bare_webview);
584 final String webViewDefaultUserAgentString = bareWebView.getSettings().getUserAgentString();
586 // Get the position of the user agent in `userAgentEntryValuesArrayAdapter`.
587 int userAgentArrayPosition = userAgentEntryValuesArrayAdapter.getPosition(currentUserAgentString);
589 // Set the user agent.
590 if (userAgentArrayPosition == -1) { // We are using a custom `userAgentString`.
591 // Set `userAgentSpinner` to `Custom`.
592 userAgentSpinner.setSelection(userAgentEntryValuesArrayAdapter.getPosition("Custom user agent"));
594 // Hide `userAgentTextView`.
595 userAgentTextView.setVisibility(View.GONE);
597 // Show `customUserAgentEditText` and set `userAgentString` as the text.
598 customUserAgentEditText.setVisibility(View.VISIBLE);
599 customUserAgentEditText.setText(currentUserAgentString);
600 } else{ // We are using one of the preset user agents.
601 // Set the `userAgentSpinner` selection.
602 userAgentSpinner.setSelection(userAgentArrayPosition);
604 // Show `userAgentTextView`.
605 userAgentTextView.setVisibility(View.VISIBLE);
607 // Hide `customUserAgentEditText`.
608 customUserAgentEditText.setVisibility(View.GONE);
610 // Set the user agent text.
611 switch (currentUserAgentString) {
612 case "System default user agent":
613 // Display the user agent text string.
614 switch (defaultUserAgentString) {
615 case "WebView default user agent":
616 // Display the `WebView` default user agent.
617 userAgentTextView.setText(webViewDefaultUserAgentString);
620 case "Custom user agent":
621 // Display the custom user agent.
622 userAgentTextView.setText(defaultCustomUserAgentString);
626 // Display the text from `defaultUserAgentString`.
627 userAgentTextView.setText(defaultUserAgentString);
631 case "WebView default user agent":
632 // Display the `WebView` default user agent.
633 userAgentTextView.setText(webViewDefaultUserAgentString);
637 // Display the text from `currentUserAgentString`.
638 userAgentTextView.setText(currentUserAgentString);
642 // Open the user agent spinner when the `TextView` is clicked.
643 userAgentTextView.setOnClickListener((View v) -> {
644 // Open the user agent spinner.
645 userAgentSpinner.performClick();
648 // Set the selected font size.
649 int fontSizeArrayPosition = fontSizeEntryValuesArrayAdapter.getPosition(String.valueOf(fontSizeInt));
650 fontSizeSpinner.setSelection(fontSizeArrayPosition);
652 // Set the default font size text.
653 int defaultFontSizeArrayPosition = fontSizeEntryValuesArrayAdapter.getPosition(defaultFontSizeString);
654 fontSizeTextView.setText(fontSizeArrayAdapter.getItem(defaultFontSizeArrayPosition));
656 // Set the display options for `fontSizeTextView`.
657 if (fontSizeArrayPosition == 0) { // System default font size is selected. Display `fontSizeTextView`.
658 fontSizeTextView.setVisibility(View.VISIBLE);
659 } else { // A custom font size is specified. Hide `fontSizeTextView`.
660 fontSizeTextView.setVisibility(View.GONE);
663 // Open the font size spinner when the `TextView` is clicked.
664 fontSizeTextView.setOnClickListener((View v) -> {
665 // Open the user agent spinner.
666 fontSizeSpinner.performClick();
669 // Display the website images mode in the spinner.
670 displayWebpageImagesSpinner.setSelection(displayImagesInt);
672 // Set the default display images text.
673 if (defaultDisplayWebpageImagesBoolean) {
674 displayImagesTextView.setText(displayImagesArrayAdapter.getItem(DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_ENABLED));
676 displayImagesTextView.setText(displayImagesArrayAdapter.getItem(DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_DISABLED));
679 // 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.
680 switch (displayImagesInt) {
681 case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_SYSTEM_DEFAULT:
682 if (defaultDisplayWebpageImagesBoolean) { // Display webpage images enabled by default.
683 // Set the icon according to the theme.
684 if (MainWebViewActivity.darkTheme) {
685 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_dark));
687 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_light));
689 } else { // Display webpage images disabled by default.
690 // Set the icon according to the theme.
691 if (MainWebViewActivity.darkTheme) {
692 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_dark));
694 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_light));
698 // Show `displayImagesTextView`.
699 displayImagesTextView.setVisibility(View.VISIBLE);
702 case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_ENABLED:
703 // Set the icon according to the theme.
704 if (MainWebViewActivity.darkTheme) {
705 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_dark));
707 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_light));
710 // Hide `displayImagesTextView`.
711 displayImagesTextView.setVisibility(View.GONE);
714 case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_DISABLED:
715 // Set the icon according to the theme.
716 if (MainWebViewActivity.darkTheme) {
717 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_dark));
719 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_light));
722 // Hide `displayImagesTextView`.
723 displayImagesTextView.setVisibility(View.GONE);
727 // Open the display images spinner when the `TextView` is clicked.
728 displayImagesTextView.setOnClickListener((View v) -> {
729 // Open the user agent spinner.
730 displayWebpageImagesSpinner.performClick();
733 // Display the night mode in the spinner.
734 nightModeSpinner.setSelection(nightModeInt);
736 // Set the default night mode text.
737 if (defaultNightModeBoolean) {
738 nightModeTextView.setText(nightModeArrayAdapter.getItem(DomainsDatabaseHelper.NIGHT_MODE_ENABLED));
740 nightModeTextView.setText(nightModeArrayAdapter.getItem(DomainsDatabaseHelper.NIGHT_MODE_DISABLED));
743 // 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.
744 switch (displayImagesInt) {
745 case DomainsDatabaseHelper.NIGHT_MODE_SYSTEM_DEFAULT:
746 if (defaultNightModeBoolean) { // Night mode enabled by default.
747 // Set the icon according to the theme.
748 if (MainWebViewActivity.darkTheme) {
749 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_dark));
751 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_light));
753 } else { // Night mode disabled by default.
754 // Set the icon according to the theme.
755 if (MainWebViewActivity.darkTheme) {
756 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_dark));
758 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_light));
762 // Show `nightModeTextView`.
763 nightModeTextView.setVisibility(View.VISIBLE);
766 case DomainsDatabaseHelper.NIGHT_MODE_ENABLED:
767 // Set the icon according to the theme.
768 if (MainWebViewActivity.darkTheme) {
769 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_dark));
771 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_light));
774 // Hide `nightModeTextView`.
775 nightModeTextView.setVisibility(View.GONE);
778 case DomainsDatabaseHelper.NIGHT_MODE_DISABLED:
779 // Set the icon according to the theme.
780 if (MainWebViewActivity.darkTheme) {
781 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_dark));
783 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_light));
786 // Hide `nightModeTextView`.
787 nightModeTextView.setVisibility(View.GONE);
791 // Open the night mode spinner when the `TextView` is clicked.
792 nightModeTextView.setOnClickListener((View v) -> {
793 // Open the user agent spinner.
794 nightModeSpinner.performClick();
797 // Set the pinned SSL certificate icon.
798 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.
800 pinnedSslCertificateSwitch.setChecked(true);
802 // Set the icon according to the theme.
803 if (MainWebViewActivity.darkTheme) {
804 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_dark));
806 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_light));
808 } else { // Pinned SSL certificate is disabled.
809 // Uncheck the switch.
810 pinnedSslCertificateSwitch.setChecked(false);
812 // Set the icon according to the theme.
813 if (MainWebViewActivity.darkTheme) {
814 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_dark));
816 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_light));
820 // Store the current date.
821 Date currentDate = Calendar.getInstance().getTime();
823 // Setup the `StringBuilders` to display the general certificate information in blue. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
824 savedSslCertificateIssuedToONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), savedSslCertificateIssuedToONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
825 savedSslCertificateIssuedToUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), savedSslCertificateIssuedToUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
826 savedSslCertificateIssuedByCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), savedSslCertificateIssuedByCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
827 savedSslCertificateIssuedByONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), savedSslCertificateIssuedByONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
828 savedSslCertificateIssuedByUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), savedSslCertificateIssuedByUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
830 // Check the certificate `Common Name` against the domain name.
831 boolean savedSSlCertificateCommonNameMatchesDomainName = checkDomainNameAgainstCertificate(domainNameString, savedSslCertificateIssuedToCNameString);
833 // Format the `issuedToCommonName` color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
834 if (savedSSlCertificateCommonNameMatchesDomainName) {
835 savedSslCertificateIssuedToCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), savedSslCertificateIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
837 savedSslCertificateIssuedToCNameStringBuilder.setSpan(redColorSpan, cNameLabel.length(), savedSslCertificateIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
840 // Format the start date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
841 if ((savedSslCertificateStartDate != null) && savedSslCertificateStartDate.after(currentDate)) { // The certificate start date is in the future.
842 savedSslCertificateStartDateStringBuilder.setSpan(redColorSpan, startDateLabel.length(), savedSslCertificateStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
843 } else { // The certificate start date is in the past.
844 savedSslCertificateStartDateStringBuilder.setSpan(blueColorSpan, startDateLabel.length(), savedSslCertificateStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
847 // Format the end date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
848 if ((savedSslCertificateEndDate != null) && savedSslCertificateEndDate.before(currentDate)) { // The certificate end date is in the past.
849 savedSslCertificateEndDateStringBuilder.setSpan(redColorSpan, endDateLabel.length(), savedSslCertificateEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
850 } else { // The certificate end date is in the future.
851 savedSslCertificateEndDateStringBuilder.setSpan(blueColorSpan, endDateLabel.length(), savedSslCertificateEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
854 // Display the current website SSL certificate strings.
855 savedSslCertificateIssuedToCNameTextView.setText(savedSslCertificateIssuedToCNameStringBuilder);
856 savedSslCertificateIssuedToONameTextView.setText(savedSslCertificateIssuedToONameStringBuilder);
857 savedSslCertificateIssuedToUNameTextView.setText(savedSslCertificateIssuedToUNameStringBuilder);
858 savedSslCertificateIssuedByCNameTextView.setText(savedSslCertificateIssuedByCNameStringBuilder);
859 savedSslCertificateIssuedByONameTextView.setText(savedSslCertificateIssuedByONameStringBuilder);
860 savedSslCertificateIssuedByUNameTextView.setText(savedSslCertificateIssuedByUNameStringBuilder);
861 savedSslCertificateStartDateTextView.setText(savedSslCertificateStartDateStringBuilder);
862 savedSslCertificateEndDateTextView.setText(savedSslCertificateEndDateStringBuilder);
864 // Populate the current website SSL certificate if there is one.
865 if (currentWebsiteSslCertificate != null) {
866 // Get the strings from the SSL certificate.
867 String currentWebsiteCertificateIssuedToCNameString = currentWebsiteSslCertificate.getIssuedTo().getCName();
868 String currentWebsiteCertificateIssuedToONameString = currentWebsiteSslCertificate.getIssuedTo().getOName();
869 String currentWebsiteCertificateIssuedToUNameString = currentWebsiteSslCertificate.getIssuedTo().getUName();
870 String currentWebsiteCertificateIssuedByCNameString = currentWebsiteSslCertificate.getIssuedBy().getCName();
871 String currentWebsiteCertificateIssuedByONameString = currentWebsiteSslCertificate.getIssuedBy().getOName();
872 String currentWebsiteCertificateIssuedByUNameString = currentWebsiteSslCertificate.getIssuedBy().getUName();
873 Date currentWebsiteCertificateStartDate = currentWebsiteSslCertificate.getValidNotBeforeDate();
874 Date currentWebsiteCertificateEndDate = currentWebsiteSslCertificate.getValidNotAfterDate();
876 // Create a `SpannableStringBuilder` for each `TextView` that needs multiple colors of text.
877 SpannableStringBuilder currentWebsiteCertificateIssuedToCNameStringBuilder = new SpannableStringBuilder(cNameLabel + currentWebsiteCertificateIssuedToCNameString);
878 SpannableStringBuilder currentWebsiteCertificateIssuedToONameStringBuilder = new SpannableStringBuilder(oNameLabel + currentWebsiteCertificateIssuedToONameString);
879 SpannableStringBuilder currentWebsiteCertificateIssuedToUNameStringBuilder = new SpannableStringBuilder(uNameLabel + currentWebsiteCertificateIssuedToUNameString);
880 SpannableStringBuilder currentWebsiteCertificateIssuedByCNameStringBuilder = new SpannableStringBuilder(cNameLabel + currentWebsiteCertificateIssuedByCNameString);
881 SpannableStringBuilder currentWebsiteCertificateIssuedByONameStringBuilder = new SpannableStringBuilder(oNameLabel + currentWebsiteCertificateIssuedByONameString);
882 SpannableStringBuilder currentWebsiteCertificateIssuedByUNameStringBuilder = new SpannableStringBuilder(uNameLabel + currentWebsiteCertificateIssuedByUNameString);
883 SpannableStringBuilder currentWebsiteCertificateStartDateStringBuilder = new SpannableStringBuilder(startDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG)
884 .format(currentWebsiteCertificateStartDate));
885 SpannableStringBuilder currentWebsiteCertificateEndDateStringBuilder = new SpannableStringBuilder(endDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG)
886 .format(currentWebsiteCertificateEndDate));
888 // Setup the `StringBuilders` to display the general certificate information in blue. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
889 currentWebsiteCertificateIssuedToONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), currentWebsiteCertificateIssuedToONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
890 currentWebsiteCertificateIssuedToUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), currentWebsiteCertificateIssuedToUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
891 currentWebsiteCertificateIssuedByCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), currentWebsiteCertificateIssuedByCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
892 currentWebsiteCertificateIssuedByONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), currentWebsiteCertificateIssuedByONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
893 currentWebsiteCertificateIssuedByUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), currentWebsiteCertificateIssuedByUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
895 // Check the certificate `Common Name` against the domain name.
896 boolean currentWebsiteCertificateCommonNameMatchesDomainName = checkDomainNameAgainstCertificate(domainNameString, currentWebsiteCertificateIssuedToCNameString);
898 // Format the `issuedToCommonName` color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
899 if (currentWebsiteCertificateCommonNameMatchesDomainName) {
900 currentWebsiteCertificateIssuedToCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), currentWebsiteCertificateIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
902 currentWebsiteCertificateIssuedToCNameStringBuilder.setSpan(redColorSpan, cNameLabel.length(), currentWebsiteCertificateIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
905 // Format the start date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
906 if (currentWebsiteCertificateStartDate.after(currentDate)) { // The certificate start date is in the future.
907 currentWebsiteCertificateStartDateStringBuilder.setSpan(redColorSpan, startDateLabel.length(), currentWebsiteCertificateStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
908 } else { // The certificate start date is in the past.
909 currentWebsiteCertificateStartDateStringBuilder.setSpan(blueColorSpan, startDateLabel.length(), currentWebsiteCertificateStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
912 // Format the end date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
913 if (currentWebsiteCertificateEndDate.before(currentDate)) { // The certificate end date is in the past.
914 currentWebsiteCertificateEndDateStringBuilder.setSpan(redColorSpan, endDateLabel.length(), currentWebsiteCertificateEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
915 } else { // The certificate end date is in the future.
916 currentWebsiteCertificateEndDateStringBuilder.setSpan(blueColorSpan, endDateLabel.length(), currentWebsiteCertificateEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
919 // Display the current website SSL certificate strings.
920 currentWebsiteCertificateIssuedToCNameTextView.setText(currentWebsiteCertificateIssuedToCNameStringBuilder);
921 currentWebsiteCertificateIssuedToONameTextView.setText(currentWebsiteCertificateIssuedToONameStringBuilder);
922 currentWebsiteCertificateIssuedToUNameTextView.setText(currentWebsiteCertificateIssuedToUNameStringBuilder);
923 currentWebsiteCertificateIssuedByCNameTextView.setText(currentWebsiteCertificateIssuedByCNameStringBuilder);
924 currentWebsiteCertificateIssuedByONameTextView.setText(currentWebsiteCertificateIssuedByONameStringBuilder);
925 currentWebsiteCertificateIssuedByUNameTextView.setText(currentWebsiteCertificateIssuedByUNameStringBuilder);
926 currentWebsiteCertificateStartDateTextView.setText(currentWebsiteCertificateStartDateStringBuilder);
927 currentWebsiteCertificateEndDateTextView.setText(currentWebsiteCertificateEndDateStringBuilder);
930 // Set the initial display status for the SSL certificates.
931 if (pinnedSslCertificateSwitch.isChecked()) {
932 // Set the visibility of the saved SSL certificate.
933 if (savedSslCertificateIssuedToCNameString == null) {
934 savedSslCertificateLinearLayout.setVisibility(View.GONE);
936 savedSslCertificateLinearLayout.setVisibility(View.VISIBLE);
939 // Set the visibility of the current website SSL certificate.
940 if (currentWebsiteSslCertificate == null) {
941 // Hide the SSL certificate.
942 currentWebsiteCertificateLinearLayout.setVisibility(View.GONE);
944 // Show the instruction.
945 noCurrentWebsiteCertificateTextView.setVisibility(View.VISIBLE);
947 // Show the SSL certificate.
948 currentWebsiteCertificateLinearLayout.setVisibility(View.VISIBLE);
950 // Hide the instruction.
951 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
954 // Set the status of the radio buttons.
955 if (savedSslCertificateLinearLayout.getVisibility() == View.VISIBLE) { // The saved SSL certificate is displayed.
956 savedSslCertificateRadioButton.setChecked(true);
957 currentWebsiteCertificateRadioButton.setChecked(false);
958 } else if (currentWebsiteCertificateLinearLayout.getVisibility() == View.VISIBLE) { // The saved SSL certificate is hidden but the current website SSL certificate is visible.
959 currentWebsiteCertificateRadioButton.setChecked(true);
960 savedSslCertificateRadioButton.setChecked(false);
961 } else { // Neither SSL certificate is visible.
962 savedSslCertificateRadioButton.setChecked(false);
963 currentWebsiteCertificateRadioButton.setChecked(false);
965 } else { // `pinnedSslCertificateSwitch` is not checked.
966 // Hide the SSl certificates and instructions.
967 savedSslCertificateLinearLayout.setVisibility(View.GONE);
968 currentWebsiteCertificateLinearLayout.setVisibility(View.GONE);
969 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
971 // Uncheck the radio buttons.
972 savedSslCertificateRadioButton.setChecked(false);
973 currentWebsiteCertificateRadioButton.setChecked(false);
977 // Set the JavaScript switch listener.
978 javaScriptEnabledSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
979 if (isChecked) { // JavaScript is enabled.
980 // Update the JavaScript icon.
981 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.javascript_enabled));
983 // Enable the DOM storage `Switch`.
984 domStorageEnabledSwitch.setEnabled(true);
986 // Update the DOM storage icon.
987 if (domStorageEnabledSwitch.isChecked()) { // DOM storage is enabled.
988 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_enabled));
989 } else { // DOM storage is disabled.
990 // Set the icon according to the theme.
991 if (MainWebViewActivity.darkTheme) {
992 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_dark));
994 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_light));
997 } else { // JavaScript is disabled.
998 // Update the JavaScript icon.
999 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.privacy_mode));
1001 // Disable the DOM storage `Switch`.
1002 domStorageEnabledSwitch.setEnabled(false);
1004 // Set the DOM storage icon according to the theme.
1005 if (MainWebViewActivity.darkTheme) {
1006 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_dark));
1008 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_light));
1013 // Set the first-party cookies switch listener.
1014 firstPartyCookiesEnabledSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1015 if (isChecked) { // First-party cookies are enabled.
1016 // Update the first-party cookies icon.
1017 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_enabled));
1019 // Enable the third-party cookies switch.
1020 thirdPartyCookiesEnabledSwitch.setEnabled(true);
1022 // Update the third-party cookies icon.
1023 if (thirdPartyCookiesEnabledSwitch.isChecked()) { // Third-party cookies are enabled.
1024 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_warning));
1025 } else { // Third-party cookies are disabled.
1026 // Set the third-party cookies icon according to the theme.
1027 if (MainWebViewActivity.darkTheme) {
1028 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_dark));
1030 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_light));
1033 } else { // First-party cookies are disabled.
1034 // Update the first-party cookies icon according to the theme.
1035 if (MainWebViewActivity.darkTheme) {
1036 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_dark));
1038 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_light));
1041 // Disable the third-party cookies switch.
1042 thirdPartyCookiesEnabledSwitch.setEnabled(false);
1044 // Set the third-party cookies icon according to the theme.
1045 if (MainWebViewActivity.darkTheme) {
1046 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_ghosted_dark));
1048 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_ghosted_light));
1053 // Set the third-party cookies switch listener.
1054 thirdPartyCookiesEnabledSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1057 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_warning));
1059 // Update the third-party cookies icon according to the theme.
1060 if (MainWebViewActivity.darkTheme) {
1061 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_dark));
1063 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_light));
1068 // Set the DOM Storage switch listener.
1069 domStorageEnabledSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1072 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_enabled));
1074 // Set the icon according to the theme.
1075 if (MainWebViewActivity.darkTheme) {
1076 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_dark));
1078 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_light));
1083 // Set the form data switch listener.
1084 formDataEnabledSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1087 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_enabled));
1089 // Set the icon according to the theme.
1090 if (MainWebViewActivity.darkTheme) {
1091 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_disabled_dark));
1093 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_disabled_light));
1098 // Set the EasyList switch listener.
1099 easyListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1101 if (isChecked) { // EasyList is on.
1102 // Set the icon according to the theme.
1103 if (MainWebViewActivity.darkTheme) {
1104 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_dark));
1106 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_light));
1108 } else { // EasyList is off.
1109 // Set the icon according to the theme.
1110 if (MainWebViewActivity.darkTheme) {
1111 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_dark));
1113 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_light));
1118 // Set the EasyPrivacy switch listener.
1119 easyPrivacySwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1121 if (isChecked) { // EasyPrivacy is on.
1122 // Set the icon according to the theme.
1123 if (MainWebViewActivity.darkTheme) {
1124 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_dark));
1126 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_light));
1128 } else { // EasyPrivacy is off.
1129 // Set the icon according to the theme.
1130 if (MainWebViewActivity.darkTheme) {
1131 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_dark));
1133 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_light));
1138 // Set the Fanboy's Annoyance List switch listener.
1139 fanboysAnnoyanceListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1140 // Update the icon and Fanboy's Social Blocking List.
1141 if (isChecked) { // Fanboy's Annoyance List is on.
1142 // Set the icon according to the theme.
1143 if (MainWebViewActivity.darkTheme) {
1144 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_dark));
1146 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_light));
1149 // Disable the Fanboy's Social Blocking List switch.
1150 fanboysSocialBlockingListSwitch.setEnabled(false);
1152 // Update the Fanboy's Social Blocking List icon according to the theme.
1153 if (MainWebViewActivity.darkTheme) {
1154 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_ghosted_dark));
1156 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_ghosted_light));
1158 } else { // Fanboy's Annoyance List is off.
1159 // Set the icon according to the theme.
1160 if (MainWebViewActivity.darkTheme) {
1161 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_dark));
1163 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_light));
1166 // Enable the Fanboy's Social Blocking List switch.
1167 fanboysSocialBlockingListSwitch.setEnabled(true);
1169 // Update the Fanboy's Social Blocking List icon.
1170 if (fanboysSocialBlockingListSwitch.isChecked()) { // Fanboy's Social Blocking List is on.
1171 // Update the icon according to the theme.
1172 if (MainWebViewActivity.darkTheme) {
1173 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_dark));
1175 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_light));
1177 } else { // Fanboy's Social Blocking List is off.
1178 // Update the icon according to the theme.
1179 if (MainWebViewActivity.darkTheme) {
1180 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_dark));
1182 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_light));
1189 // Set the Fanboy's Social Blocking List switch listener.
1190 fanboysSocialBlockingListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1192 if (isChecked) { // Fanboy's Social Blocking List is on.
1193 // Set the icon according to the theme.
1194 if (MainWebViewActivity.darkTheme) {
1195 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_dark));
1197 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_light));
1199 } else { // Fanboy's Social Blocking List is off.
1200 // Set the icon according to the theme.
1201 if (MainWebViewActivity.darkTheme) {
1202 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_dark));
1204 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_light));
1209 // Set the user agent spinner listener.
1210 userAgentSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1212 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1213 // Store the new user agent string.
1214 String newUserAgentString = resources.getStringArray(R.array.domain_settings_user_agent_entry_values)[position];
1216 // Set the new user agent.
1217 switch (newUserAgentString) {
1218 case "System default user agent":
1219 // Show `userAgentTextView`.
1220 userAgentTextView.setVisibility(View.VISIBLE);
1222 // Hide `customUserAgentEditText`.
1223 customUserAgentEditText.setVisibility(View.GONE);
1225 // Set the user text.
1226 switch (defaultUserAgentString) {
1227 case "WebView default user agent":
1228 // Display the `WebView` default user agent.
1229 userAgentTextView.setText(webViewDefaultUserAgentString);
1232 case "Custom user agent":
1233 // Display the custom user agent.
1234 userAgentTextView.setText(defaultCustomUserAgentString);
1238 // Display the text from `defaultUserAgentString`.
1239 userAgentTextView.setText(defaultUserAgentString);
1243 case "WebView default user agent":
1244 // Show `userAgentTextView` and set the text.
1245 userAgentTextView.setVisibility(View.VISIBLE);
1246 userAgentTextView.setText(webViewDefaultUserAgentString);
1248 // Hide `customUserAgentEditText`.
1249 customUserAgentEditText.setVisibility(View.GONE);
1252 case "Custom user agent":
1253 // Hide `userAgentTextView`.
1254 userAgentTextView.setVisibility(View.GONE);
1256 // Show `customUserAgentEditText` and set `userAgentString` as the text.
1257 customUserAgentEditText.setVisibility(View.VISIBLE);
1258 customUserAgentEditText.setText(currentUserAgentString);
1262 // Show `userAgentTextView` and set the text.
1263 userAgentTextView.setVisibility(View.VISIBLE);
1264 userAgentTextView.setText(newUserAgentString);
1266 // Hide `customUserAgentEditText`.
1267 customUserAgentEditText.setVisibility(View.GONE);
1272 public void onNothingSelected(AdapterView<?> parent) {
1277 // Set the font size spinner listener.
1278 fontSizeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1280 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1281 // Update the display options for `fontSizeTextView`.
1282 if (position == 0) { // System default font size has been selected. Display `fontSizeTextView`.
1283 fontSizeTextView.setVisibility(View.VISIBLE);
1284 } else { // A custom font size has been selected. Hide `fontSizeTextView`.
1285 fontSizeTextView.setVisibility(View.GONE);
1290 public void onNothingSelected(AdapterView<?> parent) {
1295 // Set the display webpage images spinner listener.
1296 displayWebpageImagesSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1298 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1299 // Update the icon and the visibility of `displayImagesTextView`.
1301 case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_SYSTEM_DEFAULT:
1302 if (defaultDisplayWebpageImagesBoolean) {
1303 // Set the icon according to the theme.
1304 if (MainWebViewActivity.darkTheme) {
1305 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_dark));
1307 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_light));
1310 // Set the icon according to the theme.
1311 if (MainWebViewActivity.darkTheme) {
1312 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_dark));
1314 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_light));
1318 // Show `displayImagesTextView`.
1319 displayImagesTextView.setVisibility(View.VISIBLE);
1322 case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_ENABLED:
1323 // Set the icon according to the theme.
1324 if (MainWebViewActivity.darkTheme) {
1325 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_dark));
1327 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_light));
1330 // Hide `displayImagesTextView`.
1331 displayImagesTextView.setVisibility(View.GONE);
1334 case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_DISABLED:
1335 // Set the icon according to the theme.
1336 if (MainWebViewActivity.darkTheme) {
1337 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_dark));
1339 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_light));
1342 // Hide `displayImagesTextView`.
1343 displayImagesTextView.setVisibility(View.GONE);
1349 public void onNothingSelected(AdapterView<?> parent) {
1354 // Set the night mode spinner listener.
1355 nightModeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1357 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1358 // 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.
1360 case DomainsDatabaseHelper.NIGHT_MODE_SYSTEM_DEFAULT:
1361 if (defaultNightModeBoolean) { // Night mode enabled by default.
1362 // Set the icon according to the theme.
1363 if (MainWebViewActivity.darkTheme) {
1364 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_dark));
1366 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_light));
1368 } else { // Night mode disabled by default.
1369 // Set the icon according to the theme.
1370 if (MainWebViewActivity.darkTheme) {
1371 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_dark));
1373 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_light));
1377 // Show `nightModeTextView`.
1378 nightModeTextView.setVisibility(View.VISIBLE);
1381 case DomainsDatabaseHelper.NIGHT_MODE_ENABLED:
1382 // Set the icon according to the theme.
1383 if (MainWebViewActivity.darkTheme) {
1384 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_dark));
1386 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_light));
1389 // Hide `nightModeTextView`.
1390 nightModeTextView.setVisibility(View.GONE);
1393 case DomainsDatabaseHelper.NIGHT_MODE_DISABLED:
1394 // Set the icon according to the theme.
1395 if (MainWebViewActivity.darkTheme) {
1396 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_dark));
1398 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_light));
1401 // Hide `nightModeTextView`.
1402 nightModeTextView.setVisibility(View.GONE);
1406 // Create a `boolean` to store the current night mode setting.
1407 boolean currentNightModeEnabled = (position == DomainsDatabaseHelper.NIGHT_MODE_ENABLED) || ((position == DomainsDatabaseHelper.NIGHT_MODE_SYSTEM_DEFAULT) && defaultNightModeBoolean);
1409 // Disable the JavaScript `Switch` if night mode is enabled.
1410 if (currentNightModeEnabled) {
1411 javaScriptEnabledSwitch.setEnabled(false);
1413 javaScriptEnabledSwitch.setEnabled(true);
1416 // Update the JavaScript icon.
1417 if ((javaScriptEnabledInt == 1) || currentNightModeEnabled) {
1418 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.javascript_enabled));
1420 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.privacy_mode));
1423 // Update the DOM storage status.
1424 if ((javaScriptEnabledInt == 1) || currentNightModeEnabled) { // JavaScript is enabled.
1425 // Enable the DOM storage `Switch`.
1426 domStorageEnabledSwitch.setEnabled(true);
1428 // Set the DOM storage status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
1429 if (domStorageEnabledInt == 1) { // Both JavaScript and DOM storage are enabled.
1430 domStorageEnabledSwitch.setChecked(true);
1431 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_enabled));
1432 } else { // JavaScript is enabled but DOM storage is disabled.
1433 // Set the DOM storage switch to off.
1434 domStorageEnabledSwitch.setChecked(false);
1436 // Set the icon according to the theme.
1437 if (MainWebViewActivity.darkTheme) {
1438 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_dark));
1440 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_light));
1443 } else { // JavaScript is disabled.
1444 // Disable the DOM storage `Switch`.
1445 domStorageEnabledSwitch.setEnabled(false);
1447 // Set the checked status of DOM storage.
1448 if (domStorageEnabledInt == 1) { // DOM storage is enabled but JavaScript is disabled.
1449 domStorageEnabledSwitch.setChecked(true);
1450 } else { // Both JavaScript and DOM storage are disabled.
1451 domStorageEnabledSwitch.setChecked(false);
1454 // Set the icon according to the theme.
1455 if (MainWebViewActivity.darkTheme) {
1456 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_dark));
1458 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_light));
1464 public void onNothingSelected(AdapterView<?> parent) {
1469 // Set the pinned SSL certificate switch listener.
1470 pinnedSslCertificateSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1472 if (isChecked) { // Pinned SSL certificate is enabled.
1473 // Set the icon according to the theme.
1474 if (MainWebViewActivity.darkTheme) {
1475 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_dark));
1477 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_light));
1480 // Update the visibility of the saved SSL certificate.
1481 if (savedSslCertificateIssuedToCNameString == null) {
1482 savedSslCertificateLinearLayout.setVisibility(View.GONE);
1484 savedSslCertificateLinearLayout.setVisibility(View.VISIBLE);
1487 // Update the visibility of the current website SSL certificate.
1488 if (currentWebsiteSslCertificate == null) {
1489 // Hide the SSL certificate.
1490 currentWebsiteCertificateLinearLayout.setVisibility(View.GONE);
1492 // Show the instruction.
1493 noCurrentWebsiteCertificateTextView.setVisibility(View.VISIBLE);
1495 // Show the SSL certificate.
1496 currentWebsiteCertificateLinearLayout.setVisibility(View.VISIBLE);
1498 // Hide the instruction.
1499 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
1502 // Set the status of the radio buttons.
1503 if (savedSslCertificateLinearLayout.getVisibility() == View.VISIBLE) { // The saved SSL certificate is displayed.
1504 savedSslCertificateRadioButton.setChecked(true);
1505 currentWebsiteCertificateRadioButton.setChecked(false);
1506 } else if (currentWebsiteCertificateLinearLayout.getVisibility() == View.VISIBLE) { // The saved SSL certificate is hidden but the current website SSL certificate is visible.
1507 currentWebsiteCertificateRadioButton.setChecked(true);
1508 savedSslCertificateRadioButton.setChecked(false);
1509 } else { // Neither SSL certificate is visible.
1510 savedSslCertificateRadioButton.setChecked(false);
1511 currentWebsiteCertificateRadioButton.setChecked(false);
1513 } else { // Pinned SSL certificate is disabled.
1514 // Set the icon according to the theme.
1515 if (MainWebViewActivity.darkTheme) {
1516 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_dark));
1518 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_light));
1521 // Hide the SSl certificates and instructions.
1522 savedSslCertificateLinearLayout.setVisibility(View.GONE);
1523 currentWebsiteCertificateLinearLayout.setVisibility(View.GONE);
1524 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
1526 // Uncheck the radio buttons.
1527 savedSslCertificateRadioButton.setChecked(false);
1528 currentWebsiteCertificateRadioButton.setChecked(false);
1532 savedSslCertificateLinearLayout.setOnClickListener((View v) -> {
1533 savedSslCertificateRadioButton.setChecked(true);
1534 currentWebsiteCertificateRadioButton.setChecked(false);
1537 savedSslCertificateRadioButton.setOnClickListener((View v) -> {
1538 savedSslCertificateRadioButton.setChecked(true);
1539 currentWebsiteCertificateRadioButton.setChecked(false);
1542 currentWebsiteCertificateLinearLayout.setOnClickListener((View v) -> {
1543 currentWebsiteCertificateRadioButton.setChecked(true);
1544 savedSslCertificateRadioButton.setChecked(false);
1547 currentWebsiteCertificateRadioButton.setOnClickListener((View v) -> {
1548 currentWebsiteCertificateRadioButton.setChecked(true);
1549 savedSslCertificateRadioButton.setChecked(false);
1552 return domainSettingsView;
1555 private boolean checkDomainNameAgainstCertificate(String domainName, String certificateCommonName) {
1556 // Initialize `domainNamesMatch`.
1557 boolean domainNamesMatch = false;
1559 // Check if the domains match.
1560 if (domainName.equals(certificateCommonName)) {
1561 domainNamesMatch = true;
1564 // Check various wildcard permutations if `domainName` and `certificateCommonName` are not empty.
1565 // `noinspection ConstantCondition` removes Android Studio's incorrect lint warning that `domainName` can never be `null`.
1566 //noinspection ConstantConditions
1567 if ((domainName != null) && (certificateCommonName != null)) {
1568 // If `domainName` starts with a wildcard, check the base domain against all the subdomains of `certificateCommonName`.
1569 if (!domainNamesMatch && domainName.startsWith("*.") && (domainName.length() > 2)) {
1570 // Remove the initial `*.`.
1571 String baseDomainName = domainName.substring(2);
1573 // Setup a copy of `certificateCommonName` to test subdomains.
1574 String certificateCommonNameSubdomain = certificateCommonName;
1576 // Check all the subdomains in `certificateCommonNameSubdomain` against `baseDomainName`.
1577 while (!domainNamesMatch && certificateCommonNameSubdomain.contains(".")) { // Stop checking if we know that `domainNamesMatch` is `true` or if we run out of `.`.
1578 // Test the `certificateCommonNameSubdomain` against `baseDomainName`.
1579 if (certificateCommonNameSubdomain.equals(baseDomainName)) {
1580 domainNamesMatch = true;
1583 // Strip out the lowest subdomain of `certificateCommonNameSubdomain`.
1585 certificateCommonNameSubdomain = certificateCommonNameSubdomain.substring(certificateCommonNameSubdomain.indexOf(".") + 1);
1586 } catch (IndexOutOfBoundsException e) { // `certificateCommonNameSubdomain` ends with `.`.
1587 certificateCommonNameSubdomain = "";
1592 // If `certificateCommonName` starts with a wildcard, check the base common name against all the subdomains of `domainName`.
1593 if (!domainNamesMatch && certificateCommonName.startsWith("*.") && (certificateCommonName.length() > 2)) {
1594 // Remove the initial `*.`.
1595 String baseCertificateCommonName = certificateCommonName.substring(2);
1597 // Setup a copy of `domainName` to test subdomains.
1598 String domainNameSubdomain = domainName;
1600 // Check all the subdomains in `domainNameSubdomain` against `baseCertificateCommonName`.
1601 while (!domainNamesMatch && domainNameSubdomain.contains(".") && (domainNameSubdomain.length() > 2)) {
1602 // Test the `domainNameSubdomain` against `baseCertificateCommonName`.
1603 if (domainNameSubdomain.equals(baseCertificateCommonName)) {
1604 domainNamesMatch = true;
1607 // Strip out the lowest subdomain of `domainNameSubdomain`.
1609 domainNameSubdomain = domainNameSubdomain.substring(domainNameSubdomain.indexOf(".") + 1);
1610 } catch (IndexOutOfBoundsException e) { // `domainNameSubdomain` ends with `.`.
1611 domainNameSubdomain = "";
1616 // If both names start with a wildcard, check if the root of one contains the root of the other.
1617 if (!domainNamesMatch && domainName.startsWith("*.") && (domainName.length() > 2) && certificateCommonName.startsWith("*.") && (certificateCommonName.length() > 2)) {
1618 // Remove the wildcards.
1619 String rootDomainName = domainName.substring(2);
1620 String rootCertificateCommonName = certificateCommonName.substring(2);
1622 // Check if one name ends with the contents of the other. If so, there will be overlap in the their wildcard subdomains.
1623 if (rootDomainName.endsWith(rootCertificateCommonName) || rootCertificateCommonName.endsWith(rootDomainName)) {
1624 domainNamesMatch = true;
1629 return domainNamesMatch;