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 a red foreground color span. The deprecated `resources.getColor` must be used until the minimum API >= 23.
299 final ForegroundColorSpan redColorSpan = new ForegroundColorSpan(resources.getColor(R.color.red_a700));
301 // Create a blue foreground color span.
302 final ForegroundColorSpan blueColorSpan;
304 // Set the blue color span according to the theme. The deprecated `resources` must be used until the minimum API >= 23.
305 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
306 blueColorSpan = new ForegroundColorSpan(resources.getColor(R.color.blue_400));
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 thirdPartyCookiesSwitch.setChecked(true);
414 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_warning));
415 } else { // First party cookies are enabled but third-party cookies are disabled.
416 thirdPartyCookiesSwitch.setChecked(false);
418 // Set the icon according to the theme.
419 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
420 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_night));
422 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_day));
425 } else { // First-party cookies are disabled.
426 // Set the status of third-party cookies.
427 if (thirdPartyCookiesInt == 1) {
428 thirdPartyCookiesSwitch.setChecked(true);
430 thirdPartyCookiesSwitch.setChecked(false);
433 // Disable the third-party cookies switch.
434 thirdPartyCookiesSwitch.setEnabled(false);
436 // Set the icon according to the theme.
437 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
438 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_ghosted_night));
440 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_ghosted_day));
443 } else { // Third-party cookies cannot be configured for API <= 21.
444 // Hide the LinearLayout for third-party cookies.
445 thirdPartyCookiesLinearLayout.setVisibility(View.GONE);
448 // Only enable DOM storage if JavaScript is enabled.
449 if ((javaScriptInt == 1) || nightModeEnabled) { // JavaScript is enabled.
450 // Enable the DOM storage `Switch`.
451 domStorageSwitch.setEnabled(true);
453 // Set the DOM storage status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
454 if (domStorageInt == 1) { // Both JavaScript and DOM storage are enabled.
455 domStorageSwitch.setChecked(true);
456 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_enabled));
457 } else { // JavaScript is enabled but DOM storage is disabled.
458 // Set the DOM storage switch to off.
459 domStorageSwitch.setChecked(false);
461 // Set the icon according to the theme.
462 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
463 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_night));
465 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_day));
468 } else { // JavaScript is disabled.
469 // Disable the DOM storage `Switch`.
470 domStorageSwitch.setEnabled(false);
472 // Set the checked status of DOM storage.
473 if (domStorageInt == 1) { // DOM storage is enabled but JavaScript is disabled.
474 domStorageSwitch.setChecked(true);
475 } else { // Both JavaScript and DOM storage are disabled.
476 domStorageSwitch.setChecked(false);
479 // Set the icon according to the theme.
480 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
481 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_night));
483 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_day));
487 // 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.
488 if (Build.VERSION.SDK_INT >= 26) { // Form data no longer applies to newer versions of Android.
489 // Hide the form data switch.
490 formDataSwitch.setVisibility(View.GONE);
491 } else { // Form data should be displayed because this is an older version of Android.
492 if (formDataInt == 1) { // Form data is on.
493 formDataSwitch.setChecked(true);
494 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_enabled));
495 } else { // Form data is off.
496 // Turn the form data switch to off.
497 formDataSwitch.setChecked(false);
499 // Set the icon according to the theme.
500 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
501 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_disabled_night));
503 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_disabled_day));
508 // Set the EasyList status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
509 if (easyListInt == 1) { // EasyList is on.
510 // Turn the switch on.
511 easyListSwitch.setChecked(true);
513 // Set the icon according to the theme.
514 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
515 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_night));
517 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_day));
519 } else { // EasyList is off.
520 // Turn the switch off.
521 easyListSwitch.setChecked(false);
523 // Set the icon according to the theme.
524 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
525 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_night));
527 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_day));
531 // Set the EasyPrivacy status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
532 if (easyPrivacyInt == 1) { // EasyPrivacy is on.
533 // Turn the switch on.
534 easyPrivacySwitch.setChecked(true);
536 // Set the icon according to the theme.
537 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
538 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_night));
540 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_day));
542 } else { // EasyPrivacy is off.
543 // Turn the switch off.
544 easyPrivacySwitch.setChecked(false);
546 // Set the icon according to the theme.
547 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
548 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_night));
550 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_day));
554 // 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.
555 if (fanboysAnnoyanceListInt == 1) { // Fanboy's Annoyance List is on.
556 // Turn the switch on.
557 fanboysAnnoyanceListSwitch.setChecked(true);
559 // Set the icon according to the theme.
560 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
561 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_night));
563 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_day));
565 } else { // Fanboy's Annoyance List is off.
566 // Turn the switch off.
567 fanboysAnnoyanceListSwitch.setChecked(false);
569 // Set the icon according to the theme.
570 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
571 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_night));
573 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_day));
577 // Only enable Fanboy's Social Blocking List if Fanboy's Annoyance List is off.
578 if (fanboysAnnoyanceListInt == 0) { // Fanboy's Annoyance List is on.
579 // 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.
580 if (fanboysSocialBlockingListInt == 1) { // Fanboy's Social Blocking List is on.
581 // Enable the switch and turn it on.
582 fanboysSocialBlockingListSwitch.setEnabled(true);
583 fanboysSocialBlockingListSwitch.setChecked(true);
585 // Set the icon according to the theme.
586 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
587 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_night));
589 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_day));
591 } else { // Fanboy's Social Blocking List is off.
592 // Enable the switch but turn it off.
593 fanboysSocialBlockingListSwitch.setEnabled(true);
594 fanboysSocialBlockingListSwitch.setChecked(false);
596 // Set the icon according to the theme.
597 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
598 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_night));
600 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_day));
603 } else { // Fanboy's Annoyance List is on.
604 // 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.
605 if (fanboysSocialBlockingListInt == 1) { // Fanboy's Social Blocking List is on.
606 // Disable the switch but turn it on.
607 fanboysSocialBlockingListSwitch.setEnabled(false);
608 fanboysSocialBlockingListSwitch.setChecked(true);
609 } else { // Fanboy's Social Blocking List is off.
610 // Disable the switch and turn it off.
611 fanboysSocialBlockingListSwitch.setEnabled(false);
612 fanboysSocialBlockingListSwitch.setChecked(false);
615 // Set the icon according to the theme.
616 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
617 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_ghosted_night));
619 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_ghosted_day));
623 // Set the UltraList status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
624 if (ultraListInt == 1) { // UltraList is on.
625 // Turn the switch on.
626 ultraListSwitch.setChecked(true);
628 // Set the icon according to the theme.
629 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
630 ultraListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_night));
632 ultraListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_day));
634 } else { // UltraList is off.
635 // Turn the switch off.
636 ultraListSwitch.setChecked(false);
638 // Set the icon according to the theme.
639 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
640 ultraListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_night));
642 ultraListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_day));
646 // Set the UltraPrivacy status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
647 if (ultraPrivacyInt == 1) { // UltraPrivacy is on.
648 // Turn the switch on.
649 ultraPrivacySwitch.setChecked(true);
651 // Set the icon according to the theme.
652 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
653 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_night));
655 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_day));
657 } else { // EasyPrivacy is off.
658 // Turn the switch off.
659 ultraPrivacySwitch.setChecked(false);
661 // Set the icon according to the theme.
662 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
663 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_night));
665 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_day));
669 // 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.
670 if (blockAllThirdPartyRequestsInt == 1) { // Blocking all third-party requests is on.
671 // Turn the switch on.
672 blockAllThirdPartyRequestsSwitch.setChecked(true);
674 // Set the icon according to the theme.
675 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
676 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_enabled_night));
678 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_enabled_day));
680 } else { // Blocking all third-party requests is off.
681 // Turn the switch off.
682 blockAllThirdPartyRequestsSwitch.setChecked(false);
684 // Set the icon according to the theme.
685 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
686 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_disabled_night));
688 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_disabled_day));
692 // Inflated a WebView to get the default user agent.
693 // `@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.
694 @SuppressLint("InflateParams") View bareWebViewLayout = inflater.inflate(R.layout.bare_webview, null, false);
695 WebView bareWebView = bareWebViewLayout.findViewById(R.id.bare_webview);
696 final String webViewDefaultUserAgentString = bareWebView.getSettings().getUserAgentString();
698 // Get a handle for the user agent array adapter. This array does not contain the `System default` entry.
699 ArrayAdapter<CharSequence> userAgentNamesArray = ArrayAdapter.createFromResource(context, R.array.user_agent_names, R.layout.spinner_item);
701 // Get the positions of the user agent and the default user agent.
702 int userAgentArrayPosition = userAgentNamesArray.getPosition(currentUserAgentName);
703 int defaultUserAgentArrayPosition = userAgentNamesArray.getPosition(defaultUserAgentName);
705 // Get a handle for the user agent data array. This array does not contain the `System default` entry.
706 String[] userAgentDataArray = resources.getStringArray(R.array.user_agent_data);
708 // Set the user agent text.
709 if (currentUserAgentName.equals(getString(R.string.system_default_user_agent))) { // Use the system default user agent.
710 // Set the user agent according to the system default.
711 switch (defaultUserAgentArrayPosition) {
712 case MainWebViewActivity.UNRECOGNIZED_USER_AGENT: // The default user agent name is not on the canonical list.
713 // This is probably because it was set in an older version of Privacy Browser before the switch to persistent user agent names.
714 userAgentTextView.setText(defaultUserAgentName);
717 case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
718 // Display the `WebView` default user agent.
719 userAgentTextView.setText(webViewDefaultUserAgentString);
722 case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
723 // Display the custom user agent.
724 userAgentTextView.setText(defaultCustomUserAgentString);
728 // Get the user agent string from the user agent data array.
729 userAgentTextView.setText(userAgentDataArray[defaultUserAgentArrayPosition]);
731 } else if (userAgentArrayPosition == MainWebViewActivity.UNRECOGNIZED_USER_AGENT) { // A custom user agent is stored in the current user agent name.
732 // Set the user agent spinner to `Custom user agent`.
733 userAgentSpinner.setSelection(MainWebViewActivity.DOMAINS_CUSTOM_USER_AGENT);
735 // Hide the user agent TextView.
736 userAgentTextView.setVisibility(View.GONE);
738 // Show the custom user agent EditText and set the current user agent name as the text.
739 customUserAgentEditText.setVisibility(View.VISIBLE);
740 customUserAgentEditText.setText(currentUserAgentName);
741 } else { // The user agent name contains one of the canonical user agents.
742 // 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.
743 userAgentSpinner.setSelection(userAgentArrayPosition + 1);
745 // Show the user agent TextView.
746 userAgentTextView.setVisibility(View.VISIBLE);
748 // Hide the custom user agent EditText.
749 customUserAgentEditText.setVisibility(View.GONE);
751 // Set the user agent text.
752 if (userAgentArrayPosition == MainWebViewActivity.DOMAINS_WEBVIEW_DEFAULT_USER_AGENT) { // The WebView default user agent is selected.
753 // Display the WebView default user agent.
754 userAgentTextView.setText(webViewDefaultUserAgentString);
755 } else { // A user agent besides the default is selected.
756 // 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.
757 userAgentTextView.setText(userAgentDataArray[userAgentArrayPosition + 1]);
761 // Open the user agent spinner when the text view is clicked.
762 userAgentTextView.setOnClickListener((View v) -> {
763 // Open the user agent spinner.
764 userAgentSpinner.performClick();
767 // Display the font size settings.
768 if (fontSizeInt == 0) { // `0` is the code for system default font size.
769 // Set the font size to the system default
770 fontSizeSpinner.setSelection(0);
772 // Show the default font size text view.
773 defaultFontSizeTextView.setVisibility(View.VISIBLE);
775 // Hide the custom font size edit text.
776 customFontSizeEditText.setVisibility(View.GONE);
778 // 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.
779 customFontSizeEditText.setText(defaultFontSizeString);
780 } else { // A custom font size is selected.
781 // Set the spinner to the custom font size.
782 fontSizeSpinner.setSelection(1);
784 // Hide the default font size text view.
785 defaultFontSizeTextView.setVisibility(View.GONE);
787 // Show the custom font size edit text.
788 customFontSizeEditText.setVisibility(View.GONE);
790 // Set the custom font size.
791 customFontSizeEditText.setText(String.valueOf(fontSizeInt));
794 // Initialize the default font size percentage string.
795 String defaultFontSizePercentageString = defaultFontSizeString + "%";
797 // Set the default font size text in the text view.
798 defaultFontSizeTextView.setText(defaultFontSizePercentageString);
800 // Open the font size spinner when the text view is clicked.
801 defaultFontSizeTextView.setOnClickListener((View v) -> {
802 // Open the user agent spinner.
803 fontSizeSpinner.performClick();
806 // Display the swipe to refresh selection in the spinner.
807 swipeToRefreshSpinner.setSelection(swipeToRefreshInt);
809 // Set the swipe to refresh text.
810 if (defaultSwipeToRefresh) {
811 swipeToRefreshTextView.setText(swipeToRefreshArrayAdapter.getItem(DomainsDatabaseHelper.ENABLED));
813 swipeToRefreshTextView.setText(swipeToRefreshArrayAdapter.getItem(DomainsDatabaseHelper.DISABLED));
816 // 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.
817 switch (swipeToRefreshInt) {
818 case DomainsDatabaseHelper.SYSTEM_DEFAULT:
819 if (defaultSwipeToRefresh) { // Swipe to refresh is enabled by default.
820 // Set the icon according to the theme.
821 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
822 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_night));
824 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_day));
826 } else { // Swipe to refresh is disabled by default
827 // Set the icon according to the theme.
828 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
829 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_night));
831 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_day));
835 // Show the swipe to refresh TextView.
836 swipeToRefreshTextView.setVisibility(View.VISIBLE);
839 case DomainsDatabaseHelper.ENABLED:
840 // Set the icon according to the theme.
841 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
842 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_night));
844 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_day));
847 // Hide the swipe to refresh TextView.`
848 swipeToRefreshTextView.setVisibility(View.GONE);
851 case DomainsDatabaseHelper.DISABLED:
852 // Set the icon according to the theme.
853 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
854 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_night));
856 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_day));
859 // Hide the swipe to refresh TextView.
860 swipeToRefreshTextView.setVisibility(View.GONE);
863 // Open the swipe to refresh spinner when the TextView is clicked.
864 swipeToRefreshTextView.setOnClickListener((View v) -> {
865 // Open the swipe to refresh spinner.
866 swipeToRefreshSpinner.performClick();
869 // Display the night mode in the spinner.
870 nightModeSpinner.setSelection(nightModeInt);
872 // Set the default night mode text.
873 if (defaultNightMode) {
874 nightModeTextView.setText(nightModeArrayAdapter.getItem(DomainsDatabaseHelper.ENABLED));
876 nightModeTextView.setText(nightModeArrayAdapter.getItem(DomainsDatabaseHelper.DISABLED));
879 // 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.
880 switch (nightModeInt) {
881 case DomainsDatabaseHelper.SYSTEM_DEFAULT:
882 if (defaultNightMode) { // Night mode enabled by default.
883 // Set the icon according to the theme.
884 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
885 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_night));
887 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_day));
889 } else { // Night mode disabled by default.
890 // Set the icon according to the theme.
891 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
892 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_night));
894 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_day));
898 // Show night mode TextView.
899 nightModeTextView.setVisibility(View.VISIBLE);
902 case DomainsDatabaseHelper.ENABLED:
903 // Set the icon according to the theme.
904 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
905 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_night));
907 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_day));
910 // Hide the night mode TextView.
911 nightModeTextView.setVisibility(View.GONE);
914 case DomainsDatabaseHelper.DISABLED:
915 // Set the icon according to the theme.
916 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
917 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_night));
919 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_day));
922 // Hide the night mode TextView.
923 nightModeTextView.setVisibility(View.GONE);
927 // Open the night mode spinner when the TextView is clicked.
928 nightModeTextView.setOnClickListener((View v) -> {
929 // Open the night mode spinner.
930 nightModeSpinner.performClick();
933 // Display the wide viewport in the spinner.
934 wideViewportSpinner.setSelection(wideViewportInt);
936 // Set the default wide viewport text.
937 if (defaultWideViewport) {
938 wideViewportTextView.setText(wideViewportArrayAdapter.getItem(DomainsDatabaseHelper.ENABLED));
940 wideViewportTextView.setText(wideViewportArrayAdapter.getItem(DomainsDatabaseHelper.DISABLED));
943 // 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.
944 switch (wideViewportInt) {
945 case DomainsDatabaseHelper.SYSTEM_DEFAULT:
946 if (defaultWideViewport) { // Wide viewport enabled by default.
947 // Set the icon according to the theme.
948 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
949 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_enabled_night));
951 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_enabled_day));
953 } else { // Wide viewport disabled by default.
954 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
955 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_disabled_night));
957 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_disabled_day));
961 // Show the wide viewport text view.
962 wideViewportTextView.setVisibility(View.VISIBLE);
965 case DomainsDatabaseHelper.ENABLED:
966 // Set the icon according to the theme.
967 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
968 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_enabled_night));
970 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_enabled_day));
973 // Hide the wide viewport text view.
974 wideViewportTextView.setVisibility(View.GONE);
977 case DomainsDatabaseHelper.DISABLED:
978 // Set the icon according to the theme.
979 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
980 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_disabled_night));
982 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_disabled_day));
985 // Hide the wide viewport text view.
986 wideViewportTextView.setVisibility(View.GONE);
990 // Open the wide viewport spinner when the text view is clicked.
991 wideViewportTextView.setOnClickListener((View view) -> {
992 // Open the wide viewport spinner.
993 wideViewportSpinner.performClick();
996 // Display the website images mode in the spinner.
997 displayWebpageImagesSpinner.setSelection(displayImagesInt);
999 // Set the default display images text.
1000 if (defaultDisplayWebpageImages) {
1001 displayImagesTextView.setText(displayImagesArrayAdapter.getItem(DomainsDatabaseHelper.ENABLED));
1003 displayImagesTextView.setText(displayImagesArrayAdapter.getItem(DomainsDatabaseHelper.DISABLED));
1006 // 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.
1007 switch (displayImagesInt) {
1008 case DomainsDatabaseHelper.SYSTEM_DEFAULT:
1009 if (defaultDisplayWebpageImages) { // Display webpage images enabled by default.
1010 // Set the icon according to the theme.
1011 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1012 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_night));
1014 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_day));
1016 } else { // Display webpage images disabled by default.
1017 // Set the icon according to the theme.
1018 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1019 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_night));
1021 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_day));
1025 // Show the display images text view.
1026 displayImagesTextView.setVisibility(View.VISIBLE);
1029 case DomainsDatabaseHelper.ENABLED:
1030 // Set the icon according to the theme.
1031 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1032 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_night));
1034 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_day));
1037 // Hide the display images text view.
1038 displayImagesTextView.setVisibility(View.GONE);
1041 case DomainsDatabaseHelper.DISABLED:
1042 // Set the icon according to the theme.
1043 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1044 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_night));
1046 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_day));
1049 // Hide the display images text view.
1050 displayImagesTextView.setVisibility(View.GONE);
1054 // Open the display images spinner when the text view is clicked.
1055 displayImagesTextView.setOnClickListener((View view) -> {
1056 // Open the user agent spinner.
1057 displayWebpageImagesSpinner.performClick();
1060 // Set the pinned SSL certificate icon.
1061 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.
1062 // Check the switch.
1063 pinnedSslCertificateSwitch.setChecked(true);
1065 // Set the icon according to the theme.
1066 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1067 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_night));
1069 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_day));
1071 } else { // Pinned SSL certificate is disabled.
1072 // Uncheck the switch.
1073 pinnedSslCertificateSwitch.setChecked(false);
1075 // Set the icon according to the theme.
1076 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1077 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_night));
1079 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_day));
1083 // Store the current date.
1084 Date currentDate = Calendar.getInstance().getTime();
1086 // Setup the string builders to display the general certificate information in blue. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1087 savedSslIssuedToONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), savedSslIssuedToONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1088 savedSslIssuedToUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), savedSslIssuedToUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1089 savedSslIssuedByCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), savedSslIssuedByCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1090 savedSslIssuedByONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), savedSslIssuedByONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1091 savedSslIssuedByUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), savedSslIssuedByUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1093 // Check the certificate Common Name against the domain name.
1094 boolean savedSslCommonNameMatchesDomainName = checkDomainNameAgainstCertificate(domainNameString, savedSslIssuedToCNameString);
1096 // Format the issued to Common Name color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1097 if (savedSslCommonNameMatchesDomainName) {
1098 savedSslIssuedToCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), savedSslIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1100 savedSslIssuedToCNameStringBuilder.setSpan(redColorSpan, cNameLabel.length(), savedSslIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1103 // Format the start date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1104 if ((savedSslStartDate != null) && savedSslStartDate.after(currentDate)) { // The certificate start date is in the future.
1105 savedSslStartDateStringBuilder.setSpan(redColorSpan, startDateLabel.length(), savedSslStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1106 } else { // The certificate start date is in the past.
1107 savedSslStartDateStringBuilder.setSpan(blueColorSpan, startDateLabel.length(), savedSslStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1110 // Format the end date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1111 if ((savedSslEndDate != null) && savedSslEndDate.before(currentDate)) { // The certificate end date is in the past.
1112 savedSslEndDateStringBuilder.setSpan(redColorSpan, endDateLabel.length(), savedSslEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1113 } else { // The certificate end date is in the future.
1114 savedSslEndDateStringBuilder.setSpan(blueColorSpan, endDateLabel.length(), savedSslEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1117 // Display the saved website SSL certificate strings.
1118 savedSslIssuedToCNameTextView.setText(savedSslIssuedToCNameStringBuilder);
1119 savedSslIssuedToONameTextView.setText(savedSslIssuedToONameStringBuilder);
1120 savedSslIssuedToUNameTextView.setText(savedSslIssuedToUNameStringBuilder);
1121 savedSslIssuedByCNameTextView.setText(savedSslIssuedByCNameStringBuilder);
1122 savedSslIssuedByONameTextView.setText(savedSslIssuedByONameStringBuilder);
1123 savedSslIssuedByUNameTextView.setText(savedSslIssuedByUNameStringBuilder);
1124 savedSslStartDateTextView.setText(savedSslStartDateStringBuilder);
1125 savedSslEndDateTextView.setText(savedSslEndDateStringBuilder);
1127 // Populate the current website SSL certificate if there is one.
1128 if (DomainsActivity.sslIssuedToCName != null) {
1129 // Get dates from the raw long values.
1130 Date currentSslStartDate = new Date(DomainsActivity.sslStartDateLong);
1131 Date currentSslEndDate = new Date(DomainsActivity.sslEndDateLong);
1133 // Create a spannable string builder for each text view that needs multiple colors of text.
1134 SpannableStringBuilder currentSslIssuedToCNameStringBuilder = new SpannableStringBuilder(cNameLabel + DomainsActivity.sslIssuedToCName);
1135 SpannableStringBuilder currentSslIssuedToONameStringBuilder = new SpannableStringBuilder(oNameLabel + DomainsActivity.sslIssuedToOName);
1136 SpannableStringBuilder currentSslIssuedToUNameStringBuilder = new SpannableStringBuilder(uNameLabel + DomainsActivity.sslIssuedToUName);
1137 SpannableStringBuilder currentSslIssuedByCNameStringBuilder = new SpannableStringBuilder(cNameLabel + DomainsActivity.sslIssuedByCName);
1138 SpannableStringBuilder currentSslIssuedByONameStringBuilder = new SpannableStringBuilder(oNameLabel + DomainsActivity.sslIssuedByOName);
1139 SpannableStringBuilder currentSslIssuedByUNameStringBuilder = new SpannableStringBuilder(uNameLabel + DomainsActivity.sslIssuedByUName);
1140 SpannableStringBuilder currentSslStartDateStringBuilder = new SpannableStringBuilder(startDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG)
1141 .format(currentSslStartDate));
1142 SpannableStringBuilder currentSslEndDateStringBuilder = new SpannableStringBuilder(endDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG)
1143 .format(currentSslEndDate));
1145 // Setup the string builders to display the general certificate information in blue. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1146 currentSslIssuedToONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), currentSslIssuedToONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1147 currentSslIssuedToUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), currentSslIssuedToUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1148 currentSslIssuedByCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), currentSslIssuedByCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1149 currentSslIssuedByONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), currentSslIssuedByONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1150 currentSslIssuedByUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), currentSslIssuedByUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1152 // Check the certificate Common Name against the domain name.
1153 boolean currentSslCommonNameMatchesDomainName = checkDomainNameAgainstCertificate(domainNameString, DomainsActivity.sslIssuedToCName);
1155 // Format the issued to Common Name color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1156 if (currentSslCommonNameMatchesDomainName) {
1157 currentSslIssuedToCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), currentSslIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1159 currentSslIssuedToCNameStringBuilder.setSpan(redColorSpan, cNameLabel.length(), currentSslIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1162 // Format the start date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1163 if (currentSslStartDate.after(currentDate)) { // The certificate start date is in the future.
1164 currentSslStartDateStringBuilder.setSpan(redColorSpan, startDateLabel.length(), currentSslStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1165 } else { // The certificate start date is in the past.
1166 currentSslStartDateStringBuilder.setSpan(blueColorSpan, startDateLabel.length(), currentSslStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1169 // Format the end date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1170 if (currentSslEndDate.before(currentDate)) { // The certificate end date is in the past.
1171 currentSslEndDateStringBuilder.setSpan(redColorSpan, endDateLabel.length(), currentSslEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1172 } else { // The certificate end date is in the future.
1173 currentSslEndDateStringBuilder.setSpan(blueColorSpan, endDateLabel.length(), currentSslEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1176 // Display the current website SSL certificate strings.
1177 currentSslIssuedToCNameTextView.setText(currentSslIssuedToCNameStringBuilder);
1178 currentSslIssuedToONameTextView.setText(currentSslIssuedToONameStringBuilder);
1179 currentSslIssuedToUNameTextView.setText(currentSslIssuedToUNameStringBuilder);
1180 currentSslIssuedByCNameTextView.setText(currentSslIssuedByCNameStringBuilder);
1181 currentSslIssuedByONameTextView.setText(currentSslIssuedByONameStringBuilder);
1182 currentSslIssuedByUNameTextView.setText(currentSslIssuedByUNameStringBuilder);
1183 currentSslStartDateTextView.setText(currentSslStartDateStringBuilder);
1184 currentSslEndDateTextView.setText(currentSslEndDateStringBuilder);
1187 // Set the initial display status of the SSL certificates card views.
1188 if (pinnedSslCertificateSwitch.isChecked()) { // An SSL certificate is pinned.
1189 // Set the visibility of the saved SSL certificate.
1190 if (savedSslIssuedToCNameString == null) {
1191 savedSslCardView.setVisibility(View.GONE);
1193 savedSslCardView.setVisibility(View.VISIBLE);
1196 // Set the visibility of the current website SSL certificate.
1197 if (DomainsActivity.sslIssuedToCName == null) { // There is no current SSL certificate.
1198 // Hide the SSL certificate.
1199 currentSslCardView.setVisibility(View.GONE);
1201 // Show the instruction.
1202 noCurrentWebsiteCertificateTextView.setVisibility(View.VISIBLE);
1203 } else { // There is a current SSL certificate.
1204 // Show the SSL certificate.
1205 currentSslCardView.setVisibility(View.VISIBLE);
1207 // Hide the instruction.
1208 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
1211 // Set the status of the radio buttons and the card view backgrounds.
1212 if (savedSslCardView.getVisibility() == View.VISIBLE) { // The saved SSL certificate is displayed.
1213 // Check the saved SSL certificate radio button.
1214 savedSslCertificateRadioButton.setChecked(true);
1216 // Uncheck the current website SSL certificate radio button.
1217 currentWebsiteCertificateRadioButton.setChecked(false);
1219 // Darken the background of the current website SSL certificate linear layout according to the theme.
1220 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1221 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
1223 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
1225 } else if (currentSslCardView.getVisibility() == View.VISIBLE) { // The saved SSL certificate is hidden but the current website SSL certificate is visible.
1226 // Check the current website SSL certificate radio button.
1227 currentWebsiteCertificateRadioButton.setChecked(true);
1229 // Uncheck the saved SSL certificate radio button.
1230 savedSslCertificateRadioButton.setChecked(false);
1231 } else { // Neither SSL certificate is visible.
1232 // Uncheck both radio buttons.
1233 savedSslCertificateRadioButton.setChecked(false);
1234 currentWebsiteCertificateRadioButton.setChecked(false);
1236 } else { // An SSL certificate is not pinned.
1237 // Hide the SSl certificates and instructions.
1238 savedSslCardView.setVisibility(View.GONE);
1239 currentSslCardView.setVisibility(View.GONE);
1240 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
1242 // Uncheck the radio buttons.
1243 savedSslCertificateRadioButton.setChecked(false);
1244 currentWebsiteCertificateRadioButton.setChecked(false);
1247 // Set the pinned IP addresses icon.
1248 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.
1249 // Check the switch.
1250 pinnedIpAddressesSwitch.setChecked(true);
1252 // Set the icon according to the theme.
1253 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1254 pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_night));
1256 pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_day));
1258 } else { // Pinned IP Addresses is disabled.
1259 // Uncheck the switch.
1260 pinnedIpAddressesSwitch.setChecked(false);
1262 // Set the icon according to the theme.
1263 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1264 pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_night));
1266 pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_day));
1270 // Populate the saved and current IP addresses.
1271 savedIpAddressesTextView.setText(savedIpAddresses);
1272 currentIpAddressesTextView.setText(DomainsActivity.currentIpAddresses);
1274 // Set the initial display status of the IP addresses card views.
1275 if (pinnedIpAddressesSwitch.isChecked()) { // IP addresses are pinned.
1276 // Set the visibility of the saved IP addresses.
1277 if (savedIpAddresses == null) { // There are no saved IP addresses.
1278 savedIpAddressesCardView.setVisibility(View.GONE);
1279 } else { // There are saved IP addresses.
1280 savedIpAddressesCardView.setVisibility(View.VISIBLE);
1283 // Set the visibility of the current IP addresses.
1284 currentIpAddressesCardView.setVisibility(View.VISIBLE);
1286 // Set the status of the radio buttons and the card view backgrounds.
1287 if (savedIpAddressesCardView.getVisibility() == View.VISIBLE) { // The saved IP addresses are displayed.
1288 // Check the saved IP addresses radio button.
1289 savedIpAddressesRadioButton.setChecked(true);
1291 // Uncheck the current IP addresses radio button.
1292 currentIpAddressesRadioButton.setChecked(false);
1294 // Darken the background of the current IP addresses linear layout according to the theme.
1295 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1296 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
1298 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
1300 } else { // The saved IP addresses are hidden.
1301 // Check the current IP addresses radio button.
1302 currentIpAddressesRadioButton.setChecked(true);
1304 // Uncheck the saved IP addresses radio button.
1305 savedIpAddressesRadioButton.setChecked(false);
1307 } else { // IP addresses are not pinned.
1308 // Hide the IP addresses card views.
1309 savedIpAddressesCardView.setVisibility(View.GONE);
1310 currentIpAddressesCardView.setVisibility(View.GONE);
1312 // Uncheck the radio buttons.
1313 savedIpAddressesRadioButton.setChecked(false);
1314 currentIpAddressesRadioButton.setChecked(false);
1318 // Set the JavaScript switch listener.
1319 javaScriptSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1320 if (isChecked) { // JavaScript is enabled.
1321 // Update the JavaScript icon.
1322 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.javascript_enabled));
1324 // Enable the DOM storage `Switch`.
1325 domStorageSwitch.setEnabled(true);
1327 // Update the DOM storage icon.
1328 if (domStorageSwitch.isChecked()) { // DOM storage is enabled.
1329 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_enabled));
1330 } else { // DOM storage is disabled.
1331 // Set the icon according to the theme.
1332 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1333 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_night));
1335 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_day));
1338 } else { // JavaScript is disabled.
1339 // Update the JavaScript icon.
1340 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.privacy_mode));
1342 // Disable the DOM storage `Switch`.
1343 domStorageSwitch.setEnabled(false);
1345 // Set the DOM storage icon according to the theme.
1346 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1347 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_night));
1349 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_day));
1354 // Set the first-party cookies switch listener.
1355 firstPartyCookiesSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1356 if (isChecked) { // First-party cookies are enabled.
1357 // Update the first-party cookies icon.
1358 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_enabled));
1360 // Enable the third-party cookies switch.
1361 thirdPartyCookiesSwitch.setEnabled(true);
1363 // Update the third-party cookies icon.
1364 if (thirdPartyCookiesSwitch.isChecked()) { // Third-party cookies are enabled.
1365 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_warning));
1366 } else { // Third-party cookies are disabled.
1367 // Set the third-party cookies icon according to the theme.
1368 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1369 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_night));
1371 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_day));
1374 } else { // First-party cookies are disabled.
1375 // Update the first-party cookies icon according to the theme.
1376 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1377 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_night));
1379 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_day));
1382 // Disable the third-party cookies switch.
1383 thirdPartyCookiesSwitch.setEnabled(false);
1385 // Set the third-party cookies icon according to the theme.
1386 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1387 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_ghosted_night));
1389 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_ghosted_day));
1394 // Set the third-party cookies switch listener.
1395 thirdPartyCookiesSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1398 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_warning));
1400 // Update the third-party cookies icon according to the theme.
1401 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1402 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_night));
1404 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_day));
1409 // Set the DOM Storage switch listener.
1410 domStorageSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1413 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_enabled));
1415 // Set the icon according to the theme.
1416 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1417 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_night));
1419 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_day));
1424 // Set the form data switch listener. It can be removed once the minimum API >= 26.
1425 if (Build.VERSION.SDK_INT < 26) {
1426 formDataSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1429 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_enabled));
1431 // Set the icon according to the theme.
1432 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1433 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_disabled_night));
1435 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_disabled_day));
1441 // Set the EasyList switch listener.
1442 easyListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1444 if (isChecked) { // EasyList is on.
1445 // Set the icon according to the theme.
1446 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1447 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_night));
1449 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_day));
1451 } else { // EasyList is off.
1452 // Set the icon according to the theme.
1453 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1454 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_night));
1456 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_day));
1461 // Set the EasyPrivacy switch listener.
1462 easyPrivacySwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1464 if (isChecked) { // EasyPrivacy is on.
1465 // Set the icon according to the theme.
1466 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1467 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_night));
1469 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_day));
1471 } else { // EasyPrivacy is off.
1472 // Set the icon according to the theme.
1473 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1474 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_night));
1476 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_day));
1481 // Set the Fanboy's Annoyance List switch listener.
1482 fanboysAnnoyanceListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1483 // Update the icon and Fanboy's Social Blocking List.
1484 if (isChecked) { // Fanboy's Annoyance List is on.
1485 // Set the icon according to the theme.
1486 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1487 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_night));
1489 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_day));
1492 // Disable the Fanboy's Social Blocking List switch.
1493 fanboysSocialBlockingListSwitch.setEnabled(false);
1495 // Update the Fanboy's Social Blocking List icon according to the theme.
1496 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1497 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_ghosted_night));
1499 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_ghosted_day));
1501 } else { // Fanboy's Annoyance List is off.
1502 // Set the icon according to the theme.
1503 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1504 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_night));
1506 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_day));
1509 // Enable the Fanboy's Social Blocking List switch.
1510 fanboysSocialBlockingListSwitch.setEnabled(true);
1512 // Update the Fanboy's Social Blocking List icon.
1513 if (fanboysSocialBlockingListSwitch.isChecked()) { // Fanboy's Social Blocking List is on.
1514 // Update the icon according to the theme.
1515 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1516 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_night));
1518 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_day));
1520 } else { // Fanboy's Social Blocking List is off.
1521 // Update the icon according to the theme.
1522 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1523 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_night));
1525 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_day));
1532 // Set the Fanboy's Social Blocking List switch listener.
1533 fanboysSocialBlockingListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1535 if (isChecked) { // Fanboy's Social Blocking List is on.
1536 // Set the icon according to the theme.
1537 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1538 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_night));
1540 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_day));
1542 } else { // Fanboy's Social Blocking List is off.
1543 // Set the icon according to the theme.
1544 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1545 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_night));
1547 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_day));
1552 // Set the UltraList switch listener.
1553 ultraListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1555 if (isChecked) { // UltraList is on.
1556 // Set the icon according to the theme.
1557 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1558 ultraListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_night));
1560 ultraListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_day));
1562 } else { // UltraList is off.
1563 // Set the icon according to the theme.
1564 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1565 ultraListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_night));
1567 ultraListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_day));
1572 // Set the UltraPrivacy switch listener.
1573 ultraPrivacySwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1575 if (isChecked) { // UltraPrivacy is on.
1576 // Set the icon according to the theme.
1577 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1578 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_night));
1580 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_day));
1582 } else { // UltraPrivacy is off.
1583 // Set the icon according to the theme.
1584 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1585 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_night));
1587 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_day));
1592 // Set the block all third-party requests switch listener.
1593 blockAllThirdPartyRequestsSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1595 if (isChecked) { // Blocking all third-party requests is on.
1596 // Set the icon according to the theme.
1597 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1598 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_enabled_night));
1600 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_enabled_day));
1602 } else { // Blocking all third-party requests is off.
1603 // Set the icon according to the theme.
1604 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1605 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_disabled_night));
1607 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_disabled_day));
1612 // Set the user agent spinner listener.
1613 userAgentSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1615 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1616 // Set the new user agent.
1618 case MainWebViewActivity.DOMAINS_SYSTEM_DEFAULT_USER_AGENT:
1619 // Show the user agent TextView.
1620 userAgentTextView.setVisibility(View.VISIBLE);
1622 // Hide the custom user agent EditText.
1623 customUserAgentEditText.setVisibility(View.GONE);
1625 // Set the user text.
1626 switch (defaultUserAgentArrayPosition) {
1627 case MainWebViewActivity.UNRECOGNIZED_USER_AGENT: // The default user agent name is not on the canonical list.
1628 // This is probably because it was set in an older version of Privacy Browser before the switch to persistent user agent names.
1629 userAgentTextView.setText(defaultUserAgentName);
1632 case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
1633 // Display the `WebView` default user agent.
1634 userAgentTextView.setText(webViewDefaultUserAgentString);
1637 case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
1638 // Display the custom user agent.
1639 userAgentTextView.setText(defaultCustomUserAgentString);
1643 // Get the user agent string from the user agent data array.
1644 userAgentTextView.setText(userAgentDataArray[defaultUserAgentArrayPosition]);
1648 case MainWebViewActivity.DOMAINS_WEBVIEW_DEFAULT_USER_AGENT:
1649 // Show the user agent TextView and set the text.
1650 userAgentTextView.setVisibility(View.VISIBLE);
1651 userAgentTextView.setText(webViewDefaultUserAgentString);
1653 // Hide the custom user agent EditTex.
1654 customUserAgentEditText.setVisibility(View.GONE);
1657 case MainWebViewActivity.DOMAINS_CUSTOM_USER_AGENT:
1658 // Hide the user agent TextView.
1659 userAgentTextView.setVisibility(View.GONE);
1661 // Show the custom user agent EditText and set the current user agent name as the text.
1662 customUserAgentEditText.setVisibility(View.VISIBLE);
1663 customUserAgentEditText.setText(currentUserAgentName);
1667 // 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.
1668 userAgentTextView.setVisibility(View.VISIBLE);
1669 userAgentTextView.setText(userAgentDataArray[position - 1]);
1671 // Hide `customUserAgentEditText`.
1672 customUserAgentEditText.setVisibility(View.GONE);
1677 public void onNothingSelected(AdapterView<?> parent) {
1682 // Set the font size spinner listener.
1683 fontSizeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1685 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1686 // Update the font size display options.
1687 if (position == 0) { // The system default font size has been selected.
1688 // Show the default font size text view.
1689 defaultFontSizeTextView.setVisibility(View.VISIBLE);
1691 // Hide the custom font size edit text.
1692 customFontSizeEditText.setVisibility(View.GONE);
1693 } else { // A custom font size has been selected.
1694 // Hide the default font size text view.
1695 defaultFontSizeTextView.setVisibility(View.GONE);
1697 // Show the custom font size edit text.
1698 customFontSizeEditText.setVisibility(View.VISIBLE);
1703 public void onNothingSelected(AdapterView<?> parent) {
1708 // Set the swipe to refresh spinner listener.
1709 swipeToRefreshSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1711 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1712 // 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.
1714 case DomainsDatabaseHelper.SYSTEM_DEFAULT:
1715 if (defaultSwipeToRefresh) { // Swipe to refresh enabled by default.
1716 // Set the icon according to the theme.
1717 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1718 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_night));
1720 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_day));
1722 } else { // Swipe to refresh disabled by default.
1723 // Set the icon according to the theme.
1724 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1725 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_night));
1727 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_day));
1731 // Show the swipe to refresh TextView.
1732 swipeToRefreshTextView.setVisibility(View.VISIBLE);
1735 case DomainsDatabaseHelper.ENABLED:
1736 // Set the icon according to the theme.
1737 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1738 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_night));
1740 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_day));
1743 // Hide the swipe to refresh TextView.
1744 swipeToRefreshTextView.setVisibility(View.GONE);
1747 case DomainsDatabaseHelper.DISABLED:
1748 // Set the icon according to the theme.
1749 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1750 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_night));
1752 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_day));
1755 // Hide the swipe to refresh TextView.
1756 swipeToRefreshTextView.setVisibility(View.GONE);
1761 public void onNothingSelected(AdapterView<?> parent) {
1766 // Set the night mode spinner listener.
1767 nightModeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1769 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1770 // 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.
1772 case DomainsDatabaseHelper.SYSTEM_DEFAULT:
1773 if (defaultNightMode) { // Night mode enabled by default.
1774 // Set the icon according to the theme.
1775 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1776 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_night));
1778 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_day));
1780 } else { // Night mode disabled by default.
1781 // Set the icon according to the theme.
1782 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1783 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_night));
1785 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_day));
1789 // Show the night mode TextView.
1790 nightModeTextView.setVisibility(View.VISIBLE);
1793 case DomainsDatabaseHelper.ENABLED:
1794 // Set the icon according to the theme.
1795 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1796 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_night));
1798 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_day));
1801 // Hide `nightModeTextView`.
1802 nightModeTextView.setVisibility(View.GONE);
1805 case DomainsDatabaseHelper.DISABLED:
1806 // Set the icon according to the theme.
1807 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1808 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_night));
1810 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_day));
1813 // Hide `nightModeTextView`.
1814 nightModeTextView.setVisibility(View.GONE);
1818 // Create a boolean to store the current night mode setting.
1819 boolean currentNightModeEnabled = (position == DomainsDatabaseHelper.ENABLED) || ((position == DomainsDatabaseHelper.SYSTEM_DEFAULT) && defaultNightMode);
1821 // Disable the JavaScript switch if night mode is enabled.
1822 if (currentNightModeEnabled) {
1823 javaScriptSwitch.setEnabled(false);
1825 javaScriptSwitch.setEnabled(true);
1828 // Update the JavaScript icon.
1829 if ((javaScriptInt == 1) || currentNightModeEnabled) {
1830 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.javascript_enabled));
1832 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.privacy_mode));
1835 // Update the DOM storage status.
1836 if ((javaScriptInt == 1) || currentNightModeEnabled) { // JavaScript is enabled.
1837 // Enable the DOM storage `Switch`.
1838 domStorageSwitch.setEnabled(true);
1840 // Set the DOM storage status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
1841 if (domStorageInt == 1) { // Both JavaScript and DOM storage are enabled.
1842 domStorageSwitch.setChecked(true);
1843 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_enabled));
1844 } else { // JavaScript is enabled but DOM storage is disabled.
1845 // Set the DOM storage switch to off.
1846 domStorageSwitch.setChecked(false);
1848 // Set the icon according to the theme.
1849 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1850 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_night));
1852 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_day));
1855 } else { // JavaScript is disabled.
1856 // Disable the DOM storage `Switch`.
1857 domStorageSwitch.setEnabled(false);
1859 // Set the checked status of DOM storage.
1860 if (domStorageInt == 1) { // DOM storage is enabled but JavaScript is disabled.
1861 domStorageSwitch.setChecked(true);
1862 } else { // Both JavaScript and DOM storage are disabled.
1863 domStorageSwitch.setChecked(false);
1866 // Set the icon according to the theme.
1867 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1868 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_night));
1870 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_day));
1876 public void onNothingSelected(AdapterView<?> parent) {
1881 // Set the wide viewport spinner listener.
1882 wideViewportSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1884 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1885 // Update the icon and the visibility of the wide viewport text view.
1887 case DomainsDatabaseHelper.SYSTEM_DEFAULT:
1888 if (defaultWideViewport) { // Wide viewport is enabled by default.
1889 // Set the icon according to the theme.
1890 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1891 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_enabled_night));
1893 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_enabled_day));
1895 } else { // Wide viewport is disabled by default.
1896 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1897 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_disabled_night));
1899 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_disabled_day));
1903 // Show the wide viewport text view.
1904 wideViewportTextView.setVisibility(View.VISIBLE);
1907 case DomainsDatabaseHelper.ENABLED:
1908 // Set the icon according to the theme.
1909 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1910 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_enabled_night));
1912 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_enabled_day));
1915 // Hide the wide viewport text view.
1916 wideViewportTextView.setVisibility(View.GONE);
1919 case DomainsDatabaseHelper.DISABLED:
1920 // Set the icon according to the theme.
1921 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1922 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_disabled_night));
1924 wideViewportImageView.setImageDrawable(resources.getDrawable(R.drawable.wide_viewport_disabled_day));
1927 // Hid ethe wide viewport text view.
1928 wideViewportTextView.setVisibility(View.GONE);
1934 public void onNothingSelected(AdapterView<?> parent) {
1939 // Set the display webpage images spinner listener.
1940 displayWebpageImagesSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1942 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1943 // Update the icon and the visibility of the display images text view.
1945 case DomainsDatabaseHelper.SYSTEM_DEFAULT:
1946 if (defaultDisplayWebpageImages) { // Display webpage images is enabled by default.
1947 // Set the icon according to the theme.
1948 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1949 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_night));
1951 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_day));
1953 } else { // Display webpage images is disabled by default.
1954 // Set the icon according to the theme.
1955 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1956 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_night));
1958 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_day));
1962 // Show the display images text view.
1963 displayImagesTextView.setVisibility(View.VISIBLE);
1966 case DomainsDatabaseHelper.ENABLED:
1967 // Set the icon according to the theme.
1968 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1969 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_night));
1971 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_day));
1974 // Hide the display images text view.
1975 displayImagesTextView.setVisibility(View.GONE);
1978 case DomainsDatabaseHelper.DISABLED:
1979 // Set the icon according to the theme.
1980 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1981 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_night));
1983 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_day));
1986 // Hide the display images text view.
1987 displayImagesTextView.setVisibility(View.GONE);
1993 public void onNothingSelected(AdapterView<?> parent) {
1998 // Set the pinned SSL certificate switch listener.
1999 pinnedSslCertificateSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
2001 if (isChecked) { // SSL certificate pinning is enabled.
2002 // Set the icon according to the theme.
2003 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2004 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_night));
2006 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_day));
2009 // Update the visibility of the saved SSL certificate.
2010 if (savedSslIssuedToCNameString == null) {
2011 savedSslCardView.setVisibility(View.GONE);
2013 savedSslCardView.setVisibility(View.VISIBLE);
2016 // Update the visibility of the current website SSL certificate.
2017 if (DomainsActivity.sslIssuedToCName == null) {
2018 // Hide the SSL certificate.
2019 currentSslCardView.setVisibility(View.GONE);
2021 // Show the instruction.
2022 noCurrentWebsiteCertificateTextView.setVisibility(View.VISIBLE);
2024 // Show the SSL certificate.
2025 currentSslCardView.setVisibility(View.VISIBLE);
2027 // Hide the instruction.
2028 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
2031 // Set the status of the radio buttons.
2032 if (savedSslCardView.getVisibility() == View.VISIBLE) { // The saved SSL certificate is displayed.
2033 // Check the saved SSL certificate radio button.
2034 savedSslCertificateRadioButton.setChecked(true);
2036 // Uncheck the current website SSL certificate radio button.
2037 currentWebsiteCertificateRadioButton.setChecked(false);
2039 // Set the background of the saved SSL certificate linear layout to be transparent.
2040 savedSslCertificateLinearLayout.setBackgroundResource(R.color.transparent);
2042 // Darken the background of the current website SSL certificate linear layout according to the theme.
2043 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2044 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2046 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2049 // Scroll to the current website SSL certificate card.
2050 savedSslCardView.getParent().requestChildFocus(savedSslCardView, savedSslCardView);
2051 } else if (currentSslCardView.getVisibility() == View.VISIBLE) { // The saved SSL certificate is hidden but the current website SSL certificate is visible.
2052 // Check the current website SSL certificate radio button.
2053 currentWebsiteCertificateRadioButton.setChecked(true);
2055 // Uncheck the saved SSL certificate radio button.
2056 savedSslCertificateRadioButton.setChecked(false);
2058 // Set the background of the current website SSL certificate linear layout to be transparent.
2059 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.transparent);
2061 // Darken the background of the saved SSL certificate linear layout according to the theme.
2062 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2063 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2065 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2068 // Scroll to the current website SSL certificate card.
2069 currentSslCardView.getParent().requestChildFocus(currentSslCardView, currentSslCardView);
2070 } else { // Neither SSL certificate is visible.
2071 // Uncheck both radio buttons.
2072 savedSslCertificateRadioButton.setChecked(false);
2073 currentWebsiteCertificateRadioButton.setChecked(false);
2075 // Scroll to the current website SSL certificate card.
2076 noCurrentWebsiteCertificateTextView.getParent().requestChildFocus(noCurrentWebsiteCertificateTextView, noCurrentWebsiteCertificateTextView);
2078 } else { // SSL certificate pinning is disabled.
2079 // Set the icon according to the theme.
2080 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2081 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_night));
2083 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_day));
2086 // Hide the SSl certificates and instructions.
2087 savedSslCardView.setVisibility(View.GONE);
2088 currentSslCardView.setVisibility(View.GONE);
2089 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
2091 // Uncheck the radio buttons.
2092 savedSslCertificateRadioButton.setChecked(false);
2093 currentWebsiteCertificateRadioButton.setChecked(false);
2097 savedSslCardView.setOnClickListener((View view) -> {
2098 // Check the saved SSL certificate radio button.
2099 savedSslCertificateRadioButton.setChecked(true);
2101 // Uncheck the current website SSL certificate radio button.
2102 currentWebsiteCertificateRadioButton.setChecked(false);
2104 // Set the background of the saved SSL certificate linear layout to be transparent.
2105 savedSslCertificateLinearLayout.setBackgroundResource(R.color.transparent);
2107 // Darken the background of the current website SSL certificate linear layout according to the theme.
2108 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2109 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2111 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2115 savedSslCertificateRadioButton.setOnClickListener((View view) -> {
2116 // Check the saved SSL certificate radio button.
2117 savedSslCertificateRadioButton.setChecked(true);
2119 // Uncheck the current website SSL certificate radio button.
2120 currentWebsiteCertificateRadioButton.setChecked(false);
2122 // Set the background of the saved SSL certificate linear layout to be transparent.
2123 savedSslCertificateLinearLayout.setBackgroundResource(R.color.transparent);
2125 // Darken the background of the current website SSL certificate linear layout according to the theme.
2126 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2127 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2129 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2133 currentSslCardView.setOnClickListener((View view) -> {
2134 // Check the current website SSL certificate radio button.
2135 currentWebsiteCertificateRadioButton.setChecked(true);
2137 // Uncheck the saved SSL certificate radio button.
2138 savedSslCertificateRadioButton.setChecked(false);
2140 // Set the background of the current website SSL certificate linear layout to be transparent.
2141 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.transparent);
2143 // Darken the background of the saved SSL certificate linear layout according to the theme.
2144 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2145 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2147 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2151 currentWebsiteCertificateRadioButton.setOnClickListener((View view) -> {
2152 // Check the current website SSL certificate radio button.
2153 currentWebsiteCertificateRadioButton.setChecked(true);
2155 // Uncheck the saved SSL certificate radio button.
2156 savedSslCertificateRadioButton.setChecked(false);
2158 // Set the background of the current website SSL certificate linear layout to be transparent.
2159 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.transparent);
2161 // Darken the background of the saved SSL certificate linear layout according to the theme.
2162 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2163 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2165 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2169 // Set the pinned IP addresses switch listener.
2170 pinnedIpAddressesSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
2172 if (isChecked) { // IP addresses pinning is enabled.
2173 // Set the icon according to the theme.
2174 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2175 pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_night));
2177 pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_day));
2180 // Update the visibility of the saved IP addresses card view.
2181 if (savedIpAddresses == null) { // There are no saved IP addresses.
2182 savedIpAddressesCardView.setVisibility(View.GONE);
2183 } else { // There are saved IP addresses.
2184 savedIpAddressesCardView.setVisibility(View.VISIBLE);
2187 // Show the current IP addresses card view.
2188 currentIpAddressesCardView.setVisibility(View.VISIBLE);
2190 // Set the status of the radio buttons.
2191 if (savedIpAddressesCardView.getVisibility() == View.VISIBLE) { // The saved IP addresses are visible.
2192 // Check the saved IP addresses radio button.
2193 savedIpAddressesRadioButton.setChecked(true);
2195 // Uncheck the current IP addresses radio button.
2196 currentIpAddressesRadioButton.setChecked(false);
2198 // Set the background of the saved IP addresses linear layout to be transparent.
2199 savedSslCertificateLinearLayout.setBackgroundResource(R.color.transparent);
2201 // Darken the background of the current IP addresses linear layout according to the theme.
2202 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2203 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2205 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2207 } else { // The saved IP addresses are not visible.
2208 // Check the current IP addresses radio button.
2209 currentIpAddressesRadioButton.setChecked(true);
2211 // Uncheck the saved IP addresses radio button.
2212 savedIpAddressesRadioButton.setChecked(false);
2214 // Set the background of the current IP addresses linear layout to be transparent.
2215 currentIpAddressesLinearLayout.setBackgroundResource(R.color.transparent);
2217 // Darken the background of the saved IP addresses linear layout according to the theme.
2218 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2219 savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2221 savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2225 // Scroll to the bottom of the card views.
2226 currentIpAddressesCardView.getParent().requestChildFocus(currentIpAddressesCardView, currentIpAddressesCardView);
2227 } else { // IP addresses pinning is disabled.
2228 // Set the icon according to the theme.
2229 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2230 pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_night));
2232 pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_day));
2235 // Hide the IP addresses card views.
2236 savedIpAddressesCardView.setVisibility(View.GONE);
2237 currentIpAddressesCardView.setVisibility(View.GONE);
2239 // Uncheck the radio buttons.
2240 savedIpAddressesRadioButton.setChecked(false);
2241 currentIpAddressesRadioButton.setChecked(false);
2245 savedIpAddressesCardView.setOnClickListener((View view) -> {
2246 // Check the saved IP addresses radio button.
2247 savedIpAddressesRadioButton.setChecked(true);
2249 // Uncheck the current website IP addresses radio button.
2250 currentIpAddressesRadioButton.setChecked(false);
2252 // Set the background of the saved IP addresses linear layout to be transparent.
2253 savedIpAddressesLinearLayout.setBackgroundResource(R.color.transparent);
2255 // Darken the background of the current IP addresses linear layout according to the theme.
2256 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2257 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2259 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2263 savedIpAddressesRadioButton.setOnClickListener((View view) -> {
2264 // Check the saved IP addresses radio button.
2265 savedIpAddressesRadioButton.setChecked(true);
2267 // Uncheck the current website IP addresses radio button.
2268 currentIpAddressesRadioButton.setChecked(false);
2270 // Set the background of the saved IP addresses linear layout to be transparent.
2271 savedIpAddressesLinearLayout.setBackgroundResource(R.color.transparent);
2273 // Darken the background of the current IP addresses linear layout according to the theme.
2274 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2275 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2277 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2281 currentIpAddressesCardView.setOnClickListener((View view) -> {
2282 // Check the current IP addresses radio button.
2283 currentIpAddressesRadioButton.setChecked(true);
2285 // Uncheck the saved IP addresses radio button.
2286 savedIpAddressesRadioButton.setChecked(false);
2288 // Set the background of the current IP addresses linear layout to be transparent.
2289 currentIpAddressesLinearLayout.setBackgroundResource(R.color.transparent);
2291 // Darken the background of the saved IP addresses linear layout according to the theme.
2292 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2293 savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2295 savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2299 currentIpAddressesRadioButton.setOnClickListener((View view) -> {
2300 // Check the current IP addresses radio button.
2301 currentIpAddressesRadioButton.setChecked(true);
2303 // Uncheck the saved IP addresses radio button.
2304 savedIpAddressesRadioButton.setChecked(false);
2306 // Set the background of the current IP addresses linear layout to be transparent.
2307 currentIpAddressesLinearLayout.setBackgroundResource(R.color.transparent);
2309 // Darken the background of the saved IP addresses linear layout according to the theme.
2310 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
2311 savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2313 savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2317 return domainSettingsView;
2320 private boolean checkDomainNameAgainstCertificate(String domainName, String certificateCommonName) {
2321 // Initialize `domainNamesMatch`.
2322 boolean domainNamesMatch = false;
2324 // Check various wildcard permutations if `domainName` and `certificateCommonName` are not empty.
2325 // `noinspection ConstantCondition` removes Android Studio's incorrect lint warning that `domainName` can never be `null`.
2326 if ((domainName != null) && (certificateCommonName != null)) {
2327 // Check if the domains match.
2328 if (domainName.equals(certificateCommonName)) {
2329 domainNamesMatch = true;
2332 // If `domainName` starts with a wildcard, check the base domain against all the subdomains of `certificateCommonName`.
2333 if (!domainNamesMatch && domainName.startsWith("*.") && (domainName.length() > 2)) {
2334 // Remove the initial `*.`.
2335 String baseDomainName = domainName.substring(2);
2337 // Setup a copy of `certificateCommonName` to test subdomains.
2338 String certificateCommonNameSubdomain = certificateCommonName;
2340 // Check all the subdomains in `certificateCommonNameSubdomain` against `baseDomainName`.
2341 while (!domainNamesMatch && certificateCommonNameSubdomain.contains(".")) { // Stop checking if we know that `domainNamesMatch` is `true` or if we run out of `.`.
2342 // Test the `certificateCommonNameSubdomain` against `baseDomainName`.
2343 if (certificateCommonNameSubdomain.equals(baseDomainName)) {
2344 domainNamesMatch = true;
2347 // Strip out the lowest subdomain of `certificateCommonNameSubdomain`.
2349 certificateCommonNameSubdomain = certificateCommonNameSubdomain.substring(certificateCommonNameSubdomain.indexOf(".") + 1);
2350 } catch (IndexOutOfBoundsException e) { // `certificateCommonNameSubdomain` ends with `.`.
2351 certificateCommonNameSubdomain = "";
2356 // If `certificateCommonName` starts with a wildcard, check the base common name against all the subdomains of `domainName`.
2357 if (!domainNamesMatch && certificateCommonName.startsWith("*.") && (certificateCommonName.length() > 2)) {
2358 // Remove the initial `*.`.
2359 String baseCertificateCommonName = certificateCommonName.substring(2);
2361 // Setup a copy of `domainName` to test subdomains.
2362 String domainNameSubdomain = domainName;
2364 // Check all the subdomains in `domainNameSubdomain` against `baseCertificateCommonName`.
2365 while (!domainNamesMatch && domainNameSubdomain.contains(".") && (domainNameSubdomain.length() > 2)) {
2366 // Test the `domainNameSubdomain` against `baseCertificateCommonName`.
2367 if (domainNameSubdomain.equals(baseCertificateCommonName)) {
2368 domainNamesMatch = true;
2371 // Strip out the lowest subdomain of `domainNameSubdomain`.
2373 domainNameSubdomain = domainNameSubdomain.substring(domainNameSubdomain.indexOf(".") + 1);
2374 } catch (IndexOutOfBoundsException e) { // `domainNameSubdomain` ends with `.`.
2375 domainNameSubdomain = "";
2380 // If both names start with a wildcard, check if the root of one contains the root of the other.
2381 if (!domainNamesMatch && domainName.startsWith("*.") && (domainName.length() > 2) && certificateCommonName.startsWith("*.") && (certificateCommonName.length() > 2)) {
2382 // Remove the wildcards.
2383 String rootDomainName = domainName.substring(2);
2384 String rootCertificateCommonName = certificateCommonName.substring(2);
2386 // Check if one name ends with the contents of the other. If so, there will be overlap in the their wildcard subdomains.
2387 if (rootDomainName.endsWith(rootCertificateCommonName) || rootCertificateCommonName.endsWith(rootDomainName)) {
2388 domainNamesMatch = true;
2393 return domainNamesMatch;