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 proxyThroughOrbotPreference = findPreference("proxy_through_orbot");
77 Preference torHomepagePreference = findPreference("tor_homepage");
78 Preference torSearchPreference = findPreference("tor_search");
79 Preference torSearchCustomURLPreference = findPreference("tor_search_custom_url");
80 Preference searchPreference = findPreference("search");
81 Preference searchCustomURLPreference = findPreference("search_custom_url");
82 Preference fullScreenBrowsingModePreference = findPreference("full_screen_browsing_mode");
83 Preference hideAppBarPreference = findPreference("hide_app_bar");
84 Preference clearEverythingPreference = findPreference("clear_everything");
85 Preference clearCookiesPreference = findPreference("clear_cookies");
86 Preference clearDomStoragePreference = findPreference("clear_dom_storage");
87 Preference clearFormDataPreference = findPreference("clear_form_data"); // The clear form data preference can be removed once the minimum API >= 26.
88 Preference clearCachePreference = findPreference("clear_cache");
89 Preference homepagePreference = findPreference("homepage");
90 Preference fontSizePreference = findPreference("font_size");
91 Preference openIntentsInNewTabPreference = findPreference("open_intents_in_new_tab");
92 Preference swipeToRefreshPreference = findPreference("swipe_to_refresh");
93 Preference scrollAppBarPreference = findPreference("scroll_app_bar");
94 Preference displayAdditionalAppBarIconsPreference = findPreference("display_additional_app_bar_icons");
95 Preference downloadWithExternalAppPreference = findPreference("download_with_external_app");
96 Preference darkThemePreference = findPreference("dark_theme");
97 Preference nightModePreference = findPreference("night_mode");
98 Preference displayWebpageImagesPreference = findPreference("display_webpage_images");
101 torHomepagePreference.setDependency("proxy_through_orbot");
102 torSearchPreference.setDependency("proxy_through_orbot");
103 hideAppBarPreference.setDependency("full_screen_browsing_mode");
105 // Get strings from the preferences.
106 String torSearchString = savedPreferences.getString("tor_search", getString(R.string.tor_search_default_value));
107 String searchString = savedPreferences.getString("search", getString(R.string.search_default_value));
109 // Get booleans that are used in multiple places from the preferences.
110 boolean javaScriptEnabled = savedPreferences.getBoolean("javascript", false);
111 boolean firstPartyCookiesEnabled = savedPreferences.getBoolean("first_party_cookies", false);
112 boolean thirdPartyCookiesEnabled = savedPreferences.getBoolean("third_party_cookies", false);
113 boolean fanboyAnnoyanceListEnabled = savedPreferences.getBoolean("fanboys_annoyance_list", true);
114 boolean fanboySocialBlockingEnabled = savedPreferences.getBoolean("fanboys_social_blocking_list", true);
115 boolean proxyThroughOrbot = savedPreferences.getBoolean("proxy_through_orbot", false);
116 boolean fullScreenBrowsingMode = savedPreferences.getBoolean("full_screen_browsing_mode", false);
117 boolean clearEverything = savedPreferences.getBoolean("clear_everything", true);
118 boolean darkTheme = savedPreferences.getBoolean("dark_theme", false);
119 boolean nightMode = savedPreferences.getBoolean("night_mode", false);
121 // Only enable the third-party cookies preference if first-party cookies are enabled and API >= 21.
122 thirdPartyCookiesPreference.setEnabled(firstPartyCookiesEnabled && (Build.VERSION.SDK_INT >= 21));
124 // Only enable the DOM storage preference if either JavaScript or Night Mode is enabled.
125 domStoragePreference.setEnabled(javaScriptEnabled || nightMode);
127 // Remove the form data preferences if the API is >= 26 as they no longer do anything.
128 if (Build.VERSION.SDK_INT >= 26) {
129 // Get the categories.
130 PreferenceCategory privacyCategory = (PreferenceCategory) findPreference("privacy");
131 PreferenceCategory clearAndExitCategory = (PreferenceCategory) findPreference("clear_and_exit");
133 // Remove the form data preferences.
134 privacyCategory.removePreference(formDataPreference);
135 clearAndExitCategory.removePreference(clearFormDataPreference);
138 // Only enable Fanboy's social blocking list preference if Fanboy's annoyance list is disabled.
139 fanboySocialBlockingListPreference.setEnabled(!fanboyAnnoyanceListEnabled);
141 // Inflate a WebView to get the default user agent.
142 LayoutInflater inflater = getActivity().getLayoutInflater();
143 // `@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.
144 @SuppressLint("InflateParams") View bareWebViewLayout = inflater.inflate(R.layout.bare_webview, null, false);
145 WebView bareWebView = bareWebViewLayout.findViewById(R.id.bare_webview);
147 // Get the user agent arrays.
148 ArrayAdapter<CharSequence> userAgentNamesArray = ArrayAdapter.createFromResource(context, R.array.user_agent_names, R.layout.spinner_item);
149 String[] translatedUserAgentNamesArray = getResources().getStringArray(R.array.translated_user_agent_names);
150 String[] userAgentDataArray = getResources().getStringArray(R.array.user_agent_data);
152 // Get the current user agent name from the preference.
153 String userAgentName = savedPreferences.getString("user_agent", getString(R.string.user_agent_default_value));
155 // Get the array position of the user agent name.
156 int userAgentArrayPosition = userAgentNamesArray.getPosition(userAgentName);
158 // Populate the user agent summary.
159 switch (userAgentArrayPosition) {
160 case MainWebViewActivity.UNRECOGNIZED_USER_AGENT: // The user agent name is not on the canonical list.
161 // 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.
162 userAgentPreference.setSummary(userAgentName);
165 case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
166 // Get the user agent text from the webview (which changes based on the version of Android and WebView installed).
167 userAgentPreference.setSummary(translatedUserAgentNamesArray[userAgentArrayPosition] + ":\n" + bareWebView.getSettings().getUserAgentString());
170 case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
171 // Set the summary text.
172 userAgentPreference.setSummary(R.string.custom_user_agent);
176 // Get the user agent summary from the user agent data array.
177 userAgentPreference.setSummary(translatedUserAgentNamesArray[userAgentArrayPosition] + ":\n" + userAgentDataArray[userAgentArrayPosition]);
180 // Set the summary text for the custom user agent preference and enable it if user agent preference is set to custom.
181 customUserAgentPreference.setSummary(savedPreferences.getString("custom_user_agent", getString(R.string.custom_user_agent_default_value)));
182 customUserAgentPreference.setEnabled(userAgentPreference.getSummary().equals(getString(R.string.custom_user_agent)));
185 // 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/`.
186 torHomepagePreference.setSummary(savedPreferences.getString("tor_homepage", getString(R.string.tor_homepage_default_value)));
189 // Set the Tor search URL as the summary text for the Tor preference when the preference screen is loaded.
190 if (torSearchString.equals("Custom URL")) {
191 // Use R.string.custom_url, which will be translated, instead of the array value, which will not.
192 torSearchPreference.setSummary(R.string.custom_url);
194 // Set the array value as the summary text.
195 torSearchPreference.setSummary(torSearchString);
198 // Set the summary text for `tor_search_custom_url`. The default is `""`.
199 torSearchCustomURLPreference.setSummary(savedPreferences.getString("tor_search_custom_url", getString(R.string.tor_search_custom_url_default_value)));
201 // Enable the Tor custom URL search options only if proxying through Orbot and the search is set to `Custom URL`.
202 torSearchCustomURLPreference.setEnabled(proxyThroughOrbot && torSearchString.equals("Custom URL"));
205 // Set the search URL as the summary text for the search preference when the preference screen is loaded.
206 if (searchString.equals("Custom URL")) {
207 // Use R.string.custom_url, which will be translated, instead of the array value, which will not.
208 searchPreference.setSummary(R.string.custom_url);
210 // Set the array value as the summary text.
211 searchPreference.setSummary(searchString);
214 // Set the summary text for `search_custom_url` (the default is `""`) and enable it if `search` is set to `Custom URL`.
215 searchCustomURLPreference.setSummary(savedPreferences.getString("search_custom_url", getString(R.string.search_custom_url_default_value)));
216 searchCustomURLPreference.setEnabled(searchString.equals("Custom URL"));
218 // Set the status of the Clear and Exit preferences.
219 clearCookiesPreference.setEnabled(!clearEverything);
220 clearDomStoragePreference.setEnabled(!clearEverything);
221 clearFormDataPreference.setEnabled(!clearEverything); // The form data line can be removed once the minimum API is >= 26.
222 clearCachePreference.setEnabled(!clearEverything);
224 // Set the homepage URL as the summary text for the homepage preference.
225 homepagePreference.setSummary(savedPreferences.getString("homepage", getString(R.string.homepage_default_value)));
227 // Set the font size as the summary text for the preference.
228 fontSizePreference.setSummary(savedPreferences.getString("font_size", getString(R.string.font_size_default_value)) + "%%");
230 // Disable the JavaScript preference if Night Mode is enabled. JavaScript will be enabled for all web pages.
231 javaScriptPreference.setEnabled(!nightMode);
233 // Set the JavaScript icon.
234 if (javaScriptEnabled || nightMode) {
235 javaScriptPreference.setIcon(R.drawable.javascript_enabled);
237 javaScriptPreference.setIcon(R.drawable.privacy_mode);
240 // Set the first-party cookies icon.
241 if (firstPartyCookiesEnabled) {
242 firstPartyCookiesPreference.setIcon(R.drawable.cookies_enabled);
245 firstPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
247 firstPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
251 // Set the third party cookies icon.
252 if (firstPartyCookiesEnabled && Build.VERSION.SDK_INT >= 21) {
253 if (thirdPartyCookiesEnabled) {
254 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_warning);
257 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
259 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
264 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_dark);
266 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_light);
270 // Set the DOM storage icon.
271 if (javaScriptEnabled || nightMode) { // The preference is enabled.
272 if (savedPreferences.getBoolean("dom_storage", false)) { // DOM storage is enabled.
273 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
274 } else { // DOM storage is disabled.
276 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_dark);
278 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_light);
281 } else { // The preference is disabled. The icon should be ghosted.
283 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_dark);
285 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_light);
289 // Set the save form data icon if API < 26. Save form data has no effect on API >= 26.
290 if (Build.VERSION.SDK_INT < 26) {
291 if (savedPreferences.getBoolean("save_form_data", false)) {
292 formDataPreference.setIcon(R.drawable.form_data_enabled);
295 formDataPreference.setIcon(R.drawable.form_data_disabled_dark);
297 formDataPreference.setIcon(R.drawable.form_data_disabled_light);
302 // Set the custom user agent icon.
303 if (customUserAgentPreference.isEnabled()) {
305 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_dark);
307 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_light);
311 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_dark);
313 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_light);
317 // Set the incognito mode icon.
318 if (savedPreferences.getBoolean("incognito_mode", false)) {
320 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_dark);
322 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_light);
326 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_dark);
328 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_light);
332 // Set the Do Not Track icon.
333 if (savedPreferences.getBoolean("do_not_track", false)) {
335 doNotTrackPreference.setIcon(R.drawable.block_tracking_enabled_dark);
337 doNotTrackPreference.setIcon(R.drawable.block_tracking_enabled_light);
341 doNotTrackPreference.setIcon(R.drawable.block_tracking_disabled_dark);
343 doNotTrackPreference.setIcon(R.drawable.block_tracking_disabled_light);
347 // Set the allow screenshots icon.
348 if (savedPreferences.getBoolean("allow_screenshots", false)) {
350 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_dark);
352 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_light);
356 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_dark);
358 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_light);
362 // Set the EasyList icon.
363 if (savedPreferences.getBoolean("easylist", true)) {
365 easyListPreference.setIcon(R.drawable.block_ads_enabled_dark);
367 easyListPreference.setIcon(R.drawable.block_ads_enabled_light);
371 easyListPreference.setIcon(R.drawable.block_ads_disabled_dark);
373 easyListPreference.setIcon(R.drawable.block_ads_disabled_light);
377 // Set the EasyPrivacy icon.
378 if (savedPreferences.getBoolean("easyprivacy", true)) {
380 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_dark);
382 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_light);
386 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_dark);
388 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_light);
392 // Set the Fanboy lists icons.
393 if (fanboyAnnoyanceListEnabled) {
395 // Set the Fanboy annoyance list icon.
396 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_dark);
398 // Set the Fanboy social blocking list icon.
399 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_dark);
401 // Set the Fanboy annoyance list icon.
402 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_light);
404 // Set the Fanboy social blocking list icon.
405 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_light);
409 // Set the Fanboy annoyance list icon.
410 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled_dark);
412 // Set the Fanboy social blocking list icon.
413 if (fanboySocialBlockingEnabled) {
414 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_dark);
416 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_dark);
419 // Set the Fanboy annoyance list icon.
420 fanboyAnnoyanceListPreference.setIcon(R.drawable.block_ads_disabled_light);
422 // Set the Fanboy social blocking list icon.
423 if (fanboySocialBlockingEnabled) {
424 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_light);
426 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_light);
431 // Set the UltraPrivacy icon.
432 if (savedPreferences.getBoolean("ultraprivacy", true)) {
434 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_dark);
436 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_light);
440 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_dark);
442 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_light);
446 // Set the block all third-party requests icon.
447 if (savedPreferences.getBoolean("block_all_third_party_requests", false)) {
449 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_dark);
451 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_light);
455 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_dark);
457 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_light);
461 // Set the Google Analytics icons according to the theme.
462 if (savedPreferences.getBoolean("google_analytics", true)) {
464 googleAnalyticsPreference.setIcon(R.drawable.modify_url_enabled_dark);
466 googleAnalyticsPreference.setIcon(R.drawable.modify_url_enabled_light);
470 googleAnalyticsPreference.setIcon(R.drawable.modify_url_disabled_dark);
472 googleAnalyticsPreference.setIcon(R.drawable.modify_url_disabled_light);
476 // Set the Tor icons according to the theme.
477 if (proxyThroughOrbot) { // Proxying is enabled.
479 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_enabled_dark);
480 torHomepagePreference.setIcon(R.drawable.home_enabled_dark);
481 torSearchPreference.setIcon(R.drawable.search_enabled_dark);
483 // Set the custom search icon.
484 if (torSearchCustomURLPreference.isEnabled()) {
485 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_dark);
487 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
490 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_enabled_light);
491 torHomepagePreference.setIcon(R.drawable.home_enabled_light);
492 torSearchPreference.setIcon(R.drawable.search_enabled_light);
494 // Set the custom search icon.
495 if (torSearchCustomURLPreference.isEnabled()) {
496 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_light);
498 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
501 } else { // Proxying is disabled.
503 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_disabled_dark);
504 torHomepagePreference.setIcon(R.drawable.home_ghosted_dark);
505 torSearchPreference.setIcon(R.drawable.search_ghosted_dark);
506 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
508 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_disabled_light);
509 torHomepagePreference.setIcon(R.drawable.home_ghosted_light);
510 torSearchPreference.setIcon(R.drawable.search_ghosted_light);
511 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
515 // Set the search custom URL icon.
516 if (searchCustomURLPreference.isEnabled()) {
518 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_dark);
520 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_light);
524 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
526 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
530 // Set the full screen browsing mode icons.
531 if (fullScreenBrowsingMode) { // Full screen browsing mode is enabled.
532 // Set the `fullScreenBrowsingModePreference` icon according to the theme.
534 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_dark);
536 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_light);
539 // Set the hide app bar icon.
540 if (savedPreferences.getBoolean("hide_app_bar", true)) { // Hide app bar is enabled.
541 // Set the icon according to the theme.
543 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
545 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
547 } else { // Hide app bar is disabled.
548 // Set the icon according to the theme.
550 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
552 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
555 } else { // Full screen browsing mode is disabled.
556 // Set the icons according to the theme.
558 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_dark);
559 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_dark);
561 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_light);
562 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_light);
566 // Set the clear everything preference icon.
567 if (clearEverything) {
569 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_dark);
571 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_light);
574 clearEverythingPreference.setIcon(R.drawable.clear_everything_disabled);
577 // Set the clear cookies preference icon.
578 if (clearEverything || savedPreferences.getBoolean("clear_cookies", true)) {
580 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_dark);
582 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_light);
585 clearCookiesPreference.setIcon(R.drawable.cookies_warning);
588 // Set the clear DOM storage preference icon.
589 if (clearEverything || savedPreferences.getBoolean("clear_dom_storage", true)) {
591 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_dark);
593 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_light);
596 clearDomStoragePreference.setIcon(R.drawable.dom_storage_warning);
599 // Set the clear form data preference icon if the API < 26. It has no effect on newer versions of Android.
600 if (Build.VERSION.SDK_INT < 26) {
601 if (clearEverything || savedPreferences.getBoolean("clear_form_data", true)) {
603 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_dark);
605 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_light);
608 clearFormDataPreference.setIcon(R.drawable.form_data_warning);
612 // Set the clear cache preference icon.
613 if (clearEverything || savedPreferences.getBoolean("clear_cache", true)) {
615 clearCachePreference.setIcon(R.drawable.cache_cleared_dark);
617 clearCachePreference.setIcon(R.drawable.cache_cleared_light);
620 clearCachePreference.setIcon(R.drawable.cache_warning);
623 // Set the open intents in new tab preference icon.
624 if (savedPreferences.getBoolean("open_intents_in_new_tab", true)) {
626 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_dark);
628 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_light);
632 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_dark);
634 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_light);
638 // Set the swipe to refresh preference icon.
639 if (savedPreferences.getBoolean("swipe_to_refresh", true)) {
641 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_dark);
643 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_light);
647 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_dark);
649 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_light);
653 // Set the scroll app bar preference icon.
654 if (savedPreferences.getBoolean("scroll_app_bar", true)) {
656 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
658 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
662 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
664 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
668 // Set the display additional app bar icons preference icon.
669 if (savedPreferences.getBoolean("display_additional_app_bar_icons", false)) {
671 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_dark);
673 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_light);
677 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_dark);
679 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_light);
683 // Set the download with external app preference icon.
684 if (savedPreferences.getBoolean("download_with_external_app", false)) {
686 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_enabled_dark);
688 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_enabled_light);
692 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_disabled_dark);
694 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_disabled_light);
698 // Set the dark theme preference icon.
699 if (savedPreferences.getBoolean("dark_theme", false)) {
700 darkThemePreference.setIcon(R.drawable.theme_dark);
702 darkThemePreference.setIcon(R.drawable.theme_light);
705 // Set the night mode preference icon.
708 nightModePreference.setIcon(R.drawable.night_mode_enabled_dark);
710 nightModePreference.setIcon(R.drawable.night_mode_enabled_light);
714 nightModePreference.setIcon(R.drawable.night_mode_disabled_dark);
716 nightModePreference.setIcon(R.drawable.night_mode_disabled_light);
720 // Set the display webpage images preference icon.
721 if (savedPreferences.getBoolean("display_webpage_images", true)) {
723 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_dark);
725 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_light);
729 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_dark);
731 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_light);
736 // Listen for preference changes.
737 preferencesListener = (SharedPreferences sharedPreferences, String key) -> {
740 // Update the icons and the DOM storage preference status.
741 if (sharedPreferences.getBoolean("javascript", false)) { // The JavaScript preference is enabled.
742 // Update the icon for the JavaScript preference.
743 javaScriptPreference.setIcon(R.drawable.javascript_enabled);
745 // Update the status of the DOM storage preference.
746 domStoragePreference.setEnabled(true);
748 // Update the icon for the DOM storage preference.
749 if (sharedPreferences.getBoolean("dom_storage", false)) {
750 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
753 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_dark);
755 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_light);
758 } else { // The JavaScript preference is disabled.
759 // Update the icon for the JavaScript preference.
760 javaScriptPreference.setIcon(R.drawable.privacy_mode);
762 // Update the status of the DOM storage preference.
763 domStoragePreference.setEnabled(false);
765 // Set the icon for DOM storage preference to be ghosted.
767 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_dark);
769 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_light);
774 case "first_party_cookies":
775 // Update the icons for `first_party_cookies` and `third_party_cookies`.
776 if (sharedPreferences.getBoolean("first_party_cookies", false)) {
777 // Set the icon for `first_party_cookies`.
778 firstPartyCookiesPreference.setIcon(R.drawable.cookies_enabled);
780 // Update the icon for `third_party_cookies`.
781 if (Build.VERSION.SDK_INT >= 21) {
782 if (sharedPreferences.getBoolean("third_party_cookies", false)) {
783 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_warning);
786 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
788 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
793 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_dark);
795 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_light);
798 } else { // `first_party_cookies` is `false`.
799 // Update the icon for `first_party_cookies`.
801 firstPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
803 firstPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
806 // Set the icon for `third_party_cookies` to be ghosted.
808 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_dark);
810 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_light);
814 // Enable `third_party_cookies` if `first_party_cookies` is `true` and API >= 21.
815 thirdPartyCookiesPreference.setEnabled(sharedPreferences.getBoolean("first_party_cookies", false) && (Build.VERSION.SDK_INT >= 21));
818 case "third_party_cookies":
820 if (sharedPreferences.getBoolean("third_party_cookies", false)) {
821 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_warning);
824 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
826 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
833 if (sharedPreferences.getBoolean("dom_storage", false)) {
834 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
837 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_dark);
839 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_light);
844 // Save form data can be removed once the minimum API >= 26.
845 case "save_form_data":
847 if (sharedPreferences.getBoolean("save_form_data", false)) {
848 formDataPreference.setIcon(R.drawable.form_data_enabled);
851 formDataPreference.setIcon(R.drawable.form_data_disabled_dark);
853 formDataPreference.setIcon(R.drawable.form_data_disabled_light);
859 // Get the new user agent name.
860 String newUserAgentName = sharedPreferences.getString("user_agent", getString(R.string.user_agent_default_value));
862 // Get the array position for the new user agent name.
863 int newUserAgentArrayPosition = userAgentNamesArray.getPosition(newUserAgentName);
865 // Get the translated new user agent name.
866 String translatedNewUserAgentName = translatedUserAgentNamesArray[newUserAgentArrayPosition];
868 // Populate the user agent summary.
869 switch (newUserAgentArrayPosition) {
870 case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
871 // Get the user agent text from the webview (which changes based on the version of Android and WebView installed).
872 userAgentPreference.setSummary(translatedNewUserAgentName + ":\n" + bareWebView.getSettings().getUserAgentString());
874 // Disable the custom user agent preference.
875 customUserAgentPreference.setEnabled(false);
877 // Set the custom user agent preference icon according to the theme.
879 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_dark);
881 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_light);
885 case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
886 // Set the summary text.
887 userAgentPreference.setSummary(R.string.custom_user_agent);
889 // Enable the custom user agent preference.
890 customUserAgentPreference.setEnabled(true);
892 // Set the custom user agent preference icon according to the theme.
894 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_dark);
896 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_light);
901 // Get the user agent summary from the user agent data array.
902 userAgentPreference.setSummary(translatedNewUserAgentName + ":\n" + userAgentDataArray[newUserAgentArrayPosition]);
904 // Disable the custom user agent preference.
905 customUserAgentPreference.setEnabled(false);
907 // Set the custom user agent preference icon according to the theme.
909 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_dark);
911 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_light);
916 case "custom_user_agent":
917 // Set the new custom user agent as the summary text for the preference.
918 customUserAgentPreference.setSummary(sharedPreferences.getString("custom_user_agent", getString(R.string.custom_user_agent_default_value)));
921 case "incognito_mode":
923 if (sharedPreferences.getBoolean("incognito_mode", false)) {
925 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_dark);
927 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_light);
931 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_dark);
933 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_light);
940 if (sharedPreferences.getBoolean("do_not_track", false)) {
942 doNotTrackPreference.setIcon(R.drawable.block_tracking_enabled_dark);
944 doNotTrackPreference.setIcon(R.drawable.block_tracking_enabled_light);
948 doNotTrackPreference.setIcon(R.drawable.block_tracking_disabled_dark);
950 doNotTrackPreference.setIcon(R.drawable.block_tracking_disabled_light);
956 case "allow_screenshots":
958 if (sharedPreferences.getBoolean("allow_screenshots", false)) {
960 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_dark);
962 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_light);
966 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_dark);
968 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_light);
972 // Create an intent to restart Privacy Browser.
973 Intent allowScreenshotsRestartIntent = getActivity().getParentActivityIntent();
975 // Assert that the intent is not null to remove the lint error below.
976 assert allowScreenshotsRestartIntent != null;
978 // `Intent.FLAG_ACTIVITY_CLEAR_TASK` removes all activities from the stack. It requires `Intent.FLAG_ACTIVITY_NEW_TASK`.
979 allowScreenshotsRestartIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
981 // Create a handler to restart the activity.
982 Handler allowScreenshotsRestartHandler = new Handler();
984 // Create a runnable to restart the activity.
985 Runnable allowScreenshotsRestartRunnable = () -> {
986 // Restart the activity.
987 startActivity(allowScreenshotsRestartIntent);
989 // Kill this instance of Privacy Browser. Otherwise, the app exhibits sporadic behavior after the restart.
993 // Restart the activity after 100 milliseconds, so that the app has enough time to save the change to the preference.
994 allowScreenshotsRestartHandler.postDelayed(allowScreenshotsRestartRunnable, 100);
999 if (sharedPreferences.getBoolean("easylist", true)) {
1001 easyListPreference.setIcon(R.drawable.block_ads_enabled_dark);
1003 easyListPreference.setIcon(R.drawable.block_ads_enabled_light);
1007 easyListPreference.setIcon(R.drawable.block_ads_disabled_dark);
1009 easyListPreference.setIcon(R.drawable.block_ads_disabled_light);
1016 if (sharedPreferences.getBoolean("easyprivacy", true)) {
1018 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_dark);
1020 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_light);
1024 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_dark);
1026 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_light);
1031 case "fanboys_annoyance_list":
1032 boolean currentFanboyAnnoyanceList = sharedPreferences.getBoolean("fanboys_annoyance_list", true);
1033 boolean currentFanboySocialBlockingList = sharedPreferences.getBoolean("fanboys_social_blocking_list", true);
1035 // Update the Fanboy icons.
1036 if (currentFanboyAnnoyanceList) { // Fanboy's annoyance list is enabled.
1038 // Update the Fanboy's annoyance list icon.
1039 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_dark);
1041 // Update the Fanboy's social blocking list icon.
1042 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_dark);
1044 // Update the Fanboy's annoyance list icon.
1045 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_light);
1047 // Update the Fanboy's social blocking list icon.
1048 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_light);
1050 } else { // Fanboy's annoyance list is disabled.
1052 // Update the Fanboy's annoyance list icon.
1053 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled_dark);
1055 // Update the Fanboy's social blocking list icon.
1056 if (currentFanboySocialBlockingList) {
1057 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_dark);
1059 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_dark);
1062 // Update the Fanboy's annoyance list icon.
1063 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled_light);
1065 // Update the Fanboy's social blocking list icon.
1066 if (currentFanboySocialBlockingList) {
1067 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_light);
1069 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_light);
1074 // Only enable Fanboy's social blocking list preference if Fanboy's annoyance list preference is disabled.
1075 fanboySocialBlockingListPreference.setEnabled(!currentFanboyAnnoyanceList);
1078 case "fanboys_social_blocking_list":
1080 if (sharedPreferences.getBoolean("fanboys_social_blocking_list", true)) {
1082 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_dark);
1084 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_light);
1088 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_dark);
1090 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_light);
1095 case "ultraprivacy":
1097 if (sharedPreferences.getBoolean("ultraprivacy", true)) {
1099 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_dark);
1101 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_light);
1105 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_dark);
1107 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_light);
1112 case "block_all_third_party_requests":
1114 if (sharedPreferences.getBoolean("block_all_third_party_requests", false)) {
1116 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_dark);
1118 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_light);
1122 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_dark);
1124 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_light);
1129 case "google_analytics":
1131 if (sharedPreferences.getBoolean("google_analytics", true)) {
1133 googleAnalyticsPreference.setIcon(R.drawable.modify_url_enabled_dark);
1135 googleAnalyticsPreference.setIcon(R.drawable.modify_url_enabled_light);
1139 googleAnalyticsPreference.setIcon(R.drawable.modify_url_disabled_dark);
1141 googleAnalyticsPreference.setIcon(R.drawable.modify_url_disabled_light);
1146 case "proxy_through_orbot":
1147 // Get current settings.
1148 boolean currentProxyThroughOrbot = sharedPreferences.getBoolean("proxy_through_orbot", false);
1149 String currentTorSearchString = sharedPreferences.getString("tor_search", getString(R.string.tor_search_default_value));
1151 // Enable the Tor custom URL search option only if `currentProxyThroughOrbot` is true and the search is set to `Custom URL`.
1152 torSearchCustomURLPreference.setEnabled(currentProxyThroughOrbot && currentTorSearchString.equals("Custom URL"));
1154 // Update the icons.
1155 if (currentProxyThroughOrbot) {
1156 // Set the Tor icons according to the theme.
1158 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_enabled_dark);
1159 torHomepagePreference.setIcon(R.drawable.home_enabled_dark);
1160 torSearchPreference.setIcon(R.drawable.search_enabled_dark);
1162 // Set the `torSearchCustomURLPreference` icon.
1163 if (torSearchCustomURLPreference.isEnabled()) {
1164 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_dark);
1166 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
1169 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_enabled_light);
1170 torHomepagePreference.setIcon(R.drawable.home_enabled_light);
1171 torSearchPreference.setIcon(R.drawable.search_enabled_light);
1173 // Set the `torSearchCustomURLPreference` icon.
1174 if (torSearchCustomURLPreference.isEnabled()) {
1175 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_light);
1177 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
1180 } else { // Proxy through Orbot is disabled.
1182 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_disabled_dark);
1183 torHomepagePreference.setIcon(R.drawable.home_ghosted_dark);
1184 torSearchPreference.setIcon(R.drawable.search_ghosted_dark);
1185 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
1187 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_disabled_light);
1188 torHomepagePreference.setIcon(R.drawable.home_ghosted_light);
1189 torSearchPreference.setIcon(R.drawable.search_ghosted_light);
1190 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
1195 case "tor_homepage":
1196 // Set the new tor homepage URL as the summary text for the `tor_homepage` preference. The default is Searx: `http://ulrn6sryqaifefld.onion/`.
1197 torHomepagePreference.setSummary(sharedPreferences.getString("tor_homepage", getString(R.string.tor_homepage_default_value)));
1201 // Get the present search string.
1202 String presentTorSearchString = sharedPreferences.getString("tor_search", getString(R.string.tor_search_default_value));
1204 // Update the preferences.
1205 if (presentTorSearchString.equals("Custom URL")) {
1206 // Use `R.string.custom_url`, which is translated, as the summary instead of the array value, which isn't.
1207 torSearchPreference.setSummary(R.string.custom_url);
1209 // Enable `torSearchCustomURLPreference`.
1210 torSearchCustomURLPreference.setEnabled(true);
1212 // Update the `torSearchCustomURLPreference` icon.
1214 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_dark);
1216 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_light);
1219 // Set the array value as the summary text.
1220 torSearchPreference.setSummary(presentTorSearchString);
1222 // Disable `torSearchCustomURLPreference`.
1223 torSearchCustomURLPreference.setEnabled(false);
1225 // Update the `torSearchCustomURLPreference` icon.
1227 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
1229 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
1234 case "tor_search_custom_url":
1235 // Set the summary text for `tor_search_custom_url`.
1236 torSearchCustomURLPreference.setSummary(sharedPreferences.getString("tor_search_custom_url", getString(R.string.tor_search_custom_url_default_value)));
1240 // Store the new search string.
1241 String newSearchString = sharedPreferences.getString("search", getString(R.string.search_default_value));
1243 // Update `searchPreference` and `searchCustomURLPreference`.
1244 if (newSearchString.equals("Custom URL")) { // `Custom URL` is selected.
1245 // Set the summary text to `R.string.custom_url`, which is translated.
1246 searchPreference.setSummary(R.string.custom_url);
1248 // Enable `searchCustomURLPreference`.
1249 searchCustomURLPreference.setEnabled(true);
1251 // Set the `searchCustomURLPreference` according to the theme.
1253 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_dark);
1255 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_light);
1257 } else { // `Custom URL` is not selected.
1258 // Set the summary text to `newSearchString`.
1259 searchPreference.setSummary(newSearchString);
1261 // Disable `searchCustomURLPreference`.
1262 searchCustomURLPreference.setEnabled(false);
1264 // Set the `searchCustomURLPreference` according to the theme.
1266 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
1268 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
1273 case "search_custom_url":
1274 // Set the new custom search URL as the summary text for `search_custom_url`. The default is `""`.
1275 searchCustomURLPreference.setSummary(sharedPreferences.getString("search_custom_url", getString(R.string.search_custom_url_default_value)));
1278 case "full_screen_browsing_mode":
1279 if (sharedPreferences.getBoolean("full_screen_browsing_mode", false)) { // Full screen browsing is enabled.
1280 // Set the full screen browsing mode preference icon according to the theme.
1282 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_dark);
1284 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_light);
1287 // Set the hide app bar preference icon.
1288 if (sharedPreferences.getBoolean("hide_app_bar", true)) { // Hide app bar is enabled.
1289 // Set the icon according to the theme.
1291 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
1293 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
1295 } else { // Hide app bar is disabled.
1296 // Set the icon according to the theme.
1298 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
1300 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
1303 } else { // Full screen browsing is disabled.
1304 // Update the icons according to the theme.
1306 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_dark);
1307 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_dark);
1309 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_light);
1310 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_light);
1315 case "hide_app_bar":
1317 if (sharedPreferences.getBoolean("hide_app_bar", true)) { // Hide app bar is enabled.
1318 // Set the icon according to the theme.
1320 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
1322 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
1324 } else { // Hide app bar is disabled.
1325 // Set the icon according to the theme.
1327 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
1329 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
1334 case "clear_everything":
1335 // Store the new `clear_everything` status
1336 boolean newClearEverythingBoolean = sharedPreferences.getBoolean("clear_everything", true);
1338 // Update the status of the `Clear and Exit` preferences.
1339 clearCookiesPreference.setEnabled(!newClearEverythingBoolean);
1340 clearDomStoragePreference.setEnabled(!newClearEverythingBoolean);
1341 clearFormDataPreference.setEnabled(!newClearEverythingBoolean); // This line can be removed once the minimum API >= 26.
1342 clearCachePreference.setEnabled(!newClearEverythingBoolean);
1344 // Update the `clearEverythingPreference` icon.
1345 if (newClearEverythingBoolean) {
1347 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_dark);
1349 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_light);
1352 clearEverythingPreference.setIcon(R.drawable.clear_everything_disabled);
1355 // Update the `clearCookiesPreference` icon.
1356 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_cookies", true)) {
1358 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_dark);
1360 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_light);
1363 clearCookiesPreference.setIcon(R.drawable.cookies_warning);
1366 // Update the `clearDomStoragePreference` icon.
1367 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_dom_storage", true)) {
1369 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_dark);
1371 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_light);
1374 clearDomStoragePreference.setIcon(R.drawable.dom_storage_warning);
1377 // Update the clear form data preference icon if the API < 26.
1378 if (Build.VERSION.SDK_INT < 26) {
1379 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_form_data", true)) {
1381 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_dark);
1383 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_light);
1386 clearFormDataPreference.setIcon(R.drawable.form_data_warning);
1390 // Update the `clearCachePreference` icon.
1391 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_cache", true)) {
1393 clearCachePreference.setIcon(R.drawable.cache_cleared_dark);
1395 clearCachePreference.setIcon(R.drawable.cache_cleared_light);
1398 clearCachePreference.setIcon(R.drawable.cache_warning);
1402 case "clear_cookies":
1404 if (sharedPreferences.getBoolean("clear_cookies", true)) {
1406 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_dark);
1408 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_light);
1411 clearCookiesPreference.setIcon(R.drawable.cookies_warning);
1415 case "clear_dom_storage":
1417 if (sharedPreferences.getBoolean("clear_dom_storage", true)) {
1419 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_dark);
1421 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_light);
1424 clearDomStoragePreference.setIcon(R.drawable.dom_storage_warning);
1428 // This section can be removed once the minimum API >= 26.
1429 case "clear_form_data":
1431 if (sharedPreferences.getBoolean("clear_form_data", true)) {
1433 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_dark);
1435 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_light);
1438 clearFormDataPreference.setIcon(R.drawable.form_data_warning);
1444 if (sharedPreferences.getBoolean("clear_cache", true)) {
1446 clearCachePreference.setIcon(R.drawable.cache_cleared_dark);
1448 clearCachePreference.setIcon(R.drawable.cache_cleared_light);
1451 clearCachePreference.setIcon(R.drawable.cache_warning);
1456 // Set the new homepage URL as the summary text for the Homepage preference.
1457 homepagePreference.setSummary(sharedPreferences.getString("homepage", getString(R.string.homepage_default_value)));
1461 // Update the font size summary text.
1462 fontSizePreference.setSummary(sharedPreferences.getString("font_size", getString(R.string.font_size_default_value)) + "%%");
1465 case "open_intents_in_new_tab":
1467 if (sharedPreferences.getBoolean("open_intents_in_new_tab", true)) {
1469 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_dark);
1471 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_light);
1475 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_dark);
1477 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_light);
1482 case "swipe_to_refresh":
1484 if (sharedPreferences.getBoolean("swipe_to_refresh", true)) {
1486 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_dark);
1488 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_light);
1492 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_dark);
1494 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_light);
1499 case "scroll_app_bar":
1501 if (sharedPreferences.getBoolean("scroll_app_bar", true)) {
1503 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
1505 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
1509 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
1511 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
1516 case "display_additional_app_bar_icons":
1518 if (sharedPreferences.getBoolean("display_additional_app_bar_icons", false)) {
1520 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_dark);
1522 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_light);
1526 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_dark);
1528 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_light);
1533 case "download_with_external_app":
1535 if (sharedPreferences.getBoolean("download_with_external_app", false)) {
1537 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_enabled_dark);
1539 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_enabled_light);
1543 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_disabled_dark);
1545 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_disabled_light);
1552 if (sharedPreferences.getBoolean("dark_theme", false)) {
1553 darkThemePreference.setIcon(R.drawable.theme_dark);
1555 darkThemePreference.setIcon(R.drawable.theme_light);
1558 // Create an intent to restart Privacy Browser.
1559 Intent changeThemeRestartIntent = getActivity().getParentActivityIntent();
1561 // Assert that the intent is not null to remove the lint error below.
1562 assert changeThemeRestartIntent != null;
1564 // `Intent.FLAG_ACTIVITY_CLEAR_TASK` removes all activities from the stack. It requires `Intent.FLAG_ACTIVITY_NEW_TASK`.
1565 changeThemeRestartIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
1567 // Create a handler to restart the activity.
1568 Handler changeThemeRestartHandler = new Handler();
1570 // Create a runnable to restart the activity.
1571 Runnable changeThemeRestartRunnable = () -> {
1572 // Restart the activity.
1573 startActivity(changeThemeRestartIntent);
1575 // Kill this instance of Privacy Browser. Otherwise, the app exhibits sporadic behavior after the restart.
1579 // Restart the activity after 100 milliseconds, so that the app has enough time to save the change to the preference.
1580 changeThemeRestartHandler.postDelayed(changeThemeRestartRunnable, 100);
1584 // Store the current night mode status.
1585 boolean currentNightModeBoolean = sharedPreferences.getBoolean("night_mode", false);
1586 boolean currentJavaScriptBoolean = sharedPreferences.getBoolean("javascript", false);
1589 if (currentNightModeBoolean) {
1591 nightModePreference.setIcon(R.drawable.night_mode_enabled_dark);
1593 nightModePreference.setIcon(R.drawable.night_mode_enabled_light);
1597 nightModePreference.setIcon(R.drawable.night_mode_disabled_dark);
1599 nightModePreference.setIcon(R.drawable.night_mode_disabled_light);
1603 // Update the status of `javaScriptPreference` and `domStoragePreference`.
1604 javaScriptPreference.setEnabled(!currentNightModeBoolean);
1605 domStoragePreference.setEnabled(currentNightModeBoolean || currentJavaScriptBoolean);
1607 // Update the `javaScriptPreference` icon.
1608 if (currentNightModeBoolean || currentJavaScriptBoolean) {
1609 javaScriptPreference.setIcon(R.drawable.javascript_enabled);
1611 javaScriptPreference.setIcon(R.drawable.privacy_mode);
1614 // Update the DOM storage preference icon.
1615 if (currentNightModeBoolean || currentJavaScriptBoolean) { // The preference is enabled.
1616 if (sharedPreferences.getBoolean("dom_storage", false)) { // DOM storage is enabled.
1617 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
1618 } else { // DOM storage is disabled.
1620 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_dark);
1622 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_light);
1625 } else { // The preference is disabled. The icon should be ghosted.
1627 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_dark);
1629 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_light);
1634 case "display_webpage_images":
1635 if (sharedPreferences.getBoolean("display_webpage_images", true)) {
1638 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_dark);
1640 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_light);
1645 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_dark);
1647 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_light);
1654 // Register the listener.
1655 savedPreferences.registerOnSharedPreferenceChangeListener(preferencesListener);
1658 // 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.
1660 public void onPause() {
1662 savedPreferences.unregisterOnSharedPreferenceChangeListener(preferencesListener);
1666 public void onResume() {
1668 savedPreferences.registerOnSharedPreferenceChangeListener(preferencesListener);