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 displayWebpageImagesPreference = findPreference("display_webpage_images");
103 torHomepagePreference.setDependency("proxy_through_orbot");
104 torSearchPreference.setDependency("proxy_through_orbot");
105 hideAppBarPreference.setDependency("full_screen_browsing_mode");
107 // Get strings from the preferences.
108 String torSearchString = savedPreferences.getString("tor_search", getString(R.string.tor_search_default_value));
109 String searchString = savedPreferences.getString("search", getString(R.string.search_default_value));
111 // Get booleans that are used in multiple places from the preferences.
112 boolean javaScriptEnabled = savedPreferences.getBoolean("javascript", false);
113 boolean firstPartyCookiesEnabled = savedPreferences.getBoolean("first_party_cookies", false);
114 boolean thirdPartyCookiesEnabled = savedPreferences.getBoolean("third_party_cookies", false);
115 boolean fanboyAnnoyanceListEnabled = savedPreferences.getBoolean("fanboys_annoyance_list", true);
116 boolean fanboySocialBlockingEnabled = savedPreferences.getBoolean("fanboys_social_blocking_list", true);
117 boolean proxyThroughOrbot = savedPreferences.getBoolean("proxy_through_orbot", false);
118 boolean fullScreenBrowsingMode = savedPreferences.getBoolean("full_screen_browsing_mode", false);
119 boolean clearEverything = savedPreferences.getBoolean("clear_everything", true);
120 boolean darkTheme = savedPreferences.getBoolean("dark_theme", false);
121 boolean nightMode = savedPreferences.getBoolean("night_mode", false);
123 // Only enable the third-party cookies preference if first-party cookies are enabled and API >= 21.
124 thirdPartyCookiesPreference.setEnabled(firstPartyCookiesEnabled && (Build.VERSION.SDK_INT >= 21));
126 // Only enable the DOM storage preference if either JavaScript or Night Mode is enabled.
127 domStoragePreference.setEnabled(javaScriptEnabled || nightMode);
129 // Remove the form data preferences if the API is >= 26 as they no longer do anything.
130 if (Build.VERSION.SDK_INT >= 26) {
131 // Get the categories.
132 PreferenceCategory privacyCategory = (PreferenceCategory) findPreference("privacy");
133 PreferenceCategory clearAndExitCategory = (PreferenceCategory) findPreference("clear_and_exit");
135 // Remove the form data preferences.
136 privacyCategory.removePreference(formDataPreference);
137 clearAndExitCategory.removePreference(clearFormDataPreference);
140 // Only enable Fanboy's social blocking list preference if Fanboy's annoyance list is disabled.
141 fanboySocialBlockingListPreference.setEnabled(!fanboyAnnoyanceListEnabled);
143 // Inflate a WebView to get the default user agent.
144 LayoutInflater inflater = getActivity().getLayoutInflater();
145 // `@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.
146 @SuppressLint("InflateParams") View bareWebViewLayout = inflater.inflate(R.layout.bare_webview, null, false);
147 WebView bareWebView = bareWebViewLayout.findViewById(R.id.bare_webview);
149 // Get the user agent arrays.
150 ArrayAdapter<CharSequence> userAgentNamesArray = ArrayAdapter.createFromResource(context, R.array.user_agent_names, R.layout.spinner_item);
151 String[] translatedUserAgentNamesArray = getResources().getStringArray(R.array.translated_user_agent_names);
152 String[] userAgentDataArray = getResources().getStringArray(R.array.user_agent_data);
154 // Get the current user agent name from the preference.
155 String userAgentName = savedPreferences.getString("user_agent", getString(R.string.user_agent_default_value));
157 // Get the array position of the user agent name.
158 int userAgentArrayPosition = userAgentNamesArray.getPosition(userAgentName);
160 // Populate the user agent summary.
161 switch (userAgentArrayPosition) {
162 case MainWebViewActivity.UNRECOGNIZED_USER_AGENT: // The user agent name is not on the canonical list.
163 // 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.
164 userAgentPreference.setSummary(userAgentName);
167 case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
168 // Get the user agent text from the webview (which changes based on the version of Android and WebView installed).
169 userAgentPreference.setSummary(translatedUserAgentNamesArray[userAgentArrayPosition] + ":\n" + bareWebView.getSettings().getUserAgentString());
172 case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
173 // Set the summary text.
174 userAgentPreference.setSummary(R.string.custom_user_agent);
178 // Get the user agent summary from the user agent data array.
179 userAgentPreference.setSummary(translatedUserAgentNamesArray[userAgentArrayPosition] + ":\n" + userAgentDataArray[userAgentArrayPosition]);
182 // Set the summary text for the custom user agent preference and enable it if user agent preference is set to custom.
183 customUserAgentPreference.setSummary(savedPreferences.getString("custom_user_agent", getString(R.string.custom_user_agent_default_value)));
184 customUserAgentPreference.setEnabled(userAgentPreference.getSummary().equals(getString(R.string.custom_user_agent)));
187 // 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/`.
188 torHomepagePreference.setSummary(savedPreferences.getString("tor_homepage", getString(R.string.tor_homepage_default_value)));
191 // Set the Tor search URL as the summary text for the Tor preference when the preference screen is loaded.
192 if (torSearchString.equals("Custom URL")) {
193 // Use R.string.custom_url, which will be translated, instead of the array value, which will not.
194 torSearchPreference.setSummary(R.string.custom_url);
196 // Set the array value as the summary text.
197 torSearchPreference.setSummary(torSearchString);
200 // Set the summary text for `tor_search_custom_url`. The default is `""`.
201 torSearchCustomURLPreference.setSummary(savedPreferences.getString("tor_search_custom_url", getString(R.string.tor_search_custom_url_default_value)));
203 // Enable the Tor custom URL search options only if proxying through Orbot and the search is set to `Custom URL`.
204 torSearchCustomURLPreference.setEnabled(proxyThroughOrbot && torSearchString.equals("Custom URL"));
207 // Set the search URL as the summary text for the search preference when the preference screen is loaded.
208 if (searchString.equals("Custom URL")) {
209 // Use R.string.custom_url, which will be translated, instead of the array value, which will not.
210 searchPreference.setSummary(R.string.custom_url);
212 // Set the array value as the summary text.
213 searchPreference.setSummary(searchString);
216 // Set the summary text for `search_custom_url` (the default is `""`) and enable it if `search` is set to `Custom URL`.
217 searchCustomURLPreference.setSummary(savedPreferences.getString("search_custom_url", getString(R.string.search_custom_url_default_value)));
218 searchCustomURLPreference.setEnabled(searchString.equals("Custom URL"));
220 // Set the status of the Clear and Exit preferences.
221 clearCookiesPreference.setEnabled(!clearEverything);
222 clearDomStoragePreference.setEnabled(!clearEverything);
223 clearFormDataPreference.setEnabled(!clearEverything); // The form data line can be removed once the minimum API is >= 26.
224 clearCachePreference.setEnabled(!clearEverything);
226 // Set the homepage URL as the summary text for the homepage preference.
227 homepagePreference.setSummary(savedPreferences.getString("homepage", getString(R.string.homepage_default_value)));
229 // Set the font size as the summary text for the preference.
230 fontSizePreference.setSummary(savedPreferences.getString("font_size", getString(R.string.font_size_default_value)) + "%%");
232 // Disable the JavaScript preference if Night Mode is enabled. JavaScript will be enabled for all web pages.
233 javaScriptPreference.setEnabled(!nightMode);
235 // Set the JavaScript icon.
236 if (javaScriptEnabled || nightMode) {
237 javaScriptPreference.setIcon(R.drawable.javascript_enabled);
239 javaScriptPreference.setIcon(R.drawable.privacy_mode);
242 // Set the first-party cookies icon.
243 if (firstPartyCookiesEnabled) {
244 firstPartyCookiesPreference.setIcon(R.drawable.cookies_enabled);
247 firstPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
249 firstPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
253 // Set the third party cookies icon.
254 if (firstPartyCookiesEnabled && Build.VERSION.SDK_INT >= 21) {
255 if (thirdPartyCookiesEnabled) {
256 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_warning);
259 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
261 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
266 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_dark);
268 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_light);
272 // Set the DOM storage icon.
273 if (javaScriptEnabled || nightMode) { // The preference is enabled.
274 if (savedPreferences.getBoolean("dom_storage", false)) { // DOM storage is enabled.
275 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
276 } else { // DOM storage is disabled.
278 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_dark);
280 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_light);
283 } else { // The preference is disabled. The icon should be ghosted.
285 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_dark);
287 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_light);
291 // Set the save form data icon if API < 26. Save form data has no effect on API >= 26.
292 if (Build.VERSION.SDK_INT < 26) {
293 if (savedPreferences.getBoolean("save_form_data", false)) {
294 formDataPreference.setIcon(R.drawable.form_data_enabled);
297 formDataPreference.setIcon(R.drawable.form_data_disabled_dark);
299 formDataPreference.setIcon(R.drawable.form_data_disabled_light);
304 // Set the custom user agent icon.
305 if (customUserAgentPreference.isEnabled()) {
307 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_dark);
309 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_light);
313 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_dark);
315 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_light);
319 // Set the incognito mode icon.
320 if (savedPreferences.getBoolean("incognito_mode", false)) {
322 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_dark);
324 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_light);
328 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_dark);
330 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_light);
334 // Set the Do Not Track icon.
335 if (savedPreferences.getBoolean("do_not_track", false)) {
337 doNotTrackPreference.setIcon(R.drawable.block_tracking_enabled_dark);
339 doNotTrackPreference.setIcon(R.drawable.block_tracking_enabled_light);
343 doNotTrackPreference.setIcon(R.drawable.block_tracking_disabled_dark);
345 doNotTrackPreference.setIcon(R.drawable.block_tracking_disabled_light);
349 // Set the allow screenshots icon.
350 if (savedPreferences.getBoolean("allow_screenshots", false)) {
352 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_dark);
354 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_light);
358 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_dark);
360 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_light);
364 // Set the EasyList icon.
365 if (savedPreferences.getBoolean("easylist", true)) {
367 easyListPreference.setIcon(R.drawable.block_ads_enabled_dark);
369 easyListPreference.setIcon(R.drawable.block_ads_enabled_light);
373 easyListPreference.setIcon(R.drawable.block_ads_disabled_dark);
375 easyListPreference.setIcon(R.drawable.block_ads_disabled_light);
379 // Set the EasyPrivacy icon.
380 if (savedPreferences.getBoolean("easyprivacy", true)) {
382 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_dark);
384 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_light);
388 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_dark);
390 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_light);
394 // Set the Fanboy lists icons.
395 if (fanboyAnnoyanceListEnabled) {
397 // Set the Fanboy annoyance list icon.
398 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_dark);
400 // Set the Fanboy social blocking list icon.
401 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_dark);
403 // Set the Fanboy annoyance list icon.
404 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_light);
406 // Set the Fanboy social blocking list icon.
407 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_light);
411 // Set the Fanboy annoyance list icon.
412 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled_dark);
414 // Set the Fanboy social blocking list icon.
415 if (fanboySocialBlockingEnabled) {
416 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_dark);
418 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_dark);
421 // Set the Fanboy annoyance list icon.
422 fanboyAnnoyanceListPreference.setIcon(R.drawable.block_ads_disabled_light);
424 // Set the Fanboy social blocking list icon.
425 if (fanboySocialBlockingEnabled) {
426 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_light);
428 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_light);
433 // Set the UltraPrivacy icon.
434 if (savedPreferences.getBoolean("ultraprivacy", true)) {
436 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_dark);
438 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_light);
442 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_dark);
444 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_light);
448 // Set the block all third-party requests icon.
449 if (savedPreferences.getBoolean("block_all_third_party_requests", false)) {
451 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_dark);
453 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_light);
457 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_dark);
459 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_light);
463 // Set the Google Analytics icon according to the theme.
464 if (savedPreferences.getBoolean("google_analytics", true)) {
466 googleAnalyticsPreference.setIcon(R.drawable.modify_url_enabled_dark);
468 googleAnalyticsPreference.setIcon(R.drawable.modify_url_enabled_light);
472 googleAnalyticsPreference.setIcon(R.drawable.modify_url_disabled_dark);
474 googleAnalyticsPreference.setIcon(R.drawable.modify_url_disabled_light);
478 // Set the Facebook Click IDs icon according to the theme.
479 if (savedPreferences.getBoolean("facebook_click_ids", true)) {
481 facebookClickIdsPreference.setIcon(R.drawable.modify_url_enabled_dark);
483 facebookClickIdsPreference.setIcon(R.drawable.modify_url_enabled_light);
487 facebookClickIdsPreference.setIcon(R.drawable.modify_url_disabled_dark);
489 facebookClickIdsPreference.setIcon(R.drawable.modify_url_disabled_light);
493 // Set the Twitter AMP redirects icon according to the theme.
494 if (savedPreferences.getBoolean("twitter_amp_redirects", true)) {
496 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_enabled_dark);
498 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_enabled_light);
502 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_disabled_dark);
504 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_disabled_light);
508 // Set the Tor icons according to the theme.
509 if (proxyThroughOrbot) { // Proxying is enabled.
511 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_enabled_dark);
512 torHomepagePreference.setIcon(R.drawable.home_enabled_dark);
513 torSearchPreference.setIcon(R.drawable.search_enabled_dark);
515 // Set the custom search icon.
516 if (torSearchCustomURLPreference.isEnabled()) {
517 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_dark);
519 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
522 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_enabled_light);
523 torHomepagePreference.setIcon(R.drawable.home_enabled_light);
524 torSearchPreference.setIcon(R.drawable.search_enabled_light);
526 // Set the custom search icon.
527 if (torSearchCustomURLPreference.isEnabled()) {
528 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_light);
530 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
533 } else { // Proxying is disabled.
535 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_disabled_dark);
536 torHomepagePreference.setIcon(R.drawable.home_ghosted_dark);
537 torSearchPreference.setIcon(R.drawable.search_ghosted_dark);
538 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
540 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_disabled_light);
541 torHomepagePreference.setIcon(R.drawable.home_ghosted_light);
542 torSearchPreference.setIcon(R.drawable.search_ghosted_light);
543 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
547 // Set the search custom URL icon.
548 if (searchCustomURLPreference.isEnabled()) {
550 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_dark);
552 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_light);
556 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
558 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
562 // Set the full screen browsing mode icons.
563 if (fullScreenBrowsingMode) { // Full screen browsing mode is enabled.
564 // Set the `fullScreenBrowsingModePreference` icon according to the theme.
566 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_dark);
568 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_light);
571 // Set the hide app bar icon.
572 if (savedPreferences.getBoolean("hide_app_bar", true)) { // Hide app bar is enabled.
573 // Set the icon according to the theme.
575 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
577 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
579 } else { // Hide app bar is disabled.
580 // Set the icon according to the theme.
582 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
584 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
587 } else { // Full screen browsing mode is disabled.
588 // Set the icons according to the theme.
590 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_dark);
591 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_dark);
593 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_light);
594 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_light);
598 // Set the clear everything preference icon.
599 if (clearEverything) {
601 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_dark);
603 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_light);
606 clearEverythingPreference.setIcon(R.drawable.clear_everything_disabled);
609 // Set the clear cookies preference icon.
610 if (clearEverything || savedPreferences.getBoolean("clear_cookies", true)) {
612 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_dark);
614 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_light);
617 clearCookiesPreference.setIcon(R.drawable.cookies_warning);
620 // Set the clear DOM storage preference icon.
621 if (clearEverything || savedPreferences.getBoolean("clear_dom_storage", true)) {
623 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_dark);
625 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_light);
628 clearDomStoragePreference.setIcon(R.drawable.dom_storage_warning);
631 // Set the clear form data preference icon if the API < 26. It has no effect on newer versions of Android.
632 if (Build.VERSION.SDK_INT < 26) {
633 if (clearEverything || savedPreferences.getBoolean("clear_form_data", true)) {
635 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_dark);
637 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_light);
640 clearFormDataPreference.setIcon(R.drawable.form_data_warning);
644 // Set the clear cache preference icon.
645 if (clearEverything || savedPreferences.getBoolean("clear_cache", true)) {
647 clearCachePreference.setIcon(R.drawable.cache_cleared_dark);
649 clearCachePreference.setIcon(R.drawable.cache_cleared_light);
652 clearCachePreference.setIcon(R.drawable.cache_warning);
655 // Set the open intents in new tab preference icon.
656 if (savedPreferences.getBoolean("open_intents_in_new_tab", true)) {
658 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_dark);
660 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_light);
664 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_dark);
666 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_light);
670 // Set the swipe to refresh preference icon.
671 if (savedPreferences.getBoolean("swipe_to_refresh", true)) {
673 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_dark);
675 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_light);
679 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_dark);
681 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_light);
685 // Set the scroll app bar preference icon.
686 if (savedPreferences.getBoolean("scroll_app_bar", true)) {
688 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
690 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
694 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
696 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
700 // Set the display additional app bar icons preference icon.
701 if (savedPreferences.getBoolean("display_additional_app_bar_icons", false)) {
703 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_dark);
705 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_light);
709 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_dark);
711 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_light);
715 // Set the download with external app preference icon.
716 if (savedPreferences.getBoolean("download_with_external_app", false)) {
718 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_enabled_dark);
720 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_enabled_light);
724 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_disabled_dark);
726 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_disabled_light);
730 // Set the dark theme preference icon.
731 if (savedPreferences.getBoolean("dark_theme", false)) {
732 darkThemePreference.setIcon(R.drawable.theme_dark);
734 darkThemePreference.setIcon(R.drawable.theme_light);
737 // Set the night mode preference icon.
740 nightModePreference.setIcon(R.drawable.night_mode_enabled_dark);
742 nightModePreference.setIcon(R.drawable.night_mode_enabled_light);
746 nightModePreference.setIcon(R.drawable.night_mode_disabled_dark);
748 nightModePreference.setIcon(R.drawable.night_mode_disabled_light);
752 // Set the display webpage images preference icon.
753 if (savedPreferences.getBoolean("display_webpage_images", true)) {
755 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_dark);
757 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_light);
761 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_dark);
763 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_light);
768 // Listen for preference changes.
769 preferencesListener = (SharedPreferences sharedPreferences, String key) -> {
772 // Update the icons and the DOM storage preference status.
773 if (sharedPreferences.getBoolean("javascript", false)) { // The JavaScript preference is enabled.
774 // Update the icon for the JavaScript preference.
775 javaScriptPreference.setIcon(R.drawable.javascript_enabled);
777 // Update the status of the DOM storage preference.
778 domStoragePreference.setEnabled(true);
780 // Update the icon for the DOM storage preference.
781 if (sharedPreferences.getBoolean("dom_storage", false)) {
782 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
785 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_dark);
787 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_light);
790 } else { // The JavaScript preference is disabled.
791 // Update the icon for the JavaScript preference.
792 javaScriptPreference.setIcon(R.drawable.privacy_mode);
794 // Update the status of the DOM storage preference.
795 domStoragePreference.setEnabled(false);
797 // Set the icon for DOM storage preference to be ghosted.
799 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_dark);
801 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_light);
806 case "first_party_cookies":
807 // Update the icons for `first_party_cookies` and `third_party_cookies`.
808 if (sharedPreferences.getBoolean("first_party_cookies", false)) {
809 // Set the icon for `first_party_cookies`.
810 firstPartyCookiesPreference.setIcon(R.drawable.cookies_enabled);
812 // Update the icon for `third_party_cookies`.
813 if (Build.VERSION.SDK_INT >= 21) {
814 if (sharedPreferences.getBoolean("third_party_cookies", false)) {
815 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_warning);
818 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
820 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
825 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_dark);
827 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_light);
830 } else { // `first_party_cookies` is `false`.
831 // Update the icon for `first_party_cookies`.
833 firstPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
835 firstPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
838 // Set the icon for `third_party_cookies` to be ghosted.
840 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_dark);
842 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_light);
846 // Enable `third_party_cookies` if `first_party_cookies` is `true` and API >= 21.
847 thirdPartyCookiesPreference.setEnabled(sharedPreferences.getBoolean("first_party_cookies", false) && (Build.VERSION.SDK_INT >= 21));
850 case "third_party_cookies":
852 if (sharedPreferences.getBoolean("third_party_cookies", false)) {
853 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_warning);
856 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
858 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
865 if (sharedPreferences.getBoolean("dom_storage", false)) {
866 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
869 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_dark);
871 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_light);
876 // Save form data can be removed once the minimum API >= 26.
877 case "save_form_data":
879 if (sharedPreferences.getBoolean("save_form_data", false)) {
880 formDataPreference.setIcon(R.drawable.form_data_enabled);
883 formDataPreference.setIcon(R.drawable.form_data_disabled_dark);
885 formDataPreference.setIcon(R.drawable.form_data_disabled_light);
891 // Get the new user agent name.
892 String newUserAgentName = sharedPreferences.getString("user_agent", getString(R.string.user_agent_default_value));
894 // Get the array position for the new user agent name.
895 int newUserAgentArrayPosition = userAgentNamesArray.getPosition(newUserAgentName);
897 // Get the translated new user agent name.
898 String translatedNewUserAgentName = translatedUserAgentNamesArray[newUserAgentArrayPosition];
900 // Populate the user agent summary.
901 switch (newUserAgentArrayPosition) {
902 case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
903 // Get the user agent text from the webview (which changes based on the version of Android and WebView installed).
904 userAgentPreference.setSummary(translatedNewUserAgentName + ":\n" + bareWebView.getSettings().getUserAgentString());
906 // Disable the custom user agent preference.
907 customUserAgentPreference.setEnabled(false);
909 // Set the custom user agent preference icon according to the theme.
911 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_dark);
913 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_light);
917 case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
918 // Set the summary text.
919 userAgentPreference.setSummary(R.string.custom_user_agent);
921 // Enable the custom user agent preference.
922 customUserAgentPreference.setEnabled(true);
924 // Set the custom user agent preference icon according to the theme.
926 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_dark);
928 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_light);
933 // Get the user agent summary from the user agent data array.
934 userAgentPreference.setSummary(translatedNewUserAgentName + ":\n" + userAgentDataArray[newUserAgentArrayPosition]);
936 // Disable the custom user agent preference.
937 customUserAgentPreference.setEnabled(false);
939 // Set the custom user agent preference icon according to the theme.
941 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_dark);
943 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_light);
948 case "custom_user_agent":
949 // Set the new custom user agent as the summary text for the preference.
950 customUserAgentPreference.setSummary(sharedPreferences.getString("custom_user_agent", getString(R.string.custom_user_agent_default_value)));
953 case "incognito_mode":
955 if (sharedPreferences.getBoolean("incognito_mode", false)) {
957 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_dark);
959 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_light);
963 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_dark);
965 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_light);
972 if (sharedPreferences.getBoolean("do_not_track", false)) {
974 doNotTrackPreference.setIcon(R.drawable.block_tracking_enabled_dark);
976 doNotTrackPreference.setIcon(R.drawable.block_tracking_enabled_light);
980 doNotTrackPreference.setIcon(R.drawable.block_tracking_disabled_dark);
982 doNotTrackPreference.setIcon(R.drawable.block_tracking_disabled_light);
988 case "allow_screenshots":
990 if (sharedPreferences.getBoolean("allow_screenshots", false)) {
992 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_dark);
994 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_light);
998 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_dark);
1000 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_light);
1004 // Create an intent to restart Privacy Browser.
1005 Intent allowScreenshotsRestartIntent = getActivity().getParentActivityIntent();
1007 // Assert that the intent is not null to remove the lint error below.
1008 assert allowScreenshotsRestartIntent != null;
1010 // `Intent.FLAG_ACTIVITY_CLEAR_TASK` removes all activities from the stack. It requires `Intent.FLAG_ACTIVITY_NEW_TASK`.
1011 allowScreenshotsRestartIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
1013 // Create a handler to restart the activity.
1014 Handler allowScreenshotsRestartHandler = new Handler();
1016 // Create a runnable to restart the activity.
1017 Runnable allowScreenshotsRestartRunnable = () -> {
1018 // Restart the activity.
1019 startActivity(allowScreenshotsRestartIntent);
1021 // Kill this instance of Privacy Browser. Otherwise, the app exhibits sporadic behavior after the restart.
1025 // Restart the activity after 100 milliseconds, so that the app has enough time to save the change to the preference.
1026 allowScreenshotsRestartHandler.postDelayed(allowScreenshotsRestartRunnable, 100);
1031 if (sharedPreferences.getBoolean("easylist", true)) {
1033 easyListPreference.setIcon(R.drawable.block_ads_enabled_dark);
1035 easyListPreference.setIcon(R.drawable.block_ads_enabled_light);
1039 easyListPreference.setIcon(R.drawable.block_ads_disabled_dark);
1041 easyListPreference.setIcon(R.drawable.block_ads_disabled_light);
1048 if (sharedPreferences.getBoolean("easyprivacy", true)) {
1050 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_dark);
1052 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_light);
1056 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_dark);
1058 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_light);
1063 case "fanboys_annoyance_list":
1064 boolean currentFanboyAnnoyanceList = sharedPreferences.getBoolean("fanboys_annoyance_list", true);
1065 boolean currentFanboySocialBlockingList = sharedPreferences.getBoolean("fanboys_social_blocking_list", true);
1067 // Update the Fanboy icons.
1068 if (currentFanboyAnnoyanceList) { // Fanboy's annoyance list is enabled.
1070 // Update the Fanboy's annoyance list icon.
1071 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_dark);
1073 // Update the Fanboy's social blocking list icon.
1074 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_dark);
1076 // Update the Fanboy's annoyance list icon.
1077 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_light);
1079 // Update the Fanboy's social blocking list icon.
1080 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_light);
1082 } else { // Fanboy's annoyance list is disabled.
1084 // Update the Fanboy's annoyance list icon.
1085 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled_dark);
1087 // Update the Fanboy's social blocking list icon.
1088 if (currentFanboySocialBlockingList) {
1089 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_dark);
1091 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_dark);
1094 // Update the Fanboy's annoyance list icon.
1095 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled_light);
1097 // Update the Fanboy's social blocking list icon.
1098 if (currentFanboySocialBlockingList) {
1099 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_light);
1101 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_light);
1106 // Only enable Fanboy's social blocking list preference if Fanboy's annoyance list preference is disabled.
1107 fanboySocialBlockingListPreference.setEnabled(!currentFanboyAnnoyanceList);
1110 case "fanboys_social_blocking_list":
1112 if (sharedPreferences.getBoolean("fanboys_social_blocking_list", true)) {
1114 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_dark);
1116 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_light);
1120 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_dark);
1122 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_light);
1127 case "ultraprivacy":
1129 if (sharedPreferences.getBoolean("ultraprivacy", true)) {
1131 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_dark);
1133 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_light);
1137 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_dark);
1139 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_light);
1144 case "block_all_third_party_requests":
1146 if (sharedPreferences.getBoolean("block_all_third_party_requests", false)) {
1148 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_dark);
1150 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_light);
1154 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_dark);
1156 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_light);
1161 case "google_analytics":
1163 if (sharedPreferences.getBoolean("google_analytics", true)) {
1165 googleAnalyticsPreference.setIcon(R.drawable.modify_url_enabled_dark);
1167 googleAnalyticsPreference.setIcon(R.drawable.modify_url_enabled_light);
1171 googleAnalyticsPreference.setIcon(R.drawable.modify_url_disabled_dark);
1173 googleAnalyticsPreference.setIcon(R.drawable.modify_url_disabled_light);
1178 case "facebook_click_ids":
1180 if (sharedPreferences.getBoolean("facebook_click_ids", true)) {
1182 facebookClickIdsPreference.setIcon(R.drawable.modify_url_enabled_dark);
1184 facebookClickIdsPreference.setIcon(R.drawable.modify_url_enabled_light);
1188 facebookClickIdsPreference.setIcon(R.drawable.modify_url_disabled_dark);
1190 facebookClickIdsPreference.setIcon(R.drawable.modify_url_disabled_light);
1195 case "twitter_amp_redirects":
1197 if (sharedPreferences.getBoolean("twitter_amp_redirects", true)) {
1199 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_enabled_dark);
1201 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_enabled_light);
1205 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_disabled_dark);
1207 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_disabled_light);
1212 case "proxy_through_orbot":
1213 // Get current settings.
1214 boolean currentProxyThroughOrbot = sharedPreferences.getBoolean("proxy_through_orbot", false);
1215 String currentTorSearchString = sharedPreferences.getString("tor_search", getString(R.string.tor_search_default_value));
1217 // Enable the Tor custom URL search option only if `currentProxyThroughOrbot` is true and the search is set to `Custom URL`.
1218 torSearchCustomURLPreference.setEnabled(currentProxyThroughOrbot && currentTorSearchString.equals("Custom URL"));
1220 // Update the icons.
1221 if (currentProxyThroughOrbot) {
1222 // Set the Tor icons according to the theme.
1224 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_enabled_dark);
1225 torHomepagePreference.setIcon(R.drawable.home_enabled_dark);
1226 torSearchPreference.setIcon(R.drawable.search_enabled_dark);
1228 // Set the `torSearchCustomURLPreference` icon.
1229 if (torSearchCustomURLPreference.isEnabled()) {
1230 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_dark);
1232 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
1235 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_enabled_light);
1236 torHomepagePreference.setIcon(R.drawable.home_enabled_light);
1237 torSearchPreference.setIcon(R.drawable.search_enabled_light);
1239 // Set the `torSearchCustomURLPreference` icon.
1240 if (torSearchCustomURLPreference.isEnabled()) {
1241 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_light);
1243 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
1246 } else { // Proxy through Orbot is disabled.
1248 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_disabled_dark);
1249 torHomepagePreference.setIcon(R.drawable.home_ghosted_dark);
1250 torSearchPreference.setIcon(R.drawable.search_ghosted_dark);
1251 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
1253 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_disabled_light);
1254 torHomepagePreference.setIcon(R.drawable.home_ghosted_light);
1255 torSearchPreference.setIcon(R.drawable.search_ghosted_light);
1256 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
1261 case "tor_homepage":
1262 // Set the new tor homepage URL as the summary text for the `tor_homepage` preference. The default is Searx: `http://ulrn6sryqaifefld.onion/`.
1263 torHomepagePreference.setSummary(sharedPreferences.getString("tor_homepage", getString(R.string.tor_homepage_default_value)));
1267 // Get the present search string.
1268 String presentTorSearchString = sharedPreferences.getString("tor_search", getString(R.string.tor_search_default_value));
1270 // Update the preferences.
1271 if (presentTorSearchString.equals("Custom URL")) {
1272 // Use `R.string.custom_url`, which is translated, as the summary instead of the array value, which isn't.
1273 torSearchPreference.setSummary(R.string.custom_url);
1275 // Enable `torSearchCustomURLPreference`.
1276 torSearchCustomURLPreference.setEnabled(true);
1278 // Update the `torSearchCustomURLPreference` icon.
1280 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_dark);
1282 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_light);
1285 // Set the array value as the summary text.
1286 torSearchPreference.setSummary(presentTorSearchString);
1288 // Disable `torSearchCustomURLPreference`.
1289 torSearchCustomURLPreference.setEnabled(false);
1291 // Update the `torSearchCustomURLPreference` icon.
1293 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
1295 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
1300 case "tor_search_custom_url":
1301 // Set the summary text for `tor_search_custom_url`.
1302 torSearchCustomURLPreference.setSummary(sharedPreferences.getString("tor_search_custom_url", getString(R.string.tor_search_custom_url_default_value)));
1306 // Store the new search string.
1307 String newSearchString = sharedPreferences.getString("search", getString(R.string.search_default_value));
1309 // Update `searchPreference` and `searchCustomURLPreference`.
1310 if (newSearchString.equals("Custom URL")) { // `Custom URL` is selected.
1311 // Set the summary text to `R.string.custom_url`, which is translated.
1312 searchPreference.setSummary(R.string.custom_url);
1314 // Enable `searchCustomURLPreference`.
1315 searchCustomURLPreference.setEnabled(true);
1317 // Set the `searchCustomURLPreference` according to the theme.
1319 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_dark);
1321 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_light);
1323 } else { // `Custom URL` is not selected.
1324 // Set the summary text to `newSearchString`.
1325 searchPreference.setSummary(newSearchString);
1327 // Disable `searchCustomURLPreference`.
1328 searchCustomURLPreference.setEnabled(false);
1330 // Set the `searchCustomURLPreference` according to the theme.
1332 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
1334 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
1339 case "search_custom_url":
1340 // Set the new custom search URL as the summary text for `search_custom_url`. The default is `""`.
1341 searchCustomURLPreference.setSummary(sharedPreferences.getString("search_custom_url", getString(R.string.search_custom_url_default_value)));
1344 case "full_screen_browsing_mode":
1345 if (sharedPreferences.getBoolean("full_screen_browsing_mode", false)) { // Full screen browsing is enabled.
1346 // Set the full screen browsing mode preference icon according to the theme.
1348 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_dark);
1350 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_light);
1353 // Set the hide app bar preference icon.
1354 if (sharedPreferences.getBoolean("hide_app_bar", true)) { // Hide app bar is enabled.
1355 // Set the icon according to the theme.
1357 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
1359 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
1361 } else { // Hide app bar is disabled.
1362 // Set the icon according to the theme.
1364 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
1366 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
1369 } else { // Full screen browsing is disabled.
1370 // Update the icons according to the theme.
1372 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_dark);
1373 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_dark);
1375 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_light);
1376 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_light);
1381 case "hide_app_bar":
1383 if (sharedPreferences.getBoolean("hide_app_bar", true)) { // Hide app bar is enabled.
1384 // Set the icon according to the theme.
1386 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
1388 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
1390 } else { // Hide app bar is disabled.
1391 // Set the icon according to the theme.
1393 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
1395 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
1400 case "clear_everything":
1401 // Store the new `clear_everything` status
1402 boolean newClearEverythingBoolean = sharedPreferences.getBoolean("clear_everything", true);
1404 // Update the status of the `Clear and Exit` preferences.
1405 clearCookiesPreference.setEnabled(!newClearEverythingBoolean);
1406 clearDomStoragePreference.setEnabled(!newClearEverythingBoolean);
1407 clearFormDataPreference.setEnabled(!newClearEverythingBoolean); // This line can be removed once the minimum API >= 26.
1408 clearCachePreference.setEnabled(!newClearEverythingBoolean);
1410 // Update the `clearEverythingPreference` icon.
1411 if (newClearEverythingBoolean) {
1413 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_dark);
1415 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_light);
1418 clearEverythingPreference.setIcon(R.drawable.clear_everything_disabled);
1421 // Update the `clearCookiesPreference` icon.
1422 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_cookies", true)) {
1424 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_dark);
1426 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_light);
1429 clearCookiesPreference.setIcon(R.drawable.cookies_warning);
1432 // Update the `clearDomStoragePreference` icon.
1433 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_dom_storage", true)) {
1435 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_dark);
1437 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_light);
1440 clearDomStoragePreference.setIcon(R.drawable.dom_storage_warning);
1443 // Update the clear form data preference icon if the API < 26.
1444 if (Build.VERSION.SDK_INT < 26) {
1445 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_form_data", true)) {
1447 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_dark);
1449 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_light);
1452 clearFormDataPreference.setIcon(R.drawable.form_data_warning);
1456 // Update the `clearCachePreference` icon.
1457 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_cache", true)) {
1459 clearCachePreference.setIcon(R.drawable.cache_cleared_dark);
1461 clearCachePreference.setIcon(R.drawable.cache_cleared_light);
1464 clearCachePreference.setIcon(R.drawable.cache_warning);
1468 case "clear_cookies":
1470 if (sharedPreferences.getBoolean("clear_cookies", true)) {
1472 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_dark);
1474 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_light);
1477 clearCookiesPreference.setIcon(R.drawable.cookies_warning);
1481 case "clear_dom_storage":
1483 if (sharedPreferences.getBoolean("clear_dom_storage", true)) {
1485 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_dark);
1487 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_light);
1490 clearDomStoragePreference.setIcon(R.drawable.dom_storage_warning);
1494 // This section can be removed once the minimum API >= 26.
1495 case "clear_form_data":
1497 if (sharedPreferences.getBoolean("clear_form_data", true)) {
1499 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_dark);
1501 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_light);
1504 clearFormDataPreference.setIcon(R.drawable.form_data_warning);
1510 if (sharedPreferences.getBoolean("clear_cache", true)) {
1512 clearCachePreference.setIcon(R.drawable.cache_cleared_dark);
1514 clearCachePreference.setIcon(R.drawable.cache_cleared_light);
1517 clearCachePreference.setIcon(R.drawable.cache_warning);
1522 // Set the new homepage URL as the summary text for the Homepage preference.
1523 homepagePreference.setSummary(sharedPreferences.getString("homepage", getString(R.string.homepage_default_value)));
1527 // Update the font size summary text.
1528 fontSizePreference.setSummary(sharedPreferences.getString("font_size", getString(R.string.font_size_default_value)) + "%%");
1531 case "open_intents_in_new_tab":
1533 if (sharedPreferences.getBoolean("open_intents_in_new_tab", true)) {
1535 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_dark);
1537 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_light);
1541 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_dark);
1543 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_light);
1548 case "swipe_to_refresh":
1550 if (sharedPreferences.getBoolean("swipe_to_refresh", true)) {
1552 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_dark);
1554 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_light);
1558 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_dark);
1560 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_light);
1565 case "scroll_app_bar":
1567 if (sharedPreferences.getBoolean("scroll_app_bar", true)) {
1569 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
1571 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
1575 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
1577 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
1582 case "display_additional_app_bar_icons":
1584 if (sharedPreferences.getBoolean("display_additional_app_bar_icons", false)) {
1586 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_dark);
1588 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_light);
1592 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_dark);
1594 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_light);
1599 case "download_with_external_app":
1601 if (sharedPreferences.getBoolean("download_with_external_app", false)) {
1603 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_enabled_dark);
1605 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_enabled_light);
1609 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_disabled_dark);
1611 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_disabled_light);
1618 if (sharedPreferences.getBoolean("dark_theme", false)) {
1619 darkThemePreference.setIcon(R.drawable.theme_dark);
1621 darkThemePreference.setIcon(R.drawable.theme_light);
1624 // Create an intent to restart Privacy Browser.
1625 Intent changeThemeRestartIntent = getActivity().getParentActivityIntent();
1627 // Assert that the intent is not null to remove the lint error below.
1628 assert changeThemeRestartIntent != null;
1630 // `Intent.FLAG_ACTIVITY_CLEAR_TASK` removes all activities from the stack. It requires `Intent.FLAG_ACTIVITY_NEW_TASK`.
1631 changeThemeRestartIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
1633 // Create a handler to restart the activity.
1634 Handler changeThemeRestartHandler = new Handler();
1636 // Create a runnable to restart the activity.
1637 Runnable changeThemeRestartRunnable = () -> {
1638 // Restart the activity.
1639 startActivity(changeThemeRestartIntent);
1641 // Kill this instance of Privacy Browser. Otherwise, the app exhibits sporadic behavior after the restart.
1645 // Restart the activity after 100 milliseconds, so that the app has enough time to save the change to the preference.
1646 changeThemeRestartHandler.postDelayed(changeThemeRestartRunnable, 100);
1650 // Store the current night mode status.
1651 boolean currentNightModeBoolean = sharedPreferences.getBoolean("night_mode", false);
1652 boolean currentJavaScriptBoolean = sharedPreferences.getBoolean("javascript", false);
1655 if (currentNightModeBoolean) {
1657 nightModePreference.setIcon(R.drawable.night_mode_enabled_dark);
1659 nightModePreference.setIcon(R.drawable.night_mode_enabled_light);
1663 nightModePreference.setIcon(R.drawable.night_mode_disabled_dark);
1665 nightModePreference.setIcon(R.drawable.night_mode_disabled_light);
1669 // Update the status of `javaScriptPreference` and `domStoragePreference`.
1670 javaScriptPreference.setEnabled(!currentNightModeBoolean);
1671 domStoragePreference.setEnabled(currentNightModeBoolean || currentJavaScriptBoolean);
1673 // Update the `javaScriptPreference` icon.
1674 if (currentNightModeBoolean || currentJavaScriptBoolean) {
1675 javaScriptPreference.setIcon(R.drawable.javascript_enabled);
1677 javaScriptPreference.setIcon(R.drawable.privacy_mode);
1680 // Update the DOM storage preference icon.
1681 if (currentNightModeBoolean || currentJavaScriptBoolean) { // The preference is enabled.
1682 if (sharedPreferences.getBoolean("dom_storage", false)) { // DOM storage is enabled.
1683 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
1684 } else { // DOM storage is disabled.
1686 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_dark);
1688 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_light);
1691 } else { // The preference is disabled. The icon should be ghosted.
1693 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_dark);
1695 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_light);
1700 case "display_webpage_images":
1701 if (sharedPreferences.getBoolean("display_webpage_images", true)) {
1704 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_dark);
1706 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_light);
1711 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_dark);
1713 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_light);
1720 // Register the listener.
1721 savedPreferences.registerOnSharedPreferenceChangeListener(preferencesListener);
1724 // 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.
1726 public void onPause() {
1728 savedPreferences.unregisterOnSharedPreferenceChangeListener(preferencesListener);
1732 public void onResume() {
1734 savedPreferences.registerOnSharedPreferenceChangeListener(preferencesListener);