2 * Copyright © 2017-2019 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.Resources;
26 import android.database.Cursor;
27 import android.net.http.SslCertificate;
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 super.onCreate(savedInstanceState);
75 // Remove the lint warning that `getArguments` might be null.
76 assert getArguments() != null;
78 // Store the database id in `databaseId`.
79 databaseId = getArguments().getInt(DATABASE_ID);
82 // The deprecated `getDrawable()` must be used until the minimum API >= 21.
84 public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
85 // Inflate `domain_settings_fragment`. `false` does not attach it to the root `container`.
86 View domainSettingsView = inflater.inflate(R.layout.domain_settings_fragment, container, false);
88 // Get a handle for the context and the resources.
89 Context context = getContext();
90 final Resources resources = getResources();
92 // Get a handle for the shared preference.
93 SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
95 // Store the default settings.
96 final String defaultUserAgentName = sharedPreferences.getString("user_agent", getString(R.string.user_agent_default_value));
97 final String defaultCustomUserAgentString = sharedPreferences.getString("custom_user_agent", getString(R.string.custom_user_agent_default_value));
98 String defaultFontSizeString = sharedPreferences.getString("font_size", getString(R.string.font_size_default_value));
99 boolean defaultSwipeToRefresh = sharedPreferences.getBoolean("swipe_to_refresh", true);
100 final boolean defaultNightMode = sharedPreferences.getBoolean("night_mode", false);
101 final boolean defaultDisplayWebpageImages = sharedPreferences.getBoolean("display_webpage_images", true);
103 // Get handles for the views in the fragment.
104 final EditText domainNameEditText = domainSettingsView.findViewById(R.id.domain_settings_name_edittext);
105 final Switch javaScriptEnabledSwitch = domainSettingsView.findViewById(R.id.javascript_switch);
106 final ImageView javaScriptImageView = domainSettingsView.findViewById(R.id.javascript_imageview);
107 Switch firstPartyCookiesEnabledSwitch = domainSettingsView.findViewById(R.id.first_party_cookies_switch);
108 final ImageView firstPartyCookiesImageView = domainSettingsView.findViewById(R.id.first_party_cookies_imageview);
109 LinearLayout thirdPartyCookiesLinearLayout = domainSettingsView.findViewById(R.id.third_party_cookies_linearlayout);
110 final Switch thirdPartyCookiesEnabledSwitch = domainSettingsView.findViewById(R.id.third_party_cookies_switch);
111 final ImageView thirdPartyCookiesImageView = domainSettingsView.findViewById(R.id.third_party_cookies_imageview);
112 final Switch domStorageEnabledSwitch = domainSettingsView.findViewById(R.id.dom_storage_switch);
113 final ImageView domStorageImageView = domainSettingsView.findViewById(R.id.dom_storage_imageview);
114 Switch formDataEnabledSwitch = domainSettingsView.findViewById(R.id.form_data_switch); // The form data views can be remove once the minimum API >= 26.
115 final ImageView formDataImageView = domainSettingsView.findViewById(R.id.form_data_imageview); // The form data views can be remove once the minimum API >= 26.
116 Switch easyListSwitch = domainSettingsView.findViewById(R.id.easylist_switch);
117 ImageView easyListImageView = domainSettingsView.findViewById(R.id.easylist_imageview);
118 Switch easyPrivacySwitch = domainSettingsView.findViewById(R.id.easyprivacy_switch);
119 ImageView easyPrivacyImageView = domainSettingsView.findViewById(R.id.easyprivacy_imageview);
120 Switch fanboysAnnoyanceListSwitch = domainSettingsView.findViewById(R.id.fanboys_annoyance_list_switch);
121 ImageView fanboysAnnoyanceListImageView = domainSettingsView.findViewById(R.id.fanboys_annoyance_list_imageview);
122 Switch fanboysSocialBlockingListSwitch = domainSettingsView.findViewById(R.id.fanboys_social_blocking_list_switch);
123 ImageView fanboysSocialBlockingListImageView = domainSettingsView.findViewById(R.id.fanboys_social_blocking_list_imageview);
124 Switch ultraPrivacySwitch = domainSettingsView.findViewById(R.id.ultraprivacy_switch);
125 ImageView ultraPrivacyImageView = domainSettingsView.findViewById(R.id.ultraprivacy_imageview);
126 Switch blockAllThirdPartyRequestsSwitch = domainSettingsView.findViewById(R.id.block_all_third_party_requests_switch);
127 ImageView blockAllThirdPartyRequestsImageView = domainSettingsView.findViewById(R.id.block_all_third_party_requests_imageview);
128 final Spinner userAgentSpinner = domainSettingsView.findViewById(R.id.user_agent_spinner);
129 final TextView userAgentTextView = domainSettingsView.findViewById(R.id.user_agent_textview);
130 final EditText customUserAgentEditText = domainSettingsView.findViewById(R.id.custom_user_agent_edittext);
131 final Spinner fontSizeSpinner = domainSettingsView.findViewById(R.id.font_size_spinner);
132 final TextView fontSizeTextView = domainSettingsView.findViewById(R.id.font_size_textview);
133 final ImageView swipeToRefreshImageView = domainSettingsView.findViewById(R.id.swipe_to_refresh_imageview);
134 final Spinner swipeToRefreshSpinner = domainSettingsView.findViewById(R.id.swipe_to_refresh_spinner);
135 final TextView swipeToRefreshTextView = domainSettingsView.findViewById(R.id.swipe_to_refresh_textview);
136 final ImageView nightModeImageView = domainSettingsView.findViewById(R.id.night_mode_imageview);
137 final Spinner nightModeSpinner = domainSettingsView.findViewById(R.id.night_mode_spinner);
138 final TextView nightModeTextView = domainSettingsView.findViewById(R.id.night_mode_textview);
139 final ImageView displayWebpageImagesImageView = domainSettingsView.findViewById(R.id.display_webpage_images_imageview);
140 final Spinner displayWebpageImagesSpinner = domainSettingsView.findViewById(R.id.display_webpage_images_spinner);
141 final TextView displayImagesTextView = domainSettingsView.findViewById(R.id.display_webpage_images_textview);
142 final ImageView pinnedSslCertificateImageView = domainSettingsView.findViewById(R.id.pinned_ssl_certificate_imageview);
143 Switch pinnedSslCertificateSwitch = domainSettingsView.findViewById(R.id.pinned_ssl_certificate_switch);
144 final CardView savedSslCertificateCardView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_cardview);
145 LinearLayout savedSslCertificateLinearLayout = domainSettingsView.findViewById(R.id.saved_ssl_certificate_linearlayout);
146 final RadioButton savedSslCertificateRadioButton = domainSettingsView.findViewById(R.id.saved_ssl_certificate_radiobutton);
147 final TextView savedSslCertificateIssuedToCNameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_to_cname);
148 TextView savedSslCertificateIssuedToONameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_to_oname);
149 TextView savedSslCertificateIssuedToUNameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_to_uname);
150 TextView savedSslCertificateIssuedByCNameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_by_cname);
151 TextView savedSslCertificateIssuedByONameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_by_oname);
152 TextView savedSslCertificateIssuedByUNameTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_issued_by_uname);
153 TextView savedSslCertificateStartDateTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_start_date);
154 TextView savedSslCertificateEndDateTextView = domainSettingsView.findViewById(R.id.saved_ssl_certificate_end_date);
155 final CardView currentWebsiteCertificateCardView = domainSettingsView.findViewById(R.id.current_website_certificate_cardview);
156 LinearLayout currentWebsiteCertificateLinearLayout = domainSettingsView.findViewById(R.id.current_website_certificate_linearlayout);
157 final RadioButton currentWebsiteCertificateRadioButton = domainSettingsView.findViewById(R.id.current_website_certificate_radiobutton);
158 final TextView currentWebsiteCertificateIssuedToCNameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_to_cname);
159 TextView currentWebsiteCertificateIssuedToONameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_to_oname);
160 TextView currentWebsiteCertificateIssuedToUNameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_to_uname);
161 TextView currentWebsiteCertificateIssuedByCNameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_by_cname);
162 TextView currentWebsiteCertificateIssuedByONameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_by_oname);
163 TextView currentWebsiteCertificateIssuedByUNameTextView = domainSettingsView.findViewById(R.id.current_website_certificate_issued_by_uname);
164 TextView currentWebsiteCertificateStartDateTextView = domainSettingsView.findViewById(R.id.current_website_certificate_start_date);
165 TextView currentWebsiteCertificateEndDateTextView = domainSettingsView.findViewById(R.id.current_website_certificate_end_date);
166 final TextView noCurrentWebsiteCertificateTextView = domainSettingsView.findViewById(R.id.no_current_website_certificate);
167 ImageView pinnedIpAddressesImageView = domainSettingsView.findViewById(R.id.pinned_ip_addresses_imageview);
168 Switch pinnedIpAddressesSwitch = domainSettingsView.findViewById(R.id.pinned_ip_addresses_switch);
169 CardView savedIpAddressesCardView = domainSettingsView.findViewById(R.id.saved_ip_addresses_cardview);
170 LinearLayout savedIpAddressesLinearLayout = domainSettingsView.findViewById(R.id.saved_ip_addresses_linearlayout);
171 RadioButton savedIpAddressesRadioButton = domainSettingsView.findViewById(R.id.saved_ip_addresses_radiobutton);
172 TextView savedIpAddressesTextView = domainSettingsView.findViewById(R.id.saved_ip_addresses_textview);
173 CardView currentIpAddressesCardView = domainSettingsView.findViewById(R.id.current_ip_addresses_cardview);
174 LinearLayout currentIpAddressesLinearLayout = domainSettingsView.findViewById(R.id.current_ip_addresses_linearlayout);
175 RadioButton currentIpAddressesRadioButton = domainSettingsView.findViewById(R.id.current_ip_addresses_radiobutton);
176 TextView currentIpAddressesTextView = domainSettingsView.findViewById(R.id.current_ip_addresses_textview);
178 // Setup the pinned labels.
179 String cNameLabel = getString(R.string.common_name) + " ";
180 String oNameLabel = getString(R.string.organization) + " ";
181 String uNameLabel = getString(R.string.organizational_unit) + " ";
182 String startDateLabel = getString(R.string.start_date) + " ";
183 String endDateLabel = getString(R.string.end_date) + " ";
185 // Get the current website SSL certificate
186 final SslCertificate currentWebsiteSslCertificate = DomainsActivity.currentSslCertificate;
188 // Initialize the database handler. The `0` specifies the database version, but that is ignored and set instead using a constant in `DomainsDatabaseHelper`.
189 DomainsDatabaseHelper domainsDatabaseHelper = new DomainsDatabaseHelper(context, null, null, 0);
191 // Get the database cursor for this ID and move it to the first row.
192 Cursor domainCursor = domainsDatabaseHelper.getCursorForId(databaseId);
193 domainCursor.moveToFirst();
195 // Save the cursor entries as variables.
196 String domainNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.DOMAIN_NAME));
197 final int javaScriptEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_JAVASCRIPT));
198 int firstPartyCookiesEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FIRST_PARTY_COOKIES));
199 int thirdPartyCookiesEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_THIRD_PARTY_COOKIES));
200 final int domStorageEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_DOM_STORAGE));
201 int formDataEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FORM_DATA)); // Form data can be remove once the minimum API >= 26.
202 int easyListEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYLIST));
203 int easyPrivacyEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYPRIVACY));
204 int fanboysAnnoyanceListInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST));
205 int fanboysSocialBlockingListInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST));
206 int ultraPrivacyEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY));
207 int blockAllThirdPartyRequestsInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS));
208 final String currentUserAgentName = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.USER_AGENT));
209 int fontSizeInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.FONT_SIZE));
210 int swipeToRefreshInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.SWIPE_TO_REFRESH));
211 int nightModeInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.NIGHT_MODE));
212 int displayImagesInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.DISPLAY_IMAGES));
213 int pinnedSslCertificateInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.PINNED_SSL_CERTIFICATE));
214 String savedSslCertificateIssuedToCNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_COMMON_NAME));
215 String savedSslCertificateIssuedToONameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATION));
216 String savedSslCertificateIssuedToUNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATIONAL_UNIT));
217 String savedSslCertificateIssuedByCNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_COMMON_NAME));
218 String savedSslCertificateIssuedByONameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATION));
219 String savedSslCertificateIssuedByUNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATIONAL_UNIT));
220 int pinnedIpAddressesInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.PINNED_IP_ADDRESSES));
221 String savedIpAddresses = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.IP_ADDRESSES));
223 // Initialize the saved SSL certificate date variables.
224 Date savedSslCertificateStartDate = null;
225 Date savedSslCertificateEndDate = null;
227 // Only get the saved SSL certificate dates from the cursor if they are not set to `0`.
228 if (domainCursor.getLong(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_START_DATE)) != 0) {
229 savedSslCertificateStartDate = new Date(domainCursor.getLong(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_START_DATE)));
232 if (domainCursor.getLong(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_END_DATE)) != 0) {
233 savedSslCertificateEndDate = new Date(domainCursor.getLong(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_END_DATE)));
236 // Create array adapters for the spinners.
237 ArrayAdapter<CharSequence> translatedUserAgentArrayAdapter = ArrayAdapter.createFromResource(context, R.array.translated_domain_settings_user_agent_names, R.layout.spinner_item);
238 ArrayAdapter<CharSequence> fontSizeArrayAdapter = ArrayAdapter.createFromResource(context, R.array.domain_settings_font_size_entries, R.layout.spinner_item);
239 ArrayAdapter<CharSequence> fontSizeEntryValuesArrayAdapter = ArrayAdapter.createFromResource(context, R.array.domain_settings_font_size_entry_values, R.layout.spinner_item);
240 ArrayAdapter<CharSequence> swipeToRefreshArrayAdapter = ArrayAdapter.createFromResource(context, R.array.swipe_to_refresh_array, R.layout.spinner_item);
241 ArrayAdapter<CharSequence> nightModeArrayAdapter = ArrayAdapter.createFromResource(context, R.array.night_mode_array, R.layout.spinner_item);
242 ArrayAdapter<CharSequence> displayImagesArrayAdapter = ArrayAdapter.createFromResource(context, R.array.display_webpage_images_array, R.layout.spinner_item);
244 // Set the drop down view resource on the spinners.
245 translatedUserAgentArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items);
246 fontSizeArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items);
247 swipeToRefreshArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items);
248 nightModeArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items);
249 displayImagesArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items);
251 // Set the array adapters for the spinners.
252 userAgentSpinner.setAdapter(translatedUserAgentArrayAdapter);
253 fontSizeSpinner.setAdapter(fontSizeArrayAdapter);
254 swipeToRefreshSpinner.setAdapter(swipeToRefreshArrayAdapter);
255 nightModeSpinner.setAdapter(nightModeArrayAdapter);
256 displayWebpageImagesSpinner.setAdapter(displayImagesArrayAdapter);
258 // Create a spannable string builder for each TextView that needs multiple colors of text.
259 SpannableStringBuilder savedSslCertificateIssuedToCNameStringBuilder = new SpannableStringBuilder(cNameLabel + savedSslCertificateIssuedToCNameString);
260 SpannableStringBuilder savedSslCertificateIssuedToONameStringBuilder = new SpannableStringBuilder(oNameLabel + savedSslCertificateIssuedToONameString);
261 SpannableStringBuilder savedSslCertificateIssuedToUNameStringBuilder = new SpannableStringBuilder(uNameLabel + savedSslCertificateIssuedToUNameString);
262 SpannableStringBuilder savedSslCertificateIssuedByCNameStringBuilder = new SpannableStringBuilder(cNameLabel + savedSslCertificateIssuedByCNameString);
263 SpannableStringBuilder savedSslCertificateIssuedByONameStringBuilder = new SpannableStringBuilder(oNameLabel + savedSslCertificateIssuedByONameString);
264 SpannableStringBuilder savedSslCertificateIssuedByUNameStringBuilder = new SpannableStringBuilder(uNameLabel + savedSslCertificateIssuedByUNameString);
266 // Initialize the spannable string builders for the SSL certificate dates.
267 SpannableStringBuilder savedSslCertificateStartDateStringBuilder;
268 SpannableStringBuilder savedSslCertificateEndDateStringBuilder;
270 // Leave the SSL certificate dates empty if they are `null`.
271 if (savedSslCertificateStartDate == null) {
272 savedSslCertificateStartDateStringBuilder = new SpannableStringBuilder(startDateLabel);
274 savedSslCertificateStartDateStringBuilder = new SpannableStringBuilder(startDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG).format(savedSslCertificateStartDate));
277 if (savedSslCertificateEndDate == null) {
278 savedSslCertificateEndDateStringBuilder = new SpannableStringBuilder(endDateLabel);
280 savedSslCertificateEndDateStringBuilder = new SpannableStringBuilder(endDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG).format(savedSslCertificateEndDate));
283 // Create a red foreground color span. The deprecated `resources.getColor` must be used until the minimum API >= 23.
284 final ForegroundColorSpan redColorSpan = new ForegroundColorSpan(resources.getColor(R.color.red_a700));
286 // Create a blue foreground color span.
287 final ForegroundColorSpan blueColorSpan;
289 // Set the blue color span according to the theme. The deprecated `resources.getColor` must be used until the minimum API >= 23.
290 if (MainWebViewActivity.darkTheme) {
291 //noinspection deprecation
292 blueColorSpan = new ForegroundColorSpan(resources.getColor(R.color.blue_400));
294 //noinspection deprecation
295 blueColorSpan = new ForegroundColorSpan(resources.getColor(R.color.blue_700));
298 // Set the domain name from the the database cursor.
299 domainNameEditText.setText(domainNameString);
301 // Update the certificates' `Common Name` color when the domain name text changes.
302 domainNameEditText.addTextChangedListener(new TextWatcher() {
304 public void beforeTextChanged(CharSequence s, int start, int count, int after) {
309 public void onTextChanged(CharSequence s, int start, int before, int count) {
314 public void afterTextChanged(Editable s) {
315 // Get the new domain name.
316 String newDomainName = domainNameEditText.getText().toString();
318 // Check the saved SSL certificate against the new domain name.
319 boolean savedSslCertificateMatchesNewDomainName = checkDomainNameAgainstCertificate(newDomainName, savedSslCertificateIssuedToCNameString);
321 // Create a `SpannableStringBuilder` for the saved certificate `Common Name`.
322 SpannableStringBuilder savedSslCertificateCommonNameStringBuilder = new SpannableStringBuilder(cNameLabel + savedSslCertificateIssuedToCNameString);
324 // Format the saved certificate `Common Name` color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
325 if (savedSslCertificateMatchesNewDomainName) {
326 savedSslCertificateCommonNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), savedSslCertificateCommonNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
328 savedSslCertificateCommonNameStringBuilder.setSpan(redColorSpan, cNameLabel.length(), savedSslCertificateCommonNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
331 // Update `savedSslCertificateIssuedToCNameTextView`.
332 savedSslCertificateIssuedToCNameTextView.setText(savedSslCertificateCommonNameStringBuilder);
334 // Update the current website certificate if it exists.
335 if (currentWebsiteSslCertificate != null) {
336 // Get the current website certificate `Common Name`.
337 String currentWebsiteCertificateCommonName = currentWebsiteSslCertificate.getIssuedTo().getCName();
339 // Check the current website certificate against the new domain name.
340 boolean currentWebsiteCertificateMatchesNewDomainName = checkDomainNameAgainstCertificate(newDomainName, currentWebsiteCertificateCommonName);
342 // Create a `SpannableStringBuilder` for the current website certificate `Common Name`.
343 SpannableStringBuilder currentWebsiteCertificateCommonNameStringBuilder = new SpannableStringBuilder(cNameLabel + currentWebsiteCertificateCommonName);
345 // Format the current certificate `Common Name` color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
346 if (currentWebsiteCertificateMatchesNewDomainName) {
347 currentWebsiteCertificateCommonNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), currentWebsiteCertificateCommonNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
349 currentWebsiteCertificateCommonNameStringBuilder.setSpan(redColorSpan, cNameLabel.length(), currentWebsiteCertificateCommonNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
352 // Update `currentWebsiteCertificateIssuedToCNameTextView`.
353 currentWebsiteCertificateIssuedToCNameTextView.setText(currentWebsiteCertificateCommonNameStringBuilder);
358 // Create a boolean to track if night mode is enabled.
359 boolean nightModeEnabled = (nightModeInt == DomainsDatabaseHelper.NIGHT_MODE_ENABLED) || ((nightModeInt == DomainsDatabaseHelper.NIGHT_MODE_SYSTEM_DEFAULT) && defaultNightMode);
361 // Disable the JavaScript switch if night mode is enabled.
362 if (nightModeEnabled) {
363 javaScriptEnabledSwitch.setEnabled(false);
365 javaScriptEnabledSwitch.setEnabled(true);
368 // Set the JavaScript icon.
369 if ((javaScriptEnabledInt == 1) || nightModeEnabled) {
370 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.javascript_enabled));
372 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.privacy_mode));
375 // Set the JavaScript switch status.
376 if (javaScriptEnabledInt == 1) { // JavaScript is enabled.
377 javaScriptEnabledSwitch.setChecked(true);
378 } else { // JavaScript is disabled.
379 javaScriptEnabledSwitch.setChecked(false);
382 // 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.
383 if (firstPartyCookiesEnabledInt == 1) { // First-party cookies are enabled.
384 firstPartyCookiesEnabledSwitch.setChecked(true);
385 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_enabled));
386 } else { // First-party cookies are disabled.
387 firstPartyCookiesEnabledSwitch.setChecked(false);
389 // Set the icon according to the theme.
390 if (MainWebViewActivity.darkTheme) {
391 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_dark));
393 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_light));
397 // Only display third-party cookies if SDK_INT >= 21.
398 if (Build.VERSION.SDK_INT >= 21) { // Third-party cookies can be configured for API >= 21.
399 // Only enable third-party-cookies if first-party cookies are enabled.
400 if (firstPartyCookiesEnabledInt == 1) { // First-party cookies are enabled.
401 // 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.
402 if (thirdPartyCookiesEnabledInt == 1) { // Both first-party and third-party cookies are enabled.
403 thirdPartyCookiesEnabledSwitch.setChecked(true);
404 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_warning));
405 } else { // First party cookies are enabled but third-party cookies are disabled.
406 thirdPartyCookiesEnabledSwitch.setChecked(false);
408 // Set the icon according to the theme.
409 if (MainWebViewActivity.darkTheme) {
410 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_dark));
412 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_light));
415 } else { // First-party cookies are disabled.
416 // Set the status of third-party cookies.
417 if (thirdPartyCookiesEnabledInt == 1) {
418 thirdPartyCookiesEnabledSwitch.setChecked(true);
420 thirdPartyCookiesEnabledSwitch.setChecked(false);
423 // Disable the third-party cookies switch.
424 thirdPartyCookiesEnabledSwitch.setEnabled(false);
426 // Set the icon according to the theme.
427 if (MainWebViewActivity.darkTheme) {
428 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_ghosted_dark));
430 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_ghosted_light));
433 } else { // Third-party cookies cannot be configured for API <= 21.
434 // Hide the LinearLayout for third-party cookies.
435 thirdPartyCookiesLinearLayout.setVisibility(View.GONE);
438 // Only enable DOM storage if JavaScript is enabled.
439 if ((javaScriptEnabledInt == 1) || nightModeEnabled) { // JavaScript is enabled.
440 // Enable the DOM storage `Switch`.
441 domStorageEnabledSwitch.setEnabled(true);
443 // Set the DOM storage status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
444 if (domStorageEnabledInt == 1) { // Both JavaScript and DOM storage are enabled.
445 domStorageEnabledSwitch.setChecked(true);
446 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_enabled));
447 } else { // JavaScript is enabled but DOM storage is disabled.
448 // Set the DOM storage switch to off.
449 domStorageEnabledSwitch.setChecked(false);
451 // Set the icon according to the theme.
452 if (MainWebViewActivity.darkTheme) {
453 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_dark));
455 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_light));
458 } else { // JavaScript is disabled.
459 // Disable the DOM storage `Switch`.
460 domStorageEnabledSwitch.setEnabled(false);
462 // Set the checked status of DOM storage.
463 if (domStorageEnabledInt == 1) { // DOM storage is enabled but JavaScript is disabled.
464 domStorageEnabledSwitch.setChecked(true);
465 } else { // Both JavaScript and DOM storage are disabled.
466 domStorageEnabledSwitch.setChecked(false);
469 // Set the icon according to the theme.
470 if (MainWebViewActivity.darkTheme) {
471 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_dark));
473 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_light));
477 // 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.
478 if (Build.VERSION.SDK_INT >= 26) { // Form data no longer applies to newer versions of Android.
479 // Hide the form data switch.
480 formDataEnabledSwitch.setVisibility(View.GONE);
481 } else { // Form data should be displayed because this is an older version of Android.
482 if (formDataEnabledInt == 1) { // Form data is on.
483 formDataEnabledSwitch.setChecked(true);
484 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_enabled));
485 } else { // Form data is off.
486 // Turn the form data switch to off.
487 formDataEnabledSwitch.setChecked(false);
489 // Set the icon according to the theme.
490 if (MainWebViewActivity.darkTheme) {
491 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_disabled_dark));
493 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_disabled_light));
498 // Set the EasyList status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
499 if (easyListEnabledInt == 1) { // EasyList is on.
500 // Turn the switch on.
501 easyListSwitch.setChecked(true);
503 // Set the icon according to the theme.
504 if (MainWebViewActivity.darkTheme) {
505 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_dark));
507 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_light));
509 } else { // EasyList is off.
510 // Turn the switch off.
511 easyListSwitch.setChecked(false);
513 // Set the icon according to the theme.
514 if (MainWebViewActivity.darkTheme) {
515 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_dark));
517 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_light));
521 // Set the EasyPrivacy status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
522 if (easyPrivacyEnabledInt == 1) { // EasyPrivacy is on.
523 // Turn the switch on.
524 easyPrivacySwitch.setChecked(true);
526 // Set the icon according to the theme.
527 if (MainWebViewActivity.darkTheme) {
528 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_dark));
530 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_light));
532 } else { // EasyPrivacy is off.
533 // Turn the switch off.
534 easyPrivacySwitch.setChecked(false);
536 // Set the icon according to the theme.
537 if (MainWebViewActivity.darkTheme) {
538 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_dark));
540 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_light));
544 // 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.
545 if (fanboysAnnoyanceListInt == 1) { // Fanboy's Annoyance List is on.
546 // Turn the switch on.
547 fanboysAnnoyanceListSwitch.setChecked(true);
549 // Set the icon according to the theme.
550 if (MainWebViewActivity.darkTheme) {
551 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_dark));
553 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_light));
555 } else { // Fanboy's Annoyance List is off.
556 // Turn the switch off.
557 fanboysAnnoyanceListSwitch.setChecked(false);
559 // Set the icon according to the theme.
560 if (MainWebViewActivity.darkTheme) {
561 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_dark));
563 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_light));
567 // Only enable Fanboy's Social Blocking List if Fanboy's Annoyance List is off.
568 if (fanboysAnnoyanceListInt == 0) { // Fanboy's Annoyance List is on.
569 // 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.
570 if (fanboysSocialBlockingListInt == 1) { // Fanboy's Social Blocking List is on.
571 // Enable the switch and turn it on.
572 fanboysSocialBlockingListSwitch.setEnabled(true);
573 fanboysSocialBlockingListSwitch.setChecked(true);
575 // Set the icon according to the theme.
576 if (MainWebViewActivity.darkTheme) {
577 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_dark));
579 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_light));
581 } else { // Fanboy's Social Blocking List is off.
582 // Enable the switch but turn it off.
583 fanboysSocialBlockingListSwitch.setEnabled(true);
584 fanboysSocialBlockingListSwitch.setChecked(false);
586 // Set the icon according to the theme.
587 if (MainWebViewActivity.darkTheme) {
588 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_dark));
590 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_light));
593 } else { // Fanboy's Annoyance List is on.
594 // 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.
595 if (fanboysSocialBlockingListInt == 1) { // Fanboy's Social Blocking List is on.
596 // Disable the switch but turn it on.
597 fanboysSocialBlockingListSwitch.setEnabled(false);
598 fanboysSocialBlockingListSwitch.setChecked(true);
599 } else { // Fanboy's Social Blocking List is off.
600 // Disable the switch and turn it off.
601 fanboysSocialBlockingListSwitch.setEnabled(false);
602 fanboysSocialBlockingListSwitch.setChecked(false);
605 // Set the icon according to the theme.
606 if (MainWebViewActivity.darkTheme) {
607 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_ghosted_dark));
609 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_ghosted_light));
613 // Set the UltraPrivacy status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
614 if (ultraPrivacyEnabledInt == 1) { // UltraPrivacy is on.
615 // Turn the switch on.
616 ultraPrivacySwitch.setChecked(true);
618 // Set the icon according to the theme.
619 if (MainWebViewActivity.darkTheme) {
620 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_dark));
622 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_light));
624 } else { // EasyPrivacy is off.
625 // Turn the switch off.
626 ultraPrivacySwitch.setChecked(false);
628 // Set the icon according to the theme.
629 if (MainWebViewActivity.darkTheme) {
630 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_dark));
632 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_light));
636 // 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.
637 if (blockAllThirdPartyRequestsInt == 1) { // Blocking all third-party requests is on.
638 // Turn the switch on.
639 blockAllThirdPartyRequestsSwitch.setChecked(true);
641 // Set the icon according to the theme.
642 if (MainWebViewActivity.darkTheme) {
643 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_enabled_dark));
645 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_enabled_light));
647 } else { // Blocking all third-party requests is off.
648 // Turn the switch off.
649 blockAllThirdPartyRequestsSwitch.setChecked(false);
651 // Set the icon according to the theme.
652 if (MainWebViewActivity.darkTheme) {
653 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_disabled_dark));
655 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_disabled_light));
659 // Inflated a WebView to get the default user agent.
660 // `@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.
661 @SuppressLint("InflateParams") View bareWebViewLayout = inflater.inflate(R.layout.bare_webview, null, false);
662 WebView bareWebView = bareWebViewLayout.findViewById(R.id.bare_webview);
663 final String webViewDefaultUserAgentString = bareWebView.getSettings().getUserAgentString();
665 // Get a handle for the user agent array adapter. This array does not contain the `System default` entry.
666 ArrayAdapter<CharSequence> userAgentNamesArray = ArrayAdapter.createFromResource(context, R.array.user_agent_names, R.layout.spinner_item);
668 // Get the positions of the user agent and the default user agent.
669 int userAgentArrayPosition = userAgentNamesArray.getPosition(currentUserAgentName);
670 int defaultUserAgentArrayPosition = userAgentNamesArray.getPosition(defaultUserAgentName);
672 // Get a handle for the user agent data array. This array does not contain the `System default` entry.
673 String[] userAgentDataArray = resources.getStringArray(R.array.user_agent_data);
675 // Set the user agent text.
676 if (currentUserAgentName.equals(getString(R.string.system_default_user_agent))) { // Use the system default user agent.
677 // Set the user agent according to the system default.
678 switch (defaultUserAgentArrayPosition) {
679 case MainWebViewActivity.UNRECOGNIZED_USER_AGENT: // The default user agent name is not on the canonical list.
680 // This is probably because it was set in an older version of Privacy Browser before the switch to persistent user agent names.
681 userAgentTextView.setText(defaultUserAgentName);
684 case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
685 // Display the `WebView` default user agent.
686 userAgentTextView.setText(webViewDefaultUserAgentString);
689 case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
690 // Display the custom user agent.
691 userAgentTextView.setText(defaultCustomUserAgentString);
695 // Get the user agent string from the user agent data array.
696 userAgentTextView.setText(userAgentDataArray[defaultUserAgentArrayPosition]);
698 } else if (userAgentArrayPosition == MainWebViewActivity.UNRECOGNIZED_USER_AGENT) { // A custom user agent is stored in the current user agent name.
699 // Set the user agent spinner to `Custom user agent`.
700 userAgentSpinner.setSelection(MainWebViewActivity.DOMAINS_CUSTOM_USER_AGENT);
702 // Hide the user agent TextView.
703 userAgentTextView.setVisibility(View.GONE);
705 // Show the custom user agent EditText and set the current user agent name as the text.
706 customUserAgentEditText.setVisibility(View.VISIBLE);
707 customUserAgentEditText.setText(currentUserAgentName);
708 } else { // The user agent name contains one of the canonical user agents.
709 // 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.
710 userAgentSpinner.setSelection(userAgentArrayPosition + 1);
712 // Show the user agent TextView.
713 userAgentTextView.setVisibility(View.VISIBLE);
715 // Hide the custom user agent EditText.
716 customUserAgentEditText.setVisibility(View.GONE);
718 // Set the user agent text.
719 switch (userAgentArrayPosition) {
720 case MainWebViewActivity.DOMAINS_WEBVIEW_DEFAULT_USER_AGENT:
721 // Display the WebView default user agent.
722 userAgentTextView.setText(webViewDefaultUserAgentString);
726 // 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.
727 userAgentTextView.setText(userAgentDataArray[userAgentArrayPosition + 1]);
731 // Open the user agent spinner when the TextView is clicked.
732 userAgentTextView.setOnClickListener((View v) -> {
733 // Open the user agent spinner.
734 userAgentSpinner.performClick();
737 // Set the selected font size.
738 int fontSizeArrayPosition = fontSizeEntryValuesArrayAdapter.getPosition(String.valueOf(fontSizeInt));
739 fontSizeSpinner.setSelection(fontSizeArrayPosition);
741 // Set the default font size text.
742 int defaultFontSizeArrayPosition = fontSizeEntryValuesArrayAdapter.getPosition(defaultFontSizeString);
743 fontSizeTextView.setText(fontSizeArrayAdapter.getItem(defaultFontSizeArrayPosition));
745 // Set the display options for the font size TextView.
746 if (fontSizeArrayPosition == 0) { // System default font size is selected. Display `fontSizeTextView`.
747 fontSizeTextView.setVisibility(View.VISIBLE);
748 } else { // A custom font size is specified. Hide `fontSizeTextView`.
749 fontSizeTextView.setVisibility(View.GONE);
752 // Open the font size spinner when the TextView is clicked.
753 fontSizeTextView.setOnClickListener((View v) -> {
754 // Open the user agent spinner.
755 fontSizeSpinner.performClick();
758 // Display the swipe to refresh selection in the spinner.
759 swipeToRefreshSpinner.setSelection(swipeToRefreshInt);
761 // Set the swipe to refresh text.
762 if (defaultSwipeToRefresh) {
763 swipeToRefreshTextView.setText(swipeToRefreshArrayAdapter.getItem(DomainsDatabaseHelper.SWIPE_TO_REFRESH_ENABLED));
765 swipeToRefreshTextView.setText(swipeToRefreshArrayAdapter.getItem(DomainsDatabaseHelper.SWIPE_TO_REFRESH_DISABLED));
768 // 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.
769 switch (swipeToRefreshInt) {
770 case DomainsDatabaseHelper.SWIPE_TO_REFRESH_SYSTEM_DEFAULT:
771 if (defaultSwipeToRefresh) { // Swipe to refresh is enabled by default.
772 // Set the icon according to the theme.
773 if (MainWebViewActivity.darkTheme) {
774 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_dark));
776 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_light));
778 } else { // Swipe to refresh is disabled by default
779 // Set the icon according to the theme.
780 if (MainWebViewActivity.darkTheme) {
781 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_dark));
783 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_light));
787 // Show the swipe to refresh TextView.
788 swipeToRefreshTextView.setVisibility(View.VISIBLE);
791 case DomainsDatabaseHelper.SWIPE_TO_REFRESH_ENABLED:
792 // Set the icon according to the theme.
793 if (MainWebViewActivity.darkTheme) {
794 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_dark));
796 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_light));
799 // Hide the swipe to refresh TextView.`
800 swipeToRefreshTextView.setVisibility(View.GONE);
803 case DomainsDatabaseHelper.SWIPE_TO_REFRESH_DISABLED:
804 // Set the icon according to the theme.
805 if (MainWebViewActivity.darkTheme) {
806 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_dark));
808 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_light));
811 // Hide the swipe to refresh TextView.
812 swipeToRefreshTextView.setVisibility(View.GONE);
815 // Open the swipe to refresh spinner when the TextView is clicked.
816 swipeToRefreshTextView.setOnClickListener((View v) -> {
817 // Open the swipe to refresh spinner.
818 swipeToRefreshSpinner.performClick();
821 // Display the night mode in the spinner.
822 nightModeSpinner.setSelection(nightModeInt);
824 // Set the default night mode text.
825 if (defaultNightMode) {
826 nightModeTextView.setText(nightModeArrayAdapter.getItem(DomainsDatabaseHelper.NIGHT_MODE_ENABLED));
828 nightModeTextView.setText(nightModeArrayAdapter.getItem(DomainsDatabaseHelper.NIGHT_MODE_DISABLED));
831 // 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.
832 switch (nightModeInt) {
833 case DomainsDatabaseHelper.NIGHT_MODE_SYSTEM_DEFAULT:
834 if (defaultNightMode) { // Night mode enabled by default.
835 // Set the icon according to the theme.
836 if (MainWebViewActivity.darkTheme) {
837 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_dark));
839 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_light));
841 } else { // Night mode disabled by default.
842 // Set the icon according to the theme.
843 if (MainWebViewActivity.darkTheme) {
844 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_dark));
846 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_light));
850 // Show night mode TextView.
851 nightModeTextView.setVisibility(View.VISIBLE);
854 case DomainsDatabaseHelper.NIGHT_MODE_ENABLED:
855 // Set the icon according to the theme.
856 if (MainWebViewActivity.darkTheme) {
857 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_dark));
859 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_light));
862 // Hide the night mode TextView.
863 nightModeTextView.setVisibility(View.GONE);
866 case DomainsDatabaseHelper.NIGHT_MODE_DISABLED:
867 // Set the icon according to the theme.
868 if (MainWebViewActivity.darkTheme) {
869 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_dark));
871 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_light));
874 // Hide the night mode TextView.
875 nightModeTextView.setVisibility(View.GONE);
879 // Open the night mode spinner when the TextView is clicked.
880 nightModeTextView.setOnClickListener((View v) -> {
881 // Open the night mode spinner.
882 nightModeSpinner.performClick();
885 // Display the website images mode in the spinner.
886 displayWebpageImagesSpinner.setSelection(displayImagesInt);
888 // Set the default display images text.
889 if (defaultDisplayWebpageImages) {
890 displayImagesTextView.setText(displayImagesArrayAdapter.getItem(DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_ENABLED));
892 displayImagesTextView.setText(displayImagesArrayAdapter.getItem(DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_DISABLED));
895 // Set the display website images icon and TextView settings. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
896 switch (displayImagesInt) {
897 case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_SYSTEM_DEFAULT:
898 if (defaultDisplayWebpageImages) { // Display webpage images enabled by default.
899 // Set the icon according to the theme.
900 if (MainWebViewActivity.darkTheme) {
901 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_dark));
903 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_light));
905 } else { // Display webpage images disabled by default.
906 // Set the icon according to the theme.
907 if (MainWebViewActivity.darkTheme) {
908 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_dark));
910 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_light));
914 // Show the display images TextView.
915 displayImagesTextView.setVisibility(View.VISIBLE);
918 case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_ENABLED:
919 // Set the icon according to the theme.
920 if (MainWebViewActivity.darkTheme) {
921 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_dark));
923 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_light));
926 // Hide the display images TextView.
927 displayImagesTextView.setVisibility(View.GONE);
930 case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_DISABLED:
931 // Set the icon according to the theme.
932 if (MainWebViewActivity.darkTheme) {
933 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_dark));
935 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_light));
938 // Hide the display images TextView.
939 displayImagesTextView.setVisibility(View.GONE);
943 // Open the display images spinner when the TextView is clicked.
944 displayImagesTextView.setOnClickListener((View v) -> {
945 // Open the user agent spinner.
946 displayWebpageImagesSpinner.performClick();
949 // Set the pinned SSL certificate icon.
950 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.
952 pinnedSslCertificateSwitch.setChecked(true);
954 // Set the icon according to the theme.
955 if (MainWebViewActivity.darkTheme) {
956 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_dark));
958 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_light));
960 } else { // Pinned SSL certificate is disabled.
961 // Uncheck the switch.
962 pinnedSslCertificateSwitch.setChecked(false);
964 // Set the icon according to the theme.
965 if (MainWebViewActivity.darkTheme) {
966 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_dark));
968 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_light));
972 // Store the current date.
973 Date currentDate = Calendar.getInstance().getTime();
975 // Setup the string builders to display the general certificate information in blue. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
976 savedSslCertificateIssuedToONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), savedSslCertificateIssuedToONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
977 savedSslCertificateIssuedToUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), savedSslCertificateIssuedToUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
978 savedSslCertificateIssuedByCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), savedSslCertificateIssuedByCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
979 savedSslCertificateIssuedByONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), savedSslCertificateIssuedByONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
980 savedSslCertificateIssuedByUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), savedSslCertificateIssuedByUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
982 // Check the certificate Common Name against the domain name.
983 boolean savedSSlCertificateCommonNameMatchesDomainName = checkDomainNameAgainstCertificate(domainNameString, savedSslCertificateIssuedToCNameString);
985 // Format the issued to Common Name color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
986 if (savedSSlCertificateCommonNameMatchesDomainName) {
987 savedSslCertificateIssuedToCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), savedSslCertificateIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
989 savedSslCertificateIssuedToCNameStringBuilder.setSpan(redColorSpan, cNameLabel.length(), savedSslCertificateIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
992 // Format the start date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
993 if ((savedSslCertificateStartDate != null) && savedSslCertificateStartDate.after(currentDate)) { // The certificate start date is in the future.
994 savedSslCertificateStartDateStringBuilder.setSpan(redColorSpan, startDateLabel.length(), savedSslCertificateStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
995 } else { // The certificate start date is in the past.
996 savedSslCertificateStartDateStringBuilder.setSpan(blueColorSpan, startDateLabel.length(), savedSslCertificateStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
999 // Format the end date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1000 if ((savedSslCertificateEndDate != null) && savedSslCertificateEndDate.before(currentDate)) { // The certificate end date is in the past.
1001 savedSslCertificateEndDateStringBuilder.setSpan(redColorSpan, endDateLabel.length(), savedSslCertificateEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1002 } else { // The certificate end date is in the future.
1003 savedSslCertificateEndDateStringBuilder.setSpan(blueColorSpan, endDateLabel.length(), savedSslCertificateEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1006 // Display the saved website SSL certificate strings.
1007 savedSslCertificateIssuedToCNameTextView.setText(savedSslCertificateIssuedToCNameStringBuilder);
1008 savedSslCertificateIssuedToONameTextView.setText(savedSslCertificateIssuedToONameStringBuilder);
1009 savedSslCertificateIssuedToUNameTextView.setText(savedSslCertificateIssuedToUNameStringBuilder);
1010 savedSslCertificateIssuedByCNameTextView.setText(savedSslCertificateIssuedByCNameStringBuilder);
1011 savedSslCertificateIssuedByONameTextView.setText(savedSslCertificateIssuedByONameStringBuilder);
1012 savedSslCertificateIssuedByUNameTextView.setText(savedSslCertificateIssuedByUNameStringBuilder);
1013 savedSslCertificateStartDateTextView.setText(savedSslCertificateStartDateStringBuilder);
1014 savedSslCertificateEndDateTextView.setText(savedSslCertificateEndDateStringBuilder);
1016 // Populate the current website SSL certificate if there is one.
1017 if (currentWebsiteSslCertificate != null) {
1018 // Get the strings from the SSL certificate.
1019 String currentWebsiteCertificateIssuedToCNameString = currentWebsiteSslCertificate.getIssuedTo().getCName();
1020 String currentWebsiteCertificateIssuedToONameString = currentWebsiteSslCertificate.getIssuedTo().getOName();
1021 String currentWebsiteCertificateIssuedToUNameString = currentWebsiteSslCertificate.getIssuedTo().getUName();
1022 String currentWebsiteCertificateIssuedByCNameString = currentWebsiteSslCertificate.getIssuedBy().getCName();
1023 String currentWebsiteCertificateIssuedByONameString = currentWebsiteSslCertificate.getIssuedBy().getOName();
1024 String currentWebsiteCertificateIssuedByUNameString = currentWebsiteSslCertificate.getIssuedBy().getUName();
1025 Date currentWebsiteCertificateStartDate = currentWebsiteSslCertificate.getValidNotBeforeDate();
1026 Date currentWebsiteCertificateEndDate = currentWebsiteSslCertificate.getValidNotAfterDate();
1028 // Create a spannable string builder for each text view that needs multiple colors of text.
1029 SpannableStringBuilder currentWebsiteCertificateIssuedToCNameStringBuilder = new SpannableStringBuilder(cNameLabel + currentWebsiteCertificateIssuedToCNameString);
1030 SpannableStringBuilder currentWebsiteCertificateIssuedToONameStringBuilder = new SpannableStringBuilder(oNameLabel + currentWebsiteCertificateIssuedToONameString);
1031 SpannableStringBuilder currentWebsiteCertificateIssuedToUNameStringBuilder = new SpannableStringBuilder(uNameLabel + currentWebsiteCertificateIssuedToUNameString);
1032 SpannableStringBuilder currentWebsiteCertificateIssuedByCNameStringBuilder = new SpannableStringBuilder(cNameLabel + currentWebsiteCertificateIssuedByCNameString);
1033 SpannableStringBuilder currentWebsiteCertificateIssuedByONameStringBuilder = new SpannableStringBuilder(oNameLabel + currentWebsiteCertificateIssuedByONameString);
1034 SpannableStringBuilder currentWebsiteCertificateIssuedByUNameStringBuilder = new SpannableStringBuilder(uNameLabel + currentWebsiteCertificateIssuedByUNameString);
1035 SpannableStringBuilder currentWebsiteCertificateStartDateStringBuilder = new SpannableStringBuilder(startDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG)
1036 .format(currentWebsiteCertificateStartDate));
1037 SpannableStringBuilder currentWebsiteCertificateEndDateStringBuilder = new SpannableStringBuilder(endDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG)
1038 .format(currentWebsiteCertificateEndDate));
1040 // Setup the string builders to display the general certificate information in blue. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1041 currentWebsiteCertificateIssuedToONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), currentWebsiteCertificateIssuedToONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1042 currentWebsiteCertificateIssuedToUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), currentWebsiteCertificateIssuedToUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1043 currentWebsiteCertificateIssuedByCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), currentWebsiteCertificateIssuedByCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1044 currentWebsiteCertificateIssuedByONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), currentWebsiteCertificateIssuedByONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1045 currentWebsiteCertificateIssuedByUNameStringBuilder.setSpan(blueColorSpan, uNameLabel.length(), currentWebsiteCertificateIssuedByUNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1047 // Check the certificate Common Name against the domain name.
1048 boolean currentWebsiteCertificateCommonNameMatchesDomainName = checkDomainNameAgainstCertificate(domainNameString, currentWebsiteCertificateIssuedToCNameString);
1050 // Format the issued to Common Name color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1051 if (currentWebsiteCertificateCommonNameMatchesDomainName) {
1052 currentWebsiteCertificateIssuedToCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), currentWebsiteCertificateIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1054 currentWebsiteCertificateIssuedToCNameStringBuilder.setSpan(redColorSpan, cNameLabel.length(), currentWebsiteCertificateIssuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1057 // Format the start date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1058 if (currentWebsiteCertificateStartDate.after(currentDate)) { // The certificate start date is in the future.
1059 currentWebsiteCertificateStartDateStringBuilder.setSpan(redColorSpan, startDateLabel.length(), currentWebsiteCertificateStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1060 } else { // The certificate start date is in the past.
1061 currentWebsiteCertificateStartDateStringBuilder.setSpan(blueColorSpan, startDateLabel.length(), currentWebsiteCertificateStartDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1064 // Format the end date color. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
1065 if (currentWebsiteCertificateEndDate.before(currentDate)) { // The certificate end date is in the past.
1066 currentWebsiteCertificateEndDateStringBuilder.setSpan(redColorSpan, endDateLabel.length(), currentWebsiteCertificateEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1067 } else { // The certificate end date is in the future.
1068 currentWebsiteCertificateEndDateStringBuilder.setSpan(blueColorSpan, endDateLabel.length(), currentWebsiteCertificateEndDateStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
1071 // Display the current website SSL certificate strings.
1072 currentWebsiteCertificateIssuedToCNameTextView.setText(currentWebsiteCertificateIssuedToCNameStringBuilder);
1073 currentWebsiteCertificateIssuedToONameTextView.setText(currentWebsiteCertificateIssuedToONameStringBuilder);
1074 currentWebsiteCertificateIssuedToUNameTextView.setText(currentWebsiteCertificateIssuedToUNameStringBuilder);
1075 currentWebsiteCertificateIssuedByCNameTextView.setText(currentWebsiteCertificateIssuedByCNameStringBuilder);
1076 currentWebsiteCertificateIssuedByONameTextView.setText(currentWebsiteCertificateIssuedByONameStringBuilder);
1077 currentWebsiteCertificateIssuedByUNameTextView.setText(currentWebsiteCertificateIssuedByUNameStringBuilder);
1078 currentWebsiteCertificateStartDateTextView.setText(currentWebsiteCertificateStartDateStringBuilder);
1079 currentWebsiteCertificateEndDateTextView.setText(currentWebsiteCertificateEndDateStringBuilder);
1082 // Set the initial display status of the SSL certificates card views.
1083 if (pinnedSslCertificateSwitch.isChecked()) { // An SSL certificate is pinned.
1084 // Set the visibility of the saved SSL certificate.
1085 if (savedSslCertificateIssuedToCNameString == null) {
1086 savedSslCertificateCardView.setVisibility(View.GONE);
1088 savedSslCertificateCardView.setVisibility(View.VISIBLE);
1091 // Set the visibility of the current website SSL certificate.
1092 if (currentWebsiteSslCertificate == null) { // There is no current SSL certificate.
1093 // Hide the SSL certificate.
1094 currentWebsiteCertificateCardView.setVisibility(View.GONE);
1096 // Show the instruction.
1097 noCurrentWebsiteCertificateTextView.setVisibility(View.VISIBLE);
1098 } else { // There is a current SSL certificate.
1099 // Show the SSL certificate.
1100 currentWebsiteCertificateCardView.setVisibility(View.VISIBLE);
1102 // Hide the instruction.
1103 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
1106 // Set the status of the radio buttons and the card view backgrounds.
1107 if (savedSslCertificateCardView.getVisibility() == View.VISIBLE) { // The saved SSL certificate is displayed.
1108 // Check the saved SSL certificate radio button.
1109 savedSslCertificateRadioButton.setChecked(true);
1111 // Uncheck the current website SSL certificate radio button.
1112 currentWebsiteCertificateRadioButton.setChecked(false);
1114 // Darken the background of the current website SSL certificate linear layout according to the theme.
1115 if (MainWebViewActivity.darkTheme) {
1116 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
1118 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
1120 } else if (currentWebsiteCertificateCardView.getVisibility() == View.VISIBLE) { // The saved SSL certificate is hidden but the current website SSL certificate is visible.
1121 // Check the current website SSL certificate radio button.
1122 currentWebsiteCertificateRadioButton.setChecked(true);
1124 // Uncheck the saved SSL certificate radio button.
1125 savedSslCertificateRadioButton.setChecked(false);
1126 } else { // Neither SSL certificate is visible.
1127 // Uncheck both radio buttons.
1128 savedSslCertificateRadioButton.setChecked(false);
1129 currentWebsiteCertificateRadioButton.setChecked(false);
1131 } else { // An SSL certificate is not pinned.
1132 // Hide the SSl certificates and instructions.
1133 savedSslCertificateCardView.setVisibility(View.GONE);
1134 currentWebsiteCertificateCardView.setVisibility(View.GONE);
1135 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
1137 // Uncheck the radio buttons.
1138 savedSslCertificateRadioButton.setChecked(false);
1139 currentWebsiteCertificateRadioButton.setChecked(false);
1142 // Set the pinned IP addresses icon.
1143 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.
1144 // Check the switch.
1145 pinnedIpAddressesSwitch.setChecked(true);
1147 // Set the icon according to the theme.
1148 if (MainWebViewActivity.darkTheme) {
1149 pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_dark));
1151 pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_light));
1153 } else { // Pinned IP Addresses is disabled.
1154 // Uncheck the switch.
1155 pinnedIpAddressesSwitch.setChecked(false);
1157 // Set the icon according to the theme.
1158 if (MainWebViewActivity.darkTheme) {
1159 pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_dark));
1161 pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_light));
1165 // Populate the saved and current IP addresses.
1166 savedIpAddressesTextView.setText(savedIpAddresses);
1167 currentIpAddressesTextView.setText(DomainsActivity.currentIpAddresses);
1169 // Set the initial display status of the IP addresses card views.
1170 if (pinnedIpAddressesSwitch.isChecked()) { // IP addresses are pinned.
1171 // Set the visibility of the saved IP addresses.
1172 if (savedIpAddresses == null) { // There are no saved IP addresses.
1173 savedIpAddressesCardView.setVisibility(View.GONE);
1174 } else { // There are saved IP addresses.
1175 savedIpAddressesCardView.setVisibility(View.VISIBLE);
1178 // Set the visibility of the current IP addresses.
1179 currentIpAddressesCardView.setVisibility(View.VISIBLE);
1181 // Set the status of the radio buttons and the card view backgrounds.
1182 if (savedIpAddressesCardView.getVisibility() == View.VISIBLE) { // The saved IP addresses are displayed.
1183 // Check the saved IP addresses radio button.
1184 savedIpAddressesRadioButton.setChecked(true);
1186 // Uncheck the current IP addresses radio button.
1187 currentIpAddressesRadioButton.setChecked(false);
1189 // Darken the background of the current IP addresses linear layout according to the theme.
1190 if (MainWebViewActivity.darkTheme) {
1191 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
1193 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
1195 } else { // The saved IP addresses are hidden.
1196 // Check the current IP addresses radio button.
1197 currentIpAddressesRadioButton.setChecked(true);
1199 // Uncheck the saved IP addresses radio button.
1200 savedIpAddressesRadioButton.setChecked(false);
1202 } else { // IP addresses are not pinned.
1203 // Hide the IP addresses card views.
1204 savedIpAddressesCardView.setVisibility(View.GONE);
1205 currentIpAddressesCardView.setVisibility(View.GONE);
1207 // Uncheck the radio buttons.
1208 savedIpAddressesRadioButton.setChecked(false);
1209 currentIpAddressesRadioButton.setChecked(false);
1213 // Set the JavaScript switch listener.
1214 javaScriptEnabledSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1215 if (isChecked) { // JavaScript is enabled.
1216 // Update the JavaScript icon.
1217 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.javascript_enabled));
1219 // Enable the DOM storage `Switch`.
1220 domStorageEnabledSwitch.setEnabled(true);
1222 // Update the DOM storage icon.
1223 if (domStorageEnabledSwitch.isChecked()) { // DOM storage is enabled.
1224 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_enabled));
1225 } else { // DOM storage is disabled.
1226 // Set the icon according to the theme.
1227 if (MainWebViewActivity.darkTheme) {
1228 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_dark));
1230 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_light));
1233 } else { // JavaScript is disabled.
1234 // Update the JavaScript icon.
1235 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.privacy_mode));
1237 // Disable the DOM storage `Switch`.
1238 domStorageEnabledSwitch.setEnabled(false);
1240 // Set the DOM storage icon according to the theme.
1241 if (MainWebViewActivity.darkTheme) {
1242 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_dark));
1244 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_light));
1249 // Set the first-party cookies switch listener.
1250 firstPartyCookiesEnabledSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1251 if (isChecked) { // First-party cookies are enabled.
1252 // Update the first-party cookies icon.
1253 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_enabled));
1255 // Enable the third-party cookies switch.
1256 thirdPartyCookiesEnabledSwitch.setEnabled(true);
1258 // Update the third-party cookies icon.
1259 if (thirdPartyCookiesEnabledSwitch.isChecked()) { // Third-party cookies are enabled.
1260 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_warning));
1261 } else { // Third-party cookies are disabled.
1262 // Set the third-party cookies icon according to the theme.
1263 if (MainWebViewActivity.darkTheme) {
1264 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_dark));
1266 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_light));
1269 } else { // First-party cookies are disabled.
1270 // Update the first-party cookies icon according to the theme.
1271 if (MainWebViewActivity.darkTheme) {
1272 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_dark));
1274 firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_light));
1277 // Disable the third-party cookies switch.
1278 thirdPartyCookiesEnabledSwitch.setEnabled(false);
1280 // Set the third-party cookies icon according to the theme.
1281 if (MainWebViewActivity.darkTheme) {
1282 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_ghosted_dark));
1284 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_ghosted_light));
1289 // Set the third-party cookies switch listener.
1290 thirdPartyCookiesEnabledSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1293 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_warning));
1295 // Update the third-party cookies icon according to the theme.
1296 if (MainWebViewActivity.darkTheme) {
1297 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_dark));
1299 thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_light));
1304 // Set the DOM Storage switch listener.
1305 domStorageEnabledSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1308 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_enabled));
1310 // Set the icon according to the theme.
1311 if (MainWebViewActivity.darkTheme) {
1312 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_dark));
1314 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_light));
1319 // Set the form data switch listener. It can be removed once the minimum API >= 26.
1320 if (Build.VERSION.SDK_INT < 26) {
1321 formDataEnabledSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1324 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_enabled));
1326 // Set the icon according to the theme.
1327 if (MainWebViewActivity.darkTheme) {
1328 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_disabled_dark));
1330 formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_disabled_light));
1336 // Set the EasyList switch listener.
1337 easyListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1339 if (isChecked) { // EasyList is on.
1340 // Set the icon according to the theme.
1341 if (MainWebViewActivity.darkTheme) {
1342 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_dark));
1344 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_light));
1346 } else { // EasyList is off.
1347 // Set the icon according to the theme.
1348 if (MainWebViewActivity.darkTheme) {
1349 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_dark));
1351 easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_light));
1356 // Set the EasyPrivacy switch listener.
1357 easyPrivacySwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1359 if (isChecked) { // EasyPrivacy is on.
1360 // Set the icon according to the theme.
1361 if (MainWebViewActivity.darkTheme) {
1362 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_dark));
1364 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_light));
1366 } else { // EasyPrivacy is off.
1367 // Set the icon according to the theme.
1368 if (MainWebViewActivity.darkTheme) {
1369 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_dark));
1371 easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_light));
1376 // Set the Fanboy's Annoyance List switch listener.
1377 fanboysAnnoyanceListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1378 // Update the icon and Fanboy's Social Blocking List.
1379 if (isChecked) { // Fanboy's Annoyance List is on.
1380 // Set the icon according to the theme.
1381 if (MainWebViewActivity.darkTheme) {
1382 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_dark));
1384 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_light));
1387 // Disable the Fanboy's Social Blocking List switch.
1388 fanboysSocialBlockingListSwitch.setEnabled(false);
1390 // Update the Fanboy's Social Blocking List icon according to the theme.
1391 if (MainWebViewActivity.darkTheme) {
1392 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_ghosted_dark));
1394 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_ghosted_light));
1396 } else { // Fanboy's Annoyance List is off.
1397 // Set the icon according to the theme.
1398 if (MainWebViewActivity.darkTheme) {
1399 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_dark));
1401 fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_light));
1404 // Enable the Fanboy's Social Blocking List switch.
1405 fanboysSocialBlockingListSwitch.setEnabled(true);
1407 // Update the Fanboy's Social Blocking List icon.
1408 if (fanboysSocialBlockingListSwitch.isChecked()) { // Fanboy's Social Blocking List is on.
1409 // Update the icon according to the theme.
1410 if (MainWebViewActivity.darkTheme) {
1411 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_dark));
1413 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_light));
1415 } else { // Fanboy's Social Blocking List is off.
1416 // Update the icon according to the theme.
1417 if (MainWebViewActivity.darkTheme) {
1418 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_dark));
1420 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_light));
1427 // Set the Fanboy's Social Blocking List switch listener.
1428 fanboysSocialBlockingListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1430 if (isChecked) { // Fanboy's Social Blocking List is on.
1431 // Set the icon according to the theme.
1432 if (MainWebViewActivity.darkTheme) {
1433 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_dark));
1435 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_light));
1437 } else { // Fanboy's Social Blocking List is off.
1438 // Set the icon according to the theme.
1439 if (MainWebViewActivity.darkTheme) {
1440 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_dark));
1442 fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_light));
1447 // Set the UltraPrivacy switch listener.
1448 ultraPrivacySwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1450 if (isChecked) { // UltraPrivacy is on.
1451 // Set the icon according to the theme.
1452 if (MainWebViewActivity.darkTheme) {
1453 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_dark));
1455 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_light));
1457 } else { // UltraPrivacy is off.
1458 // Set the icon according to the theme.
1459 if (MainWebViewActivity.darkTheme) {
1460 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_dark));
1462 ultraPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_light));
1467 // Set the block all third-party requests switch listener.
1468 blockAllThirdPartyRequestsSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1470 if (isChecked) { // Blocking all third-party requests is on.
1471 // Set the icon according to the theme.
1472 if (MainWebViewActivity.darkTheme) {
1473 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_enabled_dark));
1475 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_enabled_light));
1477 } else { // Blocking all third-party requests is off.
1478 // Set the icon according to the theme.
1479 if (MainWebViewActivity.darkTheme) {
1480 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_disabled_dark));
1482 blockAllThirdPartyRequestsImageView.setImageDrawable(resources.getDrawable(R.drawable.block_all_third_party_requests_disabled_light));
1487 // Set the user agent spinner listener.
1488 userAgentSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1490 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1491 // Set the new user agent.
1493 case MainWebViewActivity.DOMAINS_SYSTEM_DEFAULT_USER_AGENT:
1494 // Show the user agent TextView.
1495 userAgentTextView.setVisibility(View.VISIBLE);
1497 // Hide the custom user agent EditText.
1498 customUserAgentEditText.setVisibility(View.GONE);
1500 // Set the user text.
1501 switch (defaultUserAgentArrayPosition) {
1502 case MainWebViewActivity.UNRECOGNIZED_USER_AGENT: // The default user agent name is not on the canonical list.
1503 // This is probably because it was set in an older version of Privacy Browser before the switch to persistent user agent names.
1504 userAgentTextView.setText(defaultUserAgentName);
1507 case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
1508 // Display the `WebView` default user agent.
1509 userAgentTextView.setText(webViewDefaultUserAgentString);
1512 case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
1513 // Display the custom user agent.
1514 userAgentTextView.setText(defaultCustomUserAgentString);
1518 // Get the user agent string from the user agent data array.
1519 userAgentTextView.setText(userAgentDataArray[defaultUserAgentArrayPosition]);
1523 case MainWebViewActivity.DOMAINS_WEBVIEW_DEFAULT_USER_AGENT:
1524 // Show the user agent TextView and set the text.
1525 userAgentTextView.setVisibility(View.VISIBLE);
1526 userAgentTextView.setText(webViewDefaultUserAgentString);
1528 // Hide the custom user agent EditTex.
1529 customUserAgentEditText.setVisibility(View.GONE);
1532 case MainWebViewActivity.DOMAINS_CUSTOM_USER_AGENT:
1533 // Hide the user agent TextView.
1534 userAgentTextView.setVisibility(View.GONE);
1536 // Show the custom user agent EditText and set the current user agent name as the text.
1537 customUserAgentEditText.setVisibility(View.VISIBLE);
1538 customUserAgentEditText.setText(currentUserAgentName);
1542 // 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.
1543 userAgentTextView.setVisibility(View.VISIBLE);
1544 userAgentTextView.setText(userAgentDataArray[position - 1]);
1546 // Hide `customUserAgentEditText`.
1547 customUserAgentEditText.setVisibility(View.GONE);
1552 public void onNothingSelected(AdapterView<?> parent) {
1557 // Set the font size spinner listener.
1558 fontSizeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1560 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1561 // Update the display options for `fontSizeTextView`.
1562 if (position == 0) { // System default font size has been selected. Display `fontSizeTextView`.
1563 fontSizeTextView.setVisibility(View.VISIBLE);
1564 } else { // A custom font size has been selected. Hide `fontSizeTextView`.
1565 fontSizeTextView.setVisibility(View.GONE);
1570 public void onNothingSelected(AdapterView<?> parent) {
1575 // Set the swipe to refresh spinner listener.
1576 swipeToRefreshSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1578 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1579 // 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.
1581 case DomainsDatabaseHelper.SWIPE_TO_REFRESH_SYSTEM_DEFAULT:
1582 if (defaultSwipeToRefresh) { // Swipe to refresh enabled by default.
1583 // Set the icon according to the theme.
1584 if (MainWebViewActivity.darkTheme) {
1585 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_dark));
1587 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_light));
1589 } else { // Swipe to refresh disabled by default.
1590 // Set the icon according to the theme.
1591 if (MainWebViewActivity.darkTheme) {
1592 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_dark));
1594 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_light));
1598 // Show the swipe to refresh TextView.
1599 swipeToRefreshTextView.setVisibility(View.VISIBLE);
1602 case DomainsDatabaseHelper.SWIPE_TO_REFRESH_ENABLED:
1603 // Set the icon according to the theme.
1604 if (MainWebViewActivity.darkTheme) {
1605 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_dark));
1607 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_enabled_light));
1610 // Hide the swipe to refresh TextView.
1611 swipeToRefreshTextView.setVisibility(View.GONE);
1614 case DomainsDatabaseHelper.SWIPE_TO_REFRESH_DISABLED:
1615 // Set the icon according to the theme.
1616 if (MainWebViewActivity.darkTheme) {
1617 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_dark));
1619 swipeToRefreshImageView.setImageDrawable(resources.getDrawable(R.drawable.refresh_disabled_light));
1622 // Hide the swipe to refresh TextView.
1623 swipeToRefreshTextView.setVisibility(View.GONE);
1628 public void onNothingSelected(AdapterView<?> parent) {
1633 // Set the night mode spinner listener.
1634 nightModeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1636 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1637 // 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.
1639 case DomainsDatabaseHelper.NIGHT_MODE_SYSTEM_DEFAULT:
1640 if (defaultNightMode) { // Night mode enabled by default.
1641 // Set the icon according to the theme.
1642 if (MainWebViewActivity.darkTheme) {
1643 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_dark));
1645 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_light));
1647 } else { // Night mode disabled by default.
1648 // Set the icon according to the theme.
1649 if (MainWebViewActivity.darkTheme) {
1650 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_dark));
1652 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_light));
1656 // Show the night mode TextView.
1657 nightModeTextView.setVisibility(View.VISIBLE);
1660 case DomainsDatabaseHelper.NIGHT_MODE_ENABLED:
1661 // Set the icon according to the theme.
1662 if (MainWebViewActivity.darkTheme) {
1663 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_dark));
1665 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_enabled_light));
1668 // Hide `nightModeTextView`.
1669 nightModeTextView.setVisibility(View.GONE);
1672 case DomainsDatabaseHelper.NIGHT_MODE_DISABLED:
1673 // Set the icon according to the theme.
1674 if (MainWebViewActivity.darkTheme) {
1675 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_dark));
1677 nightModeImageView.setImageDrawable(resources.getDrawable(R.drawable.night_mode_disabled_light));
1680 // Hide `nightModeTextView`.
1681 nightModeTextView.setVisibility(View.GONE);
1685 // Create a `boolean` to store the current night mode setting.
1686 boolean currentNightModeEnabled = (position == DomainsDatabaseHelper.NIGHT_MODE_ENABLED) || ((position == DomainsDatabaseHelper.NIGHT_MODE_SYSTEM_DEFAULT) && defaultNightMode);
1688 // Disable the JavaScript `Switch` if night mode is enabled.
1689 if (currentNightModeEnabled) {
1690 javaScriptEnabledSwitch.setEnabled(false);
1692 javaScriptEnabledSwitch.setEnabled(true);
1695 // Update the JavaScript icon.
1696 if ((javaScriptEnabledInt == 1) || currentNightModeEnabled) {
1697 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.javascript_enabled));
1699 javaScriptImageView.setImageDrawable(resources.getDrawable(R.drawable.privacy_mode));
1702 // Update the DOM storage status.
1703 if ((javaScriptEnabledInt == 1) || currentNightModeEnabled) { // JavaScript is enabled.
1704 // Enable the DOM storage `Switch`.
1705 domStorageEnabledSwitch.setEnabled(true);
1707 // Set the DOM storage status. Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
1708 if (domStorageEnabledInt == 1) { // Both JavaScript and DOM storage are enabled.
1709 domStorageEnabledSwitch.setChecked(true);
1710 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_enabled));
1711 } else { // JavaScript is enabled but DOM storage is disabled.
1712 // Set the DOM storage switch to off.
1713 domStorageEnabledSwitch.setChecked(false);
1715 // Set the icon according to the theme.
1716 if (MainWebViewActivity.darkTheme) {
1717 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_dark));
1719 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_disabled_light));
1722 } else { // JavaScript is disabled.
1723 // Disable the DOM storage `Switch`.
1724 domStorageEnabledSwitch.setEnabled(false);
1726 // Set the checked status of DOM storage.
1727 if (domStorageEnabledInt == 1) { // DOM storage is enabled but JavaScript is disabled.
1728 domStorageEnabledSwitch.setChecked(true);
1729 } else { // Both JavaScript and DOM storage are disabled.
1730 domStorageEnabledSwitch.setChecked(false);
1733 // Set the icon according to the theme.
1734 if (MainWebViewActivity.darkTheme) {
1735 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_dark));
1737 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_ghosted_light));
1743 public void onNothingSelected(AdapterView<?> parent) {
1748 // Set the display webpage images spinner listener.
1749 displayWebpageImagesSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1751 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
1752 // Update the icon and the visibility of `displayImagesTextView`.
1754 case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_SYSTEM_DEFAULT:
1755 if (defaultDisplayWebpageImages) {
1756 // Set the icon according to the theme.
1757 if (MainWebViewActivity.darkTheme) {
1758 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_dark));
1760 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_light));
1763 // Set the icon according to the theme.
1764 if (MainWebViewActivity.darkTheme) {
1765 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_dark));
1767 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_light));
1771 // Show `displayImagesTextView`.
1772 displayImagesTextView.setVisibility(View.VISIBLE);
1775 case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_ENABLED:
1776 // Set the icon according to the theme.
1777 if (MainWebViewActivity.darkTheme) {
1778 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_dark));
1780 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_enabled_light));
1783 // Hide `displayImagesTextView`.
1784 displayImagesTextView.setVisibility(View.GONE);
1787 case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_DISABLED:
1788 // Set the icon according to the theme.
1789 if (MainWebViewActivity.darkTheme) {
1790 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_dark));
1792 displayWebpageImagesImageView.setImageDrawable(resources.getDrawable(R.drawable.images_disabled_light));
1795 // Hide `displayImagesTextView`.
1796 displayImagesTextView.setVisibility(View.GONE);
1802 public void onNothingSelected(AdapterView<?> parent) {
1807 // Set the pinned SSL certificate switch listener.
1808 pinnedSslCertificateSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1810 if (isChecked) { // SSL certificate pinning is enabled.
1811 // Set the icon according to the theme.
1812 if (MainWebViewActivity.darkTheme) {
1813 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_dark));
1815 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_light));
1818 // Update the visibility of the saved SSL certificate.
1819 if (savedSslCertificateIssuedToCNameString == null) {
1820 savedSslCertificateCardView.setVisibility(View.GONE);
1822 savedSslCertificateCardView.setVisibility(View.VISIBLE);
1825 // Update the visibility of the current website SSL certificate.
1826 if (currentWebsiteSslCertificate == null) {
1827 // Hide the SSL certificate.
1828 currentWebsiteCertificateCardView.setVisibility(View.GONE);
1830 // Show the instruction.
1831 noCurrentWebsiteCertificateTextView.setVisibility(View.VISIBLE);
1833 // Show the SSL certificate.
1834 currentWebsiteCertificateCardView.setVisibility(View.VISIBLE);
1836 // Hide the instruction.
1837 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
1840 // Set the status of the radio buttons.
1841 if (savedSslCertificateCardView.getVisibility() == View.VISIBLE) { // The saved SSL certificate is displayed.
1842 // Check the saved SSL certificate radio button.
1843 savedSslCertificateRadioButton.setChecked(true);
1845 // Uncheck the current website SSL certificate radio button.
1846 currentWebsiteCertificateRadioButton.setChecked(false);
1848 // Set the background of the saved SSL certificate linear layout to be transparent.
1849 savedSslCertificateLinearLayout.setBackgroundResource(R.color.transparent);
1851 // Darken the background of the current website SSL certificate linear layout according to the theme.
1852 if (MainWebViewActivity.darkTheme) {
1853 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
1855 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
1858 // Scroll to the current website SSL certificate card.
1859 savedSslCertificateCardView.getParent().requestChildFocus(savedSslCertificateCardView, savedSslCertificateCardView);
1860 } else if (currentWebsiteCertificateCardView.getVisibility() == View.VISIBLE) { // The saved SSL certificate is hidden but the current website SSL certificate is visible.
1861 // Check the current website SSL certificate radio button.
1862 currentWebsiteCertificateRadioButton.setChecked(true);
1864 // Uncheck the saved SSL certificate radio button.
1865 savedSslCertificateRadioButton.setChecked(false);
1867 // Set the background of the current website SSL certificate linear layout to be transparent.
1868 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.transparent);
1870 // Darken the background of the saved SSL certificate linear layout according to the theme.
1871 if (MainWebViewActivity.darkTheme) {
1872 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
1874 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
1877 // Scroll to the current website SSL certificate card.
1878 currentWebsiteCertificateCardView.getParent().requestChildFocus(currentWebsiteCertificateCardView, currentWebsiteCertificateCardView);
1879 } else { // Neither SSL certificate is visible.
1880 // Uncheck both radio buttons.
1881 savedSslCertificateRadioButton.setChecked(false);
1882 currentWebsiteCertificateRadioButton.setChecked(false);
1884 // Scroll to the current website SSL certificate card.
1885 noCurrentWebsiteCertificateTextView.getParent().requestChildFocus(noCurrentWebsiteCertificateTextView, noCurrentWebsiteCertificateTextView);
1887 } else { // SSL certificate pinning is disabled.
1888 // Set the icon according to the theme.
1889 if (MainWebViewActivity.darkTheme) {
1890 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_dark));
1892 pinnedSslCertificateImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_light));
1895 // Hide the SSl certificates and instructions.
1896 savedSslCertificateCardView.setVisibility(View.GONE);
1897 currentWebsiteCertificateCardView.setVisibility(View.GONE);
1898 noCurrentWebsiteCertificateTextView.setVisibility(View.GONE);
1900 // Uncheck the radio buttons.
1901 savedSslCertificateRadioButton.setChecked(false);
1902 currentWebsiteCertificateRadioButton.setChecked(false);
1906 savedSslCertificateCardView.setOnClickListener((View view) -> {
1907 // Check the saved SSL certificate radio button.
1908 savedSslCertificateRadioButton.setChecked(true);
1910 // Uncheck the current website SSL certificate radio button.
1911 currentWebsiteCertificateRadioButton.setChecked(false);
1913 // Set the background of the saved SSL certificate linear layout to be transparent.
1914 savedSslCertificateLinearLayout.setBackgroundResource(R.color.transparent);
1916 // Darken the background of the current website SSL certificate linear layout according to the theme.
1917 if (MainWebViewActivity.darkTheme) {
1918 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
1920 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
1924 savedSslCertificateRadioButton.setOnClickListener((View view) -> {
1925 // Check the saved SSL certificate radio button.
1926 savedSslCertificateRadioButton.setChecked(true);
1928 // Uncheck the current website SSL certificate radio button.
1929 currentWebsiteCertificateRadioButton.setChecked(false);
1931 // Set the background of the saved SSL certificate linear layout to be transparent.
1932 savedSslCertificateLinearLayout.setBackgroundResource(R.color.transparent);
1934 // Darken the background of the current website SSL certificate linear layout according to the theme.
1935 if (MainWebViewActivity.darkTheme) {
1936 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
1938 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
1942 currentWebsiteCertificateCardView.setOnClickListener((View view) -> {
1943 // Check the current website SSL certificate radio button.
1944 currentWebsiteCertificateRadioButton.setChecked(true);
1946 // Uncheck the saved SSL certificate radio button.
1947 savedSslCertificateRadioButton.setChecked(false);
1949 // Set the background of the current website SSL certificate linear layout to be transparent.
1950 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.transparent);
1952 // Darken the background of the saved SSL certificate linear layout according to the theme.
1953 if (MainWebViewActivity.darkTheme) {
1954 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
1956 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
1960 currentWebsiteCertificateRadioButton.setOnClickListener((View view) -> {
1961 // Check the current website SSL certificate radio button.
1962 currentWebsiteCertificateRadioButton.setChecked(true);
1964 // Uncheck the saved SSL certificate radio button.
1965 savedSslCertificateRadioButton.setChecked(false);
1967 // Set the background of the current website SSL certificate linear layout to be transparent.
1968 currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.transparent);
1970 // Darken the background of the saved SSL certificate linear layout according to the theme.
1971 if (MainWebViewActivity.darkTheme) {
1972 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_33);
1974 savedSslCertificateLinearLayout.setBackgroundResource(R.color.black_translucent_11);
1978 // Set the pinned IP addresses switch listener.
1979 pinnedIpAddressesSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
1981 if (isChecked) { // IP addresses pinning is enabled.
1982 // Set the icon according to the theme.
1983 if (MainWebViewActivity.darkTheme) {
1984 pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_dark));
1986 pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_enabled_light));
1989 // Update the visibility of the saved IP addresses card view.
1990 if (savedIpAddresses == null) { // There are no saved IP addresses.
1991 savedIpAddressesCardView.setVisibility(View.GONE);
1992 } else { // There are saved IP addresses.
1993 savedIpAddressesCardView.setVisibility(View.VISIBLE);
1996 // Show the current IP addresses card view.
1997 currentIpAddressesCardView.setVisibility(View.VISIBLE);
1999 // Set the status of the radio buttons.
2000 if (savedIpAddressesCardView.getVisibility() == View.VISIBLE) { // The saved IP addresses are visible.
2001 // Check the saved IP addresses radio button.
2002 savedIpAddressesRadioButton.setChecked(true);
2004 // Uncheck the current IP addresses radio button.
2005 currentIpAddressesRadioButton.setChecked(false);
2007 // Set the background of the saved IP addresses linear layout to be transparent.
2008 savedSslCertificateLinearLayout.setBackgroundResource(R.color.transparent);
2010 // Darken the background of the current IP addresses linear layout according to the theme.
2011 if (MainWebViewActivity.darkTheme) {
2012 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2014 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2016 } else { // The saved IP addresses are not visible.
2017 // Check the current IP addresses radio button.
2018 currentIpAddressesRadioButton.setChecked(true);
2020 // Uncheck the saved IP addresses radio button.
2021 savedIpAddressesRadioButton.setChecked(false);
2023 // Set the background of the current IP addresses linear layout to be transparent.
2024 currentIpAddressesLinearLayout.setBackgroundResource(R.color.transparent);
2026 // Darken the background of the saved IP addresses linear layout according to the theme.
2027 if (MainWebViewActivity.darkTheme) {
2028 savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2030 savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2034 // Scroll to the bottom of the card views.
2035 currentIpAddressesCardView.getParent().requestChildFocus(currentIpAddressesCardView, currentIpAddressesCardView);
2036 } else { // IP addresses pinning is disabled.
2037 // Set the icon according to the theme.
2038 if (MainWebViewActivity.darkTheme) {
2039 pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_dark));
2041 pinnedIpAddressesImageView.setImageDrawable(resources.getDrawable(R.drawable.ssl_certificate_disabled_light));
2044 // Hide the IP addresses card views.
2045 savedIpAddressesCardView.setVisibility(View.GONE);
2046 currentIpAddressesCardView.setVisibility(View.GONE);
2048 // Uncheck the radio buttons.
2049 savedIpAddressesRadioButton.setChecked(false);
2050 currentIpAddressesRadioButton.setChecked(false);
2054 savedIpAddressesCardView.setOnClickListener((View view) -> {
2055 // Check the saved IP addresses radio button.
2056 savedIpAddressesRadioButton.setChecked(true);
2058 // Uncheck the current website IP addresses radio button.
2059 currentIpAddressesRadioButton.setChecked(false);
2061 // Set the background of the saved IP addresses linear layout to be transparent.
2062 savedIpAddressesLinearLayout.setBackgroundResource(R.color.transparent);
2064 // Darken the background of the current IP addresses linear layout according to the theme.
2065 if (MainWebViewActivity.darkTheme) {
2066 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2068 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2072 savedIpAddressesRadioButton.setOnClickListener((View view) -> {
2073 // Check the saved IP addresses radio button.
2074 savedIpAddressesRadioButton.setChecked(true);
2076 // Uncheck the current website IP addresses radio button.
2077 currentIpAddressesRadioButton.setChecked(false);
2079 // Set the background of the saved IP addresses linear layout to be transparent.
2080 savedIpAddressesLinearLayout.setBackgroundResource(R.color.transparent);
2082 // Darken the background of the current IP addresses linear layout according to the theme.
2083 if (MainWebViewActivity.darkTheme) {
2084 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2086 currentIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2090 currentIpAddressesCardView.setOnClickListener((View view) -> {
2091 // Check the current IP addresses radio button.
2092 currentIpAddressesRadioButton.setChecked(true);
2094 // Uncheck the saved IP addresses radio button.
2095 savedIpAddressesRadioButton.setChecked(false);
2097 // Set the background of the current IP addresses linear layout to be transparent.
2098 currentIpAddressesLinearLayout.setBackgroundResource(R.color.transparent);
2100 // Darken the background of the saved IP addresses linear layout according to the theme.
2101 if (MainWebViewActivity.darkTheme) {
2102 savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2104 savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2108 currentIpAddressesRadioButton.setOnClickListener((View view) -> {
2109 // Check the current IP addresses radio button.
2110 currentIpAddressesRadioButton.setChecked(true);
2112 // Uncheck the saved IP addresses radio button.
2113 savedIpAddressesRadioButton.setChecked(false);
2115 // Set the background of the current IP addresses linear layout to be transparent.
2116 currentIpAddressesLinearLayout.setBackgroundResource(R.color.transparent);
2118 // Darken the background of the saved IP addresses linear layout according to the theme.
2119 if (MainWebViewActivity.darkTheme) {
2120 savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_33);
2122 savedIpAddressesLinearLayout.setBackgroundResource(R.color.black_translucent_11);
2126 return domainSettingsView;
2129 private boolean checkDomainNameAgainstCertificate(String domainName, String certificateCommonName) {
2130 // Initialize `domainNamesMatch`.
2131 boolean domainNamesMatch = false;
2133 // Check various wildcard permutations if `domainName` and `certificateCommonName` are not empty.
2134 // `noinspection ConstantCondition` removes Android Studio's incorrect lint warning that `domainName` can never be `null`.
2135 //noinspection ConstantConditions
2136 if ((domainName != null) && (certificateCommonName != null)) {
2137 // Check if the domains match.
2138 if (domainName.equals(certificateCommonName)) {
2139 domainNamesMatch = true;
2142 // If `domainName` starts with a wildcard, check the base domain against all the subdomains of `certificateCommonName`.
2143 if (!domainNamesMatch && domainName.startsWith("*.") && (domainName.length() > 2)) {
2144 // Remove the initial `*.`.
2145 String baseDomainName = domainName.substring(2);
2147 // Setup a copy of `certificateCommonName` to test subdomains.
2148 String certificateCommonNameSubdomain = certificateCommonName;
2150 // Check all the subdomains in `certificateCommonNameSubdomain` against `baseDomainName`.
2151 while (!domainNamesMatch && certificateCommonNameSubdomain.contains(".")) { // Stop checking if we know that `domainNamesMatch` is `true` or if we run out of `.`.
2152 // Test the `certificateCommonNameSubdomain` against `baseDomainName`.
2153 if (certificateCommonNameSubdomain.equals(baseDomainName)) {
2154 domainNamesMatch = true;
2157 // Strip out the lowest subdomain of `certificateCommonNameSubdomain`.
2159 certificateCommonNameSubdomain = certificateCommonNameSubdomain.substring(certificateCommonNameSubdomain.indexOf(".") + 1);
2160 } catch (IndexOutOfBoundsException e) { // `certificateCommonNameSubdomain` ends with `.`.
2161 certificateCommonNameSubdomain = "";
2166 // If `certificateCommonName` starts with a wildcard, check the base common name against all the subdomains of `domainName`.
2167 if (!domainNamesMatch && certificateCommonName.startsWith("*.") && (certificateCommonName.length() > 2)) {
2168 // Remove the initial `*.`.
2169 String baseCertificateCommonName = certificateCommonName.substring(2);
2171 // Setup a copy of `domainName` to test subdomains.
2172 String domainNameSubdomain = domainName;
2174 // Check all the subdomains in `domainNameSubdomain` against `baseCertificateCommonName`.
2175 while (!domainNamesMatch && domainNameSubdomain.contains(".") && (domainNameSubdomain.length() > 2)) {
2176 // Test the `domainNameSubdomain` against `baseCertificateCommonName`.
2177 if (domainNameSubdomain.equals(baseCertificateCommonName)) {
2178 domainNamesMatch = true;
2181 // Strip out the lowest subdomain of `domainNameSubdomain`.
2183 domainNameSubdomain = domainNameSubdomain.substring(domainNameSubdomain.indexOf(".") + 1);
2184 } catch (IndexOutOfBoundsException e) { // `domainNameSubdomain` ends with `.`.
2185 domainNameSubdomain = "";
2190 // If both names start with a wildcard, check if the root of one contains the root of the other.
2191 if (!domainNamesMatch && domainName.startsWith("*.") && (domainName.length() > 2) && certificateCommonName.startsWith("*.") && (certificateCommonName.length() > 2)) {
2192 // Remove the wildcards.
2193 String rootDomainName = domainName.substring(2);
2194 String rootCertificateCommonName = certificateCommonName.substring(2);
2196 // Check if one name ends with the contents of the other. If so, there will be overlap in the their wildcard subdomains.
2197 if (rootDomainName.endsWith(rootCertificateCommonName) || rootCertificateCommonName.endsWith(rootDomainName)) {
2198 domainNamesMatch = true;
2203 return domainNamesMatch;