2 * Copyright © 2017-2021 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.ScrollView;
48 import android.widget.Spinner;
49 import android.widget.TextView;
51 import androidx.annotation.NonNull;
52 import androidx.appcompat.widget.SwitchCompat;
53 import androidx.cardview.widget.CardView;
54 import androidx.core.content.res.ResourcesCompat;
55 import androidx.fragment.app.Fragment; // The AndroidX fragment must be used until minimum API >= 23. Otherwise `getContext()` does not work.
57 import com.stoutner.privacybrowser.R;
58 import com.stoutner.privacybrowser.activities.DomainsActivity;
59 import com.stoutner.privacybrowser.activities.MainWebViewActivity;
60 import com.stoutner.privacybrowser.helpers.DomainsDatabaseHelper;
62 import java.text.DateFormat;
63 import java.util.Calendar;
64 import java.util.Date;
66 public class DomainSettingsFragment extends Fragment {
67 // Initialize the public class constants. These are used by activities calling this fragment.
68 public static final String DATABASE_ID = "database_id";
69 public static final String SCROLL_Y = "scroll_y";
71 // Define the public variables. `databaseId` is public static so it can be accessed from `DomainsActivity`. It is also used in `onCreate()` and `onCreateView()`.
72 public static int databaseId;
74 // Define the class variables.
78 public void onCreate(Bundle savedInstanceState) {
79 // Run the default commands.
80 super.onCreate(savedInstanceState);
82 // Remove the lint warning that `getArguments` might be null.
83 assert getArguments() != null;
85 // Store the database id in `databaseId`.
86 databaseId = getArguments().getInt(DATABASE_ID);
87 scrollY = getArguments().getInt(SCROLL_Y);
90 // The deprecated `getDrawable()` must be used until the minimum API >= 21.
92 public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
93 // Inflate `domain_settings_fragment`. `false` does not attach it to the root `container`.
94 View domainSettingsView = inflater.inflate(R.layout.domain_settings_fragment, container, false);
96 // Get handles for the context and the resources.
97 Context context = getContext();
98 Resources resources = getResources();
100 // Remove the error below that the context might be null.
101 assert context != null;
103 // Get the current theme status.
104 int currentThemeStatus = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
106 // Get a handle for the shared preference.
107 SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
109 // Store the default settings.
110 String defaultUserAgentName = sharedPreferences.getString("user_agent", getString(R.string.user_agent_default_value));
111 String defaultCustomUserAgentString = sharedPreferences.getString("custom_user_agent", getString(R.string.custom_user_agent_default_value));
112 String defaultFontSizeString = sharedPreferences.getString("font_size", getString(R.string.font_size_default_value));
113 boolean defaultSwipeToRefresh = sharedPreferences.getBoolean("swipe_to_refresh", true);
114 String defaultWebViewTheme = sharedPreferences.getString("webview_theme", getString(R.string.webview_theme_default_value));
115 boolean defaultWideViewport = sharedPreferences.getBoolean("wide_viewport", true);
116 boolean defaultDisplayWebpageImages = sharedPreferences.getBoolean("display_webpage_images", true);
118 // Get handles for the views.
119 ScrollView domainSettingsScrollView = domainSettingsView.findViewById(R.id.domain_settings_scrollview);
120 EditText domainNameEditText = domainSettingsView.findViewById(R.id.domain_settings_name_edittext);
121 ImageView javaScriptImageView = domainSettingsView.findViewById(R.id.javascript_imageview);
122 SwitchCompat javaScriptSwitch = domainSettingsView.findViewById(R.id.javascript_switch);
123 ImageView cookiesImageView = domainSettingsView.findViewById(R.id.cookies_imageview);
124 SwitchCompat cookiesSwitch = domainSettingsView.findViewById(R.id.cookies_switch);
125 ImageView domStorageImageView = domainSettingsView.findViewById(R.id.dom_storage_imageview);
126 SwitchCompat domStorageSwitch = domainSettingsView.findViewById(R.id.dom_storage_switch);
127 ImageView formDataImageView = domainSettingsView.findViewById(R.id.form_data_imageview); // The form data views can be remove once the minimum API >= 26.
128 SwitchCompat formDataSwitch = domainSettingsView.findViewById(R.id.form_data_switch); // The form data views can be remove once the minimum API >= 26.
129 ImageView easyListImageView = domainSettingsView.findViewById(R.id.easylist_imageview);
130 SwitchCompat easyListSwitch = domainSettingsView.findViewById(R.id.easylist_switch);
131 ImageView easyPrivacyImageView = domainSettingsView.findViewById(R.id.easyprivacy_imageview);
132 SwitchCompat easyPrivacySwitch = domainSettingsView.findViewById(R.id.easyprivacy_switch);
133 ImageView fanboysAnnoyanceListImageView = domainSettingsView.findViewById(R.id.fanboys_annoyance_list_imageview);
134 SwitchCompat fanboysAnnoyanceListSwitch = domainSettingsView.findViewById(R.id.fanboys_annoyance_list_switch);
135 ImageView fanboysSocialBlockingListImageView = domainSettingsView.findViewById(R.id.fanboys_social_blocking_list_imageview);
136 SwitchCompat fanboysSocialBlockingListSwitch = domainSettingsView.findViewById(R.id.fanboys_social_blocking_list_switch);
137 ImageView ultraListImageView = domainSettingsView.findViewById(R.id.ultralist_imageview);
138 SwitchCompat ultraListSwitch = domainSettingsView.findViewById(R.id.ultralist_switch);
139 ImageView ultraPrivacyImageView = domainSettingsView.findViewById(R.id.ultraprivacy_imageview);
140 SwitchCompat ultraPrivacySwitch = domainSettingsView.findViewById(R.id.ultraprivacy_switch);
141 ImageView blockAllThirdPartyRequestsImageView = domainSettingsView.findViewById(R.id.block_all_third_party_requests_imageview);
142 SwitchCompat blockAllThirdPartyRequestsSwitch = domainSettingsView.findViewById(R.id.block_all_third_party_requests_switch);
143 Spinner userAgentSpinner = domainSettingsView.findViewById(R.id.user_agent_spinner);
144 TextView userAgentTextView = domainSettingsView.findViewById(R.id.user_agent_textview);
145 EditText customUserAgentEditText = domainSettingsView.findViewById(R.id.custom_user_agent_edittext);
146 Spinner fontSizeSpinner = domainSettingsView.findViewById(R.id.font_size_spinner);
147 TextView defaultFontSizeTextView = domainSettingsView.findViewById(R.id.default_font_size_textview);
148 EditText customFontSizeEditText = domainSettingsView.findViewById(R.id.custom_font_size_edittext);
149 ImageView swipeToRefreshImageView = domainSettingsView.findViewById(R.id.swipe_to_refresh_imageview);
150 Spinner swipeToRefreshSpinner = domainSettingsView.findViewById(R.id.swipe_to_refresh_spinner);
151 TextView swipeToRefreshTextView = domainSettingsView.findViewById(R.id.swipe_to_refresh_textview);
152 ImageView webViewThemeImageView = domainSettingsView.findViewById(R.id.webview_theme_imageview);
153 Spinner webViewThemeSpinner = domainSettingsView.findViewById(R.id.webview_theme_spinner);
154 TextView webViewThemeTextView = domainSettingsView.findViewById(R.id.webview_theme_textview);
155 ImageView wideViewportImageView = domainSettingsView.findViewById(R.id.wide_viewport_imageview);
156 Spinner wideViewportSpinner = domainSettingsView.findViewById(R.id.wide_viewport_spinner);
157 TextView wideViewportTextView = domainSettingsView.findViewById(R.id.wide_viewport_textview);
158 ImageView displayWebpageImagesImageView = domainSettingsView.findViewById(R.id.display_webpage_images_imageview);
159 Spinner displayWebpageImagesSpinner = domainSettingsView.findViewById(R.id.display_webpage_images_spinner);
160 TextView displayImagesTextView = domainSettingsView.findViewById(R.id.display_webpage_images_textview);
161 ImageView pinnedSslCertificateImageView = domainSettingsView.findViewById(R.id.pinned_ssl_certificate_imageview);
162 SwitchCompat pinnedSslCertificateSwitch = domainSettingsView.findViewById(R.id.pinned_ssl_certificate_switch);
163 CardView savedSslCardView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_cardview);
164 LinearLayout savedSslCertificateLinearLayout = domainSettingsView.findViewById(R.id.saved_ssl_certificate_linearlayout);
165 RadioButton savedSslCertificateRadioButton = domainSettingsView.findViewById(R.id.saved_ssl_certificate_radiobutton);
166 TextView savedSslIssuedToCNameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_to_cname);
167 TextView savedSslIssuedToONameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_to_oname);
168 TextView savedSslIssuedToUNameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_to_uname);
169 TextView savedSslIssuedByCNameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_by_cname);
170 TextView savedSslIssuedByONameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_by_oname);
171 TextView savedSslIssuedByUNameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_by_uname);
172 TextView savedSslStartDateTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_start_date);
173 TextView savedSslEndDateTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_end_date);
174 CardView currentSslCardView = domainSettingsView.findViewById(R.id.current_website_certificate_cardview);
175 LinearLayout currentWebsiteCertificateLinearLayout = domainSettingsView.findViewById(R.id.current_website_certificate_linearlayout);
176 RadioButton currentWebsiteCertificateRadioButton = domainSettingsView.findViewById(R.id.current_website_certificate_radiobutton);
177 TextView currentSslIssuedToCNameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_to_cname);
178 TextView currentSslIssuedToONameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_to_oname);
179 TextView currentSslIssuedToUNameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_to_uname);
180 TextView currentSslIssuedByCNameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_by_cname);
181 TextView currentSslIssuedByONameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_by_oname);
182 TextView currentSslIssuedByUNameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_by_uname);
183 TextView currentSslStartDateTextView = domainSettingsView.findViewById(R.id.current_website_certificate_start_date);
184 TextView currentSslEndDateTextView = domainSettingsView.findViewById(R.id.current_website_certificate_end_date);
185 TextView noCurrentWebsiteCertificateTextView = domainSettingsView.findViewById(R.id.no_current_website_certificate);
186 ImageView pinnedIpAddressesImageView = domainSettingsView.findViewById(R.id.pinned_ip_addresses_imageview);
187 SwitchCompat pinnedIpAddressesSwitch = domainSettingsView.findViewById(R.id.pinned_ip_addresses_switch);
188 CardView savedIpAddressesCardView = domainSettingsView.findViewById(R.id.saved_ip_addresses_cardview);
189 LinearLayout savedIpAddressesLinearLayout = domainSettingsView.findViewById(R.id.saved_ip_addresses_linearlayout);
190 RadioButton savedIpAddressesRadioButton = domainSettingsView.findViewById(R.id.saved_ip_addresses_radiobutton);
191 TextView savedIpAddressesTextView = domainSettingsView.findViewById(R.id.saved_ip_addresses_textview);
192 CardView currentIpAddressesCardView = domainSettingsView.findViewById(R.id.current_ip_addresses_cardview);
193 LinearLayout currentIpAddressesLinearLayout = domainSettingsView.findViewById(R.id.current_ip_addresses_linearlayout);
194 RadioButton currentIpAddressesRadioButton = domainSettingsView.findViewById(R.id.current_ip_addresses_radiobutton);
195 TextView currentIpAddressesTextView = domainSettingsView.findViewById(R.id.current_ip_addresses_textview);
197 // Setup the pinned labels.
198 String cNameLabel = getString(R.string.common_name) + " ";
199 String oNameLabel = getString(R.string.organization) + " ";
200 String uNameLabel = getString(R.string.organizational_unit) + " ";
201 String startDateLabel = getString(R.string.start_date) + " ";
202 String endDateLabel = getString(R.string.end_date) + " ";
204 // Initialize the database handler. The `0` specifies the database version, but that is ignored and set instead using a constant in `DomainsDatabaseHelper`.
205 DomainsDatabaseHelper domainsDatabaseHelper = new DomainsDatabaseHelper(context, null, null, 0);
207 // Get the database cursor for this ID and move it to the first row.
208 Cursor domainCursor = domainsDatabaseHelper.getCursorForId(databaseId);
209 domainCursor.moveToFirst();
211 // Save the cursor entries as variables.
212 String domainNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.DOMAIN_NAME));
213 int javaScriptInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_JAVASCRIPT));
214 int cookiesInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.COOKIES));
215 int domStorageInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_DOM_STORAGE));
216 int formDataInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FORM_DATA)); // Form data can be remove once the minimum API >= 26.
217 int easyListInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYLIST));
218 int easyPrivacyInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYPRIVACY));
219 int fanboysAnnoyanceListInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST));
220 int fanboysSocialBlockingListInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST));
221 int ultraListInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ULTRALIST));
222 int ultraPrivacyInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY));
223 int blockAllThirdPartyRequestsInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS));
224 String currentUserAgentName = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.USER_AGENT));
225 int fontSizeInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.FONT_SIZE));
226 int swipeToRefreshInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.SWIPE_TO_REFRESH));
227 int webViewThemeInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.WEBVIEW_THEME));
228 int wideViewportInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.WIDE_VIEWPORT));
229 int displayImagesInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.DISPLAY_IMAGES));
230 int pinnedSslCertificateInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.PINNED_SSL_CERTIFICATE));
231 String savedSslIssuedToCNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_COMMON_NAME));
232 String savedSslIssuedToONameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATION));
233 String savedSslIssuedToUNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATIONAL_UNIT));
234 String savedSslIssuedByCNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_COMMON_NAME));
235 String savedSslIssuedByONameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATION));
236 String savedSslIssuedByUNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATIONAL_UNIT));
237 int pinnedIpAddressesInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.PINNED_IP_ADDRESSES));
238 String savedIpAddresses = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.IP_ADDRESSES));
240 // Initialize the saved SSL certificate date variables.
241 Date savedSslStartDate = null;
242 Date savedSslEndDate = null;
244 // Only get the saved SSL certificate dates from the cursor if they are not set to `0`.
245 if (domainCursor.getLong(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_START_DATE)) != 0) {
246 savedSslStartDate = new Date(domainCursor.getLong(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_START_DATE)));
249 if (domainCursor.getLong(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_END_DATE)) != 0) {
250 savedSslEndDate = new Date(domainCursor.getLong(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_END_DATE)));
253 // Create array adapters for the spinners.
254 ArrayAdapter<CharSequence> translatedUserAgentArrayAdapter = ArrayAdapter.createFromResource(context, R.array.translated_domain_settings_user_agent_names, R.layout.spinner_item);
255 ArrayAdapter<CharSequence> fontSizeArrayAdapter = ArrayAdapter.createFromResource(context, R.array.font_size_array, R.layout.spinner_item);
256 ArrayAdapter<CharSequence> swipeToRefreshArrayAdapter = ArrayAdapter.createFromResource(context, R.array.swipe_to_refresh_array, R.layout.spinner_item);
257 ArrayAdapter<CharSequence> webViewThemeArrayAdapter = ArrayAdapter.createFromResource(context, R.array.webview_theme_array, R.layout.spinner_item);
258 ArrayAdapter<CharSequence> wideViewportArrayAdapter = ArrayAdapter.createFromResource(context, R.array.wide_viewport_array, R.layout.spinner_item);
259 ArrayAdapter<CharSequence> displayImagesArrayAdapter = ArrayAdapter.createFromResource(context, R.array.display_webpage_images_array, R.layout.spinner_item);
261 // Set the drop down view resource on the spinners.
262 translatedUserAgentArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items);
263 fontSizeArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items);
264 swipeToRefreshArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items);
265 webViewThemeArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items);
266 wideViewportArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items);
267 displayImagesArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items);
269 // Set the array adapters for the spinners.
270 userAgentSpinner.setAdapter(translatedUserAgentArrayAdapter);
271 fontSizeSpinner.setAdapter(fontSizeArrayAdapter);
272 swipeToRefreshSpinner.setAdapter(swipeToRefreshArrayAdapter);
273 webViewThemeSpinner.setAdapter(webViewThemeArrayAdapter);
274 wideViewportSpinner.setAdapter(wideViewportArrayAdapter);
275 displayWebpageImagesSpinner.setAdapter(displayImagesArrayAdapter);
277 // Create a spannable string builder for each TextView that needs multiple colors of text.
278 SpannableStringBuilder savedSslIssuedToCNameStringBuilder = new SpannableStringBuilder(cNameLabel + savedSslIssuedToCNameString);
279 SpannableStringBuilder savedSslIssuedToONameStringBuilder = new SpannableStringBuilder(oNameLabel + savedSslIssuedToONameString);
280 SpannableStringBuilder savedSslIssuedToUNameStringBuilder = new SpannableStringBuilder(uNameLabel + savedSslIssuedToUNameString);
281 SpannableStringBuilder savedSslIssuedByCNameStringBuilder = new SpannableStringBuilder(cNameLabel + savedSslIssuedByCNameString);
282 SpannableStringBuilder savedSslIssuedByONameStringBuilder = new SpannableStringBuilder(oNameLabel + savedSslIssuedByONameString);
283 SpannableStringBuilder savedSslIssuedByUNameStringBuilder = new SpannableStringBuilder(uNameLabel + savedSslIssuedByUNameString);
285 // Initialize the spannable string builders for the saved SSL certificate dates.
286 SpannableStringBuilder savedSslStartDateStringBuilder;
287 SpannableStringBuilder savedSslEndDateStringBuilder;
289 // Leave the SSL certificate dates empty if they are `null`.
290 if (savedSslStartDate == null) {
291 savedSslStartDateStringBuilder = new SpannableStringBuilder(startDateLabel);
293 savedSslStartDateStringBuilder = new SpannableStringBuilder(startDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG).format(savedSslStartDate));
296 if (savedSslEndDate == null) {
297 savedSslEndDateStringBuilder = new SpannableStringBuilder(endDateLabel);
299 savedSslEndDateStringBuilder = new SpannableStringBuilder(endDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG).format(savedSslEndDate));
302 // Create the foreground color spans.
303 final ForegroundColorSpan blueColorSpan;
304 final ForegroundColorSpan redColorSpan;
306 // Set the color spans according to the theme. The deprecated `getColor()` must be used until the minimum API >= 23.
307 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
308 blueColorSpan = new ForegroundColorSpan(resources.getColor(R.color.blue_700));
309 redColorSpan = new ForegroundColorSpan(resources.getColor(R.color.red_a700));
311 blueColorSpan = new ForegroundColorSpan(resources.getColor(R.color.violet_700));
312 redColorSpan = new ForegroundColorSpan(resources.getColor(R.color.red_900));
315 // Set the domain name from the the database cursor.
316 domainNameEditText.setText(domainNameString);
318 // Update the certificates' `Common Name` color when the domain name text changes.
319 domainNameEditText.addTextChangedListener(new TextWatcher() {
321 public void beforeTextChanged(CharSequence s, int start, int count, int after) {
326 public void onTextChanged(CharSequence s, int start, int before, int count) {
331 public void afterTextChanged(Editable s) {
332 // Get the new domain name.
333 String newDomainName = domainNameEditText.getText().toString();
335 // Check the saved SSL certificate against the new domain name.
336 boolean savedSslMatchesNewDomainName = checkDomainNameAgainstCertificate(newDomainName, savedSslIssuedToCNameString);
338 // Create a `SpannableStringBuilder` for the saved certificate `Common Name`.
339 SpannableStringBuilder savedSslCNameStringBuilder = new SpannableStringBuilder(cNameLabel + savedSslIssuedToCNameString);
341 // Format the saved certificate `Common Name` color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
342 if (savedSslMatchesNewDomainName) {
343 savedSslCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), savedSslCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
345 savedSslCNameStringBuilder.setSpan(redColorSpan, cNameLabel.length(), savedSslCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
348 // Update the saved SSL issued to CName text view.
349 savedSslIssuedToCNameTextView.setText(savedSslCNameStringBuilder);
351 // Update the current website certificate if it exists.
352 if (DomainsActivity.sslIssuedToCName != null) {
353 // Check the current website certificate against the new domain name.
354 boolean currentSslMatchesNewDomainName = checkDomainNameAgainstCertificate(newDomainName, DomainsActivity.sslIssuedToCName);
356 // Create a `SpannableStringBuilder` for the current website certificate `Common Name`.
357 SpannableStringBuilder currentSslCNameStringBuilder = new SpannableStringBuilder(cNameLabel + DomainsActivity.sslIssuedToCName);
359 // Format the current certificate `Common Name` color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
360 if (currentSslMatchesNewDomainName) {
361 currentSslCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), currentSslCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
363 currentSslCNameStringBuilder.setSpan(redColorSpan, cNameLabel.length(), currentSslCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
366 // Update the current SSL issued to CName text view.
367 currentSslIssuedToCNameTextView.setText(currentSslCNameStringBuilder);
372 // Set the JavaScript switch status.
373 if (javaScriptInt == 1) { // JavaScript is enabled.
374 javaScriptSwitch.setChecked(true);
375 javaScriptImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.javascript_enabled, null));
376 } else { // JavaScript is disabled.
377 javaScriptSwitch.setChecked(false);
378 javaScriptImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.privacy_mode, null));
381 // Set the cookies switch status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
382 if (cookiesInt == 1) { // Cookies are enabled.
383 // Turn the switch on.
384 cookiesSwitch.setChecked(true);
387 cookiesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.cookies_enabled, null));
388 } else { // Cookies are disabled.
389 // Turn the switch off
390 cookiesSwitch.setChecked(false);
392 // Set the icon according to the theme.
393 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
394 cookiesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.cookies_disabled_day, null));
396 cookiesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.cookies_disabled_night, null));
400 // Only enable DOM storage if JavaScript is enabled.
401 if (javaScriptInt == 1) { // JavaScript is enabled.
402 // Enable the DOM storage switch.
403 domStorageSwitch.setEnabled(true);
405 // Set the DOM storage status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
406 if (domStorageInt == 1) { // Both JavaScript and DOM storage are enabled.
407 domStorageSwitch.setChecked(true);
408 domStorageImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.dom_storage_enabled, null));
409 } else { // JavaScript is enabled but DOM storage is disabled.
410 // Set the DOM storage switch to off.
411 domStorageSwitch.setChecked(false);
413 // Set the icon according to the theme.
414 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
415 domStorageImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.dom_storage_disabled_night, null));
417 domStorageImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.dom_storage_disabled_day, null));
420 } else { // JavaScript is disabled.
421 // Disable the DOM storage `Switch`.
422 domStorageSwitch.setEnabled(false);
424 // Set the checked status of DOM storage.
425 domStorageSwitch.setChecked(domStorageInt == 1);
427 // Set the icon according to the theme.
428 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
429 domStorageImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.dom_storage_ghosted_night, null));
431 domStorageImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.dom_storage_ghosted_day, null));
435 // Set the form data visibility. Form data can be removed once the minimum API >= 26.
436 if (Build.VERSION.SDK_INT >= 26) { // Form data no longer applies to newer versions of Android.
437 // Hide the form data image view and switch.
438 formDataImageView.setVisibility(View.GONE);
439 formDataSwitch.setVisibility(View.GONE);
440 } else { // Form data should be displayed because this is an older version of Android.
441 if (formDataInt == 1) { // Form data is on.
442 // Turn the form data switch on.
443 formDataSwitch.setChecked(true);
445 // Set the form data icon.
446 formDataImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.form_data_enabled, null));
447 } else { // Form data is off.
448 // Turn the form data switch to off.
449 formDataSwitch.setChecked(false);
451 // 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.
452 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
453 formDataImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.form_data_disabled_night, null));
455 formDataImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.form_data_disabled_day, null));
460 // Set the EasyList status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
461 if (easyListInt == 1) { // EasyList is on.
462 // Turn the switch on.
463 easyListSwitch.setChecked(true);
465 // Set the icon according to the theme.
466 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
467 easyListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_ads_enabled_night, null));
469 easyListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_ads_enabled_day, null));
471 } else { // EasyList is off.
472 // Turn the switch off.
473 easyListSwitch.setChecked(false);
475 // Set the icon according to the theme.
476 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
477 easyListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_ads_disabled_night, null));
479 easyListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_ads_disabled_day, null));
483 // Set the EasyPrivacy status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
484 if (easyPrivacyInt == 1) { // EasyPrivacy is on.
485 // Turn the switch on.
486 easyPrivacySwitch.setChecked(true);
488 // Set the icon according to the theme.
489 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
490 easyPrivacyImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_tracking_enabled_night, null));
492 easyPrivacyImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_tracking_enabled_day, null));
494 } else { // EasyPrivacy is off.
495 // Turn the switch off.
496 easyPrivacySwitch.setChecked(false);
498 // Set the icon according to the theme.
499 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
500 easyPrivacyImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_tracking_disabled_night, null));
502 easyPrivacyImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_tracking_disabled_day, null));
506 // 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.
507 if (fanboysAnnoyanceListInt == 1) { // Fanboy's Annoyance List is on.
508 // Turn the switch on.
509 fanboysAnnoyanceListSwitch.setChecked(true);
511 // Set the icon according to the theme.
512 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
513 fanboysAnnoyanceListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.social_media_enabled_night, null));
515 fanboysAnnoyanceListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.social_media_enabled_day, null));
517 } else { // Fanboy's Annoyance List is off.
518 // Turn the switch off.
519 fanboysAnnoyanceListSwitch.setChecked(false);
521 // Set the icon according to the theme.
522 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
523 fanboysAnnoyanceListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.social_media_disabled_night, null));
525 fanboysAnnoyanceListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.social_media_disabled_day, null));
529 // Only enable Fanboy's Social Blocking List if Fanboy's Annoyance List is off.
530 if (fanboysAnnoyanceListInt == 0) { // Fanboy's Annoyance List is on.
531 // Enable Fanboy's Social Blocking List switch.
532 fanboysSocialBlockingListSwitch.setEnabled(true);
534 // 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.
535 if (fanboysSocialBlockingListInt == 1) { // Fanboy's Social Blocking List is on.
536 // Turn on Fanboy's Social Blocking List switch.
537 fanboysSocialBlockingListSwitch.setChecked(true);
539 // Set the icon according to the theme.
540 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
541 fanboysSocialBlockingListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.social_media_enabled_night, null));
543 fanboysSocialBlockingListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.social_media_enabled_day, null));
545 } else { // Fanboy's Social Blocking List is off.
546 // Turn off Fanboy's Social Blocking List switch.
547 fanboysSocialBlockingListSwitch.setChecked(false);
549 // Set the icon according to the theme.
550 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
551 fanboysSocialBlockingListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.social_media_disabled_night, null));
553 fanboysSocialBlockingListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.social_media_disabled_day, null));
556 } else { // Fanboy's Annoyance List is on.
557 // Disable Fanboy's Social Blocking List switch.
558 fanboysSocialBlockingListSwitch.setEnabled(false);
560 // Set the status of Fanboy's Social Blocking List.
561 fanboysSocialBlockingListSwitch.setChecked(fanboysSocialBlockingListInt == 1);
563 // Set the icon according to the theme.
564 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
565 fanboysSocialBlockingListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.social_media_ghosted_night, null));
567 fanboysSocialBlockingListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.social_media_ghosted_day, null));
571 // Set the UltraList status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
572 if (ultraListInt == 1) { // UltraList is on.
573 // Turn the switch on.
574 ultraListSwitch.setChecked(true);
576 // Set the icon according to the theme.
577 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
578 ultraListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_ads_enabled_night, null));
580 ultraListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_ads_enabled_day, null));
582 } else { // UltraList is off.
583 // Turn the switch off.
584 ultraListSwitch.setChecked(false);
586 // Set the icon according to the theme.
587 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
588 ultraListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_ads_disabled_night, null));
590 ultraListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_ads_disabled_day, null));
594 // Set the UltraPrivacy status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
595 if (ultraPrivacyInt == 1) { // UltraPrivacy is on.
596 // Turn the switch on.
597 ultraPrivacySwitch.setChecked(true);
599 // Set the icon according to the theme.
600 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
601 ultraPrivacyImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_tracking_enabled_night, null));
603 ultraPrivacyImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_tracking_enabled_day, null));
605 } else { // EasyPrivacy is off.
606 // Turn the switch off.
607 ultraPrivacySwitch.setChecked(false);
609 // Set the icon according to the theme.
610 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
611 ultraPrivacyImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_tracking_disabled_night, null));
613 ultraPrivacyImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_tracking_disabled_day, null));
617 // 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.
618 if (blockAllThirdPartyRequestsInt == 1) { // Blocking all third-party requests is on.
619 // Turn the switch on.
620 blockAllThirdPartyRequestsSwitch.setChecked(true);
622 // Set the icon according to the theme.
623 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
624 blockAllThirdPartyRequestsImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_all_third_party_requests_enabled_night, null));
626 blockAllThirdPartyRequestsImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_all_third_party_requests_enabled_day, null));
628 } else { // Blocking all third-party requests is off.
629 // Turn the switch off.
630 blockAllThirdPartyRequestsSwitch.setChecked(false);
632 // Set the icon according to the theme.
633 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
634 blockAllThirdPartyRequestsImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_all_third_party_requests_disabled_night, null));
636 blockAllThirdPartyRequestsImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_all_third_party_requests_disabled_day, null));
640 // Inflated a WebView to get the default user agent.
641 // `@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.
642 @SuppressLint("InflateParams") View bareWebViewLayout = inflater.inflate(R.layout.bare_webview, null, false);
643 WebView bareWebView = bareWebViewLayout.findViewById(R.id.bare_webview);
644 final String webViewDefaultUserAgentString = bareWebView.getSettings().getUserAgentString();
646 // Get a handle for the user agent array adapter. This array does not contain the `System default` entry.
647 ArrayAdapter<CharSequence> userAgentNamesArray = ArrayAdapter.createFromResource(context, R.array.user_agent_names, R.layout.spinner_item);
649 // Get the positions of the user agent and the default user agent.
650 int userAgentArrayPosition = userAgentNamesArray.getPosition(currentUserAgentName);
651 int defaultUserAgentArrayPosition = userAgentNamesArray.getPosition(defaultUserAgentName);
653 // Get a handle for the user agent data array. This array does not contain the `System default` entry.
654 String[] userAgentDataArray = resources.getStringArray(R.array.user_agent_data);
656 // Set the user agent text.
657 if (currentUserAgentName.equals(getString(R.string.system_default_user_agent))) { // Use the system default user agent.
658 // Set the user agent according to the system default.
659 switch (defaultUserAgentArrayPosition) {
660 case MainWebViewActivity.UNRECOGNIZED_USER_AGENT: // The default user agent name is not on the canonical list.
661 // This is probably because it was set in an older version of Privacy Browser before the switch to persistent user agent names.
662 userAgentTextView.setText(defaultUserAgentName);
665 case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
666 // Display the `WebView` default user agent.
667 userAgentTextView.setText(webViewDefaultUserAgentString);
670 case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
671 // Display the custom user agent.
672 userAgentTextView.setText(defaultCustomUserAgentString);
676 // Get the user agent string from the user agent data array.
677 userAgentTextView.setText(userAgentDataArray[defaultUserAgentArrayPosition]);
679 } else if (userAgentArrayPosition == MainWebViewActivity.UNRECOGNIZED_USER_AGENT) { // A custom user agent is stored in the current user agent name.
680 // Set the user agent spinner to `Custom user agent`.
681 userAgentSpinner.setSelection(MainWebViewActivity.DOMAINS_CUSTOM_USER_AGENT);
683 // Hide the user agent TextView.
684 userAgentTextView.setVisibility(View.GONE);
686 // Show the custom user agent EditText and set the current user agent name as the text.
687 customUserAgentEditText.setVisibility(View.VISIBLE);
688 customUserAgentEditText.setText(currentUserAgentName);
689 } else { // The user agent name contains one of the canonical user agents.
690 // 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.
691 userAgentSpinner.setSelection(userAgentArrayPosition + 1);
693 // Show the user agent TextView.
694 userAgentTextView.setVisibility(View.VISIBLE);
696 // Hide the custom user agent EditText.
697 customUserAgentEditText.setVisibility(View.GONE);
699 // Set the user agent text.
700 if (userAgentArrayPosition == MainWebViewActivity.DOMAINS_WEBVIEW_DEFAULT_USER_AGENT) { // The WebView default user agent is selected.
701 // Display the WebView default user agent.
702 userAgentTextView.setText(webViewDefaultUserAgentString);
703 } else { // A user agent besides the default is selected.
704 // 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.
705 userAgentTextView.setText(userAgentDataArray[userAgentArrayPosition + 1]);
709 // Open the user agent spinner when the text view is clicked.
710 userAgentTextView.setOnClickListener((View v) -> {
711 // Open the user agent spinner.
712 userAgentSpinner.performClick();
715 // Display the font size settings.
716 if (fontSizeInt == 0) { // `0` is the code for system default font size.
717 // Set the font size to the system default
718 fontSizeSpinner.setSelection(0);
720 // Show the default font size text view.
721 defaultFontSizeTextView.setVisibility(View.VISIBLE);
723 // Hide the custom font size edit text.
724 customFontSizeEditText.setVisibility(View.GONE);
726 // 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.
727 customFontSizeEditText.setText(defaultFontSizeString);
728 } else { // A custom font size is selected.
729 // Set the spinner to the custom font size.
730 fontSizeSpinner.setSelection(1);
732 // Hide the default font size text view.
733 defaultFontSizeTextView.setVisibility(View.GONE);
735 // Show the custom font size edit text.
736 customFontSizeEditText.setVisibility(View.GONE);
738 // Set the custom font size.
739 customFontSizeEditText.setText(String.valueOf(fontSizeInt));
742 // Initialize the default font size percentage string.
743 String defaultFontSizePercentageString = defaultFontSizeString + "%";
745 // Set the default font size text in the text view.
746 defaultFontSizeTextView.setText(defaultFontSizePercentageString);
748 // Open the font size spinner when the text view is clicked.
749 defaultFontSizeTextView.setOnClickListener((View v) -> {
750 // Open the user agent spinner.
751 fontSizeSpinner.performClick();
754 // Select the swipe to refresh selection in the spinner.
755 swipeToRefreshSpinner.setSelection(swipeToRefreshInt);
757 // Set the swipe to refresh text.
758 if (defaultSwipeToRefresh) {
759 swipeToRefreshTextView.setText(swipeToRefreshArrayAdapter.getItem(DomainsDatabaseHelper.ENABLED));
761 swipeToRefreshTextView.setText(swipeToRefreshArrayAdapter.getItem(DomainsDatabaseHelper.DISABLED));
764 // 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.
765 switch (swipeToRefreshInt) {
766 case DomainsDatabaseHelper.SYSTEM_DEFAULT:
767 if (defaultSwipeToRefresh) { // Swipe to refresh is enabled by default.
768 // Set the icon according to the theme.
769 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
770 swipeToRefreshImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.refresh_enabled_night, null));
772 swipeToRefreshImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.refresh_enabled_day, null));
774 } else { // Swipe to refresh is disabled by default
775 // Set the icon according to the theme.
776 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
777 swipeToRefreshImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.refresh_disabled_night, null));
779 swipeToRefreshImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.refresh_disabled_day, null));
783 // Show the swipe to refresh TextView.
784 swipeToRefreshTextView.setVisibility(View.VISIBLE);
787 case DomainsDatabaseHelper.ENABLED:
788 // Set the icon according to the theme.
789 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
790 swipeToRefreshImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.refresh_enabled_night, null));
792 swipeToRefreshImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.refresh_enabled_day, null));
795 // Hide the swipe to refresh TextView.`
796 swipeToRefreshTextView.setVisibility(View.GONE);
799 case DomainsDatabaseHelper.DISABLED:
800 // Set the icon according to the theme.
801 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
802 swipeToRefreshImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.refresh_disabled_night, null));
804 swipeToRefreshImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.refresh_disabled_day, null));
807 // Hide the swipe to refresh TextView.
808 swipeToRefreshTextView.setVisibility(View.GONE);
812 // Open the swipe to refresh spinner when the TextView is clicked.
813 swipeToRefreshTextView.setOnClickListener((View v) -> {
814 // Open the swipe to refresh spinner.
815 swipeToRefreshSpinner.performClick();
818 // Get the WebView theme string arrays.
819 String[] webViewThemeStringArray = resources.getStringArray(R.array.webview_theme_array);
820 String[] webViewThemeEntryValuesStringArray = resources.getStringArray(R.array.webview_theme_entry_values);
822 // Define an app WebView theme entry number.
823 int appWebViewThemeEntryNumber;
825 // 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.
826 if (defaultWebViewTheme.equals(webViewThemeEntryValuesStringArray[1])) { // The light theme is selected.
827 // Store the default WebView theme entry number.
828 appWebViewThemeEntryNumber = 1;
829 } else if (defaultWebViewTheme.equals(webViewThemeEntryValuesStringArray[2])) { // The dark theme is selected.
830 // Store the default WebView theme entry number.
831 appWebViewThemeEntryNumber = 2;
832 } else { // The system default theme is selected.
833 // Store the default WebView theme entry number.
834 appWebViewThemeEntryNumber = 0;
837 // Set the WebView theme visibility.
838 if (Build.VERSION.SDK_INT < 21) { // The WebView theme cannot be set on API 19.
839 // Get a handle for the webView theme linear layout.
840 LinearLayout webViewThemeLinearLayout = domainSettingsView.findViewById(R.id.webview_theme_linearlayout);
842 // Hide the WebView theme linear layout.
843 webViewThemeLinearLayout.setVisibility(View.GONE);
844 } else { // The WebView theme can be set on API >= 21.
845 // Select the WebView theme in the spinner.
846 webViewThemeSpinner.setSelection(webViewThemeInt);
848 // Set the WebView theme text.
849 if (appWebViewThemeEntryNumber == DomainsDatabaseHelper.SYSTEM_DEFAULT) { // The app WebView theme is system default.
850 // Set the text according to the current UI theme.
851 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
852 webViewThemeTextView.setText(webViewThemeStringArray[DomainsDatabaseHelper.LIGHT_THEME]);
854 webViewThemeTextView.setText(webViewThemeStringArray[DomainsDatabaseHelper.DARK_THEME]);
856 } else { // The app WebView theme is not system default.
857 // Set the text according to the app WebView theme.
858 webViewThemeTextView.setText(webViewThemeStringArray[appWebViewThemeEntryNumber]);
861 // 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.
862 switch (webViewThemeInt) {
863 case DomainsDatabaseHelper.SYSTEM_DEFAULT: // The domain WebView theme is system default.
864 // Set the icon according to the app WebView theme.
865 switch (appWebViewThemeEntryNumber) {
866 case DomainsDatabaseHelper.SYSTEM_DEFAULT: // The default WebView theme is system default.
867 // Set the icon according to the app theme.
868 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
869 // Set the light mode icon.
870 webViewThemeImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.webview_light_theme_day, null));
872 // Set the dark theme icon.
873 webViewThemeImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.webview_dark_theme_night, null));
877 case DomainsDatabaseHelper.LIGHT_THEME: // the default WebView theme is light.
878 // Set the icon according to the app theme.
879 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
880 webViewThemeImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.webview_light_theme_day, null));
882 webViewThemeImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.webview_light_theme_night, null));
886 case DomainsDatabaseHelper.DARK_THEME: // the default WebView theme is dark.
887 // Set the icon according to the app theme.
888 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
889 webViewThemeImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.webview_dark_theme_day, null));
891 webViewThemeImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.webview_dark_theme_night, null)); }
895 // Show the WebView theme text view.
896 webViewThemeTextView.setVisibility(View.VISIBLE);
899 case DomainsDatabaseHelper.LIGHT_THEME: // The domain WebView theme is light.
900 // Set the icon according to the app theme.
901 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
902 webViewThemeImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.webview_light_theme_day, null));
904 webViewThemeImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.webview_light_theme_night, null));
907 // Hide the WebView theme text view.
908 webViewThemeTextView.setVisibility(View.GONE);
911 case DomainsDatabaseHelper.DARK_THEME: // The domain WebView theme is dark.
912 // Set the icon according to the app theme.
913 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
914 webViewThemeImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.webview_dark_theme_day, null));
916 webViewThemeImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.webview_dark_theme_night, null));
919 // Hide the WebView theme text view.
920 webViewThemeTextView.setVisibility(View.GONE);
924 // Open the WebView theme spinner when the text view is clicked.
925 webViewThemeTextView.setOnClickListener((View v) -> {
926 // Open the WebView theme spinner.
927 webViewThemeSpinner.performClick();
931 // Select the wide viewport in the spinner.
932 wideViewportSpinner.setSelection(wideViewportInt);
934 // Set the default wide viewport text.
935 if (defaultWideViewport) {
936 wideViewportTextView.setText(wideViewportArrayAdapter.getItem(DomainsDatabaseHelper.ENABLED));
938 wideViewportTextView.setText(wideViewportArrayAdapter.getItem(DomainsDatabaseHelper.DISABLED));
941 // 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.
942 switch (wideViewportInt) {
943 case DomainsDatabaseHelper.SYSTEM_DEFAULT:
944 if (defaultWideViewport) { // Wide viewport enabled by default.
945 // Set the icon according to the theme.
946 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
947 wideViewportImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.wide_viewport_enabled_night, null));
949 wideViewportImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.wide_viewport_enabled_day, null));
951 } else { // Wide viewport disabled by default.
952 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
953 wideViewportImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.wide_viewport_disabled_night, null));
955 wideViewportImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.wide_viewport_disabled_day, null));
959 // Show the wide viewport text view.
960 wideViewportTextView.setVisibility(View.VISIBLE);
963 case DomainsDatabaseHelper.ENABLED:
964 // Set the icon according to the theme.
965 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
966 wideViewportImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.wide_viewport_enabled_night, null));
968 wideViewportImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.wide_viewport_enabled_day, null));
971 // Hide the wide viewport text view.
972 wideViewportTextView.setVisibility(View.GONE);
975 case DomainsDatabaseHelper.DISABLED:
976 // Set the icon according to the theme.
977 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
978 wideViewportImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.wide_viewport_disabled_night, null));
980 wideViewportImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.wide_viewport_disabled_day, null));
983 // Hide the wide viewport text view.
984 wideViewportTextView.setVisibility(View.GONE);
988 // Open the wide viewport spinner when the text view is clicked.
989 wideViewportTextView.setOnClickListener((View view) -> {
990 // Open the wide viewport spinner.
991 wideViewportSpinner.performClick();
994 // Display the website images mode in the spinner.
995 displayWebpageImagesSpinner.setSelection(displayImagesInt);
997 // Set the default display images text.
998 if (defaultDisplayWebpageImages) {
999 displayImagesTextView.setText(displayImagesArrayAdapter.getItem(DomainsDatabaseHelper.ENABLED));
1001 displayImagesTextView.setText(displayImagesArrayAdapter.getItem(DomainsDatabaseHelper.DISABLED));
1004 // 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.
1005 switch (displayImagesInt) {
1006 case DomainsDatabaseHelper.SYSTEM_DEFAULT:
1007 if (defaultDisplayWebpageImages) { // Display webpage images enabled by default.
1008 // Set the icon according to the theme.
1009 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1010 displayWebpageImagesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.images_enabled_night, null));
1012 displayWebpageImagesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.images_enabled_day, null));
1014 } else { // Display webpage images disabled by default.
1015 // Set the icon according to the theme.
1016 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1017 displayWebpageImagesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.images_disabled_night, null));
1019 displayWebpageImagesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.images_disabled_day, null));
1023 // Show the display images text view.
1024 displayImagesTextView.setVisibility(View.VISIBLE);
1027 case DomainsDatabaseHelper.ENABLED:
1028 // Set the icon according to the theme.
1029 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1030 displayWebpageImagesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.images_enabled_night, null));
1032 displayWebpageImagesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.images_enabled_day, null));
1035 // Hide the display images text view.
1036 displayImagesTextView.setVisibility(View.GONE);
1039 case DomainsDatabaseHelper.DISABLED:
1040 // Set the icon according to the theme.
1041 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1042 displayWebpageImagesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.images_disabled_night, null));
1044 displayWebpageImagesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.images_disabled_day, null));
1047 // Hide the display images text view.
1048 displayImagesTextView.setVisibility(View.GONE);
1052 // Open the display images spinner when the text view is clicked.
1053 displayImagesTextView.setOnClickListener((View view) -> {
1054 // Open the user agent spinner.
1055 displayWebpageImagesSpinner.performClick();
1058 // Set the pinned SSL certificate icon.
1059 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.
1060 // Check the switch.
1061 pinnedSslCertificateSwitch.setChecked(true);
1063 // Set the icon according to the theme.
1064 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1065 pinnedSslCertificateImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ssl_certificate_enabled_night, null));
1067 pinnedSslCertificateImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ssl_certificate_enabled_day, null));
1069 } else { // Pinned SSL certificate is disabled.
1070 // Uncheck the switch.
1071 pinnedSslCertificateSwitch.setChecked(false);
1073 // Set the icon according to the theme.
1074 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1075 pinnedSslCertificateImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ssl_certificate_disabled_night, null));
1077 pinnedSslCertificateImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ssl_certificate_disabled_day, null));
1081 // Store the current date.
1082 Date currentDate = Calendar.getInstance().getTime();
1084 // Setup the string builders to display the general certificate information in blue. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1085 savedSslIssuedToONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), savedSslIssuedToONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1086 savedSslIssuedToUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), savedSslIssuedToUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1087 savedSslIssuedByCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), savedSslIssuedByCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1088 savedSslIssuedByONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), savedSslIssuedByONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1089 savedSslIssuedByUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), savedSslIssuedByUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1091 // Check the certificate Common Name against the domain name.
1092 boolean savedSslCommonNameMatchesDomainName = checkDomainNameAgainstCertificate(domainNameString, savedSslIssuedToCNameString);
1094 // Format the issued to Common Name color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1095 if (savedSslCommonNameMatchesDomainName) {
1096 savedSslIssuedToCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), savedSslIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1098 savedSslIssuedToCNameStringBuilder.setSpan(redColorSpan, cNameLabel.length(), savedSslIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1101 // Format the start date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1102 if ((savedSslStartDate != null) && savedSslStartDate.after(currentDate)) { // The certificate start date is in the future.
1103 savedSslStartDateStringBuilder.setSpan(redColorSpan, startDateLabel.length(), savedSslStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1104 } else { // The certificate start date is in the past.
1105 savedSslStartDateStringBuilder.setSpan(blueColorSpan, startDateLabel.length(), savedSslStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1108 // Format the end date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1109 if ((savedSslEndDate != null) && savedSslEndDate.before(currentDate)) { // The certificate end date is in the past.
1110 savedSslEndDateStringBuilder.setSpan(redColorSpan, endDateLabel.length(), savedSslEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1111 } else { // The certificate end date is in the future.
1112 savedSslEndDateStringBuilder.setSpan(blueColorSpan, endDateLabel.length(), savedSslEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1115 // Display the saved website SSL certificate strings.
1116 savedSslIssuedToCNameTextView.setText(savedSslIssuedToCNameStringBuilder);
1117 savedSslIssuedToONameTextView.setText(savedSslIssuedToONameStringBuilder);
1118 savedSslIssuedToUNameTextView.setText(savedSslIssuedToUNameStringBuilder);
1119 savedSslIssuedByCNameTextView.setText(savedSslIssuedByCNameStringBuilder);
1120 savedSslIssuedByONameTextView.setText(savedSslIssuedByONameStringBuilder);
1121 savedSslIssuedByUNameTextView.setText(savedSslIssuedByUNameStringBuilder);
1122 savedSslStartDateTextView.setText(savedSslStartDateStringBuilder);
1123 savedSslEndDateTextView.setText(savedSslEndDateStringBuilder);
1125 // Populate the current website SSL certificate if there is one.
1126 if (DomainsActivity.sslIssuedToCName != null) {
1127 // Get dates from the raw long values.
1128 Date currentSslStartDate = new Date(DomainsActivity.sslStartDateLong);
1129 Date currentSslEndDate = new Date(DomainsActivity.sslEndDateLong);
1131 // Create a spannable string builder for each text view that needs multiple colors of text.
1132 SpannableStringBuilder currentSslIssuedToCNameStringBuilder = new SpannableStringBuilder(cNameLabel + DomainsActivity.sslIssuedToCName);
1133 SpannableStringBuilder currentSslIssuedToONameStringBuilder = new SpannableStringBuilder(oNameLabel + DomainsActivity.sslIssuedToOName);
1134 SpannableStringBuilder currentSslIssuedToUNameStringBuilder = new SpannableStringBuilder(uNameLabel + DomainsActivity.sslIssuedToUName);
1135 SpannableStringBuilder currentSslIssuedByCNameStringBuilder = new SpannableStringBuilder(cNameLabel + DomainsActivity.sslIssuedByCName);
1136 SpannableStringBuilder currentSslIssuedByONameStringBuilder = new SpannableStringBuilder(oNameLabel + DomainsActivity.sslIssuedByOName);
1137 SpannableStringBuilder currentSslIssuedByUNameStringBuilder = new SpannableStringBuilder(uNameLabel + DomainsActivity.sslIssuedByUName);
1138 SpannableStringBuilder currentSslStartDateStringBuilder = new SpannableStringBuilder(startDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG)
1139 .format(currentSslStartDate));
1140 SpannableStringBuilder currentSslEndDateStringBuilder = new SpannableStringBuilder(endDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG)
1141 .format(currentSslEndDate));
1143 // Setup the string builders to display the general certificate information in blue. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1144 currentSslIssuedToONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), currentSslIssuedToONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1145 currentSslIssuedToUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), currentSslIssuedToUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1146 currentSslIssuedByCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), currentSslIssuedByCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1147 currentSslIssuedByONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), currentSslIssuedByONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1148 currentSslIssuedByUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), currentSslIssuedByUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1150 // Check the certificate Common Name against the domain name.
1151 boolean currentSslCommonNameMatchesDomainName = checkDomainNameAgainstCertificate(domainNameString, DomainsActivity.sslIssuedToCName);
1153 // Format the issued to Common Name color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1154 if (currentSslCommonNameMatchesDomainName) {
1155 currentSslIssuedToCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), currentSslIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1157 currentSslIssuedToCNameStringBuilder.setSpan(redColorSpan, cNameLabel.length(), currentSslIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1160 // Format the start date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1161 if (currentSslStartDate.after(currentDate)) { // The certificate start date is in the future.
1162 currentSslStartDateStringBuilder.setSpan(redColorSpan, startDateLabel.length(), currentSslStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1163 } else { // The certificate start date is in the past.
1164 currentSslStartDateStringBuilder.setSpan(blueColorSpan, startDateLabel.length(), currentSslStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1167 // Format the end date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1168 if (currentSslEndDate.before(currentDate)) { // The certificate end date is in the past.
1169 currentSslEndDateStringBuilder.setSpan(redColorSpan, endDateLabel.length(), currentSslEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1170 } else { // The certificate end date is in the future.
1171 currentSslEndDateStringBuilder.setSpan(blueColorSpan, endDateLabel.length(), currentSslEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1174 // Display the current website SSL certificate strings.
1175 currentSslIssuedToCNameTextView.setText(currentSslIssuedToCNameStringBuilder);
1176 currentSslIssuedToONameTextView.setText(currentSslIssuedToONameStringBuilder);
1177 currentSslIssuedToUNameTextView.setText(currentSslIssuedToUNameStringBuilder);
1178 currentSslIssuedByCNameTextView.setText(currentSslIssuedByCNameStringBuilder);
1179 currentSslIssuedByONameTextView.setText(currentSslIssuedByONameStringBuilder);
1180 currentSslIssuedByUNameTextView.setText(currentSslIssuedByUNameStringBuilder);
1181 currentSslStartDateTextView.setText(currentSslStartDateStringBuilder);
1182 currentSslEndDateTextView.setText(currentSslEndDateStringBuilder);
1185 // Set the initial display status of the SSL certificates card views.
1186 if (pinnedSslCertificateSwitch.isChecked()) { // An SSL certificate is pinned.
1187 // Set the visibility of the saved SSL certificate.
1188 if (savedSslIssuedToCNameString == null) {
1189 savedSslCardView.setVisibility(View.GONE);
1191 savedSslCardView.setVisibility(View.VISIBLE);
1194 // Set the visibility of the current website SSL certificate.
1195 if (DomainsActivity.sslIssuedToCName == null) { // There is no current SSL certificate.
1196 // Hide the SSL certificate.
1197 currentSslCardView.setVisibility(View.GONE);
1199 // Show the instruction.
1200 noCurrentWebsiteCertificateTextView.setVisibility(View.VISIBLE);
1201 } else { // There is a current SSL certificate.
1202 // Show the SSL certificate.
1203 currentSslCardView.setVisibility(View.VISIBLE);
1205 // Hide the instruction.
1206 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
1209 // Set the status of the radio buttons and the card view backgrounds.
1210 if (savedSslCardView.getVisibility() == View.VISIBLE) { // The saved SSL certificate is displayed.
1211 // Check the saved SSL certificate radio button.
1212 savedSslCertificateRadioButton.setChecked(true);
1214 // Uncheck the current website SSL certificate radio button.
1215 currentWebsiteCertificateRadioButton.setChecked(false);
1217 // Darken the background of the current website SSL certificate linear layout according to the theme.
1218 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1219 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
1221 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
1223 } else if (currentSslCardView.getVisibility() == View.VISIBLE) { // The saved SSL certificate is hidden but the current website SSL certificate is visible.
1224 // Check the current website SSL certificate radio button.
1225 currentWebsiteCertificateRadioButton.setChecked(true);
1227 // Uncheck the saved SSL certificate radio button.
1228 savedSslCertificateRadioButton.setChecked(false);
1229 } else { // Neither SSL certificate is visible.
1230 // Uncheck both radio buttons.
1231 savedSslCertificateRadioButton.setChecked(false);
1232 currentWebsiteCertificateRadioButton.setChecked(false);
1234 } else { // An SSL certificate is not pinned.
1235 // Hide the SSl certificates and instructions.
1236 savedSslCardView.setVisibility(View.GONE);
1237 currentSslCardView.setVisibility(View.GONE);
1238 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
1240 // Uncheck the radio buttons.
1241 savedSslCertificateRadioButton.setChecked(false);
1242 currentWebsiteCertificateRadioButton.setChecked(false);
1245 // Set the pinned IP addresses icon.
1246 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.
1247 // Check the switch.
1248 pinnedIpAddressesSwitch.setChecked(true);
1250 // Set the icon according to the theme.
1251 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1252 pinnedIpAddressesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ssl_certificate_enabled_night, null));
1254 pinnedIpAddressesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ssl_certificate_enabled_day, null));
1256 } else { // Pinned IP Addresses is disabled.
1257 // Uncheck the switch.
1258 pinnedIpAddressesSwitch.setChecked(false);
1260 // Set the icon according to the theme.
1261 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1262 pinnedIpAddressesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ssl_certificate_disabled_night, null));
1264 pinnedIpAddressesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ssl_certificate_disabled_day, null));
1268 // Populate the saved and current IP addresses.
1269 savedIpAddressesTextView.setText(savedIpAddresses);
1270 currentIpAddressesTextView.setText(DomainsActivity.currentIpAddresses);
1272 // Set the initial display status of the IP addresses card views.
1273 if (pinnedIpAddressesSwitch.isChecked()) { // IP addresses are pinned.
1274 // Set the visibility of the saved IP addresses.
1275 if (savedIpAddresses == null) { // There are no saved IP addresses.
1276 savedIpAddressesCardView.setVisibility(View.GONE);
1277 } else { // There are saved IP addresses.
1278 savedIpAddressesCardView.setVisibility(View.VISIBLE);
1281 // Set the visibility of the current IP addresses.
1282 currentIpAddressesCardView.setVisibility(View.VISIBLE);
1284 // Set the status of the radio buttons and the card view backgrounds.
1285 if (savedIpAddressesCardView.getVisibility() == View.VISIBLE) { // The saved IP addresses are displayed.
1286 // Check the saved IP addresses radio button.
1287 savedIpAddressesRadioButton.setChecked(true);
1289 // Uncheck the current IP addresses radio button.
1290 currentIpAddressesRadioButton.setChecked(false);
1292 // Darken the background of the current IP addresses linear layout according to the theme.
1293 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1294 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
1296 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
1298 } else { // The saved IP addresses are hidden.
1299 // Check the current IP addresses radio button.
1300 currentIpAddressesRadioButton.setChecked(true);
1302 // Uncheck the saved IP addresses radio button.
1303 savedIpAddressesRadioButton.setChecked(false);
1305 } else { // IP addresses are not pinned.
1306 // Hide the IP addresses card views.
1307 savedIpAddressesCardView.setVisibility(View.GONE);
1308 currentIpAddressesCardView.setVisibility(View.GONE);
1310 // Uncheck the radio buttons.
1311 savedIpAddressesRadioButton.setChecked(false);
1312 currentIpAddressesRadioButton.setChecked(false);
1316 // Set the JavaScript switch listener.
1317 javaScriptSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1318 if (isChecked) { // JavaScript is enabled.
1319 // Update the JavaScript icon.
1320 javaScriptImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.javascript_enabled, null));
1322 // Enable the DOM storage `Switch`.
1323 domStorageSwitch.setEnabled(true);
1325 // Update the DOM storage icon.
1326 if (domStorageSwitch.isChecked()) { // DOM storage is enabled.
1327 domStorageImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.dom_storage_enabled, null));
1328 } else { // DOM storage is disabled.
1329 // Set the icon according to the theme.
1330 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1331 domStorageImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.dom_storage_disabled_night, null));
1333 domStorageImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.dom_storage_disabled_day, null));
1336 } else { // JavaScript is disabled.
1337 // Update the JavaScript icon.
1338 javaScriptImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.privacy_mode, null));
1340 // Disable the DOM storage `Switch`.
1341 domStorageSwitch.setEnabled(false);
1343 // Set the DOM storage icon according to the theme.
1344 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1345 domStorageImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.dom_storage_ghosted_night, null));
1347 domStorageImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.dom_storage_ghosted_day, null));
1352 // Set the cookies switch listener.
1353 cookiesSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1354 if (isChecked) { // Cookies are enabled.
1355 // Update the cookies icon.
1356 cookiesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.cookies_enabled, null));
1357 } else { // Cookies are disabled.
1358 // Update the cookies icon according to the theme.
1359 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1360 cookiesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.cookies_disabled_day, null));
1362 cookiesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.cookies_disabled_night, null));
1367 // Set the DOM Storage switch listener.
1368 domStorageSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1371 domStorageImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.dom_storage_enabled, null));
1373 // Set the icon according to the theme.
1374 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1375 domStorageImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.dom_storage_disabled_night, null));
1377 domStorageImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.dom_storage_disabled_day, null));
1382 // Set the form data switch listener. It can be removed once the minimum API >= 26.
1383 if (Build.VERSION.SDK_INT < 26) {
1384 formDataSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1387 formDataImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.form_data_enabled, null));
1389 // Set the icon according to the theme.
1390 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1391 formDataImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.form_data_disabled_night, null));
1393 formDataImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.form_data_disabled_day, null));
1399 // Set the EasyList switch listener.
1400 easyListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1402 if (isChecked) { // EasyList is on.
1403 // Set the icon according to the theme.
1404 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1405 easyListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_ads_enabled_night, null));
1407 easyListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_ads_enabled_day, null));
1409 } else { // EasyList is off.
1410 // Set the icon according to the theme.
1411 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1412 easyListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_ads_disabled_night, null));
1414 easyListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_ads_disabled_day, null));
1419 // Set the EasyPrivacy switch listener.
1420 easyPrivacySwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1422 if (isChecked) { // EasyPrivacy is on.
1423 // Set the icon according to the theme.
1424 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1425 easyPrivacyImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_tracking_enabled_night, null));
1427 easyPrivacyImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_tracking_enabled_day, null));
1429 } else { // EasyPrivacy is off.
1430 // Set the icon according to the theme.
1431 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1432 easyPrivacyImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_tracking_disabled_night, null));
1434 easyPrivacyImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_tracking_disabled_day, null));
1439 // Set the Fanboy's Annoyance List switch listener.
1440 fanboysAnnoyanceListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1441 // Update the icon and Fanboy's Social Blocking List.
1442 if (isChecked) { // Fanboy's Annoyance List is on.
1443 // Set the icon according to the theme.
1444 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1445 fanboysAnnoyanceListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.social_media_enabled_night, null));
1447 fanboysAnnoyanceListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.social_media_enabled_day, null));
1450 // Disable the Fanboy's Social Blocking List switch.
1451 fanboysSocialBlockingListSwitch.setEnabled(false);
1453 // Update the Fanboy's Social Blocking List icon according to the theme.
1454 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1455 fanboysSocialBlockingListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.social_media_ghosted_night, null));
1457 fanboysSocialBlockingListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.social_media_ghosted_day, null));
1459 } else { // Fanboy's Annoyance List is off.
1460 // Set the icon according to the theme.
1461 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1462 fanboysAnnoyanceListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.social_media_disabled_night, null));
1464 fanboysAnnoyanceListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.social_media_disabled_day, null));
1467 // Enable the Fanboy's Social Blocking List switch.
1468 fanboysSocialBlockingListSwitch.setEnabled(true);
1470 // Update the Fanboy's Social Blocking List icon.
1471 if (fanboysSocialBlockingListSwitch.isChecked()) { // Fanboy's Social Blocking List is on.
1472 // Update the icon according to the theme.
1473 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1474 fanboysSocialBlockingListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.social_media_enabled_night, null));
1476 fanboysSocialBlockingListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.social_media_enabled_day, null));
1478 } else { // Fanboy's Social Blocking List is off.
1479 // Update the icon according to the theme.
1480 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1481 fanboysSocialBlockingListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.social_media_disabled_night, null));
1483 fanboysSocialBlockingListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.social_media_disabled_day, null));
1490 // Set the Fanboy's Social Blocking List switch listener.
1491 fanboysSocialBlockingListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1493 if (isChecked) { // Fanboy's Social Blocking List is on.
1494 // Set the icon according to the theme.
1495 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1496 fanboysSocialBlockingListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.social_media_enabled_night, null));
1498 fanboysSocialBlockingListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.social_media_enabled_day, null));
1500 } else { // Fanboy's Social Blocking List is off.
1501 // Set the icon according to the theme.
1502 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1503 fanboysSocialBlockingListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.social_media_disabled_night, null));
1505 fanboysSocialBlockingListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.social_media_disabled_day, null));
1510 // Set the UltraList switch listener.
1511 ultraListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1513 if (isChecked) { // UltraList is on.
1514 // Set the icon according to the theme.
1515 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1516 ultraListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_ads_enabled_night, null));
1518 ultraListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_ads_enabled_day, null));
1520 } else { // UltraList is off.
1521 // Set the icon according to the theme.
1522 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1523 ultraListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_ads_disabled_night, null));
1525 ultraListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_ads_disabled_day, null));
1530 // Set the UltraPrivacy switch listener.
1531 ultraPrivacySwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1533 if (isChecked) { // UltraPrivacy is on.
1534 // Set the icon according to the theme.
1535 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1536 ultraPrivacyImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_tracking_enabled_night, null));
1538 ultraPrivacyImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_tracking_enabled_day, null));
1540 } else { // UltraPrivacy is off.
1541 // Set the icon according to the theme.
1542 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1543 ultraPrivacyImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_tracking_disabled_night, null));
1545 ultraPrivacyImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_tracking_disabled_day, null));
1550 // Set the block all third-party requests switch listener.
1551 blockAllThirdPartyRequestsSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1553 if (isChecked) { // Blocking all third-party requests is on.
1554 // Set the icon according to the theme.
1555 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1556 blockAllThirdPartyRequestsImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_all_third_party_requests_enabled_night, null));
1558 blockAllThirdPartyRequestsImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_all_third_party_requests_enabled_day, null));
1560 } else { // Blocking all third-party requests is off.
1561 // Set the icon according to the theme.
1562 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1563 blockAllThirdPartyRequestsImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_all_third_party_requests_disabled_night, null));
1565 blockAllThirdPartyRequestsImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_all_third_party_requests_disabled_day, null));
1570 // Set the user agent spinner listener.
1571 userAgentSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1573 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1574 // Set the new user agent.
1576 case MainWebViewActivity.DOMAINS_SYSTEM_DEFAULT_USER_AGENT:
1577 // Show the user agent TextView.
1578 userAgentTextView.setVisibility(View.VISIBLE);
1580 // Hide the custom user agent EditText.
1581 customUserAgentEditText.setVisibility(View.GONE);
1583 // Set the user text.
1584 switch (defaultUserAgentArrayPosition) {
1585 case MainWebViewActivity.UNRECOGNIZED_USER_AGENT: // The default user agent name is not on the canonical list.
1586 // This is probably because it was set in an older version of Privacy Browser before the switch to persistent user agent names.
1587 userAgentTextView.setText(defaultUserAgentName);
1590 case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
1591 // Display the `WebView` default user agent.
1592 userAgentTextView.setText(webViewDefaultUserAgentString);
1595 case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
1596 // Display the custom user agent.
1597 userAgentTextView.setText(defaultCustomUserAgentString);
1601 // Get the user agent string from the user agent data array.
1602 userAgentTextView.setText(userAgentDataArray[defaultUserAgentArrayPosition]);
1606 case MainWebViewActivity.DOMAINS_WEBVIEW_DEFAULT_USER_AGENT:
1607 // Show the user agent TextView and set the text.
1608 userAgentTextView.setVisibility(View.VISIBLE);
1609 userAgentTextView.setText(webViewDefaultUserAgentString);
1611 // Hide the custom user agent EditTex.
1612 customUserAgentEditText.setVisibility(View.GONE);
1615 case MainWebViewActivity.DOMAINS_CUSTOM_USER_AGENT:
1616 // Hide the user agent TextView.
1617 userAgentTextView.setVisibility(View.GONE);
1619 // Show the custom user agent EditText and set the current user agent name as the text.
1620 customUserAgentEditText.setVisibility(View.VISIBLE);
1621 customUserAgentEditText.setText(currentUserAgentName);
1625 // 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.
1626 userAgentTextView.setVisibility(View.VISIBLE);
1627 userAgentTextView.setText(userAgentDataArray[position - 1]);
1629 // Hide `customUserAgentEditText`.
1630 customUserAgentEditText.setVisibility(View.GONE);
1635 public void onNothingSelected(AdapterView<?> parent) {
1640 // Set the font size spinner listener.
1641 fontSizeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1643 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1644 // Update the font size display options.
1645 if (position == 0) { // The system default font size has been selected.
1646 // Show the default font size text view.
1647 defaultFontSizeTextView.setVisibility(View.VISIBLE);
1649 // Hide the custom font size edit text.
1650 customFontSizeEditText.setVisibility(View.GONE);
1651 } else { // A custom font size has been selected.
1652 // Hide the default font size text view.
1653 defaultFontSizeTextView.setVisibility(View.GONE);
1655 // Show the custom font size edit text.
1656 customFontSizeEditText.setVisibility(View.VISIBLE);
1661 public void onNothingSelected(AdapterView<?> parent) {
1666 // Set the swipe to refresh spinner listener.
1667 swipeToRefreshSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1669 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1670 // 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.
1672 case DomainsDatabaseHelper.SYSTEM_DEFAULT:
1673 if (defaultSwipeToRefresh) { // Swipe to refresh enabled by default.
1674 // Set the icon according to the theme.
1675 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1676 swipeToRefreshImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.refresh_enabled_night, null));
1678 swipeToRefreshImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.refresh_enabled_day, null));
1680 } else { // Swipe to refresh disabled by default.
1681 // Set the icon according to the theme.
1682 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1683 swipeToRefreshImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.refresh_disabled_night, null));
1685 swipeToRefreshImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.refresh_disabled_day, null));
1689 // Show the swipe to refresh TextView.
1690 swipeToRefreshTextView.setVisibility(View.VISIBLE);
1693 case DomainsDatabaseHelper.ENABLED:
1694 // Set the icon according to the theme.
1695 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1696 swipeToRefreshImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.refresh_enabled_night, null));
1698 swipeToRefreshImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.refresh_enabled_day, null));
1701 // Hide the swipe to refresh TextView.
1702 swipeToRefreshTextView.setVisibility(View.GONE);
1705 case DomainsDatabaseHelper.DISABLED:
1706 // Set the icon according to the theme.
1707 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1708 swipeToRefreshImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.refresh_disabled_night, null));
1710 swipeToRefreshImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.refresh_disabled_day, null));
1713 // Hide the swipe to refresh TextView.
1714 swipeToRefreshTextView.setVisibility(View.GONE);
1719 public void onNothingSelected(AdapterView<?> parent) {
1724 // Set the WebView theme spinner listener.
1725 webViewThemeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1727 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1728 // 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.
1730 case DomainsDatabaseHelper.SYSTEM_DEFAULT: // the domain WebView theme is system default.
1731 // Set the icon according to the app WebView theme.
1732 switch (appWebViewThemeEntryNumber) {
1733 case DomainsDatabaseHelper.SYSTEM_DEFAULT: // The default WebView theme is system default.
1734 // Set the icon according to the app theme.
1735 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1736 // Set the light mode icon.
1737 webViewThemeImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.webview_light_theme_day, null));
1739 // Set the dark theme icon.
1740 webViewThemeImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.webview_dark_theme_night, null));
1744 case DomainsDatabaseHelper.LIGHT_THEME: // The default WebView theme is light.
1745 // Set the icon according to the app theme.
1746 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1747 webViewThemeImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.webview_light_theme_day, null));
1749 webViewThemeImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.webview_light_theme_night, null));
1753 case DomainsDatabaseHelper.DARK_THEME: // The default WebView theme is dark.
1754 // Set the icon according to the app theme.
1755 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1756 webViewThemeImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.webview_dark_theme_day, null));
1758 webViewThemeImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.webview_dark_theme_night, null));
1763 // Show the WebView theme text view.
1764 webViewThemeTextView.setVisibility(View.VISIBLE);
1767 case DomainsDatabaseHelper.LIGHT_THEME: // The domain WebView theme is light.
1768 // Set the icon according to the app theme.
1769 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1770 webViewThemeImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.webview_light_theme_day, null));
1772 webViewThemeImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.webview_light_theme_night, null));
1775 // Hide the WebView theme text view.
1776 webViewThemeTextView.setVisibility(View.GONE);
1779 case DomainsDatabaseHelper.DARK_THEME: // The domain WebView theme is dark.
1780 // Set the icon according to the app theme.
1781 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1782 webViewThemeImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.webview_dark_theme_day, null));
1784 webViewThemeImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.webview_dark_theme_night, null));
1787 // Hide the WebView theme text view.
1788 webViewThemeTextView.setVisibility(View.GONE);
1794 public void onNothingSelected(AdapterView<?> parent) {
1799 // Set the wide viewport spinner listener.
1800 wideViewportSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1802 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1803 // Update the icon and the visibility of the wide viewport text view.
1805 case DomainsDatabaseHelper.SYSTEM_DEFAULT:
1806 if (defaultWideViewport) { // Wide viewport is enabled by default.
1807 // Set the icon according to the theme.
1808 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1809 wideViewportImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.wide_viewport_enabled_night, null));
1811 wideViewportImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.wide_viewport_enabled_day, null));
1813 } else { // Wide viewport is disabled by default.
1814 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1815 wideViewportImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.wide_viewport_disabled_night, null));
1817 wideViewportImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.wide_viewport_disabled_day, null));
1821 // Show the wide viewport text view.
1822 wideViewportTextView.setVisibility(View.VISIBLE);
1825 case DomainsDatabaseHelper.ENABLED:
1826 // Set the icon according to the theme.
1827 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1828 wideViewportImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.wide_viewport_enabled_night, null));
1830 wideViewportImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.wide_viewport_enabled_day, null));
1833 // Hide the wide viewport text view.
1834 wideViewportTextView.setVisibility(View.GONE);
1837 case DomainsDatabaseHelper.DISABLED:
1838 // Set the icon according to the theme.
1839 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1840 wideViewportImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.wide_viewport_disabled_night, null));
1842 wideViewportImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.wide_viewport_disabled_day, null));
1845 // Hid ethe wide viewport text view.
1846 wideViewportTextView.setVisibility(View.GONE);
1852 public void onNothingSelected(AdapterView<?> parent) {
1857 // Set the display webpage images spinner listener.
1858 displayWebpageImagesSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1860 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1861 // Update the icon and the visibility of the display images text view.
1863 case DomainsDatabaseHelper.SYSTEM_DEFAULT:
1864 if (defaultDisplayWebpageImages) { // Display webpage images is enabled by default.
1865 // Set the icon according to the theme.
1866 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1867 displayWebpageImagesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.images_enabled_night, null));
1869 displayWebpageImagesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.images_enabled_day, null));
1871 } else { // Display webpage images is disabled by default.
1872 // Set the icon according to the theme.
1873 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1874 displayWebpageImagesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.images_disabled_night, null));
1876 displayWebpageImagesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.images_disabled_day, null));
1880 // Show the display images text view.
1881 displayImagesTextView.setVisibility(View.VISIBLE);
1884 case DomainsDatabaseHelper.ENABLED:
1885 // Set the icon according to the theme.
1886 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1887 displayWebpageImagesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.images_enabled_night, null));
1889 displayWebpageImagesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.images_enabled_day, null));
1892 // Hide the display images text view.
1893 displayImagesTextView.setVisibility(View.GONE);
1896 case DomainsDatabaseHelper.DISABLED:
1897 // Set the icon according to the theme.
1898 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1899 displayWebpageImagesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.images_disabled_night, null));
1901 displayWebpageImagesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.images_disabled_day, null));
1904 // Hide the display images text view.
1905 displayImagesTextView.setVisibility(View.GONE);
1911 public void onNothingSelected(AdapterView<?> parent) {
1916 // Set the pinned SSL certificate switch listener.
1917 pinnedSslCertificateSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1919 if (isChecked) { // SSL certificate pinning is enabled.
1920 // Set the icon according to the theme.
1921 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1922 pinnedSslCertificateImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ssl_certificate_enabled_night, null));
1924 pinnedSslCertificateImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ssl_certificate_enabled_day, null));
1927 // Update the visibility of the saved SSL certificate.
1928 if (savedSslIssuedToCNameString == null) {
1929 savedSslCardView.setVisibility(View.GONE);
1931 savedSslCardView.setVisibility(View.VISIBLE);
1934 // Update the visibility of the current website SSL certificate.
1935 if (DomainsActivity.sslIssuedToCName == null) {
1936 // Hide the SSL certificate.
1937 currentSslCardView.setVisibility(View.GONE);
1939 // Show the instruction.
1940 noCurrentWebsiteCertificateTextView.setVisibility(View.VISIBLE);
1942 // Show the SSL certificate.
1943 currentSslCardView.setVisibility(View.VISIBLE);
1945 // Hide the instruction.
1946 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
1949 // Set the status of the radio buttons.
1950 if (savedSslCardView.getVisibility() == View.VISIBLE) { // The saved SSL certificate is displayed.
1951 // Check the saved SSL certificate radio button.
1952 savedSslCertificateRadioButton.setChecked(true);
1954 // Uncheck the current website SSL certificate radio button.
1955 currentWebsiteCertificateRadioButton.setChecked(false);
1957 // Set the background of the saved SSL certificate linear layout to be transparent.
1958 savedSslCertificateLinearLayout.setBackgroundResource(R.color.transparent);
1960 // Darken the background of the current website SSL certificate linear layout according to the theme.
1961 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1962 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
1964 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
1967 // Scroll to the current website SSL certificate card.
1968 savedSslCardView.getParent().requestChildFocus(savedSslCardView, savedSslCardView);
1969 } else if (currentSslCardView.getVisibility() == View.VISIBLE) { // The saved SSL certificate is hidden but the current website SSL certificate is visible.
1970 // Check the current website SSL certificate radio button.
1971 currentWebsiteCertificateRadioButton.setChecked(true);
1973 // Uncheck the saved SSL certificate radio button.
1974 savedSslCertificateRadioButton.setChecked(false);
1976 // Set the background of the current website SSL certificate linear layout to be transparent.
1977 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.transparent);
1979 // Darken the background of the saved SSL certificate linear layout according to the theme.
1980 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1981 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
1983 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
1986 // Scroll to the current website SSL certificate card.
1987 currentSslCardView.getParent().requestChildFocus(currentSslCardView, currentSslCardView);
1988 } else { // Neither SSL certificate is visible.
1989 // Uncheck both radio buttons.
1990 savedSslCertificateRadioButton.setChecked(false);
1991 currentWebsiteCertificateRadioButton.setChecked(false);
1993 // Scroll to the current website SSL certificate card.
1994 noCurrentWebsiteCertificateTextView.getParent().requestChildFocus(noCurrentWebsiteCertificateTextView, noCurrentWebsiteCertificateTextView);
1996 } else { // SSL certificate pinning is disabled.
1997 // Set the icon according to the theme.
1998 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1999 pinnedSslCertificateImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ssl_certificate_disabled_night, null));
2001 pinnedSslCertificateImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ssl_certificate_disabled_day, null));
2004 // Hide the SSl certificates and instructions.
2005 savedSslCardView.setVisibility(View.GONE);
2006 currentSslCardView.setVisibility(View.GONE);
2007 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
2009 // Uncheck the radio buttons.
2010 savedSslCertificateRadioButton.setChecked(false);
2011 currentWebsiteCertificateRadioButton.setChecked(false);
2015 savedSslCardView.setOnClickListener((View view) -> {
2016 // Check the saved SSL certificate radio button.
2017 savedSslCertificateRadioButton.setChecked(true);
2019 // Uncheck the current website SSL certificate radio button.
2020 currentWebsiteCertificateRadioButton.setChecked(false);
2022 // Set the background of the saved SSL certificate linear layout to be transparent.
2023 savedSslCertificateLinearLayout.setBackgroundResource(R.color.transparent);
2025 // Darken the background of the current website SSL certificate linear layout according to the theme.
2026 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2027 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2029 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2033 savedSslCertificateRadioButton.setOnClickListener((View view) -> {
2034 // Check the saved SSL certificate radio button.
2035 savedSslCertificateRadioButton.setChecked(true);
2037 // Uncheck the current website SSL certificate radio button.
2038 currentWebsiteCertificateRadioButton.setChecked(false);
2040 // Set the background of the saved SSL certificate linear layout to be transparent.
2041 savedSslCertificateLinearLayout.setBackgroundResource(R.color.transparent);
2043 // Darken the background of the current website SSL certificate linear layout according to the theme.
2044 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2045 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2047 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2051 currentSslCardView.setOnClickListener((View view) -> {
2052 // Check the current website SSL certificate radio button.
2053 currentWebsiteCertificateRadioButton.setChecked(true);
2055 // Uncheck the saved SSL certificate radio button.
2056 savedSslCertificateRadioButton.setChecked(false);
2058 // Set the background of the current website SSL certificate linear layout to be transparent.
2059 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.transparent);
2061 // Darken the background of the saved SSL certificate linear layout according to the theme.
2062 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2063 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2065 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2069 currentWebsiteCertificateRadioButton.setOnClickListener((View view) -> {
2070 // Check the current website SSL certificate radio button.
2071 currentWebsiteCertificateRadioButton.setChecked(true);
2073 // Uncheck the saved SSL certificate radio button.
2074 savedSslCertificateRadioButton.setChecked(false);
2076 // Set the background of the current website SSL certificate linear layout to be transparent.
2077 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.transparent);
2079 // Darken the background of the saved SSL certificate linear layout according to the theme.
2080 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2081 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2083 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2087 // Set the pinned IP addresses switch listener.
2088 pinnedIpAddressesSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
2090 if (isChecked) { // IP addresses pinning is enabled.
2091 // Set the icon according to the theme.
2092 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2093 pinnedIpAddressesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ssl_certificate_enabled_night, null));
2095 pinnedIpAddressesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ssl_certificate_enabled_day, null));
2098 // Update the visibility of the saved IP addresses card view.
2099 if (savedIpAddresses == null) { // There are no saved IP addresses.
2100 savedIpAddressesCardView.setVisibility(View.GONE);
2101 } else { // There are saved IP addresses.
2102 savedIpAddressesCardView.setVisibility(View.VISIBLE);
2105 // Show the current IP addresses card view.
2106 currentIpAddressesCardView.setVisibility(View.VISIBLE);
2108 // Set the status of the radio buttons.
2109 if (savedIpAddressesCardView.getVisibility() == View.VISIBLE) { // The saved IP addresses are visible.
2110 // Check the saved IP addresses radio button.
2111 savedIpAddressesRadioButton.setChecked(true);
2113 // Uncheck the current IP addresses radio button.
2114 currentIpAddressesRadioButton.setChecked(false);
2116 // Set the background of the saved IP addresses linear layout to be transparent.
2117 savedSslCertificateLinearLayout.setBackgroundResource(R.color.transparent);
2119 // Darken the background of the current IP addresses linear layout according to the theme.
2120 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2121 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2123 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2125 } else { // The saved IP addresses are not visible.
2126 // Check the current IP addresses radio button.
2127 currentIpAddressesRadioButton.setChecked(true);
2129 // Uncheck the saved IP addresses radio button.
2130 savedIpAddressesRadioButton.setChecked(false);
2132 // Set the background of the current IP addresses linear layout to be transparent.
2133 currentIpAddressesLinearLayout.setBackgroundResource(R.color.transparent);
2135 // Darken the background of the saved IP addresses linear layout according to the theme.
2136 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2137 savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2139 savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2143 // Scroll to the bottom of the card views.
2144 currentIpAddressesCardView.getParent().requestChildFocus(currentIpAddressesCardView, currentIpAddressesCardView);
2145 } else { // IP addresses pinning is disabled.
2146 // Set the icon according to the theme.
2147 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2148 pinnedIpAddressesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ssl_certificate_disabled_night, null));
2150 pinnedIpAddressesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ssl_certificate_disabled_day, null));
2153 // Hide the IP addresses card views.
2154 savedIpAddressesCardView.setVisibility(View.GONE);
2155 currentIpAddressesCardView.setVisibility(View.GONE);
2157 // Uncheck the radio buttons.
2158 savedIpAddressesRadioButton.setChecked(false);
2159 currentIpAddressesRadioButton.setChecked(false);
2163 savedIpAddressesCardView.setOnClickListener((View view) -> {
2164 // Check the saved IP addresses radio button.
2165 savedIpAddressesRadioButton.setChecked(true);
2167 // Uncheck the current website IP addresses radio button.
2168 currentIpAddressesRadioButton.setChecked(false);
2170 // Set the background of the saved IP addresses linear layout to be transparent.
2171 savedIpAddressesLinearLayout.setBackgroundResource(R.color.transparent);
2173 // Darken the background of the current IP addresses linear layout according to the theme.
2174 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2175 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2177 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2181 savedIpAddressesRadioButton.setOnClickListener((View view) -> {
2182 // Check the saved IP addresses radio button.
2183 savedIpAddressesRadioButton.setChecked(true);
2185 // Uncheck the current website IP addresses radio button.
2186 currentIpAddressesRadioButton.setChecked(false);
2188 // Set the background of the saved IP addresses linear layout to be transparent.
2189 savedIpAddressesLinearLayout.setBackgroundResource(R.color.transparent);
2191 // Darken the background of the current IP addresses linear layout according to the theme.
2192 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2193 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2195 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2199 currentIpAddressesCardView.setOnClickListener((View view) -> {
2200 // Check the current IP addresses radio button.
2201 currentIpAddressesRadioButton.setChecked(true);
2203 // Uncheck the saved IP addresses radio button.
2204 savedIpAddressesRadioButton.setChecked(false);
2206 // Set the background of the current IP addresses linear layout to be transparent.
2207 currentIpAddressesLinearLayout.setBackgroundResource(R.color.transparent);
2209 // Darken the background of the saved IP addresses linear layout according to the theme.
2210 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2211 savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2213 savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2217 currentIpAddressesRadioButton.setOnClickListener((View view) -> {
2218 // Check the current IP addresses radio button.
2219 currentIpAddressesRadioButton.setChecked(true);
2221 // Uncheck the saved IP addresses radio button.
2222 savedIpAddressesRadioButton.setChecked(false);
2224 // Set the background of the current IP addresses linear layout to be transparent.
2225 currentIpAddressesLinearLayout.setBackgroundResource(R.color.transparent);
2227 // Darken the background of the saved IP addresses linear layout according to the theme.
2228 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2229 savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2231 savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2235 // Set the scroll Y.
2236 domainSettingsScrollView.post(() -> domainSettingsScrollView.setScrollY(scrollY));
2238 // Return the domain settings view.
2239 return domainSettingsView;
2242 private boolean checkDomainNameAgainstCertificate(String domainName, String certificateCommonName) {
2243 // Initialize `domainNamesMatch`.
2244 boolean domainNamesMatch = false;
2246 // Check various wildcard permutations if `domainName` and `certificateCommonName` are not empty.
2247 // `noinspection ConstantCondition` removes Android Studio's incorrect lint warning that `domainName` can never be `null`.
2248 if ((domainName != null) && (certificateCommonName != null)) {
2249 // Check if the domains match.
2250 if (domainName.equals(certificateCommonName)) {
2251 domainNamesMatch = true;
2254 // If `domainName` starts with a wildcard, check the base domain against all the subdomains of `certificateCommonName`.
2255 if (!domainNamesMatch && domainName.startsWith("*.") && (domainName.length() > 2)) {
2256 // Remove the initial `*.`.
2257 String baseDomainName = domainName.substring(2);
2259 // Setup a copy of `certificateCommonName` to test subdomains.
2260 String certificateCommonNameSubdomain = certificateCommonName;
2262 // Check all the subdomains in `certificateCommonNameSubdomain` against `baseDomainName`.
2263 while (!domainNamesMatch && certificateCommonNameSubdomain.contains(".")) { // Stop checking if we know that `domainNamesMatch` is `true` or if we run out of `.`.
2264 // Test the `certificateCommonNameSubdomain` against `baseDomainName`.
2265 if (certificateCommonNameSubdomain.equals(baseDomainName)) {
2266 domainNamesMatch = true;
2269 // Strip out the lowest subdomain of `certificateCommonNameSubdomain`.
2271 certificateCommonNameSubdomain = certificateCommonNameSubdomain.substring(certificateCommonNameSubdomain.indexOf(".") + 1);
2272 } catch (IndexOutOfBoundsException e) { // `certificateCommonNameSubdomain` ends with `.`.
2273 certificateCommonNameSubdomain = "";
2278 // If `certificateCommonName` starts with a wildcard, check the base common name against all the subdomains of `domainName`.
2279 if (!domainNamesMatch && certificateCommonName.startsWith("*.") && (certificateCommonName.length() > 2)) {
2280 // Remove the initial `*.`.
2281 String baseCertificateCommonName = certificateCommonName.substring(2);
2283 // Setup a copy of `domainName` to test subdomains.
2284 String domainNameSubdomain = domainName;
2286 // Check all the subdomains in `domainNameSubdomain` against `baseCertificateCommonName`.
2287 while (!domainNamesMatch && domainNameSubdomain.contains(".") && (domainNameSubdomain.length() > 2)) {
2288 // Test the `domainNameSubdomain` against `baseCertificateCommonName`.
2289 if (domainNameSubdomain.equals(baseCertificateCommonName)) {
2290 domainNamesMatch = true;
2293 // Strip out the lowest subdomain of `domainNameSubdomain`.
2295 domainNameSubdomain = domainNameSubdomain.substring(domainNameSubdomain.indexOf(".") + 1);
2296 } catch (IndexOutOfBoundsException e) { // `domainNameSubdomain` ends with `.`.
2297 domainNameSubdomain = "";
2302 // If both names start with a wildcard, check if the root of one contains the root of the other.
2303 if (!domainNamesMatch && domainName.startsWith("*.") && (domainName.length() > 2) && certificateCommonName.startsWith("*.") && (certificateCommonName.length() > 2)) {
2304 // Remove the wildcards.
2305 String rootDomainName = domainName.substring(2);
2306 String rootCertificateCommonName = certificateCommonName.substring(2);
2308 // Check if one name ends with the contents of the other. If so, there will be overlap in the their wildcard subdomains.
2309 if (rootDomainName.endsWith(rootCertificateCommonName) || rootCertificateCommonName.endsWith(rootDomainName)) {
2310 domainNamesMatch = true;
2315 return domainNamesMatch;