2 * Copyright © 2017-2020 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.Configuration;
26 import android.content.res.Resources;
27 import android.database.Cursor;
28 import android.os.Build;
29 import android.os.Bundle;
30 import android.preference.PreferenceManager;
31 import android.text.Editable;
32 import android.text.SpannableStringBuilder;
33 import android.text.Spanned;
34 import android.text.TextWatcher;
35 import android.text.style.ForegroundColorSpan;
36 import android.view.LayoutInflater;
37 import android.view.View;
38 import android.view.ViewGroup;
39 import android.webkit.WebView;
40 import android.widget.AdapterView;
41 import android.widget.ArrayAdapter;
42 import android.widget.CompoundButton;
43 import android.widget.EditText;
44 import android.widget.ImageView;
45 import android.widget.LinearLayout;
46 import android.widget.RadioButton;
47 import android.widget.Spinner;
48 import android.widget.Switch;
49 import android.widget.TextView;
51 import androidx.annotation.NonNull;
52 import androidx.cardview.widget.CardView;
53 import androidx.fragment.app.Fragment; // The AndroidX fragment must be used until minimum API >= 23. Otherwise `getContext()` does not work.
55 import com.stoutner.privacybrowser.R;
56 import com.stoutner.privacybrowser.activities.DomainsActivity;
57 import com.stoutner.privacybrowser.activities.MainWebViewActivity;
58 import com.stoutner.privacybrowser.helpers.DomainsDatabaseHelper;
60 import java.text.DateFormat;
61 import java.util.Calendar;
62 import java.util.Date;
64 public class DomainSettingsFragment extends Fragment {
65 // `DATABASE_ID` is used by activities calling this fragment.
66 public static final String DATABASE_ID = "database_id";
68 // `databaseId` is public static so it can be accessed from `DomainsActivity`. It is also used in `onCreate()` and `onCreateView()`.
69 public static int databaseId;
72 public void onCreate(Bundle savedInstanceState) {
73 // Run the default commands.
74 super.onCreate(savedInstanceState);
76 // Remove the lint warning that `getArguments` might be null.
77 assert getArguments() != null;
79 // Store the database id in `databaseId`.
80 databaseId = getArguments().getInt(DATABASE_ID);
83 // The deprecated `getDrawable()` must be used until the minimum API >= 21.
85 public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
86 // Inflate `domain_settings_fragment`. `false` does not attach it to the root `container`.
87 View domainSettingsView = inflater.inflate(R.layout.domain_settings_fragment, container, false);
89 // Get a handle for the context and the resources.
90 Context context = getContext();
91 Resources resources = getResources();
93 // Remove the error below that the context might be null.
94 assert context != null;
96 // Get the current theme status.
97 int currentThemeStatus = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
99 // Get a handle for the shared preference.
100 SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
102 // Store the default settings.
103 String defaultUserAgentName = sharedPreferences.getString("user_agent", getString(R.string.user_agent_default_value));
104 String defaultCustomUserAgentString = sharedPreferences.getString("custom_user_agent", getString(R.string.custom_user_agent_default_value));
105 String defaultFontSizeString = sharedPreferences.getString("font_size", getString(R.string.font_size_default_value));
106 boolean defaultSwipeToRefresh = sharedPreferences.getBoolean("swipe_to_refresh", true);
107 String defaultWebViewTheme = sharedPreferences.getString("webview_theme", getString(R.string.webview_theme_default_value));
108 boolean defaultWideViewport = sharedPreferences.getBoolean("wide_viewport", true);
109 boolean defaultDisplayWebpageImages = sharedPreferences.getBoolean("display_webpage_images", true);
111 // Get handles for the views in the fragment.
112 EditText domainNameEditText = domainSettingsView.findViewById(R.id.domain_settings_name_edittext);
113 ImageView javaScriptImageView = domainSettingsView.findViewById(R.id.javascript_imageview);
114 Switch javaScriptSwitch = domainSettingsView.findViewById(R.id.javascript_switch);
115 ImageView firstPartyCookiesImageView = domainSettingsView.findViewById(R.id.first_party_cookies_imageview);
116 Switch firstPartyCookiesSwitch = domainSettingsView.findViewById(R.id.first_party_cookies_switch);
117 LinearLayout thirdPartyCookiesLinearLayout = domainSettingsView.findViewById(R.id.third_party_cookies_linearlayout);
118 ImageView thirdPartyCookiesImageView = domainSettingsView.findViewById(R.id.third_party_cookies_imageview);
119 Switch thirdPartyCookiesSwitch = domainSettingsView.findViewById(R.id.third_party_cookies_switch);
120 ImageView domStorageImageView = domainSettingsView.findViewById(R.id.dom_storage_imageview);
121 Switch domStorageSwitch = domainSettingsView.findViewById(R.id.dom_storage_switch);
122 ImageView formDataImageView = domainSettingsView.findViewById(R.id.form_data_imageview); // The form data views can be remove once the minimum API >= 26.
123 Switch formDataSwitch = domainSettingsView.findViewById(R.id.form_data_switch); // The form data views can be remove once the minimum API >= 26.
124 ImageView easyListImageView = domainSettingsView.findViewById(R.id.easylist_imageview);
125 Switch easyListSwitch = domainSettingsView.findViewById(R.id.easylist_switch);
126 ImageView easyPrivacyImageView = domainSettingsView.findViewById(R.id.easyprivacy_imageview);
127 Switch easyPrivacySwitch = domainSettingsView.findViewById(R.id.easyprivacy_switch);
128 ImageView fanboysAnnoyanceListImageView = domainSettingsView.findViewById(R.id.fanboys_annoyance_list_imageview);
129 Switch fanboysAnnoyanceListSwitch = domainSettingsView.findViewById(R.id.fanboys_annoyance_list_switch);
130 ImageView fanboysSocialBlockingListImageView = domainSettingsView.findViewById(R.id.fanboys_social_blocking_list_imageview);
131 Switch fanboysSocialBlockingListSwitch = domainSettingsView.findViewById(R.id.fanboys_social_blocking_list_switch);
132 ImageView ultraListImageView = domainSettingsView.findViewById(R.id.ultralist_imageview);
133 Switch ultraListSwitch = domainSettingsView.findViewById(R.id.ultralist_switch);
134 ImageView ultraPrivacyImageView = domainSettingsView.findViewById(R.id.ultraprivacy_imageview);
135 Switch ultraPrivacySwitch = domainSettingsView.findViewById(R.id.ultraprivacy_switch);
136 ImageView blockAllThirdPartyRequestsImageView = domainSettingsView.findViewById(R.id.block_all_third_party_requests_imageview);
137 Switch blockAllThirdPartyRequestsSwitch = domainSettingsView.findViewById(R.id.block_all_third_party_requests_switch);
138 Spinner userAgentSpinner = domainSettingsView.findViewById(R.id.user_agent_spinner);
139 TextView userAgentTextView = domainSettingsView.findViewById(R.id.user_agent_textview);
140 EditText customUserAgentEditText = domainSettingsView.findViewById(R.id.custom_user_agent_edittext);
141 Spinner fontSizeSpinner = domainSettingsView.findViewById(R.id.font_size_spinner);
142 TextView defaultFontSizeTextView = domainSettingsView.findViewById(R.id.default_font_size_textview);
143 EditText customFontSizeEditText = domainSettingsView.findViewById(R.id.custom_font_size_edittext);
144 ImageView swipeToRefreshImageView = domainSettingsView.findViewById(R.id.swipe_to_refresh_imageview);
145 Spinner swipeToRefreshSpinner = domainSettingsView.findViewById(R.id.swipe_to_refresh_spinner);
146 TextView swipeToRefreshTextView = domainSettingsView.findViewById(R.id.swipe_to_refresh_textview);
147 ImageView webViewThemeImageView = domainSettingsView.findViewById(R.id.webview_theme_imageview);
148 Spinner webViewThemeSpinner = domainSettingsView.findViewById(R.id.webview_theme_spinner);
149 TextView webViewThemeTextView = domainSettingsView.findViewById(R.id.webview_theme_textview);
150 ImageView wideViewportImageView = domainSettingsView.findViewById(R.id.wide_viewport_imageview);
151 Spinner wideViewportSpinner = domainSettingsView.findViewById(R.id.wide_viewport_spinner);
152 TextView wideViewportTextView = domainSettingsView.findViewById(R.id.wide_viewport_textview);
153 ImageView displayWebpageImagesImageView = domainSettingsView.findViewById(R.id.display_webpage_images_imageview);
154 Spinner displayWebpageImagesSpinner = domainSettingsView.findViewById(R.id.display_webpage_images_spinner);
155 TextView displayImagesTextView = domainSettingsView.findViewById(R.id.display_webpage_images_textview);
156 ImageView pinnedSslCertificateImageView = domainSettingsView.findViewById(R.id.pinned_ssl_certificate_imageview);
157 Switch pinnedSslCertificateSwitch = domainSettingsView.findViewById(R.id.pinned_ssl_certificate_switch);
158 CardView savedSslCardView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_cardview);
159 LinearLayout savedSslCertificateLinearLayout = domainSettingsView.findViewById(R.id.saved_ssl_certificate_linearlayout);
160 RadioButton savedSslCertificateRadioButton = domainSettingsView.findViewById(R.id.saved_ssl_certificate_radiobutton);
161 TextView savedSslIssuedToCNameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_to_cname);
162 TextView savedSslIssuedToONameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_to_oname);
163 TextView savedSslIssuedToUNameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_to_uname);
164 TextView savedSslIssuedByCNameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_by_cname);
165 TextView savedSslIssuedByONameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_by_oname);
166 TextView savedSslIssuedByUNameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_by_uname);
167 TextView savedSslStartDateTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_start_date);
168 TextView savedSslEndDateTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_end_date);
169 CardView currentSslCardView = domainSettingsView.findViewById(R.id.current_website_certificate_cardview);
170 LinearLayout currentWebsiteCertificateLinearLayout = domainSettingsView.findViewById(R.id.current_website_certificate_linearlayout);
171 RadioButton currentWebsiteCertificateRadioButton = domainSettingsView.findViewById(R.id.current_website_certificate_radiobutton);
172 TextView currentSslIssuedToCNameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_to_cname);
173 TextView currentSslIssuedToONameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_to_oname);
174 TextView currentSslIssuedToUNameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_to_uname);
175 TextView currentSslIssuedByCNameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_by_cname);
176 TextView currentSslIssuedByONameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_by_oname);
177 TextView currentSslIssuedByUNameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_by_uname);
178 TextView currentSslStartDateTextView = domainSettingsView.findViewById(R.id.current_website_certificate_start_date);
179 TextView currentSslEndDateTextView = domainSettingsView.findViewById(R.id.current_website_certificate_end_date);
180 TextView noCurrentWebsiteCertificateTextView = domainSettingsView.findViewById(R.id.no_current_website_certificate);
181 ImageView pinnedIpAddressesImageView = domainSettingsView.findViewById(R.id.pinned_ip_addresses_imageview);
182 Switch pinnedIpAddressesSwitch = domainSettingsView.findViewById(R.id.pinned_ip_addresses_switch);
183 CardView savedIpAddressesCardView = domainSettingsView.findViewById(R.id.saved_ip_addresses_cardview);
184 LinearLayout savedIpAddressesLinearLayout = domainSettingsView.findViewById(R.id.saved_ip_addresses_linearlayout);
185 RadioButton savedIpAddressesRadioButton = domainSettingsView.findViewById(R.id.saved_ip_addresses_radiobutton);
186 TextView savedIpAddressesTextView = domainSettingsView.findViewById(R.id.saved_ip_addresses_textview);
187 CardView currentIpAddressesCardView = domainSettingsView.findViewById(R.id.current_ip_addresses_cardview);
188 LinearLayout currentIpAddressesLinearLayout = domainSettingsView.findViewById(R.id.current_ip_addresses_linearlayout);
189 RadioButton currentIpAddressesRadioButton = domainSettingsView.findViewById(R.id.current_ip_addresses_radiobutton);
190 TextView currentIpAddressesTextView = domainSettingsView.findViewById(R.id.current_ip_addresses_textview);
192 // Setup the pinned labels.
193 String cNameLabel = getString(R.string.common_name) + " ";
194 String oNameLabel = getString(R.string.organization) + " ";
195 String uNameLabel = getString(R.string.organizational_unit) + " ";
196 String startDateLabel = getString(R.string.start_date) + " ";
197 String endDateLabel = getString(R.string.end_date) + " ";
199 // Initialize the database handler. The `0` specifies the database version, but that is ignored and set instead using a constant in `DomainsDatabaseHelper`.
200 DomainsDatabaseHelper domainsDatabaseHelper = new DomainsDatabaseHelper(context, null, null, 0);
202 // Get the database cursor for this ID and move it to the first row.
203 Cursor domainCursor = domainsDatabaseHelper.getCursorForId(databaseId);
204 domainCursor.moveToFirst();
206 // Save the cursor entries as variables.
207 String domainNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.DOMAIN_NAME));
208 int javaScriptInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_JAVASCRIPT));
209 int firstPartyCookiesInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FIRST_PARTY_COOKIES));
210 int thirdPartyCookiesInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_THIRD_PARTY_COOKIES));
211 int domStorageInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_DOM_STORAGE));
212 int formDataInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FORM_DATA)); // Form data can be remove once the minimum API >= 26.
213 int easyListInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYLIST));
214 int easyPrivacyInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYPRIVACY));
215 int fanboysAnnoyanceListInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST));
216 int fanboysSocialBlockingListInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST));
217 int ultraListInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ULTRALIST));
218 int ultraPrivacyInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY));
219 int blockAllThirdPartyRequestsInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS));
220 String currentUserAgentName = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.USER_AGENT));
221 int fontSizeInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.FONT_SIZE));
222 int swipeToRefreshInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.SWIPE_TO_REFRESH));
223 int webViewThemeInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.WEBVIEW_THEME));
224 int wideViewportInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.WIDE_VIEWPORT));
225 int displayImagesInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.DISPLAY_IMAGES));
226 int pinnedSslCertificateInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.PINNED_SSL_CERTIFICATE));
227 String savedSslIssuedToCNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_COMMON_NAME));
228 String savedSslIssuedToONameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATION));
229 String savedSslIssuedToUNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATIONAL_UNIT));
230 String savedSslIssuedByCNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_COMMON_NAME));
231 String savedSslIssuedByONameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATION));
232 String savedSslIssuedByUNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATIONAL_UNIT));
233 int pinnedIpAddressesInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.PINNED_IP_ADDRESSES));
234 String savedIpAddresses = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.IP_ADDRESSES));
236 // Initialize the saved SSL certificate date variables.
237 Date savedSslStartDate = null;
238 Date savedSslEndDate = null;
240 // Only get the saved SSL certificate dates from the cursor if they are not set to `0`.
241 if (domainCursor.getLong(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_START_DATE)) != 0) {
242 savedSslStartDate = new Date(domainCursor.getLong(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_START_DATE)));
245 if (domainCursor.getLong(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_END_DATE)) != 0) {
246 savedSslEndDate = new Date(domainCursor.getLong(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_END_DATE)));
249 // Create array adapters for the spinners.
250 ArrayAdapter<CharSequence> translatedUserAgentArrayAdapter = ArrayAdapter.createFromResource(context, R.array.translated_domain_settings_user_agent_names, R.layout.spinner_item);
251 ArrayAdapter<CharSequence> fontSizeArrayAdapter = ArrayAdapter.createFromResource(context, R.array.font_size_array, R.layout.spinner_item);
252 ArrayAdapter<CharSequence> swipeToRefreshArrayAdapter = ArrayAdapter.createFromResource(context, R.array.swipe_to_refresh_array, R.layout.spinner_item);
253 ArrayAdapter<CharSequence> webViewThemeArrayAdapter = ArrayAdapter.createFromResource(context, R.array.webview_theme_array, R.layout.spinner_item);
254 ArrayAdapter<CharSequence> wideViewportArrayAdapter = ArrayAdapter.createFromResource(context, R.array.wide_viewport_array, R.layout.spinner_item);
255 ArrayAdapter<CharSequence> displayImagesArrayAdapter = ArrayAdapter.createFromResource(context, R.array.display_webpage_images_array, R.layout.spinner_item);
257 // Set the drop down view resource on the spinners.
258 translatedUserAgentArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items);
259 fontSizeArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items);
260 swipeToRefreshArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items);
261 webViewThemeArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items);
262 wideViewportArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items);
263 displayImagesArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items);
265 // Set the array adapters for the spinners.
266 userAgentSpinner.setAdapter(translatedUserAgentArrayAdapter);
267 fontSizeSpinner.setAdapter(fontSizeArrayAdapter);
268 swipeToRefreshSpinner.setAdapter(swipeToRefreshArrayAdapter);
269 webViewThemeSpinner.setAdapter(webViewThemeArrayAdapter);
270 wideViewportSpinner.setAdapter(wideViewportArrayAdapter);
271 displayWebpageImagesSpinner.setAdapter(displayImagesArrayAdapter);
273 // Create a spannable string builder for each TextView that needs multiple colors of text.
274 SpannableStringBuilder savedSslIssuedToCNameStringBuilder = new SpannableStringBuilder(cNameLabel + savedSslIssuedToCNameString);
275 SpannableStringBuilder savedSslIssuedToONameStringBuilder = new SpannableStringBuilder(oNameLabel + savedSslIssuedToONameString);
276 SpannableStringBuilder savedSslIssuedToUNameStringBuilder = new SpannableStringBuilder(uNameLabel + savedSslIssuedToUNameString);
277 SpannableStringBuilder savedSslIssuedByCNameStringBuilder = new SpannableStringBuilder(cNameLabel + savedSslIssuedByCNameString);
278 SpannableStringBuilder savedSslIssuedByONameStringBuilder = new SpannableStringBuilder(oNameLabel + savedSslIssuedByONameString);
279 SpannableStringBuilder savedSslIssuedByUNameStringBuilder = new SpannableStringBuilder(uNameLabel + savedSslIssuedByUNameString);
281 // Initialize the spannable string builders for the saved SSL certificate dates.
282 SpannableStringBuilder savedSslStartDateStringBuilder;
283 SpannableStringBuilder savedSslEndDateStringBuilder;
285 // Leave the SSL certificate dates empty if they are `null`.
286 if (savedSslStartDate == null) {
287 savedSslStartDateStringBuilder = new SpannableStringBuilder(startDateLabel);
289 savedSslStartDateStringBuilder = new SpannableStringBuilder(startDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG).format(savedSslStartDate));
292 if (savedSslEndDate == null) {
293 savedSslEndDateStringBuilder = new SpannableStringBuilder(endDateLabel);
295 savedSslEndDateStringBuilder = new SpannableStringBuilder(endDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG).format(savedSslEndDate));
298 // Create the foreground color spans.
299 final ForegroundColorSpan redColorSpan;
300 final ForegroundColorSpan blueColorSpan;
302 // Set the color spans according to the theme. The deprecated `resources` must be used until the minimum API >= 23.
303 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
304 redColorSpan = new ForegroundColorSpan(resources.getColor(R.color.red_900));
305 blueColorSpan = new ForegroundColorSpan(resources.getColor(R.color.violet_500));
307 redColorSpan = new ForegroundColorSpan(resources.getColor(R.color.red_a700));
308 blueColorSpan = new ForegroundColorSpan(resources.getColor(R.color.blue_700));
311 // Set the domain name from the the database cursor.
312 domainNameEditText.setText(domainNameString);
314 // Update the certificates' `Common Name` color when the domain name text changes.
315 domainNameEditText.addTextChangedListener(new TextWatcher() {
317 public void beforeTextChanged(CharSequence s, int start, int count, int after) {
322 public void onTextChanged(CharSequence s, int start, int before, int count) {
327 public void afterTextChanged(Editable s) {
328 // Get the new domain name.
329 String newDomainName = domainNameEditText.getText().toString();
331 // Check the saved SSL certificate against the new domain name.
332 boolean savedSslMatchesNewDomainName = checkDomainNameAgainstCertificate(newDomainName, savedSslIssuedToCNameString);
334 // Create a `SpannableStringBuilder` for the saved certificate `Common Name`.
335 SpannableStringBuilder savedSslCNameStringBuilder = new SpannableStringBuilder(cNameLabel + savedSslIssuedToCNameString);
337 // Format the saved certificate `Common Name` color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
338 if (savedSslMatchesNewDomainName) {
339 savedSslCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), savedSslCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
341 savedSslCNameStringBuilder.setSpan(redColorSpan, cNameLabel.length(), savedSslCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
344 // Update the saved SSL issued to CName text view.
345 savedSslIssuedToCNameTextView.setText(savedSslCNameStringBuilder);
347 // Update the current website certificate if it exists.
348 if (DomainsActivity.sslIssuedToCName != null) {
349 // Check the current website certificate against the new domain name.
350 boolean currentSslMatchesNewDomainName = checkDomainNameAgainstCertificate(newDomainName, DomainsActivity.sslIssuedToCName);
352 // Create a `SpannableStringBuilder` for the current website certificate `Common Name`.
353 SpannableStringBuilder currentSslCNameStringBuilder = new SpannableStringBuilder(cNameLabel + DomainsActivity.sslIssuedToCName);
355 // Format the current certificate `Common Name` color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
356 if (currentSslMatchesNewDomainName) {
357 currentSslCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), currentSslCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
359 currentSslCNameStringBuilder.setSpan(redColorSpan, cNameLabel.length(), currentSslCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
362 // Update the current SSL issued to CName text view.
363 currentSslIssuedToCNameTextView.setText(currentSslCNameStringBuilder);
368 // Set the JavaScript switch status.
369 if (javaScriptInt == 1) { // JavaScript is enabled.
370 javaScriptSwitch.setChecked(true);
371 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.javascript_enabled));
372 } else { // JavaScript is disabled.
373 javaScriptSwitch.setChecked(false);
374 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.privacy_mode));
377 // 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.
378 if (firstPartyCookiesInt == 1) { // First-party cookies are enabled.
379 firstPartyCookiesSwitch.setChecked(true);
380 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_enabled));
381 } else { // First-party cookies are disabled.
382 firstPartyCookiesSwitch.setChecked(false);
384 // Set the icon according to the theme.
385 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
386 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_night));
388 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_day));
392 // Only display third-party cookies if SDK_INT >= 21.
393 if (Build.VERSION.SDK_INT >= 21) { // Third-party cookies can be configured for API >= 21.
394 // Only enable third-party-cookies if first-party cookies are enabled.
395 if (firstPartyCookiesInt == 1) { // First-party cookies are enabled.
396 // 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.
397 if (thirdPartyCookiesInt == 1) { // Both first-party and third-party cookies are enabled.
398 // Set the third-party cookies switch to be checked.
399 thirdPartyCookiesSwitch.setChecked(true);
401 // Set the icon to be red.
402 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_warning));
403 } else { // First party cookies are enabled but third-party cookies are disabled.
404 // Set the third-party cookies switch to be checked.
405 thirdPartyCookiesSwitch.setChecked(false);
407 // Set the icon according to the theme.
408 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
409 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_night));
411 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_day));
414 } else { // First-party cookies are disabled.
415 // Set the status of third-party cookies.
416 if (thirdPartyCookiesInt == 1) {
417 thirdPartyCookiesSwitch.setChecked(true);
419 thirdPartyCookiesSwitch.setChecked(false);
422 // Disable the third-party cookies switch.
423 thirdPartyCookiesSwitch.setEnabled(false);
425 // Set the icon according to the theme.
426 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
427 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_ghosted_night));
429 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_ghosted_day));
432 } else { // Third-party cookies cannot be configured for API <= 21.
433 // Hide the LinearLayout for third-party cookies.
434 thirdPartyCookiesLinearLayout.setVisibility(View.GONE);
437 // Only enable DOM storage if JavaScript is enabled.
438 if (javaScriptInt == 1) { // JavaScript is enabled.
439 // Enable the DOM storage `Switch`.
440 domStorageSwitch.setEnabled(true);
442 // Set the DOM storage status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
443 if (domStorageInt == 1) { // Both JavaScript and DOM storage are enabled.
444 domStorageSwitch.setChecked(true);
445 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_enabled));
446 } else { // JavaScript is enabled but DOM storage is disabled.
447 // Set the DOM storage switch to off.
448 domStorageSwitch.setChecked(false);
450 // Set the icon according to the theme.
451 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
452 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_night));
454 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_day));
457 } else { // JavaScript is disabled.
458 // Disable the DOM storage `Switch`.
459 domStorageSwitch.setEnabled(false);
461 // Set the checked status of DOM storage.
462 if (domStorageInt == 1) { // DOM storage is enabled but JavaScript is disabled.
463 domStorageSwitch.setChecked(true);
464 } else { // Both JavaScript and DOM storage are disabled.
465 domStorageSwitch.setChecked(false);
468 // Set the icon according to the theme.
469 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
470 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_night));
472 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_day));
476 // Set the form data visibility. Form data can be removed once the minimum API >= 26.
477 if (Build.VERSION.SDK_INT >= 26) { // Form data no longer applies to newer versions of Android.
478 // Hide the form data image view and switch.
479 formDataImageView.setVisibility(View.GONE);
480 formDataSwitch.setVisibility(View.GONE);
481 } else { // Form data should be displayed because this is an older version of Android.
482 if (formDataInt == 1) { // Form data is on.
483 // Turn the form data switch on.
484 formDataSwitch.setChecked(true);
486 // Set the form data icon.
487 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_enabled));
488 } else { // Form data is off.
489 // Turn the form data switch to off.
490 formDataSwitch.setChecked(false);
492 // Set the icon according to the theme. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
493 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
494 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_disabled_night));
496 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_disabled_day));
501 // Set the EasyList status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
502 if (easyListInt == 1) { // EasyList is on.
503 // Turn the switch on.
504 easyListSwitch.setChecked(true);
506 // Set the icon according to the theme.
507 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
508 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_night));
510 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_day));
512 } else { // EasyList is off.
513 // Turn the switch off.
514 easyListSwitch.setChecked(false);
516 // Set the icon according to the theme.
517 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
518 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_night));
520 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_day));
524 // Set the EasyPrivacy status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
525 if (easyPrivacyInt == 1) { // EasyPrivacy is on.
526 // Turn the switch on.
527 easyPrivacySwitch.setChecked(true);
529 // Set the icon according to the theme.
530 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
531 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_night));
533 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_day));
535 } else { // EasyPrivacy is off.
536 // Turn the switch off.
537 easyPrivacySwitch.setChecked(false);
539 // Set the icon according to the theme.
540 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
541 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_night));
543 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_day));
547 // 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.
548 if (fanboysAnnoyanceListInt == 1) { // Fanboy's Annoyance List is on.
549 // Turn the switch on.
550 fanboysAnnoyanceListSwitch.setChecked(true);
552 // Set the icon according to the theme.
553 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
554 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_night));
556 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_day));
558 } else { // Fanboy's Annoyance List is off.
559 // Turn the switch off.
560 fanboysAnnoyanceListSwitch.setChecked(false);
562 // Set the icon according to the theme.
563 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
564 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_night));
566 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_day));
570 // Only enable Fanboy's Social Blocking List if Fanboy's Annoyance List is off.
571 if (fanboysAnnoyanceListInt == 0) { // Fanboy's Annoyance List is on.
572 // Enable Fanboy's Social Blocking List switch.
573 fanboysSocialBlockingListSwitch.setEnabled(true);
575 // 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.
576 if (fanboysSocialBlockingListInt == 1) { // Fanboy's Social Blocking List is on.
577 // Turn on Fanboy's Social Blocking List switch.
578 fanboysSocialBlockingListSwitch.setChecked(true);
580 // Set the icon according to the theme.
581 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
582 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_night));
584 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_day));
586 } else { // Fanboy's Social Blocking List is off.
587 // Turn off Fanboy's Social Blocking List switch.
588 fanboysSocialBlockingListSwitch.setChecked(false);
590 // Set the icon according to the theme.
591 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
592 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_night));
594 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_day));
597 } else { // Fanboy's Annoyance List is on.
598 // Disable Fanboy's Social Blocking List switch.
599 fanboysSocialBlockingListSwitch.setEnabled(false);
601 // Handle the status of Fanboy's Social Blocking List. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
602 if (fanboysSocialBlockingListInt == 1) { // Fanboy's Social Blocking List is on.
603 // Turn on Fanboy's Social Blocking List switch.
604 fanboysSocialBlockingListSwitch.setChecked(true);
605 } else { // Fanboy's Social Blocking List is off.
606 // Turn off Fanboy's Social Blocking List switch.
607 fanboysSocialBlockingListSwitch.setChecked(false);
610 // Set the icon according to the theme.
611 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
612 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_ghosted_night));
614 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_ghosted_day));
618 // Set the UltraList status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
619 if (ultraListInt == 1) { // UltraList is on.
620 // Turn the switch on.
621 ultraListSwitch.setChecked(true);
623 // Set the icon according to the theme.
624 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
625 ultraListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_night));
627 ultraListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_day));
629 } else { // UltraList is off.
630 // Turn the switch off.
631 ultraListSwitch.setChecked(false);
633 // Set the icon according to the theme.
634 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
635 ultraListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_night));
637 ultraListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_day));
641 // Set the UltraPrivacy status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
642 if (ultraPrivacyInt == 1) { // UltraPrivacy is on.
643 // Turn the switch on.
644 ultraPrivacySwitch.setChecked(true);
646 // Set the icon according to the theme.
647 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
648 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_night));
650 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_day));
652 } else { // EasyPrivacy is off.
653 // Turn the switch off.
654 ultraPrivacySwitch.setChecked(false);
656 // Set the icon according to the theme.
657 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
658 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_night));
660 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_day));
664 // Set the third-party resource blocking status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
665 if (blockAllThirdPartyRequestsInt == 1) { // Blocking all third-party requests is on.
666 // Turn the switch on.
667 blockAllThirdPartyRequestsSwitch.setChecked(true);
669 // Set the icon according to the theme.
670 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
671 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_enabled_night));
673 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_enabled_day));
675 } else { // Blocking all third-party requests is off.
676 // Turn the switch off.
677 blockAllThirdPartyRequestsSwitch.setChecked(false);
679 // Set the icon according to the theme.
680 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
681 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_disabled_night));
683 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_disabled_day));
687 // Inflated a WebView to get the default user agent.
688 // `@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.
689 @SuppressLint("InflateParams") View bareWebViewLayout = inflater.inflate(R.layout.bare_webview, null, false);
690 WebView bareWebView = bareWebViewLayout.findViewById(R.id.bare_webview);
691 final String webViewDefaultUserAgentString = bareWebView.getSettings().getUserAgentString();
693 // Get a handle for the user agent array adapter. This array does not contain the `System default` entry.
694 ArrayAdapter<CharSequence> userAgentNamesArray = ArrayAdapter.createFromResource(context, R.array.user_agent_names, R.layout.spinner_item);
696 // Get the positions of the user agent and the default user agent.
697 int userAgentArrayPosition = userAgentNamesArray.getPosition(currentUserAgentName);
698 int defaultUserAgentArrayPosition = userAgentNamesArray.getPosition(defaultUserAgentName);
700 // Get a handle for the user agent data array. This array does not contain the `System default` entry.
701 String[] userAgentDataArray = resources.getStringArray(R.array.user_agent_data);
703 // Set the user agent text.
704 if (currentUserAgentName.equals(getString(R.string.system_default_user_agent))) { // Use the system default user agent.
705 // Set the user agent according to the system default.
706 switch (defaultUserAgentArrayPosition) {
707 case MainWebViewActivity.UNRECOGNIZED_USER_AGENT: // The default user agent name is not on the canonical list.
708 // This is probably because it was set in an older version of Privacy Browser before the switch to persistent user agent names.
709 userAgentTextView.setText(defaultUserAgentName);
712 case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
713 // Display the `WebView` default user agent.
714 userAgentTextView.setText(webViewDefaultUserAgentString);
717 case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
718 // Display the custom user agent.
719 userAgentTextView.setText(defaultCustomUserAgentString);
723 // Get the user agent string from the user agent data array.
724 userAgentTextView.setText(userAgentDataArray[defaultUserAgentArrayPosition]);
726 } else if (userAgentArrayPosition == MainWebViewActivity.UNRECOGNIZED_USER_AGENT) { // A custom user agent is stored in the current user agent name.
727 // Set the user agent spinner to `Custom user agent`.
728 userAgentSpinner.setSelection(MainWebViewActivity.DOMAINS_CUSTOM_USER_AGENT);
730 // Hide the user agent TextView.
731 userAgentTextView.setVisibility(View.GONE);
733 // Show the custom user agent EditText and set the current user agent name as the text.
734 customUserAgentEditText.setVisibility(View.VISIBLE);
735 customUserAgentEditText.setText(currentUserAgentName);
736 } else { // The user agent name contains one of the canonical user agents.
737 // 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.
738 userAgentSpinner.setSelection(userAgentArrayPosition + 1);
740 // Show the user agent TextView.
741 userAgentTextView.setVisibility(View.VISIBLE);
743 // Hide the custom user agent EditText.
744 customUserAgentEditText.setVisibility(View.GONE);
746 // Set the user agent text.
747 if (userAgentArrayPosition == MainWebViewActivity.DOMAINS_WEBVIEW_DEFAULT_USER_AGENT) { // The WebView default user agent is selected.
748 // Display the WebView default user agent.
749 userAgentTextView.setText(webViewDefaultUserAgentString);
750 } else { // A user agent besides the default is selected.
751 // 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.
752 userAgentTextView.setText(userAgentDataArray[userAgentArrayPosition + 1]);
756 // Open the user agent spinner when the text view is clicked.
757 userAgentTextView.setOnClickListener((View v) -> {
758 // Open the user agent spinner.
759 userAgentSpinner.performClick();
762 // Display the font size settings.
763 if (fontSizeInt == 0) { // `0` is the code for system default font size.
764 // Set the font size to the system default
765 fontSizeSpinner.setSelection(0);
767 // Show the default font size text view.
768 defaultFontSizeTextView.setVisibility(View.VISIBLE);
770 // Hide the custom font size edit text.
771 customFontSizeEditText.setVisibility(View.GONE);
773 // Set the default font size as the text of the custom font size edit text. This way, if the user switches to custom it will already be populated.
774 customFontSizeEditText.setText(defaultFontSizeString);
775 } else { // A custom font size is selected.
776 // Set the spinner to the custom font size.
777 fontSizeSpinner.setSelection(1);
779 // Hide the default font size text view.
780 defaultFontSizeTextView.setVisibility(View.GONE);
782 // Show the custom font size edit text.
783 customFontSizeEditText.setVisibility(View.GONE);
785 // Set the custom font size.
786 customFontSizeEditText.setText(String.valueOf(fontSizeInt));
789 // Initialize the default font size percentage string.
790 String defaultFontSizePercentageString = defaultFontSizeString + "%";
792 // Set the default font size text in the text view.
793 defaultFontSizeTextView.setText(defaultFontSizePercentageString);
795 // Open the font size spinner when the text view is clicked.
796 defaultFontSizeTextView.setOnClickListener((View v) -> {
797 // Open the user agent spinner.
798 fontSizeSpinner.performClick();
801 // Select the swipe to refresh selection in the spinner.
802 swipeToRefreshSpinner.setSelection(swipeToRefreshInt);
804 // Set the swipe to refresh text.
805 if (defaultSwipeToRefresh) {
806 swipeToRefreshTextView.setText(swipeToRefreshArrayAdapter.getItem(DomainsDatabaseHelper.ENABLED));
808 swipeToRefreshTextView.setText(swipeToRefreshArrayAdapter.getItem(DomainsDatabaseHelper.DISABLED));
811 // 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.
812 switch (swipeToRefreshInt) {
813 case DomainsDatabaseHelper.SYSTEM_DEFAULT:
814 if (defaultSwipeToRefresh) { // Swipe to refresh is enabled by default.
815 // Set the icon according to the theme.
816 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
817 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_night));
819 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_day));
821 } else { // Swipe to refresh is disabled by default
822 // Set the icon according to the theme.
823 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
824 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_night));
826 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_day));
830 // Show the swipe to refresh TextView.
831 swipeToRefreshTextView.setVisibility(View.VISIBLE);
834 case DomainsDatabaseHelper.ENABLED:
835 // Set the icon according to the theme.
836 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
837 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_night));
839 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_day));
842 // Hide the swipe to refresh TextView.`
843 swipeToRefreshTextView.setVisibility(View.GONE);
846 case DomainsDatabaseHelper.DISABLED:
847 // Set the icon according to the theme.
848 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
849 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_night));
851 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_day));
854 // Hide the swipe to refresh TextView.
855 swipeToRefreshTextView.setVisibility(View.GONE);
858 // Open the swipe to refresh spinner when the TextView is clicked.
859 swipeToRefreshTextView.setOnClickListener((View v) -> {
860 // Open the swipe to refresh spinner.
861 swipeToRefreshSpinner.performClick();
864 // Get the WebView theme string arrays.
865 String[] webViewThemeStringArray = resources.getStringArray(R.array.webview_theme_array);
866 String[] webViewThemeEntryValuesStringArray = resources.getStringArray(R.array.webview_theme_entry_values);
868 // Define an app WebView theme entry number.
869 int appWebViewThemeEntryNumber;
871 // Get the WebView theme entry number that matches the current WebView theme. A switch statement cannot be used because the WebView theme entry values string array is not a compile time constant.
872 if (defaultWebViewTheme.equals(webViewThemeEntryValuesStringArray[1])) { // The light theme is selected.
873 // Store the default WebView theme entry number.
874 appWebViewThemeEntryNumber = 1;
875 } else if (defaultWebViewTheme.equals(webViewThemeEntryValuesStringArray[2])) { // The dark theme is selected.
876 // Store the default WebView theme entry number.
877 appWebViewThemeEntryNumber = 2;
878 } else { // The system default theme is selected.
879 // Store the default WebView theme entry number.
880 appWebViewThemeEntryNumber = 0;
883 // Set the WebView theme visibility.
884 if (Build.VERSION.SDK_INT < 21) { // The WebView theme cannot be set on API 19.
885 // Get a handle for the webView theme linear layout.
886 LinearLayout webViewThemeLinearLayout = domainSettingsView.findViewById(R.id.webview_theme_linearlayout);
888 // Hide the WebView theme linear layout.
889 webViewThemeLinearLayout.setVisibility(View.GONE);
890 } else { // The WebView theme can be set on API >= 21.
891 // Select the WebView theme in the spinner.
892 webViewThemeSpinner.setSelection(webViewThemeInt);
894 // Set the WebView theme text.
895 if (appWebViewThemeEntryNumber == DomainsDatabaseHelper.SYSTEM_DEFAULT) { // The app WebView theme is system default.
896 // Set the text according to the current UI theme.
897 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
898 webViewThemeTextView.setText(webViewThemeStringArray[DomainsDatabaseHelper.LIGHT_THEME]);
900 webViewThemeTextView.setText(webViewThemeStringArray[DomainsDatabaseHelper.DARK_THEME]);
902 } else { // The app WebView theme is not system default.
903 // Set the text according to the app WebView theme.
904 webViewThemeTextView.setText(webViewThemeStringArray[appWebViewThemeEntryNumber]);
907 // Set the WebView theme icon and text visibility. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
908 switch (webViewThemeInt) {
909 case DomainsDatabaseHelper.SYSTEM_DEFAULT: // The domain WebView theme is system default.
910 // Set the icon according to the app WebView theme.
911 switch (appWebViewThemeEntryNumber) {
912 case DomainsDatabaseHelper.SYSTEM_DEFAULT: // The default WebView theme is system default.
913 // Set the icon according to the app theme.
914 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
915 // Set the light mode icon.
916 webViewThemeImageView.setImageDrawable(resources.getDrawable(R.drawable.webview_light_theme_day));
918 // Set the dark theme icon.
919 webViewThemeImageView.setImageDrawable(resources.getDrawable(R.drawable.webview_dark_theme_night));
923 case DomainsDatabaseHelper.LIGHT_THEME: // the default WebView theme is light.
924 // Set the icon according to the app theme.
925 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
926 webViewThemeImageView.setImageDrawable(resources.getDrawable(R.drawable.webview_light_theme_day));
928 webViewThemeImageView.setImageDrawable(resources.getDrawable(R.drawable.webview_light_theme_night));
932 case DomainsDatabaseHelper.DARK_THEME: // the default WebView theme is dark.
933 // Set the icon according to the app theme.
934 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
935 webViewThemeImageView.setImageDrawable(resources.getDrawable(R.drawable.webview_dark_theme_day));
937 webViewThemeImageView.setImageDrawable(resources.getDrawable(R.drawable.webview_dark_theme_night));
942 // Show the WebView theme text view.
943 webViewThemeTextView.setVisibility(View.VISIBLE);
946 case DomainsDatabaseHelper.LIGHT_THEME: // The domain WebView theme is light.
947 // Set the icon according to the app theme.
948 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
949 webViewThemeImageView.setImageDrawable(resources.getDrawable(R.drawable.webview_light_theme_day));
951 webViewThemeImageView.setImageDrawable(resources.getDrawable(R.drawable.webview_light_theme_night));
954 // Hide the WebView theme text view.
955 webViewThemeTextView.setVisibility(View.GONE);
958 case DomainsDatabaseHelper.DARK_THEME: // The domain WebView theme is dark.
959 // Set the icon according to the app theme.
960 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
961 webViewThemeImageView.setImageDrawable(resources.getDrawable(R.drawable.webview_dark_theme_day));
963 webViewThemeImageView.setImageDrawable(resources.getDrawable(R.drawable.webview_dark_theme_night));
966 // Hide the WebView theme text view.
967 webViewThemeTextView.setVisibility(View.GONE);
971 // Open the WebView theme spinner when the text view is clicked.
972 webViewThemeTextView.setOnClickListener((View v) -> {
973 // Open the WebView theme spinner.
974 webViewThemeSpinner.performClick();
978 // Select the wide viewport in the spinner.
979 wideViewportSpinner.setSelection(wideViewportInt);
981 // Set the default wide viewport text.
982 if (defaultWideViewport) {
983 wideViewportTextView.setText(wideViewportArrayAdapter.getItem(DomainsDatabaseHelper.ENABLED));
985 wideViewportTextView.setText(wideViewportArrayAdapter.getItem(DomainsDatabaseHelper.DISABLED));
988 // Set the wide viewport icon and text view settings. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
989 switch (wideViewportInt) {
990 case DomainsDatabaseHelper.SYSTEM_DEFAULT:
991 if (defaultWideViewport) { // Wide viewport enabled by default.
992 // Set the icon according to the theme.
993 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
994 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_enabled_night));
996 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_enabled_day));
998 } else { // Wide viewport disabled by default.
999 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1000 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_disabled_night));
1002 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_disabled_day));
1006 // Show the wide viewport text view.
1007 wideViewportTextView.setVisibility(View.VISIBLE);
1010 case DomainsDatabaseHelper.ENABLED:
1011 // Set the icon according to the theme.
1012 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1013 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_enabled_night));
1015 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_enabled_day));
1018 // Hide the wide viewport text view.
1019 wideViewportTextView.setVisibility(View.GONE);
1022 case DomainsDatabaseHelper.DISABLED:
1023 // Set the icon according to the theme.
1024 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1025 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_disabled_night));
1027 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_disabled_day));
1030 // Hide the wide viewport text view.
1031 wideViewportTextView.setVisibility(View.GONE);
1035 // Open the wide viewport spinner when the text view is clicked.
1036 wideViewportTextView.setOnClickListener((View view) -> {
1037 // Open the wide viewport spinner.
1038 wideViewportSpinner.performClick();
1041 // Display the website images mode in the spinner.
1042 displayWebpageImagesSpinner.setSelection(displayImagesInt);
1044 // Set the default display images text.
1045 if (defaultDisplayWebpageImages) {
1046 displayImagesTextView.setText(displayImagesArrayAdapter.getItem(DomainsDatabaseHelper.ENABLED));
1048 displayImagesTextView.setText(displayImagesArrayAdapter.getItem(DomainsDatabaseHelper.DISABLED));
1051 // Set the display website images icon and text view settings. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
1052 switch (displayImagesInt) {
1053 case DomainsDatabaseHelper.SYSTEM_DEFAULT:
1054 if (defaultDisplayWebpageImages) { // Display webpage images enabled by default.
1055 // Set the icon according to the theme.
1056 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1057 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_night));
1059 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_day));
1061 } else { // Display webpage images disabled by default.
1062 // Set the icon according to the theme.
1063 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1064 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_night));
1066 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_day));
1070 // Show the display images text view.
1071 displayImagesTextView.setVisibility(View.VISIBLE);
1074 case DomainsDatabaseHelper.ENABLED:
1075 // Set the icon according to the theme.
1076 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1077 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_night));
1079 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_day));
1082 // Hide the display images text view.
1083 displayImagesTextView.setVisibility(View.GONE);
1086 case DomainsDatabaseHelper.DISABLED:
1087 // Set the icon according to the theme.
1088 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1089 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_night));
1091 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_day));
1094 // Hide the display images text view.
1095 displayImagesTextView.setVisibility(View.GONE);
1099 // Open the display images spinner when the text view is clicked.
1100 displayImagesTextView.setOnClickListener((View view) -> {
1101 // Open the user agent spinner.
1102 displayWebpageImagesSpinner.performClick();
1105 // Set the pinned SSL certificate icon.
1106 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.
1107 // Check the switch.
1108 pinnedSslCertificateSwitch.setChecked(true);
1110 // Set the icon according to the theme.
1111 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1112 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_night));
1114 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_day));
1116 } else { // Pinned SSL certificate is disabled.
1117 // Uncheck the switch.
1118 pinnedSslCertificateSwitch.setChecked(false);
1120 // Set the icon according to the theme.
1121 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1122 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_night));
1124 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_day));
1128 // Store the current date.
1129 Date currentDate = Calendar.getInstance().getTime();
1131 // Setup the string builders to display the general certificate information in blue. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1132 savedSslIssuedToONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), savedSslIssuedToONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1133 savedSslIssuedToUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), savedSslIssuedToUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1134 savedSslIssuedByCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), savedSslIssuedByCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1135 savedSslIssuedByONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), savedSslIssuedByONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1136 savedSslIssuedByUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), savedSslIssuedByUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1138 // Check the certificate Common Name against the domain name.
1139 boolean savedSslCommonNameMatchesDomainName = checkDomainNameAgainstCertificate(domainNameString, savedSslIssuedToCNameString);
1141 // Format the issued to Common Name color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1142 if (savedSslCommonNameMatchesDomainName) {
1143 savedSslIssuedToCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), savedSslIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1145 savedSslIssuedToCNameStringBuilder.setSpan(redColorSpan, cNameLabel.length(), savedSslIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1148 // Format the start date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1149 if ((savedSslStartDate != null) && savedSslStartDate.after(currentDate)) { // The certificate start date is in the future.
1150 savedSslStartDateStringBuilder.setSpan(redColorSpan, startDateLabel.length(), savedSslStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1151 } else { // The certificate start date is in the past.
1152 savedSslStartDateStringBuilder.setSpan(blueColorSpan, startDateLabel.length(), savedSslStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1155 // Format the end date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1156 if ((savedSslEndDate != null) && savedSslEndDate.before(currentDate)) { // The certificate end date is in the past.
1157 savedSslEndDateStringBuilder.setSpan(redColorSpan, endDateLabel.length(), savedSslEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1158 } else { // The certificate end date is in the future.
1159 savedSslEndDateStringBuilder.setSpan(blueColorSpan, endDateLabel.length(), savedSslEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1162 // Display the saved website SSL certificate strings.
1163 savedSslIssuedToCNameTextView.setText(savedSslIssuedToCNameStringBuilder);
1164 savedSslIssuedToONameTextView.setText(savedSslIssuedToONameStringBuilder);
1165 savedSslIssuedToUNameTextView.setText(savedSslIssuedToUNameStringBuilder);
1166 savedSslIssuedByCNameTextView.setText(savedSslIssuedByCNameStringBuilder);
1167 savedSslIssuedByONameTextView.setText(savedSslIssuedByONameStringBuilder);
1168 savedSslIssuedByUNameTextView.setText(savedSslIssuedByUNameStringBuilder);
1169 savedSslStartDateTextView.setText(savedSslStartDateStringBuilder);
1170 savedSslEndDateTextView.setText(savedSslEndDateStringBuilder);
1172 // Populate the current website SSL certificate if there is one.
1173 if (DomainsActivity.sslIssuedToCName != null) {
1174 // Get dates from the raw long values.
1175 Date currentSslStartDate = new Date(DomainsActivity.sslStartDateLong);
1176 Date currentSslEndDate = new Date(DomainsActivity.sslEndDateLong);
1178 // Create a spannable string builder for each text view that needs multiple colors of text.
1179 SpannableStringBuilder currentSslIssuedToCNameStringBuilder = new SpannableStringBuilder(cNameLabel + DomainsActivity.sslIssuedToCName);
1180 SpannableStringBuilder currentSslIssuedToONameStringBuilder = new SpannableStringBuilder(oNameLabel + DomainsActivity.sslIssuedToOName);
1181 SpannableStringBuilder currentSslIssuedToUNameStringBuilder = new SpannableStringBuilder(uNameLabel + DomainsActivity.sslIssuedToUName);
1182 SpannableStringBuilder currentSslIssuedByCNameStringBuilder = new SpannableStringBuilder(cNameLabel + DomainsActivity.sslIssuedByCName);
1183 SpannableStringBuilder currentSslIssuedByONameStringBuilder = new SpannableStringBuilder(oNameLabel + DomainsActivity.sslIssuedByOName);
1184 SpannableStringBuilder currentSslIssuedByUNameStringBuilder = new SpannableStringBuilder(uNameLabel + DomainsActivity.sslIssuedByUName);
1185 SpannableStringBuilder currentSslStartDateStringBuilder = new SpannableStringBuilder(startDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG)
1186 .format(currentSslStartDate));
1187 SpannableStringBuilder currentSslEndDateStringBuilder = new SpannableStringBuilder(endDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG)
1188 .format(currentSslEndDate));
1190 // Setup the string builders to display the general certificate information in blue. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1191 currentSslIssuedToONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), currentSslIssuedToONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1192 currentSslIssuedToUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), currentSslIssuedToUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1193 currentSslIssuedByCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), currentSslIssuedByCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1194 currentSslIssuedByONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), currentSslIssuedByONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1195 currentSslIssuedByUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), currentSslIssuedByUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1197 // Check the certificate Common Name against the domain name.
1198 boolean currentSslCommonNameMatchesDomainName = checkDomainNameAgainstCertificate(domainNameString, DomainsActivity.sslIssuedToCName);
1200 // Format the issued to Common Name color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1201 if (currentSslCommonNameMatchesDomainName) {
1202 currentSslIssuedToCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), currentSslIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1204 currentSslIssuedToCNameStringBuilder.setSpan(redColorSpan, cNameLabel.length(), currentSslIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1207 // Format the start date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1208 if (currentSslStartDate.after(currentDate)) { // The certificate start date is in the future.
1209 currentSslStartDateStringBuilder.setSpan(redColorSpan, startDateLabel.length(), currentSslStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1210 } else { // The certificate start date is in the past.
1211 currentSslStartDateStringBuilder.setSpan(blueColorSpan, startDateLabel.length(), currentSslStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1214 // Format the end date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1215 if (currentSslEndDate.before(currentDate)) { // The certificate end date is in the past.
1216 currentSslEndDateStringBuilder.setSpan(redColorSpan, endDateLabel.length(), currentSslEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1217 } else { // The certificate end date is in the future.
1218 currentSslEndDateStringBuilder.setSpan(blueColorSpan, endDateLabel.length(), currentSslEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1221 // Display the current website SSL certificate strings.
1222 currentSslIssuedToCNameTextView.setText(currentSslIssuedToCNameStringBuilder);
1223 currentSslIssuedToONameTextView.setText(currentSslIssuedToONameStringBuilder);
1224 currentSslIssuedToUNameTextView.setText(currentSslIssuedToUNameStringBuilder);
1225 currentSslIssuedByCNameTextView.setText(currentSslIssuedByCNameStringBuilder);
1226 currentSslIssuedByONameTextView.setText(currentSslIssuedByONameStringBuilder);
1227 currentSslIssuedByUNameTextView.setText(currentSslIssuedByUNameStringBuilder);
1228 currentSslStartDateTextView.setText(currentSslStartDateStringBuilder);
1229 currentSslEndDateTextView.setText(currentSslEndDateStringBuilder);
1232 // Set the initial display status of the SSL certificates card views.
1233 if (pinnedSslCertificateSwitch.isChecked()) { // An SSL certificate is pinned.
1234 // Set the visibility of the saved SSL certificate.
1235 if (savedSslIssuedToCNameString == null) {
1236 savedSslCardView.setVisibility(View.GONE);
1238 savedSslCardView.setVisibility(View.VISIBLE);
1241 // Set the visibility of the current website SSL certificate.
1242 if (DomainsActivity.sslIssuedToCName == null) { // There is no current SSL certificate.
1243 // Hide the SSL certificate.
1244 currentSslCardView.setVisibility(View.GONE);
1246 // Show the instruction.
1247 noCurrentWebsiteCertificateTextView.setVisibility(View.VISIBLE);
1248 } else { // There is a current SSL certificate.
1249 // Show the SSL certificate.
1250 currentSslCardView.setVisibility(View.VISIBLE);
1252 // Hide the instruction.
1253 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
1256 // Set the status of the radio buttons and the card view backgrounds.
1257 if (savedSslCardView.getVisibility() == View.VISIBLE) { // The saved SSL certificate is displayed.
1258 // Check the saved SSL certificate radio button.
1259 savedSslCertificateRadioButton.setChecked(true);
1261 // Uncheck the current website SSL certificate radio button.
1262 currentWebsiteCertificateRadioButton.setChecked(false);
1264 // Darken the background of the current website SSL certificate linear layout according to the theme.
1265 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1266 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
1268 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
1270 } else if (currentSslCardView.getVisibility() == View.VISIBLE) { // The saved SSL certificate is hidden but the current website SSL certificate is visible.
1271 // Check the current website SSL certificate radio button.
1272 currentWebsiteCertificateRadioButton.setChecked(true);
1274 // Uncheck the saved SSL certificate radio button.
1275 savedSslCertificateRadioButton.setChecked(false);
1276 } else { // Neither SSL certificate is visible.
1277 // Uncheck both radio buttons.
1278 savedSslCertificateRadioButton.setChecked(false);
1279 currentWebsiteCertificateRadioButton.setChecked(false);
1281 } else { // An SSL certificate is not pinned.
1282 // Hide the SSl certificates and instructions.
1283 savedSslCardView.setVisibility(View.GONE);
1284 currentSslCardView.setVisibility(View.GONE);
1285 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
1287 // Uncheck the radio buttons.
1288 savedSslCertificateRadioButton.setChecked(false);
1289 currentWebsiteCertificateRadioButton.setChecked(false);
1292 // Set the pinned IP addresses icon.
1293 if (pinnedIpAddressesInt == 1) { // Pinned IP addresses is enabled. Once the minimum API >= 21 a selector can be sued as the tint mode instead of specifying different icons.
1294 // Check the switch.
1295 pinnedIpAddressesSwitch.setChecked(true);
1297 // Set the icon according to the theme.
1298 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1299 pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_night));
1301 pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_day));
1303 } else { // Pinned IP Addresses is disabled.
1304 // Uncheck the switch.
1305 pinnedIpAddressesSwitch.setChecked(false);
1307 // Set the icon according to the theme.
1308 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1309 pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_night));
1311 pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_day));
1315 // Populate the saved and current IP addresses.
1316 savedIpAddressesTextView.setText(savedIpAddresses);
1317 currentIpAddressesTextView.setText(DomainsActivity.currentIpAddresses);
1319 // Set the initial display status of the IP addresses card views.
1320 if (pinnedIpAddressesSwitch.isChecked()) { // IP addresses are pinned.
1321 // Set the visibility of the saved IP addresses.
1322 if (savedIpAddresses == null) { // There are no saved IP addresses.
1323 savedIpAddressesCardView.setVisibility(View.GONE);
1324 } else { // There are saved IP addresses.
1325 savedIpAddressesCardView.setVisibility(View.VISIBLE);
1328 // Set the visibility of the current IP addresses.
1329 currentIpAddressesCardView.setVisibility(View.VISIBLE);
1331 // Set the status of the radio buttons and the card view backgrounds.
1332 if (savedIpAddressesCardView.getVisibility() == View.VISIBLE) { // The saved IP addresses are displayed.
1333 // Check the saved IP addresses radio button.
1334 savedIpAddressesRadioButton.setChecked(true);
1336 // Uncheck the current IP addresses radio button.
1337 currentIpAddressesRadioButton.setChecked(false);
1339 // Darken the background of the current IP addresses linear layout according to the theme.
1340 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1341 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
1343 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
1345 } else { // The saved IP addresses are hidden.
1346 // Check the current IP addresses radio button.
1347 currentIpAddressesRadioButton.setChecked(true);
1349 // Uncheck the saved IP addresses radio button.
1350 savedIpAddressesRadioButton.setChecked(false);
1352 } else { // IP addresses are not pinned.
1353 // Hide the IP addresses card views.
1354 savedIpAddressesCardView.setVisibility(View.GONE);
1355 currentIpAddressesCardView.setVisibility(View.GONE);
1357 // Uncheck the radio buttons.
1358 savedIpAddressesRadioButton.setChecked(false);
1359 currentIpAddressesRadioButton.setChecked(false);
1363 // Set the JavaScript switch listener.
1364 javaScriptSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1365 if (isChecked) { // JavaScript is enabled.
1366 // Update the JavaScript icon.
1367 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.javascript_enabled));
1369 // Enable the DOM storage `Switch`.
1370 domStorageSwitch.setEnabled(true);
1372 // Update the DOM storage icon.
1373 if (domStorageSwitch.isChecked()) { // DOM storage is enabled.
1374 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_enabled));
1375 } else { // DOM storage is disabled.
1376 // Set the icon according to the theme.
1377 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1378 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_night));
1380 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_day));
1383 } else { // JavaScript is disabled.
1384 // Update the JavaScript icon.
1385 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.privacy_mode));
1387 // Disable the DOM storage `Switch`.
1388 domStorageSwitch.setEnabled(false);
1390 // Set the DOM storage icon according to the theme.
1391 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1392 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_night));
1394 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_day));
1399 // Set the first-party cookies switch listener.
1400 firstPartyCookiesSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1401 if (isChecked) { // First-party cookies are enabled.
1402 // Update the first-party cookies icon.
1403 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_enabled));
1405 // Enable the third-party cookies switch.
1406 thirdPartyCookiesSwitch.setEnabled(true);
1408 // Update the third-party cookies icon.
1409 if (thirdPartyCookiesSwitch.isChecked()) { // Third-party cookies are enabled.
1410 // Set the third-party cookies icon to be red.
1411 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_warning));
1412 } else { // Third-party cookies are disabled.
1413 // Set the third-party cookies icon according to the theme.
1414 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1415 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_night));
1417 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_day));
1420 } else { // First-party cookies are disabled.
1421 // Update the first-party cookies icon according to the theme.
1422 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1423 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_night));
1425 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_day));
1428 // Disable the third-party cookies switch.
1429 thirdPartyCookiesSwitch.setEnabled(false);
1431 // Set the third-party cookies icon according to the theme.
1432 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1433 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_ghosted_night));
1435 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_ghosted_day));
1440 // Set the third-party cookies switch listener.
1441 thirdPartyCookiesSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1444 // Set the third-party cookies icon to be red.
1445 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_warning));
1447 // Update the third-party cookies icon according to the theme.
1448 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1449 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_night));
1451 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_day));
1456 // Set the DOM Storage switch listener.
1457 domStorageSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1460 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_enabled));
1462 // Set the icon according to the theme.
1463 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1464 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_night));
1466 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_day));
1471 // Set the form data switch listener. It can be removed once the minimum API >= 26.
1472 if (Build.VERSION.SDK_INT < 26) {
1473 formDataSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1476 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_enabled));
1478 // Set the icon according to the theme.
1479 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1480 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_disabled_night));
1482 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_disabled_day));
1488 // Set the EasyList switch listener.
1489 easyListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1491 if (isChecked) { // EasyList is on.
1492 // Set the icon according to the theme.
1493 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1494 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_night));
1496 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_day));
1498 } else { // EasyList is off.
1499 // Set the icon according to the theme.
1500 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1501 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_night));
1503 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_day));
1508 // Set the EasyPrivacy switch listener.
1509 easyPrivacySwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1511 if (isChecked) { // EasyPrivacy is on.
1512 // Set the icon according to the theme.
1513 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1514 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_night));
1516 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_day));
1518 } else { // EasyPrivacy is off.
1519 // Set the icon according to the theme.
1520 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1521 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_night));
1523 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_day));
1528 // Set the Fanboy's Annoyance List switch listener.
1529 fanboysAnnoyanceListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1530 // Update the icon and Fanboy's Social Blocking List.
1531 if (isChecked) { // Fanboy's Annoyance List is on.
1532 // Set the icon according to the theme.
1533 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1534 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_night));
1536 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_day));
1539 // Disable the Fanboy's Social Blocking List switch.
1540 fanboysSocialBlockingListSwitch.setEnabled(false);
1542 // Update the Fanboy's Social Blocking List icon according to the theme.
1543 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1544 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_ghosted_night));
1546 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_ghosted_day));
1548 } else { // Fanboy's Annoyance List is off.
1549 // Set the icon according to the theme.
1550 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1551 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_night));
1553 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_day));
1556 // Enable the Fanboy's Social Blocking List switch.
1557 fanboysSocialBlockingListSwitch.setEnabled(true);
1559 // Update the Fanboy's Social Blocking List icon.
1560 if (fanboysSocialBlockingListSwitch.isChecked()) { // Fanboy's Social Blocking List is on.
1561 // Update the icon according to the theme.
1562 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1563 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_night));
1565 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_day));
1567 } else { // Fanboy's Social Blocking List is off.
1568 // Update the icon according to the theme.
1569 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1570 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_night));
1572 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_day));
1579 // Set the Fanboy's Social Blocking List switch listener.
1580 fanboysSocialBlockingListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1582 if (isChecked) { // Fanboy's Social Blocking List is on.
1583 // Set the icon according to the theme.
1584 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1585 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_night));
1587 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_day));
1589 } else { // Fanboy's Social Blocking List is off.
1590 // Set the icon according to the theme.
1591 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1592 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_night));
1594 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_day));
1599 // Set the UltraList switch listener.
1600 ultraListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1602 if (isChecked) { // UltraList is on.
1603 // Set the icon according to the theme.
1604 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1605 ultraListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_night));
1607 ultraListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_day));
1609 } else { // UltraList is off.
1610 // Set the icon according to the theme.
1611 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1612 ultraListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_night));
1614 ultraListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_day));
1619 // Set the UltraPrivacy switch listener.
1620 ultraPrivacySwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1622 if (isChecked) { // UltraPrivacy is on.
1623 // Set the icon according to the theme.
1624 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1625 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_night));
1627 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_day));
1629 } else { // UltraPrivacy is off.
1630 // Set the icon according to the theme.
1631 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1632 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_night));
1634 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_day));
1639 // Set the block all third-party requests switch listener.
1640 blockAllThirdPartyRequestsSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1642 if (isChecked) { // Blocking all third-party requests is on.
1643 // Set the icon according to the theme.
1644 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1645 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_enabled_night));
1647 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_enabled_day));
1649 } else { // Blocking all third-party requests is off.
1650 // Set the icon according to the theme.
1651 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1652 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_disabled_night));
1654 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_disabled_day));
1659 // Set the user agent spinner listener.
1660 userAgentSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1662 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1663 // Set the new user agent.
1665 case MainWebViewActivity.DOMAINS_SYSTEM_DEFAULT_USER_AGENT:
1666 // Show the user agent TextView.
1667 userAgentTextView.setVisibility(View.VISIBLE);
1669 // Hide the custom user agent EditText.
1670 customUserAgentEditText.setVisibility(View.GONE);
1672 // Set the user text.
1673 switch (defaultUserAgentArrayPosition) {
1674 case MainWebViewActivity.UNRECOGNIZED_USER_AGENT: // The default user agent name is not on the canonical list.
1675 // This is probably because it was set in an older version of Privacy Browser before the switch to persistent user agent names.
1676 userAgentTextView.setText(defaultUserAgentName);
1679 case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
1680 // Display the `WebView` default user agent.
1681 userAgentTextView.setText(webViewDefaultUserAgentString);
1684 case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
1685 // Display the custom user agent.
1686 userAgentTextView.setText(defaultCustomUserAgentString);
1690 // Get the user agent string from the user agent data array.
1691 userAgentTextView.setText(userAgentDataArray[defaultUserAgentArrayPosition]);
1695 case MainWebViewActivity.DOMAINS_WEBVIEW_DEFAULT_USER_AGENT:
1696 // Show the user agent TextView and set the text.
1697 userAgentTextView.setVisibility(View.VISIBLE);
1698 userAgentTextView.setText(webViewDefaultUserAgentString);
1700 // Hide the custom user agent EditTex.
1701 customUserAgentEditText.setVisibility(View.GONE);
1704 case MainWebViewActivity.DOMAINS_CUSTOM_USER_AGENT:
1705 // Hide the user agent TextView.
1706 userAgentTextView.setVisibility(View.GONE);
1708 // Show the custom user agent EditText and set the current user agent name as the text.
1709 customUserAgentEditText.setVisibility(View.VISIBLE);
1710 customUserAgentEditText.setText(currentUserAgentName);
1714 // 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.
1715 userAgentTextView.setVisibility(View.VISIBLE);
1716 userAgentTextView.setText(userAgentDataArray[position - 1]);
1718 // Hide `customUserAgentEditText`.
1719 customUserAgentEditText.setVisibility(View.GONE);
1724 public void onNothingSelected(AdapterView<?> parent) {
1729 // Set the font size spinner listener.
1730 fontSizeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1732 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1733 // Update the font size display options.
1734 if (position == 0) { // The system default font size has been selected.
1735 // Show the default font size text view.
1736 defaultFontSizeTextView.setVisibility(View.VISIBLE);
1738 // Hide the custom font size edit text.
1739 customFontSizeEditText.setVisibility(View.GONE);
1740 } else { // A custom font size has been selected.
1741 // Hide the default font size text view.
1742 defaultFontSizeTextView.setVisibility(View.GONE);
1744 // Show the custom font size edit text.
1745 customFontSizeEditText.setVisibility(View.VISIBLE);
1750 public void onNothingSelected(AdapterView<?> parent) {
1755 // Set the swipe to refresh spinner listener.
1756 swipeToRefreshSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1758 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1759 // 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.
1761 case DomainsDatabaseHelper.SYSTEM_DEFAULT:
1762 if (defaultSwipeToRefresh) { // Swipe to refresh enabled by default.
1763 // Set the icon according to the theme.
1764 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1765 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_night));
1767 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_day));
1769 } else { // Swipe to refresh disabled by default.
1770 // Set the icon according to the theme.
1771 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1772 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_night));
1774 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_day));
1778 // Show the swipe to refresh TextView.
1779 swipeToRefreshTextView.setVisibility(View.VISIBLE);
1782 case DomainsDatabaseHelper.ENABLED:
1783 // Set the icon according to the theme.
1784 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1785 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_night));
1787 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_day));
1790 // Hide the swipe to refresh TextView.
1791 swipeToRefreshTextView.setVisibility(View.GONE);
1794 case DomainsDatabaseHelper.DISABLED:
1795 // Set the icon according to the theme.
1796 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1797 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_night));
1799 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_day));
1802 // Hide the swipe to refresh TextView.
1803 swipeToRefreshTextView.setVisibility(View.GONE);
1808 public void onNothingSelected(AdapterView<?> parent) {
1813 // Set the WebView theme spinner listener.
1814 webViewThemeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1816 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1817 // Update the icon and the visibility of the WebView theme text view. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
1819 case DomainsDatabaseHelper.SYSTEM_DEFAULT: // the domain WebView theme is system default.
1820 // Set the icon according to the app WebView theme.
1821 switch (appWebViewThemeEntryNumber) {
1822 case DomainsDatabaseHelper.SYSTEM_DEFAULT: // The default WebView theme is system default.
1823 // Set the icon according to the app theme.
1824 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1825 // Set the light mode icon.
1826 webViewThemeImageView.setImageDrawable(resources.getDrawable(R.drawable.webview_light_theme_day));
1828 // Set the dark theme icon.
1829 webViewThemeImageView.setImageDrawable(resources.getDrawable(R.drawable.webview_dark_theme_night));
1833 case DomainsDatabaseHelper.LIGHT_THEME: // The default WebView theme is light.
1834 // Set the icon according to the app theme.
1835 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1836 webViewThemeImageView.setImageDrawable(resources.getDrawable(R.drawable.webview_light_theme_day));
1838 webViewThemeImageView.setImageDrawable(resources.getDrawable(R.drawable.webview_light_theme_night));
1842 case DomainsDatabaseHelper.DARK_THEME: // The default WebView theme is dark.
1843 // Set the icon according to the app theme.
1844 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1845 webViewThemeImageView.setImageDrawable(resources.getDrawable(R.drawable.webview_dark_theme_day));
1847 webViewThemeImageView.setImageDrawable(resources.getDrawable(R.drawable.webview_dark_theme_night));
1852 // Show the WebView theme text view.
1853 webViewThemeTextView.setVisibility(View.VISIBLE);
1856 case DomainsDatabaseHelper.LIGHT_THEME: // The domain WebView theme is light.
1857 // Set the icon according to the app theme.
1858 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1859 webViewThemeImageView.setImageDrawable(resources.getDrawable(R.drawable.webview_light_theme_day));
1861 webViewThemeImageView.setImageDrawable(resources.getDrawable(R.drawable.webview_light_theme_night));
1864 // Hide the WebView theme text view.
1865 webViewThemeTextView.setVisibility(View.GONE);
1868 case DomainsDatabaseHelper.DARK_THEME: // The domain WebView theme is dark.
1869 // Set the icon according to the app theme.
1870 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1871 webViewThemeImageView.setImageDrawable(resources.getDrawable(R.drawable.webview_dark_theme_day));
1873 webViewThemeImageView.setImageDrawable(resources.getDrawable(R.drawable.webview_dark_theme_night));
1876 // Hide the WebView theme text view.
1877 webViewThemeTextView.setVisibility(View.GONE);
1883 public void onNothingSelected(AdapterView<?> parent) {
1888 // Set the wide viewport spinner listener.
1889 wideViewportSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1891 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1892 // Update the icon and the visibility of the wide viewport text view.
1894 case DomainsDatabaseHelper.SYSTEM_DEFAULT:
1895 if (defaultWideViewport) { // Wide viewport is enabled by default.
1896 // Set the icon according to the theme.
1897 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1898 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_enabled_night));
1900 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_enabled_day));
1902 } else { // Wide viewport is disabled by default.
1903 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1904 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_disabled_night));
1906 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_disabled_day));
1910 // Show the wide viewport text view.
1911 wideViewportTextView.setVisibility(View.VISIBLE);
1914 case DomainsDatabaseHelper.ENABLED:
1915 // Set the icon according to the theme.
1916 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1917 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_enabled_night));
1919 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_enabled_day));
1922 // Hide the wide viewport text view.
1923 wideViewportTextView.setVisibility(View.GONE);
1926 case DomainsDatabaseHelper.DISABLED:
1927 // Set the icon according to the theme.
1928 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1929 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_disabled_night));
1931 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_disabled_day));
1934 // Hid ethe wide viewport text view.
1935 wideViewportTextView.setVisibility(View.GONE);
1941 public void onNothingSelected(AdapterView<?> parent) {
1946 // Set the display webpage images spinner listener.
1947 displayWebpageImagesSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1949 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1950 // Update the icon and the visibility of the display images text view.
1952 case DomainsDatabaseHelper.SYSTEM_DEFAULT:
1953 if (defaultDisplayWebpageImages) { // Display webpage images is enabled by default.
1954 // Set the icon according to the theme.
1955 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1956 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_night));
1958 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_day));
1960 } else { // Display webpage images is disabled by default.
1961 // Set the icon according to the theme.
1962 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1963 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_night));
1965 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_day));
1969 // Show the display images text view.
1970 displayImagesTextView.setVisibility(View.VISIBLE);
1973 case DomainsDatabaseHelper.ENABLED:
1974 // Set the icon according to the theme.
1975 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1976 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_night));
1978 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_day));
1981 // Hide the display images text view.
1982 displayImagesTextView.setVisibility(View.GONE);
1985 case DomainsDatabaseHelper.DISABLED:
1986 // Set the icon according to the theme.
1987 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1988 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_night));
1990 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_day));
1993 // Hide the display images text view.
1994 displayImagesTextView.setVisibility(View.GONE);
2000 public void onNothingSelected(AdapterView<?> parent) {
2005 // Set the pinned SSL certificate switch listener.
2006 pinnedSslCertificateSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
2008 if (isChecked) { // SSL certificate pinning is enabled.
2009 // Set the icon according to the theme.
2010 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2011 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_night));
2013 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_day));
2016 // Update the visibility of the saved SSL certificate.
2017 if (savedSslIssuedToCNameString == null) {
2018 savedSslCardView.setVisibility(View.GONE);
2020 savedSslCardView.setVisibility(View.VISIBLE);
2023 // Update the visibility of the current website SSL certificate.
2024 if (DomainsActivity.sslIssuedToCName == null) {
2025 // Hide the SSL certificate.
2026 currentSslCardView.setVisibility(View.GONE);
2028 // Show the instruction.
2029 noCurrentWebsiteCertificateTextView.setVisibility(View.VISIBLE);
2031 // Show the SSL certificate.
2032 currentSslCardView.setVisibility(View.VISIBLE);
2034 // Hide the instruction.
2035 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
2038 // Set the status of the radio buttons.
2039 if (savedSslCardView.getVisibility() == View.VISIBLE) { // The saved SSL certificate is displayed.
2040 // Check the saved SSL certificate radio button.
2041 savedSslCertificateRadioButton.setChecked(true);
2043 // Uncheck the current website SSL certificate radio button.
2044 currentWebsiteCertificateRadioButton.setChecked(false);
2046 // Set the background of the saved SSL certificate linear layout to be transparent.
2047 savedSslCertificateLinearLayout.setBackgroundResource(R.color.transparent);
2049 // Darken the background of the current website SSL certificate linear layout according to the theme.
2050 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2051 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2053 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2056 // Scroll to the current website SSL certificate card.
2057 savedSslCardView.getParent().requestChildFocus(savedSslCardView, savedSslCardView);
2058 } else if (currentSslCardView.getVisibility() == View.VISIBLE) { // The saved SSL certificate is hidden but the current website SSL certificate is visible.
2059 // Check the current website SSL certificate radio button.
2060 currentWebsiteCertificateRadioButton.setChecked(true);
2062 // Uncheck the saved SSL certificate radio button.
2063 savedSslCertificateRadioButton.setChecked(false);
2065 // Set the background of the current website SSL certificate linear layout to be transparent.
2066 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.transparent);
2068 // Darken the background of the saved SSL certificate linear layout according to the theme.
2069 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2070 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2072 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2075 // Scroll to the current website SSL certificate card.
2076 currentSslCardView.getParent().requestChildFocus(currentSslCardView, currentSslCardView);
2077 } else { // Neither SSL certificate is visible.
2078 // Uncheck both radio buttons.
2079 savedSslCertificateRadioButton.setChecked(false);
2080 currentWebsiteCertificateRadioButton.setChecked(false);
2082 // Scroll to the current website SSL certificate card.
2083 noCurrentWebsiteCertificateTextView.getParent().requestChildFocus(noCurrentWebsiteCertificateTextView, noCurrentWebsiteCertificateTextView);
2085 } else { // SSL certificate pinning is disabled.
2086 // Set the icon according to the theme.
2087 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2088 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_night));
2090 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_day));
2093 // Hide the SSl certificates and instructions.
2094 savedSslCardView.setVisibility(View.GONE);
2095 currentSslCardView.setVisibility(View.GONE);
2096 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
2098 // Uncheck the radio buttons.
2099 savedSslCertificateRadioButton.setChecked(false);
2100 currentWebsiteCertificateRadioButton.setChecked(false);
2104 savedSslCardView.setOnClickListener((View view) -> {
2105 // Check the saved SSL certificate radio button.
2106 savedSslCertificateRadioButton.setChecked(true);
2108 // Uncheck the current website SSL certificate radio button.
2109 currentWebsiteCertificateRadioButton.setChecked(false);
2111 // Set the background of the saved SSL certificate linear layout to be transparent.
2112 savedSslCertificateLinearLayout.setBackgroundResource(R.color.transparent);
2114 // Darken the background of the current website SSL certificate linear layout according to the theme.
2115 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2116 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2118 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2122 savedSslCertificateRadioButton.setOnClickListener((View view) -> {
2123 // Check the saved SSL certificate radio button.
2124 savedSslCertificateRadioButton.setChecked(true);
2126 // Uncheck the current website SSL certificate radio button.
2127 currentWebsiteCertificateRadioButton.setChecked(false);
2129 // Set the background of the saved SSL certificate linear layout to be transparent.
2130 savedSslCertificateLinearLayout.setBackgroundResource(R.color.transparent);
2132 // Darken the background of the current website SSL certificate linear layout according to the theme.
2133 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2134 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2136 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2140 currentSslCardView.setOnClickListener((View view) -> {
2141 // Check the current website SSL certificate radio button.
2142 currentWebsiteCertificateRadioButton.setChecked(true);
2144 // Uncheck the saved SSL certificate radio button.
2145 savedSslCertificateRadioButton.setChecked(false);
2147 // Set the background of the current website SSL certificate linear layout to be transparent.
2148 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.transparent);
2150 // Darken the background of the saved SSL certificate linear layout according to the theme.
2151 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2152 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2154 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2158 currentWebsiteCertificateRadioButton.setOnClickListener((View view) -> {
2159 // Check the current website SSL certificate radio button.
2160 currentWebsiteCertificateRadioButton.setChecked(true);
2162 // Uncheck the saved SSL certificate radio button.
2163 savedSslCertificateRadioButton.setChecked(false);
2165 // Set the background of the current website SSL certificate linear layout to be transparent.
2166 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.transparent);
2168 // Darken the background of the saved SSL certificate linear layout according to the theme.
2169 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2170 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2172 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2176 // Set the pinned IP addresses switch listener.
2177 pinnedIpAddressesSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
2179 if (isChecked) { // IP addresses pinning is enabled.
2180 // Set the icon according to the theme.
2181 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2182 pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_night));
2184 pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_day));
2187 // Update the visibility of the saved IP addresses card view.
2188 if (savedIpAddresses == null) { // There are no saved IP addresses.
2189 savedIpAddressesCardView.setVisibility(View.GONE);
2190 } else { // There are saved IP addresses.
2191 savedIpAddressesCardView.setVisibility(View.VISIBLE);
2194 // Show the current IP addresses card view.
2195 currentIpAddressesCardView.setVisibility(View.VISIBLE);
2197 // Set the status of the radio buttons.
2198 if (savedIpAddressesCardView.getVisibility() == View.VISIBLE) { // The saved IP addresses are visible.
2199 // Check the saved IP addresses radio button.
2200 savedIpAddressesRadioButton.setChecked(true);
2202 // Uncheck the current IP addresses radio button.
2203 currentIpAddressesRadioButton.setChecked(false);
2205 // Set the background of the saved IP addresses linear layout to be transparent.
2206 savedSslCertificateLinearLayout.setBackgroundResource(R.color.transparent);
2208 // Darken the background of the current IP addresses linear layout according to the theme.
2209 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2210 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2212 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2214 } else { // The saved IP addresses are not visible.
2215 // Check the current IP addresses radio button.
2216 currentIpAddressesRadioButton.setChecked(true);
2218 // Uncheck the saved IP addresses radio button.
2219 savedIpAddressesRadioButton.setChecked(false);
2221 // Set the background of the current IP addresses linear layout to be transparent.
2222 currentIpAddressesLinearLayout.setBackgroundResource(R.color.transparent);
2224 // Darken the background of the saved IP addresses linear layout according to the theme.
2225 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2226 savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2228 savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2232 // Scroll to the bottom of the card views.
2233 currentIpAddressesCardView.getParent().requestChildFocus(currentIpAddressesCardView, currentIpAddressesCardView);
2234 } else { // IP addresses pinning is disabled.
2235 // Set the icon according to the theme.
2236 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2237 pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_night));
2239 pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_day));
2242 // Hide the IP addresses card views.
2243 savedIpAddressesCardView.setVisibility(View.GONE);
2244 currentIpAddressesCardView.setVisibility(View.GONE);
2246 // Uncheck the radio buttons.
2247 savedIpAddressesRadioButton.setChecked(false);
2248 currentIpAddressesRadioButton.setChecked(false);
2252 savedIpAddressesCardView.setOnClickListener((View view) -> {
2253 // Check the saved IP addresses radio button.
2254 savedIpAddressesRadioButton.setChecked(true);
2256 // Uncheck the current website IP addresses radio button.
2257 currentIpAddressesRadioButton.setChecked(false);
2259 // Set the background of the saved IP addresses linear layout to be transparent.
2260 savedIpAddressesLinearLayout.setBackgroundResource(R.color.transparent);
2262 // Darken the background of the current IP addresses linear layout according to the theme.
2263 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2264 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2266 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2270 savedIpAddressesRadioButton.setOnClickListener((View view) -> {
2271 // Check the saved IP addresses radio button.
2272 savedIpAddressesRadioButton.setChecked(true);
2274 // Uncheck the current website IP addresses radio button.
2275 currentIpAddressesRadioButton.setChecked(false);
2277 // Set the background of the saved IP addresses linear layout to be transparent.
2278 savedIpAddressesLinearLayout.setBackgroundResource(R.color.transparent);
2280 // Darken the background of the current IP addresses linear layout according to the theme.
2281 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2282 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2284 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2288 currentIpAddressesCardView.setOnClickListener((View view) -> {
2289 // Check the current IP addresses radio button.
2290 currentIpAddressesRadioButton.setChecked(true);
2292 // Uncheck the saved IP addresses radio button.
2293 savedIpAddressesRadioButton.setChecked(false);
2295 // Set the background of the current IP addresses linear layout to be transparent.
2296 currentIpAddressesLinearLayout.setBackgroundResource(R.color.transparent);
2298 // Darken the background of the saved IP addresses linear layout according to the theme.
2299 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2300 savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2302 savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2306 currentIpAddressesRadioButton.setOnClickListener((View view) -> {
2307 // Check the current IP addresses radio button.
2308 currentIpAddressesRadioButton.setChecked(true);
2310 // Uncheck the saved IP addresses radio button.
2311 savedIpAddressesRadioButton.setChecked(false);
2313 // Set the background of the current IP addresses linear layout to be transparent.
2314 currentIpAddressesLinearLayout.setBackgroundResource(R.color.transparent);
2316 // Darken the background of the saved IP addresses linear layout according to the theme.
2317 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2318 savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2320 savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2324 return domainSettingsView;
2327 private boolean checkDomainNameAgainstCertificate(String domainName, String certificateCommonName) {
2328 // Initialize `domainNamesMatch`.
2329 boolean domainNamesMatch = false;
2331 // Check various wildcard permutations if `domainName` and `certificateCommonName` are not empty.
2332 // `noinspection ConstantCondition` removes Android Studio's incorrect lint warning that `domainName` can never be `null`.
2333 if ((domainName != null) && (certificateCommonName != null)) {
2334 // Check if the domains match.
2335 if (domainName.equals(certificateCommonName)) {
2336 domainNamesMatch = true;
2339 // If `domainName` starts with a wildcard, check the base domain against all the subdomains of `certificateCommonName`.
2340 if (!domainNamesMatch && domainName.startsWith("*.") && (domainName.length() > 2)) {
2341 // Remove the initial `*.`.
2342 String baseDomainName = domainName.substring(2);
2344 // Setup a copy of `certificateCommonName` to test subdomains.
2345 String certificateCommonNameSubdomain = certificateCommonName;
2347 // Check all the subdomains in `certificateCommonNameSubdomain` against `baseDomainName`.
2348 while (!domainNamesMatch && certificateCommonNameSubdomain.contains(".")) { // Stop checking if we know that `domainNamesMatch` is `true` or if we run out of `.`.
2349 // Test the `certificateCommonNameSubdomain` against `baseDomainName`.
2350 if (certificateCommonNameSubdomain.equals(baseDomainName)) {
2351 domainNamesMatch = true;
2354 // Strip out the lowest subdomain of `certificateCommonNameSubdomain`.
2356 certificateCommonNameSubdomain = certificateCommonNameSubdomain.substring(certificateCommonNameSubdomain.indexOf(".") + 1);
2357 } catch (IndexOutOfBoundsException e) { // `certificateCommonNameSubdomain` ends with `.`.
2358 certificateCommonNameSubdomain = "";
2363 // If `certificateCommonName` starts with a wildcard, check the base common name against all the subdomains of `domainName`.
2364 if (!domainNamesMatch && certificateCommonName.startsWith("*.") && (certificateCommonName.length() > 2)) {
2365 // Remove the initial `*.`.
2366 String baseCertificateCommonName = certificateCommonName.substring(2);
2368 // Setup a copy of `domainName` to test subdomains.
2369 String domainNameSubdomain = domainName;
2371 // Check all the subdomains in `domainNameSubdomain` against `baseCertificateCommonName`.
2372 while (!domainNamesMatch && domainNameSubdomain.contains(".") && (domainNameSubdomain.length() > 2)) {
2373 // Test the `domainNameSubdomain` against `baseCertificateCommonName`.
2374 if (domainNameSubdomain.equals(baseCertificateCommonName)) {
2375 domainNamesMatch = true;
2378 // Strip out the lowest subdomain of `domainNameSubdomain`.
2380 domainNameSubdomain = domainNameSubdomain.substring(domainNameSubdomain.indexOf(".") + 1);
2381 } catch (IndexOutOfBoundsException e) { // `domainNameSubdomain` ends with `.`.
2382 domainNameSubdomain = "";
2387 // If both names start with a wildcard, check if the root of one contains the root of the other.
2388 if (!domainNamesMatch && domainName.startsWith("*.") && (domainName.length() > 2) && certificateCommonName.startsWith("*.") && (certificateCommonName.length() > 2)) {
2389 // Remove the wildcards.
2390 String rootDomainName = domainName.substring(2);
2391 String rootCertificateCommonName = certificateCommonName.substring(2);
2393 // Check if one name ends with the contents of the other. If so, there will be overlap in the their wildcard subdomains.
2394 if (rootDomainName.endsWith(rootCertificateCommonName) || rootCertificateCommonName.endsWith(rootDomainName)) {
2395 domainNamesMatch = true;
2400 return domainNamesMatch;