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 ultraListPreference = findPreference("ultralist");
74 Preference ultraPrivacyPreference = findPreference("ultraprivacy");
75 Preference blockAllThirdPartyRequestsPreference = findPreference("block_all_third_party_requests");
76 Preference googleAnalyticsPreference = findPreference("google_analytics");
77 Preference facebookClickIdsPreference = findPreference("facebook_click_ids");
78 Preference twitterAmpRedirectsPreference = findPreference("twitter_amp_redirects");
79 Preference proxyThroughOrbotPreference = findPreference("proxy_through_orbot");
80 Preference torHomepagePreference = findPreference("tor_homepage");
81 Preference torSearchPreference = findPreference("tor_search");
82 Preference torSearchCustomURLPreference = findPreference("tor_search_custom_url");
83 Preference searchPreference = findPreference("search");
84 Preference searchCustomURLPreference = findPreference("search_custom_url");
85 Preference fullScreenBrowsingModePreference = findPreference("full_screen_browsing_mode");
86 Preference hideAppBarPreference = findPreference("hide_app_bar");
87 Preference clearEverythingPreference = findPreference("clear_everything");
88 Preference clearCookiesPreference = findPreference("clear_cookies");
89 Preference clearDomStoragePreference = findPreference("clear_dom_storage");
90 Preference clearFormDataPreference = findPreference("clear_form_data"); // The clear form data preference can be removed once the minimum API >= 26.
91 Preference clearCachePreference = findPreference("clear_cache");
92 Preference homepagePreference = findPreference("homepage");
93 Preference fontSizePreference = findPreference("font_size");
94 Preference openIntentsInNewTabPreference = findPreference("open_intents_in_new_tab");
95 Preference swipeToRefreshPreference = findPreference("swipe_to_refresh");
96 Preference scrollAppBarPreference = findPreference("scroll_app_bar");
97 Preference displayAdditionalAppBarIconsPreference = findPreference("display_additional_app_bar_icons");
98 Preference downloadWithExternalAppPreference = findPreference("download_with_external_app");
99 Preference darkThemePreference = findPreference("dark_theme");
100 Preference nightModePreference = findPreference("night_mode");
101 Preference wideViewportPreference = findPreference("wide_viewport");
102 Preference displayWebpageImagesPreference = findPreference("display_webpage_images");
105 torHomepagePreference.setDependency("proxy_through_orbot");
106 torSearchPreference.setDependency("proxy_through_orbot");
107 hideAppBarPreference.setDependency("full_screen_browsing_mode");
109 // Get strings from the preferences.
110 String torSearchString = savedPreferences.getString("tor_search", getString(R.string.tor_search_default_value));
111 String searchString = savedPreferences.getString("search", getString(R.string.search_default_value));
113 // Get booleans that are used in multiple places from the preferences.
114 boolean javaScriptEnabled = savedPreferences.getBoolean("javascript", false);
115 boolean firstPartyCookiesEnabled = savedPreferences.getBoolean("first_party_cookies", false);
116 boolean thirdPartyCookiesEnabled = savedPreferences.getBoolean("third_party_cookies", false);
117 boolean fanboyAnnoyanceListEnabled = savedPreferences.getBoolean("fanboys_annoyance_list", true);
118 boolean fanboySocialBlockingEnabled = savedPreferences.getBoolean("fanboys_social_blocking_list", true);
119 boolean proxyThroughOrbot = savedPreferences.getBoolean("proxy_through_orbot", false);
120 boolean fullScreenBrowsingMode = savedPreferences.getBoolean("full_screen_browsing_mode", false);
121 boolean clearEverything = savedPreferences.getBoolean("clear_everything", true);
122 boolean darkTheme = savedPreferences.getBoolean("dark_theme", false);
123 boolean nightMode = savedPreferences.getBoolean("night_mode", false);
125 // Only enable the third-party cookies preference if first-party cookies are enabled and API >= 21.
126 thirdPartyCookiesPreference.setEnabled(firstPartyCookiesEnabled && (Build.VERSION.SDK_INT >= 21));
128 // Only enable the DOM storage preference if either JavaScript or Night Mode is enabled.
129 domStoragePreference.setEnabled(javaScriptEnabled || nightMode);
131 // Remove the form data preferences if the API is >= 26 as they no longer do anything.
132 if (Build.VERSION.SDK_INT >= 26) {
133 // Get the categories.
134 PreferenceCategory privacyCategory = (PreferenceCategory) findPreference("privacy");
135 PreferenceCategory clearAndExitCategory = (PreferenceCategory) findPreference("clear_and_exit");
137 // Remove the form data preferences.
138 privacyCategory.removePreference(formDataPreference);
139 clearAndExitCategory.removePreference(clearFormDataPreference);
142 // Only enable Fanboy's social blocking list preference if Fanboy's annoyance list is disabled.
143 fanboySocialBlockingListPreference.setEnabled(!fanboyAnnoyanceListEnabled);
145 // Inflate a WebView to get the default user agent.
146 LayoutInflater inflater = getActivity().getLayoutInflater();
147 // `@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.
148 @SuppressLint("InflateParams") View bareWebViewLayout = inflater.inflate(R.layout.bare_webview, null, false);
149 WebView bareWebView = bareWebViewLayout.findViewById(R.id.bare_webview);
151 // Get the user agent arrays.
152 ArrayAdapter<CharSequence> userAgentNamesArray = ArrayAdapter.createFromResource(context, R.array.user_agent_names, R.layout.spinner_item);
153 String[] translatedUserAgentNamesArray = getResources().getStringArray(R.array.translated_user_agent_names);
154 String[] userAgentDataArray = getResources().getStringArray(R.array.user_agent_data);
156 // Get the current user agent name from the preference.
157 String userAgentName = savedPreferences.getString("user_agent", getString(R.string.user_agent_default_value));
159 // Get the array position of the user agent name.
160 int userAgentArrayPosition = userAgentNamesArray.getPosition(userAgentName);
162 // Populate the user agent summary.
163 switch (userAgentArrayPosition) {
164 case MainWebViewActivity.UNRECOGNIZED_USER_AGENT: // The user agent name is not on the canonical list.
165 // 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.
166 userAgentPreference.setSummary(userAgentName);
169 case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
170 // Get the user agent text from the webview (which changes based on the version of Android and WebView installed).
171 userAgentPreference.setSummary(translatedUserAgentNamesArray[userAgentArrayPosition] + ":\n" + bareWebView.getSettings().getUserAgentString());
174 case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
175 // Set the summary text.
176 userAgentPreference.setSummary(R.string.custom_user_agent);
180 // Get the user agent summary from the user agent data array.
181 userAgentPreference.setSummary(translatedUserAgentNamesArray[userAgentArrayPosition] + ":\n" + userAgentDataArray[userAgentArrayPosition]);
184 // Set the summary text for the custom user agent preference and enable it if user agent preference is set to custom.
185 customUserAgentPreference.setSummary(savedPreferences.getString("custom_user_agent", getString(R.string.custom_user_agent_default_value)));
186 customUserAgentPreference.setEnabled(userAgentPreference.getSummary().equals(getString(R.string.custom_user_agent)));
189 // 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/`.
190 torHomepagePreference.setSummary(savedPreferences.getString("tor_homepage", getString(R.string.tor_homepage_default_value)));
193 // Set the Tor search URL as the summary text for the Tor preference when the preference screen is loaded.
194 if (torSearchString.equals("Custom URL")) {
195 // Use R.string.custom_url, which will be translated, instead of the array value, which will not.
196 torSearchPreference.setSummary(R.string.custom_url);
198 // Set the array value as the summary text.
199 torSearchPreference.setSummary(torSearchString);
202 // Set the summary text for `tor_search_custom_url`. The default is `""`.
203 torSearchCustomURLPreference.setSummary(savedPreferences.getString("tor_search_custom_url", getString(R.string.tor_search_custom_url_default_value)));
205 // Enable the Tor custom URL search options only if proxying through Orbot and the search is set to `Custom URL`.
206 torSearchCustomURLPreference.setEnabled(proxyThroughOrbot && torSearchString.equals("Custom URL"));
209 // Set the search URL as the summary text for the search preference when the preference screen is loaded.
210 if (searchString.equals("Custom URL")) {
211 // Use R.string.custom_url, which will be translated, instead of the array value, which will not.
212 searchPreference.setSummary(R.string.custom_url);
214 // Set the array value as the summary text.
215 searchPreference.setSummary(searchString);
218 // Set the summary text for `search_custom_url` (the default is `""`) and enable it if `search` is set to `Custom URL`.
219 searchCustomURLPreference.setSummary(savedPreferences.getString("search_custom_url", getString(R.string.search_custom_url_default_value)));
220 searchCustomURLPreference.setEnabled(searchString.equals("Custom URL"));
222 // Set the status of the Clear and Exit preferences.
223 clearCookiesPreference.setEnabled(!clearEverything);
224 clearDomStoragePreference.setEnabled(!clearEverything);
225 clearFormDataPreference.setEnabled(!clearEverything); // The form data line can be removed once the minimum API is >= 26.
226 clearCachePreference.setEnabled(!clearEverything);
228 // Set the homepage URL as the summary text for the homepage preference.
229 homepagePreference.setSummary(savedPreferences.getString("homepage", getString(R.string.homepage_default_value)));
231 // Set the font size as the summary text for the preference.
232 fontSizePreference.setSummary(savedPreferences.getString("font_size", getString(R.string.font_size_default_value)) + "%%");
234 // Disable the JavaScript preference if Night Mode is enabled. JavaScript will be enabled for all web pages.
235 javaScriptPreference.setEnabled(!nightMode);
237 // Set the JavaScript icon.
238 if (javaScriptEnabled || nightMode) {
239 javaScriptPreference.setIcon(R.drawable.javascript_enabled);
241 javaScriptPreference.setIcon(R.drawable.privacy_mode);
244 // Set the first-party cookies icon.
245 if (firstPartyCookiesEnabled) {
246 firstPartyCookiesPreference.setIcon(R.drawable.cookies_enabled);
249 firstPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
251 firstPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
255 // Set the third party cookies icon.
256 if (firstPartyCookiesEnabled && Build.VERSION.SDK_INT >= 21) {
257 if (thirdPartyCookiesEnabled) {
258 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_warning);
261 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
263 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
268 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_dark);
270 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_light);
274 // Set the DOM storage icon.
275 if (javaScriptEnabled || nightMode) { // The preference is enabled.
276 if (savedPreferences.getBoolean("dom_storage", false)) { // DOM storage is enabled.
277 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
278 } else { // DOM storage is disabled.
280 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_dark);
282 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_light);
285 } else { // The preference is disabled. The icon should be ghosted.
287 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_dark);
289 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_light);
293 // Set the save form data icon if API < 26. Save form data has no effect on API >= 26.
294 if (Build.VERSION.SDK_INT < 26) {
295 if (savedPreferences.getBoolean("save_form_data", false)) {
296 formDataPreference.setIcon(R.drawable.form_data_enabled);
299 formDataPreference.setIcon(R.drawable.form_data_disabled_dark);
301 formDataPreference.setIcon(R.drawable.form_data_disabled_light);
306 // Set the custom user agent icon.
307 if (customUserAgentPreference.isEnabled()) {
309 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_dark);
311 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_light);
315 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_dark);
317 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_light);
321 // Set the incognito mode icon.
322 if (savedPreferences.getBoolean("incognito_mode", false)) {
324 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_dark);
326 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_light);
330 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_dark);
332 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_light);
336 // Set the Do Not Track icon.
337 if (savedPreferences.getBoolean("do_not_track", false)) {
339 doNotTrackPreference.setIcon(R.drawable.block_tracking_enabled_dark);
341 doNotTrackPreference.setIcon(R.drawable.block_tracking_enabled_light);
345 doNotTrackPreference.setIcon(R.drawable.block_tracking_disabled_dark);
347 doNotTrackPreference.setIcon(R.drawable.block_tracking_disabled_light);
351 // Set the allow screenshots icon.
352 if (savedPreferences.getBoolean("allow_screenshots", false)) {
354 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_dark);
356 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_light);
360 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_dark);
362 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_light);
366 // Set the EasyList icon.
367 if (savedPreferences.getBoolean("easylist", true)) {
369 easyListPreference.setIcon(R.drawable.block_ads_enabled_dark);
371 easyListPreference.setIcon(R.drawable.block_ads_enabled_light);
375 easyListPreference.setIcon(R.drawable.block_ads_disabled_dark);
377 easyListPreference.setIcon(R.drawable.block_ads_disabled_light);
381 // Set the EasyPrivacy icon.
382 if (savedPreferences.getBoolean("easyprivacy", true)) {
384 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_dark);
386 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_light);
390 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_dark);
392 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_light);
396 // Set the Fanboy lists icons.
397 if (fanboyAnnoyanceListEnabled) {
399 // Set the Fanboy annoyance list icon.
400 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_dark);
402 // Set the Fanboy social blocking list icon.
403 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_dark);
405 // Set the Fanboy annoyance list icon.
406 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_light);
408 // Set the Fanboy social blocking list icon.
409 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_light);
413 // Set the Fanboy annoyance list icon.
414 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled_dark);
416 // Set the Fanboy social blocking list icon.
417 if (fanboySocialBlockingEnabled) {
418 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_dark);
420 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_dark);
423 // Set the Fanboy annoyance list icon.
424 fanboyAnnoyanceListPreference.setIcon(R.drawable.block_ads_disabled_light);
426 // Set the Fanboy social blocking list icon.
427 if (fanboySocialBlockingEnabled) {
428 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_light);
430 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_light);
435 // Set the UltraList icon.
436 if (savedPreferences.getBoolean("ultralist", true)){
438 ultraListPreference.setIcon(R.drawable.block_ads_enabled_dark);
440 ultraListPreference.setIcon(R.drawable.block_ads_enabled_light);
444 ultraListPreference.setIcon(R.drawable.block_ads_disabled_dark);
446 ultraListPreference.setIcon(R.drawable.block_ads_disabled_light);
450 // Set the UltraPrivacy icon.
451 if (savedPreferences.getBoolean("ultraprivacy", true)) {
453 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_dark);
455 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_light);
459 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_dark);
461 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_light);
465 // Set the block all third-party requests icon.
466 if (savedPreferences.getBoolean("block_all_third_party_requests", false)) {
468 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_dark);
470 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_light);
474 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_dark);
476 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_light);
480 // Set the Google Analytics icon according to the theme.
481 if (savedPreferences.getBoolean("google_analytics", true)) {
483 googleAnalyticsPreference.setIcon(R.drawable.modify_url_enabled_dark);
485 googleAnalyticsPreference.setIcon(R.drawable.modify_url_enabled_light);
489 googleAnalyticsPreference.setIcon(R.drawable.modify_url_disabled_dark);
491 googleAnalyticsPreference.setIcon(R.drawable.modify_url_disabled_light);
495 // Set the Facebook Click IDs icon according to the theme.
496 if (savedPreferences.getBoolean("facebook_click_ids", true)) {
498 facebookClickIdsPreference.setIcon(R.drawable.modify_url_enabled_dark);
500 facebookClickIdsPreference.setIcon(R.drawable.modify_url_enabled_light);
504 facebookClickIdsPreference.setIcon(R.drawable.modify_url_disabled_dark);
506 facebookClickIdsPreference.setIcon(R.drawable.modify_url_disabled_light);
510 // Set the Twitter AMP redirects icon according to the theme.
511 if (savedPreferences.getBoolean("twitter_amp_redirects", true)) {
513 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_enabled_dark);
515 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_enabled_light);
519 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_disabled_dark);
521 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_disabled_light);
525 // Set the Tor icons according to the theme.
526 if (proxyThroughOrbot) { // Proxying is enabled.
528 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_enabled_dark);
529 torHomepagePreference.setIcon(R.drawable.home_enabled_dark);
530 torSearchPreference.setIcon(R.drawable.search_enabled_dark);
532 // Set the custom search icon.
533 if (torSearchCustomURLPreference.isEnabled()) {
534 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_dark);
536 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
539 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_enabled_light);
540 torHomepagePreference.setIcon(R.drawable.home_enabled_light);
541 torSearchPreference.setIcon(R.drawable.search_enabled_light);
543 // Set the custom search icon.
544 if (torSearchCustomURLPreference.isEnabled()) {
545 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_light);
547 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
550 } else { // Proxying is disabled.
552 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_disabled_dark);
553 torHomepagePreference.setIcon(R.drawable.home_ghosted_dark);
554 torSearchPreference.setIcon(R.drawable.search_ghosted_dark);
555 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
557 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_disabled_light);
558 torHomepagePreference.setIcon(R.drawable.home_ghosted_light);
559 torSearchPreference.setIcon(R.drawable.search_ghosted_light);
560 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
564 // Set the search custom URL icon.
565 if (searchCustomURLPreference.isEnabled()) {
567 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_dark);
569 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_light);
573 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
575 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
579 // Set the full screen browsing mode icons.
580 if (fullScreenBrowsingMode) { // Full screen browsing mode is enabled.
581 // Set the `fullScreenBrowsingModePreference` icon according to the theme.
583 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_dark);
585 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_light);
588 // Set the hide app bar icon.
589 if (savedPreferences.getBoolean("hide_app_bar", true)) { // Hide app bar is enabled.
590 // Set the icon according to the theme.
592 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
594 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
596 } else { // Hide app bar is disabled.
597 // Set the icon according to the theme.
599 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
601 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
604 } else { // Full screen browsing mode is disabled.
605 // Set the icons according to the theme.
607 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_dark);
608 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_dark);
610 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_light);
611 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_light);
615 // Set the clear everything preference icon.
616 if (clearEverything) {
618 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_dark);
620 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_light);
623 clearEverythingPreference.setIcon(R.drawable.clear_everything_disabled);
626 // Set the clear cookies preference icon.
627 if (clearEverything || savedPreferences.getBoolean("clear_cookies", true)) {
629 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_dark);
631 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_light);
634 clearCookiesPreference.setIcon(R.drawable.cookies_warning);
637 // Set the clear DOM storage preference icon.
638 if (clearEverything || savedPreferences.getBoolean("clear_dom_storage", true)) {
640 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_dark);
642 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_light);
645 clearDomStoragePreference.setIcon(R.drawable.dom_storage_warning);
648 // Set the clear form data preference icon if the API < 26. It has no effect on newer versions of Android.
649 if (Build.VERSION.SDK_INT < 26) {
650 if (clearEverything || savedPreferences.getBoolean("clear_form_data", true)) {
652 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_dark);
654 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_light);
657 clearFormDataPreference.setIcon(R.drawable.form_data_warning);
661 // Set the clear cache preference icon.
662 if (clearEverything || savedPreferences.getBoolean("clear_cache", true)) {
664 clearCachePreference.setIcon(R.drawable.cache_cleared_dark);
666 clearCachePreference.setIcon(R.drawable.cache_cleared_light);
669 clearCachePreference.setIcon(R.drawable.cache_warning);
672 // Set the open intents in new tab preference icon.
673 if (savedPreferences.getBoolean("open_intents_in_new_tab", true)) {
675 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_dark);
677 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_light);
681 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_dark);
683 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_light);
687 // Set the swipe to refresh preference icon.
688 if (savedPreferences.getBoolean("swipe_to_refresh", true)) {
690 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_dark);
692 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_light);
696 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_dark);
698 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_light);
702 // Set the scroll app bar preference icon.
703 if (savedPreferences.getBoolean("scroll_app_bar", true)) {
705 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
707 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
711 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
713 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
717 // Set the display additional app bar icons preference icon.
718 if (savedPreferences.getBoolean("display_additional_app_bar_icons", false)) {
720 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_dark);
722 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_light);
726 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_dark);
728 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_light);
732 // Set the download with external app preference icon.
733 if (savedPreferences.getBoolean("download_with_external_app", false)) {
735 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_enabled_dark);
737 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_enabled_light);
741 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_disabled_dark);
743 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_disabled_light);
747 // Set the dark theme preference icon.
748 if (savedPreferences.getBoolean("dark_theme", false)) {
749 darkThemePreference.setIcon(R.drawable.theme_dark);
751 darkThemePreference.setIcon(R.drawable.theme_light);
754 // Set the night mode preference icon.
757 nightModePreference.setIcon(R.drawable.night_mode_enabled_dark);
759 nightModePreference.setIcon(R.drawable.night_mode_enabled_light);
763 nightModePreference.setIcon(R.drawable.night_mode_disabled_dark);
765 nightModePreference.setIcon(R.drawable.night_mode_disabled_light);
769 // Set the wide viewport preference icon.
770 if (savedPreferences.getBoolean("wide_viewport", true)) {
772 wideViewportPreference.setIcon(R.drawable.wide_viewport_enabled_dark);
774 wideViewportPreference.setIcon(R.drawable.wide_viewport_enabled_light);
778 wideViewportPreference.setIcon(R.drawable.wide_viewport_disabled_dark);
780 wideViewportPreference.setIcon(R.drawable.wide_viewport_disabled_light);
784 // Set the display webpage images preference icon.
785 if (savedPreferences.getBoolean("display_webpage_images", true)) {
787 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_dark);
789 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_light);
793 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_dark);
795 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_light);
800 // Listen for preference changes.
801 preferencesListener = (SharedPreferences sharedPreferences, String key) -> {
804 // Update the icons and the DOM storage preference status.
805 if (sharedPreferences.getBoolean("javascript", false)) { // The JavaScript preference is enabled.
806 // Update the icon for the JavaScript preference.
807 javaScriptPreference.setIcon(R.drawable.javascript_enabled);
809 // Update the status of the DOM storage preference.
810 domStoragePreference.setEnabled(true);
812 // Update the icon for the DOM storage preference.
813 if (sharedPreferences.getBoolean("dom_storage", false)) {
814 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
817 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_dark);
819 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_light);
822 } else { // The JavaScript preference is disabled.
823 // Update the icon for the JavaScript preference.
824 javaScriptPreference.setIcon(R.drawable.privacy_mode);
826 // Update the status of the DOM storage preference.
827 domStoragePreference.setEnabled(false);
829 // Set the icon for DOM storage preference to be ghosted.
831 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_dark);
833 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_light);
838 case "first_party_cookies":
839 // Update the icons for `first_party_cookies` and `third_party_cookies`.
840 if (sharedPreferences.getBoolean("first_party_cookies", false)) {
841 // Set the icon for `first_party_cookies`.
842 firstPartyCookiesPreference.setIcon(R.drawable.cookies_enabled);
844 // Update the icon for `third_party_cookies`.
845 if (Build.VERSION.SDK_INT >= 21) {
846 if (sharedPreferences.getBoolean("third_party_cookies", false)) {
847 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_warning);
850 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
852 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
857 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_dark);
859 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_light);
862 } else { // `first_party_cookies` is `false`.
863 // Update the icon for `first_party_cookies`.
865 firstPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
867 firstPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
870 // Set the icon for `third_party_cookies` to be ghosted.
872 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_dark);
874 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_light);
878 // Enable `third_party_cookies` if `first_party_cookies` is `true` and API >= 21.
879 thirdPartyCookiesPreference.setEnabled(sharedPreferences.getBoolean("first_party_cookies", false) && (Build.VERSION.SDK_INT >= 21));
882 case "third_party_cookies":
884 if (sharedPreferences.getBoolean("third_party_cookies", false)) {
885 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_warning);
888 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
890 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
897 if (sharedPreferences.getBoolean("dom_storage", false)) {
898 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
901 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_dark);
903 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_light);
908 // Save form data can be removed once the minimum API >= 26.
909 case "save_form_data":
911 if (sharedPreferences.getBoolean("save_form_data", false)) {
912 formDataPreference.setIcon(R.drawable.form_data_enabled);
915 formDataPreference.setIcon(R.drawable.form_data_disabled_dark);
917 formDataPreference.setIcon(R.drawable.form_data_disabled_light);
923 // Get the new user agent name.
924 String newUserAgentName = sharedPreferences.getString("user_agent", getString(R.string.user_agent_default_value));
926 // Get the array position for the new user agent name.
927 int newUserAgentArrayPosition = userAgentNamesArray.getPosition(newUserAgentName);
929 // Get the translated new user agent name.
930 String translatedNewUserAgentName = translatedUserAgentNamesArray[newUserAgentArrayPosition];
932 // Populate the user agent summary.
933 switch (newUserAgentArrayPosition) {
934 case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
935 // Get the user agent text from the webview (which changes based on the version of Android and WebView installed).
936 userAgentPreference.setSummary(translatedNewUserAgentName + ":\n" + bareWebView.getSettings().getUserAgentString());
938 // Disable the custom user agent preference.
939 customUserAgentPreference.setEnabled(false);
941 // Set the custom user agent preference icon according to the theme.
943 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_dark);
945 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_light);
949 case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
950 // Set the summary text.
951 userAgentPreference.setSummary(R.string.custom_user_agent);
953 // Enable the custom user agent preference.
954 customUserAgentPreference.setEnabled(true);
956 // Set the custom user agent preference icon according to the theme.
958 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_dark);
960 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_light);
965 // Get the user agent summary from the user agent data array.
966 userAgentPreference.setSummary(translatedNewUserAgentName + ":\n" + userAgentDataArray[newUserAgentArrayPosition]);
968 // Disable the custom user agent preference.
969 customUserAgentPreference.setEnabled(false);
971 // Set the custom user agent preference icon according to the theme.
973 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_dark);
975 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_light);
980 case "custom_user_agent":
981 // Set the new custom user agent as the summary text for the preference.
982 customUserAgentPreference.setSummary(sharedPreferences.getString("custom_user_agent", getString(R.string.custom_user_agent_default_value)));
985 case "incognito_mode":
987 if (sharedPreferences.getBoolean("incognito_mode", false)) {
989 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_dark);
991 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_light);
995 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_dark);
997 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_light);
1002 case "do_not_track":
1004 if (sharedPreferences.getBoolean("do_not_track", false)) {
1006 doNotTrackPreference.setIcon(R.drawable.block_tracking_enabled_dark);
1008 doNotTrackPreference.setIcon(R.drawable.block_tracking_enabled_light);
1012 doNotTrackPreference.setIcon(R.drawable.block_tracking_disabled_dark);
1014 doNotTrackPreference.setIcon(R.drawable.block_tracking_disabled_light);
1020 case "allow_screenshots":
1022 if (sharedPreferences.getBoolean("allow_screenshots", false)) {
1024 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_dark);
1026 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_light);
1030 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_dark);
1032 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_light);
1036 // Create an intent to restart Privacy Browser.
1037 Intent allowScreenshotsRestartIntent = getActivity().getParentActivityIntent();
1039 // Assert that the intent is not null to remove the lint error below.
1040 assert allowScreenshotsRestartIntent != null;
1042 // `Intent.FLAG_ACTIVITY_CLEAR_TASK` removes all activities from the stack. It requires `Intent.FLAG_ACTIVITY_NEW_TASK`.
1043 allowScreenshotsRestartIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
1045 // Create a handler to restart the activity.
1046 Handler allowScreenshotsRestartHandler = new Handler();
1048 // Create a runnable to restart the activity.
1049 Runnable allowScreenshotsRestartRunnable = () -> {
1050 // Restart the activity.
1051 startActivity(allowScreenshotsRestartIntent);
1053 // Kill this instance of Privacy Browser. Otherwise, the app exhibits sporadic behavior after the restart.
1057 // Restart the activity after 150 milliseconds, so that the app has enough time to save the change to the preference.
1058 allowScreenshotsRestartHandler.postDelayed(allowScreenshotsRestartRunnable, 150);
1063 if (sharedPreferences.getBoolean("easylist", true)) {
1065 easyListPreference.setIcon(R.drawable.block_ads_enabled_dark);
1067 easyListPreference.setIcon(R.drawable.block_ads_enabled_light);
1071 easyListPreference.setIcon(R.drawable.block_ads_disabled_dark);
1073 easyListPreference.setIcon(R.drawable.block_ads_disabled_light);
1080 if (sharedPreferences.getBoolean("easyprivacy", true)) {
1082 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_dark);
1084 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_light);
1088 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_dark);
1090 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_light);
1095 case "fanboys_annoyance_list":
1096 boolean currentFanboyAnnoyanceList = sharedPreferences.getBoolean("fanboys_annoyance_list", true);
1097 boolean currentFanboySocialBlockingList = sharedPreferences.getBoolean("fanboys_social_blocking_list", true);
1099 // Update the Fanboy icons.
1100 if (currentFanboyAnnoyanceList) { // Fanboy's annoyance list is enabled.
1102 // Update the Fanboy's annoyance list icon.
1103 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_dark);
1105 // Update the Fanboy's social blocking list icon.
1106 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_dark);
1108 // Update the Fanboy's annoyance list icon.
1109 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_light);
1111 // Update the Fanboy's social blocking list icon.
1112 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_light);
1114 } else { // Fanboy's annoyance list is disabled.
1116 // Update the Fanboy's annoyance list icon.
1117 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled_dark);
1119 // Update the Fanboy's social blocking list icon.
1120 if (currentFanboySocialBlockingList) {
1121 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_dark);
1123 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_dark);
1126 // Update the Fanboy's annoyance list icon.
1127 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled_light);
1129 // Update the Fanboy's social blocking list icon.
1130 if (currentFanboySocialBlockingList) {
1131 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_light);
1133 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_light);
1138 // Only enable Fanboy's social blocking list preference if Fanboy's annoyance list preference is disabled.
1139 fanboySocialBlockingListPreference.setEnabled(!currentFanboyAnnoyanceList);
1142 case "fanboys_social_blocking_list":
1144 if (sharedPreferences.getBoolean("fanboys_social_blocking_list", true)) {
1146 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_dark);
1148 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_light);
1152 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_dark);
1154 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_light);
1161 if (sharedPreferences.getBoolean("ultralist", true)) {
1163 ultraListPreference.setIcon(R.drawable.block_ads_enabled_dark);
1165 ultraListPreference.setIcon(R.drawable.block_ads_enabled_light);
1169 ultraListPreference.setIcon(R.drawable.block_ads_disabled_dark);
1171 ultraListPreference.setIcon(R.drawable.block_ads_disabled_light);
1176 case "ultraprivacy":
1178 if (sharedPreferences.getBoolean("ultraprivacy", true)) {
1180 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_dark);
1182 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_light);
1186 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_dark);
1188 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_light);
1193 case "block_all_third_party_requests":
1195 if (sharedPreferences.getBoolean("block_all_third_party_requests", false)) {
1197 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_dark);
1199 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_light);
1203 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_dark);
1205 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_light);
1210 case "google_analytics":
1212 if (sharedPreferences.getBoolean("google_analytics", true)) {
1214 googleAnalyticsPreference.setIcon(R.drawable.modify_url_enabled_dark);
1216 googleAnalyticsPreference.setIcon(R.drawable.modify_url_enabled_light);
1220 googleAnalyticsPreference.setIcon(R.drawable.modify_url_disabled_dark);
1222 googleAnalyticsPreference.setIcon(R.drawable.modify_url_disabled_light);
1227 case "facebook_click_ids":
1229 if (sharedPreferences.getBoolean("facebook_click_ids", true)) {
1231 facebookClickIdsPreference.setIcon(R.drawable.modify_url_enabled_dark);
1233 facebookClickIdsPreference.setIcon(R.drawable.modify_url_enabled_light);
1237 facebookClickIdsPreference.setIcon(R.drawable.modify_url_disabled_dark);
1239 facebookClickIdsPreference.setIcon(R.drawable.modify_url_disabled_light);
1244 case "twitter_amp_redirects":
1246 if (sharedPreferences.getBoolean("twitter_amp_redirects", true)) {
1248 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_enabled_dark);
1250 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_enabled_light);
1254 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_disabled_dark);
1256 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_disabled_light);
1261 case "proxy_through_orbot":
1262 // Get current settings.
1263 boolean currentProxyThroughOrbot = sharedPreferences.getBoolean("proxy_through_orbot", false);
1264 String currentTorSearchString = sharedPreferences.getString("tor_search", getString(R.string.tor_search_default_value));
1266 // Enable the Tor custom URL search option only if `currentProxyThroughOrbot` is true and the search is set to `Custom URL`.
1267 torSearchCustomURLPreference.setEnabled(currentProxyThroughOrbot && currentTorSearchString.equals("Custom URL"));
1269 // Update the icons.
1270 if (currentProxyThroughOrbot) {
1271 // Set the Tor icons according to the theme.
1273 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_enabled_dark);
1274 torHomepagePreference.setIcon(R.drawable.home_enabled_dark);
1275 torSearchPreference.setIcon(R.drawable.search_enabled_dark);
1277 // Set the `torSearchCustomURLPreference` icon.
1278 if (torSearchCustomURLPreference.isEnabled()) {
1279 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_dark);
1281 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
1284 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_enabled_light);
1285 torHomepagePreference.setIcon(R.drawable.home_enabled_light);
1286 torSearchPreference.setIcon(R.drawable.search_enabled_light);
1288 // Set the `torSearchCustomURLPreference` icon.
1289 if (torSearchCustomURLPreference.isEnabled()) {
1290 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_light);
1292 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
1295 } else { // Proxy through Orbot is disabled.
1297 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_disabled_dark);
1298 torHomepagePreference.setIcon(R.drawable.home_ghosted_dark);
1299 torSearchPreference.setIcon(R.drawable.search_ghosted_dark);
1300 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
1302 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_disabled_light);
1303 torHomepagePreference.setIcon(R.drawable.home_ghosted_light);
1304 torSearchPreference.setIcon(R.drawable.search_ghosted_light);
1305 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
1310 case "tor_homepage":
1311 // Set the new tor homepage URL as the summary text for the `tor_homepage` preference. The default is Searx: `http://ulrn6sryqaifefld.onion/`.
1312 torHomepagePreference.setSummary(sharedPreferences.getString("tor_homepage", getString(R.string.tor_homepage_default_value)));
1316 // Get the present search string.
1317 String presentTorSearchString = sharedPreferences.getString("tor_search", getString(R.string.tor_search_default_value));
1319 // Update the preferences.
1320 if (presentTorSearchString.equals("Custom URL")) {
1321 // Use `R.string.custom_url`, which is translated, as the summary instead of the array value, which isn't.
1322 torSearchPreference.setSummary(R.string.custom_url);
1324 // Enable `torSearchCustomURLPreference`.
1325 torSearchCustomURLPreference.setEnabled(true);
1327 // Update the `torSearchCustomURLPreference` icon.
1329 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_dark);
1331 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_light);
1334 // Set the array value as the summary text.
1335 torSearchPreference.setSummary(presentTorSearchString);
1337 // Disable `torSearchCustomURLPreference`.
1338 torSearchCustomURLPreference.setEnabled(false);
1340 // Update the `torSearchCustomURLPreference` icon.
1342 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
1344 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
1349 case "tor_search_custom_url":
1350 // Set the summary text for `tor_search_custom_url`.
1351 torSearchCustomURLPreference.setSummary(sharedPreferences.getString("tor_search_custom_url", getString(R.string.tor_search_custom_url_default_value)));
1355 // Store the new search string.
1356 String newSearchString = sharedPreferences.getString("search", getString(R.string.search_default_value));
1358 // Update `searchPreference` and `searchCustomURLPreference`.
1359 if (newSearchString.equals("Custom URL")) { // `Custom URL` is selected.
1360 // Set the summary text to `R.string.custom_url`, which is translated.
1361 searchPreference.setSummary(R.string.custom_url);
1363 // Enable `searchCustomURLPreference`.
1364 searchCustomURLPreference.setEnabled(true);
1366 // Set the `searchCustomURLPreference` according to the theme.
1368 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_dark);
1370 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_light);
1372 } else { // `Custom URL` is not selected.
1373 // Set the summary text to `newSearchString`.
1374 searchPreference.setSummary(newSearchString);
1376 // Disable `searchCustomURLPreference`.
1377 searchCustomURLPreference.setEnabled(false);
1379 // Set the `searchCustomURLPreference` according to the theme.
1381 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
1383 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
1388 case "search_custom_url":
1389 // Set the new custom search URL as the summary text for `search_custom_url`. The default is `""`.
1390 searchCustomURLPreference.setSummary(sharedPreferences.getString("search_custom_url", getString(R.string.search_custom_url_default_value)));
1393 case "full_screen_browsing_mode":
1394 if (sharedPreferences.getBoolean("full_screen_browsing_mode", false)) { // Full screen browsing is enabled.
1395 // Set the full screen browsing mode preference icon according to the theme.
1397 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_dark);
1399 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_light);
1402 // Set the hide app bar preference icon.
1403 if (sharedPreferences.getBoolean("hide_app_bar", true)) { // Hide app bar is enabled.
1404 // Set the icon according to the theme.
1406 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
1408 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
1410 } else { // Hide app bar is disabled.
1411 // Set the icon according to the theme.
1413 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
1415 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
1418 } else { // Full screen browsing is disabled.
1419 // Update the icons according to the theme.
1421 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_dark);
1422 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_dark);
1424 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_light);
1425 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_light);
1430 case "hide_app_bar":
1432 if (sharedPreferences.getBoolean("hide_app_bar", true)) { // Hide app bar is enabled.
1433 // Set the icon according to the theme.
1435 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
1437 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
1439 } else { // Hide app bar is disabled.
1440 // Set the icon according to the theme.
1442 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
1444 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
1449 case "clear_everything":
1450 // Store the new `clear_everything` status
1451 boolean newClearEverythingBoolean = sharedPreferences.getBoolean("clear_everything", true);
1453 // Update the status of the `Clear and Exit` preferences.
1454 clearCookiesPreference.setEnabled(!newClearEverythingBoolean);
1455 clearDomStoragePreference.setEnabled(!newClearEverythingBoolean);
1456 clearFormDataPreference.setEnabled(!newClearEverythingBoolean); // This line can be removed once the minimum API >= 26.
1457 clearCachePreference.setEnabled(!newClearEverythingBoolean);
1459 // Update the `clearEverythingPreference` icon.
1460 if (newClearEverythingBoolean) {
1462 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_dark);
1464 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_light);
1467 clearEverythingPreference.setIcon(R.drawable.clear_everything_disabled);
1470 // Update the `clearCookiesPreference` icon.
1471 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_cookies", true)) {
1473 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_dark);
1475 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_light);
1478 clearCookiesPreference.setIcon(R.drawable.cookies_warning);
1481 // Update the `clearDomStoragePreference` icon.
1482 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_dom_storage", true)) {
1484 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_dark);
1486 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_light);
1489 clearDomStoragePreference.setIcon(R.drawable.dom_storage_warning);
1492 // Update the clear form data preference icon if the API < 26.
1493 if (Build.VERSION.SDK_INT < 26) {
1494 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_form_data", true)) {
1496 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_dark);
1498 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_light);
1501 clearFormDataPreference.setIcon(R.drawable.form_data_warning);
1505 // Update the `clearCachePreference` icon.
1506 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_cache", true)) {
1508 clearCachePreference.setIcon(R.drawable.cache_cleared_dark);
1510 clearCachePreference.setIcon(R.drawable.cache_cleared_light);
1513 clearCachePreference.setIcon(R.drawable.cache_warning);
1517 case "clear_cookies":
1519 if (sharedPreferences.getBoolean("clear_cookies", true)) {
1521 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_dark);
1523 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_light);
1526 clearCookiesPreference.setIcon(R.drawable.cookies_warning);
1530 case "clear_dom_storage":
1532 if (sharedPreferences.getBoolean("clear_dom_storage", true)) {
1534 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_dark);
1536 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_light);
1539 clearDomStoragePreference.setIcon(R.drawable.dom_storage_warning);
1543 // This section can be removed once the minimum API >= 26.
1544 case "clear_form_data":
1546 if (sharedPreferences.getBoolean("clear_form_data", true)) {
1548 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_dark);
1550 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_light);
1553 clearFormDataPreference.setIcon(R.drawable.form_data_warning);
1559 if (sharedPreferences.getBoolean("clear_cache", true)) {
1561 clearCachePreference.setIcon(R.drawable.cache_cleared_dark);
1563 clearCachePreference.setIcon(R.drawable.cache_cleared_light);
1566 clearCachePreference.setIcon(R.drawable.cache_warning);
1571 // Set the new homepage URL as the summary text for the Homepage preference.
1572 homepagePreference.setSummary(sharedPreferences.getString("homepage", getString(R.string.homepage_default_value)));
1576 // Update the font size summary text.
1577 fontSizePreference.setSummary(sharedPreferences.getString("font_size", getString(R.string.font_size_default_value)) + "%%");
1580 case "open_intents_in_new_tab":
1582 if (sharedPreferences.getBoolean("open_intents_in_new_tab", true)) {
1584 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_dark);
1586 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_light);
1590 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_dark);
1592 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_light);
1597 case "swipe_to_refresh":
1599 if (sharedPreferences.getBoolean("swipe_to_refresh", true)) {
1601 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_dark);
1603 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_light);
1607 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_dark);
1609 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_light);
1614 case "scroll_app_bar":
1616 if (sharedPreferences.getBoolean("scroll_app_bar", true)) {
1618 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
1620 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
1624 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
1626 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
1631 case "display_additional_app_bar_icons":
1633 if (sharedPreferences.getBoolean("display_additional_app_bar_icons", false)) {
1635 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_dark);
1637 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_light);
1641 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_dark);
1643 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_light);
1648 case "download_with_external_app":
1650 if (sharedPreferences.getBoolean("download_with_external_app", false)) {
1652 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_enabled_dark);
1654 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_enabled_light);
1658 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_disabled_dark);
1660 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_disabled_light);
1667 if (sharedPreferences.getBoolean("dark_theme", false)) {
1668 darkThemePreference.setIcon(R.drawable.theme_dark);
1670 darkThemePreference.setIcon(R.drawable.theme_light);
1673 // Create an intent to restart Privacy Browser.
1674 Intent changeThemeRestartIntent = getActivity().getParentActivityIntent();
1676 // Assert that the intent is not null to remove the lint error below.
1677 assert changeThemeRestartIntent != null;
1679 // `Intent.FLAG_ACTIVITY_CLEAR_TASK` removes all activities from the stack. It requires `Intent.FLAG_ACTIVITY_NEW_TASK`.
1680 changeThemeRestartIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
1682 // Create a handler to restart the activity.
1683 Handler changeThemeRestartHandler = new Handler();
1685 // Create a runnable to restart the activity.
1686 Runnable changeThemeRestartRunnable = () -> {
1687 // Restart the activity.
1688 startActivity(changeThemeRestartIntent);
1690 // Kill this instance of Privacy Browser. Otherwise, the app exhibits sporadic behavior after the restart.
1694 // Restart the activity after 150 milliseconds, so that the app has enough time to save the change to the preference.
1695 changeThemeRestartHandler.postDelayed(changeThemeRestartRunnable, 150);
1699 // Store the current night mode status.
1700 boolean currentNightModeBoolean = sharedPreferences.getBoolean("night_mode", false);
1701 boolean currentJavaScriptBoolean = sharedPreferences.getBoolean("javascript", false);
1704 if (currentNightModeBoolean) {
1706 nightModePreference.setIcon(R.drawable.night_mode_enabled_dark);
1708 nightModePreference.setIcon(R.drawable.night_mode_enabled_light);
1712 nightModePreference.setIcon(R.drawable.night_mode_disabled_dark);
1714 nightModePreference.setIcon(R.drawable.night_mode_disabled_light);
1718 // Update the status of `javaScriptPreference` and `domStoragePreference`.
1719 javaScriptPreference.setEnabled(!currentNightModeBoolean);
1720 domStoragePreference.setEnabled(currentNightModeBoolean || currentJavaScriptBoolean);
1722 // Update the `javaScriptPreference` icon.
1723 if (currentNightModeBoolean || currentJavaScriptBoolean) {
1724 javaScriptPreference.setIcon(R.drawable.javascript_enabled);
1726 javaScriptPreference.setIcon(R.drawable.privacy_mode);
1729 // Update the DOM storage preference icon.
1730 if (currentNightModeBoolean || currentJavaScriptBoolean) { // The preference is enabled.
1731 if (sharedPreferences.getBoolean("dom_storage", false)) { // DOM storage is enabled.
1732 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
1733 } else { // DOM storage is disabled.
1735 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_dark);
1737 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_light);
1740 } else { // The preference is disabled. The icon should be ghosted.
1742 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_dark);
1744 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_light);
1749 case "wide_viewport":
1751 if (sharedPreferences.getBoolean("wide_viewport", true)) {
1753 wideViewportPreference.setIcon(R.drawable.wide_viewport_enabled_dark);
1755 wideViewportPreference.setIcon(R.drawable.wide_viewport_enabled_light);
1759 wideViewportPreference.setIcon(R.drawable.wide_viewport_disabled_dark);
1761 wideViewportPreference.setIcon(R.drawable.wide_viewport_disabled_light);
1766 case "display_webpage_images":
1768 if (sharedPreferences.getBoolean("display_webpage_images", true)) {
1770 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_dark);
1772 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_light);
1776 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_dark);
1778 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_light);
1785 // Register the listener.
1786 savedPreferences.registerOnSharedPreferenceChangeListener(preferencesListener);
1789 // 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.
1791 public void onPause() {
1793 savedPreferences.unregisterOnSharedPreferenceChangeListener(preferencesListener);
1797 public void onResume() {
1799 savedPreferences.registerOnSharedPreferenceChangeListener(preferencesListener);