2 * Copyright © 2017-2022 Soren Stoutner <soren@stoutner.com>.
4 * This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
6 * Privacy Browser Android 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 Android 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 Android. 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.getColumnIndexOrThrow(DomainsDatabaseHelper.DOMAIN_NAME));
213 int javaScriptInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_JAVASCRIPT));
214 int cookiesInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.COOKIES));
215 int domStorageInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_DOM_STORAGE));
216 int formDataInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_FORM_DATA)); // Form data can be remove once the minimum API >= 26.
217 int easyListInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_EASYLIST));
218 int easyPrivacyInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_EASYPRIVACY));
219 int fanboysAnnoyanceListInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST));
220 int fanboysSocialBlockingListInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST));
221 int ultraListInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ULTRALIST));
222 int ultraPrivacyInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY));
223 int blockAllThirdPartyRequestsInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS));
224 String currentUserAgentName = domainCursor.getString(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.USER_AGENT));
225 int fontSizeInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.FONT_SIZE));
226 int swipeToRefreshInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SWIPE_TO_REFRESH));
227 int webViewThemeInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.WEBVIEW_THEME));
228 int wideViewportInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.WIDE_VIEWPORT));
229 int displayImagesInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.DISPLAY_IMAGES));
230 int pinnedSslCertificateInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.PINNED_SSL_CERTIFICATE));
231 String savedSslIssuedToCNameString = domainCursor.getString(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_TO_COMMON_NAME));
232 String savedSslIssuedToONameString = domainCursor.getString(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATION));
233 String savedSslIssuedToUNameString = domainCursor.getString(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATIONAL_UNIT));
234 String savedSslIssuedByCNameString = domainCursor.getString(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_BY_COMMON_NAME));
235 String savedSslIssuedByONameString = domainCursor.getString(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATION));
236 String savedSslIssuedByUNameString = domainCursor.getString(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATIONAL_UNIT));
237 int pinnedIpAddressesInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.PINNED_IP_ADDRESSES));
238 String savedIpAddresses = domainCursor.getString(domainCursor.getColumnIndexOrThrow(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.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_START_DATE)) != 0) {
246 savedSslStartDate = new Date(domainCursor.getLong(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_START_DATE)));
249 if (domainCursor.getLong(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_END_DATE)) != 0) {
250 savedSslEndDate = new Date(domainCursor.getLong(domainCursor.getColumnIndexOrThrow(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.
307 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
308 blueColorSpan = new ForegroundColorSpan(context.getColor(R.color.blue_700));
309 redColorSpan = new ForegroundColorSpan(context.getColor(R.color.red_a700));
311 blueColorSpan = new ForegroundColorSpan(context.getColor(R.color.violet_700));
312 redColorSpan = new ForegroundColorSpan(context.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 // Select the WebView theme in the spinner.
838 webViewThemeSpinner.setSelection(webViewThemeInt);
840 // Set the WebView theme text.
841 if (appWebViewThemeEntryNumber == DomainsDatabaseHelper.SYSTEM_DEFAULT) { // The app WebView theme is system default.
842 // Set the text according to the current UI theme.
843 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
844 webViewThemeTextView.setText(webViewThemeStringArray[DomainsDatabaseHelper.LIGHT_THEME]);
846 webViewThemeTextView.setText(webViewThemeStringArray[DomainsDatabaseHelper.DARK_THEME]);
848 } else { // The app WebView theme is not system default.
849 // Set the text according to the app WebView theme.
850 webViewThemeTextView.setText(webViewThemeStringArray[appWebViewThemeEntryNumber]);
853 // 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.
854 switch (webViewThemeInt) {
855 case DomainsDatabaseHelper.SYSTEM_DEFAULT: // The domain WebView theme is system default.
856 // Set the icon according to the app WebView theme.
857 switch (appWebViewThemeEntryNumber) {
858 case DomainsDatabaseHelper.SYSTEM_DEFAULT: // The default WebView theme is system default.
859 // Set the icon according to the app theme.
860 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
861 // Set the light mode icon.
862 webViewThemeImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.webview_light_theme_day, null));
864 // Set the dark theme icon.
865 webViewThemeImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.webview_dark_theme_night, null));
869 case DomainsDatabaseHelper.LIGHT_THEME: // the default WebView theme is light.
870 // Set the icon according to the app theme.
871 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
872 webViewThemeImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.webview_light_theme_day, null));
874 webViewThemeImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.webview_light_theme_night, null));
878 case DomainsDatabaseHelper.DARK_THEME: // the default WebView theme is dark.
879 // Set the icon according to the app theme.
880 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
881 webViewThemeImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.webview_dark_theme_day, null));
883 webViewThemeImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.webview_dark_theme_night, null)); }
887 // Show the WebView theme text view.
888 webViewThemeTextView.setVisibility(View.VISIBLE);
891 case DomainsDatabaseHelper.LIGHT_THEME: // The domain WebView theme is light.
892 // Set the icon according to the app theme.
893 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
894 webViewThemeImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.webview_light_theme_day, null));
896 webViewThemeImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.webview_light_theme_night, null));
899 // Hide the WebView theme text view.
900 webViewThemeTextView.setVisibility(View.GONE);
903 case DomainsDatabaseHelper.DARK_THEME: // The domain WebView theme is dark.
904 // Set the icon according to the app theme.
905 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
906 webViewThemeImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.webview_dark_theme_day, null));
908 webViewThemeImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.webview_dark_theme_night, null));
911 // Hide the WebView theme text view.
912 webViewThemeTextView.setVisibility(View.GONE);
916 // Open the WebView theme spinner when the text view is clicked.
917 webViewThemeTextView.setOnClickListener((View v) -> {
918 // Open the WebView theme spinner.
919 webViewThemeSpinner.performClick();
922 // Select the wide viewport in the spinner.
923 wideViewportSpinner.setSelection(wideViewportInt);
925 // Set the default wide viewport text.
926 if (defaultWideViewport) {
927 wideViewportTextView.setText(wideViewportArrayAdapter.getItem(DomainsDatabaseHelper.ENABLED));
929 wideViewportTextView.setText(wideViewportArrayAdapter.getItem(DomainsDatabaseHelper.DISABLED));
932 // 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.
933 switch (wideViewportInt) {
934 case DomainsDatabaseHelper.SYSTEM_DEFAULT:
935 if (defaultWideViewport) { // Wide viewport enabled by default.
936 // Set the icon according to the theme.
937 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
938 wideViewportImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.wide_viewport_enabled_night, null));
940 wideViewportImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.wide_viewport_enabled_day, null));
942 } else { // Wide viewport disabled by default.
943 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
944 wideViewportImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.wide_viewport_disabled_night, null));
946 wideViewportImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.wide_viewport_disabled_day, null));
950 // Show the wide viewport text view.
951 wideViewportTextView.setVisibility(View.VISIBLE);
954 case DomainsDatabaseHelper.ENABLED:
955 // Set the icon according to the theme.
956 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
957 wideViewportImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.wide_viewport_enabled_night, null));
959 wideViewportImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.wide_viewport_enabled_day, null));
962 // Hide the wide viewport text view.
963 wideViewportTextView.setVisibility(View.GONE);
966 case DomainsDatabaseHelper.DISABLED:
967 // Set the icon according to the theme.
968 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
969 wideViewportImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.wide_viewport_disabled_night, null));
971 wideViewportImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.wide_viewport_disabled_day, null));
974 // Hide the wide viewport text view.
975 wideViewportTextView.setVisibility(View.GONE);
979 // Open the wide viewport spinner when the text view is clicked.
980 wideViewportTextView.setOnClickListener((View view) -> {
981 // Open the wide viewport spinner.
982 wideViewportSpinner.performClick();
985 // Display the website images mode in the spinner.
986 displayWebpageImagesSpinner.setSelection(displayImagesInt);
988 // Set the default display images text.
989 if (defaultDisplayWebpageImages) {
990 displayImagesTextView.setText(displayImagesArrayAdapter.getItem(DomainsDatabaseHelper.ENABLED));
992 displayImagesTextView.setText(displayImagesArrayAdapter.getItem(DomainsDatabaseHelper.DISABLED));
995 // 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.
996 switch (displayImagesInt) {
997 case DomainsDatabaseHelper.SYSTEM_DEFAULT:
998 if (defaultDisplayWebpageImages) { // Display webpage images enabled by default.
999 // Set the icon according to the theme.
1000 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1001 displayWebpageImagesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.images_enabled_night, null));
1003 displayWebpageImagesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.images_enabled_day, null));
1005 } else { // Display webpage images disabled by default.
1006 // Set the icon according to the theme.
1007 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1008 displayWebpageImagesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.images_disabled_night, null));
1010 displayWebpageImagesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.images_disabled_day, null));
1014 // Show the display images text view.
1015 displayImagesTextView.setVisibility(View.VISIBLE);
1018 case DomainsDatabaseHelper.ENABLED:
1019 // Set the icon according to the theme.
1020 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1021 displayWebpageImagesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.images_enabled_night, null));
1023 displayWebpageImagesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.images_enabled_day, null));
1026 // Hide the display images text view.
1027 displayImagesTextView.setVisibility(View.GONE);
1030 case DomainsDatabaseHelper.DISABLED:
1031 // Set the icon according to the theme.
1032 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1033 displayWebpageImagesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.images_disabled_night, null));
1035 displayWebpageImagesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.images_disabled_day, null));
1038 // Hide the display images text view.
1039 displayImagesTextView.setVisibility(View.GONE);
1043 // Open the display images spinner when the text view is clicked.
1044 displayImagesTextView.setOnClickListener((View view) -> {
1045 // Open the user agent spinner.
1046 displayWebpageImagesSpinner.performClick();
1049 // Set the pinned SSL certificate icon.
1050 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.
1051 // Check the switch.
1052 pinnedSslCertificateSwitch.setChecked(true);
1054 // Set the icon according to the theme.
1055 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1056 pinnedSslCertificateImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ssl_certificate_enabled_night, null));
1058 pinnedSslCertificateImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ssl_certificate_enabled_day, null));
1060 } else { // Pinned SSL certificate is disabled.
1061 // Uncheck the switch.
1062 pinnedSslCertificateSwitch.setChecked(false);
1064 // Set the icon according to the theme.
1065 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1066 pinnedSslCertificateImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ssl_certificate_disabled_night, null));
1068 pinnedSslCertificateImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ssl_certificate_disabled_day, null));
1072 // Store the current date.
1073 Date currentDate = Calendar.getInstance().getTime();
1075 // Setup the string builders to display the general certificate information in blue. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1076 savedSslIssuedToONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), savedSslIssuedToONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1077 savedSslIssuedToUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), savedSslIssuedToUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1078 savedSslIssuedByCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), savedSslIssuedByCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1079 savedSslIssuedByONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), savedSslIssuedByONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1080 savedSslIssuedByUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), savedSslIssuedByUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1082 // Check the certificate Common Name against the domain name.
1083 boolean savedSslCommonNameMatchesDomainName = checkDomainNameAgainstCertificate(domainNameString, savedSslIssuedToCNameString);
1085 // Format the issued to Common Name color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1086 if (savedSslCommonNameMatchesDomainName) {
1087 savedSslIssuedToCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), savedSslIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1089 savedSslIssuedToCNameStringBuilder.setSpan(redColorSpan, cNameLabel.length(), savedSslIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1092 // Format the start date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1093 if ((savedSslStartDate != null) && savedSslStartDate.after(currentDate)) { // The certificate start date is in the future.
1094 savedSslStartDateStringBuilder.setSpan(redColorSpan, startDateLabel.length(), savedSslStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1095 } else { // The certificate start date is in the past.
1096 savedSslStartDateStringBuilder.setSpan(blueColorSpan, startDateLabel.length(), savedSslStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1099 // Format the end date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1100 if ((savedSslEndDate != null) && savedSslEndDate.before(currentDate)) { // The certificate end date is in the past.
1101 savedSslEndDateStringBuilder.setSpan(redColorSpan, endDateLabel.length(), savedSslEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1102 } else { // The certificate end date is in the future.
1103 savedSslEndDateStringBuilder.setSpan(blueColorSpan, endDateLabel.length(), savedSslEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1106 // Display the saved website SSL certificate strings.
1107 savedSslIssuedToCNameTextView.setText(savedSslIssuedToCNameStringBuilder);
1108 savedSslIssuedToONameTextView.setText(savedSslIssuedToONameStringBuilder);
1109 savedSslIssuedToUNameTextView.setText(savedSslIssuedToUNameStringBuilder);
1110 savedSslIssuedByCNameTextView.setText(savedSslIssuedByCNameStringBuilder);
1111 savedSslIssuedByONameTextView.setText(savedSslIssuedByONameStringBuilder);
1112 savedSslIssuedByUNameTextView.setText(savedSslIssuedByUNameStringBuilder);
1113 savedSslStartDateTextView.setText(savedSslStartDateStringBuilder);
1114 savedSslEndDateTextView.setText(savedSslEndDateStringBuilder);
1116 // Populate the current website SSL certificate if there is one.
1117 if (DomainsActivity.sslIssuedToCName != null) {
1118 // Get dates from the raw long values.
1119 Date currentSslStartDate = new Date(DomainsActivity.sslStartDateLong);
1120 Date currentSslEndDate = new Date(DomainsActivity.sslEndDateLong);
1122 // Create a spannable string builder for each text view that needs multiple colors of text.
1123 SpannableStringBuilder currentSslIssuedToCNameStringBuilder = new SpannableStringBuilder(cNameLabel + DomainsActivity.sslIssuedToCName);
1124 SpannableStringBuilder currentSslIssuedToONameStringBuilder = new SpannableStringBuilder(oNameLabel + DomainsActivity.sslIssuedToOName);
1125 SpannableStringBuilder currentSslIssuedToUNameStringBuilder = new SpannableStringBuilder(uNameLabel + DomainsActivity.sslIssuedToUName);
1126 SpannableStringBuilder currentSslIssuedByCNameStringBuilder = new SpannableStringBuilder(cNameLabel + DomainsActivity.sslIssuedByCName);
1127 SpannableStringBuilder currentSslIssuedByONameStringBuilder = new SpannableStringBuilder(oNameLabel + DomainsActivity.sslIssuedByOName);
1128 SpannableStringBuilder currentSslIssuedByUNameStringBuilder = new SpannableStringBuilder(uNameLabel + DomainsActivity.sslIssuedByUName);
1129 SpannableStringBuilder currentSslStartDateStringBuilder = new SpannableStringBuilder(startDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG)
1130 .format(currentSslStartDate));
1131 SpannableStringBuilder currentSslEndDateStringBuilder = new SpannableStringBuilder(endDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG)
1132 .format(currentSslEndDate));
1134 // Setup the string builders to display the general certificate information in blue. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1135 currentSslIssuedToONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), currentSslIssuedToONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1136 currentSslIssuedToUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), currentSslIssuedToUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1137 currentSslIssuedByCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), currentSslIssuedByCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1138 currentSslIssuedByONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), currentSslIssuedByONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1139 currentSslIssuedByUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), currentSslIssuedByUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1141 // Check the certificate Common Name against the domain name.
1142 boolean currentSslCommonNameMatchesDomainName = checkDomainNameAgainstCertificate(domainNameString, DomainsActivity.sslIssuedToCName);
1144 // Format the issued to Common Name color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1145 if (currentSslCommonNameMatchesDomainName) {
1146 currentSslIssuedToCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), currentSslIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1148 currentSslIssuedToCNameStringBuilder.setSpan(redColorSpan, cNameLabel.length(), currentSslIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1151 // Format the start date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1152 if (currentSslStartDate.after(currentDate)) { // The certificate start date is in the future.
1153 currentSslStartDateStringBuilder.setSpan(redColorSpan, startDateLabel.length(), currentSslStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1154 } else { // The certificate start date is in the past.
1155 currentSslStartDateStringBuilder.setSpan(blueColorSpan, startDateLabel.length(), currentSslStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1158 // Format the end date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1159 if (currentSslEndDate.before(currentDate)) { // The certificate end date is in the past.
1160 currentSslEndDateStringBuilder.setSpan(redColorSpan, endDateLabel.length(), currentSslEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1161 } else { // The certificate end date is in the future.
1162 currentSslEndDateStringBuilder.setSpan(blueColorSpan, endDateLabel.length(), currentSslEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1165 // Display the current website SSL certificate strings.
1166 currentSslIssuedToCNameTextView.setText(currentSslIssuedToCNameStringBuilder);
1167 currentSslIssuedToONameTextView.setText(currentSslIssuedToONameStringBuilder);
1168 currentSslIssuedToUNameTextView.setText(currentSslIssuedToUNameStringBuilder);
1169 currentSslIssuedByCNameTextView.setText(currentSslIssuedByCNameStringBuilder);
1170 currentSslIssuedByONameTextView.setText(currentSslIssuedByONameStringBuilder);
1171 currentSslIssuedByUNameTextView.setText(currentSslIssuedByUNameStringBuilder);
1172 currentSslStartDateTextView.setText(currentSslStartDateStringBuilder);
1173 currentSslEndDateTextView.setText(currentSslEndDateStringBuilder);
1176 // Set the initial display status of the SSL certificates card views.
1177 if (pinnedSslCertificateSwitch.isChecked()) { // An SSL certificate is pinned.
1178 // Set the visibility of the saved SSL certificate.
1179 if (savedSslIssuedToCNameString == null) {
1180 savedSslCardView.setVisibility(View.GONE);
1182 savedSslCardView.setVisibility(View.VISIBLE);
1185 // Set the visibility of the current website SSL certificate.
1186 if (DomainsActivity.sslIssuedToCName == null) { // There is no current SSL certificate.
1187 // Hide the SSL certificate.
1188 currentSslCardView.setVisibility(View.GONE);
1190 // Show the instruction.
1191 noCurrentWebsiteCertificateTextView.setVisibility(View.VISIBLE);
1192 } else { // There is a current SSL certificate.
1193 // Show the SSL certificate.
1194 currentSslCardView.setVisibility(View.VISIBLE);
1196 // Hide the instruction.
1197 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
1200 // Set the status of the radio buttons and the card view backgrounds.
1201 if (savedSslCardView.getVisibility() == View.VISIBLE) { // The saved SSL certificate is displayed.
1202 // Check the saved SSL certificate radio button.
1203 savedSslCertificateRadioButton.setChecked(true);
1205 // Uncheck the current website SSL certificate radio button.
1206 currentWebsiteCertificateRadioButton.setChecked(false);
1208 // Darken the background of the current website SSL certificate linear layout according to the theme.
1209 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1210 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
1212 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
1214 } else if (currentSslCardView.getVisibility() == View.VISIBLE) { // The saved SSL certificate is hidden but the current website SSL certificate is visible.
1215 // Check the current website SSL certificate radio button.
1216 currentWebsiteCertificateRadioButton.setChecked(true);
1218 // Uncheck the saved SSL certificate radio button.
1219 savedSslCertificateRadioButton.setChecked(false);
1220 } else { // Neither SSL certificate is visible.
1221 // Uncheck both radio buttons.
1222 savedSslCertificateRadioButton.setChecked(false);
1223 currentWebsiteCertificateRadioButton.setChecked(false);
1225 } else { // An SSL certificate is not pinned.
1226 // Hide the SSl certificates and instructions.
1227 savedSslCardView.setVisibility(View.GONE);
1228 currentSslCardView.setVisibility(View.GONE);
1229 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
1231 // Uncheck the radio buttons.
1232 savedSslCertificateRadioButton.setChecked(false);
1233 currentWebsiteCertificateRadioButton.setChecked(false);
1236 // Set the pinned IP addresses icon.
1237 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.
1238 // Check the switch.
1239 pinnedIpAddressesSwitch.setChecked(true);
1241 // Set the icon according to the theme.
1242 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1243 pinnedIpAddressesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ssl_certificate_enabled_night, null));
1245 pinnedIpAddressesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ssl_certificate_enabled_day, null));
1247 } else { // Pinned IP Addresses is disabled.
1248 // Uncheck the switch.
1249 pinnedIpAddressesSwitch.setChecked(false);
1251 // Set the icon according to the theme.
1252 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1253 pinnedIpAddressesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ssl_certificate_disabled_night, null));
1255 pinnedIpAddressesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ssl_certificate_disabled_day, null));
1259 // Populate the saved and current IP addresses.
1260 savedIpAddressesTextView.setText(savedIpAddresses);
1261 currentIpAddressesTextView.setText(DomainsActivity.currentIpAddresses);
1263 // Set the initial display status of the IP addresses card views.
1264 if (pinnedIpAddressesSwitch.isChecked()) { // IP addresses are pinned.
1265 // Set the visibility of the saved IP addresses.
1266 if (savedIpAddresses == null) { // There are no saved IP addresses.
1267 savedIpAddressesCardView.setVisibility(View.GONE);
1268 } else { // There are saved IP addresses.
1269 savedIpAddressesCardView.setVisibility(View.VISIBLE);
1272 // Set the visibility of the current IP addresses.
1273 currentIpAddressesCardView.setVisibility(View.VISIBLE);
1275 // Set the status of the radio buttons and the card view backgrounds.
1276 if (savedIpAddressesCardView.getVisibility() == View.VISIBLE) { // The saved IP addresses are displayed.
1277 // Check the saved IP addresses radio button.
1278 savedIpAddressesRadioButton.setChecked(true);
1280 // Uncheck the current IP addresses radio button.
1281 currentIpAddressesRadioButton.setChecked(false);
1283 // Darken the background of the current IP addresses linear layout according to the theme.
1284 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1285 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
1287 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
1289 } else { // The saved IP addresses are hidden.
1290 // Check the current IP addresses radio button.
1291 currentIpAddressesRadioButton.setChecked(true);
1293 // Uncheck the saved IP addresses radio button.
1294 savedIpAddressesRadioButton.setChecked(false);
1296 } else { // IP addresses are not pinned.
1297 // Hide the IP addresses card views.
1298 savedIpAddressesCardView.setVisibility(View.GONE);
1299 currentIpAddressesCardView.setVisibility(View.GONE);
1301 // Uncheck the radio buttons.
1302 savedIpAddressesRadioButton.setChecked(false);
1303 currentIpAddressesRadioButton.setChecked(false);
1307 // Set the JavaScript switch listener.
1308 javaScriptSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1309 if (isChecked) { // JavaScript is enabled.
1310 // Update the JavaScript icon.
1311 javaScriptImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.javascript_enabled, null));
1313 // Enable the DOM storage `Switch`.
1314 domStorageSwitch.setEnabled(true);
1316 // Update the DOM storage icon.
1317 if (domStorageSwitch.isChecked()) { // DOM storage is enabled.
1318 domStorageImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.dom_storage_enabled, null));
1319 } else { // DOM storage is disabled.
1320 // Set the icon according to the theme.
1321 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1322 domStorageImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.dom_storage_disabled_night, null));
1324 domStorageImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.dom_storage_disabled_day, null));
1327 } else { // JavaScript is disabled.
1328 // Update the JavaScript icon.
1329 javaScriptImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.privacy_mode, null));
1331 // Disable the DOM storage `Switch`.
1332 domStorageSwitch.setEnabled(false);
1334 // Set the DOM storage icon according to the theme.
1335 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1336 domStorageImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.dom_storage_ghosted_night, null));
1338 domStorageImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.dom_storage_ghosted_day, null));
1343 // Set the cookies switch listener.
1344 cookiesSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1345 if (isChecked) { // Cookies are enabled.
1346 // Update the cookies icon.
1347 cookiesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.cookies_enabled, null));
1348 } else { // Cookies are disabled.
1349 // Update the cookies icon according to the theme.
1350 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1351 cookiesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.cookies_disabled_day, null));
1353 cookiesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.cookies_disabled_night, null));
1358 // Set the DOM Storage switch listener.
1359 domStorageSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1362 domStorageImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.dom_storage_enabled, null));
1364 // Set the icon according to the theme.
1365 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1366 domStorageImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.dom_storage_disabled_night, null));
1368 domStorageImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.dom_storage_disabled_day, null));
1373 // Set the form data switch listener. It can be removed once the minimum API >= 26.
1374 if (Build.VERSION.SDK_INT < 26) {
1375 formDataSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1378 formDataImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.form_data_enabled, null));
1380 // Set the icon according to the theme.
1381 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1382 formDataImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.form_data_disabled_night, null));
1384 formDataImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.form_data_disabled_day, null));
1390 // Set the EasyList switch listener.
1391 easyListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1393 if (isChecked) { // EasyList is on.
1394 // Set the icon according to the theme.
1395 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1396 easyListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_ads_enabled_night, null));
1398 easyListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_ads_enabled_day, null));
1400 } else { // EasyList is off.
1401 // Set the icon according to the theme.
1402 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1403 easyListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_ads_disabled_night, null));
1405 easyListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_ads_disabled_day, null));
1410 // Set the EasyPrivacy switch listener.
1411 easyPrivacySwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1413 if (isChecked) { // EasyPrivacy is on.
1414 // Set the icon according to the theme.
1415 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1416 easyPrivacyImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_tracking_enabled_night, null));
1418 easyPrivacyImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_tracking_enabled_day, null));
1420 } else { // EasyPrivacy is off.
1421 // Set the icon according to the theme.
1422 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1423 easyPrivacyImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_tracking_disabled_night, null));
1425 easyPrivacyImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_tracking_disabled_day, null));
1430 // Set the Fanboy's Annoyance List switch listener.
1431 fanboysAnnoyanceListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1432 // Update the icon and Fanboy's Social Blocking List.
1433 if (isChecked) { // Fanboy's Annoyance List is on.
1434 // Set the icon according to the theme.
1435 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1436 fanboysAnnoyanceListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.social_media_enabled_night, null));
1438 fanboysAnnoyanceListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.social_media_enabled_day, null));
1441 // Disable the Fanboy's Social Blocking List switch.
1442 fanboysSocialBlockingListSwitch.setEnabled(false);
1444 // Update the Fanboy's Social Blocking List icon according to the theme.
1445 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1446 fanboysSocialBlockingListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.social_media_ghosted_night, null));
1448 fanboysSocialBlockingListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.social_media_ghosted_day, null));
1450 } else { // Fanboy's Annoyance List is off.
1451 // Set the icon according to the theme.
1452 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1453 fanboysAnnoyanceListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.social_media_disabled_night, null));
1455 fanboysAnnoyanceListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.social_media_disabled_day, null));
1458 // Enable the Fanboy's Social Blocking List switch.
1459 fanboysSocialBlockingListSwitch.setEnabled(true);
1461 // Update the Fanboy's Social Blocking List icon.
1462 if (fanboysSocialBlockingListSwitch.isChecked()) { // Fanboy's Social Blocking List is on.
1463 // Update the icon according to the theme.
1464 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1465 fanboysSocialBlockingListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.social_media_enabled_night, null));
1467 fanboysSocialBlockingListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.social_media_enabled_day, null));
1469 } else { // Fanboy's Social Blocking List is off.
1470 // Update the icon according to the theme.
1471 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1472 fanboysSocialBlockingListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.social_media_disabled_night, null));
1474 fanboysSocialBlockingListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.social_media_disabled_day, null));
1481 // Set the Fanboy's Social Blocking List switch listener.
1482 fanboysSocialBlockingListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1484 if (isChecked) { // Fanboy's Social Blocking List is on.
1485 // Set the icon according to the theme.
1486 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1487 fanboysSocialBlockingListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.social_media_enabled_night, null));
1489 fanboysSocialBlockingListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.social_media_enabled_day, null));
1491 } else { // Fanboy's Social Blocking List is off.
1492 // Set the icon according to the theme.
1493 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1494 fanboysSocialBlockingListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.social_media_disabled_night, null));
1496 fanboysSocialBlockingListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.social_media_disabled_day, null));
1501 // Set the UltraList switch listener.
1502 ultraListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1504 if (isChecked) { // UltraList is on.
1505 // Set the icon according to the theme.
1506 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1507 ultraListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_ads_enabled_night, null));
1509 ultraListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_ads_enabled_day, null));
1511 } else { // UltraList is off.
1512 // Set the icon according to the theme.
1513 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1514 ultraListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_ads_disabled_night, null));
1516 ultraListImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_ads_disabled_day, null));
1521 // Set the UltraPrivacy switch listener.
1522 ultraPrivacySwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1524 if (isChecked) { // UltraPrivacy is on.
1525 // Set the icon according to the theme.
1526 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1527 ultraPrivacyImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_tracking_enabled_night, null));
1529 ultraPrivacyImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_tracking_enabled_day, null));
1531 } else { // UltraPrivacy is off.
1532 // Set the icon according to the theme.
1533 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1534 ultraPrivacyImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_tracking_disabled_night, null));
1536 ultraPrivacyImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_tracking_disabled_day, null));
1541 // Set the block all third-party requests switch listener.
1542 blockAllThirdPartyRequestsSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1544 if (isChecked) { // Blocking all third-party requests is on.
1545 // Set the icon according to the theme.
1546 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1547 blockAllThirdPartyRequestsImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_all_third_party_requests_enabled_night, null));
1549 blockAllThirdPartyRequestsImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_all_third_party_requests_enabled_day, null));
1551 } else { // Blocking all third-party requests is off.
1552 // Set the icon according to the theme.
1553 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1554 blockAllThirdPartyRequestsImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_all_third_party_requests_disabled_night, null));
1556 blockAllThirdPartyRequestsImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.block_all_third_party_requests_disabled_day, null));
1561 // Set the user agent spinner listener.
1562 userAgentSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1564 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1565 // Set the new user agent.
1567 case MainWebViewActivity.DOMAINS_SYSTEM_DEFAULT_USER_AGENT:
1568 // Show the user agent TextView.
1569 userAgentTextView.setVisibility(View.VISIBLE);
1571 // Hide the custom user agent EditText.
1572 customUserAgentEditText.setVisibility(View.GONE);
1574 // Set the user text.
1575 switch (defaultUserAgentArrayPosition) {
1576 case MainWebViewActivity.UNRECOGNIZED_USER_AGENT: // The default user agent name is not on the canonical list.
1577 // This is probably because it was set in an older version of Privacy Browser before the switch to persistent user agent names.
1578 userAgentTextView.setText(defaultUserAgentName);
1581 case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
1582 // Display the `WebView` default user agent.
1583 userAgentTextView.setText(webViewDefaultUserAgentString);
1586 case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
1587 // Display the custom user agent.
1588 userAgentTextView.setText(defaultCustomUserAgentString);
1592 // Get the user agent string from the user agent data array.
1593 userAgentTextView.setText(userAgentDataArray[defaultUserAgentArrayPosition]);
1597 case MainWebViewActivity.DOMAINS_WEBVIEW_DEFAULT_USER_AGENT:
1598 // Show the user agent TextView and set the text.
1599 userAgentTextView.setVisibility(View.VISIBLE);
1600 userAgentTextView.setText(webViewDefaultUserAgentString);
1602 // Hide the custom user agent EditTex.
1603 customUserAgentEditText.setVisibility(View.GONE);
1606 case MainWebViewActivity.DOMAINS_CUSTOM_USER_AGENT:
1607 // Hide the user agent TextView.
1608 userAgentTextView.setVisibility(View.GONE);
1610 // Show the custom user agent EditText and set the current user agent name as the text.
1611 customUserAgentEditText.setVisibility(View.VISIBLE);
1612 customUserAgentEditText.setText(currentUserAgentName);
1616 // 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.
1617 userAgentTextView.setVisibility(View.VISIBLE);
1618 userAgentTextView.setText(userAgentDataArray[position - 1]);
1620 // Hide `customUserAgentEditText`.
1621 customUserAgentEditText.setVisibility(View.GONE);
1626 public void onNothingSelected(AdapterView<?> parent) {
1631 // Set the font size spinner listener.
1632 fontSizeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1634 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1635 // Update the font size display options.
1636 if (position == 0) { // The system default font size has been selected.
1637 // Show the default font size text view.
1638 defaultFontSizeTextView.setVisibility(View.VISIBLE);
1640 // Hide the custom font size edit text.
1641 customFontSizeEditText.setVisibility(View.GONE);
1642 } else { // A custom font size has been selected.
1643 // Hide the default font size text view.
1644 defaultFontSizeTextView.setVisibility(View.GONE);
1646 // Show the custom font size edit text.
1647 customFontSizeEditText.setVisibility(View.VISIBLE);
1652 public void onNothingSelected(AdapterView<?> parent) {
1657 // Set the swipe to refresh spinner listener.
1658 swipeToRefreshSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1660 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1661 // 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.
1663 case DomainsDatabaseHelper.SYSTEM_DEFAULT:
1664 if (defaultSwipeToRefresh) { // Swipe to refresh enabled by default.
1665 // Set the icon according to the theme.
1666 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1667 swipeToRefreshImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.refresh_enabled_night, null));
1669 swipeToRefreshImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.refresh_enabled_day, null));
1671 } else { // Swipe to refresh disabled by default.
1672 // Set the icon according to the theme.
1673 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1674 swipeToRefreshImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.refresh_disabled_night, null));
1676 swipeToRefreshImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.refresh_disabled_day, null));
1680 // Show the swipe to refresh TextView.
1681 swipeToRefreshTextView.setVisibility(View.VISIBLE);
1684 case DomainsDatabaseHelper.ENABLED:
1685 // Set the icon according to the theme.
1686 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1687 swipeToRefreshImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.refresh_enabled_night, null));
1689 swipeToRefreshImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.refresh_enabled_day, null));
1692 // Hide the swipe to refresh TextView.
1693 swipeToRefreshTextView.setVisibility(View.GONE);
1696 case DomainsDatabaseHelper.DISABLED:
1697 // Set the icon according to the theme.
1698 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1699 swipeToRefreshImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.refresh_disabled_night, null));
1701 swipeToRefreshImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.refresh_disabled_day, null));
1704 // Hide the swipe to refresh TextView.
1705 swipeToRefreshTextView.setVisibility(View.GONE);
1710 public void onNothingSelected(AdapterView<?> parent) {
1715 // Set the WebView theme spinner listener.
1716 webViewThemeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1718 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1719 // 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.
1721 case DomainsDatabaseHelper.SYSTEM_DEFAULT: // the domain WebView theme is system default.
1722 // Set the icon according to the app WebView theme.
1723 switch (appWebViewThemeEntryNumber) {
1724 case DomainsDatabaseHelper.SYSTEM_DEFAULT: // The default WebView theme is system default.
1725 // Set the icon according to the app theme.
1726 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1727 // Set the light mode icon.
1728 webViewThemeImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.webview_light_theme_day, null));
1730 // Set the dark theme icon.
1731 webViewThemeImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.webview_dark_theme_night, null));
1735 case DomainsDatabaseHelper.LIGHT_THEME: // The default WebView theme is light.
1736 // Set the icon according to the app theme.
1737 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1738 webViewThemeImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.webview_light_theme_day, null));
1740 webViewThemeImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.webview_light_theme_night, null));
1744 case DomainsDatabaseHelper.DARK_THEME: // The default WebView theme is dark.
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_dark_theme_day, null));
1749 webViewThemeImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.webview_dark_theme_night, null));
1754 // Show the WebView theme text view.
1755 webViewThemeTextView.setVisibility(View.VISIBLE);
1758 case DomainsDatabaseHelper.LIGHT_THEME: // The domain WebView theme is light.
1759 // Set the icon according to the app theme.
1760 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1761 webViewThemeImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.webview_light_theme_day, null));
1763 webViewThemeImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.webview_light_theme_night, null));
1766 // Hide the WebView theme text view.
1767 webViewThemeTextView.setVisibility(View.GONE);
1770 case DomainsDatabaseHelper.DARK_THEME: // The domain WebView theme is dark.
1771 // Set the icon according to the app theme.
1772 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1773 webViewThemeImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.webview_dark_theme_day, null));
1775 webViewThemeImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.webview_dark_theme_night, null));
1778 // Hide the WebView theme text view.
1779 webViewThemeTextView.setVisibility(View.GONE);
1785 public void onNothingSelected(AdapterView<?> parent) {
1790 // Set the wide viewport spinner listener.
1791 wideViewportSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1793 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1794 // Update the icon and the visibility of the wide viewport text view.
1796 case DomainsDatabaseHelper.SYSTEM_DEFAULT:
1797 if (defaultWideViewport) { // Wide viewport is enabled by default.
1798 // Set the icon according to the theme.
1799 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1800 wideViewportImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.wide_viewport_enabled_night, null));
1802 wideViewportImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.wide_viewport_enabled_day, null));
1804 } else { // Wide viewport is disabled by default.
1805 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1806 wideViewportImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.wide_viewport_disabled_night, null));
1808 wideViewportImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.wide_viewport_disabled_day, null));
1812 // Show the wide viewport text view.
1813 wideViewportTextView.setVisibility(View.VISIBLE);
1816 case DomainsDatabaseHelper.ENABLED:
1817 // Set the icon according to the theme.
1818 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1819 wideViewportImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.wide_viewport_enabled_night, null));
1821 wideViewportImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.wide_viewport_enabled_day, null));
1824 // Hide the wide viewport text view.
1825 wideViewportTextView.setVisibility(View.GONE);
1828 case DomainsDatabaseHelper.DISABLED:
1829 // Set the icon according to the theme.
1830 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1831 wideViewportImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.wide_viewport_disabled_night, null));
1833 wideViewportImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.wide_viewport_disabled_day, null));
1836 // Hid ethe wide viewport text view.
1837 wideViewportTextView.setVisibility(View.GONE);
1843 public void onNothingSelected(AdapterView<?> parent) {
1848 // Set the display webpage images spinner listener.
1849 displayWebpageImagesSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1851 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1852 // Update the icon and the visibility of the display images text view.
1854 case DomainsDatabaseHelper.SYSTEM_DEFAULT:
1855 if (defaultDisplayWebpageImages) { // Display webpage images is enabled by default.
1856 // Set the icon according to the theme.
1857 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1858 displayWebpageImagesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.images_enabled_night, null));
1860 displayWebpageImagesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.images_enabled_day, null));
1862 } else { // Display webpage images is disabled by default.
1863 // Set the icon according to the theme.
1864 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1865 displayWebpageImagesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.images_disabled_night, null));
1867 displayWebpageImagesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.images_disabled_day, null));
1871 // Show the display images text view.
1872 displayImagesTextView.setVisibility(View.VISIBLE);
1875 case DomainsDatabaseHelper.ENABLED:
1876 // Set the icon according to the theme.
1877 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1878 displayWebpageImagesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.images_enabled_night, null));
1880 displayWebpageImagesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.images_enabled_day, null));
1883 // Hide the display images text view.
1884 displayImagesTextView.setVisibility(View.GONE);
1887 case DomainsDatabaseHelper.DISABLED:
1888 // Set the icon according to the theme.
1889 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1890 displayWebpageImagesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.images_disabled_night, null));
1892 displayWebpageImagesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.images_disabled_day, null));
1895 // Hide the display images text view.
1896 displayImagesTextView.setVisibility(View.GONE);
1902 public void onNothingSelected(AdapterView<?> parent) {
1907 // Set the pinned SSL certificate switch listener.
1908 pinnedSslCertificateSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1910 if (isChecked) { // SSL certificate pinning is enabled.
1911 // Set the icon according to the theme.
1912 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1913 pinnedSslCertificateImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ssl_certificate_enabled_night, null));
1915 pinnedSslCertificateImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ssl_certificate_enabled_day, null));
1918 // Update the visibility of the saved SSL certificate.
1919 if (savedSslIssuedToCNameString == null) {
1920 savedSslCardView.setVisibility(View.GONE);
1922 savedSslCardView.setVisibility(View.VISIBLE);
1925 // Update the visibility of the current website SSL certificate.
1926 if (DomainsActivity.sslIssuedToCName == null) {
1927 // Hide the SSL certificate.
1928 currentSslCardView.setVisibility(View.GONE);
1930 // Show the instruction.
1931 noCurrentWebsiteCertificateTextView.setVisibility(View.VISIBLE);
1933 // Show the SSL certificate.
1934 currentSslCardView.setVisibility(View.VISIBLE);
1936 // Hide the instruction.
1937 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
1940 // Set the status of the radio buttons.
1941 if (savedSslCardView.getVisibility() == View.VISIBLE) { // The saved SSL certificate is displayed.
1942 // Check the saved SSL certificate radio button.
1943 savedSslCertificateRadioButton.setChecked(true);
1945 // Uncheck the current website SSL certificate radio button.
1946 currentWebsiteCertificateRadioButton.setChecked(false);
1948 // Set the background of the saved SSL certificate linear layout to be transparent.
1949 savedSslCertificateLinearLayout.setBackgroundResource(R.color.transparent);
1951 // Darken the background of the current website SSL certificate linear layout according to the theme.
1952 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1953 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
1955 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
1958 // Scroll to the current website SSL certificate card.
1959 savedSslCardView.getParent().requestChildFocus(savedSslCardView, savedSslCardView);
1960 } else if (currentSslCardView.getVisibility() == View.VISIBLE) { // The saved SSL certificate is hidden but the current website SSL certificate is visible.
1961 // Check the current website SSL certificate radio button.
1962 currentWebsiteCertificateRadioButton.setChecked(true);
1964 // Uncheck the saved SSL certificate radio button.
1965 savedSslCertificateRadioButton.setChecked(false);
1967 // Set the background of the current website SSL certificate linear layout to be transparent.
1968 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.transparent);
1970 // Darken the background of the saved SSL certificate linear layout according to the theme.
1971 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1972 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
1974 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
1977 // Scroll to the current website SSL certificate card.
1978 currentSslCardView.getParent().requestChildFocus(currentSslCardView, currentSslCardView);
1979 } else { // Neither SSL certificate is visible.
1980 // Uncheck both radio buttons.
1981 savedSslCertificateRadioButton.setChecked(false);
1982 currentWebsiteCertificateRadioButton.setChecked(false);
1984 // Scroll to the current website SSL certificate card.
1985 noCurrentWebsiteCertificateTextView.getParent().requestChildFocus(noCurrentWebsiteCertificateTextView, noCurrentWebsiteCertificateTextView);
1987 } else { // SSL certificate pinning is disabled.
1988 // Set the icon according to the theme.
1989 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1990 pinnedSslCertificateImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ssl_certificate_disabled_night, null));
1992 pinnedSslCertificateImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ssl_certificate_disabled_day, null));
1995 // Hide the SSl certificates and instructions.
1996 savedSslCardView.setVisibility(View.GONE);
1997 currentSslCardView.setVisibility(View.GONE);
1998 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
2000 // Uncheck the radio buttons.
2001 savedSslCertificateRadioButton.setChecked(false);
2002 currentWebsiteCertificateRadioButton.setChecked(false);
2006 savedSslCardView.setOnClickListener((View view) -> {
2007 // Check the saved SSL certificate radio button.
2008 savedSslCertificateRadioButton.setChecked(true);
2010 // Uncheck the current website SSL certificate radio button.
2011 currentWebsiteCertificateRadioButton.setChecked(false);
2013 // Set the background of the saved SSL certificate linear layout to be transparent.
2014 savedSslCertificateLinearLayout.setBackgroundResource(R.color.transparent);
2016 // Darken the background of the current website SSL certificate linear layout according to the theme.
2017 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2018 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2020 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2024 savedSslCertificateRadioButton.setOnClickListener((View view) -> {
2025 // Check the saved SSL certificate radio button.
2026 savedSslCertificateRadioButton.setChecked(true);
2028 // Uncheck the current website SSL certificate radio button.
2029 currentWebsiteCertificateRadioButton.setChecked(false);
2031 // Set the background of the saved SSL certificate linear layout to be transparent.
2032 savedSslCertificateLinearLayout.setBackgroundResource(R.color.transparent);
2034 // Darken the background of the current website SSL certificate linear layout according to the theme.
2035 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2036 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2038 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2042 currentSslCardView.setOnClickListener((View view) -> {
2043 // Check the current website SSL certificate radio button.
2044 currentWebsiteCertificateRadioButton.setChecked(true);
2046 // Uncheck the saved SSL certificate radio button.
2047 savedSslCertificateRadioButton.setChecked(false);
2049 // Set the background of the current website SSL certificate linear layout to be transparent.
2050 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.transparent);
2052 // Darken the background of the saved SSL certificate linear layout according to the theme.
2053 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2054 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2056 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2060 currentWebsiteCertificateRadioButton.setOnClickListener((View view) -> {
2061 // Check the current website SSL certificate radio button.
2062 currentWebsiteCertificateRadioButton.setChecked(true);
2064 // Uncheck the saved SSL certificate radio button.
2065 savedSslCertificateRadioButton.setChecked(false);
2067 // Set the background of the current website SSL certificate linear layout to be transparent.
2068 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.transparent);
2070 // Darken the background of the saved SSL certificate linear layout according to the theme.
2071 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2072 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2074 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2078 // Set the pinned IP addresses switch listener.
2079 pinnedIpAddressesSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
2081 if (isChecked) { // IP addresses pinning is enabled.
2082 // Set the icon according to the theme.
2083 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2084 pinnedIpAddressesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ssl_certificate_enabled_night, null));
2086 pinnedIpAddressesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ssl_certificate_enabled_day, null));
2089 // Update the visibility of the saved IP addresses card view.
2090 if (savedIpAddresses == null) { // There are no saved IP addresses.
2091 savedIpAddressesCardView.setVisibility(View.GONE);
2092 } else { // There are saved IP addresses.
2093 savedIpAddressesCardView.setVisibility(View.VISIBLE);
2096 // Show the current IP addresses card view.
2097 currentIpAddressesCardView.setVisibility(View.VISIBLE);
2099 // Set the status of the radio buttons.
2100 if (savedIpAddressesCardView.getVisibility() == View.VISIBLE) { // The saved IP addresses are visible.
2101 // Check the saved IP addresses radio button.
2102 savedIpAddressesRadioButton.setChecked(true);
2104 // Uncheck the current IP addresses radio button.
2105 currentIpAddressesRadioButton.setChecked(false);
2107 // Set the background of the saved IP addresses linear layout to be transparent.
2108 savedSslCertificateLinearLayout.setBackgroundResource(R.color.transparent);
2110 // Darken the background of the current IP addresses linear layout according to the theme.
2111 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2112 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2114 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2116 } else { // The saved IP addresses are not visible.
2117 // Check the current IP addresses radio button.
2118 currentIpAddressesRadioButton.setChecked(true);
2120 // Uncheck the saved IP addresses radio button.
2121 savedIpAddressesRadioButton.setChecked(false);
2123 // Set the background of the current IP addresses linear layout to be transparent.
2124 currentIpAddressesLinearLayout.setBackgroundResource(R.color.transparent);
2126 // Darken the background of the saved IP addresses linear layout according to the theme.
2127 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2128 savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2130 savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2134 // Scroll to the bottom of the card views.
2135 currentIpAddressesCardView.getParent().requestChildFocus(currentIpAddressesCardView, currentIpAddressesCardView);
2136 } else { // IP addresses pinning is disabled.
2137 // Set the icon according to the theme.
2138 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2139 pinnedIpAddressesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ssl_certificate_disabled_night, null));
2141 pinnedIpAddressesImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ssl_certificate_disabled_day, null));
2144 // Hide the IP addresses card views.
2145 savedIpAddressesCardView.setVisibility(View.GONE);
2146 currentIpAddressesCardView.setVisibility(View.GONE);
2148 // Uncheck the radio buttons.
2149 savedIpAddressesRadioButton.setChecked(false);
2150 currentIpAddressesRadioButton.setChecked(false);
2154 savedIpAddressesCardView.setOnClickListener((View view) -> {
2155 // Check the saved IP addresses radio button.
2156 savedIpAddressesRadioButton.setChecked(true);
2158 // Uncheck the current website IP addresses radio button.
2159 currentIpAddressesRadioButton.setChecked(false);
2161 // Set the background of the saved IP addresses linear layout to be transparent.
2162 savedIpAddressesLinearLayout.setBackgroundResource(R.color.transparent);
2164 // Darken the background of the current IP addresses linear layout according to the theme.
2165 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2166 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2168 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2172 savedIpAddressesRadioButton.setOnClickListener((View view) -> {
2173 // Check the saved IP addresses radio button.
2174 savedIpAddressesRadioButton.setChecked(true);
2176 // Uncheck the current website IP addresses radio button.
2177 currentIpAddressesRadioButton.setChecked(false);
2179 // Set the background of the saved IP addresses linear layout to be transparent.
2180 savedIpAddressesLinearLayout.setBackgroundResource(R.color.transparent);
2182 // Darken the background of the current IP addresses linear layout according to the theme.
2183 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2184 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2186 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2190 currentIpAddressesCardView.setOnClickListener((View view) -> {
2191 // Check the current IP addresses radio button.
2192 currentIpAddressesRadioButton.setChecked(true);
2194 // Uncheck the saved IP addresses radio button.
2195 savedIpAddressesRadioButton.setChecked(false);
2197 // Set the background of the current IP addresses linear layout to be transparent.
2198 currentIpAddressesLinearLayout.setBackgroundResource(R.color.transparent);
2200 // Darken the background of the saved IP addresses linear layout according to the theme.
2201 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2202 savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2204 savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2208 currentIpAddressesRadioButton.setOnClickListener((View view) -> {
2209 // Check the current IP addresses radio button.
2210 currentIpAddressesRadioButton.setChecked(true);
2212 // Uncheck the saved IP addresses radio button.
2213 savedIpAddressesRadioButton.setChecked(false);
2215 // Set the background of the current IP addresses linear layout to be transparent.
2216 currentIpAddressesLinearLayout.setBackgroundResource(R.color.transparent);
2218 // Darken the background of the saved IP addresses linear layout according to the theme.
2219 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2220 savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2222 savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2226 // Set the scroll Y.
2227 domainSettingsScrollView.post(() -> domainSettingsScrollView.setScrollY(scrollY));
2229 // Return the domain settings view.
2230 return domainSettingsView;
2233 private boolean checkDomainNameAgainstCertificate(String domainName, String certificateCommonName) {
2234 // Initialize `domainNamesMatch`.
2235 boolean domainNamesMatch = false;
2237 // Check various wildcard permutations if `domainName` and `certificateCommonName` are not empty.
2238 // `noinspection ConstantCondition` removes Android Studio's incorrect lint warning that `domainName` can never be `null`.
2239 if ((domainName != null) && (certificateCommonName != null)) {
2240 // Check if the domains match.
2241 if (domainName.equals(certificateCommonName)) {
2242 domainNamesMatch = true;
2245 // If `domainName` starts with a wildcard, check the base domain against all the subdomains of `certificateCommonName`.
2246 if (!domainNamesMatch && domainName.startsWith("*.") && (domainName.length() > 2)) {
2247 // Remove the initial `*.`.
2248 String baseDomainName = domainName.substring(2);
2250 // Setup a copy of `certificateCommonName` to test subdomains.
2251 String certificateCommonNameSubdomain = certificateCommonName;
2253 // Check all the subdomains in `certificateCommonNameSubdomain` against `baseDomainName`.
2254 while (!domainNamesMatch && certificateCommonNameSubdomain.contains(".")) { // Stop checking if we know that `domainNamesMatch` is `true` or if we run out of `.`.
2255 // Test the `certificateCommonNameSubdomain` against `baseDomainName`.
2256 if (certificateCommonNameSubdomain.equals(baseDomainName)) {
2257 domainNamesMatch = true;
2260 // Strip out the lowest subdomain of `certificateCommonNameSubdomain`.
2262 certificateCommonNameSubdomain = certificateCommonNameSubdomain.substring(certificateCommonNameSubdomain.indexOf(".") + 1);
2263 } catch (IndexOutOfBoundsException e) { // `certificateCommonNameSubdomain` ends with `.`.
2264 certificateCommonNameSubdomain = "";
2269 // If `certificateCommonName` starts with a wildcard, check the base common name against all the subdomains of `domainName`.
2270 if (!domainNamesMatch && certificateCommonName.startsWith("*.") && (certificateCommonName.length() > 2)) {
2271 // Remove the initial `*.`.
2272 String baseCertificateCommonName = certificateCommonName.substring(2);
2274 // Setup a copy of `domainName` to test subdomains.
2275 String domainNameSubdomain = domainName;
2277 // Check all the subdomains in `domainNameSubdomain` against `baseCertificateCommonName`.
2278 while (!domainNamesMatch && domainNameSubdomain.contains(".") && (domainNameSubdomain.length() > 2)) {
2279 // Test the `domainNameSubdomain` against `baseCertificateCommonName`.
2280 if (domainNameSubdomain.equals(baseCertificateCommonName)) {
2281 domainNamesMatch = true;
2284 // Strip out the lowest subdomain of `domainNameSubdomain`.
2286 domainNameSubdomain = domainNameSubdomain.substring(domainNameSubdomain.indexOf(".") + 1);
2287 } catch (IndexOutOfBoundsException e) { // `domainNameSubdomain` ends with `.`.
2288 domainNameSubdomain = "";
2293 // If both names start with a wildcard, check if the root of one contains the root of the other.
2294 if (!domainNamesMatch && domainName.startsWith("*.") && (domainName.length() > 2) && certificateCommonName.startsWith("*.") && (certificateCommonName.length() > 2)) {
2295 // Remove the wildcards.
2296 String rootDomainName = domainName.substring(2);
2297 String rootCertificateCommonName = certificateCommonName.substring(2);
2299 // Check if one name ends with the contents of the other. If so, there will be overlap in the their wildcard subdomains.
2300 if (rootDomainName.endsWith(rootCertificateCommonName) || rootCertificateCommonName.endsWith(rootDomainName)) {
2301 domainNamesMatch = true;
2306 return domainNamesMatch;