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 twitterAmpRedirectsPreference = findPreference("twitter_amp_redirects");
78 Preference proxyThroughOrbotPreference = findPreference("proxy_through_orbot");
79 Preference torHomepagePreference = findPreference("tor_homepage");
80 Preference torSearchPreference = findPreference("tor_search");
81 Preference torSearchCustomURLPreference = findPreference("tor_search_custom_url");
82 Preference searchPreference = findPreference("search");
83 Preference searchCustomURLPreference = findPreference("search_custom_url");
84 Preference fullScreenBrowsingModePreference = findPreference("full_screen_browsing_mode");
85 Preference hideAppBarPreference = findPreference("hide_app_bar");
86 Preference clearEverythingPreference = findPreference("clear_everything");
87 Preference clearCookiesPreference = findPreference("clear_cookies");
88 Preference clearDomStoragePreference = findPreference("clear_dom_storage");
89 Preference clearFormDataPreference = findPreference("clear_form_data"); // The clear form data preference can be removed once the minimum API >= 26.
90 Preference clearCachePreference = findPreference("clear_cache");
91 Preference homepagePreference = findPreference("homepage");
92 Preference fontSizePreference = findPreference("font_size");
93 Preference openIntentsInNewTabPreference = findPreference("open_intents_in_new_tab");
94 Preference swipeToRefreshPreference = findPreference("swipe_to_refresh");
95 Preference scrollAppBarPreference = findPreference("scroll_app_bar");
96 Preference displayAdditionalAppBarIconsPreference = findPreference("display_additional_app_bar_icons");
97 Preference downloadWithExternalAppPreference = findPreference("download_with_external_app");
98 Preference darkThemePreference = findPreference("dark_theme");
99 Preference nightModePreference = findPreference("night_mode");
100 Preference wideViewportPreference = findPreference("wide_viewport");
101 Preference displayWebpageImagesPreference = findPreference("display_webpage_images");
104 torHomepagePreference.setDependency("proxy_through_orbot");
105 torSearchPreference.setDependency("proxy_through_orbot");
106 hideAppBarPreference.setDependency("full_screen_browsing_mode");
108 // Get strings from the preferences.
109 String torSearchString = savedPreferences.getString("tor_search", getString(R.string.tor_search_default_value));
110 String searchString = savedPreferences.getString("search", getString(R.string.search_default_value));
112 // Get booleans that are used in multiple places from the preferences.
113 boolean javaScriptEnabled = savedPreferences.getBoolean("javascript", false);
114 boolean firstPartyCookiesEnabled = savedPreferences.getBoolean("first_party_cookies", false);
115 boolean thirdPartyCookiesEnabled = savedPreferences.getBoolean("third_party_cookies", false);
116 boolean fanboyAnnoyanceListEnabled = savedPreferences.getBoolean("fanboys_annoyance_list", true);
117 boolean fanboySocialBlockingEnabled = savedPreferences.getBoolean("fanboys_social_blocking_list", true);
118 boolean proxyThroughOrbot = savedPreferences.getBoolean("proxy_through_orbot", false);
119 boolean fullScreenBrowsingMode = savedPreferences.getBoolean("full_screen_browsing_mode", false);
120 boolean clearEverything = savedPreferences.getBoolean("clear_everything", true);
121 boolean darkTheme = savedPreferences.getBoolean("dark_theme", false);
122 boolean nightMode = savedPreferences.getBoolean("night_mode", false);
124 // Only enable the third-party cookies preference if first-party cookies are enabled and API >= 21.
125 thirdPartyCookiesPreference.setEnabled(firstPartyCookiesEnabled && (Build.VERSION.SDK_INT >= 21));
127 // Only enable the DOM storage preference if either JavaScript or Night Mode is enabled.
128 domStoragePreference.setEnabled(javaScriptEnabled || nightMode);
130 // Remove the form data preferences if the API is >= 26 as they no longer do anything.
131 if (Build.VERSION.SDK_INT >= 26) {
132 // Get the categories.
133 PreferenceCategory privacyCategory = (PreferenceCategory) findPreference("privacy");
134 PreferenceCategory clearAndExitCategory = (PreferenceCategory) findPreference("clear_and_exit");
136 // Remove the form data preferences.
137 privacyCategory.removePreference(formDataPreference);
138 clearAndExitCategory.removePreference(clearFormDataPreference);
141 // Only enable Fanboy's social blocking list preference if Fanboy's annoyance list is disabled.
142 fanboySocialBlockingListPreference.setEnabled(!fanboyAnnoyanceListEnabled);
144 // Inflate a WebView to get the default user agent.
145 LayoutInflater inflater = getActivity().getLayoutInflater();
146 // `@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.
147 @SuppressLint("InflateParams") View bareWebViewLayout = inflater.inflate(R.layout.bare_webview, null, false);
148 WebView bareWebView = bareWebViewLayout.findViewById(R.id.bare_webview);
150 // Get the user agent arrays.
151 ArrayAdapter<CharSequence> userAgentNamesArray = ArrayAdapter.createFromResource(context, R.array.user_agent_names, R.layout.spinner_item);
152 String[] translatedUserAgentNamesArray = getResources().getStringArray(R.array.translated_user_agent_names);
153 String[] userAgentDataArray = getResources().getStringArray(R.array.user_agent_data);
155 // Get the current user agent name from the preference.
156 String userAgentName = savedPreferences.getString("user_agent", getString(R.string.user_agent_default_value));
158 // Get the array position of the user agent name.
159 int userAgentArrayPosition = userAgentNamesArray.getPosition(userAgentName);
161 // Populate the user agent summary.
162 switch (userAgentArrayPosition) {
163 case MainWebViewActivity.UNRECOGNIZED_USER_AGENT: // The user agent name is not on the canonical list.
164 // 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.
165 userAgentPreference.setSummary(userAgentName);
168 case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
169 // Get the user agent text from the webview (which changes based on the version of Android and WebView installed).
170 userAgentPreference.setSummary(translatedUserAgentNamesArray[userAgentArrayPosition] + ":\n" + bareWebView.getSettings().getUserAgentString());
173 case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
174 // Set the summary text.
175 userAgentPreference.setSummary(R.string.custom_user_agent);
179 // Get the user agent summary from the user agent data array.
180 userAgentPreference.setSummary(translatedUserAgentNamesArray[userAgentArrayPosition] + ":\n" + userAgentDataArray[userAgentArrayPosition]);
183 // Set the summary text for the custom user agent preference and enable it if user agent preference is set to custom.
184 customUserAgentPreference.setSummary(savedPreferences.getString("custom_user_agent", getString(R.string.custom_user_agent_default_value)));
185 customUserAgentPreference.setEnabled(userAgentPreference.getSummary().equals(getString(R.string.custom_user_agent)));
188 // 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/`.
189 torHomepagePreference.setSummary(savedPreferences.getString("tor_homepage", getString(R.string.tor_homepage_default_value)));
192 // Set the Tor search URL as the summary text for the Tor preference when the preference screen is loaded.
193 if (torSearchString.equals("Custom URL")) {
194 // Use R.string.custom_url, which will be translated, instead of the array value, which will not.
195 torSearchPreference.setSummary(R.string.custom_url);
197 // Set the array value as the summary text.
198 torSearchPreference.setSummary(torSearchString);
201 // Set the summary text for `tor_search_custom_url`. The default is `""`.
202 torSearchCustomURLPreference.setSummary(savedPreferences.getString("tor_search_custom_url", getString(R.string.tor_search_custom_url_default_value)));
204 // Enable the Tor custom URL search options only if proxying through Orbot and the search is set to `Custom URL`.
205 torSearchCustomURLPreference.setEnabled(proxyThroughOrbot && torSearchString.equals("Custom URL"));
208 // Set the search URL as the summary text for the search preference when the preference screen is loaded.
209 if (searchString.equals("Custom URL")) {
210 // Use R.string.custom_url, which will be translated, instead of the array value, which will not.
211 searchPreference.setSummary(R.string.custom_url);
213 // Set the array value as the summary text.
214 searchPreference.setSummary(searchString);
217 // Set the summary text for `search_custom_url` (the default is `""`) and enable it if `search` is set to `Custom URL`.
218 searchCustomURLPreference.setSummary(savedPreferences.getString("search_custom_url", getString(R.string.search_custom_url_default_value)));
219 searchCustomURLPreference.setEnabled(searchString.equals("Custom URL"));
221 // Set the status of the Clear and Exit preferences.
222 clearCookiesPreference.setEnabled(!clearEverything);
223 clearDomStoragePreference.setEnabled(!clearEverything);
224 clearFormDataPreference.setEnabled(!clearEverything); // The form data line can be removed once the minimum API is >= 26.
225 clearCachePreference.setEnabled(!clearEverything);
227 // Set the homepage URL as the summary text for the homepage preference.
228 homepagePreference.setSummary(savedPreferences.getString("homepage", getString(R.string.homepage_default_value)));
230 // Set the font size as the summary text for the preference.
231 fontSizePreference.setSummary(savedPreferences.getString("font_size", getString(R.string.font_size_default_value)) + "%%");
233 // Disable the JavaScript preference if Night Mode is enabled. JavaScript will be enabled for all web pages.
234 javaScriptPreference.setEnabled(!nightMode);
236 // Set the JavaScript icon.
237 if (javaScriptEnabled || nightMode) {
238 javaScriptPreference.setIcon(R.drawable.javascript_enabled);
240 javaScriptPreference.setIcon(R.drawable.privacy_mode);
243 // Set the first-party cookies icon.
244 if (firstPartyCookiesEnabled) {
245 firstPartyCookiesPreference.setIcon(R.drawable.cookies_enabled);
248 firstPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
250 firstPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
254 // Set the third party cookies icon.
255 if (firstPartyCookiesEnabled && Build.VERSION.SDK_INT >= 21) {
256 if (thirdPartyCookiesEnabled) {
257 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_warning);
260 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
262 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
267 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_dark);
269 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_light);
273 // Set the DOM storage icon.
274 if (javaScriptEnabled || nightMode) { // The preference is enabled.
275 if (savedPreferences.getBoolean("dom_storage", false)) { // DOM storage is enabled.
276 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
277 } else { // DOM storage is disabled.
279 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_dark);
281 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_light);
284 } else { // The preference is disabled. The icon should be ghosted.
286 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_dark);
288 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_light);
292 // Set the save form data icon if API < 26. Save form data has no effect on API >= 26.
293 if (Build.VERSION.SDK_INT < 26) {
294 if (savedPreferences.getBoolean("save_form_data", false)) {
295 formDataPreference.setIcon(R.drawable.form_data_enabled);
298 formDataPreference.setIcon(R.drawable.form_data_disabled_dark);
300 formDataPreference.setIcon(R.drawable.form_data_disabled_light);
305 // Set the custom user agent icon.
306 if (customUserAgentPreference.isEnabled()) {
308 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_dark);
310 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_light);
314 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_dark);
316 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_light);
320 // Set the incognito mode icon.
321 if (savedPreferences.getBoolean("incognito_mode", false)) {
323 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_dark);
325 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_light);
329 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_dark);
331 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_light);
335 // Set the Do Not Track icon.
336 if (savedPreferences.getBoolean("do_not_track", false)) {
338 doNotTrackPreference.setIcon(R.drawable.block_tracking_enabled_dark);
340 doNotTrackPreference.setIcon(R.drawable.block_tracking_enabled_light);
344 doNotTrackPreference.setIcon(R.drawable.block_tracking_disabled_dark);
346 doNotTrackPreference.setIcon(R.drawable.block_tracking_disabled_light);
350 // Set the allow screenshots icon.
351 if (savedPreferences.getBoolean("allow_screenshots", false)) {
353 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_dark);
355 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_light);
359 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_dark);
361 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_light);
365 // Set the EasyList icon.
366 if (savedPreferences.getBoolean("easylist", true)) {
368 easyListPreference.setIcon(R.drawable.block_ads_enabled_dark);
370 easyListPreference.setIcon(R.drawable.block_ads_enabled_light);
374 easyListPreference.setIcon(R.drawable.block_ads_disabled_dark);
376 easyListPreference.setIcon(R.drawable.block_ads_disabled_light);
380 // Set the EasyPrivacy icon.
381 if (savedPreferences.getBoolean("easyprivacy", true)) {
383 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_dark);
385 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_light);
389 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_dark);
391 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_light);
395 // Set the Fanboy lists icons.
396 if (fanboyAnnoyanceListEnabled) {
398 // Set the Fanboy annoyance list icon.
399 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_dark);
401 // Set the Fanboy social blocking list icon.
402 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_dark);
404 // Set the Fanboy annoyance list icon.
405 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_light);
407 // Set the Fanboy social blocking list icon.
408 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_light);
412 // Set the Fanboy annoyance list icon.
413 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled_dark);
415 // Set the Fanboy social blocking list icon.
416 if (fanboySocialBlockingEnabled) {
417 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_dark);
419 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_dark);
422 // Set the Fanboy annoyance list icon.
423 fanboyAnnoyanceListPreference.setIcon(R.drawable.block_ads_disabled_light);
425 // Set the Fanboy social blocking list icon.
426 if (fanboySocialBlockingEnabled) {
427 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_light);
429 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_light);
434 // Set the UltraPrivacy icon.
435 if (savedPreferences.getBoolean("ultraprivacy", true)) {
437 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_dark);
439 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_light);
443 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_dark);
445 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_light);
449 // Set the block all third-party requests icon.
450 if (savedPreferences.getBoolean("block_all_third_party_requests", false)) {
452 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_dark);
454 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_light);
458 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_dark);
460 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_light);
464 // Set the Google Analytics icon according to the theme.
465 if (savedPreferences.getBoolean("google_analytics", true)) {
467 googleAnalyticsPreference.setIcon(R.drawable.modify_url_enabled_dark);
469 googleAnalyticsPreference.setIcon(R.drawable.modify_url_enabled_light);
473 googleAnalyticsPreference.setIcon(R.drawable.modify_url_disabled_dark);
475 googleAnalyticsPreference.setIcon(R.drawable.modify_url_disabled_light);
479 // Set the Facebook Click IDs icon according to the theme.
480 if (savedPreferences.getBoolean("facebook_click_ids", true)) {
482 facebookClickIdsPreference.setIcon(R.drawable.modify_url_enabled_dark);
484 facebookClickIdsPreference.setIcon(R.drawable.modify_url_enabled_light);
488 facebookClickIdsPreference.setIcon(R.drawable.modify_url_disabled_dark);
490 facebookClickIdsPreference.setIcon(R.drawable.modify_url_disabled_light);
494 // Set the Twitter AMP redirects icon according to the theme.
495 if (savedPreferences.getBoolean("twitter_amp_redirects", true)) {
497 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_enabled_dark);
499 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_enabled_light);
503 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_disabled_dark);
505 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_disabled_light);
509 // Set the Tor icons according to the theme.
510 if (proxyThroughOrbot) { // Proxying is enabled.
512 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_enabled_dark);
513 torHomepagePreference.setIcon(R.drawable.home_enabled_dark);
514 torSearchPreference.setIcon(R.drawable.search_enabled_dark);
516 // Set the custom search icon.
517 if (torSearchCustomURLPreference.isEnabled()) {
518 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_dark);
520 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
523 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_enabled_light);
524 torHomepagePreference.setIcon(R.drawable.home_enabled_light);
525 torSearchPreference.setIcon(R.drawable.search_enabled_light);
527 // Set the custom search icon.
528 if (torSearchCustomURLPreference.isEnabled()) {
529 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_light);
531 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
534 } else { // Proxying is disabled.
536 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_disabled_dark);
537 torHomepagePreference.setIcon(R.drawable.home_ghosted_dark);
538 torSearchPreference.setIcon(R.drawable.search_ghosted_dark);
539 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
541 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_disabled_light);
542 torHomepagePreference.setIcon(R.drawable.home_ghosted_light);
543 torSearchPreference.setIcon(R.drawable.search_ghosted_light);
544 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
548 // Set the search custom URL icon.
549 if (searchCustomURLPreference.isEnabled()) {
551 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_dark);
553 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_light);
557 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
559 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
563 // Set the full screen browsing mode icons.
564 if (fullScreenBrowsingMode) { // Full screen browsing mode is enabled.
565 // Set the `fullScreenBrowsingModePreference` icon according to the theme.
567 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_dark);
569 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_light);
572 // Set the hide app bar icon.
573 if (savedPreferences.getBoolean("hide_app_bar", true)) { // Hide app bar is enabled.
574 // Set the icon according to the theme.
576 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
578 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
580 } else { // Hide app bar is disabled.
581 // Set the icon according to the theme.
583 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
585 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
588 } else { // Full screen browsing mode is disabled.
589 // Set the icons according to the theme.
591 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_dark);
592 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_dark);
594 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_light);
595 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_light);
599 // Set the clear everything preference icon.
600 if (clearEverything) {
602 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_dark);
604 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_light);
607 clearEverythingPreference.setIcon(R.drawable.clear_everything_disabled);
610 // Set the clear cookies preference icon.
611 if (clearEverything || savedPreferences.getBoolean("clear_cookies", true)) {
613 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_dark);
615 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_light);
618 clearCookiesPreference.setIcon(R.drawable.cookies_warning);
621 // Set the clear DOM storage preference icon.
622 if (clearEverything || savedPreferences.getBoolean("clear_dom_storage", true)) {
624 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_dark);
626 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_light);
629 clearDomStoragePreference.setIcon(R.drawable.dom_storage_warning);
632 // Set the clear form data preference icon if the API < 26. It has no effect on newer versions of Android.
633 if (Build.VERSION.SDK_INT < 26) {
634 if (clearEverything || savedPreferences.getBoolean("clear_form_data", true)) {
636 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_dark);
638 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_light);
641 clearFormDataPreference.setIcon(R.drawable.form_data_warning);
645 // Set the clear cache preference icon.
646 if (clearEverything || savedPreferences.getBoolean("clear_cache", true)) {
648 clearCachePreference.setIcon(R.drawable.cache_cleared_dark);
650 clearCachePreference.setIcon(R.drawable.cache_cleared_light);
653 clearCachePreference.setIcon(R.drawable.cache_warning);
656 // Set the open intents in new tab preference icon.
657 if (savedPreferences.getBoolean("open_intents_in_new_tab", true)) {
659 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_dark);
661 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_light);
665 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_dark);
667 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_light);
671 // Set the swipe to refresh preference icon.
672 if (savedPreferences.getBoolean("swipe_to_refresh", true)) {
674 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_dark);
676 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_light);
680 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_dark);
682 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_light);
686 // Set the scroll app bar preference icon.
687 if (savedPreferences.getBoolean("scroll_app_bar", true)) {
689 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
691 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
695 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
697 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
701 // Set the display additional app bar icons preference icon.
702 if (savedPreferences.getBoolean("display_additional_app_bar_icons", false)) {
704 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_dark);
706 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_light);
710 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_dark);
712 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_light);
716 // Set the download with external app preference icon.
717 if (savedPreferences.getBoolean("download_with_external_app", false)) {
719 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_enabled_dark);
721 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_enabled_light);
725 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_disabled_dark);
727 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_disabled_light);
731 // Set the dark theme preference icon.
732 if (savedPreferences.getBoolean("dark_theme", false)) {
733 darkThemePreference.setIcon(R.drawable.theme_dark);
735 darkThemePreference.setIcon(R.drawable.theme_light);
738 // Set the night mode preference icon.
741 nightModePreference.setIcon(R.drawable.night_mode_enabled_dark);
743 nightModePreference.setIcon(R.drawable.night_mode_enabled_light);
747 nightModePreference.setIcon(R.drawable.night_mode_disabled_dark);
749 nightModePreference.setIcon(R.drawable.night_mode_disabled_light);
753 // Set the wide viewport preference icon.
754 if (savedPreferences.getBoolean("wide_viewport", true)) {
756 wideViewportPreference.setIcon(R.drawable.wide_viewport_enabled_dark);
758 wideViewportPreference.setIcon(R.drawable.wide_viewport_enabled_light);
762 wideViewportPreference.setIcon(R.drawable.wide_viewport_disabled_dark);
764 wideViewportPreference.setIcon(R.drawable.wide_viewport_disabled_light);
768 // Set the display webpage images preference icon.
769 if (savedPreferences.getBoolean("display_webpage_images", true)) {
771 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_dark);
773 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_light);
777 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_dark);
779 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_light);
784 // Listen for preference changes.
785 preferencesListener = (SharedPreferences sharedPreferences, String key) -> {
788 // Update the icons and the DOM storage preference status.
789 if (sharedPreferences.getBoolean("javascript", false)) { // The JavaScript preference is enabled.
790 // Update the icon for the JavaScript preference.
791 javaScriptPreference.setIcon(R.drawable.javascript_enabled);
793 // Update the status of the DOM storage preference.
794 domStoragePreference.setEnabled(true);
796 // Update the icon for the DOM storage preference.
797 if (sharedPreferences.getBoolean("dom_storage", false)) {
798 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
801 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_dark);
803 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_light);
806 } else { // The JavaScript preference is disabled.
807 // Update the icon for the JavaScript preference.
808 javaScriptPreference.setIcon(R.drawable.privacy_mode);
810 // Update the status of the DOM storage preference.
811 domStoragePreference.setEnabled(false);
813 // Set the icon for DOM storage preference to be ghosted.
815 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_dark);
817 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_light);
822 case "first_party_cookies":
823 // Update the icons for `first_party_cookies` and `third_party_cookies`.
824 if (sharedPreferences.getBoolean("first_party_cookies", false)) {
825 // Set the icon for `first_party_cookies`.
826 firstPartyCookiesPreference.setIcon(R.drawable.cookies_enabled);
828 // Update the icon for `third_party_cookies`.
829 if (Build.VERSION.SDK_INT >= 21) {
830 if (sharedPreferences.getBoolean("third_party_cookies", false)) {
831 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_warning);
834 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
836 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
841 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_dark);
843 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_light);
846 } else { // `first_party_cookies` is `false`.
847 // Update the icon for `first_party_cookies`.
849 firstPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
851 firstPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
854 // Set the icon for `third_party_cookies` to be ghosted.
856 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_dark);
858 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_light);
862 // Enable `third_party_cookies` if `first_party_cookies` is `true` and API >= 21.
863 thirdPartyCookiesPreference.setEnabled(sharedPreferences.getBoolean("first_party_cookies", false) && (Build.VERSION.SDK_INT >= 21));
866 case "third_party_cookies":
868 if (sharedPreferences.getBoolean("third_party_cookies", false)) {
869 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_warning);
872 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
874 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
881 if (sharedPreferences.getBoolean("dom_storage", false)) {
882 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
885 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_dark);
887 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_light);
892 // Save form data can be removed once the minimum API >= 26.
893 case "save_form_data":
895 if (sharedPreferences.getBoolean("save_form_data", false)) {
896 formDataPreference.setIcon(R.drawable.form_data_enabled);
899 formDataPreference.setIcon(R.drawable.form_data_disabled_dark);
901 formDataPreference.setIcon(R.drawable.form_data_disabled_light);
907 // Get the new user agent name.
908 String newUserAgentName = sharedPreferences.getString("user_agent", getString(R.string.user_agent_default_value));
910 // Get the array position for the new user agent name.
911 int newUserAgentArrayPosition = userAgentNamesArray.getPosition(newUserAgentName);
913 // Get the translated new user agent name.
914 String translatedNewUserAgentName = translatedUserAgentNamesArray[newUserAgentArrayPosition];
916 // Populate the user agent summary.
917 switch (newUserAgentArrayPosition) {
918 case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
919 // Get the user agent text from the webview (which changes based on the version of Android and WebView installed).
920 userAgentPreference.setSummary(translatedNewUserAgentName + ":\n" + bareWebView.getSettings().getUserAgentString());
922 // Disable the custom user agent preference.
923 customUserAgentPreference.setEnabled(false);
925 // Set the custom user agent preference icon according to the theme.
927 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_dark);
929 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_light);
933 case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
934 // Set the summary text.
935 userAgentPreference.setSummary(R.string.custom_user_agent);
937 // Enable the custom user agent preference.
938 customUserAgentPreference.setEnabled(true);
940 // Set the custom user agent preference icon according to the theme.
942 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_dark);
944 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_light);
949 // Get the user agent summary from the user agent data array.
950 userAgentPreference.setSummary(translatedNewUserAgentName + ":\n" + userAgentDataArray[newUserAgentArrayPosition]);
952 // Disable the custom user agent preference.
953 customUserAgentPreference.setEnabled(false);
955 // Set the custom user agent preference icon according to the theme.
957 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_dark);
959 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_light);
964 case "custom_user_agent":
965 // Set the new custom user agent as the summary text for the preference.
966 customUserAgentPreference.setSummary(sharedPreferences.getString("custom_user_agent", getString(R.string.custom_user_agent_default_value)));
969 case "incognito_mode":
971 if (sharedPreferences.getBoolean("incognito_mode", false)) {
973 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_dark);
975 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_light);
979 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_dark);
981 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_light);
988 if (sharedPreferences.getBoolean("do_not_track", false)) {
990 doNotTrackPreference.setIcon(R.drawable.block_tracking_enabled_dark);
992 doNotTrackPreference.setIcon(R.drawable.block_tracking_enabled_light);
996 doNotTrackPreference.setIcon(R.drawable.block_tracking_disabled_dark);
998 doNotTrackPreference.setIcon(R.drawable.block_tracking_disabled_light);
1004 case "allow_screenshots":
1006 if (sharedPreferences.getBoolean("allow_screenshots", false)) {
1008 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_dark);
1010 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_light);
1014 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_dark);
1016 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_light);
1020 // Create an intent to restart Privacy Browser.
1021 Intent allowScreenshotsRestartIntent = getActivity().getParentActivityIntent();
1023 // Assert that the intent is not null to remove the lint error below.
1024 assert allowScreenshotsRestartIntent != null;
1026 // `Intent.FLAG_ACTIVITY_CLEAR_TASK` removes all activities from the stack. It requires `Intent.FLAG_ACTIVITY_NEW_TASK`.
1027 allowScreenshotsRestartIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
1029 // Create a handler to restart the activity.
1030 Handler allowScreenshotsRestartHandler = new Handler();
1032 // Create a runnable to restart the activity.
1033 Runnable allowScreenshotsRestartRunnable = () -> {
1034 // Restart the activity.
1035 startActivity(allowScreenshotsRestartIntent);
1037 // Kill this instance of Privacy Browser. Otherwise, the app exhibits sporadic behavior after the restart.
1041 // Restart the activity after 150 milliseconds, so that the app has enough time to save the change to the preference.
1042 allowScreenshotsRestartHandler.postDelayed(allowScreenshotsRestartRunnable, 150);
1047 if (sharedPreferences.getBoolean("easylist", true)) {
1049 easyListPreference.setIcon(R.drawable.block_ads_enabled_dark);
1051 easyListPreference.setIcon(R.drawable.block_ads_enabled_light);
1055 easyListPreference.setIcon(R.drawable.block_ads_disabled_dark);
1057 easyListPreference.setIcon(R.drawable.block_ads_disabled_light);
1064 if (sharedPreferences.getBoolean("easyprivacy", true)) {
1066 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_dark);
1068 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_light);
1072 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_dark);
1074 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_light);
1079 case "fanboys_annoyance_list":
1080 boolean currentFanboyAnnoyanceList = sharedPreferences.getBoolean("fanboys_annoyance_list", true);
1081 boolean currentFanboySocialBlockingList = sharedPreferences.getBoolean("fanboys_social_blocking_list", true);
1083 // Update the Fanboy icons.
1084 if (currentFanboyAnnoyanceList) { // Fanboy's annoyance list is enabled.
1086 // Update the Fanboy's annoyance list icon.
1087 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_dark);
1089 // Update the Fanboy's social blocking list icon.
1090 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_dark);
1092 // Update the Fanboy's annoyance list icon.
1093 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_light);
1095 // Update the Fanboy's social blocking list icon.
1096 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_light);
1098 } else { // Fanboy's annoyance list is disabled.
1100 // Update the Fanboy's annoyance list icon.
1101 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled_dark);
1103 // Update the Fanboy's social blocking list icon.
1104 if (currentFanboySocialBlockingList) {
1105 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_dark);
1107 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_dark);
1110 // Update the Fanboy's annoyance list icon.
1111 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled_light);
1113 // Update the Fanboy's social blocking list icon.
1114 if (currentFanboySocialBlockingList) {
1115 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_light);
1117 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_light);
1122 // Only enable Fanboy's social blocking list preference if Fanboy's annoyance list preference is disabled.
1123 fanboySocialBlockingListPreference.setEnabled(!currentFanboyAnnoyanceList);
1126 case "fanboys_social_blocking_list":
1128 if (sharedPreferences.getBoolean("fanboys_social_blocking_list", true)) {
1130 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_dark);
1132 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_light);
1136 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_dark);
1138 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_light);
1143 case "ultraprivacy":
1145 if (sharedPreferences.getBoolean("ultraprivacy", true)) {
1147 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_dark);
1149 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_light);
1153 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_dark);
1155 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_light);
1160 case "block_all_third_party_requests":
1162 if (sharedPreferences.getBoolean("block_all_third_party_requests", false)) {
1164 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_dark);
1166 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_light);
1170 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_dark);
1172 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_light);
1177 case "google_analytics":
1179 if (sharedPreferences.getBoolean("google_analytics", true)) {
1181 googleAnalyticsPreference.setIcon(R.drawable.modify_url_enabled_dark);
1183 googleAnalyticsPreference.setIcon(R.drawable.modify_url_enabled_light);
1187 googleAnalyticsPreference.setIcon(R.drawable.modify_url_disabled_dark);
1189 googleAnalyticsPreference.setIcon(R.drawable.modify_url_disabled_light);
1194 case "facebook_click_ids":
1196 if (sharedPreferences.getBoolean("facebook_click_ids", true)) {
1198 facebookClickIdsPreference.setIcon(R.drawable.modify_url_enabled_dark);
1200 facebookClickIdsPreference.setIcon(R.drawable.modify_url_enabled_light);
1204 facebookClickIdsPreference.setIcon(R.drawable.modify_url_disabled_dark);
1206 facebookClickIdsPreference.setIcon(R.drawable.modify_url_disabled_light);
1211 case "twitter_amp_redirects":
1213 if (sharedPreferences.getBoolean("twitter_amp_redirects", true)) {
1215 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_enabled_dark);
1217 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_enabled_light);
1221 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_disabled_dark);
1223 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_disabled_light);
1228 case "proxy_through_orbot":
1229 // Get current settings.
1230 boolean currentProxyThroughOrbot = sharedPreferences.getBoolean("proxy_through_orbot", false);
1231 String currentTorSearchString = sharedPreferences.getString("tor_search", getString(R.string.tor_search_default_value));
1233 // Enable the Tor custom URL search option only if `currentProxyThroughOrbot` is true and the search is set to `Custom URL`.
1234 torSearchCustomURLPreference.setEnabled(currentProxyThroughOrbot && currentTorSearchString.equals("Custom URL"));
1236 // Update the icons.
1237 if (currentProxyThroughOrbot) {
1238 // Set the Tor icons according to the theme.
1240 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_enabled_dark);
1241 torHomepagePreference.setIcon(R.drawable.home_enabled_dark);
1242 torSearchPreference.setIcon(R.drawable.search_enabled_dark);
1244 // Set the `torSearchCustomURLPreference` icon.
1245 if (torSearchCustomURLPreference.isEnabled()) {
1246 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_dark);
1248 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
1251 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_enabled_light);
1252 torHomepagePreference.setIcon(R.drawable.home_enabled_light);
1253 torSearchPreference.setIcon(R.drawable.search_enabled_light);
1255 // Set the `torSearchCustomURLPreference` icon.
1256 if (torSearchCustomURLPreference.isEnabled()) {
1257 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_light);
1259 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
1262 } else { // Proxy through Orbot is disabled.
1264 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_disabled_dark);
1265 torHomepagePreference.setIcon(R.drawable.home_ghosted_dark);
1266 torSearchPreference.setIcon(R.drawable.search_ghosted_dark);
1267 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
1269 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_disabled_light);
1270 torHomepagePreference.setIcon(R.drawable.home_ghosted_light);
1271 torSearchPreference.setIcon(R.drawable.search_ghosted_light);
1272 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
1277 case "tor_homepage":
1278 // Set the new tor homepage URL as the summary text for the `tor_homepage` preference. The default is Searx: `http://ulrn6sryqaifefld.onion/`.
1279 torHomepagePreference.setSummary(sharedPreferences.getString("tor_homepage", getString(R.string.tor_homepage_default_value)));
1283 // Get the present search string.
1284 String presentTorSearchString = sharedPreferences.getString("tor_search", getString(R.string.tor_search_default_value));
1286 // Update the preferences.
1287 if (presentTorSearchString.equals("Custom URL")) {
1288 // Use `R.string.custom_url`, which is translated, as the summary instead of the array value, which isn't.
1289 torSearchPreference.setSummary(R.string.custom_url);
1291 // Enable `torSearchCustomURLPreference`.
1292 torSearchCustomURLPreference.setEnabled(true);
1294 // Update the `torSearchCustomURLPreference` icon.
1296 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_dark);
1298 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_light);
1301 // Set the array value as the summary text.
1302 torSearchPreference.setSummary(presentTorSearchString);
1304 // Disable `torSearchCustomURLPreference`.
1305 torSearchCustomURLPreference.setEnabled(false);
1307 // Update the `torSearchCustomURLPreference` icon.
1309 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
1311 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
1316 case "tor_search_custom_url":
1317 // Set the summary text for `tor_search_custom_url`.
1318 torSearchCustomURLPreference.setSummary(sharedPreferences.getString("tor_search_custom_url", getString(R.string.tor_search_custom_url_default_value)));
1322 // Store the new search string.
1323 String newSearchString = sharedPreferences.getString("search", getString(R.string.search_default_value));
1325 // Update `searchPreference` and `searchCustomURLPreference`.
1326 if (newSearchString.equals("Custom URL")) { // `Custom URL` is selected.
1327 // Set the summary text to `R.string.custom_url`, which is translated.
1328 searchPreference.setSummary(R.string.custom_url);
1330 // Enable `searchCustomURLPreference`.
1331 searchCustomURLPreference.setEnabled(true);
1333 // Set the `searchCustomURLPreference` according to the theme.
1335 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_dark);
1337 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_light);
1339 } else { // `Custom URL` is not selected.
1340 // Set the summary text to `newSearchString`.
1341 searchPreference.setSummary(newSearchString);
1343 // Disable `searchCustomURLPreference`.
1344 searchCustomURLPreference.setEnabled(false);
1346 // Set the `searchCustomURLPreference` according to the theme.
1348 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
1350 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
1355 case "search_custom_url":
1356 // Set the new custom search URL as the summary text for `search_custom_url`. The default is `""`.
1357 searchCustomURLPreference.setSummary(sharedPreferences.getString("search_custom_url", getString(R.string.search_custom_url_default_value)));
1360 case "full_screen_browsing_mode":
1361 if (sharedPreferences.getBoolean("full_screen_browsing_mode", false)) { // Full screen browsing is enabled.
1362 // Set the full screen browsing mode preference icon according to the theme.
1364 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_dark);
1366 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_light);
1369 // Set the hide app bar preference icon.
1370 if (sharedPreferences.getBoolean("hide_app_bar", true)) { // Hide app bar is enabled.
1371 // Set the icon according to the theme.
1373 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
1375 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
1377 } else { // Hide app bar is disabled.
1378 // Set the icon according to the theme.
1380 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
1382 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
1385 } else { // Full screen browsing is disabled.
1386 // Update the icons according to the theme.
1388 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_dark);
1389 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_dark);
1391 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_light);
1392 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_light);
1397 case "hide_app_bar":
1399 if (sharedPreferences.getBoolean("hide_app_bar", true)) { // Hide app bar is enabled.
1400 // Set the icon according to the theme.
1402 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
1404 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
1406 } else { // Hide app bar is disabled.
1407 // Set the icon according to the theme.
1409 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
1411 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
1416 case "clear_everything":
1417 // Store the new `clear_everything` status
1418 boolean newClearEverythingBoolean = sharedPreferences.getBoolean("clear_everything", true);
1420 // Update the status of the `Clear and Exit` preferences.
1421 clearCookiesPreference.setEnabled(!newClearEverythingBoolean);
1422 clearDomStoragePreference.setEnabled(!newClearEverythingBoolean);
1423 clearFormDataPreference.setEnabled(!newClearEverythingBoolean); // This line can be removed once the minimum API >= 26.
1424 clearCachePreference.setEnabled(!newClearEverythingBoolean);
1426 // Update the `clearEverythingPreference` icon.
1427 if (newClearEverythingBoolean) {
1429 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_dark);
1431 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_light);
1434 clearEverythingPreference.setIcon(R.drawable.clear_everything_disabled);
1437 // Update the `clearCookiesPreference` icon.
1438 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_cookies", true)) {
1440 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_dark);
1442 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_light);
1445 clearCookiesPreference.setIcon(R.drawable.cookies_warning);
1448 // Update the `clearDomStoragePreference` icon.
1449 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_dom_storage", true)) {
1451 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_dark);
1453 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_light);
1456 clearDomStoragePreference.setIcon(R.drawable.dom_storage_warning);
1459 // Update the clear form data preference icon if the API < 26.
1460 if (Build.VERSION.SDK_INT < 26) {
1461 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_form_data", true)) {
1463 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_dark);
1465 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_light);
1468 clearFormDataPreference.setIcon(R.drawable.form_data_warning);
1472 // Update the `clearCachePreference` icon.
1473 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_cache", true)) {
1475 clearCachePreference.setIcon(R.drawable.cache_cleared_dark);
1477 clearCachePreference.setIcon(R.drawable.cache_cleared_light);
1480 clearCachePreference.setIcon(R.drawable.cache_warning);
1484 case "clear_cookies":
1486 if (sharedPreferences.getBoolean("clear_cookies", true)) {
1488 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_dark);
1490 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_light);
1493 clearCookiesPreference.setIcon(R.drawable.cookies_warning);
1497 case "clear_dom_storage":
1499 if (sharedPreferences.getBoolean("clear_dom_storage", true)) {
1501 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_dark);
1503 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_light);
1506 clearDomStoragePreference.setIcon(R.drawable.dom_storage_warning);
1510 // This section can be removed once the minimum API >= 26.
1511 case "clear_form_data":
1513 if (sharedPreferences.getBoolean("clear_form_data", true)) {
1515 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_dark);
1517 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_light);
1520 clearFormDataPreference.setIcon(R.drawable.form_data_warning);
1526 if (sharedPreferences.getBoolean("clear_cache", true)) {
1528 clearCachePreference.setIcon(R.drawable.cache_cleared_dark);
1530 clearCachePreference.setIcon(R.drawable.cache_cleared_light);
1533 clearCachePreference.setIcon(R.drawable.cache_warning);
1538 // Set the new homepage URL as the summary text for the Homepage preference.
1539 homepagePreference.setSummary(sharedPreferences.getString("homepage", getString(R.string.homepage_default_value)));
1543 // Update the font size summary text.
1544 fontSizePreference.setSummary(sharedPreferences.getString("font_size", getString(R.string.font_size_default_value)) + "%%");
1547 case "open_intents_in_new_tab":
1549 if (sharedPreferences.getBoolean("open_intents_in_new_tab", true)) {
1551 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_dark);
1553 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_light);
1557 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_dark);
1559 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_light);
1564 case "swipe_to_refresh":
1566 if (sharedPreferences.getBoolean("swipe_to_refresh", true)) {
1568 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_dark);
1570 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_light);
1574 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_dark);
1576 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_light);
1581 case "scroll_app_bar":
1583 if (sharedPreferences.getBoolean("scroll_app_bar", true)) {
1585 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
1587 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
1591 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
1593 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
1598 case "display_additional_app_bar_icons":
1600 if (sharedPreferences.getBoolean("display_additional_app_bar_icons", false)) {
1602 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_dark);
1604 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_light);
1608 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_dark);
1610 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_light);
1615 case "download_with_external_app":
1617 if (sharedPreferences.getBoolean("download_with_external_app", false)) {
1619 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_enabled_dark);
1621 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_enabled_light);
1625 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_disabled_dark);
1627 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_disabled_light);
1634 if (sharedPreferences.getBoolean("dark_theme", false)) {
1635 darkThemePreference.setIcon(R.drawable.theme_dark);
1637 darkThemePreference.setIcon(R.drawable.theme_light);
1640 // Create an intent to restart Privacy Browser.
1641 Intent changeThemeRestartIntent = getActivity().getParentActivityIntent();
1643 // Assert that the intent is not null to remove the lint error below.
1644 assert changeThemeRestartIntent != null;
1646 // `Intent.FLAG_ACTIVITY_CLEAR_TASK` removes all activities from the stack. It requires `Intent.FLAG_ACTIVITY_NEW_TASK`.
1647 changeThemeRestartIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
1649 // Create a handler to restart the activity.
1650 Handler changeThemeRestartHandler = new Handler();
1652 // Create a runnable to restart the activity.
1653 Runnable changeThemeRestartRunnable = () -> {
1654 // Restart the activity.
1655 startActivity(changeThemeRestartIntent);
1657 // Kill this instance of Privacy Browser. Otherwise, the app exhibits sporadic behavior after the restart.
1661 // Restart the activity after 150 milliseconds, so that the app has enough time to save the change to the preference.
1662 changeThemeRestartHandler.postDelayed(changeThemeRestartRunnable, 150);
1666 // Store the current night mode status.
1667 boolean currentNightModeBoolean = sharedPreferences.getBoolean("night_mode", false);
1668 boolean currentJavaScriptBoolean = sharedPreferences.getBoolean("javascript", false);
1671 if (currentNightModeBoolean) {
1673 nightModePreference.setIcon(R.drawable.night_mode_enabled_dark);
1675 nightModePreference.setIcon(R.drawable.night_mode_enabled_light);
1679 nightModePreference.setIcon(R.drawable.night_mode_disabled_dark);
1681 nightModePreference.setIcon(R.drawable.night_mode_disabled_light);
1685 // Update the status of `javaScriptPreference` and `domStoragePreference`.
1686 javaScriptPreference.setEnabled(!currentNightModeBoolean);
1687 domStoragePreference.setEnabled(currentNightModeBoolean || currentJavaScriptBoolean);
1689 // Update the `javaScriptPreference` icon.
1690 if (currentNightModeBoolean || currentJavaScriptBoolean) {
1691 javaScriptPreference.setIcon(R.drawable.javascript_enabled);
1693 javaScriptPreference.setIcon(R.drawable.privacy_mode);
1696 // Update the DOM storage preference icon.
1697 if (currentNightModeBoolean || currentJavaScriptBoolean) { // The preference is enabled.
1698 if (sharedPreferences.getBoolean("dom_storage", false)) { // DOM storage is enabled.
1699 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
1700 } else { // DOM storage is disabled.
1702 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_dark);
1704 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_light);
1707 } else { // The preference is disabled. The icon should be ghosted.
1709 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_dark);
1711 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_light);
1716 case "wide_viewport":
1718 if (sharedPreferences.getBoolean("wide_viewport", true)) {
1720 wideViewportPreference.setIcon(R.drawable.wide_viewport_enabled_dark);
1722 wideViewportPreference.setIcon(R.drawable.wide_viewport_enabled_light);
1726 wideViewportPreference.setIcon(R.drawable.wide_viewport_disabled_dark);
1728 wideViewportPreference.setIcon(R.drawable.wide_viewport_disabled_light);
1733 case "display_webpage_images":
1735 if (sharedPreferences.getBoolean("display_webpage_images", true)) {
1737 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_dark);
1739 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_light);
1743 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_dark);
1745 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_light);
1752 // Register the listener.
1753 savedPreferences.registerOnSharedPreferenceChangeListener(preferencesListener);
1756 // 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.
1758 public void onPause() {
1760 savedPreferences.unregisterOnSharedPreferenceChangeListener(preferencesListener);
1764 public void onResume() {
1766 savedPreferences.registerOnSharedPreferenceChangeListener(preferencesListener);