2 * Copyright © 2017-2020 Soren Stoutner <soren@stoutner.com>.
4 * This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
6 * Privacy Browser is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * Privacy Browser is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with Privacy Browser. If not, see <http://www.gnu.org/licenses/>.
20 package com.stoutner.privacybrowser.fragments;
22 import android.annotation.SuppressLint;
23 import android.content.Context;
24 import android.content.SharedPreferences;
25 import android.content.res.Configuration;
26 import android.content.res.Resources;
27 import android.database.Cursor;
28 import android.os.Build;
29 import android.os.Bundle;
30 import android.preference.PreferenceManager;
31 import android.text.Editable;
32 import android.text.SpannableStringBuilder;
33 import android.text.Spanned;
34 import android.text.TextWatcher;
35 import android.text.style.ForegroundColorSpan;
36 import android.view.LayoutInflater;
37 import android.view.View;
38 import android.view.ViewGroup;
39 import android.webkit.WebView;
40 import android.widget.AdapterView;
41 import android.widget.ArrayAdapter;
42 import android.widget.CompoundButton;
43 import android.widget.EditText;
44 import android.widget.ImageView;
45 import android.widget.LinearLayout;
46 import android.widget.RadioButton;
47 import android.widget.Spinner;
48 import android.widget.Switch;
49 import android.widget.TextView;
51 import androidx.annotation.NonNull;
52 import androidx.cardview.widget.CardView;
53 import androidx.fragment.app.Fragment; // The AndroidX fragment must be used until minimum API >= 23. Otherwise `getContext()` does not work.
55 import com.stoutner.privacybrowser.R;
56 import com.stoutner.privacybrowser.activities.DomainsActivity;
57 import com.stoutner.privacybrowser.activities.MainWebViewActivity;
58 import com.stoutner.privacybrowser.helpers.DomainsDatabaseHelper;
60 import java.text.DateFormat;
61 import java.util.Calendar;
62 import java.util.Date;
64 public class DomainSettingsFragment extends Fragment {
65 // `DATABASE_ID` is used by activities calling this fragment.
66 public static final String DATABASE_ID = "database_id";
68 // `databaseId` is public static so it can be accessed from `DomainsActivity`. It is also used in `onCreate()` and `onCreateView()`.
69 public static int databaseId;
72 public void onCreate(Bundle savedInstanceState) {
73 // Run the default commands.
74 super.onCreate(savedInstanceState);
76 // Remove the lint warning that `getArguments` might be null.
77 assert getArguments() != null;
79 // Store the database id in `databaseId`.
80 databaseId = getArguments().getInt(DATABASE_ID);
83 // The deprecated `getDrawable()` must be used until the minimum API >= 21.
85 public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
86 // Inflate `domain_settings_fragment`. `false` does not attach it to the root `container`.
87 View domainSettingsView = inflater.inflate(R.layout.domain_settings_fragment, container, false);
89 // Get a handle for the context and the resources.
90 Context context = getContext();
91 Resources resources = getResources();
93 // Remove the error below that the context might be null.
94 assert context != null;
96 // Get the current theme status.
97 int currentThemeStatus = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
99 // Get a handle for the shared preference.
100 SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
102 // Store the default settings.
103 String defaultUserAgentName = sharedPreferences.getString("user_agent", getString(R.string.user_agent_default_value));
104 String defaultCustomUserAgentString = sharedPreferences.getString("custom_user_agent", getString(R.string.custom_user_agent_default_value));
105 String defaultFontSizeString = sharedPreferences.getString("font_size", getString(R.string.font_size_default_value));
106 boolean defaultSwipeToRefresh = sharedPreferences.getBoolean("swipe_to_refresh", true);
107 boolean defaultNightMode = sharedPreferences.getBoolean("night_mode", false);
108 boolean defaultWideViewport = sharedPreferences.getBoolean("wide_viewport", true);
109 boolean defaultDisplayWebpageImages = sharedPreferences.getBoolean("display_webpage_images", true);
111 // Get handles for the views in the fragment.
112 EditText domainNameEditText = domainSettingsView.findViewById(R.id.domain_settings_name_edittext);
113 ImageView javaScriptImageView = domainSettingsView.findViewById(R.id.javascript_imageview);
114 Switch javaScriptSwitch = domainSettingsView.findViewById(R.id.javascript_switch);
115 ImageView firstPartyCookiesImageView = domainSettingsView.findViewById(R.id.first_party_cookies_imageview);
116 Switch firstPartyCookiesSwitch = domainSettingsView.findViewById(R.id.first_party_cookies_switch);
117 LinearLayout thirdPartyCookiesLinearLayout = domainSettingsView.findViewById(R.id.third_party_cookies_linearlayout);
118 ImageView thirdPartyCookiesImageView = domainSettingsView.findViewById(R.id.third_party_cookies_imageview);
119 Switch thirdPartyCookiesSwitch = domainSettingsView.findViewById(R.id.third_party_cookies_switch);
120 ImageView domStorageImageView = domainSettingsView.findViewById(R.id.dom_storage_imageview);
121 Switch domStorageSwitch = domainSettingsView.findViewById(R.id.dom_storage_switch);
122 ImageView formDataImageView = domainSettingsView.findViewById(R.id.form_data_imageview); // The form data views can be remove once the minimum API >= 26.
123 Switch formDataSwitch = domainSettingsView.findViewById(R.id.form_data_switch); // The form data views can be remove once the minimum API >= 26.
124 ImageView easyListImageView = domainSettingsView.findViewById(R.id.easylist_imageview);
125 Switch easyListSwitch = domainSettingsView.findViewById(R.id.easylist_switch);
126 ImageView easyPrivacyImageView = domainSettingsView.findViewById(R.id.easyprivacy_imageview);
127 Switch easyPrivacySwitch = domainSettingsView.findViewById(R.id.easyprivacy_switch);
128 ImageView fanboysAnnoyanceListImageView = domainSettingsView.findViewById(R.id.fanboys_annoyance_list_imageview);
129 Switch fanboysAnnoyanceListSwitch = domainSettingsView.findViewById(R.id.fanboys_annoyance_list_switch);
130 ImageView fanboysSocialBlockingListImageView = domainSettingsView.findViewById(R.id.fanboys_social_blocking_list_imageview);
131 Switch fanboysSocialBlockingListSwitch = domainSettingsView.findViewById(R.id.fanboys_social_blocking_list_switch);
132 ImageView ultraListImageView = domainSettingsView.findViewById(R.id.ultralist_imageview);
133 Switch ultraListSwitch = domainSettingsView.findViewById(R.id.ultralist_switch);
134 ImageView ultraPrivacyImageView = domainSettingsView.findViewById(R.id.ultraprivacy_imageview);
135 Switch ultraPrivacySwitch = domainSettingsView.findViewById(R.id.ultraprivacy_switch);
136 ImageView blockAllThirdPartyRequestsImageView = domainSettingsView.findViewById(R.id.block_all_third_party_requests_imageview);
137 Switch blockAllThirdPartyRequestsSwitch = domainSettingsView.findViewById(R.id.block_all_third_party_requests_switch);
138 Spinner userAgentSpinner = domainSettingsView.findViewById(R.id.user_agent_spinner);
139 TextView userAgentTextView = domainSettingsView.findViewById(R.id.user_agent_textview);
140 EditText customUserAgentEditText = domainSettingsView.findViewById(R.id.custom_user_agent_edittext);
141 Spinner fontSizeSpinner = domainSettingsView.findViewById(R.id.font_size_spinner);
142 TextView defaultFontSizeTextView = domainSettingsView.findViewById(R.id.default_font_size_textview);
143 EditText customFontSizeEditText = domainSettingsView.findViewById(R.id.custom_font_size_edittext);
144 ImageView swipeToRefreshImageView = domainSettingsView.findViewById(R.id.swipe_to_refresh_imageview);
145 Spinner swipeToRefreshSpinner = domainSettingsView.findViewById(R.id.swipe_to_refresh_spinner);
146 TextView swipeToRefreshTextView = domainSettingsView.findViewById(R.id.swipe_to_refresh_textview);
147 ImageView nightModeImageView = domainSettingsView.findViewById(R.id.night_mode_imageview);
148 Spinner nightModeSpinner = domainSettingsView.findViewById(R.id.night_mode_spinner);
149 TextView nightModeTextView = domainSettingsView.findViewById(R.id.night_mode_textview);
150 ImageView wideViewportImageView = domainSettingsView.findViewById(R.id.wide_viewport_imageview);
151 Spinner wideViewportSpinner = domainSettingsView.findViewById(R.id.wide_viewport_spinner);
152 TextView wideViewportTextView = domainSettingsView.findViewById(R.id.wide_viewport_textview);
153 ImageView displayWebpageImagesImageView = domainSettingsView.findViewById(R.id.display_webpage_images_imageview);
154 Spinner displayWebpageImagesSpinner = domainSettingsView.findViewById(R.id.display_webpage_images_spinner);
155 TextView displayImagesTextView = domainSettingsView.findViewById(R.id.display_webpage_images_textview);
156 ImageView pinnedSslCertificateImageView = domainSettingsView.findViewById(R.id.pinned_ssl_certificate_imageview);
157 Switch pinnedSslCertificateSwitch = domainSettingsView.findViewById(R.id.pinned_ssl_certificate_switch);
158 CardView savedSslCardView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_cardview);
159 LinearLayout savedSslCertificateLinearLayout = domainSettingsView.findViewById(R.id.saved_ssl_certificate_linearlayout);
160 RadioButton savedSslCertificateRadioButton = domainSettingsView.findViewById(R.id.saved_ssl_certificate_radiobutton);
161 TextView savedSslIssuedToCNameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_to_cname);
162 TextView savedSslIssuedToONameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_to_oname);
163 TextView savedSslIssuedToUNameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_to_uname);
164 TextView savedSslIssuedByCNameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_by_cname);
165 TextView savedSslIssuedByONameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_by_oname);
166 TextView savedSslIssuedByUNameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_by_uname);
167 TextView savedSslStartDateTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_start_date);
168 TextView savedSslEndDateTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_end_date);
169 CardView currentSslCardView = domainSettingsView.findViewById(R.id.current_website_certificate_cardview);
170 LinearLayout currentWebsiteCertificateLinearLayout = domainSettingsView.findViewById(R.id.current_website_certificate_linearlayout);
171 RadioButton currentWebsiteCertificateRadioButton = domainSettingsView.findViewById(R.id.current_website_certificate_radiobutton);
172 TextView currentSslIssuedToCNameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_to_cname);
173 TextView currentSslIssuedToONameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_to_oname);
174 TextView currentSslIssuedToUNameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_to_uname);
175 TextView currentSslIssuedByCNameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_by_cname);
176 TextView currentSslIssuedByONameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_by_oname);
177 TextView currentSslIssuedByUNameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_by_uname);
178 TextView currentSslStartDateTextView = domainSettingsView.findViewById(R.id.current_website_certificate_start_date);
179 TextView currentSslEndDateTextView = domainSettingsView.findViewById(R.id.current_website_certificate_end_date);
180 TextView noCurrentWebsiteCertificateTextView = domainSettingsView.findViewById(R.id.no_current_website_certificate);
181 ImageView pinnedIpAddressesImageView = domainSettingsView.findViewById(R.id.pinned_ip_addresses_imageview);
182 Switch pinnedIpAddressesSwitch = domainSettingsView.findViewById(R.id.pinned_ip_addresses_switch);
183 CardView savedIpAddressesCardView = domainSettingsView.findViewById(R.id.saved_ip_addresses_cardview);
184 LinearLayout savedIpAddressesLinearLayout = domainSettingsView.findViewById(R.id.saved_ip_addresses_linearlayout);
185 RadioButton savedIpAddressesRadioButton = domainSettingsView.findViewById(R.id.saved_ip_addresses_radiobutton);
186 TextView savedIpAddressesTextView = domainSettingsView.findViewById(R.id.saved_ip_addresses_textview);
187 CardView currentIpAddressesCardView = domainSettingsView.findViewById(R.id.current_ip_addresses_cardview);
188 LinearLayout currentIpAddressesLinearLayout = domainSettingsView.findViewById(R.id.current_ip_addresses_linearlayout);
189 RadioButton currentIpAddressesRadioButton = domainSettingsView.findViewById(R.id.current_ip_addresses_radiobutton);
190 TextView currentIpAddressesTextView = domainSettingsView.findViewById(R.id.current_ip_addresses_textview);
192 // Setup the pinned labels.
193 String cNameLabel = getString(R.string.common_name) + " ";
194 String oNameLabel = getString(R.string.organization) + " ";
195 String uNameLabel = getString(R.string.organizational_unit) + " ";
196 String startDateLabel = getString(R.string.start_date) + " ";
197 String endDateLabel = getString(R.string.end_date) + " ";
199 // Initialize the database handler. The `0` specifies the database version, but that is ignored and set instead using a constant in `DomainsDatabaseHelper`.
200 DomainsDatabaseHelper domainsDatabaseHelper = new DomainsDatabaseHelper(context, null, null, 0);
202 // Get the database cursor for this ID and move it to the first row.
203 Cursor domainCursor = domainsDatabaseHelper.getCursorForId(databaseId);
204 domainCursor.moveToFirst();
206 // Save the cursor entries as variables.
207 String domainNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.DOMAIN_NAME));
208 int javaScriptInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_JAVASCRIPT));
209 int firstPartyCookiesInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FIRST_PARTY_COOKIES));
210 int thirdPartyCookiesInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_THIRD_PARTY_COOKIES));
211 int domStorageInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_DOM_STORAGE));
212 int formDataInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FORM_DATA)); // Form data can be remove once the minimum API >= 26.
213 int easyListInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYLIST));
214 int easyPrivacyInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYPRIVACY));
215 int fanboysAnnoyanceListInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST));
216 int fanboysSocialBlockingListInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST));
217 int ultraListInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ULTRALIST));
218 int ultraPrivacyInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY));
219 int blockAllThirdPartyRequestsInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS));
220 String currentUserAgentName = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.USER_AGENT));
221 int fontSizeInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.FONT_SIZE));
222 int swipeToRefreshInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.SWIPE_TO_REFRESH));
223 int nightModeInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.NIGHT_MODE));
224 int wideViewportInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.WIDE_VIEWPORT));
225 int displayImagesInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.DISPLAY_IMAGES));
226 int pinnedSslCertificateInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.PINNED_SSL_CERTIFICATE));
227 String savedSslIssuedToCNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_COMMON_NAME));
228 String savedSslIssuedToONameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATION));
229 String savedSslIssuedToUNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATIONAL_UNIT));
230 String savedSslIssuedByCNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_COMMON_NAME));
231 String savedSslIssuedByONameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATION));
232 String savedSslIssuedByUNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATIONAL_UNIT));
233 int pinnedIpAddressesInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.PINNED_IP_ADDRESSES));
234 String savedIpAddresses = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.IP_ADDRESSES));
236 // Initialize the saved SSL certificate date variables.
237 Date savedSslStartDate = null;
238 Date savedSslEndDate = null;
240 // Only get the saved SSL certificate dates from the cursor if they are not set to `0`.
241 if (domainCursor.getLong(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_START_DATE)) != 0) {
242 savedSslStartDate = new Date(domainCursor.getLong(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_START_DATE)));
245 if (domainCursor.getLong(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_END_DATE)) != 0) {
246 savedSslEndDate = new Date(domainCursor.getLong(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_END_DATE)));
249 // Create array adapters for the spinners.
250 ArrayAdapter<CharSequence> translatedUserAgentArrayAdapter = ArrayAdapter.createFromResource(context, R.array.translated_domain_settings_user_agent_names, R.layout.spinner_item);
251 ArrayAdapter<CharSequence> fontSizeArrayAdapter = ArrayAdapter.createFromResource(context, R.array.font_size_array, R.layout.spinner_item);
252 ArrayAdapter<CharSequence> swipeToRefreshArrayAdapter = ArrayAdapter.createFromResource(context, R.array.swipe_to_refresh_array, R.layout.spinner_item);
253 ArrayAdapter<CharSequence> nightModeArrayAdapter = ArrayAdapter.createFromResource(context, R.array.night_mode_array, R.layout.spinner_item);
254 ArrayAdapter<CharSequence> wideViewportArrayAdapter = ArrayAdapter.createFromResource(context, R.array.wide_viewport_array, R.layout.spinner_item);
255 ArrayAdapter<CharSequence> displayImagesArrayAdapter = ArrayAdapter.createFromResource(context, R.array.display_webpage_images_array, R.layout.spinner_item);
257 // Set the drop down view resource on the spinners.
258 translatedUserAgentArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items);
259 fontSizeArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items);
260 swipeToRefreshArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items);
261 nightModeArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items);
262 wideViewportArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items);
263 displayImagesArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items);
265 // Set the array adapters for the spinners.
266 userAgentSpinner.setAdapter(translatedUserAgentArrayAdapter);
267 fontSizeSpinner.setAdapter(fontSizeArrayAdapter);
268 swipeToRefreshSpinner.setAdapter(swipeToRefreshArrayAdapter);
269 nightModeSpinner.setAdapter(nightModeArrayAdapter);
270 wideViewportSpinner.setAdapter(wideViewportArrayAdapter);
271 displayWebpageImagesSpinner.setAdapter(displayImagesArrayAdapter);
273 // Create a spannable string builder for each TextView that needs multiple colors of text.
274 SpannableStringBuilder savedSslIssuedToCNameStringBuilder = new SpannableStringBuilder(cNameLabel + savedSslIssuedToCNameString);
275 SpannableStringBuilder savedSslIssuedToONameStringBuilder = new SpannableStringBuilder(oNameLabel + savedSslIssuedToONameString);
276 SpannableStringBuilder savedSslIssuedToUNameStringBuilder = new SpannableStringBuilder(uNameLabel + savedSslIssuedToUNameString);
277 SpannableStringBuilder savedSslIssuedByCNameStringBuilder = new SpannableStringBuilder(cNameLabel + savedSslIssuedByCNameString);
278 SpannableStringBuilder savedSslIssuedByONameStringBuilder = new SpannableStringBuilder(oNameLabel + savedSslIssuedByONameString);
279 SpannableStringBuilder savedSslIssuedByUNameStringBuilder = new SpannableStringBuilder(uNameLabel + savedSslIssuedByUNameString);
281 // Initialize the spannable string builders for the saved SSL certificate dates.
282 SpannableStringBuilder savedSslStartDateStringBuilder;
283 SpannableStringBuilder savedSslEndDateStringBuilder;
285 // Leave the SSL certificate dates empty if they are `null`.
286 if (savedSslStartDate == null) {
287 savedSslStartDateStringBuilder = new SpannableStringBuilder(startDateLabel);
289 savedSslStartDateStringBuilder = new SpannableStringBuilder(startDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG).format(savedSslStartDate));
292 if (savedSslEndDate == null) {
293 savedSslEndDateStringBuilder = new SpannableStringBuilder(endDateLabel);
295 savedSslEndDateStringBuilder = new SpannableStringBuilder(endDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG).format(savedSslEndDate));
298 // Create the foreground color spans.
299 final ForegroundColorSpan redColorSpan;
300 final ForegroundColorSpan blueColorSpan;
302 // Set the color spans according to the theme. The deprecated `resources` must be used until the minimum API >= 23.
303 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
304 redColorSpan = new ForegroundColorSpan(resources.getColor(R.color.red_900));
305 blueColorSpan = new ForegroundColorSpan(resources.getColor(R.color.violet_500));
307 redColorSpan = new ForegroundColorSpan(resources.getColor(R.color.red_a700));
308 blueColorSpan = new ForegroundColorSpan(resources.getColor(R.color.blue_700));
311 // Set the domain name from the the database cursor.
312 domainNameEditText.setText(domainNameString);
314 // Update the certificates' `Common Name` color when the domain name text changes.
315 domainNameEditText.addTextChangedListener(new TextWatcher() {
317 public void beforeTextChanged(CharSequence s, int start, int count, int after) {
322 public void onTextChanged(CharSequence s, int start, int before, int count) {
327 public void afterTextChanged(Editable s) {
328 // Get the new domain name.
329 String newDomainName = domainNameEditText.getText().toString();
331 // Check the saved SSL certificate against the new domain name.
332 boolean savedSslMatchesNewDomainName = checkDomainNameAgainstCertificate(newDomainName, savedSslIssuedToCNameString);
334 // Create a `SpannableStringBuilder` for the saved certificate `Common Name`.
335 SpannableStringBuilder savedSslCNameStringBuilder = new SpannableStringBuilder(cNameLabel + savedSslIssuedToCNameString);
337 // Format the saved certificate `Common Name` color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
338 if (savedSslMatchesNewDomainName) {
339 savedSslCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), savedSslCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
341 savedSslCNameStringBuilder.setSpan(redColorSpan, cNameLabel.length(), savedSslCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
344 // Update the saved SSL issued to CName text view.
345 savedSslIssuedToCNameTextView.setText(savedSslCNameStringBuilder);
347 // Update the current website certificate if it exists.
348 if (DomainsActivity.sslIssuedToCName != null) {
349 // Check the current website certificate against the new domain name.
350 boolean currentSslMatchesNewDomainName = checkDomainNameAgainstCertificate(newDomainName, DomainsActivity.sslIssuedToCName);
352 // Create a `SpannableStringBuilder` for the current website certificate `Common Name`.
353 SpannableStringBuilder currentSslCNameStringBuilder = new SpannableStringBuilder(cNameLabel + DomainsActivity.sslIssuedToCName);
355 // Format the current certificate `Common Name` color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
356 if (currentSslMatchesNewDomainName) {
357 currentSslCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), currentSslCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
359 currentSslCNameStringBuilder.setSpan(redColorSpan, cNameLabel.length(), currentSslCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
362 // Update the current SSL issued to CName text view.
363 currentSslIssuedToCNameTextView.setText(currentSslCNameStringBuilder);
368 // Create a boolean to track if night mode is enabled.
369 boolean nightModeEnabled = (nightModeInt == DomainsDatabaseHelper.ENABLED) || ((nightModeInt == DomainsDatabaseHelper.SYSTEM_DEFAULT) && defaultNightMode);
371 // Disable the JavaScript switch if night mode is enabled.
372 if (nightModeEnabled) {
373 javaScriptSwitch.setEnabled(false);
375 javaScriptSwitch.setEnabled(true);
378 // Set the JavaScript icon.
379 if ((javaScriptInt == 1) || nightModeEnabled) {
380 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.javascript_enabled));
382 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.privacy_mode));
385 // Set the JavaScript switch status.
386 if (javaScriptInt == 1) { // JavaScript is enabled.
387 javaScriptSwitch.setChecked(true);
388 } else { // JavaScript is disabled.
389 javaScriptSwitch.setChecked(false);
392 // Set the first-party cookies status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
393 if (firstPartyCookiesInt == 1) { // First-party cookies are enabled.
394 firstPartyCookiesSwitch.setChecked(true);
395 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_enabled));
396 } else { // First-party cookies are disabled.
397 firstPartyCookiesSwitch.setChecked(false);
399 // Set the icon according to the theme.
400 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
401 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_night));
403 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_day));
407 // Only display third-party cookies if SDK_INT >= 21.
408 if (Build.VERSION.SDK_INT >= 21) { // Third-party cookies can be configured for API >= 21.
409 // Only enable third-party-cookies if first-party cookies are enabled.
410 if (firstPartyCookiesInt == 1) { // First-party cookies are enabled.
411 // Set the third-party cookies status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
412 if (thirdPartyCookiesInt == 1) { // Both first-party and third-party cookies are enabled.
413 // Set the third-party cookies switch to be checked.
414 thirdPartyCookiesSwitch.setChecked(true);
416 // Set the icon to be red.
417 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_warning));
418 } else { // First party cookies are enabled but third-party cookies are disabled.
419 // Set the third-party cookies switch to be checked.
420 thirdPartyCookiesSwitch.setChecked(false);
422 // Set the icon according to the theme.
423 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
424 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_night));
426 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_day));
429 } else { // First-party cookies are disabled.
430 // Set the status of third-party cookies.
431 if (thirdPartyCookiesInt == 1) {
432 thirdPartyCookiesSwitch.setChecked(true);
434 thirdPartyCookiesSwitch.setChecked(false);
437 // Disable the third-party cookies switch.
438 thirdPartyCookiesSwitch.setEnabled(false);
440 // Set the icon according to the theme.
441 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
442 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_ghosted_night));
444 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_ghosted_day));
447 } else { // Third-party cookies cannot be configured for API <= 21.
448 // Hide the LinearLayout for third-party cookies.
449 thirdPartyCookiesLinearLayout.setVisibility(View.GONE);
452 // Only enable DOM storage if JavaScript is enabled.
453 if ((javaScriptInt == 1) || nightModeEnabled) { // JavaScript is enabled.
454 // Enable the DOM storage `Switch`.
455 domStorageSwitch.setEnabled(true);
457 // Set the DOM storage status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
458 if (domStorageInt == 1) { // Both JavaScript and DOM storage are enabled.
459 domStorageSwitch.setChecked(true);
460 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_enabled));
461 } else { // JavaScript is enabled but DOM storage is disabled.
462 // Set the DOM storage switch to off.
463 domStorageSwitch.setChecked(false);
465 // Set the icon according to the theme.
466 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
467 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_night));
469 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_day));
472 } else { // JavaScript is disabled.
473 // Disable the DOM storage `Switch`.
474 domStorageSwitch.setEnabled(false);
476 // Set the checked status of DOM storage.
477 if (domStorageInt == 1) { // DOM storage is enabled but JavaScript is disabled.
478 domStorageSwitch.setChecked(true);
479 } else { // Both JavaScript and DOM storage are disabled.
480 domStorageSwitch.setChecked(false);
483 // Set the icon according to the theme.
484 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
485 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_night));
487 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_day));
491 // Set the form data status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons. Form data can be removed once the minimum API >= 26.
492 if (Build.VERSION.SDK_INT >= 26) { // Form data no longer applies to newer versions of Android.
493 // Hide the form data switch.
494 formDataSwitch.setVisibility(View.GONE);
495 } else { // Form data should be displayed because this is an older version of Android.
496 if (formDataInt == 1) { // Form data is on.
497 formDataSwitch.setChecked(true);
498 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_enabled));
499 } else { // Form data is off.
500 // Turn the form data switch to off.
501 formDataSwitch.setChecked(false);
503 // Set the icon according to the theme.
504 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
505 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_disabled_night));
507 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_disabled_day));
512 // Set the EasyList status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
513 if (easyListInt == 1) { // EasyList is on.
514 // Turn the switch on.
515 easyListSwitch.setChecked(true);
517 // Set the icon according to the theme.
518 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
519 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_night));
521 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_day));
523 } else { // EasyList is off.
524 // Turn the switch off.
525 easyListSwitch.setChecked(false);
527 // Set the icon according to the theme.
528 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
529 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_night));
531 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_day));
535 // Set the EasyPrivacy status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
536 if (easyPrivacyInt == 1) { // EasyPrivacy is on.
537 // Turn the switch on.
538 easyPrivacySwitch.setChecked(true);
540 // Set the icon according to the theme.
541 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
542 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_night));
544 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_day));
546 } else { // EasyPrivacy is off.
547 // Turn the switch off.
548 easyPrivacySwitch.setChecked(false);
550 // Set the icon according to the theme.
551 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
552 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_night));
554 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_day));
558 // 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.
559 if (fanboysAnnoyanceListInt == 1) { // Fanboy's Annoyance List is on.
560 // Turn the switch on.
561 fanboysAnnoyanceListSwitch.setChecked(true);
563 // Set the icon according to the theme.
564 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
565 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_night));
567 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_day));
569 } else { // Fanboy's Annoyance List is off.
570 // Turn the switch off.
571 fanboysAnnoyanceListSwitch.setChecked(false);
573 // Set the icon according to the theme.
574 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
575 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_night));
577 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_day));
581 // Only enable Fanboy's Social Blocking List if Fanboy's Annoyance List is off.
582 if (fanboysAnnoyanceListInt == 0) { // Fanboy's Annoyance List is on.
583 // Enable Fanboy's Social Blocking List switch.
584 fanboysSocialBlockingListSwitch.setEnabled(true);
586 // 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.
587 if (fanboysSocialBlockingListInt == 1) { // Fanboy's Social Blocking List is on.
588 // Turn on Fanboy's Social Blocking List switch.
589 fanboysSocialBlockingListSwitch.setChecked(true);
591 // Set the icon according to the theme.
592 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
593 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_night));
595 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_day));
597 } else { // Fanboy's Social Blocking List is off.
598 // Turn off Fanboy's Social Blocking List switch.
599 fanboysSocialBlockingListSwitch.setChecked(false);
601 // Set the icon according to the theme.
602 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
603 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_night));
605 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_day));
608 } else { // Fanboy's Annoyance List is on.
609 // Disable Fanboy's Social Blocking List switch.
610 fanboysSocialBlockingListSwitch.setEnabled(false);
612 // Handle the status of Fanboy's Social Blocking List. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
613 if (fanboysSocialBlockingListInt == 1) { // Fanboy's Social Blocking List is on.
614 // Turn on Fanboy's Social Blocking List switch.
615 fanboysSocialBlockingListSwitch.setChecked(true);
616 } else { // Fanboy's Social Blocking List is off.
617 // Turn off Fanboy's Social Blocking List switch.
618 fanboysSocialBlockingListSwitch.setChecked(false);
621 // Set the icon according to the theme.
622 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
623 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_ghosted_night));
625 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_ghosted_day));
629 // Set the UltraList status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
630 if (ultraListInt == 1) { // UltraList is on.
631 // Turn the switch on.
632 ultraListSwitch.setChecked(true);
634 // Set the icon according to the theme.
635 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
636 ultraListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_night));
638 ultraListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_day));
640 } else { // UltraList is off.
641 // Turn the switch off.
642 ultraListSwitch.setChecked(false);
644 // Set the icon according to the theme.
645 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
646 ultraListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_night));
648 ultraListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_day));
652 // Set the UltraPrivacy status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
653 if (ultraPrivacyInt == 1) { // UltraPrivacy is on.
654 // Turn the switch on.
655 ultraPrivacySwitch.setChecked(true);
657 // Set the icon according to the theme.
658 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
659 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_night));
661 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_day));
663 } else { // EasyPrivacy is off.
664 // Turn the switch off.
665 ultraPrivacySwitch.setChecked(false);
667 // Set the icon according to the theme.
668 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
669 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_night));
671 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_day));
675 // 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.
676 if (blockAllThirdPartyRequestsInt == 1) { // Blocking all third-party requests is on.
677 // Turn the switch on.
678 blockAllThirdPartyRequestsSwitch.setChecked(true);
680 // Set the icon according to the theme.
681 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
682 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_enabled_night));
684 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_enabled_day));
686 } else { // Blocking all third-party requests is off.
687 // Turn the switch off.
688 blockAllThirdPartyRequestsSwitch.setChecked(false);
690 // Set the icon according to the theme.
691 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
692 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_disabled_night));
694 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_disabled_day));
698 // Inflated a WebView to get the default user agent.
699 // `@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.
700 @SuppressLint("InflateParams") View bareWebViewLayout = inflater.inflate(R.layout.bare_webview, null, false);
701 WebView bareWebView = bareWebViewLayout.findViewById(R.id.bare_webview);
702 final String webViewDefaultUserAgentString = bareWebView.getSettings().getUserAgentString();
704 // Get a handle for the user agent array adapter. This array does not contain the `System default` entry.
705 ArrayAdapter<CharSequence> userAgentNamesArray = ArrayAdapter.createFromResource(context, R.array.user_agent_names, R.layout.spinner_item);
707 // Get the positions of the user agent and the default user agent.
708 int userAgentArrayPosition = userAgentNamesArray.getPosition(currentUserAgentName);
709 int defaultUserAgentArrayPosition = userAgentNamesArray.getPosition(defaultUserAgentName);
711 // Get a handle for the user agent data array. This array does not contain the `System default` entry.
712 String[] userAgentDataArray = resources.getStringArray(R.array.user_agent_data);
714 // Set the user agent text.
715 if (currentUserAgentName.equals(getString(R.string.system_default_user_agent))) { // Use the system default user agent.
716 // Set the user agent according to the system default.
717 switch (defaultUserAgentArrayPosition) {
718 case MainWebViewActivity.UNRECOGNIZED_USER_AGENT: // The default user agent name is not on the canonical list.
719 // This is probably because it was set in an older version of Privacy Browser before the switch to persistent user agent names.
720 userAgentTextView.setText(defaultUserAgentName);
723 case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
724 // Display the `WebView` default user agent.
725 userAgentTextView.setText(webViewDefaultUserAgentString);
728 case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
729 // Display the custom user agent.
730 userAgentTextView.setText(defaultCustomUserAgentString);
734 // Get the user agent string from the user agent data array.
735 userAgentTextView.setText(userAgentDataArray[defaultUserAgentArrayPosition]);
737 } else if (userAgentArrayPosition == MainWebViewActivity.UNRECOGNIZED_USER_AGENT) { // A custom user agent is stored in the current user agent name.
738 // Set the user agent spinner to `Custom user agent`.
739 userAgentSpinner.setSelection(MainWebViewActivity.DOMAINS_CUSTOM_USER_AGENT);
741 // Hide the user agent TextView.
742 userAgentTextView.setVisibility(View.GONE);
744 // Show the custom user agent EditText and set the current user agent name as the text.
745 customUserAgentEditText.setVisibility(View.VISIBLE);
746 customUserAgentEditText.setText(currentUserAgentName);
747 } else { // The user agent name contains one of the canonical user agents.
748 // 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.
749 userAgentSpinner.setSelection(userAgentArrayPosition + 1);
751 // Show the user agent TextView.
752 userAgentTextView.setVisibility(View.VISIBLE);
754 // Hide the custom user agent EditText.
755 customUserAgentEditText.setVisibility(View.GONE);
757 // Set the user agent text.
758 if (userAgentArrayPosition == MainWebViewActivity.DOMAINS_WEBVIEW_DEFAULT_USER_AGENT) { // The WebView default user agent is selected.
759 // Display the WebView default user agent.
760 userAgentTextView.setText(webViewDefaultUserAgentString);
761 } else { // A user agent besides the default is selected.
762 // 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.
763 userAgentTextView.setText(userAgentDataArray[userAgentArrayPosition + 1]);
767 // Open the user agent spinner when the text view is clicked.
768 userAgentTextView.setOnClickListener((View v) -> {
769 // Open the user agent spinner.
770 userAgentSpinner.performClick();
773 // Display the font size settings.
774 if (fontSizeInt == 0) { // `0` is the code for system default font size.
775 // Set the font size to the system default
776 fontSizeSpinner.setSelection(0);
778 // Show the default font size text view.
779 defaultFontSizeTextView.setVisibility(View.VISIBLE);
781 // Hide the custom font size edit text.
782 customFontSizeEditText.setVisibility(View.GONE);
784 // 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.
785 customFontSizeEditText.setText(defaultFontSizeString);
786 } else { // A custom font size is selected.
787 // Set the spinner to the custom font size.
788 fontSizeSpinner.setSelection(1);
790 // Hide the default font size text view.
791 defaultFontSizeTextView.setVisibility(View.GONE);
793 // Show the custom font size edit text.
794 customFontSizeEditText.setVisibility(View.GONE);
796 // Set the custom font size.
797 customFontSizeEditText.setText(String.valueOf(fontSizeInt));
800 // Initialize the default font size percentage string.
801 String defaultFontSizePercentageString = defaultFontSizeString + "%";
803 // Set the default font size text in the text view.
804 defaultFontSizeTextView.setText(defaultFontSizePercentageString);
806 // Open the font size spinner when the text view is clicked.
807 defaultFontSizeTextView.setOnClickListener((View v) -> {
808 // Open the user agent spinner.
809 fontSizeSpinner.performClick();
812 // Display the swipe to refresh selection in the spinner.
813 swipeToRefreshSpinner.setSelection(swipeToRefreshInt);
815 // Set the swipe to refresh text.
816 if (defaultSwipeToRefresh) {
817 swipeToRefreshTextView.setText(swipeToRefreshArrayAdapter.getItem(DomainsDatabaseHelper.ENABLED));
819 swipeToRefreshTextView.setText(swipeToRefreshArrayAdapter.getItem(DomainsDatabaseHelper.DISABLED));
822 // 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.
823 switch (swipeToRefreshInt) {
824 case DomainsDatabaseHelper.SYSTEM_DEFAULT:
825 if (defaultSwipeToRefresh) { // Swipe to refresh is enabled by default.
826 // Set the icon according to the theme.
827 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
828 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_night));
830 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_day));
832 } else { // Swipe to refresh is disabled by default
833 // Set the icon according to the theme.
834 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
835 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_night));
837 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_day));
841 // Show the swipe to refresh TextView.
842 swipeToRefreshTextView.setVisibility(View.VISIBLE);
845 case DomainsDatabaseHelper.ENABLED:
846 // Set the icon according to the theme.
847 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
848 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_night));
850 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_day));
853 // Hide the swipe to refresh TextView.`
854 swipeToRefreshTextView.setVisibility(View.GONE);
857 case DomainsDatabaseHelper.DISABLED:
858 // Set the icon according to the theme.
859 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
860 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_night));
862 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_day));
865 // Hide the swipe to refresh TextView.
866 swipeToRefreshTextView.setVisibility(View.GONE);
869 // Open the swipe to refresh spinner when the TextView is clicked.
870 swipeToRefreshTextView.setOnClickListener((View v) -> {
871 // Open the swipe to refresh spinner.
872 swipeToRefreshSpinner.performClick();
875 // Display the night mode in the spinner.
876 nightModeSpinner.setSelection(nightModeInt);
878 // Set the default night mode text.
879 if (defaultNightMode) {
880 nightModeTextView.setText(nightModeArrayAdapter.getItem(DomainsDatabaseHelper.ENABLED));
882 nightModeTextView.setText(nightModeArrayAdapter.getItem(DomainsDatabaseHelper.DISABLED));
885 // Set the night mode icon and TextView settings. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
886 switch (nightModeInt) {
887 case DomainsDatabaseHelper.SYSTEM_DEFAULT:
888 if (defaultNightMode) { // Night mode enabled by default.
889 // Set the icon according to the theme.
890 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
891 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.webview_theme_enabled_night));
893 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.webview_theme_enabled_day));
895 } else { // Night mode disabled by default.
896 // Set the icon according to the theme.
897 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
898 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.webview_theme_disabled_night));
900 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.webview_theme_disabled_day));
904 // Show night mode TextView.
905 nightModeTextView.setVisibility(View.VISIBLE);
908 case DomainsDatabaseHelper.ENABLED:
909 // Set the icon according to the theme.
910 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
911 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.webview_theme_enabled_night));
913 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.webview_theme_enabled_day));
916 // Hide the night mode TextView.
917 nightModeTextView.setVisibility(View.GONE);
920 case DomainsDatabaseHelper.DISABLED:
921 // Set the icon according to the theme.
922 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
923 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.webview_theme_disabled_night));
925 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.webview_theme_disabled_day));
928 // Hide the night mode TextView.
929 nightModeTextView.setVisibility(View.GONE);
933 // Open the night mode spinner when the TextView is clicked.
934 nightModeTextView.setOnClickListener((View v) -> {
935 // Open the night mode spinner.
936 nightModeSpinner.performClick();
939 // Display the wide viewport in the spinner.
940 wideViewportSpinner.setSelection(wideViewportInt);
942 // Set the default wide viewport text.
943 if (defaultWideViewport) {
944 wideViewportTextView.setText(wideViewportArrayAdapter.getItem(DomainsDatabaseHelper.ENABLED));
946 wideViewportTextView.setText(wideViewportArrayAdapter.getItem(DomainsDatabaseHelper.DISABLED));
949 // 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.
950 switch (wideViewportInt) {
951 case DomainsDatabaseHelper.SYSTEM_DEFAULT:
952 if (defaultWideViewport) { // Wide viewport enabled by default.
953 // Set the icon according to the theme.
954 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
955 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_enabled_night));
957 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_enabled_day));
959 } else { // Wide viewport disabled by default.
960 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
961 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_disabled_night));
963 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_disabled_day));
967 // Show the wide viewport text view.
968 wideViewportTextView.setVisibility(View.VISIBLE);
971 case DomainsDatabaseHelper.ENABLED:
972 // Set the icon according to the theme.
973 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
974 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_enabled_night));
976 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_enabled_day));
979 // Hide the wide viewport text view.
980 wideViewportTextView.setVisibility(View.GONE);
983 case DomainsDatabaseHelper.DISABLED:
984 // Set the icon according to the theme.
985 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
986 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_disabled_night));
988 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_disabled_day));
991 // Hide the wide viewport text view.
992 wideViewportTextView.setVisibility(View.GONE);
996 // Open the wide viewport spinner when the text view is clicked.
997 wideViewportTextView.setOnClickListener((View view) -> {
998 // Open the wide viewport spinner.
999 wideViewportSpinner.performClick();
1002 // Display the website images mode in the spinner.
1003 displayWebpageImagesSpinner.setSelection(displayImagesInt);
1005 // Set the default display images text.
1006 if (defaultDisplayWebpageImages) {
1007 displayImagesTextView.setText(displayImagesArrayAdapter.getItem(DomainsDatabaseHelper.ENABLED));
1009 displayImagesTextView.setText(displayImagesArrayAdapter.getItem(DomainsDatabaseHelper.DISABLED));
1012 // 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.
1013 switch (displayImagesInt) {
1014 case DomainsDatabaseHelper.SYSTEM_DEFAULT:
1015 if (defaultDisplayWebpageImages) { // Display webpage images enabled by default.
1016 // Set the icon according to the theme.
1017 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1018 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_night));
1020 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_day));
1022 } else { // Display webpage images disabled by default.
1023 // Set the icon according to the theme.
1024 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1025 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_night));
1027 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_day));
1031 // Show the display images text view.
1032 displayImagesTextView.setVisibility(View.VISIBLE);
1035 case DomainsDatabaseHelper.ENABLED:
1036 // Set the icon according to the theme.
1037 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1038 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_night));
1040 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_day));
1043 // Hide the display images text view.
1044 displayImagesTextView.setVisibility(View.GONE);
1047 case DomainsDatabaseHelper.DISABLED:
1048 // Set the icon according to the theme.
1049 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1050 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_night));
1052 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_day));
1055 // Hide the display images text view.
1056 displayImagesTextView.setVisibility(View.GONE);
1060 // Open the display images spinner when the text view is clicked.
1061 displayImagesTextView.setOnClickListener((View view) -> {
1062 // Open the user agent spinner.
1063 displayWebpageImagesSpinner.performClick();
1066 // Set the pinned SSL certificate icon.
1067 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.
1068 // Check the switch.
1069 pinnedSslCertificateSwitch.setChecked(true);
1071 // Set the icon according to the theme.
1072 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1073 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_night));
1075 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_day));
1077 } else { // Pinned SSL certificate is disabled.
1078 // Uncheck the switch.
1079 pinnedSslCertificateSwitch.setChecked(false);
1081 // Set the icon according to the theme.
1082 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1083 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_night));
1085 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_day));
1089 // Store the current date.
1090 Date currentDate = Calendar.getInstance().getTime();
1092 // Setup the string builders to display the general certificate information in blue. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1093 savedSslIssuedToONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), savedSslIssuedToONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1094 savedSslIssuedToUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), savedSslIssuedToUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1095 savedSslIssuedByCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), savedSslIssuedByCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1096 savedSslIssuedByONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), savedSslIssuedByONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1097 savedSslIssuedByUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), savedSslIssuedByUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1099 // Check the certificate Common Name against the domain name.
1100 boolean savedSslCommonNameMatchesDomainName = checkDomainNameAgainstCertificate(domainNameString, savedSslIssuedToCNameString);
1102 // Format the issued to Common Name color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1103 if (savedSslCommonNameMatchesDomainName) {
1104 savedSslIssuedToCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), savedSslIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1106 savedSslIssuedToCNameStringBuilder.setSpan(redColorSpan, cNameLabel.length(), savedSslIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1109 // Format the start date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1110 if ((savedSslStartDate != null) && savedSslStartDate.after(currentDate)) { // The certificate start date is in the future.
1111 savedSslStartDateStringBuilder.setSpan(redColorSpan, startDateLabel.length(), savedSslStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1112 } else { // The certificate start date is in the past.
1113 savedSslStartDateStringBuilder.setSpan(blueColorSpan, startDateLabel.length(), savedSslStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1116 // Format the end date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1117 if ((savedSslEndDate != null) && savedSslEndDate.before(currentDate)) { // The certificate end date is in the past.
1118 savedSslEndDateStringBuilder.setSpan(redColorSpan, endDateLabel.length(), savedSslEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1119 } else { // The certificate end date is in the future.
1120 savedSslEndDateStringBuilder.setSpan(blueColorSpan, endDateLabel.length(), savedSslEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1123 // Display the saved website SSL certificate strings.
1124 savedSslIssuedToCNameTextView.setText(savedSslIssuedToCNameStringBuilder);
1125 savedSslIssuedToONameTextView.setText(savedSslIssuedToONameStringBuilder);
1126 savedSslIssuedToUNameTextView.setText(savedSslIssuedToUNameStringBuilder);
1127 savedSslIssuedByCNameTextView.setText(savedSslIssuedByCNameStringBuilder);
1128 savedSslIssuedByONameTextView.setText(savedSslIssuedByONameStringBuilder);
1129 savedSslIssuedByUNameTextView.setText(savedSslIssuedByUNameStringBuilder);
1130 savedSslStartDateTextView.setText(savedSslStartDateStringBuilder);
1131 savedSslEndDateTextView.setText(savedSslEndDateStringBuilder);
1133 // Populate the current website SSL certificate if there is one.
1134 if (DomainsActivity.sslIssuedToCName != null) {
1135 // Get dates from the raw long values.
1136 Date currentSslStartDate = new Date(DomainsActivity.sslStartDateLong);
1137 Date currentSslEndDate = new Date(DomainsActivity.sslEndDateLong);
1139 // Create a spannable string builder for each text view that needs multiple colors of text.
1140 SpannableStringBuilder currentSslIssuedToCNameStringBuilder = new SpannableStringBuilder(cNameLabel + DomainsActivity.sslIssuedToCName);
1141 SpannableStringBuilder currentSslIssuedToONameStringBuilder = new SpannableStringBuilder(oNameLabel + DomainsActivity.sslIssuedToOName);
1142 SpannableStringBuilder currentSslIssuedToUNameStringBuilder = new SpannableStringBuilder(uNameLabel + DomainsActivity.sslIssuedToUName);
1143 SpannableStringBuilder currentSslIssuedByCNameStringBuilder = new SpannableStringBuilder(cNameLabel + DomainsActivity.sslIssuedByCName);
1144 SpannableStringBuilder currentSslIssuedByONameStringBuilder = new SpannableStringBuilder(oNameLabel + DomainsActivity.sslIssuedByOName);
1145 SpannableStringBuilder currentSslIssuedByUNameStringBuilder = new SpannableStringBuilder(uNameLabel + DomainsActivity.sslIssuedByUName);
1146 SpannableStringBuilder currentSslStartDateStringBuilder = new SpannableStringBuilder(startDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG)
1147 .format(currentSslStartDate));
1148 SpannableStringBuilder currentSslEndDateStringBuilder = new SpannableStringBuilder(endDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG)
1149 .format(currentSslEndDate));
1151 // Setup the string builders to display the general certificate information in blue. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1152 currentSslIssuedToONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), currentSslIssuedToONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1153 currentSslIssuedToUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), currentSslIssuedToUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1154 currentSslIssuedByCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), currentSslIssuedByCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1155 currentSslIssuedByONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), currentSslIssuedByONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1156 currentSslIssuedByUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), currentSslIssuedByUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1158 // Check the certificate Common Name against the domain name.
1159 boolean currentSslCommonNameMatchesDomainName = checkDomainNameAgainstCertificate(domainNameString, DomainsActivity.sslIssuedToCName);
1161 // Format the issued to Common Name color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1162 if (currentSslCommonNameMatchesDomainName) {
1163 currentSslIssuedToCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), currentSslIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1165 currentSslIssuedToCNameStringBuilder.setSpan(redColorSpan, cNameLabel.length(), currentSslIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1168 // Format the start date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1169 if (currentSslStartDate.after(currentDate)) { // The certificate start date is in the future.
1170 currentSslStartDateStringBuilder.setSpan(redColorSpan, startDateLabel.length(), currentSslStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1171 } else { // The certificate start date is in the past.
1172 currentSslStartDateStringBuilder.setSpan(blueColorSpan, startDateLabel.length(), currentSslStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1175 // Format the end date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1176 if (currentSslEndDate.before(currentDate)) { // The certificate end date is in the past.
1177 currentSslEndDateStringBuilder.setSpan(redColorSpan, endDateLabel.length(), currentSslEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1178 } else { // The certificate end date is in the future.
1179 currentSslEndDateStringBuilder.setSpan(blueColorSpan, endDateLabel.length(), currentSslEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1182 // Display the current website SSL certificate strings.
1183 currentSslIssuedToCNameTextView.setText(currentSslIssuedToCNameStringBuilder);
1184 currentSslIssuedToONameTextView.setText(currentSslIssuedToONameStringBuilder);
1185 currentSslIssuedToUNameTextView.setText(currentSslIssuedToUNameStringBuilder);
1186 currentSslIssuedByCNameTextView.setText(currentSslIssuedByCNameStringBuilder);
1187 currentSslIssuedByONameTextView.setText(currentSslIssuedByONameStringBuilder);
1188 currentSslIssuedByUNameTextView.setText(currentSslIssuedByUNameStringBuilder);
1189 currentSslStartDateTextView.setText(currentSslStartDateStringBuilder);
1190 currentSslEndDateTextView.setText(currentSslEndDateStringBuilder);
1193 // Set the initial display status of the SSL certificates card views.
1194 if (pinnedSslCertificateSwitch.isChecked()) { // An SSL certificate is pinned.
1195 // Set the visibility of the saved SSL certificate.
1196 if (savedSslIssuedToCNameString == null) {
1197 savedSslCardView.setVisibility(View.GONE);
1199 savedSslCardView.setVisibility(View.VISIBLE);
1202 // Set the visibility of the current website SSL certificate.
1203 if (DomainsActivity.sslIssuedToCName == null) { // There is no current SSL certificate.
1204 // Hide the SSL certificate.
1205 currentSslCardView.setVisibility(View.GONE);
1207 // Show the instruction.
1208 noCurrentWebsiteCertificateTextView.setVisibility(View.VISIBLE);
1209 } else { // There is a current SSL certificate.
1210 // Show the SSL certificate.
1211 currentSslCardView.setVisibility(View.VISIBLE);
1213 // Hide the instruction.
1214 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
1217 // Set the status of the radio buttons and the card view backgrounds.
1218 if (savedSslCardView.getVisibility() == View.VISIBLE) { // The saved SSL certificate is displayed.
1219 // Check the saved SSL certificate radio button.
1220 savedSslCertificateRadioButton.setChecked(true);
1222 // Uncheck the current website SSL certificate radio button.
1223 currentWebsiteCertificateRadioButton.setChecked(false);
1225 // Darken the background of the current website SSL certificate linear layout according to the theme.
1226 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1227 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
1229 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
1231 } else if (currentSslCardView.getVisibility() == View.VISIBLE) { // The saved SSL certificate is hidden but the current website SSL certificate is visible.
1232 // Check the current website SSL certificate radio button.
1233 currentWebsiteCertificateRadioButton.setChecked(true);
1235 // Uncheck the saved SSL certificate radio button.
1236 savedSslCertificateRadioButton.setChecked(false);
1237 } else { // Neither SSL certificate is visible.
1238 // Uncheck both radio buttons.
1239 savedSslCertificateRadioButton.setChecked(false);
1240 currentWebsiteCertificateRadioButton.setChecked(false);
1242 } else { // An SSL certificate is not pinned.
1243 // Hide the SSl certificates and instructions.
1244 savedSslCardView.setVisibility(View.GONE);
1245 currentSslCardView.setVisibility(View.GONE);
1246 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
1248 // Uncheck the radio buttons.
1249 savedSslCertificateRadioButton.setChecked(false);
1250 currentWebsiteCertificateRadioButton.setChecked(false);
1253 // Set the pinned IP addresses icon.
1254 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.
1255 // Check the switch.
1256 pinnedIpAddressesSwitch.setChecked(true);
1258 // Set the icon according to the theme.
1259 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1260 pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_night));
1262 pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_day));
1264 } else { // Pinned IP Addresses is disabled.
1265 // Uncheck the switch.
1266 pinnedIpAddressesSwitch.setChecked(false);
1268 // Set the icon according to the theme.
1269 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1270 pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_night));
1272 pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_day));
1276 // Populate the saved and current IP addresses.
1277 savedIpAddressesTextView.setText(savedIpAddresses);
1278 currentIpAddressesTextView.setText(DomainsActivity.currentIpAddresses);
1280 // Set the initial display status of the IP addresses card views.
1281 if (pinnedIpAddressesSwitch.isChecked()) { // IP addresses are pinned.
1282 // Set the visibility of the saved IP addresses.
1283 if (savedIpAddresses == null) { // There are no saved IP addresses.
1284 savedIpAddressesCardView.setVisibility(View.GONE);
1285 } else { // There are saved IP addresses.
1286 savedIpAddressesCardView.setVisibility(View.VISIBLE);
1289 // Set the visibility of the current IP addresses.
1290 currentIpAddressesCardView.setVisibility(View.VISIBLE);
1292 // Set the status of the radio buttons and the card view backgrounds.
1293 if (savedIpAddressesCardView.getVisibility() == View.VISIBLE) { // The saved IP addresses are displayed.
1294 // Check the saved IP addresses radio button.
1295 savedIpAddressesRadioButton.setChecked(true);
1297 // Uncheck the current IP addresses radio button.
1298 currentIpAddressesRadioButton.setChecked(false);
1300 // Darken the background of the current IP addresses linear layout according to the theme.
1301 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1302 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
1304 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
1306 } else { // The saved IP addresses are hidden.
1307 // Check the current IP addresses radio button.
1308 currentIpAddressesRadioButton.setChecked(true);
1310 // Uncheck the saved IP addresses radio button.
1311 savedIpAddressesRadioButton.setChecked(false);
1313 } else { // IP addresses are not pinned.
1314 // Hide the IP addresses card views.
1315 savedIpAddressesCardView.setVisibility(View.GONE);
1316 currentIpAddressesCardView.setVisibility(View.GONE);
1318 // Uncheck the radio buttons.
1319 savedIpAddressesRadioButton.setChecked(false);
1320 currentIpAddressesRadioButton.setChecked(false);
1324 // Set the JavaScript switch listener.
1325 javaScriptSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1326 if (isChecked) { // JavaScript is enabled.
1327 // Update the JavaScript icon.
1328 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.javascript_enabled));
1330 // Enable the DOM storage `Switch`.
1331 domStorageSwitch.setEnabled(true);
1333 // Update the DOM storage icon.
1334 if (domStorageSwitch.isChecked()) { // DOM storage is enabled.
1335 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_enabled));
1336 } else { // DOM storage is disabled.
1337 // Set the icon according to the theme.
1338 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1339 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_night));
1341 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_day));
1344 } else { // JavaScript is disabled.
1345 // Update the JavaScript icon.
1346 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.privacy_mode));
1348 // Disable the DOM storage `Switch`.
1349 domStorageSwitch.setEnabled(false);
1351 // Set the DOM storage icon according to the theme.
1352 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1353 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_night));
1355 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_day));
1360 // Set the first-party cookies switch listener.
1361 firstPartyCookiesSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1362 if (isChecked) { // First-party cookies are enabled.
1363 // Update the first-party cookies icon.
1364 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_enabled));
1366 // Enable the third-party cookies switch.
1367 thirdPartyCookiesSwitch.setEnabled(true);
1369 // Update the third-party cookies icon.
1370 if (thirdPartyCookiesSwitch.isChecked()) { // Third-party cookies are enabled.
1371 // Set the third-party cookies icon to be red.
1372 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_warning));
1373 } else { // Third-party cookies are disabled.
1374 // Set the third-party cookies icon according to the theme.
1375 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1376 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_night));
1378 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_day));
1381 } else { // First-party cookies are disabled.
1382 // Update the first-party cookies icon according to the theme.
1383 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1384 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_night));
1386 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_day));
1389 // Disable the third-party cookies switch.
1390 thirdPartyCookiesSwitch.setEnabled(false);
1392 // Set the third-party cookies icon according to the theme.
1393 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1394 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_ghosted_night));
1396 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_ghosted_day));
1401 // Set the third-party cookies switch listener.
1402 thirdPartyCookiesSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1405 // Set the third-party cookies icon to be red.
1406 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_warning));
1408 // Update the third-party cookies icon according to the theme.
1409 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1410 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_night));
1412 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_day));
1417 // Set the DOM Storage switch listener.
1418 domStorageSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1421 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_enabled));
1423 // Set the icon according to the theme.
1424 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1425 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_night));
1427 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_day));
1432 // Set the form data switch listener. It can be removed once the minimum API >= 26.
1433 if (Build.VERSION.SDK_INT < 26) {
1434 formDataSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1437 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_enabled));
1439 // Set the icon according to the theme.
1440 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1441 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_disabled_night));
1443 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_disabled_day));
1449 // Set the EasyList switch listener.
1450 easyListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1452 if (isChecked) { // EasyList is on.
1453 // Set the icon according to the theme.
1454 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1455 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_night));
1457 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_day));
1459 } else { // EasyList is off.
1460 // Set the icon according to the theme.
1461 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1462 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_night));
1464 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_day));
1469 // Set the EasyPrivacy switch listener.
1470 easyPrivacySwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1472 if (isChecked) { // EasyPrivacy is on.
1473 // Set the icon according to the theme.
1474 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1475 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_night));
1477 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_day));
1479 } else { // EasyPrivacy is off.
1480 // Set the icon according to the theme.
1481 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1482 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_night));
1484 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_day));
1489 // Set the Fanboy's Annoyance List switch listener.
1490 fanboysAnnoyanceListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1491 // Update the icon and Fanboy's Social Blocking List.
1492 if (isChecked) { // Fanboy's Annoyance List is on.
1493 // Set the icon according to the theme.
1494 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1495 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_night));
1497 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_day));
1500 // Disable the Fanboy's Social Blocking List switch.
1501 fanboysSocialBlockingListSwitch.setEnabled(false);
1503 // Update the Fanboy's Social Blocking List icon according to the theme.
1504 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1505 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_ghosted_night));
1507 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_ghosted_day));
1509 } else { // Fanboy's Annoyance List is off.
1510 // Set the icon according to the theme.
1511 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1512 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_night));
1514 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_day));
1517 // Enable the Fanboy's Social Blocking List switch.
1518 fanboysSocialBlockingListSwitch.setEnabled(true);
1520 // Update the Fanboy's Social Blocking List icon.
1521 if (fanboysSocialBlockingListSwitch.isChecked()) { // Fanboy's Social Blocking List is on.
1522 // Update the icon according to the theme.
1523 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1524 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_night));
1526 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_day));
1528 } else { // Fanboy's Social Blocking List is off.
1529 // Update the icon according to the theme.
1530 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1531 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_night));
1533 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_day));
1540 // Set the Fanboy's Social Blocking List switch listener.
1541 fanboysSocialBlockingListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1543 if (isChecked) { // Fanboy's Social Blocking List is on.
1544 // Set the icon according to the theme.
1545 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1546 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_night));
1548 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_day));
1550 } else { // Fanboy's Social Blocking List is off.
1551 // Set the icon according to the theme.
1552 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1553 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_night));
1555 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_day));
1560 // Set the UltraList switch listener.
1561 ultraListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1563 if (isChecked) { // UltraList is on.
1564 // Set the icon according to the theme.
1565 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1566 ultraListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_night));
1568 ultraListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_day));
1570 } else { // UltraList is off.
1571 // Set the icon according to the theme.
1572 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1573 ultraListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_night));
1575 ultraListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_day));
1580 // Set the UltraPrivacy switch listener.
1581 ultraPrivacySwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1583 if (isChecked) { // UltraPrivacy is on.
1584 // Set the icon according to the theme.
1585 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1586 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_night));
1588 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_day));
1590 } else { // UltraPrivacy is off.
1591 // Set the icon according to the theme.
1592 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1593 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_night));
1595 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_day));
1600 // Set the block all third-party requests switch listener.
1601 blockAllThirdPartyRequestsSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1603 if (isChecked) { // Blocking all third-party requests is on.
1604 // Set the icon according to the theme.
1605 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1606 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_enabled_night));
1608 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_enabled_day));
1610 } else { // Blocking all third-party requests is off.
1611 // Set the icon according to the theme.
1612 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1613 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_disabled_night));
1615 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_disabled_day));
1620 // Set the user agent spinner listener.
1621 userAgentSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1623 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1624 // Set the new user agent.
1626 case MainWebViewActivity.DOMAINS_SYSTEM_DEFAULT_USER_AGENT:
1627 // Show the user agent TextView.
1628 userAgentTextView.setVisibility(View.VISIBLE);
1630 // Hide the custom user agent EditText.
1631 customUserAgentEditText.setVisibility(View.GONE);
1633 // Set the user text.
1634 switch (defaultUserAgentArrayPosition) {
1635 case MainWebViewActivity.UNRECOGNIZED_USER_AGENT: // The default user agent name is not on the canonical list.
1636 // This is probably because it was set in an older version of Privacy Browser before the switch to persistent user agent names.
1637 userAgentTextView.setText(defaultUserAgentName);
1640 case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
1641 // Display the `WebView` default user agent.
1642 userAgentTextView.setText(webViewDefaultUserAgentString);
1645 case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
1646 // Display the custom user agent.
1647 userAgentTextView.setText(defaultCustomUserAgentString);
1651 // Get the user agent string from the user agent data array.
1652 userAgentTextView.setText(userAgentDataArray[defaultUserAgentArrayPosition]);
1656 case MainWebViewActivity.DOMAINS_WEBVIEW_DEFAULT_USER_AGENT:
1657 // Show the user agent TextView and set the text.
1658 userAgentTextView.setVisibility(View.VISIBLE);
1659 userAgentTextView.setText(webViewDefaultUserAgentString);
1661 // Hide the custom user agent EditTex.
1662 customUserAgentEditText.setVisibility(View.GONE);
1665 case MainWebViewActivity.DOMAINS_CUSTOM_USER_AGENT:
1666 // Hide the user agent TextView.
1667 userAgentTextView.setVisibility(View.GONE);
1669 // Show the custom user agent EditText and set the current user agent name as the text.
1670 customUserAgentEditText.setVisibility(View.VISIBLE);
1671 customUserAgentEditText.setText(currentUserAgentName);
1675 // 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.
1676 userAgentTextView.setVisibility(View.VISIBLE);
1677 userAgentTextView.setText(userAgentDataArray[position - 1]);
1679 // Hide `customUserAgentEditText`.
1680 customUserAgentEditText.setVisibility(View.GONE);
1685 public void onNothingSelected(AdapterView<?> parent) {
1690 // Set the font size spinner listener.
1691 fontSizeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1693 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1694 // Update the font size display options.
1695 if (position == 0) { // The system default font size has been selected.
1696 // Show the default font size text view.
1697 defaultFontSizeTextView.setVisibility(View.VISIBLE);
1699 // Hide the custom font size edit text.
1700 customFontSizeEditText.setVisibility(View.GONE);
1701 } else { // A custom font size has been selected.
1702 // Hide the default font size text view.
1703 defaultFontSizeTextView.setVisibility(View.GONE);
1705 // Show the custom font size edit text.
1706 customFontSizeEditText.setVisibility(View.VISIBLE);
1711 public void onNothingSelected(AdapterView<?> parent) {
1716 // Set the swipe to refresh spinner listener.
1717 swipeToRefreshSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1719 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1720 // 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.
1722 case DomainsDatabaseHelper.SYSTEM_DEFAULT:
1723 if (defaultSwipeToRefresh) { // Swipe to refresh enabled by default.
1724 // Set the icon according to the theme.
1725 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1726 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_night));
1728 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_day));
1730 } else { // Swipe to refresh disabled by default.
1731 // Set the icon according to the theme.
1732 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1733 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_night));
1735 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_day));
1739 // Show the swipe to refresh TextView.
1740 swipeToRefreshTextView.setVisibility(View.VISIBLE);
1743 case DomainsDatabaseHelper.ENABLED:
1744 // Set the icon according to the theme.
1745 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1746 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_night));
1748 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_day));
1751 // Hide the swipe to refresh TextView.
1752 swipeToRefreshTextView.setVisibility(View.GONE);
1755 case DomainsDatabaseHelper.DISABLED:
1756 // Set the icon according to the theme.
1757 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1758 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_night));
1760 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_day));
1763 // Hide the swipe to refresh TextView.
1764 swipeToRefreshTextView.setVisibility(View.GONE);
1769 public void onNothingSelected(AdapterView<?> parent) {
1774 // Set the night mode spinner listener.
1775 nightModeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1777 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1778 // 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.
1780 case DomainsDatabaseHelper.SYSTEM_DEFAULT:
1781 if (defaultNightMode) { // Night mode enabled by default.
1782 // Set the icon according to the theme.
1783 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1784 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.webview_theme_enabled_night));
1786 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.webview_theme_enabled_day));
1788 } else { // Night mode disabled by default.
1789 // Set the icon according to the theme.
1790 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1791 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.webview_theme_disabled_night));
1793 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.webview_theme_disabled_day));
1797 // Show the night mode TextView.
1798 nightModeTextView.setVisibility(View.VISIBLE);
1801 case DomainsDatabaseHelper.ENABLED:
1802 // Set the icon according to the theme.
1803 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1804 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.webview_theme_enabled_night));
1806 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.webview_theme_enabled_day));
1809 // Hide `nightModeTextView`.
1810 nightModeTextView.setVisibility(View.GONE);
1813 case DomainsDatabaseHelper.DISABLED:
1814 // Set the icon according to the theme.
1815 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1816 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.webview_theme_disabled_night));
1818 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.webview_theme_disabled_day));
1821 // Hide `nightModeTextView`.
1822 nightModeTextView.setVisibility(View.GONE);
1826 // Create a boolean to store the current night mode setting.
1827 boolean currentNightModeEnabled = (position == DomainsDatabaseHelper.ENABLED) || ((position == DomainsDatabaseHelper.SYSTEM_DEFAULT) && defaultNightMode);
1829 // Disable the JavaScript switch if night mode is enabled.
1830 if (currentNightModeEnabled) {
1831 javaScriptSwitch.setEnabled(false);
1833 javaScriptSwitch.setEnabled(true);
1836 // Update the JavaScript icon.
1837 if ((javaScriptInt == 1) || currentNightModeEnabled) {
1838 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.javascript_enabled));
1840 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.privacy_mode));
1843 // Update the DOM storage status.
1844 if ((javaScriptInt == 1) || currentNightModeEnabled) { // JavaScript is enabled.
1845 // Enable the DOM storage `Switch`.
1846 domStorageSwitch.setEnabled(true);
1848 // Set the DOM storage status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
1849 if (domStorageInt == 1) { // Both JavaScript and DOM storage are enabled.
1850 domStorageSwitch.setChecked(true);
1851 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_enabled));
1852 } else { // JavaScript is enabled but DOM storage is disabled.
1853 // Set the DOM storage switch to off.
1854 domStorageSwitch.setChecked(false);
1856 // Set the icon according to the theme.
1857 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1858 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_night));
1860 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_day));
1863 } else { // JavaScript is disabled.
1864 // Disable the DOM storage `Switch`.
1865 domStorageSwitch.setEnabled(false);
1867 // Set the checked status of DOM storage.
1868 if (domStorageInt == 1) { // DOM storage is enabled but JavaScript is disabled.
1869 domStorageSwitch.setChecked(true);
1870 } else { // Both JavaScript and DOM storage are disabled.
1871 domStorageSwitch.setChecked(false);
1874 // Set the icon according to the theme.
1875 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1876 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_night));
1878 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_day));
1884 public void onNothingSelected(AdapterView<?> parent) {
1889 // Set the wide viewport spinner listener.
1890 wideViewportSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1892 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1893 // Update the icon and the visibility of the wide viewport text view.
1895 case DomainsDatabaseHelper.SYSTEM_DEFAULT:
1896 if (defaultWideViewport) { // Wide viewport is enabled by default.
1897 // Set the icon according to the theme.
1898 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1899 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_enabled_night));
1901 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_enabled_day));
1903 } else { // Wide viewport is disabled by default.
1904 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1905 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_disabled_night));
1907 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_disabled_day));
1911 // Show the wide viewport text view.
1912 wideViewportTextView.setVisibility(View.VISIBLE);
1915 case DomainsDatabaseHelper.ENABLED:
1916 // Set the icon according to the theme.
1917 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1918 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_enabled_night));
1920 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_enabled_day));
1923 // Hide the wide viewport text view.
1924 wideViewportTextView.setVisibility(View.GONE);
1927 case DomainsDatabaseHelper.DISABLED:
1928 // Set the icon according to the theme.
1929 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1930 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_disabled_night));
1932 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_disabled_day));
1935 // Hid ethe wide viewport text view.
1936 wideViewportTextView.setVisibility(View.GONE);
1942 public void onNothingSelected(AdapterView<?> parent) {
1947 // Set the display webpage images spinner listener.
1948 displayWebpageImagesSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1950 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1951 // Update the icon and the visibility of the display images text view.
1953 case DomainsDatabaseHelper.SYSTEM_DEFAULT:
1954 if (defaultDisplayWebpageImages) { // Display webpage images is enabled by default.
1955 // Set the icon according to the theme.
1956 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1957 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_night));
1959 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_day));
1961 } else { // Display webpage images is disabled by default.
1962 // Set the icon according to the theme.
1963 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1964 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_night));
1966 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_day));
1970 // Show the display images text view.
1971 displayImagesTextView.setVisibility(View.VISIBLE);
1974 case DomainsDatabaseHelper.ENABLED:
1975 // Set the icon according to the theme.
1976 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1977 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_night));
1979 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_day));
1982 // Hide the display images text view.
1983 displayImagesTextView.setVisibility(View.GONE);
1986 case DomainsDatabaseHelper.DISABLED:
1987 // Set the icon according to the theme.
1988 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1989 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_night));
1991 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_day));
1994 // Hide the display images text view.
1995 displayImagesTextView.setVisibility(View.GONE);
2001 public void onNothingSelected(AdapterView<?> parent) {
2006 // Set the pinned SSL certificate switch listener.
2007 pinnedSslCertificateSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
2009 if (isChecked) { // SSL certificate pinning is enabled.
2010 // Set the icon according to the theme.
2011 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2012 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_night));
2014 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_day));
2017 // Update the visibility of the saved SSL certificate.
2018 if (savedSslIssuedToCNameString == null) {
2019 savedSslCardView.setVisibility(View.GONE);
2021 savedSslCardView.setVisibility(View.VISIBLE);
2024 // Update the visibility of the current website SSL certificate.
2025 if (DomainsActivity.sslIssuedToCName == null) {
2026 // Hide the SSL certificate.
2027 currentSslCardView.setVisibility(View.GONE);
2029 // Show the instruction.
2030 noCurrentWebsiteCertificateTextView.setVisibility(View.VISIBLE);
2032 // Show the SSL certificate.
2033 currentSslCardView.setVisibility(View.VISIBLE);
2035 // Hide the instruction.
2036 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
2039 // Set the status of the radio buttons.
2040 if (savedSslCardView.getVisibility() == View.VISIBLE) { // The saved SSL certificate is displayed.
2041 // Check the saved SSL certificate radio button.
2042 savedSslCertificateRadioButton.setChecked(true);
2044 // Uncheck the current website SSL certificate radio button.
2045 currentWebsiteCertificateRadioButton.setChecked(false);
2047 // Set the background of the saved SSL certificate linear layout to be transparent.
2048 savedSslCertificateLinearLayout.setBackgroundResource(R.color.transparent);
2050 // Darken the background of the current website SSL certificate linear layout according to the theme.
2051 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2052 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2054 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2057 // Scroll to the current website SSL certificate card.
2058 savedSslCardView.getParent().requestChildFocus(savedSslCardView, savedSslCardView);
2059 } else if (currentSslCardView.getVisibility() == View.VISIBLE) { // The saved SSL certificate is hidden but the current website SSL certificate is visible.
2060 // Check the current website SSL certificate radio button.
2061 currentWebsiteCertificateRadioButton.setChecked(true);
2063 // Uncheck the saved SSL certificate radio button.
2064 savedSslCertificateRadioButton.setChecked(false);
2066 // Set the background of the current website SSL certificate linear layout to be transparent.
2067 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.transparent);
2069 // Darken the background of the saved SSL certificate linear layout according to the theme.
2070 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2071 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2073 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2076 // Scroll to the current website SSL certificate card.
2077 currentSslCardView.getParent().requestChildFocus(currentSslCardView, currentSslCardView);
2078 } else { // Neither SSL certificate is visible.
2079 // Uncheck both radio buttons.
2080 savedSslCertificateRadioButton.setChecked(false);
2081 currentWebsiteCertificateRadioButton.setChecked(false);
2083 // Scroll to the current website SSL certificate card.
2084 noCurrentWebsiteCertificateTextView.getParent().requestChildFocus(noCurrentWebsiteCertificateTextView, noCurrentWebsiteCertificateTextView);
2086 } else { // SSL certificate pinning is disabled.
2087 // Set the icon according to the theme.
2088 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2089 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_night));
2091 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_day));
2094 // Hide the SSl certificates and instructions.
2095 savedSslCardView.setVisibility(View.GONE);
2096 currentSslCardView.setVisibility(View.GONE);
2097 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
2099 // Uncheck the radio buttons.
2100 savedSslCertificateRadioButton.setChecked(false);
2101 currentWebsiteCertificateRadioButton.setChecked(false);
2105 savedSslCardView.setOnClickListener((View view) -> {
2106 // Check the saved SSL certificate radio button.
2107 savedSslCertificateRadioButton.setChecked(true);
2109 // Uncheck the current website SSL certificate radio button.
2110 currentWebsiteCertificateRadioButton.setChecked(false);
2112 // Set the background of the saved SSL certificate linear layout to be transparent.
2113 savedSslCertificateLinearLayout.setBackgroundResource(R.color.transparent);
2115 // Darken the background of the current website SSL certificate linear layout according to the theme.
2116 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2117 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2119 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2123 savedSslCertificateRadioButton.setOnClickListener((View view) -> {
2124 // Check the saved SSL certificate radio button.
2125 savedSslCertificateRadioButton.setChecked(true);
2127 // Uncheck the current website SSL certificate radio button.
2128 currentWebsiteCertificateRadioButton.setChecked(false);
2130 // Set the background of the saved SSL certificate linear layout to be transparent.
2131 savedSslCertificateLinearLayout.setBackgroundResource(R.color.transparent);
2133 // Darken the background of the current website SSL certificate linear layout according to the theme.
2134 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2135 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2137 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2141 currentSslCardView.setOnClickListener((View view) -> {
2142 // Check the current website SSL certificate radio button.
2143 currentWebsiteCertificateRadioButton.setChecked(true);
2145 // Uncheck the saved SSL certificate radio button.
2146 savedSslCertificateRadioButton.setChecked(false);
2148 // Set the background of the current website SSL certificate linear layout to be transparent.
2149 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.transparent);
2151 // Darken the background of the saved SSL certificate linear layout according to the theme.
2152 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2153 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2155 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2159 currentWebsiteCertificateRadioButton.setOnClickListener((View view) -> {
2160 // Check the current website SSL certificate radio button.
2161 currentWebsiteCertificateRadioButton.setChecked(true);
2163 // Uncheck the saved SSL certificate radio button.
2164 savedSslCertificateRadioButton.setChecked(false);
2166 // Set the background of the current website SSL certificate linear layout to be transparent.
2167 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.transparent);
2169 // Darken the background of the saved SSL certificate linear layout according to the theme.
2170 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2171 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2173 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2177 // Set the pinned IP addresses switch listener.
2178 pinnedIpAddressesSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
2180 if (isChecked) { // IP addresses pinning is enabled.
2181 // Set the icon according to the theme.
2182 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2183 pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_night));
2185 pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_day));
2188 // Update the visibility of the saved IP addresses card view.
2189 if (savedIpAddresses == null) { // There are no saved IP addresses.
2190 savedIpAddressesCardView.setVisibility(View.GONE);
2191 } else { // There are saved IP addresses.
2192 savedIpAddressesCardView.setVisibility(View.VISIBLE);
2195 // Show the current IP addresses card view.
2196 currentIpAddressesCardView.setVisibility(View.VISIBLE);
2198 // Set the status of the radio buttons.
2199 if (savedIpAddressesCardView.getVisibility() == View.VISIBLE) { // The saved IP addresses are visible.
2200 // Check the saved IP addresses radio button.
2201 savedIpAddressesRadioButton.setChecked(true);
2203 // Uncheck the current IP addresses radio button.
2204 currentIpAddressesRadioButton.setChecked(false);
2206 // Set the background of the saved IP addresses linear layout to be transparent.
2207 savedSslCertificateLinearLayout.setBackgroundResource(R.color.transparent);
2209 // Darken the background of the current IP addresses linear layout according to the theme.
2210 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2211 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2213 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2215 } else { // The saved IP addresses are not visible.
2216 // Check the current IP addresses radio button.
2217 currentIpAddressesRadioButton.setChecked(true);
2219 // Uncheck the saved IP addresses radio button.
2220 savedIpAddressesRadioButton.setChecked(false);
2222 // Set the background of the current IP addresses linear layout to be transparent.
2223 currentIpAddressesLinearLayout.setBackgroundResource(R.color.transparent);
2225 // Darken the background of the saved IP addresses linear layout according to the theme.
2226 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2227 savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2229 savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2233 // Scroll to the bottom of the card views.
2234 currentIpAddressesCardView.getParent().requestChildFocus(currentIpAddressesCardView, currentIpAddressesCardView);
2235 } else { // IP addresses pinning is disabled.
2236 // Set the icon according to the theme.
2237 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2238 pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_night));
2240 pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_day));
2243 // Hide the IP addresses card views.
2244 savedIpAddressesCardView.setVisibility(View.GONE);
2245 currentIpAddressesCardView.setVisibility(View.GONE);
2247 // Uncheck the radio buttons.
2248 savedIpAddressesRadioButton.setChecked(false);
2249 currentIpAddressesRadioButton.setChecked(false);
2253 savedIpAddressesCardView.setOnClickListener((View view) -> {
2254 // Check the saved IP addresses radio button.
2255 savedIpAddressesRadioButton.setChecked(true);
2257 // Uncheck the current website IP addresses radio button.
2258 currentIpAddressesRadioButton.setChecked(false);
2260 // Set the background of the saved IP addresses linear layout to be transparent.
2261 savedIpAddressesLinearLayout.setBackgroundResource(R.color.transparent);
2263 // Darken the background of the current IP addresses linear layout according to the theme.
2264 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2265 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2267 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2271 savedIpAddressesRadioButton.setOnClickListener((View view) -> {
2272 // Check the saved IP addresses radio button.
2273 savedIpAddressesRadioButton.setChecked(true);
2275 // Uncheck the current website IP addresses radio button.
2276 currentIpAddressesRadioButton.setChecked(false);
2278 // Set the background of the saved IP addresses linear layout to be transparent.
2279 savedIpAddressesLinearLayout.setBackgroundResource(R.color.transparent);
2281 // Darken the background of the current IP addresses linear layout according to the theme.
2282 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2283 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2285 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2289 currentIpAddressesCardView.setOnClickListener((View view) -> {
2290 // Check the current IP addresses radio button.
2291 currentIpAddressesRadioButton.setChecked(true);
2293 // Uncheck the saved IP addresses radio button.
2294 savedIpAddressesRadioButton.setChecked(false);
2296 // Set the background of the current IP addresses linear layout to be transparent.
2297 currentIpAddressesLinearLayout.setBackgroundResource(R.color.transparent);
2299 // Darken the background of the saved IP addresses linear layout according to the theme.
2300 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2301 savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2303 savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2307 currentIpAddressesRadioButton.setOnClickListener((View view) -> {
2308 // Check the current IP addresses radio button.
2309 currentIpAddressesRadioButton.setChecked(true);
2311 // Uncheck the saved IP addresses radio button.
2312 savedIpAddressesRadioButton.setChecked(false);
2314 // Set the background of the current IP addresses linear layout to be transparent.
2315 currentIpAddressesLinearLayout.setBackgroundResource(R.color.transparent);
2317 // Darken the background of the saved IP addresses linear layout according to the theme.
2318 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2319 savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2321 savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2325 return domainSettingsView;
2328 private boolean checkDomainNameAgainstCertificate(String domainName, String certificateCommonName) {
2329 // Initialize `domainNamesMatch`.
2330 boolean domainNamesMatch = false;
2332 // Check various wildcard permutations if `domainName` and `certificateCommonName` are not empty.
2333 // `noinspection ConstantCondition` removes Android Studio's incorrect lint warning that `domainName` can never be `null`.
2334 if ((domainName != null) && (certificateCommonName != null)) {
2335 // Check if the domains match.
2336 if (domainName.equals(certificateCommonName)) {
2337 domainNamesMatch = true;
2340 // If `domainName` starts with a wildcard, check the base domain against all the subdomains of `certificateCommonName`.
2341 if (!domainNamesMatch && domainName.startsWith("*.") && (domainName.length() > 2)) {
2342 // Remove the initial `*.`.
2343 String baseDomainName = domainName.substring(2);
2345 // Setup a copy of `certificateCommonName` to test subdomains.
2346 String certificateCommonNameSubdomain = certificateCommonName;
2348 // Check all the subdomains in `certificateCommonNameSubdomain` against `baseDomainName`.
2349 while (!domainNamesMatch && certificateCommonNameSubdomain.contains(".")) { // Stop checking if we know that `domainNamesMatch` is `true` or if we run out of `.`.
2350 // Test the `certificateCommonNameSubdomain` against `baseDomainName`.
2351 if (certificateCommonNameSubdomain.equals(baseDomainName)) {
2352 domainNamesMatch = true;
2355 // Strip out the lowest subdomain of `certificateCommonNameSubdomain`.
2357 certificateCommonNameSubdomain = certificateCommonNameSubdomain.substring(certificateCommonNameSubdomain.indexOf(".") + 1);
2358 } catch (IndexOutOfBoundsException e) { // `certificateCommonNameSubdomain` ends with `.`.
2359 certificateCommonNameSubdomain = "";
2364 // If `certificateCommonName` starts with a wildcard, check the base common name against all the subdomains of `domainName`.
2365 if (!domainNamesMatch && certificateCommonName.startsWith("*.") && (certificateCommonName.length() > 2)) {
2366 // Remove the initial `*.`.
2367 String baseCertificateCommonName = certificateCommonName.substring(2);
2369 // Setup a copy of `domainName` to test subdomains.
2370 String domainNameSubdomain = domainName;
2372 // Check all the subdomains in `domainNameSubdomain` against `baseCertificateCommonName`.
2373 while (!domainNamesMatch && domainNameSubdomain.contains(".") && (domainNameSubdomain.length() > 2)) {
2374 // Test the `domainNameSubdomain` against `baseCertificateCommonName`.
2375 if (domainNameSubdomain.equals(baseCertificateCommonName)) {
2376 domainNamesMatch = true;
2379 // Strip out the lowest subdomain of `domainNameSubdomain`.
2381 domainNameSubdomain = domainNameSubdomain.substring(domainNameSubdomain.indexOf(".") + 1);
2382 } catch (IndexOutOfBoundsException e) { // `domainNameSubdomain` ends with `.`.
2383 domainNameSubdomain = "";
2388 // If both names start with a wildcard, check if the root of one contains the root of the other.
2389 if (!domainNamesMatch && domainName.startsWith("*.") && (domainName.length() > 2) && certificateCommonName.startsWith("*.") && (certificateCommonName.length() > 2)) {
2390 // Remove the wildcards.
2391 String rootDomainName = domainName.substring(2);
2392 String rootCertificateCommonName = certificateCommonName.substring(2);
2394 // Check if one name ends with the contents of the other. If so, there will be overlap in the their wildcard subdomains.
2395 if (rootDomainName.endsWith(rootCertificateCommonName) || rootCertificateCommonName.endsWith(rootDomainName)) {
2396 domainNamesMatch = true;
2401 return domainNamesMatch;