2 * Copyright © 2016-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.Intent;
25 import android.content.SharedPreferences;
26 import android.os.Build;
27 import android.os.Bundle;
28 import android.os.Handler;
29 import android.preference.Preference;
30 import android.preference.PreferenceCategory;
31 import android.preference.PreferenceFragment;
32 import android.view.LayoutInflater;
33 import android.view.View;
34 import android.webkit.WebView;
35 import android.widget.ArrayAdapter;
37 import com.stoutner.privacybrowser.R;
38 import com.stoutner.privacybrowser.activities.MainWebViewActivity;
40 public class SettingsFragment extends PreferenceFragment {
41 private SharedPreferences.OnSharedPreferenceChangeListener preferencesListener;
42 private SharedPreferences savedPreferences;
45 public void onCreate(Bundle savedInstanceState) {
46 // Run the default commands.
47 super.onCreate(savedInstanceState);
49 // Load the preferences from the XML file.
50 addPreferencesFromResource(R.xml.preferences);
52 // Get a handle for the context.
53 Context context = getActivity().getApplicationContext();
55 // Initialize savedPreferences.
56 savedPreferences = getPreferenceScreen().getSharedPreferences();
58 // Get handles for the preferences.
59 Preference javaScriptPreference = findPreference("javascript");
60 Preference firstPartyCookiesPreference = findPreference("first_party_cookies");
61 Preference thirdPartyCookiesPreference = findPreference("third_party_cookies");
62 Preference domStoragePreference = findPreference("dom_storage");
63 Preference saveFormDataPreference = findPreference("save_form_data"); // The form data preference can be removed once the minimum API >= 26.
64 Preference userAgentPreference = findPreference("user_agent");
65 Preference customUserAgentPreference = findPreference("custom_user_agent");
66 Preference incognitoModePreference = findPreference("incognito_mode");
67 Preference doNotTrackPreference = findPreference("do_not_track");
68 Preference allowScreenshotsPreference = findPreference("allow_screenshots");
69 Preference easyListPreference = findPreference("easylist");
70 Preference easyPrivacyPreference = findPreference("easyprivacy");
71 Preference fanboyAnnoyanceListPreference = findPreference("fanboys_annoyance_list");
72 Preference fanboySocialBlockingListPreference = findPreference("fanboys_social_blocking_list");
73 Preference ultraPrivacyPreference = findPreference("ultraprivacy");
74 Preference blockAllThirdPartyRequestsPreference = findPreference("block_all_third_party_requests");
75 Preference proxyThroughOrbotPreference = findPreference("proxy_through_orbot");
76 Preference torHomepagePreference = findPreference("tor_homepage");
77 Preference torSearchPreference = findPreference("tor_search");
78 Preference torSearchCustomURLPreference = findPreference("tor_search_custom_url");
79 Preference searchPreference = findPreference("search");
80 Preference searchCustomURLPreference = findPreference("search_custom_url");
81 Preference fullScreenBrowsingModePreference = findPreference("full_screen_browsing_mode");
82 Preference hideAppBarPreference = findPreference("hide_app_bar");
83 Preference clearEverythingPreference = findPreference("clear_everything");
84 Preference clearCookiesPreference = findPreference("clear_cookies");
85 Preference clearDomStoragePreference = findPreference("clear_dom_storage");
86 Preference clearFormDataPreference = findPreference("clear_form_data"); // The clear form data preference can be removed once the minimum API >= 26.
87 Preference clearCachePreference = findPreference("clear_cache");
88 Preference homepagePreference = findPreference("homepage");
89 Preference fontSizePreference = findPreference("font_size");
90 Preference openIntentsInNewTabPreference = findPreference("open_intents_in_new_tab");
91 Preference swipeToRefreshPreference = findPreference("swipe_to_refresh");
92 Preference scrollAppBarPreference = findPreference("scroll_app_bar");
93 Preference displayAdditionalAppBarIconsPreference = findPreference("display_additional_app_bar_icons");
94 Preference downloadWithExternalAppPreference = findPreference("download_with_external_app");
95 Preference darkThemePreference = findPreference("dark_theme");
96 Preference nightModePreference = findPreference("night_mode");
97 Preference displayWebpageImagesPreference = findPreference("display_webpage_images");
100 torHomepagePreference.setDependency("proxy_through_orbot");
101 torSearchPreference.setDependency("proxy_through_orbot");
102 hideAppBarPreference.setDependency("full_screen_browsing_mode");
104 // Get strings from the preferences.
105 String torSearchString = savedPreferences.getString("tor_search", getString(R.string.tor_search_default_value));
106 String searchString = savedPreferences.getString("search", getString(R.string.search_default_value));
108 // Get booleans that are used in multiple places from the preferences.
109 boolean javaScriptEnabled = savedPreferences.getBoolean("javascript", false);
110 boolean firstPartyCookiesEnabled = savedPreferences.getBoolean("first_party_cookies", false);
111 boolean thirdPartyCookiesEnabled = savedPreferences.getBoolean("third_party_cookies", false);
112 boolean fanboyAnnoyanceListEnabled = savedPreferences.getBoolean("fanboys_annoyance_list", true);
113 boolean fanboySocialBlockingEnabled = savedPreferences.getBoolean("fanboys_social_blocking_list", true);
114 boolean proxyThroughOrbot = savedPreferences.getBoolean("proxy_through_orbot", false);
115 boolean fullScreenBrowsingMode = savedPreferences.getBoolean("full_screen_browsing_mode", false);
116 boolean clearEverything = savedPreferences.getBoolean("clear_everything", true);
117 boolean darkTheme = savedPreferences.getBoolean("dark_theme", false);
118 boolean nightMode = savedPreferences.getBoolean("night_mode", false);
120 // Only enable the third-party cookies preference if first-party cookies are enabled and API >= 21.
121 thirdPartyCookiesPreference.setEnabled(firstPartyCookiesEnabled && (Build.VERSION.SDK_INT >= 21));
123 // Only enable the DOM storage preference if either JavaScript or Night Mode is enabled.
124 domStoragePreference.setEnabled(javaScriptEnabled || nightMode);
126 // Remove the form data preferences if the API is >= 26 as they no longer do anything.
127 if (Build.VERSION.SDK_INT >= 26) {
128 // Get the categories.
129 PreferenceCategory privacyCategory = (PreferenceCategory) findPreference("privacy");
130 PreferenceCategory clearAndExitCategory = (PreferenceCategory) findPreference("clear_and_exit");
132 // Remove the form data preferences.
133 privacyCategory.removePreference(saveFormDataPreference);
134 clearAndExitCategory.removePreference(clearFormDataPreference);
137 // Only enable Fanboy's social blocking list preference if Fanboy's annoyance list is disabled.
138 fanboySocialBlockingListPreference.setEnabled(!fanboyAnnoyanceListEnabled);
140 // Inflate a WebView to get the default user agent.
141 LayoutInflater inflater = getActivity().getLayoutInflater();
142 // `@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.
143 @SuppressLint("InflateParams") View bareWebViewLayout = inflater.inflate(R.layout.bare_webview, null, false);
144 WebView bareWebView = bareWebViewLayout.findViewById(R.id.bare_webview);
146 // Get the user agent arrays.
147 ArrayAdapter<CharSequence> userAgentNamesArray = ArrayAdapter.createFromResource(context, R.array.user_agent_names, R.layout.spinner_item);
148 String[] translatedUserAgentNamesArray = getResources().getStringArray(R.array.translated_user_agent_names);
149 String[] userAgentDataArray = getResources().getStringArray(R.array.user_agent_data);
151 // Get the current user agent name from the preference.
152 String userAgentName = savedPreferences.getString("user_agent", getString(R.string.user_agent_default_value));
154 // Get the array position of the user agent name.
155 int userAgentArrayPosition = userAgentNamesArray.getPosition(userAgentName);
157 // Populate the user agent summary.
158 switch (userAgentArrayPosition) {
159 case MainWebViewActivity.UNRECOGNIZED_USER_AGENT: // The user agent name is not on the canonical list.
160 // 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.
161 userAgentPreference.setSummary(userAgentName);
164 case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
165 // Get the user agent text from the webview (which changes based on the version of Android and WebView installed).
166 userAgentPreference.setSummary(translatedUserAgentNamesArray[userAgentArrayPosition] + ":\n" + bareWebView.getSettings().getUserAgentString());
169 case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
170 // Set the summary text.
171 userAgentPreference.setSummary(R.string.custom_user_agent);
175 // Get the user agent summary from the user agent data array.
176 userAgentPreference.setSummary(translatedUserAgentNamesArray[userAgentArrayPosition] + ":\n" + userAgentDataArray[userAgentArrayPosition]);
179 // Set the summary text for the custom user agent preference and enable it if user agent preference is set to custom.
180 customUserAgentPreference.setSummary(savedPreferences.getString("custom_user_agent", getString(R.string.custom_user_agent_default_value)));
181 customUserAgentPreference.setEnabled(userAgentPreference.getSummary().equals(getString(R.string.custom_user_agent)));
184 // Set the Tor homepage URL as the summary text for the `tor_homepage` preference when the preference screen is loaded. The default is Searx: `http://ulrn6sryqaifefld.onion/`.
185 torHomepagePreference.setSummary(savedPreferences.getString("tor_homepage", getString(R.string.tor_homepage_default_value)));
188 // Set the Tor search URL as the summary text for the Tor preference when the preference screen is loaded.
189 if (torSearchString.equals("Custom URL")) {
190 // Use R.string.custom_url, which will be translated, instead of the array value, which will not.
191 torSearchPreference.setSummary(R.string.custom_url);
193 // Set the array value as the summary text.
194 torSearchPreference.setSummary(torSearchString);
197 // Set the summary text for `tor_search_custom_url`. The default is `""`.
198 torSearchCustomURLPreference.setSummary(savedPreferences.getString("tor_search_custom_url", getString(R.string.tor_search_custom_url_default_value)));
200 // Enable the Tor custom URL search options only if proxying through Orbot and the search is set to `Custom URL`.
201 torSearchCustomURLPreference.setEnabled(proxyThroughOrbot && torSearchString.equals("Custom URL"));
204 // Set the search URL as the summary text for the search preference when the preference screen is loaded.
205 if (searchString.equals("Custom URL")) {
206 // Use R.string.custom_url, which will be translated, instead of the array value, which will not.
207 searchPreference.setSummary(R.string.custom_url);
209 // Set the array value as the summary text.
210 searchPreference.setSummary(searchString);
213 // Set the summary text for `search_custom_url` (the default is `""`) and enable it if `search` is set to `Custom URL`.
214 searchCustomURLPreference.setSummary(savedPreferences.getString("search_custom_url", getString(R.string.search_custom_url_default_value)));
215 searchCustomURLPreference.setEnabled(searchString.equals("Custom URL"));
217 // Set the status of the Clear and Exit preferences.
218 clearCookiesPreference.setEnabled(!clearEverything);
219 clearDomStoragePreference.setEnabled(!clearEverything);
220 clearFormDataPreference.setEnabled(!clearEverything); // The form data line can be removed once the minimum API is >= 26.
221 clearCachePreference.setEnabled(!clearEverything);
223 // Set the homepage URL as the summary text for the homepage preference.
224 homepagePreference.setSummary(savedPreferences.getString("homepage", getString(R.string.homepage_default_value)));
226 // Set the font size as the summary text for the preference.
227 fontSizePreference.setSummary(savedPreferences.getString("font_size", getString(R.string.font_size_default_value)) + "%%");
229 // Disable the JavaScript preference if Night Mode is enabled. JavaScript will be enabled for all web pages.
230 javaScriptPreference.setEnabled(!nightMode);
232 // Set the JavaScript icon.
233 if (javaScriptEnabled || nightMode) {
234 javaScriptPreference.setIcon(R.drawable.javascript_enabled);
236 javaScriptPreference.setIcon(R.drawable.privacy_mode);
239 // Set the first-party cookies icon.
240 if (firstPartyCookiesEnabled) {
241 firstPartyCookiesPreference.setIcon(R.drawable.cookies_enabled);
244 firstPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
246 firstPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
250 // Set the third party cookies icon.
251 if (firstPartyCookiesEnabled && Build.VERSION.SDK_INT >= 21) {
252 if (thirdPartyCookiesEnabled) {
253 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_warning);
256 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
258 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
263 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_dark);
265 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_light);
269 // Set the DOM storage icon.
270 if (javaScriptEnabled || nightMode) { // The preference is enabled.
271 if (savedPreferences.getBoolean("dom_storage", false)) { // DOM storage is enabled.
272 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
273 } else { // DOM storage is disabled.
275 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_dark);
277 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_light);
280 } else { // The preference is disabled. The icon should be ghosted.
282 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_dark);
284 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_light);
288 // Set the save form data icon if API < 26. Save form data has no effect on API >= 26.
289 if (Build.VERSION.SDK_INT < 26) {
290 if (savedPreferences.getBoolean("save_form_data", false)) {
291 saveFormDataPreference.setIcon(R.drawable.form_data_enabled);
294 saveFormDataPreference.setIcon(R.drawable.form_data_disabled_dark);
296 saveFormDataPreference.setIcon(R.drawable.form_data_disabled_light);
301 // Set the custom user agent icon.
302 if (customUserAgentPreference.isEnabled()) {
304 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_dark);
306 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_light);
310 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_dark);
312 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_light);
316 // Set the incognito mode icon.
317 if (savedPreferences.getBoolean("incognito_mode", false)) {
319 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_dark);
321 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_light);
325 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_dark);
327 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_light);
331 // Set the Do Not Track icon.
332 if (savedPreferences.getBoolean("do_not_track", false)) {
334 doNotTrackPreference.setIcon(R.drawable.block_tracking_enabled_dark);
336 doNotTrackPreference.setIcon(R.drawable.block_tracking_enabled_light);
340 doNotTrackPreference.setIcon(R.drawable.block_tracking_disabled_dark);
342 doNotTrackPreference.setIcon(R.drawable.block_tracking_disabled_light);
346 // Set the allow screenshots icon.
347 if (savedPreferences.getBoolean("allow_screenshots", false)) {
349 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_dark);
351 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_light);
355 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_dark);
357 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_light);
361 // Set the EasyList icon.
362 if (savedPreferences.getBoolean("easylist", true)) {
364 easyListPreference.setIcon(R.drawable.block_ads_enabled_dark);
366 easyListPreference.setIcon(R.drawable.block_ads_enabled_light);
370 easyListPreference.setIcon(R.drawable.block_ads_disabled_dark);
372 easyListPreference.setIcon(R.drawable.block_ads_disabled_light);
376 // Set the EasyPrivacy icon.
377 if (savedPreferences.getBoolean("easyprivacy", true)) {
379 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_dark);
381 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_light);
385 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_dark);
387 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_light);
391 // Set the Fanboy lists icons.
392 if (fanboyAnnoyanceListEnabled) {
394 // Set the Fanboy annoyance list icon.
395 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_dark);
397 // Set the Fanboy social blocking list icon.
398 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_dark);
400 // Set the Fanboy annoyance list icon.
401 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_light);
403 // Set the Fanboy social blocking list icon.
404 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_light);
408 // Set the Fanboy annoyance list icon.
409 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled_dark);
411 // Set the Fanboy social blocking list icon.
412 if (fanboySocialBlockingEnabled) {
413 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_dark);
415 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_dark);
418 // Set the Fanboy annoyance list icon.
419 fanboyAnnoyanceListPreference.setIcon(R.drawable.block_ads_disabled_light);
421 // Set the Fanboy social blocking list icon.
422 if (fanboySocialBlockingEnabled) {
423 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_light);
425 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_light);
430 // Set the UltraPrivacy icon.
431 if (savedPreferences.getBoolean("ultraprivacy", true)) {
433 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_dark);
435 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_light);
439 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_dark);
441 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_light);
445 // Set the block all third-party requests icon.
446 if (savedPreferences.getBoolean("block_all_third_party_requests", false)) {
448 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_dark);
450 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_light);
454 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_dark);
456 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_light);
460 // Set the Tor icons according to the theme.
461 if (proxyThroughOrbot) { // Proxying is enabled.
463 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_enabled_dark);
464 torHomepagePreference.setIcon(R.drawable.home_enabled_dark);
465 torSearchPreference.setIcon(R.drawable.search_enabled_dark);
467 // Set the custom search icon.
468 if (torSearchCustomURLPreference.isEnabled()) {
469 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_dark);
471 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
474 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_enabled_light);
475 torHomepagePreference.setIcon(R.drawable.home_enabled_light);
476 torSearchPreference.setIcon(R.drawable.search_enabled_light);
478 // Set the custom search icon.
479 if (torSearchCustomURLPreference.isEnabled()) {
480 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_light);
482 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
485 } else { // Proxying is disabled.
487 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_disabled_dark);
488 torHomepagePreference.setIcon(R.drawable.home_ghosted_dark);
489 torSearchPreference.setIcon(R.drawable.search_ghosted_dark);
490 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
492 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_disabled_light);
493 torHomepagePreference.setIcon(R.drawable.home_ghosted_light);
494 torSearchPreference.setIcon(R.drawable.search_ghosted_light);
495 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
499 // Set the search custom URL icon.
500 if (searchCustomURLPreference.isEnabled()) {
502 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_dark);
504 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_light);
508 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
510 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
514 // Set the full screen browsing mode icons.
515 if (fullScreenBrowsingMode) { // Full screen browsing mode is enabled.
516 // Set the `fullScreenBrowsingModePreference` icon according to the theme.
518 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_dark);
520 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_light);
523 // Set the hide app bar icon.
524 if (savedPreferences.getBoolean("hide_app_bar", true)) { // Hide app bar is enabled.
525 // Set the icon according to the theme.
527 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
529 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
531 } else { // Hide app bar is disabled.
532 // Set the icon according to the theme.
534 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
536 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
539 } else { // Full screen browsing mode is disabled.
540 // Set the icons according to the theme.
542 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_dark);
543 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_dark);
545 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_light);
546 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_light);
550 // Set the clear everything preference icon.
551 if (clearEverything) {
553 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_dark);
555 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_light);
558 clearEverythingPreference.setIcon(R.drawable.clear_everything_disabled);
561 // Set the clear cookies preference icon.
562 if (clearEverything || savedPreferences.getBoolean("clear_cookies", true)) {
564 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_dark);
566 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_light);
569 clearCookiesPreference.setIcon(R.drawable.cookies_warning);
572 // Set the clear DOM storage preference icon.
573 if (clearEverything || savedPreferences.getBoolean("clear_dom_storage", true)) {
575 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_dark);
577 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_light);
580 clearDomStoragePreference.setIcon(R.drawable.dom_storage_warning);
583 // Set the clear form data preference icon if the API < 26. It has no effect on newer versions of Android.
584 if (Build.VERSION.SDK_INT < 26) {
585 if (clearEverything || savedPreferences.getBoolean("clear_form_data", true)) {
587 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_dark);
589 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_light);
592 clearFormDataPreference.setIcon(R.drawable.form_data_warning);
596 // Set the clear cache preference icon.
597 if (clearEverything || savedPreferences.getBoolean("clear_cache", true)) {
599 clearCachePreference.setIcon(R.drawable.cache_cleared_dark);
601 clearCachePreference.setIcon(R.drawable.cache_cleared_light);
604 clearCachePreference.setIcon(R.drawable.cache_warning);
607 // Set the open intents in new tab preference icon.
608 if (savedPreferences.getBoolean("open_intents_in_new_tab", true)) {
610 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_dark);
612 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_light);
616 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_dark);
618 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_light);
622 // Set the swipe to refresh preference icon.
623 if (savedPreferences.getBoolean("swipe_to_refresh", true)) {
625 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_dark);
627 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_light);
631 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_dark);
633 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_light);
637 // Set the scroll app bar preference icon.
638 if (savedPreferences.getBoolean("scroll_app_bar", true)) {
640 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
642 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
646 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
648 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
652 // Set the display additional app bar icons preference icon.
653 if (savedPreferences.getBoolean("display_additional_app_bar_icons", false)) {
655 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_dark);
657 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_light);
661 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_dark);
663 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_light);
667 // Set the download with external app preference icon.
668 if (savedPreferences.getBoolean("download_with_external_app", false)) {
670 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_enabled_dark);
672 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_enabled_light);
676 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_disabled_dark);
678 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_disabled_light);
682 // Set the dark theme preference icon.
683 if (savedPreferences.getBoolean("dark_theme", false)) {
684 darkThemePreference.setIcon(R.drawable.theme_dark);
686 darkThemePreference.setIcon(R.drawable.theme_light);
689 // Set the night mode preference icon.
692 nightModePreference.setIcon(R.drawable.night_mode_enabled_dark);
694 nightModePreference.setIcon(R.drawable.night_mode_enabled_light);
698 nightModePreference.setIcon(R.drawable.night_mode_disabled_dark);
700 nightModePreference.setIcon(R.drawable.night_mode_disabled_light);
704 // Set the display webpage images preference icon.
705 if (savedPreferences.getBoolean("display_webpage_images", true)) {
707 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_dark);
709 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_light);
713 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_dark);
715 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_light);
720 // Listen for preference changes.
721 preferencesListener = (SharedPreferences sharedPreferences, String key) -> {
724 // Update the icons and the DOM storage preference status.
725 if (sharedPreferences.getBoolean("javascript", false)) { // The JavaScript preference is enabled.
726 // Update the icon for the JavaScript preference.
727 javaScriptPreference.setIcon(R.drawable.javascript_enabled);
729 // Update the status of the DOM storage preference.
730 domStoragePreference.setEnabled(true);
732 // Update the icon for the DOM storage preference.
733 if (sharedPreferences.getBoolean("dom_storage", false)) {
734 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
737 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_dark);
739 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_light);
742 } else { // The JavaScript preference is disabled.
743 // Update the icon for the JavaScript preference.
744 javaScriptPreference.setIcon(R.drawable.privacy_mode);
746 // Update the status of the DOM storage preference.
747 domStoragePreference.setEnabled(false);
749 // Set the icon for DOM storage preference to be ghosted.
751 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_dark);
753 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_light);
758 case "first_party_cookies":
759 // Update the icons for `first_party_cookies` and `third_party_cookies`.
760 if (sharedPreferences.getBoolean("first_party_cookies", false)) {
761 // Set the icon for `first_party_cookies`.
762 firstPartyCookiesPreference.setIcon(R.drawable.cookies_enabled);
764 // Update the icon for `third_party_cookies`.
765 if (Build.VERSION.SDK_INT >= 21) {
766 if (sharedPreferences.getBoolean("third_party_cookies", false)) {
767 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_warning);
770 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
772 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
777 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_dark);
779 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_light);
782 } else { // `first_party_cookies` is `false`.
783 // Update the icon for `first_party_cookies`.
785 firstPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
787 firstPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
790 // Set the icon for `third_party_cookies` to be ghosted.
792 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_dark);
794 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_light);
798 // Enable `third_party_cookies` if `first_party_cookies` is `true` and API >= 21.
799 thirdPartyCookiesPreference.setEnabled(sharedPreferences.getBoolean("first_party_cookies", false) && (Build.VERSION.SDK_INT >= 21));
802 case "third_party_cookies":
804 if (sharedPreferences.getBoolean("third_party_cookies", false)) {
805 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_warning);
808 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
810 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
817 if (sharedPreferences.getBoolean("dom_storage", false)) {
818 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
821 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_dark);
823 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_light);
828 // Save form data can be removed once the minimum API >= 26.
829 case "save_form_data":
831 if (sharedPreferences.getBoolean("save_form_data", false)) {
832 saveFormDataPreference.setIcon(R.drawable.form_data_enabled);
835 saveFormDataPreference.setIcon(R.drawable.form_data_disabled_dark);
837 saveFormDataPreference.setIcon(R.drawable.form_data_disabled_light);
843 // Get the new user agent name.
844 String newUserAgentName = sharedPreferences.getString("user_agent", getString(R.string.user_agent_default_value));
846 // Get the array position for the new user agent name.
847 int newUserAgentArrayPosition = userAgentNamesArray.getPosition(newUserAgentName);
849 // Get the translated new user agent name.
850 String translatedNewUserAgentName = translatedUserAgentNamesArray[newUserAgentArrayPosition];
852 // Populate the user agent summary.
853 switch (newUserAgentArrayPosition) {
854 case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
855 // Get the user agent text from the webview (which changes based on the version of Android and WebView installed).
856 userAgentPreference.setSummary(translatedNewUserAgentName + ":\n" + bareWebView.getSettings().getUserAgentString());
858 // Disable the custom user agent preference.
859 customUserAgentPreference.setEnabled(false);
861 // Set the custom user agent preference icon according to the theme.
863 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_dark);
865 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_light);
869 case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
870 // Set the summary text.
871 userAgentPreference.setSummary(R.string.custom_user_agent);
873 // Enable the custom user agent preference.
874 customUserAgentPreference.setEnabled(true);
876 // Set the custom user agent preference icon according to the theme.
878 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_dark);
880 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_light);
885 // Get the user agent summary from the user agent data array.
886 userAgentPreference.setSummary(translatedNewUserAgentName + ":\n" + userAgentDataArray[newUserAgentArrayPosition]);
888 // Disable the custom user agent preference.
889 customUserAgentPreference.setEnabled(false);
891 // Set the custom user agent preference icon according to the theme.
893 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_dark);
895 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_light);
900 case "custom_user_agent":
901 // Set the new custom user agent as the summary text for the preference.
902 customUserAgentPreference.setSummary(sharedPreferences.getString("custom_user_agent", getString(R.string.custom_user_agent_default_value)));
905 case "incognito_mode":
907 if (sharedPreferences.getBoolean("incognito_mode", false)) {
909 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_dark);
911 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_light);
915 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_dark);
917 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_light);
924 if (sharedPreferences.getBoolean("do_not_track", false)) {
926 doNotTrackPreference.setIcon(R.drawable.block_tracking_enabled_dark);
928 doNotTrackPreference.setIcon(R.drawable.block_tracking_enabled_light);
932 doNotTrackPreference.setIcon(R.drawable.block_tracking_disabled_dark);
934 doNotTrackPreference.setIcon(R.drawable.block_tracking_disabled_light);
940 case "allow_screenshots":
942 if (sharedPreferences.getBoolean("allow_screenshots", false)) {
944 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_dark);
946 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_light);
950 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_dark);
952 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_light);
956 // Create an intent to restart Privacy Browser.
957 Intent allowScreenshotsRestartIntent = getActivity().getParentActivityIntent();
959 // Assert that the intent is not null to remove the lint error below.
960 assert allowScreenshotsRestartIntent != null;
962 // `Intent.FLAG_ACTIVITY_CLEAR_TASK` removes all activities from the stack. It requires `Intent.FLAG_ACTIVITY_NEW_TASK`.
963 allowScreenshotsRestartIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
965 // Create a handler to restart the activity.
966 Handler allowScreenshotsRestartHandler = new Handler();
968 // Create a runnable to restart the activity.
969 Runnable allowScreenshotsRestartRunnable = () -> {
970 // Restart the activity.
971 startActivity(allowScreenshotsRestartIntent);
973 // Kill this instance of Privacy Browser. Otherwise, the app exhibits sporadic behavior after the restart.
977 // Restart the activity after 100 milliseconds, so that the app has enough time to save the change to the preference.
978 allowScreenshotsRestartHandler.postDelayed(allowScreenshotsRestartRunnable, 100);
983 if (sharedPreferences.getBoolean("easylist", true)) {
985 easyListPreference.setIcon(R.drawable.block_ads_enabled_dark);
987 easyListPreference.setIcon(R.drawable.block_ads_enabled_light);
991 easyListPreference.setIcon(R.drawable.block_ads_disabled_dark);
993 easyListPreference.setIcon(R.drawable.block_ads_disabled_light);
1000 if (sharedPreferences.getBoolean("easyprivacy", true)) {
1002 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_dark);
1004 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_light);
1008 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_dark);
1010 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_light);
1015 case "fanboys_annoyance_list":
1016 boolean currentFanboyAnnoyanceList = sharedPreferences.getBoolean("fanboys_annoyance_list", true);
1017 boolean currentFanboySocialBlockingList = sharedPreferences.getBoolean("fanboys_social_blocking_list", true);
1019 // Update the Fanboy icons.
1020 if (currentFanboyAnnoyanceList) { // Fanboy's annoyance list is enabled.
1022 // Update the Fanboy's annoyance list icon.
1023 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_dark);
1025 // Update the Fanboy's social blocking list icon.
1026 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_dark);
1028 // Update the Fanboy's annoyance list icon.
1029 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_light);
1031 // Update the Fanboy's social blocking list icon.
1032 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_light);
1034 } else { // Fanboy's annoyance list is disabled.
1036 // Update the Fanboy's annoyance list icon.
1037 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled_dark);
1039 // Update the Fanboy's social blocking list icon.
1040 if (currentFanboySocialBlockingList) {
1041 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_dark);
1043 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_dark);
1046 // Update the Fanboy's annoyance list icon.
1047 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled_light);
1049 // Update the Fanboy's social blocking list icon.
1050 if (currentFanboySocialBlockingList) {
1051 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_light);
1053 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_light);
1058 // Only enable Fanboy's social blocking list preference if Fanboy's annoyance list preference is disabled.
1059 fanboySocialBlockingListPreference.setEnabled(!currentFanboyAnnoyanceList);
1062 case "fanboys_social_blocking_list":
1064 if (sharedPreferences.getBoolean("fanboys_social_blocking_list", true)) {
1066 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_dark);
1068 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_light);
1072 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_dark);
1074 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_light);
1079 case "ultraprivacy":
1081 if (sharedPreferences.getBoolean("ultraprivacy", true)) {
1083 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_dark);
1085 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_light);
1089 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_dark);
1091 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_light);
1096 case "block_all_third_party_requests":
1098 if (sharedPreferences.getBoolean("block_all_third_party_requests", false)) {
1100 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_dark);
1102 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_light);
1106 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_dark);
1108 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_light);
1113 case "proxy_through_orbot":
1114 // Get current settings.
1115 boolean currentProxyThroughOrbot = sharedPreferences.getBoolean("proxy_through_orbot", false);
1116 String currentTorSearchString = sharedPreferences.getString("tor_search", getString(R.string.tor_search_default_value));
1118 // Enable the Tor custom URL search option only if `currentProxyThroughOrbot` is true and the search is set to `Custom URL`.
1119 torSearchCustomURLPreference.setEnabled(currentProxyThroughOrbot && currentTorSearchString.equals("Custom URL"));
1121 // Update the icons.
1122 if (currentProxyThroughOrbot) {
1123 // Set the Tor icons according to the theme.
1125 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_enabled_dark);
1126 torHomepagePreference.setIcon(R.drawable.home_enabled_dark);
1127 torSearchPreference.setIcon(R.drawable.search_enabled_dark);
1129 // Set the `torSearchCustomURLPreference` icon.
1130 if (torSearchCustomURLPreference.isEnabled()) {
1131 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_dark);
1133 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
1136 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_enabled_light);
1137 torHomepagePreference.setIcon(R.drawable.home_enabled_light);
1138 torSearchPreference.setIcon(R.drawable.search_enabled_light);
1140 // Set the `torSearchCustomURLPreference` icon.
1141 if (torSearchCustomURLPreference.isEnabled()) {
1142 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_light);
1144 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
1147 } else { // Proxy through Orbot is disabled.
1149 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_disabled_dark);
1150 torHomepagePreference.setIcon(R.drawable.home_ghosted_dark);
1151 torSearchPreference.setIcon(R.drawable.search_ghosted_dark);
1152 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
1154 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_disabled_light);
1155 torHomepagePreference.setIcon(R.drawable.home_ghosted_light);
1156 torSearchPreference.setIcon(R.drawable.search_ghosted_light);
1157 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
1162 case "tor_homepage":
1163 // Set the new tor homepage URL as the summary text for the `tor_homepage` preference. The default is Searx: `http://ulrn6sryqaifefld.onion/`.
1164 torHomepagePreference.setSummary(sharedPreferences.getString("tor_homepage", getString(R.string.tor_homepage_default_value)));
1168 // Get the present search string.
1169 String presentTorSearchString = sharedPreferences.getString("tor_search", getString(R.string.tor_search_default_value));
1171 // Update the preferences.
1172 if (presentTorSearchString.equals("Custom URL")) {
1173 // Use `R.string.custom_url`, which is translated, as the summary instead of the array value, which isn't.
1174 torSearchPreference.setSummary(R.string.custom_url);
1176 // Enable `torSearchCustomURLPreference`.
1177 torSearchCustomURLPreference.setEnabled(true);
1179 // Update the `torSearchCustomURLPreference` icon.
1181 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_dark);
1183 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_light);
1186 // Set the array value as the summary text.
1187 torSearchPreference.setSummary(presentTorSearchString);
1189 // Disable `torSearchCustomURLPreference`.
1190 torSearchCustomURLPreference.setEnabled(false);
1192 // Update the `torSearchCustomURLPreference` icon.
1194 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
1196 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
1201 case "tor_search_custom_url":
1202 // Set the summary text for `tor_search_custom_url`.
1203 torSearchCustomURLPreference.setSummary(sharedPreferences.getString("tor_search_custom_url", getString(R.string.tor_search_custom_url_default_value)));
1207 // Store the new search string.
1208 String newSearchString = sharedPreferences.getString("search", getString(R.string.search_default_value));
1210 // Update `searchPreference` and `searchCustomURLPreference`.
1211 if (newSearchString.equals("Custom URL")) { // `Custom URL` is selected.
1212 // Set the summary text to `R.string.custom_url`, which is translated.
1213 searchPreference.setSummary(R.string.custom_url);
1215 // Enable `searchCustomURLPreference`.
1216 searchCustomURLPreference.setEnabled(true);
1218 // Set the `searchCustomURLPreference` according to the theme.
1220 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_dark);
1222 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_light);
1224 } else { // `Custom URL` is not selected.
1225 // Set the summary text to `newSearchString`.
1226 searchPreference.setSummary(newSearchString);
1228 // Disable `searchCustomURLPreference`.
1229 searchCustomURLPreference.setEnabled(false);
1231 // Set the `searchCustomURLPreference` according to the theme.
1233 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
1235 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
1240 case "search_custom_url":
1241 // Set the new custom search URL as the summary text for `search_custom_url`. The default is `""`.
1242 searchCustomURLPreference.setSummary(sharedPreferences.getString("search_custom_url", getString(R.string.search_custom_url_default_value)));
1245 case "full_screen_browsing_mode":
1246 if (sharedPreferences.getBoolean("full_screen_browsing_mode", false)) { // Full screen browsing is enabled.
1247 // Set the full screen browsing mode preference icon according to the theme.
1249 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_dark);
1251 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_light);
1254 // Set the hide app bar preference icon.
1255 if (sharedPreferences.getBoolean("hide_app_bar", true)) { // Hide app bar is enabled.
1256 // Set the icon according to the theme.
1258 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
1260 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
1262 } else { // Hide app bar is disabled.
1263 // Set the icon according to the theme.
1265 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
1267 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
1270 } else { // Full screen browsing is disabled.
1271 // Update the icons according to the theme.
1273 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_dark);
1274 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_dark);
1276 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_light);
1277 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_light);
1282 case "hide_app_bar":
1284 if (sharedPreferences.getBoolean("hide_app_bar", true)) { // Hide app bar is enabled.
1285 // Set the icon according to the theme.
1287 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
1289 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
1291 } else { // Hide app bar is disabled.
1292 // Set the icon according to the theme.
1294 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
1296 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
1301 case "clear_everything":
1302 // Store the new `clear_everything` status
1303 boolean newClearEverythingBoolean = sharedPreferences.getBoolean("clear_everything", true);
1305 // Update the status of the `Clear and Exit` preferences.
1306 clearCookiesPreference.setEnabled(!newClearEverythingBoolean);
1307 clearDomStoragePreference.setEnabled(!newClearEverythingBoolean);
1308 clearFormDataPreference.setEnabled(!newClearEverythingBoolean); // This line can be removed once the minimum API >= 26.
1309 clearCachePreference.setEnabled(!newClearEverythingBoolean);
1311 // Update the `clearEverythingPreference` icon.
1312 if (newClearEverythingBoolean) {
1314 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_dark);
1316 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_light);
1319 clearEverythingPreference.setIcon(R.drawable.clear_everything_disabled);
1322 // Update the `clearCookiesPreference` icon.
1323 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_cookies", true)) {
1325 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_dark);
1327 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_light);
1330 clearCookiesPreference.setIcon(R.drawable.cookies_warning);
1333 // Update the `clearDomStoragePreference` icon.
1334 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_dom_storage", true)) {
1336 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_dark);
1338 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_light);
1341 clearDomStoragePreference.setIcon(R.drawable.dom_storage_warning);
1344 // Update the clear form data preference icon if the API < 26.
1345 if (Build.VERSION.SDK_INT < 26) {
1346 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_form_data", true)) {
1348 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_dark);
1350 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_light);
1353 clearFormDataPreference.setIcon(R.drawable.form_data_warning);
1357 // Update the `clearCachePreference` icon.
1358 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_cache", true)) {
1360 clearCachePreference.setIcon(R.drawable.cache_cleared_dark);
1362 clearCachePreference.setIcon(R.drawable.cache_cleared_light);
1365 clearCachePreference.setIcon(R.drawable.cache_warning);
1369 case "clear_cookies":
1371 if (sharedPreferences.getBoolean("clear_cookies", true)) {
1373 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_dark);
1375 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_light);
1378 clearCookiesPreference.setIcon(R.drawable.cookies_warning);
1382 case "clear_dom_storage":
1384 if (sharedPreferences.getBoolean("clear_dom_storage", true)) {
1386 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_dark);
1388 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_light);
1391 clearDomStoragePreference.setIcon(R.drawable.dom_storage_warning);
1395 // This section can be removed once the minimum API >= 26.
1396 case "clear_form_data":
1398 if (sharedPreferences.getBoolean("clear_form_data", true)) {
1400 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_dark);
1402 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_light);
1405 clearFormDataPreference.setIcon(R.drawable.form_data_warning);
1411 if (sharedPreferences.getBoolean("clear_cache", true)) {
1413 clearCachePreference.setIcon(R.drawable.cache_cleared_dark);
1415 clearCachePreference.setIcon(R.drawable.cache_cleared_light);
1418 clearCachePreference.setIcon(R.drawable.cache_warning);
1423 // Set the new homepage URL as the summary text for the Homepage preference.
1424 homepagePreference.setSummary(sharedPreferences.getString("homepage", getString(R.string.homepage_default_value)));
1428 // Update the font size summary text.
1429 fontSizePreference.setSummary(sharedPreferences.getString("font_size", getString(R.string.font_size_default_value)) + "%%");
1432 case "open_intents_in_new_tab":
1434 if (sharedPreferences.getBoolean("open_intents_in_new_tab", true)) {
1436 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_dark);
1438 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_light);
1442 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_dark);
1444 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_light);
1449 case "swipe_to_refresh":
1451 if (sharedPreferences.getBoolean("swipe_to_refresh", true)) {
1453 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_dark);
1455 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_light);
1459 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_dark);
1461 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_light);
1466 case "scroll_app_bar":
1468 if (sharedPreferences.getBoolean("scroll_app_bar", true)) {
1470 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
1472 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
1476 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
1478 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
1483 case "display_additional_app_bar_icons":
1485 if (sharedPreferences.getBoolean("display_additional_app_bar_icons", false)) {
1487 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_dark);
1489 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_light);
1493 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_dark);
1495 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_light);
1500 case "download_with_external_app":
1502 if (sharedPreferences.getBoolean("download_with_external_app", false)) {
1504 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_enabled_dark);
1506 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_enabled_light);
1510 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_disabled_dark);
1512 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_disabled_light);
1519 if (sharedPreferences.getBoolean("dark_theme", false)) {
1520 darkThemePreference.setIcon(R.drawable.theme_dark);
1522 darkThemePreference.setIcon(R.drawable.theme_light);
1525 // Create an intent to restart Privacy Browser.
1526 Intent changeThemeRestartIntent = getActivity().getParentActivityIntent();
1528 // Assert that the intent is not null to remove the lint error below.
1529 assert changeThemeRestartIntent != null;
1531 // `Intent.FLAG_ACTIVITY_CLEAR_TASK` removes all activities from the stack. It requires `Intent.FLAG_ACTIVITY_NEW_TASK`.
1532 changeThemeRestartIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
1534 // Create a handler to restart the activity.
1535 Handler changeThemeRestartHandler = new Handler();
1537 // Create a runnable to restart the activity.
1538 Runnable changeThemeRestartRunnable = () -> {
1539 // Restart the activity.
1540 startActivity(changeThemeRestartIntent);
1542 // Kill this instance of Privacy Browser. Otherwise, the app exhibits sporadic behavior after the restart.
1546 // Restart the activity after 100 milliseconds, so that the app has enough time to save the change to the preference.
1547 changeThemeRestartHandler.postDelayed(changeThemeRestartRunnable, 100);
1551 // Store the current night mode status.
1552 boolean currentNightModeBoolean = sharedPreferences.getBoolean("night_mode", false);
1553 boolean currentJavaScriptBoolean = sharedPreferences.getBoolean("javascript", false);
1556 if (currentNightModeBoolean) {
1558 nightModePreference.setIcon(R.drawable.night_mode_enabled_dark);
1560 nightModePreference.setIcon(R.drawable.night_mode_enabled_light);
1564 nightModePreference.setIcon(R.drawable.night_mode_disabled_dark);
1566 nightModePreference.setIcon(R.drawable.night_mode_disabled_light);
1570 // Update the status of `javaScriptPreference` and `domStoragePreference`.
1571 javaScriptPreference.setEnabled(!currentNightModeBoolean);
1572 domStoragePreference.setEnabled(currentNightModeBoolean || currentJavaScriptBoolean);
1574 // Update the `javaScriptPreference` icon.
1575 if (currentNightModeBoolean || currentJavaScriptBoolean) {
1576 javaScriptPreference.setIcon(R.drawable.javascript_enabled);
1578 javaScriptPreference.setIcon(R.drawable.privacy_mode);
1581 // Update the DOM storage preference icon.
1582 if (currentNightModeBoolean || currentJavaScriptBoolean) { // The preference is enabled.
1583 if (sharedPreferences.getBoolean("dom_storage", false)) { // DOM storage is enabled.
1584 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
1585 } else { // DOM storage is disabled.
1587 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_dark);
1589 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_light);
1592 } else { // The preference is disabled. The icon should be ghosted.
1594 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_dark);
1596 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_light);
1601 case "display_webpage_images":
1602 if (sharedPreferences.getBoolean("display_webpage_images", true)) {
1605 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_dark);
1607 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_light);
1612 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_dark);
1614 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_light);
1621 // Register the listener.
1622 savedPreferences.registerOnSharedPreferenceChangeListener(preferencesListener);
1625 // It is necessary to re-register the listener on every resume or it will randomly stop working because apps can be paused and resumed at any time, even while running in the foreground.
1627 public void onPause() {
1629 savedPreferences.unregisterOnSharedPreferenceChangeListener(preferencesListener);
1633 public void onResume() {
1635 savedPreferences.registerOnSharedPreferenceChangeListener(preferencesListener);