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 formDataPreference = 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 googleAnalyticsPreference = findPreference("google_analytics");
76 Preference facebookClickIdsPreference = findPreference("facebook_click_ids");
77 Preference proxyThroughOrbotPreference = findPreference("proxy_through_orbot");
78 Preference torHomepagePreference = findPreference("tor_homepage");
79 Preference torSearchPreference = findPreference("tor_search");
80 Preference torSearchCustomURLPreference = findPreference("tor_search_custom_url");
81 Preference searchPreference = findPreference("search");
82 Preference searchCustomURLPreference = findPreference("search_custom_url");
83 Preference fullScreenBrowsingModePreference = findPreference("full_screen_browsing_mode");
84 Preference hideAppBarPreference = findPreference("hide_app_bar");
85 Preference clearEverythingPreference = findPreference("clear_everything");
86 Preference clearCookiesPreference = findPreference("clear_cookies");
87 Preference clearDomStoragePreference = findPreference("clear_dom_storage");
88 Preference clearFormDataPreference = findPreference("clear_form_data"); // The clear form data preference can be removed once the minimum API >= 26.
89 Preference clearCachePreference = findPreference("clear_cache");
90 Preference homepagePreference = findPreference("homepage");
91 Preference fontSizePreference = findPreference("font_size");
92 Preference openIntentsInNewTabPreference = findPreference("open_intents_in_new_tab");
93 Preference swipeToRefreshPreference = findPreference("swipe_to_refresh");
94 Preference scrollAppBarPreference = findPreference("scroll_app_bar");
95 Preference displayAdditionalAppBarIconsPreference = findPreference("display_additional_app_bar_icons");
96 Preference downloadWithExternalAppPreference = findPreference("download_with_external_app");
97 Preference darkThemePreference = findPreference("dark_theme");
98 Preference nightModePreference = findPreference("night_mode");
99 Preference displayWebpageImagesPreference = findPreference("display_webpage_images");
102 torHomepagePreference.setDependency("proxy_through_orbot");
103 torSearchPreference.setDependency("proxy_through_orbot");
104 hideAppBarPreference.setDependency("full_screen_browsing_mode");
106 // Get strings from the preferences.
107 String torSearchString = savedPreferences.getString("tor_search", getString(R.string.tor_search_default_value));
108 String searchString = savedPreferences.getString("search", getString(R.string.search_default_value));
110 // Get booleans that are used in multiple places from the preferences.
111 boolean javaScriptEnabled = savedPreferences.getBoolean("javascript", false);
112 boolean firstPartyCookiesEnabled = savedPreferences.getBoolean("first_party_cookies", false);
113 boolean thirdPartyCookiesEnabled = savedPreferences.getBoolean("third_party_cookies", false);
114 boolean fanboyAnnoyanceListEnabled = savedPreferences.getBoolean("fanboys_annoyance_list", true);
115 boolean fanboySocialBlockingEnabled = savedPreferences.getBoolean("fanboys_social_blocking_list", true);
116 boolean proxyThroughOrbot = savedPreferences.getBoolean("proxy_through_orbot", false);
117 boolean fullScreenBrowsingMode = savedPreferences.getBoolean("full_screen_browsing_mode", false);
118 boolean clearEverything = savedPreferences.getBoolean("clear_everything", true);
119 boolean darkTheme = savedPreferences.getBoolean("dark_theme", false);
120 boolean nightMode = savedPreferences.getBoolean("night_mode", false);
122 // Only enable the third-party cookies preference if first-party cookies are enabled and API >= 21.
123 thirdPartyCookiesPreference.setEnabled(firstPartyCookiesEnabled && (Build.VERSION.SDK_INT >= 21));
125 // Only enable the DOM storage preference if either JavaScript or Night Mode is enabled.
126 domStoragePreference.setEnabled(javaScriptEnabled || nightMode);
128 // Remove the form data preferences if the API is >= 26 as they no longer do anything.
129 if (Build.VERSION.SDK_INT >= 26) {
130 // Get the categories.
131 PreferenceCategory privacyCategory = (PreferenceCategory) findPreference("privacy");
132 PreferenceCategory clearAndExitCategory = (PreferenceCategory) findPreference("clear_and_exit");
134 // Remove the form data preferences.
135 privacyCategory.removePreference(formDataPreference);
136 clearAndExitCategory.removePreference(clearFormDataPreference);
139 // Only enable Fanboy's social blocking list preference if Fanboy's annoyance list is disabled.
140 fanboySocialBlockingListPreference.setEnabled(!fanboyAnnoyanceListEnabled);
142 // Inflate a WebView to get the default user agent.
143 LayoutInflater inflater = getActivity().getLayoutInflater();
144 // `@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.
145 @SuppressLint("InflateParams") View bareWebViewLayout = inflater.inflate(R.layout.bare_webview, null, false);
146 WebView bareWebView = bareWebViewLayout.findViewById(R.id.bare_webview);
148 // Get the user agent arrays.
149 ArrayAdapter<CharSequence> userAgentNamesArray = ArrayAdapter.createFromResource(context, R.array.user_agent_names, R.layout.spinner_item);
150 String[] translatedUserAgentNamesArray = getResources().getStringArray(R.array.translated_user_agent_names);
151 String[] userAgentDataArray = getResources().getStringArray(R.array.user_agent_data);
153 // Get the current user agent name from the preference.
154 String userAgentName = savedPreferences.getString("user_agent", getString(R.string.user_agent_default_value));
156 // Get the array position of the user agent name.
157 int userAgentArrayPosition = userAgentNamesArray.getPosition(userAgentName);
159 // Populate the user agent summary.
160 switch (userAgentArrayPosition) {
161 case MainWebViewActivity.UNRECOGNIZED_USER_AGENT: // The user agent name is not on the canonical list.
162 // 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.
163 userAgentPreference.setSummary(userAgentName);
166 case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
167 // Get the user agent text from the webview (which changes based on the version of Android and WebView installed).
168 userAgentPreference.setSummary(translatedUserAgentNamesArray[userAgentArrayPosition] + ":\n" + bareWebView.getSettings().getUserAgentString());
171 case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
172 // Set the summary text.
173 userAgentPreference.setSummary(R.string.custom_user_agent);
177 // Get the user agent summary from the user agent data array.
178 userAgentPreference.setSummary(translatedUserAgentNamesArray[userAgentArrayPosition] + ":\n" + userAgentDataArray[userAgentArrayPosition]);
181 // Set the summary text for the custom user agent preference and enable it if user agent preference is set to custom.
182 customUserAgentPreference.setSummary(savedPreferences.getString("custom_user_agent", getString(R.string.custom_user_agent_default_value)));
183 customUserAgentPreference.setEnabled(userAgentPreference.getSummary().equals(getString(R.string.custom_user_agent)));
186 // 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/`.
187 torHomepagePreference.setSummary(savedPreferences.getString("tor_homepage", getString(R.string.tor_homepage_default_value)));
190 // Set the Tor search URL as the summary text for the Tor preference when the preference screen is loaded.
191 if (torSearchString.equals("Custom URL")) {
192 // Use R.string.custom_url, which will be translated, instead of the array value, which will not.
193 torSearchPreference.setSummary(R.string.custom_url);
195 // Set the array value as the summary text.
196 torSearchPreference.setSummary(torSearchString);
199 // Set the summary text for `tor_search_custom_url`. The default is `""`.
200 torSearchCustomURLPreference.setSummary(savedPreferences.getString("tor_search_custom_url", getString(R.string.tor_search_custom_url_default_value)));
202 // Enable the Tor custom URL search options only if proxying through Orbot and the search is set to `Custom URL`.
203 torSearchCustomURLPreference.setEnabled(proxyThroughOrbot && torSearchString.equals("Custom URL"));
206 // Set the search URL as the summary text for the search preference when the preference screen is loaded.
207 if (searchString.equals("Custom URL")) {
208 // Use R.string.custom_url, which will be translated, instead of the array value, which will not.
209 searchPreference.setSummary(R.string.custom_url);
211 // Set the array value as the summary text.
212 searchPreference.setSummary(searchString);
215 // Set the summary text for `search_custom_url` (the default is `""`) and enable it if `search` is set to `Custom URL`.
216 searchCustomURLPreference.setSummary(savedPreferences.getString("search_custom_url", getString(R.string.search_custom_url_default_value)));
217 searchCustomURLPreference.setEnabled(searchString.equals("Custom URL"));
219 // Set the status of the Clear and Exit preferences.
220 clearCookiesPreference.setEnabled(!clearEverything);
221 clearDomStoragePreference.setEnabled(!clearEverything);
222 clearFormDataPreference.setEnabled(!clearEverything); // The form data line can be removed once the minimum API is >= 26.
223 clearCachePreference.setEnabled(!clearEverything);
225 // Set the homepage URL as the summary text for the homepage preference.
226 homepagePreference.setSummary(savedPreferences.getString("homepage", getString(R.string.homepage_default_value)));
228 // Set the font size as the summary text for the preference.
229 fontSizePreference.setSummary(savedPreferences.getString("font_size", getString(R.string.font_size_default_value)) + "%%");
231 // Disable the JavaScript preference if Night Mode is enabled. JavaScript will be enabled for all web pages.
232 javaScriptPreference.setEnabled(!nightMode);
234 // Set the JavaScript icon.
235 if (javaScriptEnabled || nightMode) {
236 javaScriptPreference.setIcon(R.drawable.javascript_enabled);
238 javaScriptPreference.setIcon(R.drawable.privacy_mode);
241 // Set the first-party cookies icon.
242 if (firstPartyCookiesEnabled) {
243 firstPartyCookiesPreference.setIcon(R.drawable.cookies_enabled);
246 firstPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
248 firstPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
252 // Set the third party cookies icon.
253 if (firstPartyCookiesEnabled && Build.VERSION.SDK_INT >= 21) {
254 if (thirdPartyCookiesEnabled) {
255 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_warning);
258 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
260 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
265 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_dark);
267 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_light);
271 // Set the DOM storage icon.
272 if (javaScriptEnabled || nightMode) { // The preference is enabled.
273 if (savedPreferences.getBoolean("dom_storage", false)) { // DOM storage is enabled.
274 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
275 } else { // DOM storage is disabled.
277 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_dark);
279 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_light);
282 } else { // The preference is disabled. The icon should be ghosted.
284 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_dark);
286 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_light);
290 // Set the save form data icon if API < 26. Save form data has no effect on API >= 26.
291 if (Build.VERSION.SDK_INT < 26) {
292 if (savedPreferences.getBoolean("save_form_data", false)) {
293 formDataPreference.setIcon(R.drawable.form_data_enabled);
296 formDataPreference.setIcon(R.drawable.form_data_disabled_dark);
298 formDataPreference.setIcon(R.drawable.form_data_disabled_light);
303 // Set the custom user agent icon.
304 if (customUserAgentPreference.isEnabled()) {
306 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_dark);
308 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_light);
312 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_dark);
314 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_light);
318 // Set the incognito mode icon.
319 if (savedPreferences.getBoolean("incognito_mode", false)) {
321 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_dark);
323 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_light);
327 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_dark);
329 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_light);
333 // Set the Do Not Track icon.
334 if (savedPreferences.getBoolean("do_not_track", false)) {
336 doNotTrackPreference.setIcon(R.drawable.block_tracking_enabled_dark);
338 doNotTrackPreference.setIcon(R.drawable.block_tracking_enabled_light);
342 doNotTrackPreference.setIcon(R.drawable.block_tracking_disabled_dark);
344 doNotTrackPreference.setIcon(R.drawable.block_tracking_disabled_light);
348 // Set the allow screenshots icon.
349 if (savedPreferences.getBoolean("allow_screenshots", false)) {
351 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_dark);
353 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_light);
357 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_dark);
359 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_light);
363 // Set the EasyList icon.
364 if (savedPreferences.getBoolean("easylist", true)) {
366 easyListPreference.setIcon(R.drawable.block_ads_enabled_dark);
368 easyListPreference.setIcon(R.drawable.block_ads_enabled_light);
372 easyListPreference.setIcon(R.drawable.block_ads_disabled_dark);
374 easyListPreference.setIcon(R.drawable.block_ads_disabled_light);
378 // Set the EasyPrivacy icon.
379 if (savedPreferences.getBoolean("easyprivacy", true)) {
381 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_dark);
383 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_light);
387 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_dark);
389 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_light);
393 // Set the Fanboy lists icons.
394 if (fanboyAnnoyanceListEnabled) {
396 // Set the Fanboy annoyance list icon.
397 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_dark);
399 // Set the Fanboy social blocking list icon.
400 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_dark);
402 // Set the Fanboy annoyance list icon.
403 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_light);
405 // Set the Fanboy social blocking list icon.
406 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_light);
410 // Set the Fanboy annoyance list icon.
411 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled_dark);
413 // Set the Fanboy social blocking list icon.
414 if (fanboySocialBlockingEnabled) {
415 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_dark);
417 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_dark);
420 // Set the Fanboy annoyance list icon.
421 fanboyAnnoyanceListPreference.setIcon(R.drawable.block_ads_disabled_light);
423 // Set the Fanboy social blocking list icon.
424 if (fanboySocialBlockingEnabled) {
425 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_light);
427 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_light);
432 // Set the UltraPrivacy icon.
433 if (savedPreferences.getBoolean("ultraprivacy", true)) {
435 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_dark);
437 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_light);
441 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_dark);
443 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_light);
447 // Set the block all third-party requests icon.
448 if (savedPreferences.getBoolean("block_all_third_party_requests", false)) {
450 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_dark);
452 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_light);
456 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_dark);
458 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_light);
462 // Set the Google Analytics icon according to the theme.
463 if (savedPreferences.getBoolean("google_analytics", true)) {
465 googleAnalyticsPreference.setIcon(R.drawable.modify_url_enabled_dark);
467 googleAnalyticsPreference.setIcon(R.drawable.modify_url_enabled_light);
471 googleAnalyticsPreference.setIcon(R.drawable.modify_url_disabled_dark);
473 googleAnalyticsPreference.setIcon(R.drawable.modify_url_disabled_light);
477 // Set the Facebook Click IDs icon according to the theme.
478 if (savedPreferences.getBoolean("facebook_click_ids", true)) {
480 facebookClickIdsPreference.setIcon(R.drawable.modify_url_enabled_dark);
482 facebookClickIdsPreference.setIcon(R.drawable.modify_url_enabled_light);
486 facebookClickIdsPreference.setIcon(R.drawable.modify_url_disabled_dark);
488 facebookClickIdsPreference.setIcon(R.drawable.modify_url_disabled_light);
492 // Set the Tor icons according to the theme.
493 if (proxyThroughOrbot) { // Proxying is enabled.
495 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_enabled_dark);
496 torHomepagePreference.setIcon(R.drawable.home_enabled_dark);
497 torSearchPreference.setIcon(R.drawable.search_enabled_dark);
499 // Set the custom search icon.
500 if (torSearchCustomURLPreference.isEnabled()) {
501 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_dark);
503 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
506 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_enabled_light);
507 torHomepagePreference.setIcon(R.drawable.home_enabled_light);
508 torSearchPreference.setIcon(R.drawable.search_enabled_light);
510 // Set the custom search icon.
511 if (torSearchCustomURLPreference.isEnabled()) {
512 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_light);
514 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
517 } else { // Proxying is disabled.
519 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_disabled_dark);
520 torHomepagePreference.setIcon(R.drawable.home_ghosted_dark);
521 torSearchPreference.setIcon(R.drawable.search_ghosted_dark);
522 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
524 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_disabled_light);
525 torHomepagePreference.setIcon(R.drawable.home_ghosted_light);
526 torSearchPreference.setIcon(R.drawable.search_ghosted_light);
527 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
531 // Set the search custom URL icon.
532 if (searchCustomURLPreference.isEnabled()) {
534 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_dark);
536 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_light);
540 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
542 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
546 // Set the full screen browsing mode icons.
547 if (fullScreenBrowsingMode) { // Full screen browsing mode is enabled.
548 // Set the `fullScreenBrowsingModePreference` icon according to the theme.
550 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_dark);
552 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_light);
555 // Set the hide app bar icon.
556 if (savedPreferences.getBoolean("hide_app_bar", true)) { // Hide app bar is enabled.
557 // Set the icon according to the theme.
559 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
561 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
563 } else { // Hide app bar is disabled.
564 // Set the icon according to the theme.
566 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
568 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
571 } else { // Full screen browsing mode is disabled.
572 // Set the icons according to the theme.
574 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_dark);
575 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_dark);
577 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_light);
578 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_light);
582 // Set the clear everything preference icon.
583 if (clearEverything) {
585 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_dark);
587 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_light);
590 clearEverythingPreference.setIcon(R.drawable.clear_everything_disabled);
593 // Set the clear cookies preference icon.
594 if (clearEverything || savedPreferences.getBoolean("clear_cookies", true)) {
596 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_dark);
598 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_light);
601 clearCookiesPreference.setIcon(R.drawable.cookies_warning);
604 // Set the clear DOM storage preference icon.
605 if (clearEverything || savedPreferences.getBoolean("clear_dom_storage", true)) {
607 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_dark);
609 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_light);
612 clearDomStoragePreference.setIcon(R.drawable.dom_storage_warning);
615 // Set the clear form data preference icon if the API < 26. It has no effect on newer versions of Android.
616 if (Build.VERSION.SDK_INT < 26) {
617 if (clearEverything || savedPreferences.getBoolean("clear_form_data", true)) {
619 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_dark);
621 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_light);
624 clearFormDataPreference.setIcon(R.drawable.form_data_warning);
628 // Set the clear cache preference icon.
629 if (clearEverything || savedPreferences.getBoolean("clear_cache", true)) {
631 clearCachePreference.setIcon(R.drawable.cache_cleared_dark);
633 clearCachePreference.setIcon(R.drawable.cache_cleared_light);
636 clearCachePreference.setIcon(R.drawable.cache_warning);
639 // Set the open intents in new tab preference icon.
640 if (savedPreferences.getBoolean("open_intents_in_new_tab", true)) {
642 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_dark);
644 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_light);
648 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_dark);
650 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_light);
654 // Set the swipe to refresh preference icon.
655 if (savedPreferences.getBoolean("swipe_to_refresh", true)) {
657 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_dark);
659 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_light);
663 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_dark);
665 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_light);
669 // Set the scroll app bar preference icon.
670 if (savedPreferences.getBoolean("scroll_app_bar", true)) {
672 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
674 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
678 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
680 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
684 // Set the display additional app bar icons preference icon.
685 if (savedPreferences.getBoolean("display_additional_app_bar_icons", false)) {
687 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_dark);
689 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_light);
693 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_dark);
695 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_light);
699 // Set the download with external app preference icon.
700 if (savedPreferences.getBoolean("download_with_external_app", false)) {
702 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_enabled_dark);
704 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_enabled_light);
708 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_disabled_dark);
710 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_disabled_light);
714 // Set the dark theme preference icon.
715 if (savedPreferences.getBoolean("dark_theme", false)) {
716 darkThemePreference.setIcon(R.drawable.theme_dark);
718 darkThemePreference.setIcon(R.drawable.theme_light);
721 // Set the night mode preference icon.
724 nightModePreference.setIcon(R.drawable.night_mode_enabled_dark);
726 nightModePreference.setIcon(R.drawable.night_mode_enabled_light);
730 nightModePreference.setIcon(R.drawable.night_mode_disabled_dark);
732 nightModePreference.setIcon(R.drawable.night_mode_disabled_light);
736 // Set the display webpage images preference icon.
737 if (savedPreferences.getBoolean("display_webpage_images", true)) {
739 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_dark);
741 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_light);
745 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_dark);
747 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_light);
752 // Listen for preference changes.
753 preferencesListener = (SharedPreferences sharedPreferences, String key) -> {
756 // Update the icons and the DOM storage preference status.
757 if (sharedPreferences.getBoolean("javascript", false)) { // The JavaScript preference is enabled.
758 // Update the icon for the JavaScript preference.
759 javaScriptPreference.setIcon(R.drawable.javascript_enabled);
761 // Update the status of the DOM storage preference.
762 domStoragePreference.setEnabled(true);
764 // Update the icon for the DOM storage preference.
765 if (sharedPreferences.getBoolean("dom_storage", false)) {
766 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
769 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_dark);
771 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_light);
774 } else { // The JavaScript preference is disabled.
775 // Update the icon for the JavaScript preference.
776 javaScriptPreference.setIcon(R.drawable.privacy_mode);
778 // Update the status of the DOM storage preference.
779 domStoragePreference.setEnabled(false);
781 // Set the icon for DOM storage preference to be ghosted.
783 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_dark);
785 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_light);
790 case "first_party_cookies":
791 // Update the icons for `first_party_cookies` and `third_party_cookies`.
792 if (sharedPreferences.getBoolean("first_party_cookies", false)) {
793 // Set the icon for `first_party_cookies`.
794 firstPartyCookiesPreference.setIcon(R.drawable.cookies_enabled);
796 // Update the icon for `third_party_cookies`.
797 if (Build.VERSION.SDK_INT >= 21) {
798 if (sharedPreferences.getBoolean("third_party_cookies", false)) {
799 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_warning);
802 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
804 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
809 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_dark);
811 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_light);
814 } else { // `first_party_cookies` is `false`.
815 // Update the icon for `first_party_cookies`.
817 firstPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
819 firstPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
822 // Set the icon for `third_party_cookies` to be ghosted.
824 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_dark);
826 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_light);
830 // Enable `third_party_cookies` if `first_party_cookies` is `true` and API >= 21.
831 thirdPartyCookiesPreference.setEnabled(sharedPreferences.getBoolean("first_party_cookies", false) && (Build.VERSION.SDK_INT >= 21));
834 case "third_party_cookies":
836 if (sharedPreferences.getBoolean("third_party_cookies", false)) {
837 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_warning);
840 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
842 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
849 if (sharedPreferences.getBoolean("dom_storage", false)) {
850 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
853 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_dark);
855 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_light);
860 // Save form data can be removed once the minimum API >= 26.
861 case "save_form_data":
863 if (sharedPreferences.getBoolean("save_form_data", false)) {
864 formDataPreference.setIcon(R.drawable.form_data_enabled);
867 formDataPreference.setIcon(R.drawable.form_data_disabled_dark);
869 formDataPreference.setIcon(R.drawable.form_data_disabled_light);
875 // Get the new user agent name.
876 String newUserAgentName = sharedPreferences.getString("user_agent", getString(R.string.user_agent_default_value));
878 // Get the array position for the new user agent name.
879 int newUserAgentArrayPosition = userAgentNamesArray.getPosition(newUserAgentName);
881 // Get the translated new user agent name.
882 String translatedNewUserAgentName = translatedUserAgentNamesArray[newUserAgentArrayPosition];
884 // Populate the user agent summary.
885 switch (newUserAgentArrayPosition) {
886 case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
887 // Get the user agent text from the webview (which changes based on the version of Android and WebView installed).
888 userAgentPreference.setSummary(translatedNewUserAgentName + ":\n" + bareWebView.getSettings().getUserAgentString());
890 // Disable the custom user agent preference.
891 customUserAgentPreference.setEnabled(false);
893 // Set the custom user agent preference icon according to the theme.
895 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_dark);
897 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_light);
901 case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
902 // Set the summary text.
903 userAgentPreference.setSummary(R.string.custom_user_agent);
905 // Enable the custom user agent preference.
906 customUserAgentPreference.setEnabled(true);
908 // Set the custom user agent preference icon according to the theme.
910 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_dark);
912 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_light);
917 // Get the user agent summary from the user agent data array.
918 userAgentPreference.setSummary(translatedNewUserAgentName + ":\n" + userAgentDataArray[newUserAgentArrayPosition]);
920 // Disable the custom user agent preference.
921 customUserAgentPreference.setEnabled(false);
923 // Set the custom user agent preference icon according to the theme.
925 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_dark);
927 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_light);
932 case "custom_user_agent":
933 // Set the new custom user agent as the summary text for the preference.
934 customUserAgentPreference.setSummary(sharedPreferences.getString("custom_user_agent", getString(R.string.custom_user_agent_default_value)));
937 case "incognito_mode":
939 if (sharedPreferences.getBoolean("incognito_mode", false)) {
941 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_dark);
943 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_light);
947 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_dark);
949 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_light);
956 if (sharedPreferences.getBoolean("do_not_track", false)) {
958 doNotTrackPreference.setIcon(R.drawable.block_tracking_enabled_dark);
960 doNotTrackPreference.setIcon(R.drawable.block_tracking_enabled_light);
964 doNotTrackPreference.setIcon(R.drawable.block_tracking_disabled_dark);
966 doNotTrackPreference.setIcon(R.drawable.block_tracking_disabled_light);
972 case "allow_screenshots":
974 if (sharedPreferences.getBoolean("allow_screenshots", false)) {
976 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_dark);
978 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_light);
982 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_dark);
984 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_light);
988 // Create an intent to restart Privacy Browser.
989 Intent allowScreenshotsRestartIntent = getActivity().getParentActivityIntent();
991 // Assert that the intent is not null to remove the lint error below.
992 assert allowScreenshotsRestartIntent != null;
994 // `Intent.FLAG_ACTIVITY_CLEAR_TASK` removes all activities from the stack. It requires `Intent.FLAG_ACTIVITY_NEW_TASK`.
995 allowScreenshotsRestartIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
997 // Create a handler to restart the activity.
998 Handler allowScreenshotsRestartHandler = new Handler();
1000 // Create a runnable to restart the activity.
1001 Runnable allowScreenshotsRestartRunnable = () -> {
1002 // Restart the activity.
1003 startActivity(allowScreenshotsRestartIntent);
1005 // Kill this instance of Privacy Browser. Otherwise, the app exhibits sporadic behavior after the restart.
1009 // Restart the activity after 100 milliseconds, so that the app has enough time to save the change to the preference.
1010 allowScreenshotsRestartHandler.postDelayed(allowScreenshotsRestartRunnable, 100);
1015 if (sharedPreferences.getBoolean("easylist", true)) {
1017 easyListPreference.setIcon(R.drawable.block_ads_enabled_dark);
1019 easyListPreference.setIcon(R.drawable.block_ads_enabled_light);
1023 easyListPreference.setIcon(R.drawable.block_ads_disabled_dark);
1025 easyListPreference.setIcon(R.drawable.block_ads_disabled_light);
1032 if (sharedPreferences.getBoolean("easyprivacy", true)) {
1034 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_dark);
1036 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_light);
1040 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_dark);
1042 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_light);
1047 case "fanboys_annoyance_list":
1048 boolean currentFanboyAnnoyanceList = sharedPreferences.getBoolean("fanboys_annoyance_list", true);
1049 boolean currentFanboySocialBlockingList = sharedPreferences.getBoolean("fanboys_social_blocking_list", true);
1051 // Update the Fanboy icons.
1052 if (currentFanboyAnnoyanceList) { // Fanboy's annoyance list is enabled.
1054 // Update the Fanboy's annoyance list icon.
1055 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_dark);
1057 // Update the Fanboy's social blocking list icon.
1058 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_dark);
1060 // Update the Fanboy's annoyance list icon.
1061 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_light);
1063 // Update the Fanboy's social blocking list icon.
1064 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_light);
1066 } else { // Fanboy's annoyance list is disabled.
1068 // Update the Fanboy's annoyance list icon.
1069 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled_dark);
1071 // Update the Fanboy's social blocking list icon.
1072 if (currentFanboySocialBlockingList) {
1073 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_dark);
1075 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_dark);
1078 // Update the Fanboy's annoyance list icon.
1079 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled_light);
1081 // Update the Fanboy's social blocking list icon.
1082 if (currentFanboySocialBlockingList) {
1083 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_light);
1085 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_light);
1090 // Only enable Fanboy's social blocking list preference if Fanboy's annoyance list preference is disabled.
1091 fanboySocialBlockingListPreference.setEnabled(!currentFanboyAnnoyanceList);
1094 case "fanboys_social_blocking_list":
1096 if (sharedPreferences.getBoolean("fanboys_social_blocking_list", true)) {
1098 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_dark);
1100 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_light);
1104 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_dark);
1106 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_light);
1111 case "ultraprivacy":
1113 if (sharedPreferences.getBoolean("ultraprivacy", true)) {
1115 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_dark);
1117 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_light);
1121 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_dark);
1123 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_light);
1128 case "block_all_third_party_requests":
1130 if (sharedPreferences.getBoolean("block_all_third_party_requests", false)) {
1132 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_dark);
1134 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_light);
1138 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_dark);
1140 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_light);
1145 case "google_analytics":
1147 if (sharedPreferences.getBoolean("google_analytics", true)) {
1149 googleAnalyticsPreference.setIcon(R.drawable.modify_url_enabled_dark);
1151 googleAnalyticsPreference.setIcon(R.drawable.modify_url_enabled_light);
1155 googleAnalyticsPreference.setIcon(R.drawable.modify_url_disabled_dark);
1157 googleAnalyticsPreference.setIcon(R.drawable.modify_url_disabled_light);
1162 case "facebook_click_ids":
1164 if (sharedPreferences.getBoolean("facebook_click_ids", true)) {
1166 facebookClickIdsPreference.setIcon(R.drawable.modify_url_enabled_dark);
1168 facebookClickIdsPreference.setIcon(R.drawable.modify_url_enabled_light);
1172 facebookClickIdsPreference.setIcon(R.drawable.modify_url_disabled_dark);
1174 facebookClickIdsPreference.setIcon(R.drawable.modify_url_disabled_light);
1179 case "proxy_through_orbot":
1180 // Get current settings.
1181 boolean currentProxyThroughOrbot = sharedPreferences.getBoolean("proxy_through_orbot", false);
1182 String currentTorSearchString = sharedPreferences.getString("tor_search", getString(R.string.tor_search_default_value));
1184 // Enable the Tor custom URL search option only if `currentProxyThroughOrbot` is true and the search is set to `Custom URL`.
1185 torSearchCustomURLPreference.setEnabled(currentProxyThroughOrbot && currentTorSearchString.equals("Custom URL"));
1187 // Update the icons.
1188 if (currentProxyThroughOrbot) {
1189 // Set the Tor icons according to the theme.
1191 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_enabled_dark);
1192 torHomepagePreference.setIcon(R.drawable.home_enabled_dark);
1193 torSearchPreference.setIcon(R.drawable.search_enabled_dark);
1195 // Set the `torSearchCustomURLPreference` icon.
1196 if (torSearchCustomURLPreference.isEnabled()) {
1197 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_dark);
1199 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
1202 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_enabled_light);
1203 torHomepagePreference.setIcon(R.drawable.home_enabled_light);
1204 torSearchPreference.setIcon(R.drawable.search_enabled_light);
1206 // Set the `torSearchCustomURLPreference` icon.
1207 if (torSearchCustomURLPreference.isEnabled()) {
1208 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_light);
1210 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
1213 } else { // Proxy through Orbot is disabled.
1215 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_disabled_dark);
1216 torHomepagePreference.setIcon(R.drawable.home_ghosted_dark);
1217 torSearchPreference.setIcon(R.drawable.search_ghosted_dark);
1218 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
1220 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_disabled_light);
1221 torHomepagePreference.setIcon(R.drawable.home_ghosted_light);
1222 torSearchPreference.setIcon(R.drawable.search_ghosted_light);
1223 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
1228 case "tor_homepage":
1229 // Set the new tor homepage URL as the summary text for the `tor_homepage` preference. The default is Searx: `http://ulrn6sryqaifefld.onion/`.
1230 torHomepagePreference.setSummary(sharedPreferences.getString("tor_homepage", getString(R.string.tor_homepage_default_value)));
1234 // Get the present search string.
1235 String presentTorSearchString = sharedPreferences.getString("tor_search", getString(R.string.tor_search_default_value));
1237 // Update the preferences.
1238 if (presentTorSearchString.equals("Custom URL")) {
1239 // Use `R.string.custom_url`, which is translated, as the summary instead of the array value, which isn't.
1240 torSearchPreference.setSummary(R.string.custom_url);
1242 // Enable `torSearchCustomURLPreference`.
1243 torSearchCustomURLPreference.setEnabled(true);
1245 // Update the `torSearchCustomURLPreference` icon.
1247 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_dark);
1249 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_light);
1252 // Set the array value as the summary text.
1253 torSearchPreference.setSummary(presentTorSearchString);
1255 // Disable `torSearchCustomURLPreference`.
1256 torSearchCustomURLPreference.setEnabled(false);
1258 // Update the `torSearchCustomURLPreference` icon.
1260 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
1262 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
1267 case "tor_search_custom_url":
1268 // Set the summary text for `tor_search_custom_url`.
1269 torSearchCustomURLPreference.setSummary(sharedPreferences.getString("tor_search_custom_url", getString(R.string.tor_search_custom_url_default_value)));
1273 // Store the new search string.
1274 String newSearchString = sharedPreferences.getString("search", getString(R.string.search_default_value));
1276 // Update `searchPreference` and `searchCustomURLPreference`.
1277 if (newSearchString.equals("Custom URL")) { // `Custom URL` is selected.
1278 // Set the summary text to `R.string.custom_url`, which is translated.
1279 searchPreference.setSummary(R.string.custom_url);
1281 // Enable `searchCustomURLPreference`.
1282 searchCustomURLPreference.setEnabled(true);
1284 // Set the `searchCustomURLPreference` according to the theme.
1286 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_dark);
1288 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_light);
1290 } else { // `Custom URL` is not selected.
1291 // Set the summary text to `newSearchString`.
1292 searchPreference.setSummary(newSearchString);
1294 // Disable `searchCustomURLPreference`.
1295 searchCustomURLPreference.setEnabled(false);
1297 // Set the `searchCustomURLPreference` according to the theme.
1299 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
1301 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
1306 case "search_custom_url":
1307 // Set the new custom search URL as the summary text for `search_custom_url`. The default is `""`.
1308 searchCustomURLPreference.setSummary(sharedPreferences.getString("search_custom_url", getString(R.string.search_custom_url_default_value)));
1311 case "full_screen_browsing_mode":
1312 if (sharedPreferences.getBoolean("full_screen_browsing_mode", false)) { // Full screen browsing is enabled.
1313 // Set the full screen browsing mode preference icon according to the theme.
1315 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_dark);
1317 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_light);
1320 // Set the hide app bar preference icon.
1321 if (sharedPreferences.getBoolean("hide_app_bar", true)) { // Hide app bar is enabled.
1322 // Set the icon according to the theme.
1324 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
1326 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
1328 } else { // Hide app bar is disabled.
1329 // Set the icon according to the theme.
1331 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
1333 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
1336 } else { // Full screen browsing is disabled.
1337 // Update the icons according to the theme.
1339 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_dark);
1340 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_dark);
1342 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_light);
1343 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_light);
1348 case "hide_app_bar":
1350 if (sharedPreferences.getBoolean("hide_app_bar", true)) { // Hide app bar is enabled.
1351 // Set the icon according to the theme.
1353 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
1355 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
1357 } else { // Hide app bar is disabled.
1358 // Set the icon according to the theme.
1360 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
1362 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
1367 case "clear_everything":
1368 // Store the new `clear_everything` status
1369 boolean newClearEverythingBoolean = sharedPreferences.getBoolean("clear_everything", true);
1371 // Update the status of the `Clear and Exit` preferences.
1372 clearCookiesPreference.setEnabled(!newClearEverythingBoolean);
1373 clearDomStoragePreference.setEnabled(!newClearEverythingBoolean);
1374 clearFormDataPreference.setEnabled(!newClearEverythingBoolean); // This line can be removed once the minimum API >= 26.
1375 clearCachePreference.setEnabled(!newClearEverythingBoolean);
1377 // Update the `clearEverythingPreference` icon.
1378 if (newClearEverythingBoolean) {
1380 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_dark);
1382 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_light);
1385 clearEverythingPreference.setIcon(R.drawable.clear_everything_disabled);
1388 // Update the `clearCookiesPreference` icon.
1389 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_cookies", true)) {
1391 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_dark);
1393 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_light);
1396 clearCookiesPreference.setIcon(R.drawable.cookies_warning);
1399 // Update the `clearDomStoragePreference` icon.
1400 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_dom_storage", true)) {
1402 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_dark);
1404 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_light);
1407 clearDomStoragePreference.setIcon(R.drawable.dom_storage_warning);
1410 // Update the clear form data preference icon if the API < 26.
1411 if (Build.VERSION.SDK_INT < 26) {
1412 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_form_data", true)) {
1414 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_dark);
1416 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_light);
1419 clearFormDataPreference.setIcon(R.drawable.form_data_warning);
1423 // Update the `clearCachePreference` icon.
1424 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_cache", true)) {
1426 clearCachePreference.setIcon(R.drawable.cache_cleared_dark);
1428 clearCachePreference.setIcon(R.drawable.cache_cleared_light);
1431 clearCachePreference.setIcon(R.drawable.cache_warning);
1435 case "clear_cookies":
1437 if (sharedPreferences.getBoolean("clear_cookies", true)) {
1439 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_dark);
1441 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_light);
1444 clearCookiesPreference.setIcon(R.drawable.cookies_warning);
1448 case "clear_dom_storage":
1450 if (sharedPreferences.getBoolean("clear_dom_storage", true)) {
1452 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_dark);
1454 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_light);
1457 clearDomStoragePreference.setIcon(R.drawable.dom_storage_warning);
1461 // This section can be removed once the minimum API >= 26.
1462 case "clear_form_data":
1464 if (sharedPreferences.getBoolean("clear_form_data", true)) {
1466 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_dark);
1468 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_light);
1471 clearFormDataPreference.setIcon(R.drawable.form_data_warning);
1477 if (sharedPreferences.getBoolean("clear_cache", true)) {
1479 clearCachePreference.setIcon(R.drawable.cache_cleared_dark);
1481 clearCachePreference.setIcon(R.drawable.cache_cleared_light);
1484 clearCachePreference.setIcon(R.drawable.cache_warning);
1489 // Set the new homepage URL as the summary text for the Homepage preference.
1490 homepagePreference.setSummary(sharedPreferences.getString("homepage", getString(R.string.homepage_default_value)));
1494 // Update the font size summary text.
1495 fontSizePreference.setSummary(sharedPreferences.getString("font_size", getString(R.string.font_size_default_value)) + "%%");
1498 case "open_intents_in_new_tab":
1500 if (sharedPreferences.getBoolean("open_intents_in_new_tab", true)) {
1502 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_dark);
1504 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_light);
1508 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_dark);
1510 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_light);
1515 case "swipe_to_refresh":
1517 if (sharedPreferences.getBoolean("swipe_to_refresh", true)) {
1519 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_dark);
1521 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_light);
1525 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_dark);
1527 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_light);
1532 case "scroll_app_bar":
1534 if (sharedPreferences.getBoolean("scroll_app_bar", true)) {
1536 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
1538 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
1542 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
1544 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
1549 case "display_additional_app_bar_icons":
1551 if (sharedPreferences.getBoolean("display_additional_app_bar_icons", false)) {
1553 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_dark);
1555 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_light);
1559 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_dark);
1561 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_light);
1566 case "download_with_external_app":
1568 if (sharedPreferences.getBoolean("download_with_external_app", false)) {
1570 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_enabled_dark);
1572 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_enabled_light);
1576 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_disabled_dark);
1578 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_disabled_light);
1585 if (sharedPreferences.getBoolean("dark_theme", false)) {
1586 darkThemePreference.setIcon(R.drawable.theme_dark);
1588 darkThemePreference.setIcon(R.drawable.theme_light);
1591 // Create an intent to restart Privacy Browser.
1592 Intent changeThemeRestartIntent = getActivity().getParentActivityIntent();
1594 // Assert that the intent is not null to remove the lint error below.
1595 assert changeThemeRestartIntent != null;
1597 // `Intent.FLAG_ACTIVITY_CLEAR_TASK` removes all activities from the stack. It requires `Intent.FLAG_ACTIVITY_NEW_TASK`.
1598 changeThemeRestartIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
1600 // Create a handler to restart the activity.
1601 Handler changeThemeRestartHandler = new Handler();
1603 // Create a runnable to restart the activity.
1604 Runnable changeThemeRestartRunnable = () -> {
1605 // Restart the activity.
1606 startActivity(changeThemeRestartIntent);
1608 // Kill this instance of Privacy Browser. Otherwise, the app exhibits sporadic behavior after the restart.
1612 // Restart the activity after 100 milliseconds, so that the app has enough time to save the change to the preference.
1613 changeThemeRestartHandler.postDelayed(changeThemeRestartRunnable, 100);
1617 // Store the current night mode status.
1618 boolean currentNightModeBoolean = sharedPreferences.getBoolean("night_mode", false);
1619 boolean currentJavaScriptBoolean = sharedPreferences.getBoolean("javascript", false);
1622 if (currentNightModeBoolean) {
1624 nightModePreference.setIcon(R.drawable.night_mode_enabled_dark);
1626 nightModePreference.setIcon(R.drawable.night_mode_enabled_light);
1630 nightModePreference.setIcon(R.drawable.night_mode_disabled_dark);
1632 nightModePreference.setIcon(R.drawable.night_mode_disabled_light);
1636 // Update the status of `javaScriptPreference` and `domStoragePreference`.
1637 javaScriptPreference.setEnabled(!currentNightModeBoolean);
1638 domStoragePreference.setEnabled(currentNightModeBoolean || currentJavaScriptBoolean);
1640 // Update the `javaScriptPreference` icon.
1641 if (currentNightModeBoolean || currentJavaScriptBoolean) {
1642 javaScriptPreference.setIcon(R.drawable.javascript_enabled);
1644 javaScriptPreference.setIcon(R.drawable.privacy_mode);
1647 // Update the DOM storage preference icon.
1648 if (currentNightModeBoolean || currentJavaScriptBoolean) { // The preference is enabled.
1649 if (sharedPreferences.getBoolean("dom_storage", false)) { // DOM storage is enabled.
1650 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
1651 } else { // DOM storage is disabled.
1653 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_dark);
1655 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_light);
1658 } else { // The preference is disabled. The icon should be ghosted.
1660 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_dark);
1662 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_light);
1667 case "display_webpage_images":
1668 if (sharedPreferences.getBoolean("display_webpage_images", true)) {
1671 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_dark);
1673 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_light);
1678 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_dark);
1680 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_light);
1687 // Register the listener.
1688 savedPreferences.registerOnSharedPreferenceChangeListener(preferencesListener);
1691 // 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.
1693 public void onPause() {
1695 savedPreferences.unregisterOnSharedPreferenceChangeListener(preferencesListener);
1699 public void onResume() {
1701 savedPreferences.registerOnSharedPreferenceChangeListener(preferencesListener);