2 * Copyright © 2016-2022 Soren Stoutner <soren@stoutner.com>.
4 * This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
6 * Privacy Browser Android is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * Privacy Browser Android is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with Privacy Browser Android. If not, see <http://www.gnu.org/licenses/>.
20 package com.stoutner.privacybrowser.fragments;
22 import android.annotation.SuppressLint;
23 import android.app.Activity;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.content.SharedPreferences;
27 import android.content.res.Configuration;
28 import android.content.res.Resources;
29 import android.os.Build;
30 import android.os.Bundle;
31 import android.os.Handler;
32 import android.os.Looper;
33 import android.view.LayoutInflater;
34 import android.view.View;
35 import android.webkit.WebView;
36 import android.widget.ArrayAdapter;
38 import androidx.appcompat.app.AppCompatDelegate;
39 import androidx.preference.Preference;
40 import androidx.preference.PreferenceCategory;
41 import androidx.preference.PreferenceFragmentCompat;
43 import com.stoutner.privacybrowser.R;
44 import com.stoutner.privacybrowser.activities.MainWebViewActivity;
45 import com.stoutner.privacybrowser.helpers.ProxyHelper;
47 import java.util.Objects;
49 public class SettingsFragment extends PreferenceFragmentCompat {
50 // Declare the class variables.
51 private int currentThemeStatus;
52 private String defaultUserAgent;
53 private ArrayAdapter<CharSequence> userAgentNamesArray;
54 private String[] translatedUserAgentNamesArray;
55 private String[] userAgentDataArray;
56 private String[] appThemeEntriesStringArray;
57 private String[] appThemeEntryValuesStringArray;
58 private String[] webViewThemeEntriesStringArray;
59 private String[] webViewThemeEntryValuesStringArray;
60 private SharedPreferences.OnSharedPreferenceChangeListener sharedPreferenceChangeListener;
62 // Declare the class views.
63 private Preference javaScriptPreference;
64 private Preference cookiesPreference;
65 private Preference domStoragePreference;
66 private Preference formDataPreference; // The form data preference can be removed once the minimum API >= 26.
67 private Preference userAgentPreference;
68 private Preference customUserAgentPreference;
69 private Preference incognitoModePreference;
70 private Preference allowScreenshotsPreference;
71 private Preference easyListPreference;
72 private Preference easyPrivacyPreference;
73 private Preference fanboyAnnoyanceListPreference;
74 private Preference fanboySocialBlockingListPreference;
75 private Preference ultraListPreference;
76 private Preference ultraPrivacyPreference;
77 private Preference blockAllThirdPartyRequestsPreference;
78 private Preference trackingQueriesPreference;
79 private Preference ampRedirectsPreference;
80 private Preference searchPreference;
81 private Preference searchCustomURLPreference;
82 private Preference proxyPreference;
83 private Preference proxyCustomUrlPreference;
84 private Preference fullScreenBrowsingModePreference;
85 private Preference hideAppBarPreference;
86 private Preference clearEverythingPreference;
87 private Preference clearCookiesPreference;
88 private Preference clearDomStoragePreference;
89 private Preference clearFormDataPreference; // The clear form data preference can be removed once the minimum API >= 26.
90 private Preference clearLogcatPreference;
91 private Preference clearCachePreference;
92 private Preference homepagePreference;
93 private Preference fontSizePreference;
94 private Preference openIntentsInNewTabPreference;
95 private Preference swipeToRefreshPreference;
96 private Preference downloadWithExternalAppPreference;
97 private Preference scrollAppBarPreference;
98 private Preference bottomAppBarPreference;
99 private Preference displayAdditionalAppBarIconsPreference;
100 private Preference appThemePreference;
101 private Preference webViewThemePreference;
102 private Preference wideViewportPreference;
103 private Preference displayWebpageImagesPreference;
106 public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
107 // Load the preferences from the XML file.
108 setPreferencesFromResource(R.xml.preferences, rootKey);
110 // Get a handle for the activity.
111 Activity activity = getActivity();
113 // Remove the lint warning below that `getApplicationContext()` might produce a null pointer exception.
114 assert activity != null;
116 // Get a handle for the resources.
117 Resources resources = getResources();
119 // Get the current theme status.
120 currentThemeStatus = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
122 // Get a handle for the shared preferences.
123 SharedPreferences sharedPreferences = getPreferenceScreen().getSharedPreferences();
125 // Remove the incorrect warning below that the shared preferences might be null.
126 assert sharedPreferences != null;
128 // Get handles for the preferences.
129 javaScriptPreference = findPreference("javascript");
130 cookiesPreference = findPreference(getString(R.string.cookies_key));
131 domStoragePreference = findPreference("dom_storage");
132 formDataPreference = findPreference("save_form_data"); // The form data preference can be removed once the minimum API >= 26.
133 userAgentPreference = findPreference("user_agent");
134 customUserAgentPreference = findPreference("custom_user_agent");
135 incognitoModePreference = findPreference("incognito_mode");
136 allowScreenshotsPreference = findPreference(getString(R.string.allow_screenshots_key));
137 easyListPreference = findPreference("easylist");
138 easyPrivacyPreference = findPreference("easyprivacy");
139 fanboyAnnoyanceListPreference = findPreference("fanboys_annoyance_list");
140 fanboySocialBlockingListPreference = findPreference("fanboys_social_blocking_list");
141 ultraListPreference = findPreference("ultralist");
142 ultraPrivacyPreference = findPreference("ultraprivacy");
143 blockAllThirdPartyRequestsPreference = findPreference("block_all_third_party_requests");
144 trackingQueriesPreference = findPreference(getString(R.string.tracking_queries_key));
145 ampRedirectsPreference = findPreference(getString(R.string.amp_redirects_key));
146 searchPreference = findPreference("search");
147 searchCustomURLPreference = findPreference("search_custom_url");
148 proxyPreference = findPreference("proxy");
149 proxyCustomUrlPreference = findPreference(getString(R.string.proxy_custom_url_key));
150 fullScreenBrowsingModePreference = findPreference("full_screen_browsing_mode");
151 hideAppBarPreference = findPreference("hide_app_bar");
152 clearEverythingPreference = findPreference("clear_everything");
153 clearCookiesPreference = findPreference("clear_cookies");
154 clearDomStoragePreference = findPreference("clear_dom_storage");
155 clearFormDataPreference = findPreference("clear_form_data"); // The clear form data preference can be removed once the minimum API >= 26.
156 clearLogcatPreference = findPreference(getString(R.string.clear_logcat_key));
157 clearCachePreference = findPreference("clear_cache");
158 homepagePreference = findPreference("homepage");
159 fontSizePreference = findPreference("font_size");
160 openIntentsInNewTabPreference = findPreference("open_intents_in_new_tab");
161 swipeToRefreshPreference = findPreference("swipe_to_refresh");
162 downloadWithExternalAppPreference = findPreference(getString(R.string.download_with_external_app_key));
163 scrollAppBarPreference = findPreference(getString(R.string.scroll_app_bar_key));
164 bottomAppBarPreference = findPreference(getString(R.string.bottom_app_bar_key));
165 displayAdditionalAppBarIconsPreference = findPreference(getString(R.string.display_additional_app_bar_icons_key));
166 appThemePreference = findPreference("app_theme");
167 webViewThemePreference = findPreference("webview_theme");
168 wideViewportPreference = findPreference("wide_viewport");
169 displayWebpageImagesPreference = findPreference("display_webpage_images");
171 // Remove the lint warnings below that the preferences might be null.
172 assert javaScriptPreference != null;
173 assert cookiesPreference != null;
174 assert domStoragePreference != null;
175 assert formDataPreference != null;
176 assert userAgentPreference != null;
177 assert customUserAgentPreference != null;
178 assert incognitoModePreference != null;
179 assert allowScreenshotsPreference != null;
180 assert easyListPreference != null;
181 assert easyPrivacyPreference != null;
182 assert fanboyAnnoyanceListPreference != null;
183 assert fanboySocialBlockingListPreference != null;
184 assert ultraListPreference != null;
185 assert ultraPrivacyPreference != null;
186 assert blockAllThirdPartyRequestsPreference != null;
187 assert trackingQueriesPreference != null;
188 assert ampRedirectsPreference != null;
189 assert searchPreference != null;
190 assert searchCustomURLPreference != null;
191 assert proxyPreference != null;
192 assert proxyCustomUrlPreference != null;
193 assert fullScreenBrowsingModePreference != null;
194 assert hideAppBarPreference != null;
195 assert clearEverythingPreference != null;
196 assert clearCookiesPreference != null;
197 assert clearDomStoragePreference != null;
198 assert clearFormDataPreference != null;
199 assert clearLogcatPreference != null;
200 assert clearCachePreference != null;
201 assert homepagePreference != null;
202 assert fontSizePreference != null;
203 assert openIntentsInNewTabPreference != null;
204 assert swipeToRefreshPreference != null;
205 assert downloadWithExternalAppPreference != null;
206 assert scrollAppBarPreference != null;
207 assert bottomAppBarPreference != null;
208 assert displayAdditionalAppBarIconsPreference != null;
209 assert appThemePreference != null;
210 assert webViewThemePreference != null;
211 assert wideViewportPreference != null;
212 assert displayWebpageImagesPreference != null;
214 // Set the preference dependencies.
215 hideAppBarPreference.setDependency("full_screen_browsing_mode");
216 domStoragePreference.setDependency("javascript");
218 // Get strings from the preferences.
219 String userAgentName = sharedPreferences.getString("user_agent", getString(R.string.user_agent_default_value));
220 String searchString = sharedPreferences.getString("search", getString(R.string.search_default_value));
221 String proxyString = sharedPreferences.getString("proxy", getString(R.string.proxy_default_value));
223 // Get booleans that are used in multiple places from the preferences.
224 boolean javaScriptEnabled = sharedPreferences.getBoolean("javascript", false);
225 boolean fanboyAnnoyanceListEnabled = sharedPreferences.getBoolean("fanboys_annoyance_list", true);
226 boolean fanboySocialBlockingEnabled = sharedPreferences.getBoolean("fanboys_social_blocking_list", true);
227 boolean fullScreenBrowsingMode = sharedPreferences.getBoolean("full_screen_browsing_mode", false);
228 boolean clearEverything = sharedPreferences.getBoolean("clear_everything", true);
230 // Remove the form data preferences if the API is >= 26 as they no longer do anything.
231 if (Build.VERSION.SDK_INT >= 26) {
232 // Get handles for the categories.
233 PreferenceCategory privacyCategory = findPreference("privacy");
234 PreferenceCategory clearAndExitCategory = findPreference("clear_and_exit");
236 // Remove the incorrect lint warnings below that the preference categories might be null.
237 assert privacyCategory != null;
238 assert clearAndExitCategory != null;
240 // Remove the form data preferences.
241 privacyCategory.removePreference(formDataPreference);
242 clearAndExitCategory.removePreference(clearFormDataPreference);
245 // Only enable Fanboy's social blocking list preference if Fanboy's annoyance list is disabled.
246 fanboySocialBlockingListPreference.setEnabled(!fanboyAnnoyanceListEnabled);
249 // Inflate a WebView to get the default user agent.
250 LayoutInflater inflater = getActivity().getLayoutInflater();
252 // `@SuppressLint("InflateParams")` removes the warning about using `null` as the `ViewGroup`, which in this case makes sense because the `bare_webview` will not be displayed.
253 @SuppressLint("InflateParams") View bareWebViewLayout = inflater.inflate(R.layout.bare_webview, null, false);
255 // Get a handle for a bare WebView.
256 WebView bareWebView = bareWebViewLayout.findViewById(R.id.bare_webview);
258 // Get the default user agent.
259 defaultUserAgent = bareWebView.getSettings().getUserAgentString();
261 // Get the user agent arrays.
262 userAgentNamesArray = ArrayAdapter.createFromResource(requireContext(), R.array.user_agent_names, R.layout.spinner_item);
263 translatedUserAgentNamesArray = resources.getStringArray(R.array.translated_user_agent_names);
264 userAgentDataArray = resources.getStringArray(R.array.user_agent_data);
266 // Get the array position of the user agent name.
267 int userAgentArrayPosition = userAgentNamesArray.getPosition(userAgentName);
269 // Populate the user agent summary.
270 switch (userAgentArrayPosition) {
271 case MainWebViewActivity.UNRECOGNIZED_USER_AGENT: // The user agent name is not on the canonical list.
272 // This is probably because it was set in an older version of Privacy Browser before the switch to persistent user agent names. Use the current user agent entry name as the summary.
273 userAgentPreference.setSummary(userAgentName);
276 case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
277 // Get the user agent text from the webview (which changes based on the version of Android and WebView installed).
278 userAgentPreference.setSummary(translatedUserAgentNamesArray[userAgentArrayPosition] + ":\n" + defaultUserAgent);
281 case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
282 // Set the summary text.
283 userAgentPreference.setSummary(R.string.custom_user_agent);
287 // Get the user agent summary from the user agent data array.
288 userAgentPreference.setSummary(translatedUserAgentNamesArray[userAgentArrayPosition] + ":\n" + userAgentDataArray[userAgentArrayPosition]);
291 // Set the summary text for the custom user agent preference.
292 customUserAgentPreference.setSummary(sharedPreferences.getString("custom_user_agent", getString(R.string.custom_user_agent_default_value)));
294 // Only enable the custom user agent preference if the user agent is set to `Custom`.
295 customUserAgentPreference.setEnabled(Objects.equals(userAgentPreference.getSummary(), getString(R.string.custom_user_agent)));
297 // Set the search URL as the summary text for the search preference when the preference screen is loaded.
298 if (searchString.equals("Custom URL")) {
299 // Use R.string.custom_url, which will be translated, instead of the array value, which will not.
300 searchPreference.setSummary(R.string.custom_url);
302 // Set the array value as the summary text.
303 searchPreference.setSummary(searchString);
306 // Set the summary text for the search custom URL (the default is `""`).
307 searchCustomURLPreference.setSummary(sharedPreferences.getString("search_custom_url", getString(R.string.search_custom_url_default_value)));
309 // Only enable the search custom URL preference if the search is set to `Custom URL`.
310 searchCustomURLPreference.setEnabled(searchString.equals("Custom URL"));
313 // Set the summary text for the proxy preference when the preference screen is loaded.
314 switch (proxyString) {
315 case ProxyHelper.NONE:
316 proxyPreference.setSummary(getString(R.string.no_proxy_enabled));
319 case ProxyHelper.TOR:
320 proxyPreference.setSummary(getString(R.string.tor_enabled));
323 case ProxyHelper.I2P:
324 proxyPreference.setSummary(getString(R.string.i2p_enabled));
327 case ProxyHelper.CUSTOM:
328 proxyPreference.setSummary(getString(R.string.custom_proxy));
332 // Set the summary text for the custom proxy URL.
333 proxyCustomUrlPreference.setSummary(sharedPreferences.getString(getString(R.string.proxy_custom_url_key), getString(R.string.proxy_custom_url_default_value)));
335 // Only enable the custom proxy URL if a custom proxy is selected.
336 proxyCustomUrlPreference.setEnabled(proxyString.equals(ProxyHelper.CUSTOM));
339 // Set the status of the clear and exit preferences.
340 clearCookiesPreference.setEnabled(!clearEverything);
341 clearDomStoragePreference.setEnabled(!clearEverything);
342 clearFormDataPreference.setEnabled(!clearEverything); // The form data line can be removed once the minimum API is >= 26.
343 clearLogcatPreference.setEnabled(!clearEverything);
344 clearCachePreference.setEnabled(!clearEverything);
347 // Set the homepage URL as the summary text for the homepage preference.
348 homepagePreference.setSummary(sharedPreferences.getString("homepage", getString(R.string.homepage_default_value)));
351 // Set the font size as the summary text for the preference.
352 fontSizePreference.setSummary(sharedPreferences.getString("font_size", getString(R.string.font_size_default_value)) + "%");
355 // Get the app theme string arrays.
356 appThemeEntriesStringArray = resources.getStringArray(R.array.app_theme_entries);
357 appThemeEntryValuesStringArray = resources.getStringArray(R.array.app_theme_entry_values);
359 // Get the current app theme.
360 String currentAppTheme = sharedPreferences.getString("app_theme", getString(R.string.app_theme_default_value));
362 // Define an app theme entry number.
363 int appThemeEntryNumber;
365 // Get the app theme entry number that matches the current app theme. A switch statement cannot be used because the theme entry values string array is not a compile time constant.
366 if (currentAppTheme.equals(appThemeEntryValuesStringArray[1])) { // The light theme is selected.
367 // Store the app theme entry number.
368 appThemeEntryNumber = 1;
369 } else if (currentAppTheme.equals(appThemeEntryValuesStringArray[2])) { // The dark theme is selected.
370 // Store the app theme entry number.
371 appThemeEntryNumber = 2;
372 } else { // The system default theme is selected.
373 // Store the app theme entry number.
374 appThemeEntryNumber = 0;
377 // Set the current theme as the summary text for the preference.
378 appThemePreference.setSummary(appThemeEntriesStringArray[appThemeEntryNumber]);
381 // Get the WebView theme string arrays.
382 webViewThemeEntriesStringArray = resources.getStringArray(R.array.webview_theme_entries);
383 webViewThemeEntryValuesStringArray = resources.getStringArray(R.array.webview_theme_entry_values);
385 // Get the current WebView theme.
386 String currentWebViewTheme = sharedPreferences.getString("webview_theme", getString(R.string.webview_theme_default_value));
388 // Define a WebView theme entry number.
389 int webViewThemeEntryNumber;
391 // Get the WebView theme entry number that matches the current WebView theme. A switch statement cannot be used because the WebView theme entry values string array is not a compile time constant.
392 if (currentWebViewTheme.equals(webViewThemeEntryValuesStringArray[1])) { // The light theme is selected.
393 // Store the WebView theme entry number.
394 webViewThemeEntryNumber = 1;
395 } else if (currentWebViewTheme.equals(webViewThemeEntryValuesStringArray[2])) { // The dark theme is selected.
396 // Store the WebView theme entry number.
397 webViewThemeEntryNumber = 2;
398 } else { // The system default theme is selected.
399 // Store the WebView theme entry number.
400 webViewThemeEntryNumber = 0;
403 // Set the current theme as the summary text for the preference.
404 webViewThemePreference.setSummary(webViewThemeEntriesStringArray[webViewThemeEntryNumber]);
407 // Set the JavaScript icon.
408 if (javaScriptEnabled) {
409 javaScriptPreference.setIcon(R.drawable.javascript_enabled);
411 javaScriptPreference.setIcon(R.drawable.privacy_mode);
414 // Set the cookies icon.
415 if (sharedPreferences.getBoolean(getString(R.string.cookies_key), false)) {
416 cookiesPreference.setIcon(R.drawable.cookies_enabled);
418 cookiesPreference.setIcon(R.drawable.cookies_disabled);
421 // Set the DOM storage icon.
422 if (javaScriptEnabled) { // The preference is enabled.
423 if (sharedPreferences.getBoolean("dom_storage", false)) { // DOM storage is enabled.
424 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
425 } else { // DOM storage is disabled.
426 domStoragePreference.setIcon(R.drawable.dom_storage_disabled);
428 } else { // The preference is disabled. The icon should be ghosted.
429 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted);
432 // Set the save form data icon if API < 26. Save form data has no effect on API >= 26.
433 if (Build.VERSION.SDK_INT < 26) {
434 if (sharedPreferences.getBoolean("save_form_data", false)) {
435 formDataPreference.setIcon(R.drawable.form_data_enabled);
437 formDataPreference.setIcon(R.drawable.form_data_disabled);
441 // Set the custom user agent icon.
442 if (customUserAgentPreference.isEnabled()) {
443 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled);
445 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted);
448 // Set the incognito mode icon.
449 if (sharedPreferences.getBoolean("incognito_mode", false)) {
450 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled);
452 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled);
455 // Set the allow screenshots icon.
456 if (sharedPreferences.getBoolean(getString(R.string.allow_screenshots_key), false)) {
457 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled);
459 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled);
462 // Set the EasyList icon.
463 if (sharedPreferences.getBoolean("easylist", true)) {
464 easyListPreference.setIcon(R.drawable.block_ads_enabled);
466 easyListPreference.setIcon(R.drawable.block_ads_disabled);
469 // Set the EasyPrivacy icon.
470 if (sharedPreferences.getBoolean("easyprivacy", true)) {
471 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled);
473 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled);
476 // Set the Fanboy lists icons.
477 if (fanboyAnnoyanceListEnabled) {
478 // Set the Fanboy annoyance list icon.
479 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled);
481 // Set the Fanboy social blocking list icon.
482 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted);
484 // Set the Fanboy annoyance list icon.
485 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled);
487 // Set the Fanboy social blocking list icon.
488 if (fanboySocialBlockingEnabled) {
489 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled);
491 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled);
495 // Set the UltraList icon.
496 if (sharedPreferences.getBoolean("ultralist", true)){
497 ultraListPreference.setIcon(R.drawable.block_ads_enabled);
499 ultraListPreference.setIcon(R.drawable.block_ads_disabled);
502 // Set the UltraPrivacy icon.
503 if (sharedPreferences.getBoolean("ultraprivacy", true)) {
504 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled);
506 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled);
509 // Set the block all third-party requests icon.
510 if (sharedPreferences.getBoolean("block_all_third_party_requests", false)) {
511 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled);
513 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled);
516 // Set the Tracking Queries icon.
517 if (sharedPreferences.getBoolean(getString(R.string.tracking_queries_key), true)) {
518 trackingQueriesPreference.setIcon(R.drawable.modify_url_enabled);
520 trackingQueriesPreference.setIcon(R.drawable.modify_url_disabled);
523 // Set the AMP Redirects icon.
524 if (sharedPreferences.getBoolean(getString(R.string.amp_redirects_key), true)) {
525 ampRedirectsPreference.setIcon(R.drawable.modify_url_enabled);
527 ampRedirectsPreference.setIcon(R.drawable.modify_url_disabled);
530 // Set the search custom URL icon.
531 if (searchCustomURLPreference.isEnabled()) {
532 searchCustomURLPreference.setIcon(R.drawable.search_custom_enabled);
534 searchCustomURLPreference.setIcon(R.drawable.search_custom_ghosted);
537 // Set the Proxy icons according to the theme and status.
538 if (proxyString.equals(ProxyHelper.NONE)) { // Proxying is disabled.
539 // Set the main proxy icon to be disabled.
540 proxyPreference.setIcon(R.drawable.proxy_disabled);
542 // Set the custom proxy URL icon to be ghosted.
543 proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted);
544 } else { // Proxying is enabled.
545 // Set the main proxy icon to be enabled.
546 proxyPreference.setIcon(R.drawable.proxy_enabled);
548 // Set the custom proxy URL icon according to its status.
549 if (proxyCustomUrlPreference.isEnabled()) {
550 proxyCustomUrlPreference.setIcon(R.drawable.proxy_enabled);
552 proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted);
556 // Set the full screen browsing mode icons.
557 if (fullScreenBrowsingMode) { // Full screen browsing mode is enabled.
558 // Set the full screen browsing mode preference icon.
559 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled);
561 // Set the hide app bar icon.
562 if (sharedPreferences.getBoolean("hide_app_bar", true)) {
563 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled);
565 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled);
567 } else { // Full screen browsing mode is disabled.
569 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled);
570 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted);
573 // Set the clear everything preference icon.
574 if (clearEverything) {
575 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled);
577 clearEverythingPreference.setIcon(R.drawable.clear_everything_disabled);
580 // Set the clear cookies preference icon.
581 if (clearEverything || sharedPreferences.getBoolean("clear_cookies", true)) {
582 clearCookiesPreference.setIcon(R.drawable.clear_cookies_enabled);
584 clearCookiesPreference.setIcon(R.drawable.clear_cookies_disabled);
587 // Set the clear DOM storage preference icon.
588 if (clearEverything || sharedPreferences.getBoolean("clear_dom_storage", true)) {
589 clearDomStoragePreference.setIcon(R.drawable.clear_dom_storage_enabled);
591 clearDomStoragePreference.setIcon(R.drawable.clear_dom_storage_disabled);
594 // Set the clear form data preference icon if the API < 26. It has no effect on newer versions of Android.
595 if (Build.VERSION.SDK_INT < 26) {
596 if (clearEverything || sharedPreferences.getBoolean("clear_form_data", true)) {
597 clearFormDataPreference.setIcon(R.drawable.clear_form_data_enabled);
599 clearFormDataPreference.setIcon(R.drawable.clear_form_data_disabled);
603 // Set the clear logcat preference icon.
604 if (clearEverything || sharedPreferences.getBoolean(getString(R.string.clear_logcat_key), true)) {
605 clearLogcatPreference.setIcon(R.drawable.clear_logcat_enabled);
607 clearLogcatPreference.setIcon(R.drawable.clear_logcat_disabled);
610 // Set the clear cache preference icon.
611 if (clearEverything || sharedPreferences.getBoolean("clear_cache", true)) {
612 clearCachePreference.setIcon(R.drawable.clear_cache_enabled);
614 clearCachePreference.setIcon(R.drawable.clear_cache_disabled);
617 // Set the open intents in new tab preference icon.
618 if (sharedPreferences.getBoolean("open_intents_in_new_tab", true)) {
619 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled);
621 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled);
624 // Set the swipe to refresh preference icon.
625 if (sharedPreferences.getBoolean("swipe_to_refresh", true)) {
626 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled);
628 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled);
631 // Set the download with external app preference icon.
632 if (sharedPreferences.getBoolean(getString(R.string.download_with_external_app_key), false)) {
633 downloadWithExternalAppPreference.setIcon(R.drawable.download_with_external_app_enabled);
635 downloadWithExternalAppPreference.setIcon(R.drawable.download_with_external_app_disabled);
638 // Set the scroll app bar preference icon.
639 if (sharedPreferences.getBoolean(getString(R.string.scroll_app_bar_key), true)) {
640 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled);
642 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled);
645 // Set the bottom app bar preference icon.
646 if (sharedPreferences.getBoolean(getString(R.string.bottom_app_bar_key), false)) {
647 bottomAppBarPreference.setIcon(R.drawable.bottom_app_bar_enabled);
649 bottomAppBarPreference.setIcon(R.drawable.bottom_app_bar_disabled);
652 // Set the display additional app bar icons preference icon.
653 if (sharedPreferences.getBoolean(getString(R.string.display_additional_app_bar_icons_key), false)) {
654 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled);
656 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled);
659 // Set the WebView theme preference icon.
660 switch (webViewThemeEntryNumber) {
661 case 0: // The system default WebView theme is selected.
662 // Set the icon according to the app theme.
663 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
664 webViewThemePreference.setIcon(R.drawable.webview_light_theme);
666 webViewThemePreference.setIcon(R.drawable.webview_dark_theme);
670 case 1: // The light WebView theme is selected.
672 webViewThemePreference.setIcon(R.drawable.webview_light_theme);
675 case 2: // The dark WebView theme is selected.
677 webViewThemePreference.setIcon(R.drawable.webview_dark_theme);
681 // Set the wide viewport preference icon.
682 if (sharedPreferences.getBoolean("wide_viewport", true)) {
683 wideViewportPreference.setIcon(R.drawable.wide_viewport_enabled);
685 wideViewportPreference.setIcon(R.drawable.wide_viewport_disabled);
688 // Set the display webpage images preference icon.
689 if (sharedPreferences.getBoolean("display_webpage_images", true)) {
690 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled);
692 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled);
696 // The listener should be unregistered when the app is paused.
698 public void onPause() {
699 // Run the default commands.
702 // Get a handle for the shared preferences.
703 SharedPreferences sharedPreferences = getPreferenceScreen().getSharedPreferences();
705 // Remove the incorrect lint warning below that the shared preferences might be null.
706 assert sharedPreferences != null;
708 // Unregister the shared preference listener.
709 sharedPreferences.unregisterOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
712 // The listener should be re-registered when the app is resumed.
714 public void onResume() {
715 // Run the default commands.
718 // Get a new shared preference change listener.
719 sharedPreferenceChangeListener = getSharedPreferenceChangeListener(requireContext());
721 // Get a handle for the shared preferences.
722 SharedPreferences sharedPreferences = getPreferenceScreen().getSharedPreferences();
724 // Remove the incorrect lint warning below that the shared preferences might be null.
725 assert sharedPreferences != null;
727 // Re-register the shared preference listener.
728 sharedPreferences.registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
731 // The context must be passed to the shared preference change listener or else any calls to the system `getString()` will crash if the app has been restarted.
732 // This can be removed at some future point, perhaps after the switch to PreferenceScreenCompat. It isn't an issue in Privacy Cell.
733 private SharedPreferences.OnSharedPreferenceChangeListener getSharedPreferenceChangeListener(Context context) {
734 // Return the shared preference change listener.
735 return (SharedPreferences sharedPreferences, String key) -> {
738 // Update the icons and the DOM storage preference status.
739 if (sharedPreferences.getBoolean("javascript", false)) { // The JavaScript preference is enabled.
740 // Update the icon for the JavaScript preference.
741 javaScriptPreference.setIcon(R.drawable.javascript_enabled);
743 // Update the status of the DOM storage preference.
744 domStoragePreference.setEnabled(true);
746 // Update the icon for the DOM storage preference.
747 if (sharedPreferences.getBoolean("dom_storage", false)) {
748 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
750 domStoragePreference.setIcon(R.drawable.dom_storage_disabled);
752 } else { // The JavaScript preference is disabled.
753 // Update the icon for the JavaScript preference.
754 javaScriptPreference.setIcon(R.drawable.privacy_mode);
756 // Update the status of the DOM storage preference.
757 domStoragePreference.setEnabled(false);
759 // Set the icon for DOM storage preference to be ghosted.
760 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted);
766 if (sharedPreferences.getBoolean(context.getString(R.string.cookies_key), false)) {
767 cookiesPreference.setIcon(R.drawable.cookies_enabled);
769 cookiesPreference.setIcon(R.drawable.cookies_disabled);
775 if (sharedPreferences.getBoolean("dom_storage", false)) {
776 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
778 domStoragePreference.setIcon(R.drawable.dom_storage_disabled);
782 // Save form data can be removed once the minimum API >= 26.
783 case "save_form_data":
785 if (sharedPreferences.getBoolean("save_form_data", false)) {
786 formDataPreference.setIcon(R.drawable.form_data_enabled);
788 formDataPreference.setIcon(R.drawable.form_data_disabled);
793 // Get the new user agent name.
794 String newUserAgentName = sharedPreferences.getString("user_agent", context.getString(R.string.user_agent_default_value));
796 // Get the array position for the new user agent name.
797 int newUserAgentArrayPosition = userAgentNamesArray.getPosition(newUserAgentName);
799 // Get the translated new user agent name.
800 String translatedNewUserAgentName = translatedUserAgentNamesArray[newUserAgentArrayPosition];
802 // Populate the user agent summary.
803 switch (newUserAgentArrayPosition) {
804 case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
805 // Get the user agent text from the webview (which changes based on the version of Android and WebView installed).
806 userAgentPreference.setSummary(translatedNewUserAgentName + ":\n" + defaultUserAgent);
808 // Disable the custom user agent preference.
809 customUserAgentPreference.setEnabled(false);
811 // Set the custom user agent preference icon.
812 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted);
815 case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
816 // Set the summary text.
817 userAgentPreference.setSummary(R.string.custom_user_agent);
819 // Enable the custom user agent preference.
820 customUserAgentPreference.setEnabled(true);
822 // Set the custom user agent preference icon.
823 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled);
827 // Get the user agent summary from the user agent data array.
828 userAgentPreference.setSummary(translatedNewUserAgentName + ":\n" + userAgentDataArray[newUserAgentArrayPosition]);
830 // Disable the custom user agent preference.
831 customUserAgentPreference.setEnabled(false);
833 // Set the custom user agent preference icon.
834 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted);
838 case "custom_user_agent":
839 // Set the new custom user agent as the summary text for the preference.
840 customUserAgentPreference.setSummary(sharedPreferences.getString("custom_user_agent", context.getString(R.string.custom_user_agent_default_value)));
843 case "incognito_mode":
845 if (sharedPreferences.getBoolean("incognito_mode", false)) {
846 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled);
848 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled);
852 case "allow_screenshots":
854 if (sharedPreferences.getBoolean(context.getString(R.string.allow_screenshots_key), false)) {
855 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled);
857 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled);
860 // Restart Privacy Browser.
861 restartPrivacyBrowser();
866 if (sharedPreferences.getBoolean("easylist", true)) {
867 easyListPreference.setIcon(R.drawable.block_ads_enabled);
869 easyListPreference.setIcon(R.drawable.block_ads_disabled);
875 if (sharedPreferences.getBoolean("easyprivacy", true)) {
876 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled);
878 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled);
882 case "fanboys_annoyance_list":
883 boolean currentFanboyAnnoyanceList = sharedPreferences.getBoolean("fanboys_annoyance_list", true);
884 boolean currentFanboySocialBlockingList = sharedPreferences.getBoolean("fanboys_social_blocking_list", true);
886 // Update the Fanboy icons.
887 if (currentFanboyAnnoyanceList) { // Fanboy's annoyance list is enabled.
888 // Update the Fanboy's annoyance list icon.
889 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled);
891 // Update the Fanboy's social blocking list icon.
892 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted);
893 } else { // Fanboy's annoyance list is disabled.
894 // Update the Fanboy's annoyance list icon.
895 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled);
897 // Update the Fanboy's social blocking list icon.
898 if (currentFanboySocialBlockingList) {
899 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled);
901 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled);
905 // Only enable Fanboy's social blocking list preference if Fanboy's annoyance list preference is disabled.
906 fanboySocialBlockingListPreference.setEnabled(!currentFanboyAnnoyanceList);
909 case "fanboys_social_blocking_list":
911 if (sharedPreferences.getBoolean("fanboys_social_blocking_list", true)) {
912 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled);
914 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled);
920 if (sharedPreferences.getBoolean("ultralist", true)) {
921 ultraListPreference.setIcon(R.drawable.block_ads_enabled);
923 ultraListPreference.setIcon(R.drawable.block_ads_disabled);
929 if (sharedPreferences.getBoolean("ultraprivacy", true)) {
930 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled);
932 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled);
936 case "block_all_third_party_requests":
938 if (sharedPreferences.getBoolean("block_all_third_party_requests", false)) {
939 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled);
941 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled);
945 case "tracking_queries":
947 if (sharedPreferences.getBoolean(context.getString(R.string.tracking_queries_key), true)) {
948 trackingQueriesPreference.setIcon(R.drawable.modify_url_enabled);
950 trackingQueriesPreference.setIcon(R.drawable.modify_url_disabled);
954 case "amp_redirects":
956 if (sharedPreferences.getBoolean(context.getString(R.string.amp_redirects_key), true)) {
957 ampRedirectsPreference.setIcon(R.drawable.modify_url_enabled);
959 ampRedirectsPreference.setIcon(R.drawable.modify_url_disabled);
964 // Store the new search string.
965 String newSearchString = sharedPreferences.getString("search", context.getString(R.string.search_default_value));
967 // Update the search and search custom URL preferences.
968 if (newSearchString.equals("Custom URL")) { // `Custom URL` is selected.
969 // Set the summary text to `R.string.custom_url`, which is translated.
970 searchPreference.setSummary(R.string.custom_url);
972 // Enable the search custom URL preference.
973 searchCustomURLPreference.setEnabled(true);
975 // Set the search custom URL preference icon.
976 searchCustomURLPreference.setIcon(R.drawable.search_custom_enabled);
977 } else { // `Custom URL` is not selected.
978 // Set the summary text to `newSearchString`.
979 searchPreference.setSummary(newSearchString);
981 // Disable `searchCustomURLPreference`.
982 searchCustomURLPreference.setEnabled(false);
984 // Set the search custom URL preference icon.
985 searchCustomURLPreference.setIcon(R.drawable.search_custom_ghosted);
989 case "search_custom_url":
990 // Set the new search custom URL as the summary text for the preference.
991 searchCustomURLPreference.setSummary(sharedPreferences.getString("search_custom_url", context.getString(R.string.search_custom_url_default_value)));
995 // Get current proxy string.
996 String currentProxyString = sharedPreferences.getString("proxy", context.getString(R.string.proxy_default_value));
998 // Update the summary text for the proxy preference.
999 switch (currentProxyString) {
1000 case ProxyHelper.NONE:
1001 proxyPreference.setSummary(context.getString(R.string.no_proxy_enabled));
1004 case ProxyHelper.TOR:
1005 proxyPreference.setSummary(context.getString(R.string.tor_enabled));
1008 case ProxyHelper.I2P:
1009 proxyPreference.setSummary(context.getString(R.string.i2p_enabled));
1012 case ProxyHelper.CUSTOM:
1013 proxyPreference.setSummary(context.getString(R.string.custom_proxy));
1017 // Update the status of the custom URL preference.
1018 proxyCustomUrlPreference.setEnabled(currentProxyString.equals(ProxyHelper.CUSTOM));
1020 // Update the icons.
1021 if (currentProxyString.equals(ProxyHelper.NONE)) { // Proxying is disabled.
1022 // Set the main proxy icon to be disabled
1023 proxyPreference.setIcon(R.drawable.proxy_disabled);
1025 // Set the custom proxy URL icon to be ghosted.
1026 proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted);
1027 } else { // Proxying is enabled.
1028 // Set the main proxy icon to be enabled.
1029 proxyPreference.setIcon(R.drawable.proxy_enabled);
1031 /// Set the custom proxy URL icon according to its status.
1032 if (proxyCustomUrlPreference.isEnabled()) {
1033 proxyCustomUrlPreference.setIcon(R.drawable.proxy_enabled);
1035 proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted);
1040 case "proxy_custom_url":
1041 // Set the summary text for the proxy custom URL.
1042 proxyCustomUrlPreference.setSummary(sharedPreferences.getString(context.getString(R.string.proxy_custom_url_key), context.getString(R.string.proxy_custom_url_default_value)));
1045 case "full_screen_browsing_mode":
1046 if (sharedPreferences.getBoolean("full_screen_browsing_mode", false)) { // Full screen browsing is enabled.
1047 // Set the full screen browsing mode preference icon.
1048 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled);
1050 // Set the hide app bar preference icon.
1051 if (sharedPreferences.getBoolean("hide_app_bar", true)) {
1052 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled);
1054 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled);
1056 } else { // Full screen browsing is disabled.
1057 // Update the icons.
1058 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled);
1059 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted);
1063 case "hide_app_bar":
1065 if (sharedPreferences.getBoolean("hide_app_bar", true)) {
1066 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled);
1067 } else { // Hide app bar is disabled.
1068 // Set the icon according to the theme.
1069 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled);
1073 case "clear_everything":
1074 // Store the new clear everything status
1075 boolean newClearEverythingBoolean = sharedPreferences.getBoolean("clear_everything", true);
1077 // Update the status of the clear and exit preferences.
1078 clearCookiesPreference.setEnabled(!newClearEverythingBoolean);
1079 clearDomStoragePreference.setEnabled(!newClearEverythingBoolean);
1080 clearFormDataPreference.setEnabled(!newClearEverythingBoolean); // This line can be removed once the minimum API >= 26.
1081 clearLogcatPreference.setEnabled(!newClearEverythingBoolean);
1082 clearCachePreference.setEnabled(!newClearEverythingBoolean);
1084 // Update the clear everything preference icon.
1085 if (newClearEverythingBoolean) {
1086 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled);
1088 clearEverythingPreference.setIcon(R.drawable.clear_everything_disabled);
1091 // Update the clear cookies preference icon.
1092 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_cookies", true)) {
1093 clearCookiesPreference.setIcon(R.drawable.clear_cookies_enabled);
1095 clearCookiesPreference.setIcon(R.drawable.clear_cookies_disabled);
1098 // Update the clear dom storage preference icon.
1099 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_dom_storage", true)) {
1100 clearDomStoragePreference.setIcon(R.drawable.clear_dom_storage_enabled);
1102 clearDomStoragePreference.setIcon(R.drawable.clear_dom_storage_disabled);
1105 // Update the clear form data preference icon if the API < 26.
1106 if (Build.VERSION.SDK_INT < 26) {
1107 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_form_data", true)) {
1108 clearFormDataPreference.setIcon(R.drawable.clear_form_data_enabled);
1110 clearFormDataPreference.setIcon(R.drawable.clear_form_data_disabled);
1114 // Update the clear logcat preference icon.
1115 if (newClearEverythingBoolean || sharedPreferences.getBoolean(context.getString(R.string.clear_logcat_key), true)) {
1116 clearLogcatPreference.setIcon(R.drawable.clear_logcat_enabled);
1118 clearLogcatPreference.setIcon(R.drawable.clear_cache_disabled);
1121 // Update the clear cache preference icon.
1122 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_cache", true)) {
1123 clearCachePreference.setIcon(R.drawable.clear_cache_enabled);
1125 clearCachePreference.setIcon(R.drawable.clear_cache_disabled);
1129 case "clear_cookies":
1131 if (sharedPreferences.getBoolean("clear_cookies", true)) {
1132 clearCookiesPreference.setIcon(R.drawable.clear_cookies_enabled);
1134 clearCookiesPreference.setIcon(R.drawable.clear_cookies_disabled);
1138 case "clear_dom_storage":
1140 if (sharedPreferences.getBoolean("clear_dom_storage", true)) {
1141 clearDomStoragePreference.setIcon(R.drawable.clear_dom_storage_enabled);
1143 clearDomStoragePreference.setIcon(R.drawable.clear_dom_storage_disabled);
1147 // This section can be removed once the minimum API >= 26.
1148 case "clear_form_data":
1150 if (sharedPreferences.getBoolean("clear_form_data", true)) {
1151 clearFormDataPreference.setIcon(R.drawable.clear_form_data_enabled);
1153 clearFormDataPreference.setIcon(R.drawable.clear_form_data_disabled);
1157 case "clear_logcat":
1159 if (sharedPreferences.getBoolean(context.getString(R.string.clear_logcat_key), true)) {
1160 clearLogcatPreference.setIcon(R.drawable.clear_logcat_enabled);
1162 clearLogcatPreference.setIcon(R.drawable.clear_logcat_disabled);
1168 if (sharedPreferences.getBoolean("clear_cache", true)) {
1169 clearCachePreference.setIcon(R.drawable.clear_cache_enabled);
1171 clearCachePreference.setIcon(R.drawable.clear_cache_disabled);
1176 // Set the new homepage URL as the summary text for the Homepage preference.
1177 homepagePreference.setSummary(sharedPreferences.getString("homepage", context.getString(R.string.homepage_default_value)));
1181 // Update the font size summary text.
1182 fontSizePreference.setSummary(sharedPreferences.getString("font_size", context.getString(R.string.font_size_default_value)) + "%");
1185 case "open_intents_in_new_tab":
1187 if (sharedPreferences.getBoolean("open_intents_in_new_tab", true)) {
1188 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled);
1190 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled);
1194 case "swipe_to_refresh":
1196 if (sharedPreferences.getBoolean("swipe_to_refresh", true)) {
1197 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled);
1199 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled);
1203 case "download_with_external_app":
1205 if (sharedPreferences.getBoolean(context.getString(R.string.download_with_external_app_key), false)) {
1206 downloadWithExternalAppPreference.setIcon(R.drawable.download_with_external_app_enabled);
1208 downloadWithExternalAppPreference.setIcon(R.drawable.download_with_external_app_disabled);
1212 case "scroll_app_bar":
1214 if (sharedPreferences.getBoolean(context.getString(R.string.scroll_app_bar_key), true)) scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled);
1215 else scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled);
1219 case "bottom_app_bar":
1221 if (sharedPreferences.getBoolean(context.getString(R.string.bottom_app_bar_key), false)) bottomAppBarPreference.setIcon(R.drawable.bottom_app_bar_enabled);
1222 else bottomAppBarPreference.setIcon(R.drawable.bottom_app_bar_disabled);
1224 // Restart Privacy Browser.
1225 restartPrivacyBrowser();
1228 case "display_additional_app_bar_icons":
1230 if (sharedPreferences.getBoolean(context.getString(R.string.display_additional_app_bar_icons_key), false)) {
1231 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled);
1233 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled);
1238 // Get the new theme.
1239 String newAppTheme = sharedPreferences.getString("app_theme", context.getString(R.string.app_theme_default_value));
1241 // Update the system according to the new theme. A switch statement cannot be used because the theme entry values string array is not a compile-time constant.
1242 if (newAppTheme.equals(appThemeEntryValuesStringArray[1])) { // The light theme is selected.
1243 // Update the theme preference summary text.
1244 appThemePreference.setSummary(appThemeEntriesStringArray[1]);
1246 // Apply the new theme.
1247 AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
1248 } else if (newAppTheme.equals(appThemeEntryValuesStringArray[2])) { // The dark theme is selected.
1249 // Update the theme preference summary text.
1250 appThemePreference.setSummary(appThemeEntriesStringArray[2]);
1252 // Apply the new theme.
1253 AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
1254 } else { // The system default theme is selected.
1255 // Update the theme preference summary text.
1256 appThemePreference.setSummary(appThemeEntriesStringArray[0]);
1258 // Apply the new theme.
1259 if (Build.VERSION.SDK_INT >= 28) { // The system default theme is supported.
1260 // Follow the system default theme.
1261 AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
1262 } else {// The system default theme is not supported.
1263 // Follow the battery saver mode.
1264 AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY);
1268 // Update the current theme status.
1269 currentThemeStatus = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
1272 case "webview_theme":
1273 // Get the new WebView theme.
1274 String newWebViewTheme = sharedPreferences.getString("webview_theme", context.getString(R.string.webview_theme_default_value));
1276 // Define a new WebView theme entry number.
1277 int newWebViewThemeEntryNumber;
1279 // Get the webView theme entry number that matches the new WebView theme. A switch statement cannot be used because the theme entry values string array is not a compile time constant.
1280 if (newWebViewTheme.equals(webViewThemeEntriesStringArray[1])) { // The light theme is selected.
1281 // Store the new WebView theme entry number.
1282 newWebViewThemeEntryNumber = 1;
1283 } else if (newWebViewTheme.equals(webViewThemeEntryValuesStringArray[2])) { // The dark theme is selected.
1284 // Store the WebView theme entry number.
1285 newWebViewThemeEntryNumber = 2;
1286 } else { // The system default theme is selected.
1287 // Store the WebView theme entry number.
1288 newWebViewThemeEntryNumber = 0;
1292 switch (newWebViewThemeEntryNumber) {
1293 case 0: // The system default WebView theme is selected.
1295 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1296 webViewThemePreference.setIcon(R.drawable.webview_light_theme);
1298 webViewThemePreference.setIcon(R.drawable.webview_dark_theme);
1302 case 1: // The light theme is selected.
1304 webViewThemePreference.setIcon(R.drawable.webview_light_theme);
1307 case 2: // The dark theme is selected.
1309 webViewThemePreference.setIcon(R.drawable.webview_dark_theme);
1313 // Set the current theme as the summary text for the preference.
1314 webViewThemePreference.setSummary(webViewThemeEntriesStringArray[newWebViewThemeEntryNumber]);
1317 case "wide_viewport":
1319 if (sharedPreferences.getBoolean("wide_viewport", true)) {
1320 wideViewportPreference.setIcon(R.drawable.wide_viewport_enabled);
1322 wideViewportPreference.setIcon(R.drawable.wide_viewport_disabled);
1326 case "display_webpage_images":
1328 if (sharedPreferences.getBoolean("display_webpage_images", true)) {
1329 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled);
1331 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled);
1338 private void restartPrivacyBrowser() {
1339 // Create an intent to restart Privacy Browser.
1340 Intent restartIntent = requireActivity().getParentActivityIntent();
1342 // Assert that the intent is not null to remove the lint error below.
1343 assert restartIntent != null;
1345 // `Intent.FLAG_ACTIVITY_CLEAR_TASK` removes all activities from the stack. It requires `Intent.FLAG_ACTIVITY_NEW_TASK`.
1346 restartIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
1348 // Create a handler to restart the activity.
1349 Handler restartHandler = new Handler(Looper.getMainLooper());
1351 // Create a runnable to restart the activity.
1352 Runnable restartRunnable = () -> {
1353 // Restart the activity.
1354 startActivity(restartIntent);
1356 // Kill this instance of Privacy Browser. Otherwise, the app exhibits sporadic behavior after the restart.
1360 // Restart the activity after 400 milliseconds, so that the app has enough time to save the change to the preference.
1361 restartHandler.postDelayed(restartRunnable, 400);