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. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
584 if (fanboysSocialBlockingListInt == 1) { // Fanboy's Social Blocking List is on.
585 // Enable the switch and turn it on.
586 fanboysSocialBlockingListSwitch.setEnabled(true);
587 fanboysSocialBlockingListSwitch.setChecked(true);
589 // Set the icon according to the theme.
590 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
591 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_night));
593 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_day));
595 } else { // Fanboy's Social Blocking List is off.
596 // Enable the switch but turn it off.
597 fanboysSocialBlockingListSwitch.setEnabled(true);
598 fanboysSocialBlockingListSwitch.setChecked(false);
600 // Set the icon according to the theme.
601 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
602 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_night));
604 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_day));
607 } else { // Fanboy's Annoyance List is on.
608 // Disable Fanboy's Social Blocking List. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
609 if (fanboysSocialBlockingListInt == 1) { // Fanboy's Social Blocking List is on.
610 // Disable the switch but turn it on.
611 fanboysSocialBlockingListSwitch.setEnabled(false);
612 fanboysSocialBlockingListSwitch.setChecked(true);
613 } else { // Fanboy's Social Blocking List is off.
614 // Disable the switch and turn it off.
615 fanboysSocialBlockingListSwitch.setEnabled(false);
616 fanboysSocialBlockingListSwitch.setChecked(false);
619 // Set the icon according to the theme.
620 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
621 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_ghosted_night));
623 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_ghosted_day));
627 // Set the UltraList status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
628 if (ultraListInt == 1) { // UltraList is on.
629 // Turn the switch on.
630 ultraListSwitch.setChecked(true);
632 // Set the icon according to the theme.
633 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
634 ultraListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_night));
636 ultraListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_day));
638 } else { // UltraList is off.
639 // Turn the switch off.
640 ultraListSwitch.setChecked(false);
642 // Set the icon according to the theme.
643 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
644 ultraListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_night));
646 ultraListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_day));
650 // Set the UltraPrivacy status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
651 if (ultraPrivacyInt == 1) { // UltraPrivacy is on.
652 // Turn the switch on.
653 ultraPrivacySwitch.setChecked(true);
655 // Set the icon according to the theme.
656 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
657 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_night));
659 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_day));
661 } else { // EasyPrivacy is off.
662 // Turn the switch off.
663 ultraPrivacySwitch.setChecked(false);
665 // Set the icon according to the theme.
666 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
667 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_night));
669 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_day));
673 // 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.
674 if (blockAllThirdPartyRequestsInt == 1) { // Blocking all third-party requests is on.
675 // Turn the switch on.
676 blockAllThirdPartyRequestsSwitch.setChecked(true);
678 // Set the icon according to the theme.
679 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
680 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_enabled_night));
682 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_enabled_day));
684 } else { // Blocking all third-party requests is off.
685 // Turn the switch off.
686 blockAllThirdPartyRequestsSwitch.setChecked(false);
688 // Set the icon according to the theme.
689 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
690 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_disabled_night));
692 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_disabled_day));
696 // Inflated a WebView to get the default user agent.
697 // `@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.
698 @SuppressLint("InflateParams") View bareWebViewLayout = inflater.inflate(R.layout.bare_webview, null, false);
699 WebView bareWebView = bareWebViewLayout.findViewById(R.id.bare_webview);
700 final String webViewDefaultUserAgentString = bareWebView.getSettings().getUserAgentString();
702 // Get a handle for the user agent array adapter. This array does not contain the `System default` entry.
703 ArrayAdapter<CharSequence> userAgentNamesArray = ArrayAdapter.createFromResource(context, R.array.user_agent_names, R.layout.spinner_item);
705 // Get the positions of the user agent and the default user agent.
706 int userAgentArrayPosition = userAgentNamesArray.getPosition(currentUserAgentName);
707 int defaultUserAgentArrayPosition = userAgentNamesArray.getPosition(defaultUserAgentName);
709 // Get a handle for the user agent data array. This array does not contain the `System default` entry.
710 String[] userAgentDataArray = resources.getStringArray(R.array.user_agent_data);
712 // Set the user agent text.
713 if (currentUserAgentName.equals(getString(R.string.system_default_user_agent))) { // Use the system default user agent.
714 // Set the user agent according to the system default.
715 switch (defaultUserAgentArrayPosition) {
716 case MainWebViewActivity.UNRECOGNIZED_USER_AGENT: // The default user agent name is not on the canonical list.
717 // This is probably because it was set in an older version of Privacy Browser before the switch to persistent user agent names.
718 userAgentTextView.setText(defaultUserAgentName);
721 case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
722 // Display the `WebView` default user agent.
723 userAgentTextView.setText(webViewDefaultUserAgentString);
726 case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
727 // Display the custom user agent.
728 userAgentTextView.setText(defaultCustomUserAgentString);
732 // Get the user agent string from the user agent data array.
733 userAgentTextView.setText(userAgentDataArray[defaultUserAgentArrayPosition]);
735 } else if (userAgentArrayPosition == MainWebViewActivity.UNRECOGNIZED_USER_AGENT) { // A custom user agent is stored in the current user agent name.
736 // Set the user agent spinner to `Custom user agent`.
737 userAgentSpinner.setSelection(MainWebViewActivity.DOMAINS_CUSTOM_USER_AGENT);
739 // Hide the user agent TextView.
740 userAgentTextView.setVisibility(View.GONE);
742 // Show the custom user agent EditText and set the current user agent name as the text.
743 customUserAgentEditText.setVisibility(View.VISIBLE);
744 customUserAgentEditText.setText(currentUserAgentName);
745 } else { // The user agent name contains one of the canonical user agents.
746 // 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.
747 userAgentSpinner.setSelection(userAgentArrayPosition + 1);
749 // Show the user agent TextView.
750 userAgentTextView.setVisibility(View.VISIBLE);
752 // Hide the custom user agent EditText.
753 customUserAgentEditText.setVisibility(View.GONE);
755 // Set the user agent text.
756 if (userAgentArrayPosition == MainWebViewActivity.DOMAINS_WEBVIEW_DEFAULT_USER_AGENT) { // The WebView default user agent is selected.
757 // Display the WebView default user agent.
758 userAgentTextView.setText(webViewDefaultUserAgentString);
759 } else { // A user agent besides the default is selected.
760 // 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.
761 userAgentTextView.setText(userAgentDataArray[userAgentArrayPosition + 1]);
765 // Open the user agent spinner when the text view is clicked.
766 userAgentTextView.setOnClickListener((View v) -> {
767 // Open the user agent spinner.
768 userAgentSpinner.performClick();
771 // Display the font size settings.
772 if (fontSizeInt == 0) { // `0` is the code for system default font size.
773 // Set the font size to the system default
774 fontSizeSpinner.setSelection(0);
776 // Show the default font size text view.
777 defaultFontSizeTextView.setVisibility(View.VISIBLE);
779 // Hide the custom font size edit text.
780 customFontSizeEditText.setVisibility(View.GONE);
782 // 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.
783 customFontSizeEditText.setText(defaultFontSizeString);
784 } else { // A custom font size is selected.
785 // Set the spinner to the custom font size.
786 fontSizeSpinner.setSelection(1);
788 // Hide the default font size text view.
789 defaultFontSizeTextView.setVisibility(View.GONE);
791 // Show the custom font size edit text.
792 customFontSizeEditText.setVisibility(View.GONE);
794 // Set the custom font size.
795 customFontSizeEditText.setText(String.valueOf(fontSizeInt));
798 // Initialize the default font size percentage string.
799 String defaultFontSizePercentageString = defaultFontSizeString + "%";
801 // Set the default font size text in the text view.
802 defaultFontSizeTextView.setText(defaultFontSizePercentageString);
804 // Open the font size spinner when the text view is clicked.
805 defaultFontSizeTextView.setOnClickListener((View v) -> {
806 // Open the user agent spinner.
807 fontSizeSpinner.performClick();
810 // Display the swipe to refresh selection in the spinner.
811 swipeToRefreshSpinner.setSelection(swipeToRefreshInt);
813 // Set the swipe to refresh text.
814 if (defaultSwipeToRefresh) {
815 swipeToRefreshTextView.setText(swipeToRefreshArrayAdapter.getItem(DomainsDatabaseHelper.ENABLED));
817 swipeToRefreshTextView.setText(swipeToRefreshArrayAdapter.getItem(DomainsDatabaseHelper.DISABLED));
820 // 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.
821 switch (swipeToRefreshInt) {
822 case DomainsDatabaseHelper.SYSTEM_DEFAULT:
823 if (defaultSwipeToRefresh) { // Swipe to refresh is enabled by default.
824 // Set the icon according to the theme.
825 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
826 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_night));
828 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_day));
830 } else { // Swipe to refresh is disabled by default
831 // Set the icon according to the theme.
832 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
833 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_night));
835 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_day));
839 // Show the swipe to refresh TextView.
840 swipeToRefreshTextView.setVisibility(View.VISIBLE);
843 case DomainsDatabaseHelper.ENABLED:
844 // Set the icon according to the theme.
845 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
846 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_night));
848 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_day));
851 // Hide the swipe to refresh TextView.`
852 swipeToRefreshTextView.setVisibility(View.GONE);
855 case DomainsDatabaseHelper.DISABLED:
856 // Set the icon according to the theme.
857 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
858 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_night));
860 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_day));
863 // Hide the swipe to refresh TextView.
864 swipeToRefreshTextView.setVisibility(View.GONE);
867 // Open the swipe to refresh spinner when the TextView is clicked.
868 swipeToRefreshTextView.setOnClickListener((View v) -> {
869 // Open the swipe to refresh spinner.
870 swipeToRefreshSpinner.performClick();
873 // Display the night mode in the spinner.
874 nightModeSpinner.setSelection(nightModeInt);
876 // Set the default night mode text.
877 if (defaultNightMode) {
878 nightModeTextView.setText(nightModeArrayAdapter.getItem(DomainsDatabaseHelper.ENABLED));
880 nightModeTextView.setText(nightModeArrayAdapter.getItem(DomainsDatabaseHelper.DISABLED));
883 // 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.
884 switch (nightModeInt) {
885 case DomainsDatabaseHelper.SYSTEM_DEFAULT:
886 if (defaultNightMode) { // Night mode enabled by default.
887 // Set the icon according to the theme.
888 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
889 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_night));
891 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_day));
893 } else { // Night mode disabled by default.
894 // Set the icon according to the theme.
895 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
896 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_night));
898 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_day));
902 // Show night mode TextView.
903 nightModeTextView.setVisibility(View.VISIBLE);
906 case DomainsDatabaseHelper.ENABLED:
907 // Set the icon according to the theme.
908 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
909 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_night));
911 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_day));
914 // Hide the night mode TextView.
915 nightModeTextView.setVisibility(View.GONE);
918 case DomainsDatabaseHelper.DISABLED:
919 // Set the icon according to the theme.
920 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
921 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_night));
923 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_day));
926 // Hide the night mode TextView.
927 nightModeTextView.setVisibility(View.GONE);
931 // Open the night mode spinner when the TextView is clicked.
932 nightModeTextView.setOnClickListener((View v) -> {
933 // Open the night mode spinner.
934 nightModeSpinner.performClick();
937 // Display the wide viewport in the spinner.
938 wideViewportSpinner.setSelection(wideViewportInt);
940 // Set the default wide viewport text.
941 if (defaultWideViewport) {
942 wideViewportTextView.setText(wideViewportArrayAdapter.getItem(DomainsDatabaseHelper.ENABLED));
944 wideViewportTextView.setText(wideViewportArrayAdapter.getItem(DomainsDatabaseHelper.DISABLED));
947 // 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.
948 switch (wideViewportInt) {
949 case DomainsDatabaseHelper.SYSTEM_DEFAULT:
950 if (defaultWideViewport) { // Wide viewport enabled by default.
951 // Set the icon according to the theme.
952 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
953 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_enabled_night));
955 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_enabled_day));
957 } else { // Wide viewport disabled by default.
958 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
959 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_disabled_night));
961 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_disabled_day));
965 // Show the wide viewport text view.
966 wideViewportTextView.setVisibility(View.VISIBLE);
969 case DomainsDatabaseHelper.ENABLED:
970 // Set the icon according to the theme.
971 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
972 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_enabled_night));
974 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_enabled_day));
977 // Hide the wide viewport text view.
978 wideViewportTextView.setVisibility(View.GONE);
981 case DomainsDatabaseHelper.DISABLED:
982 // Set the icon according to the theme.
983 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
984 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_disabled_night));
986 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_disabled_day));
989 // Hide the wide viewport text view.
990 wideViewportTextView.setVisibility(View.GONE);
994 // Open the wide viewport spinner when the text view is clicked.
995 wideViewportTextView.setOnClickListener((View view) -> {
996 // Open the wide viewport spinner.
997 wideViewportSpinner.performClick();
1000 // Display the website images mode in the spinner.
1001 displayWebpageImagesSpinner.setSelection(displayImagesInt);
1003 // Set the default display images text.
1004 if (defaultDisplayWebpageImages) {
1005 displayImagesTextView.setText(displayImagesArrayAdapter.getItem(DomainsDatabaseHelper.ENABLED));
1007 displayImagesTextView.setText(displayImagesArrayAdapter.getItem(DomainsDatabaseHelper.DISABLED));
1010 // 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.
1011 switch (displayImagesInt) {
1012 case DomainsDatabaseHelper.SYSTEM_DEFAULT:
1013 if (defaultDisplayWebpageImages) { // Display webpage images enabled by default.
1014 // Set the icon according to the theme.
1015 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1016 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_night));
1018 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_day));
1020 } else { // Display webpage images disabled by default.
1021 // Set the icon according to the theme.
1022 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1023 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_night));
1025 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_day));
1029 // Show the display images text view.
1030 displayImagesTextView.setVisibility(View.VISIBLE);
1033 case DomainsDatabaseHelper.ENABLED:
1034 // Set the icon according to the theme.
1035 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1036 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_night));
1038 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_day));
1041 // Hide the display images text view.
1042 displayImagesTextView.setVisibility(View.GONE);
1045 case DomainsDatabaseHelper.DISABLED:
1046 // Set the icon according to the theme.
1047 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1048 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_night));
1050 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_day));
1053 // Hide the display images text view.
1054 displayImagesTextView.setVisibility(View.GONE);
1058 // Open the display images spinner when the text view is clicked.
1059 displayImagesTextView.setOnClickListener((View view) -> {
1060 // Open the user agent spinner.
1061 displayWebpageImagesSpinner.performClick();
1064 // Set the pinned SSL certificate icon.
1065 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.
1066 // Check the switch.
1067 pinnedSslCertificateSwitch.setChecked(true);
1069 // Set the icon according to the theme.
1070 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1071 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_night));
1073 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_day));
1075 } else { // Pinned SSL certificate is disabled.
1076 // Uncheck the switch.
1077 pinnedSslCertificateSwitch.setChecked(false);
1079 // Set the icon according to the theme.
1080 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1081 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_night));
1083 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_day));
1087 // Store the current date.
1088 Date currentDate = Calendar.getInstance().getTime();
1090 // Setup the string builders to display the general certificate information in blue. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1091 savedSslIssuedToONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), savedSslIssuedToONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1092 savedSslIssuedToUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), savedSslIssuedToUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1093 savedSslIssuedByCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), savedSslIssuedByCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1094 savedSslIssuedByONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), savedSslIssuedByONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1095 savedSslIssuedByUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), savedSslIssuedByUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1097 // Check the certificate Common Name against the domain name.
1098 boolean savedSslCommonNameMatchesDomainName = checkDomainNameAgainstCertificate(domainNameString, savedSslIssuedToCNameString);
1100 // Format the issued to Common Name color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1101 if (savedSslCommonNameMatchesDomainName) {
1102 savedSslIssuedToCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), savedSslIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1104 savedSslIssuedToCNameStringBuilder.setSpan(redColorSpan, cNameLabel.length(), savedSslIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1107 // Format the start date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1108 if ((savedSslStartDate != null) && savedSslStartDate.after(currentDate)) { // The certificate start date is in the future.
1109 savedSslStartDateStringBuilder.setSpan(redColorSpan, startDateLabel.length(), savedSslStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1110 } else { // The certificate start date is in the past.
1111 savedSslStartDateStringBuilder.setSpan(blueColorSpan, startDateLabel.length(), savedSslStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1114 // Format the end date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1115 if ((savedSslEndDate != null) && savedSslEndDate.before(currentDate)) { // The certificate end date is in the past.
1116 savedSslEndDateStringBuilder.setSpan(redColorSpan, endDateLabel.length(), savedSslEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1117 } else { // The certificate end date is in the future.
1118 savedSslEndDateStringBuilder.setSpan(blueColorSpan, endDateLabel.length(), savedSslEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1121 // Display the saved website SSL certificate strings.
1122 savedSslIssuedToCNameTextView.setText(savedSslIssuedToCNameStringBuilder);
1123 savedSslIssuedToONameTextView.setText(savedSslIssuedToONameStringBuilder);
1124 savedSslIssuedToUNameTextView.setText(savedSslIssuedToUNameStringBuilder);
1125 savedSslIssuedByCNameTextView.setText(savedSslIssuedByCNameStringBuilder);
1126 savedSslIssuedByONameTextView.setText(savedSslIssuedByONameStringBuilder);
1127 savedSslIssuedByUNameTextView.setText(savedSslIssuedByUNameStringBuilder);
1128 savedSslStartDateTextView.setText(savedSslStartDateStringBuilder);
1129 savedSslEndDateTextView.setText(savedSslEndDateStringBuilder);
1131 // Populate the current website SSL certificate if there is one.
1132 if (DomainsActivity.sslIssuedToCName != null) {
1133 // Get dates from the raw long values.
1134 Date currentSslStartDate = new Date(DomainsActivity.sslStartDateLong);
1135 Date currentSslEndDate = new Date(DomainsActivity.sslEndDateLong);
1137 // Create a spannable string builder for each text view that needs multiple colors of text.
1138 SpannableStringBuilder currentSslIssuedToCNameStringBuilder = new SpannableStringBuilder(cNameLabel + DomainsActivity.sslIssuedToCName);
1139 SpannableStringBuilder currentSslIssuedToONameStringBuilder = new SpannableStringBuilder(oNameLabel + DomainsActivity.sslIssuedToOName);
1140 SpannableStringBuilder currentSslIssuedToUNameStringBuilder = new SpannableStringBuilder(uNameLabel + DomainsActivity.sslIssuedToUName);
1141 SpannableStringBuilder currentSslIssuedByCNameStringBuilder = new SpannableStringBuilder(cNameLabel + DomainsActivity.sslIssuedByCName);
1142 SpannableStringBuilder currentSslIssuedByONameStringBuilder = new SpannableStringBuilder(oNameLabel + DomainsActivity.sslIssuedByOName);
1143 SpannableStringBuilder currentSslIssuedByUNameStringBuilder = new SpannableStringBuilder(uNameLabel + DomainsActivity.sslIssuedByUName);
1144 SpannableStringBuilder currentSslStartDateStringBuilder = new SpannableStringBuilder(startDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG)
1145 .format(currentSslStartDate));
1146 SpannableStringBuilder currentSslEndDateStringBuilder = new SpannableStringBuilder(endDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG)
1147 .format(currentSslEndDate));
1149 // Setup the string builders to display the general certificate information in blue. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1150 currentSslIssuedToONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), currentSslIssuedToONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1151 currentSslIssuedToUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), currentSslIssuedToUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1152 currentSslIssuedByCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), currentSslIssuedByCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1153 currentSslIssuedByONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), currentSslIssuedByONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1154 currentSslIssuedByUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), currentSslIssuedByUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1156 // Check the certificate Common Name against the domain name.
1157 boolean currentSslCommonNameMatchesDomainName = checkDomainNameAgainstCertificate(domainNameString, DomainsActivity.sslIssuedToCName);
1159 // Format the issued to Common Name color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1160 if (currentSslCommonNameMatchesDomainName) {
1161 currentSslIssuedToCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), currentSslIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1163 currentSslIssuedToCNameStringBuilder.setSpan(redColorSpan, cNameLabel.length(), currentSslIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1166 // Format the start date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1167 if (currentSslStartDate.after(currentDate)) { // The certificate start date is in the future.
1168 currentSslStartDateStringBuilder.setSpan(redColorSpan, startDateLabel.length(), currentSslStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1169 } else { // The certificate start date is in the past.
1170 currentSslStartDateStringBuilder.setSpan(blueColorSpan, startDateLabel.length(), currentSslStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1173 // Format the end date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1174 if (currentSslEndDate.before(currentDate)) { // The certificate end date is in the past.
1175 currentSslEndDateStringBuilder.setSpan(redColorSpan, endDateLabel.length(), currentSslEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1176 } else { // The certificate end date is in the future.
1177 currentSslEndDateStringBuilder.setSpan(blueColorSpan, endDateLabel.length(), currentSslEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1180 // Display the current website SSL certificate strings.
1181 currentSslIssuedToCNameTextView.setText(currentSslIssuedToCNameStringBuilder);
1182 currentSslIssuedToONameTextView.setText(currentSslIssuedToONameStringBuilder);
1183 currentSslIssuedToUNameTextView.setText(currentSslIssuedToUNameStringBuilder);
1184 currentSslIssuedByCNameTextView.setText(currentSslIssuedByCNameStringBuilder);
1185 currentSslIssuedByONameTextView.setText(currentSslIssuedByONameStringBuilder);
1186 currentSslIssuedByUNameTextView.setText(currentSslIssuedByUNameStringBuilder);
1187 currentSslStartDateTextView.setText(currentSslStartDateStringBuilder);
1188 currentSslEndDateTextView.setText(currentSslEndDateStringBuilder);
1191 // Set the initial display status of the SSL certificates card views.
1192 if (pinnedSslCertificateSwitch.isChecked()) { // An SSL certificate is pinned.
1193 // Set the visibility of the saved SSL certificate.
1194 if (savedSslIssuedToCNameString == null) {
1195 savedSslCardView.setVisibility(View.GONE);
1197 savedSslCardView.setVisibility(View.VISIBLE);
1200 // Set the visibility of the current website SSL certificate.
1201 if (DomainsActivity.sslIssuedToCName == null) { // There is no current SSL certificate.
1202 // Hide the SSL certificate.
1203 currentSslCardView.setVisibility(View.GONE);
1205 // Show the instruction.
1206 noCurrentWebsiteCertificateTextView.setVisibility(View.VISIBLE);
1207 } else { // There is a current SSL certificate.
1208 // Show the SSL certificate.
1209 currentSslCardView.setVisibility(View.VISIBLE);
1211 // Hide the instruction.
1212 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
1215 // Set the status of the radio buttons and the card view backgrounds.
1216 if (savedSslCardView.getVisibility() == View.VISIBLE) { // The saved SSL certificate is displayed.
1217 // Check the saved SSL certificate radio button.
1218 savedSslCertificateRadioButton.setChecked(true);
1220 // Uncheck the current website SSL certificate radio button.
1221 currentWebsiteCertificateRadioButton.setChecked(false);
1223 // Darken the background of the current website SSL certificate linear layout according to the theme.
1224 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1225 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
1227 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
1229 } else if (currentSslCardView.getVisibility() == View.VISIBLE) { // The saved SSL certificate is hidden but the current website SSL certificate is visible.
1230 // Check the current website SSL certificate radio button.
1231 currentWebsiteCertificateRadioButton.setChecked(true);
1233 // Uncheck the saved SSL certificate radio button.
1234 savedSslCertificateRadioButton.setChecked(false);
1235 } else { // Neither SSL certificate is visible.
1236 // Uncheck both radio buttons.
1237 savedSslCertificateRadioButton.setChecked(false);
1238 currentWebsiteCertificateRadioButton.setChecked(false);
1240 } else { // An SSL certificate is not pinned.
1241 // Hide the SSl certificates and instructions.
1242 savedSslCardView.setVisibility(View.GONE);
1243 currentSslCardView.setVisibility(View.GONE);
1244 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
1246 // Uncheck the radio buttons.
1247 savedSslCertificateRadioButton.setChecked(false);
1248 currentWebsiteCertificateRadioButton.setChecked(false);
1251 // Set the pinned IP addresses icon.
1252 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.
1253 // Check the switch.
1254 pinnedIpAddressesSwitch.setChecked(true);
1256 // Set the icon according to the theme.
1257 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1258 pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_night));
1260 pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_day));
1262 } else { // Pinned IP Addresses is disabled.
1263 // Uncheck the switch.
1264 pinnedIpAddressesSwitch.setChecked(false);
1266 // Set the icon according to the theme.
1267 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1268 pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_night));
1270 pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_day));
1274 // Populate the saved and current IP addresses.
1275 savedIpAddressesTextView.setText(savedIpAddresses);
1276 currentIpAddressesTextView.setText(DomainsActivity.currentIpAddresses);
1278 // Set the initial display status of the IP addresses card views.
1279 if (pinnedIpAddressesSwitch.isChecked()) { // IP addresses are pinned.
1280 // Set the visibility of the saved IP addresses.
1281 if (savedIpAddresses == null) { // There are no saved IP addresses.
1282 savedIpAddressesCardView.setVisibility(View.GONE);
1283 } else { // There are saved IP addresses.
1284 savedIpAddressesCardView.setVisibility(View.VISIBLE);
1287 // Set the visibility of the current IP addresses.
1288 currentIpAddressesCardView.setVisibility(View.VISIBLE);
1290 // Set the status of the radio buttons and the card view backgrounds.
1291 if (savedIpAddressesCardView.getVisibility() == View.VISIBLE) { // The saved IP addresses are displayed.
1292 // Check the saved IP addresses radio button.
1293 savedIpAddressesRadioButton.setChecked(true);
1295 // Uncheck the current IP addresses radio button.
1296 currentIpAddressesRadioButton.setChecked(false);
1298 // Darken the background of the current IP addresses linear layout according to the theme.
1299 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1300 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
1302 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
1304 } else { // The saved IP addresses are hidden.
1305 // Check the current IP addresses radio button.
1306 currentIpAddressesRadioButton.setChecked(true);
1308 // Uncheck the saved IP addresses radio button.
1309 savedIpAddressesRadioButton.setChecked(false);
1311 } else { // IP addresses are not pinned.
1312 // Hide the IP addresses card views.
1313 savedIpAddressesCardView.setVisibility(View.GONE);
1314 currentIpAddressesCardView.setVisibility(View.GONE);
1316 // Uncheck the radio buttons.
1317 savedIpAddressesRadioButton.setChecked(false);
1318 currentIpAddressesRadioButton.setChecked(false);
1322 // Set the JavaScript switch listener.
1323 javaScriptSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1324 if (isChecked) { // JavaScript is enabled.
1325 // Update the JavaScript icon.
1326 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.javascript_enabled));
1328 // Enable the DOM storage `Switch`.
1329 domStorageSwitch.setEnabled(true);
1331 // Update the DOM storage icon.
1332 if (domStorageSwitch.isChecked()) { // DOM storage is enabled.
1333 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_enabled));
1334 } else { // DOM storage is disabled.
1335 // Set the icon according to the theme.
1336 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1337 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_night));
1339 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_day));
1342 } else { // JavaScript is disabled.
1343 // Update the JavaScript icon.
1344 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.privacy_mode));
1346 // Disable the DOM storage `Switch`.
1347 domStorageSwitch.setEnabled(false);
1349 // Set the DOM storage icon according to the theme.
1350 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1351 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_night));
1353 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_day));
1358 // Set the first-party cookies switch listener.
1359 firstPartyCookiesSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1360 if (isChecked) { // First-party cookies are enabled.
1361 // Update the first-party cookies icon.
1362 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_enabled));
1364 // Enable the third-party cookies switch.
1365 thirdPartyCookiesSwitch.setEnabled(true);
1367 // Update the third-party cookies icon.
1368 if (thirdPartyCookiesSwitch.isChecked()) { // Third-party cookies are enabled.
1369 // Set the third-party cookies icon to be red.
1370 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_warning));
1371 } else { // Third-party cookies are disabled.
1372 // Set the third-party cookies icon according to the theme.
1373 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1374 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_night));
1376 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_day));
1379 } else { // First-party cookies are disabled.
1380 // Update the first-party cookies icon according to the theme.
1381 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1382 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_night));
1384 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_day));
1387 // Disable the third-party cookies switch.
1388 thirdPartyCookiesSwitch.setEnabled(false);
1390 // Set the third-party cookies icon according to the theme.
1391 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1392 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_ghosted_night));
1394 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_ghosted_day));
1399 // Set the third-party cookies switch listener.
1400 thirdPartyCookiesSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1403 // Set the third-party cookies icon to be red.
1404 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_warning));
1406 // Update the third-party cookies icon according to the theme.
1407 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1408 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_night));
1410 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_day));
1415 // Set the DOM Storage switch listener.
1416 domStorageSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1419 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_enabled));
1421 // Set the icon according to the theme.
1422 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1423 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_night));
1425 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_day));
1430 // Set the form data switch listener. It can be removed once the minimum API >= 26.
1431 if (Build.VERSION.SDK_INT < 26) {
1432 formDataSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1435 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_enabled));
1437 // Set the icon according to the theme.
1438 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1439 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_disabled_night));
1441 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_disabled_day));
1447 // Set the EasyList switch listener.
1448 easyListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1450 if (isChecked) { // EasyList is on.
1451 // Set the icon according to the theme.
1452 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1453 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_night));
1455 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_day));
1457 } else { // EasyList is off.
1458 // Set the icon according to the theme.
1459 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1460 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_night));
1462 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_day));
1467 // Set the EasyPrivacy switch listener.
1468 easyPrivacySwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1470 if (isChecked) { // EasyPrivacy is on.
1471 // Set the icon according to the theme.
1472 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1473 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_night));
1475 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_day));
1477 } else { // EasyPrivacy is off.
1478 // Set the icon according to the theme.
1479 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1480 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_night));
1482 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_day));
1487 // Set the Fanboy's Annoyance List switch listener.
1488 fanboysAnnoyanceListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1489 // Update the icon and Fanboy's Social Blocking List.
1490 if (isChecked) { // Fanboy's Annoyance List is on.
1491 // Set the icon according to the theme.
1492 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1493 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_night));
1495 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_day));
1498 // Disable the Fanboy's Social Blocking List switch.
1499 fanboysSocialBlockingListSwitch.setEnabled(false);
1501 // Update the Fanboy's Social Blocking List icon according to the theme.
1502 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1503 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_ghosted_night));
1505 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_ghosted_day));
1507 } else { // Fanboy's Annoyance List is off.
1508 // Set the icon according to the theme.
1509 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1510 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_night));
1512 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_day));
1515 // Enable the Fanboy's Social Blocking List switch.
1516 fanboysSocialBlockingListSwitch.setEnabled(true);
1518 // Update the Fanboy's Social Blocking List icon.
1519 if (fanboysSocialBlockingListSwitch.isChecked()) { // Fanboy's Social Blocking List is on.
1520 // Update the icon according to the theme.
1521 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1522 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_night));
1524 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_day));
1526 } else { // Fanboy's Social Blocking List is off.
1527 // Update the icon according to the theme.
1528 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1529 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_night));
1531 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_day));
1538 // Set the Fanboy's Social Blocking List switch listener.
1539 fanboysSocialBlockingListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1541 if (isChecked) { // Fanboy's Social Blocking List is on.
1542 // Set the icon according to the theme.
1543 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1544 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_night));
1546 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_day));
1548 } else { // Fanboy's Social Blocking List is off.
1549 // Set the icon according to the theme.
1550 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1551 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_night));
1553 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_day));
1558 // Set the UltraList switch listener.
1559 ultraListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1561 if (isChecked) { // UltraList is on.
1562 // Set the icon according to the theme.
1563 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1564 ultraListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_night));
1566 ultraListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_day));
1568 } else { // UltraList is off.
1569 // Set the icon according to the theme.
1570 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1571 ultraListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_night));
1573 ultraListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_day));
1578 // Set the UltraPrivacy switch listener.
1579 ultraPrivacySwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1581 if (isChecked) { // UltraPrivacy is on.
1582 // Set the icon according to the theme.
1583 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1584 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_night));
1586 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_day));
1588 } else { // UltraPrivacy is off.
1589 // Set the icon according to the theme.
1590 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1591 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_night));
1593 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_day));
1598 // Set the block all third-party requests switch listener.
1599 blockAllThirdPartyRequestsSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1601 if (isChecked) { // Blocking all third-party requests is on.
1602 // Set the icon according to the theme.
1603 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1604 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_enabled_night));
1606 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_enabled_day));
1608 } else { // Blocking all third-party requests is off.
1609 // Set the icon according to the theme.
1610 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1611 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_disabled_night));
1613 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_disabled_day));
1618 // Set the user agent spinner listener.
1619 userAgentSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1621 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1622 // Set the new user agent.
1624 case MainWebViewActivity.DOMAINS_SYSTEM_DEFAULT_USER_AGENT:
1625 // Show the user agent TextView.
1626 userAgentTextView.setVisibility(View.VISIBLE);
1628 // Hide the custom user agent EditText.
1629 customUserAgentEditText.setVisibility(View.GONE);
1631 // Set the user text.
1632 switch (defaultUserAgentArrayPosition) {
1633 case MainWebViewActivity.UNRECOGNIZED_USER_AGENT: // The default user agent name is not on the canonical list.
1634 // This is probably because it was set in an older version of Privacy Browser before the switch to persistent user agent names.
1635 userAgentTextView.setText(defaultUserAgentName);
1638 case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
1639 // Display the `WebView` default user agent.
1640 userAgentTextView.setText(webViewDefaultUserAgentString);
1643 case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
1644 // Display the custom user agent.
1645 userAgentTextView.setText(defaultCustomUserAgentString);
1649 // Get the user agent string from the user agent data array.
1650 userAgentTextView.setText(userAgentDataArray[defaultUserAgentArrayPosition]);
1654 case MainWebViewActivity.DOMAINS_WEBVIEW_DEFAULT_USER_AGENT:
1655 // Show the user agent TextView and set the text.
1656 userAgentTextView.setVisibility(View.VISIBLE);
1657 userAgentTextView.setText(webViewDefaultUserAgentString);
1659 // Hide the custom user agent EditTex.
1660 customUserAgentEditText.setVisibility(View.GONE);
1663 case MainWebViewActivity.DOMAINS_CUSTOM_USER_AGENT:
1664 // Hide the user agent TextView.
1665 userAgentTextView.setVisibility(View.GONE);
1667 // Show the custom user agent EditText and set the current user agent name as the text.
1668 customUserAgentEditText.setVisibility(View.VISIBLE);
1669 customUserAgentEditText.setText(currentUserAgentName);
1673 // 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.
1674 userAgentTextView.setVisibility(View.VISIBLE);
1675 userAgentTextView.setText(userAgentDataArray[position - 1]);
1677 // Hide `customUserAgentEditText`.
1678 customUserAgentEditText.setVisibility(View.GONE);
1683 public void onNothingSelected(AdapterView<?> parent) {
1688 // Set the font size spinner listener.
1689 fontSizeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1691 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1692 // Update the font size display options.
1693 if (position == 0) { // The system default font size has been selected.
1694 // Show the default font size text view.
1695 defaultFontSizeTextView.setVisibility(View.VISIBLE);
1697 // Hide the custom font size edit text.
1698 customFontSizeEditText.setVisibility(View.GONE);
1699 } else { // A custom font size has been selected.
1700 // Hide the default font size text view.
1701 defaultFontSizeTextView.setVisibility(View.GONE);
1703 // Show the custom font size edit text.
1704 customFontSizeEditText.setVisibility(View.VISIBLE);
1709 public void onNothingSelected(AdapterView<?> parent) {
1714 // Set the swipe to refresh spinner listener.
1715 swipeToRefreshSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1717 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1718 // 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.
1720 case DomainsDatabaseHelper.SYSTEM_DEFAULT:
1721 if (defaultSwipeToRefresh) { // Swipe to refresh enabled by default.
1722 // Set the icon according to the theme.
1723 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1724 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_night));
1726 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_day));
1728 } else { // Swipe to refresh disabled by default.
1729 // Set the icon according to the theme.
1730 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1731 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_night));
1733 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_day));
1737 // Show the swipe to refresh TextView.
1738 swipeToRefreshTextView.setVisibility(View.VISIBLE);
1741 case DomainsDatabaseHelper.ENABLED:
1742 // Set the icon according to the theme.
1743 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1744 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_night));
1746 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_day));
1749 // Hide the swipe to refresh TextView.
1750 swipeToRefreshTextView.setVisibility(View.GONE);
1753 case DomainsDatabaseHelper.DISABLED:
1754 // Set the icon according to the theme.
1755 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1756 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_night));
1758 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_day));
1761 // Hide the swipe to refresh TextView.
1762 swipeToRefreshTextView.setVisibility(View.GONE);
1767 public void onNothingSelected(AdapterView<?> parent) {
1772 // Set the night mode spinner listener.
1773 nightModeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1775 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1776 // 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.
1778 case DomainsDatabaseHelper.SYSTEM_DEFAULT:
1779 if (defaultNightMode) { // Night mode enabled by default.
1780 // Set the icon according to the theme.
1781 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1782 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_night));
1784 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_day));
1786 } else { // Night mode disabled by default.
1787 // Set the icon according to the theme.
1788 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1789 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_night));
1791 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_day));
1795 // Show the night mode TextView.
1796 nightModeTextView.setVisibility(View.VISIBLE);
1799 case DomainsDatabaseHelper.ENABLED:
1800 // Set the icon according to the theme.
1801 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1802 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_night));
1804 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_day));
1807 // Hide `nightModeTextView`.
1808 nightModeTextView.setVisibility(View.GONE);
1811 case DomainsDatabaseHelper.DISABLED:
1812 // Set the icon according to the theme.
1813 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1814 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_night));
1816 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_day));
1819 // Hide `nightModeTextView`.
1820 nightModeTextView.setVisibility(View.GONE);
1824 // Create a boolean to store the current night mode setting.
1825 boolean currentNightModeEnabled = (position == DomainsDatabaseHelper.ENABLED) || ((position == DomainsDatabaseHelper.SYSTEM_DEFAULT) && defaultNightMode);
1827 // Disable the JavaScript switch if night mode is enabled.
1828 if (currentNightModeEnabled) {
1829 javaScriptSwitch.setEnabled(false);
1831 javaScriptSwitch.setEnabled(true);
1834 // Update the JavaScript icon.
1835 if ((javaScriptInt == 1) || currentNightModeEnabled) {
1836 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.javascript_enabled));
1838 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.privacy_mode));
1841 // Update the DOM storage status.
1842 if ((javaScriptInt == 1) || currentNightModeEnabled) { // JavaScript is enabled.
1843 // Enable the DOM storage `Switch`.
1844 domStorageSwitch.setEnabled(true);
1846 // Set the DOM storage status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
1847 if (domStorageInt == 1) { // Both JavaScript and DOM storage are enabled.
1848 domStorageSwitch.setChecked(true);
1849 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_enabled));
1850 } else { // JavaScript is enabled but DOM storage is disabled.
1851 // Set the DOM storage switch to off.
1852 domStorageSwitch.setChecked(false);
1854 // Set the icon according to the theme.
1855 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1856 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_night));
1858 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_day));
1861 } else { // JavaScript is disabled.
1862 // Disable the DOM storage `Switch`.
1863 domStorageSwitch.setEnabled(false);
1865 // Set the checked status of DOM storage.
1866 if (domStorageInt == 1) { // DOM storage is enabled but JavaScript is disabled.
1867 domStorageSwitch.setChecked(true);
1868 } else { // Both JavaScript and DOM storage are disabled.
1869 domStorageSwitch.setChecked(false);
1872 // Set the icon according to the theme.
1873 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1874 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_night));
1876 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_day));
1882 public void onNothingSelected(AdapterView<?> parent) {
1887 // Set the wide viewport spinner listener.
1888 wideViewportSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1890 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1891 // Update the icon and the visibility of the wide viewport text view.
1893 case DomainsDatabaseHelper.SYSTEM_DEFAULT:
1894 if (defaultWideViewport) { // Wide viewport is enabled by default.
1895 // Set the icon according to the theme.
1896 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1897 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_enabled_night));
1899 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_enabled_day));
1901 } else { // Wide viewport is disabled by default.
1902 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1903 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_disabled_night));
1905 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_disabled_day));
1909 // Show the wide viewport text view.
1910 wideViewportTextView.setVisibility(View.VISIBLE);
1913 case DomainsDatabaseHelper.ENABLED:
1914 // Set the icon according to the theme.
1915 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1916 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_enabled_night));
1918 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_enabled_day));
1921 // Hide the wide viewport text view.
1922 wideViewportTextView.setVisibility(View.GONE);
1925 case DomainsDatabaseHelper.DISABLED:
1926 // Set the icon according to the theme.
1927 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1928 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_disabled_night));
1930 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_disabled_day));
1933 // Hid ethe wide viewport text view.
1934 wideViewportTextView.setVisibility(View.GONE);
1940 public void onNothingSelected(AdapterView<?> parent) {
1945 // Set the display webpage images spinner listener.
1946 displayWebpageImagesSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1948 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1949 // Update the icon and the visibility of the display images text view.
1951 case DomainsDatabaseHelper.SYSTEM_DEFAULT:
1952 if (defaultDisplayWebpageImages) { // Display webpage images is enabled by default.
1953 // Set the icon according to the theme.
1954 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1955 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_night));
1957 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_day));
1959 } else { // Display webpage images is disabled by default.
1960 // Set the icon according to the theme.
1961 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1962 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_night));
1964 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_day));
1968 // Show the display images text view.
1969 displayImagesTextView.setVisibility(View.VISIBLE);
1972 case DomainsDatabaseHelper.ENABLED:
1973 // Set the icon according to the theme.
1974 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1975 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_night));
1977 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_day));
1980 // Hide the display images text view.
1981 displayImagesTextView.setVisibility(View.GONE);
1984 case DomainsDatabaseHelper.DISABLED:
1985 // Set the icon according to the theme.
1986 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1987 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_night));
1989 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_day));
1992 // Hide the display images text view.
1993 displayImagesTextView.setVisibility(View.GONE);
1999 public void onNothingSelected(AdapterView<?> parent) {
2004 // Set the pinned SSL certificate switch listener.
2005 pinnedSslCertificateSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
2007 if (isChecked) { // SSL certificate pinning is enabled.
2008 // Set the icon according to the theme.
2009 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2010 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_night));
2012 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_day));
2015 // Update the visibility of the saved SSL certificate.
2016 if (savedSslIssuedToCNameString == null) {
2017 savedSslCardView.setVisibility(View.GONE);
2019 savedSslCardView.setVisibility(View.VISIBLE);
2022 // Update the visibility of the current website SSL certificate.
2023 if (DomainsActivity.sslIssuedToCName == null) {
2024 // Hide the SSL certificate.
2025 currentSslCardView.setVisibility(View.GONE);
2027 // Show the instruction.
2028 noCurrentWebsiteCertificateTextView.setVisibility(View.VISIBLE);
2030 // Show the SSL certificate.
2031 currentSslCardView.setVisibility(View.VISIBLE);
2033 // Hide the instruction.
2034 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
2037 // Set the status of the radio buttons.
2038 if (savedSslCardView.getVisibility() == View.VISIBLE) { // The saved SSL certificate is displayed.
2039 // Check the saved SSL certificate radio button.
2040 savedSslCertificateRadioButton.setChecked(true);
2042 // Uncheck the current website SSL certificate radio button.
2043 currentWebsiteCertificateRadioButton.setChecked(false);
2045 // Set the background of the saved SSL certificate linear layout to be transparent.
2046 savedSslCertificateLinearLayout.setBackgroundResource(R.color.transparent);
2048 // Darken the background of the current website SSL certificate linear layout according to the theme.
2049 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2050 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2052 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2055 // Scroll to the current website SSL certificate card.
2056 savedSslCardView.getParent().requestChildFocus(savedSslCardView, savedSslCardView);
2057 } else if (currentSslCardView.getVisibility() == View.VISIBLE) { // The saved SSL certificate is hidden but the current website SSL certificate is visible.
2058 // Check the current website SSL certificate radio button.
2059 currentWebsiteCertificateRadioButton.setChecked(true);
2061 // Uncheck the saved SSL certificate radio button.
2062 savedSslCertificateRadioButton.setChecked(false);
2064 // Set the background of the current website SSL certificate linear layout to be transparent.
2065 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.transparent);
2067 // Darken the background of the saved SSL certificate linear layout according to the theme.
2068 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2069 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2071 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2074 // Scroll to the current website SSL certificate card.
2075 currentSslCardView.getParent().requestChildFocus(currentSslCardView, currentSslCardView);
2076 } else { // Neither SSL certificate is visible.
2077 // Uncheck both radio buttons.
2078 savedSslCertificateRadioButton.setChecked(false);
2079 currentWebsiteCertificateRadioButton.setChecked(false);
2081 // Scroll to the current website SSL certificate card.
2082 noCurrentWebsiteCertificateTextView.getParent().requestChildFocus(noCurrentWebsiteCertificateTextView, noCurrentWebsiteCertificateTextView);
2084 } else { // SSL certificate pinning is disabled.
2085 // Set the icon according to the theme.
2086 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2087 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_night));
2089 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_day));
2092 // Hide the SSl certificates and instructions.
2093 savedSslCardView.setVisibility(View.GONE);
2094 currentSslCardView.setVisibility(View.GONE);
2095 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
2097 // Uncheck the radio buttons.
2098 savedSslCertificateRadioButton.setChecked(false);
2099 currentWebsiteCertificateRadioButton.setChecked(false);
2103 savedSslCardView.setOnClickListener((View view) -> {
2104 // Check the saved SSL certificate radio button.
2105 savedSslCertificateRadioButton.setChecked(true);
2107 // Uncheck the current website SSL certificate radio button.
2108 currentWebsiteCertificateRadioButton.setChecked(false);
2110 // Set the background of the saved SSL certificate linear layout to be transparent.
2111 savedSslCertificateLinearLayout.setBackgroundResource(R.color.transparent);
2113 // Darken the background of the current website SSL certificate linear layout according to the theme.
2114 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2115 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2117 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2121 savedSslCertificateRadioButton.setOnClickListener((View view) -> {
2122 // Check the saved SSL certificate radio button.
2123 savedSslCertificateRadioButton.setChecked(true);
2125 // Uncheck the current website SSL certificate radio button.
2126 currentWebsiteCertificateRadioButton.setChecked(false);
2128 // Set the background of the saved SSL certificate linear layout to be transparent.
2129 savedSslCertificateLinearLayout.setBackgroundResource(R.color.transparent);
2131 // Darken the background of the current website SSL certificate linear layout according to the theme.
2132 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2133 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2135 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2139 currentSslCardView.setOnClickListener((View view) -> {
2140 // Check the current website SSL certificate radio button.
2141 currentWebsiteCertificateRadioButton.setChecked(true);
2143 // Uncheck the saved SSL certificate radio button.
2144 savedSslCertificateRadioButton.setChecked(false);
2146 // Set the background of the current website SSL certificate linear layout to be transparent.
2147 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.transparent);
2149 // Darken the background of the saved SSL certificate linear layout according to the theme.
2150 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2151 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2153 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2157 currentWebsiteCertificateRadioButton.setOnClickListener((View view) -> {
2158 // Check the current website SSL certificate radio button.
2159 currentWebsiteCertificateRadioButton.setChecked(true);
2161 // Uncheck the saved SSL certificate radio button.
2162 savedSslCertificateRadioButton.setChecked(false);
2164 // Set the background of the current website SSL certificate linear layout to be transparent.
2165 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.transparent);
2167 // Darken the background of the saved SSL certificate linear layout according to the theme.
2168 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2169 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2171 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2175 // Set the pinned IP addresses switch listener.
2176 pinnedIpAddressesSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
2178 if (isChecked) { // IP addresses pinning is enabled.
2179 // Set the icon according to the theme.
2180 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2181 pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_night));
2183 pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_day));
2186 // Update the visibility of the saved IP addresses card view.
2187 if (savedIpAddresses == null) { // There are no saved IP addresses.
2188 savedIpAddressesCardView.setVisibility(View.GONE);
2189 } else { // There are saved IP addresses.
2190 savedIpAddressesCardView.setVisibility(View.VISIBLE);
2193 // Show the current IP addresses card view.
2194 currentIpAddressesCardView.setVisibility(View.VISIBLE);
2196 // Set the status of the radio buttons.
2197 if (savedIpAddressesCardView.getVisibility() == View.VISIBLE) { // The saved IP addresses are visible.
2198 // Check the saved IP addresses radio button.
2199 savedIpAddressesRadioButton.setChecked(true);
2201 // Uncheck the current IP addresses radio button.
2202 currentIpAddressesRadioButton.setChecked(false);
2204 // Set the background of the saved IP addresses linear layout to be transparent.
2205 savedSslCertificateLinearLayout.setBackgroundResource(R.color.transparent);
2207 // Darken the background of the current IP addresses linear layout according to the theme.
2208 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2209 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2211 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2213 } else { // The saved IP addresses are not visible.
2214 // Check the current IP addresses radio button.
2215 currentIpAddressesRadioButton.setChecked(true);
2217 // Uncheck the saved IP addresses radio button.
2218 savedIpAddressesRadioButton.setChecked(false);
2220 // Set the background of the current IP addresses linear layout to be transparent.
2221 currentIpAddressesLinearLayout.setBackgroundResource(R.color.transparent);
2223 // Darken the background of the saved IP addresses linear layout according to the theme.
2224 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2225 savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2227 savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2231 // Scroll to the bottom of the card views.
2232 currentIpAddressesCardView.getParent().requestChildFocus(currentIpAddressesCardView, currentIpAddressesCardView);
2233 } else { // IP addresses pinning is disabled.
2234 // Set the icon according to the theme.
2235 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2236 pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_night));
2238 pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_day));
2241 // Hide the IP addresses card views.
2242 savedIpAddressesCardView.setVisibility(View.GONE);
2243 currentIpAddressesCardView.setVisibility(View.GONE);
2245 // Uncheck the radio buttons.
2246 savedIpAddressesRadioButton.setChecked(false);
2247 currentIpAddressesRadioButton.setChecked(false);
2251 savedIpAddressesCardView.setOnClickListener((View view) -> {
2252 // Check the saved IP addresses radio button.
2253 savedIpAddressesRadioButton.setChecked(true);
2255 // Uncheck the current website IP addresses radio button.
2256 currentIpAddressesRadioButton.setChecked(false);
2258 // Set the background of the saved IP addresses linear layout to be transparent.
2259 savedIpAddressesLinearLayout.setBackgroundResource(R.color.transparent);
2261 // Darken the background of the current IP addresses linear layout according to the theme.
2262 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2263 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2265 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2269 savedIpAddressesRadioButton.setOnClickListener((View view) -> {
2270 // Check the saved IP addresses radio button.
2271 savedIpAddressesRadioButton.setChecked(true);
2273 // Uncheck the current website IP addresses radio button.
2274 currentIpAddressesRadioButton.setChecked(false);
2276 // Set the background of the saved IP addresses linear layout to be transparent.
2277 savedIpAddressesLinearLayout.setBackgroundResource(R.color.transparent);
2279 // Darken the background of the current IP addresses linear layout according to the theme.
2280 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2281 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2283 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2287 currentIpAddressesCardView.setOnClickListener((View view) -> {
2288 // Check the current IP addresses radio button.
2289 currentIpAddressesRadioButton.setChecked(true);
2291 // Uncheck the saved IP addresses radio button.
2292 savedIpAddressesRadioButton.setChecked(false);
2294 // Set the background of the current IP addresses linear layout to be transparent.
2295 currentIpAddressesLinearLayout.setBackgroundResource(R.color.transparent);
2297 // Darken the background of the saved IP addresses linear layout according to the theme.
2298 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2299 savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2301 savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2305 currentIpAddressesRadioButton.setOnClickListener((View view) -> {
2306 // Check the current IP addresses radio button.
2307 currentIpAddressesRadioButton.setChecked(true);
2309 // Uncheck the saved IP addresses radio button.
2310 savedIpAddressesRadioButton.setChecked(false);
2312 // Set the background of the current IP addresses linear layout to be transparent.
2313 currentIpAddressesLinearLayout.setBackgroundResource(R.color.transparent);
2315 // Darken the background of the saved IP addresses linear layout according to the theme.
2316 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2317 savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2319 savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2323 return domainSettingsView;
2326 private boolean checkDomainNameAgainstCertificate(String domainName, String certificateCommonName) {
2327 // Initialize `domainNamesMatch`.
2328 boolean domainNamesMatch = false;
2330 // Check various wildcard permutations if `domainName` and `certificateCommonName` are not empty.
2331 // `noinspection ConstantCondition` removes Android Studio's incorrect lint warning that `domainName` can never be `null`.
2332 if ((domainName != null) && (certificateCommonName != null)) {
2333 // Check if the domains match.
2334 if (domainName.equals(certificateCommonName)) {
2335 domainNamesMatch = true;
2338 // If `domainName` starts with a wildcard, check the base domain against all the subdomains of `certificateCommonName`.
2339 if (!domainNamesMatch && domainName.startsWith("*.") && (domainName.length() > 2)) {
2340 // Remove the initial `*.`.
2341 String baseDomainName = domainName.substring(2);
2343 // Setup a copy of `certificateCommonName` to test subdomains.
2344 String certificateCommonNameSubdomain = certificateCommonName;
2346 // Check all the subdomains in `certificateCommonNameSubdomain` against `baseDomainName`.
2347 while (!domainNamesMatch && certificateCommonNameSubdomain.contains(".")) { // Stop checking if we know that `domainNamesMatch` is `true` or if we run out of `.`.
2348 // Test the `certificateCommonNameSubdomain` against `baseDomainName`.
2349 if (certificateCommonNameSubdomain.equals(baseDomainName)) {
2350 domainNamesMatch = true;
2353 // Strip out the lowest subdomain of `certificateCommonNameSubdomain`.
2355 certificateCommonNameSubdomain = certificateCommonNameSubdomain.substring(certificateCommonNameSubdomain.indexOf(".") + 1);
2356 } catch (IndexOutOfBoundsException e) { // `certificateCommonNameSubdomain` ends with `.`.
2357 certificateCommonNameSubdomain = "";
2362 // If `certificateCommonName` starts with a wildcard, check the base common name against all the subdomains of `domainName`.
2363 if (!domainNamesMatch && certificateCommonName.startsWith("*.") && (certificateCommonName.length() > 2)) {
2364 // Remove the initial `*.`.
2365 String baseCertificateCommonName = certificateCommonName.substring(2);
2367 // Setup a copy of `domainName` to test subdomains.
2368 String domainNameSubdomain = domainName;
2370 // Check all the subdomains in `domainNameSubdomain` against `baseCertificateCommonName`.
2371 while (!domainNamesMatch && domainNameSubdomain.contains(".") && (domainNameSubdomain.length() > 2)) {
2372 // Test the `domainNameSubdomain` against `baseCertificateCommonName`.
2373 if (domainNameSubdomain.equals(baseCertificateCommonName)) {
2374 domainNamesMatch = true;
2377 // Strip out the lowest subdomain of `domainNameSubdomain`.
2379 domainNameSubdomain = domainNameSubdomain.substring(domainNameSubdomain.indexOf(".") + 1);
2380 } catch (IndexOutOfBoundsException e) { // `domainNameSubdomain` ends with `.`.
2381 domainNameSubdomain = "";
2386 // If both names start with a wildcard, check if the root of one contains the root of the other.
2387 if (!domainNamesMatch && domainName.startsWith("*.") && (domainName.length() > 2) && certificateCommonName.startsWith("*.") && (certificateCommonName.length() > 2)) {
2388 // Remove the wildcards.
2389 String rootDomainName = domainName.substring(2);
2390 String rootCertificateCommonName = certificateCommonName.substring(2);
2392 // Check if one name ends with the contents of the other. If so, there will be overlap in the their wildcard subdomains.
2393 if (rootDomainName.endsWith(rootCertificateCommonName) || rootCertificateCommonName.endsWith(rootDomainName)) {
2394 domainNamesMatch = true;
2399 return domainNamesMatch;