2 * Copyright © 2016-2020 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.app.Activity;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.content.SharedPreferences;
27 import android.os.Build;
28 import android.os.Bundle;
29 import android.os.Handler;
30 import android.view.LayoutInflater;
31 import android.view.View;
32 import android.webkit.WebView;
33 import android.widget.ArrayAdapter;
35 import androidx.preference.Preference;
36 import androidx.preference.PreferenceCategory;
37 import androidx.preference.PreferenceFragmentCompat;
39 import com.stoutner.privacybrowser.R;
40 import com.stoutner.privacybrowser.activities.MainWebViewActivity;
41 import com.stoutner.privacybrowser.helpers.ProxyHelper;
43 public class SettingsFragment extends PreferenceFragmentCompat {
44 // Define the class variables.
45 private SharedPreferences.OnSharedPreferenceChangeListener preferencesListener;
46 private SharedPreferences savedPreferences;
49 public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
50 // Load the preferences from the XML file.
51 setPreferencesFromResource(R.xml.preferences, rootKey);
53 // Get a handle for the activity.
54 Activity activity = getActivity();
56 // Remove the lint warning below that `getApplicationContext()` might produce a null pointer exception.
57 assert activity != null;
59 // Get a handle for the context.
60 Context context = activity.getApplicationContext();
62 // Initialize savedPreferences.
63 savedPreferences = getPreferenceScreen().getSharedPreferences();
65 // Get handles for the preferences.
66 Preference javaScriptPreference = findPreference("javascript");
67 Preference firstPartyCookiesPreference = findPreference("first_party_cookies");
68 Preference thirdPartyCookiesPreference = findPreference("third_party_cookies");
69 Preference domStoragePreference = findPreference("dom_storage");
70 Preference formDataPreference = findPreference("save_form_data"); // The form data preference can be removed once the minimum API >= 26.
71 Preference userAgentPreference = findPreference("user_agent");
72 Preference customUserAgentPreference = findPreference("custom_user_agent");
73 Preference incognitoModePreference = findPreference("incognito_mode");
74 Preference doNotTrackPreference = findPreference("do_not_track");
75 Preference allowScreenshotsPreference = findPreference("allow_screenshots");
76 Preference easyListPreference = findPreference("easylist");
77 Preference easyPrivacyPreference = findPreference("easyprivacy");
78 Preference fanboyAnnoyanceListPreference = findPreference("fanboys_annoyance_list");
79 Preference fanboySocialBlockingListPreference = findPreference("fanboys_social_blocking_list");
80 Preference ultraListPreference = findPreference("ultralist");
81 Preference ultraPrivacyPreference = findPreference("ultraprivacy");
82 Preference blockAllThirdPartyRequestsPreference = findPreference("block_all_third_party_requests");
83 Preference googleAnalyticsPreference = findPreference("google_analytics");
84 Preference facebookClickIdsPreference = findPreference("facebook_click_ids");
85 Preference twitterAmpRedirectsPreference = findPreference("twitter_amp_redirects");
86 Preference searchPreference = findPreference("search");
87 Preference searchCustomURLPreference = findPreference("search_custom_url");
88 Preference proxyPreference = findPreference("proxy");
89 Preference proxyCustomUrlPreference = findPreference("proxy_custom_url");
90 Preference fullScreenBrowsingModePreference = findPreference("full_screen_browsing_mode");
91 Preference hideAppBarPreference = findPreference("hide_app_bar");
92 Preference clearEverythingPreference = findPreference("clear_everything");
93 Preference clearCookiesPreference = findPreference("clear_cookies");
94 Preference clearDomStoragePreference = findPreference("clear_dom_storage");
95 Preference clearFormDataPreference = findPreference("clear_form_data"); // The clear form data preference can be removed once the minimum API >= 26.
96 Preference clearCachePreference = findPreference("clear_cache");
97 Preference homepagePreference = findPreference("homepage");
98 Preference fontSizePreference = findPreference("font_size");
99 Preference openIntentsInNewTabPreference = findPreference("open_intents_in_new_tab");
100 Preference swipeToRefreshPreference = findPreference("swipe_to_refresh");
101 Preference scrollAppBarPreference = findPreference("scroll_app_bar");
102 Preference displayAdditionalAppBarIconsPreference = findPreference("display_additional_app_bar_icons");
103 Preference darkThemePreference = findPreference("dark_theme");
104 Preference nightModePreference = findPreference("night_mode");
105 Preference wideViewportPreference = findPreference("wide_viewport");
106 Preference displayWebpageImagesPreference = findPreference("display_webpage_images");
108 // Remove the lint warnings below that the preferences might be null.
109 assert javaScriptPreference != null;
110 assert firstPartyCookiesPreference != null;
111 assert thirdPartyCookiesPreference != null;
112 assert domStoragePreference != null;
113 assert formDataPreference != null;
114 assert userAgentPreference != null;
115 assert customUserAgentPreference != null;
116 assert incognitoModePreference != null;
117 assert doNotTrackPreference != null;
118 assert allowScreenshotsPreference != null;
119 assert easyListPreference != null;
120 assert easyPrivacyPreference != null;
121 assert fanboyAnnoyanceListPreference != null;
122 assert fanboySocialBlockingListPreference != null;
123 assert ultraListPreference != null;
124 assert ultraPrivacyPreference != null;
125 assert blockAllThirdPartyRequestsPreference != null;
126 assert googleAnalyticsPreference != null;
127 assert facebookClickIdsPreference != null;
128 assert twitterAmpRedirectsPreference != null;
129 assert searchPreference != null;
130 assert searchCustomURLPreference != null;
131 assert proxyPreference != null;
132 assert proxyCustomUrlPreference != null;
133 assert fullScreenBrowsingModePreference != null;
134 assert hideAppBarPreference != null;
135 assert clearEverythingPreference != null;
136 assert clearCookiesPreference != null;
137 assert clearDomStoragePreference != null;
138 assert clearFormDataPreference != null;
139 assert clearCachePreference != null;
140 assert homepagePreference != null;
141 assert fontSizePreference != null;
142 assert openIntentsInNewTabPreference != null;
143 assert swipeToRefreshPreference != null;
144 assert scrollAppBarPreference != null;
145 assert displayAdditionalAppBarIconsPreference != null;
146 assert darkThemePreference != null;
147 assert nightModePreference != null;
148 assert wideViewportPreference != null;
149 assert displayWebpageImagesPreference != null;
151 // Set the hide app bar preference dependency.
152 hideAppBarPreference.setDependency("full_screen_browsing_mode");
154 // Get strings from the preferences.
155 String searchString = savedPreferences.getString("search", getString(R.string.search_default_value));
156 String proxyString = savedPreferences.getString("proxy", getString(R.string.proxy_default_value));
158 // Get booleans that are used in multiple places from the preferences.
159 boolean javaScriptEnabled = savedPreferences.getBoolean("javascript", false);
160 boolean firstPartyCookiesEnabled = savedPreferences.getBoolean("first_party_cookies", false);
161 boolean thirdPartyCookiesEnabled = savedPreferences.getBoolean("third_party_cookies", false);
162 boolean fanboyAnnoyanceListEnabled = savedPreferences.getBoolean("fanboys_annoyance_list", true);
163 boolean fanboySocialBlockingEnabled = savedPreferences.getBoolean("fanboys_social_blocking_list", true);
164 boolean fullScreenBrowsingMode = savedPreferences.getBoolean("full_screen_browsing_mode", false);
165 boolean clearEverything = savedPreferences.getBoolean("clear_everything", true);
166 boolean darkTheme = savedPreferences.getBoolean("dark_theme", false);
167 boolean nightMode = savedPreferences.getBoolean("night_mode", false);
169 // Only enable the third-party cookies preference if first-party cookies are enabled and API >= 21.
170 thirdPartyCookiesPreference.setEnabled(firstPartyCookiesEnabled && (Build.VERSION.SDK_INT >= 21));
172 // Only enable the DOM storage preference if either JavaScript or Night Mode is enabled.
173 domStoragePreference.setEnabled(javaScriptEnabled || nightMode);
175 // Remove the form data preferences if the API is >= 26 as they no longer do anything.
176 if (Build.VERSION.SDK_INT >= 26) {
177 // Get the categories.
178 PreferenceCategory privacyCategory = findPreference("privacy");
179 PreferenceCategory clearAndExitCategory = findPreference("clear_and_exit");
181 // Remove the lint warnings below that the preference categories might be null.
182 assert privacyCategory != null;
183 assert clearAndExitCategory != null;
185 // Remove the form data preferences.
186 privacyCategory.removePreference(formDataPreference);
187 clearAndExitCategory.removePreference(clearFormDataPreference);
190 // Only enable Fanboy's social blocking list preference if Fanboy's annoyance list is disabled.
191 fanboySocialBlockingListPreference.setEnabled(!fanboyAnnoyanceListEnabled);
193 // Inflate a WebView to get the default user agent.
194 LayoutInflater inflater = getActivity().getLayoutInflater();
195 // `@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.
196 @SuppressLint("InflateParams") View bareWebViewLayout = inflater.inflate(R.layout.bare_webview, null, false);
197 WebView bareWebView = bareWebViewLayout.findViewById(R.id.bare_webview);
199 // Get the user agent arrays.
200 ArrayAdapter<CharSequence> userAgentNamesArray = ArrayAdapter.createFromResource(context, R.array.user_agent_names, R.layout.spinner_item);
201 String[] translatedUserAgentNamesArray = getResources().getStringArray(R.array.translated_user_agent_names);
202 String[] userAgentDataArray = getResources().getStringArray(R.array.user_agent_data);
204 // Get the current user agent name from the preference.
205 String userAgentName = savedPreferences.getString("user_agent", getString(R.string.user_agent_default_value));
207 // Get the array position of the user agent name.
208 int userAgentArrayPosition = userAgentNamesArray.getPosition(userAgentName);
210 // Populate the user agent summary.
211 switch (userAgentArrayPosition) {
212 case MainWebViewActivity.UNRECOGNIZED_USER_AGENT: // The user agent name is not on the canonical list.
213 // 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.
214 userAgentPreference.setSummary(userAgentName);
217 case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
218 // Get the user agent text from the webview (which changes based on the version of Android and WebView installed).
219 userAgentPreference.setSummary(translatedUserAgentNamesArray[userAgentArrayPosition] + ":\n" + bareWebView.getSettings().getUserAgentString());
222 case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
223 // Set the summary text.
224 userAgentPreference.setSummary(R.string.custom_user_agent);
228 // Get the user agent summary from the user agent data array.
229 userAgentPreference.setSummary(translatedUserAgentNamesArray[userAgentArrayPosition] + ":\n" + userAgentDataArray[userAgentArrayPosition]);
232 // Set the summary text for the custom user agent preference and enable it if user agent preference is set to custom.
233 customUserAgentPreference.setSummary(savedPreferences.getString("custom_user_agent", getString(R.string.custom_user_agent_default_value)));
234 customUserAgentPreference.setEnabled(userAgentPreference.getSummary().equals(getString(R.string.custom_user_agent)));
236 // Set the search URL as the summary text for the search preference when the preference screen is loaded.
237 if (searchString.equals("Custom URL")) {
238 // Use R.string.custom_url, which will be translated, instead of the array value, which will not.
239 searchPreference.setSummary(R.string.custom_url);
241 // Set the array value as the summary text.
242 searchPreference.setSummary(searchString);
245 // Set the summary text for `search_custom_url` (the default is `""`) and enable it if `search` is set to `Custom URL`.
246 searchCustomURLPreference.setSummary(savedPreferences.getString("search_custom_url", getString(R.string.search_custom_url_default_value)));
247 searchCustomURLPreference.setEnabled(searchString.equals("Custom URL"));
249 // Set the summary text for the proxy preference when the preference screen is loaded.
250 switch (proxyString) {
251 case ProxyHelper.NONE:
252 proxyPreference.setSummary(getString(R.string.no_proxy_enabled));
255 case ProxyHelper.TOR:
256 if (Build.VERSION.SDK_INT == 19) { // Proxying through SOCKS doesn't work on Android KitKat.
257 proxyPreference.setSummary(getString(R.string.tor_enabled_kitkat));
259 proxyPreference.setSummary(getString(R.string.tor_enabled));
263 case ProxyHelper.I2P:
264 proxyPreference.setSummary(getString(R.string.i2p_enabled));
267 case ProxyHelper.CUSTOM:
268 proxyPreference.setSummary(getString(R.string.custom_proxy));
272 // Only enable the custom proxy URL if a custom proxy is selected.
273 proxyCustomUrlPreference.setEnabled(proxyString.equals("Custom"));
275 // Set the summary text for the custom proxy URL.
276 proxyCustomUrlPreference.setSummary(savedPreferences.getString("proxy_custom_url", getString(R.string.proxy_custom_url_default_value)));
278 // Set the status of the Clear and Exit preferences.
279 clearCookiesPreference.setEnabled(!clearEverything);
280 clearDomStoragePreference.setEnabled(!clearEverything);
281 clearFormDataPreference.setEnabled(!clearEverything); // The form data line can be removed once the minimum API is >= 26.
282 clearCachePreference.setEnabled(!clearEverything);
284 // Set the homepage URL as the summary text for the homepage preference.
285 homepagePreference.setSummary(savedPreferences.getString("homepage", getString(R.string.homepage_default_value)));
287 // Set the font size as the summary text for the preference.
288 fontSizePreference.setSummary(savedPreferences.getString("font_size", getString(R.string.font_size_default_value)) + "%");
290 // Disable the JavaScript preference if Night Mode is enabled. JavaScript will be enabled for all web pages.
291 javaScriptPreference.setEnabled(!nightMode);
293 // Set the JavaScript icon.
294 if (javaScriptEnabled || nightMode) {
295 javaScriptPreference.setIcon(R.drawable.javascript_enabled);
297 javaScriptPreference.setIcon(R.drawable.privacy_mode);
300 // Set the first-party cookies icon.
301 if (firstPartyCookiesEnabled) {
302 firstPartyCookiesPreference.setIcon(R.drawable.cookies_enabled);
305 firstPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
307 firstPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
311 // Set the third party cookies icon.
312 if (firstPartyCookiesEnabled && Build.VERSION.SDK_INT >= 21) {
313 if (thirdPartyCookiesEnabled) {
314 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_warning);
317 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
319 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
324 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_dark);
326 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_light);
330 // Set the DOM storage icon.
331 if (javaScriptEnabled || nightMode) { // The preference is enabled.
332 if (savedPreferences.getBoolean("dom_storage", false)) { // DOM storage is enabled.
333 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
334 } else { // DOM storage is disabled.
336 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_dark);
338 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_light);
341 } else { // The preference is disabled. The icon should be ghosted.
343 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_dark);
345 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_light);
349 // Set the save form data icon if API < 26. Save form data has no effect on API >= 26.
350 if (Build.VERSION.SDK_INT < 26) {
351 if (savedPreferences.getBoolean("save_form_data", false)) {
352 formDataPreference.setIcon(R.drawable.form_data_enabled);
355 formDataPreference.setIcon(R.drawable.form_data_disabled_dark);
357 formDataPreference.setIcon(R.drawable.form_data_disabled_light);
362 // Set the custom user agent icon.
363 if (customUserAgentPreference.isEnabled()) {
365 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_dark);
367 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_light);
371 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_dark);
373 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_light);
377 // Set the incognito mode icon.
378 if (savedPreferences.getBoolean("incognito_mode", false)) {
380 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_dark);
382 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_light);
386 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_dark);
388 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_light);
392 // Set the Do Not Track icon.
393 if (savedPreferences.getBoolean("do_not_track", false)) {
395 doNotTrackPreference.setIcon(R.drawable.block_tracking_enabled_dark);
397 doNotTrackPreference.setIcon(R.drawable.block_tracking_enabled_light);
401 doNotTrackPreference.setIcon(R.drawable.block_tracking_disabled_dark);
403 doNotTrackPreference.setIcon(R.drawable.block_tracking_disabled_light);
407 // Set the allow screenshots icon.
408 if (savedPreferences.getBoolean("allow_screenshots", false)) {
410 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_dark);
412 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_light);
416 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_dark);
418 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_light);
422 // Set the EasyList icon.
423 if (savedPreferences.getBoolean("easylist", true)) {
425 easyListPreference.setIcon(R.drawable.block_ads_enabled_dark);
427 easyListPreference.setIcon(R.drawable.block_ads_enabled_light);
431 easyListPreference.setIcon(R.drawable.block_ads_disabled_dark);
433 easyListPreference.setIcon(R.drawable.block_ads_disabled_light);
437 // Set the EasyPrivacy icon.
438 if (savedPreferences.getBoolean("easyprivacy", true)) {
440 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_dark);
442 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_light);
446 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_dark);
448 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_light);
452 // Set the Fanboy lists icons.
453 if (fanboyAnnoyanceListEnabled) {
455 // Set the Fanboy annoyance list icon.
456 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_dark);
458 // Set the Fanboy social blocking list icon.
459 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_dark);
461 // Set the Fanboy annoyance list icon.
462 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_light);
464 // Set the Fanboy social blocking list icon.
465 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_light);
469 // Set the Fanboy annoyance list icon.
470 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled_dark);
472 // Set the Fanboy social blocking list icon.
473 if (fanboySocialBlockingEnabled) {
474 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_dark);
476 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_dark);
479 // Set the Fanboy annoyance list icon.
480 fanboyAnnoyanceListPreference.setIcon(R.drawable.block_ads_disabled_light);
482 // Set the Fanboy social blocking list icon.
483 if (fanboySocialBlockingEnabled) {
484 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_light);
486 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_light);
491 // Set the UltraList icon.
492 if (savedPreferences.getBoolean("ultralist", true)){
494 ultraListPreference.setIcon(R.drawable.block_ads_enabled_dark);
496 ultraListPreference.setIcon(R.drawable.block_ads_enabled_light);
500 ultraListPreference.setIcon(R.drawable.block_ads_disabled_dark);
502 ultraListPreference.setIcon(R.drawable.block_ads_disabled_light);
506 // Set the UltraPrivacy icon.
507 if (savedPreferences.getBoolean("ultraprivacy", true)) {
509 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_dark);
511 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_light);
515 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_dark);
517 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_light);
521 // Set the block all third-party requests icon.
522 if (savedPreferences.getBoolean("block_all_third_party_requests", false)) {
524 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_dark);
526 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_light);
530 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_dark);
532 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_light);
536 // Set the Google Analytics icon according to the theme.
537 if (savedPreferences.getBoolean("google_analytics", true)) {
539 googleAnalyticsPreference.setIcon(R.drawable.modify_url_enabled_dark);
541 googleAnalyticsPreference.setIcon(R.drawable.modify_url_enabled_light);
545 googleAnalyticsPreference.setIcon(R.drawable.modify_url_disabled_dark);
547 googleAnalyticsPreference.setIcon(R.drawable.modify_url_disabled_light);
551 // Set the Facebook Click IDs icon according to the theme.
552 if (savedPreferences.getBoolean("facebook_click_ids", true)) {
554 facebookClickIdsPreference.setIcon(R.drawable.modify_url_enabled_dark);
556 facebookClickIdsPreference.setIcon(R.drawable.modify_url_enabled_light);
560 facebookClickIdsPreference.setIcon(R.drawable.modify_url_disabled_dark);
562 facebookClickIdsPreference.setIcon(R.drawable.modify_url_disabled_light);
566 // Set the Twitter AMP redirects icon according to the theme.
567 if (savedPreferences.getBoolean("twitter_amp_redirects", true)) {
569 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_enabled_dark);
571 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_enabled_light);
575 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_disabled_dark);
577 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_disabled_light);
581 // Set the search custom URL icon.
582 if (searchCustomURLPreference.isEnabled()) {
584 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_dark);
586 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_light);
590 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
592 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
596 // Set the Proxy icons according to the theme and status.
597 if (proxyString.equals("None")) { // Proxying is disabled.
598 if (darkTheme) { // Dark theme.
599 // Set the main proxy icon to be disabled.
600 proxyPreference.setIcon(R.drawable.proxy_disabled_dark);
602 // Set the custom proxy URL icon to be ghosted.
603 proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted_dark);
604 } else { // Light theme.
605 // Set the main proxy icon to be disabled.
606 proxyPreference.setIcon(R.drawable.proxy_disabled_light);
608 // Set the custom proxy URL icon to be ghosted.
609 proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted_light);
611 } else { // Proxying is enabled.
612 if (darkTheme) { // Dark theme.
613 // Set the main proxy icon to be enabled.
614 proxyPreference.setIcon(R.drawable.proxy_enabled_dark);
616 // Set the custom proxy URL icon according to its status.
617 if (proxyCustomUrlPreference.isEnabled()) { // Custom proxy is enabled.
618 proxyCustomUrlPreference.setIcon(R.drawable.proxy_enabled_dark);
619 } else { // Custom proxy is disabled.
620 proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted_dark);
622 } else { // Light theme.
623 // Set the main proxy icon to be enabled.
624 proxyPreference.setIcon(R.drawable.proxy_enabled_light);
626 // Set the custom proxy URL icon according to its status.
627 if (proxyCustomUrlPreference.isEnabled()) { // Custom proxy is enabled.
628 proxyCustomUrlPreference.setIcon(R.drawable.proxy_enabled_light);
629 } else { // Custom proxy is disabled.
630 proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted_light);
635 // Set the full screen browsing mode icons.
636 if (fullScreenBrowsingMode) { // Full screen browsing mode is enabled.
637 // Set the `fullScreenBrowsingModePreference` icon according to the theme.
639 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_dark);
641 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_light);
644 // Set the hide app bar icon.
645 if (savedPreferences.getBoolean("hide_app_bar", true)) { // Hide app bar is enabled.
646 // Set the icon according to the theme.
648 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
650 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
652 } else { // Hide app bar is disabled.
653 // Set the icon according to the theme.
655 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
657 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
660 } else { // Full screen browsing mode is disabled.
661 // Set the icons according to the theme.
663 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_dark);
664 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_dark);
666 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_light);
667 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_light);
671 // Set the clear everything preference icon.
672 if (clearEverything) {
674 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_dark);
676 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_light);
679 clearEverythingPreference.setIcon(R.drawable.clear_everything_disabled);
682 // Set the clear cookies preference icon.
683 if (clearEverything || savedPreferences.getBoolean("clear_cookies", true)) {
685 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_dark);
687 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_light);
690 clearCookiesPreference.setIcon(R.drawable.cookies_warning);
693 // Set the clear DOM storage preference icon.
694 if (clearEverything || savedPreferences.getBoolean("clear_dom_storage", true)) {
696 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_dark);
698 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_light);
701 clearDomStoragePreference.setIcon(R.drawable.dom_storage_warning);
704 // Set the clear form data preference icon if the API < 26. It has no effect on newer versions of Android.
705 if (Build.VERSION.SDK_INT < 26) {
706 if (clearEverything || savedPreferences.getBoolean("clear_form_data", true)) {
708 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_dark);
710 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_light);
713 clearFormDataPreference.setIcon(R.drawable.form_data_warning);
717 // Set the clear cache preference icon.
718 if (clearEverything || savedPreferences.getBoolean("clear_cache", true)) {
720 clearCachePreference.setIcon(R.drawable.cache_cleared_dark);
722 clearCachePreference.setIcon(R.drawable.cache_cleared_light);
725 clearCachePreference.setIcon(R.drawable.cache_warning);
728 // Set the open intents in new tab preference icon.
729 if (savedPreferences.getBoolean("open_intents_in_new_tab", true)) {
731 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_dark);
733 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_light);
737 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_dark);
739 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_light);
743 // Set the swipe to refresh preference icon.
744 if (savedPreferences.getBoolean("swipe_to_refresh", true)) {
746 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_dark);
748 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_light);
752 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_dark);
754 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_light);
758 // Set the scroll app bar preference icon.
759 if (savedPreferences.getBoolean("scroll_app_bar", true)) {
761 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
763 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
767 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
769 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
773 // Set the display additional app bar icons preference icon.
774 if (savedPreferences.getBoolean("display_additional_app_bar_icons", false)) {
776 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_dark);
778 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_light);
782 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_dark);
784 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_light);
788 // Set the dark theme preference icon.
789 if (savedPreferences.getBoolean("dark_theme", false)) {
790 darkThemePreference.setIcon(R.drawable.theme_dark);
792 darkThemePreference.setIcon(R.drawable.theme_light);
795 // Set the night mode preference icon.
798 nightModePreference.setIcon(R.drawable.night_mode_enabled_dark);
800 nightModePreference.setIcon(R.drawable.night_mode_enabled_light);
804 nightModePreference.setIcon(R.drawable.night_mode_disabled_dark);
806 nightModePreference.setIcon(R.drawable.night_mode_disabled_light);
810 // Set the wide viewport preference icon.
811 if (savedPreferences.getBoolean("wide_viewport", true)) {
813 wideViewportPreference.setIcon(R.drawable.wide_viewport_enabled_dark);
815 wideViewportPreference.setIcon(R.drawable.wide_viewport_enabled_light);
819 wideViewportPreference.setIcon(R.drawable.wide_viewport_disabled_dark);
821 wideViewportPreference.setIcon(R.drawable.wide_viewport_disabled_light);
825 // Set the display webpage images preference icon.
826 if (savedPreferences.getBoolean("display_webpage_images", true)) {
828 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_dark);
830 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_light);
834 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_dark);
836 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_light);
841 // Listen for preference changes.
842 preferencesListener = (SharedPreferences sharedPreferences, String key) -> {
845 // Update the icons and the DOM storage preference status.
846 if (sharedPreferences.getBoolean("javascript", false)) { // The JavaScript preference is enabled.
847 // Update the icon for the JavaScript preference.
848 javaScriptPreference.setIcon(R.drawable.javascript_enabled);
850 // Update the status of the DOM storage preference.
851 domStoragePreference.setEnabled(true);
853 // Update the icon for the DOM storage preference.
854 if (sharedPreferences.getBoolean("dom_storage", false)) {
855 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
858 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_dark);
860 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_light);
863 } else { // The JavaScript preference is disabled.
864 // Update the icon for the JavaScript preference.
865 javaScriptPreference.setIcon(R.drawable.privacy_mode);
867 // Update the status of the DOM storage preference.
868 domStoragePreference.setEnabled(false);
870 // Set the icon for DOM storage preference to be ghosted.
872 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_dark);
874 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_light);
879 case "first_party_cookies":
880 // Update the icons for `first_party_cookies` and `third_party_cookies`.
881 if (sharedPreferences.getBoolean("first_party_cookies", false)) {
882 // Set the icon for `first_party_cookies`.
883 firstPartyCookiesPreference.setIcon(R.drawable.cookies_enabled);
885 // Update the icon for `third_party_cookies`.
886 if (Build.VERSION.SDK_INT >= 21) {
887 if (sharedPreferences.getBoolean("third_party_cookies", false)) {
888 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_warning);
891 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
893 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
898 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_dark);
900 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_light);
903 } else { // `first_party_cookies` is `false`.
904 // Update the icon for `first_party_cookies`.
906 firstPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
908 firstPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
911 // Set the icon for `third_party_cookies` to be ghosted.
913 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_dark);
915 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_light);
919 // Enable `third_party_cookies` if `first_party_cookies` is `true` and API >= 21.
920 thirdPartyCookiesPreference.setEnabled(sharedPreferences.getBoolean("first_party_cookies", false) && (Build.VERSION.SDK_INT >= 21));
923 case "third_party_cookies":
925 if (sharedPreferences.getBoolean("third_party_cookies", false)) {
926 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_warning);
929 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
931 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
938 if (sharedPreferences.getBoolean("dom_storage", false)) {
939 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
942 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_dark);
944 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_light);
949 // Save form data can be removed once the minimum API >= 26.
950 case "save_form_data":
952 if (sharedPreferences.getBoolean("save_form_data", false)) {
953 formDataPreference.setIcon(R.drawable.form_data_enabled);
956 formDataPreference.setIcon(R.drawable.form_data_disabled_dark);
958 formDataPreference.setIcon(R.drawable.form_data_disabled_light);
964 // Get the new user agent name.
965 String newUserAgentName = sharedPreferences.getString("user_agent", getString(R.string.user_agent_default_value));
967 // Get the array position for the new user agent name.
968 int newUserAgentArrayPosition = userAgentNamesArray.getPosition(newUserAgentName);
970 // Get the translated new user agent name.
971 String translatedNewUserAgentName = translatedUserAgentNamesArray[newUserAgentArrayPosition];
973 // Populate the user agent summary.
974 switch (newUserAgentArrayPosition) {
975 case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
976 // Get the user agent text from the webview (which changes based on the version of Android and WebView installed).
977 userAgentPreference.setSummary(translatedNewUserAgentName + ":\n" + bareWebView.getSettings().getUserAgentString());
979 // Disable the custom user agent preference.
980 customUserAgentPreference.setEnabled(false);
982 // Set the custom user agent preference icon according to the theme.
984 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_dark);
986 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_light);
990 case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
991 // Set the summary text.
992 userAgentPreference.setSummary(R.string.custom_user_agent);
994 // Enable the custom user agent preference.
995 customUserAgentPreference.setEnabled(true);
997 // Set the custom user agent preference icon according to the theme.
999 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_dark);
1001 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_light);
1006 // Get the user agent summary from the user agent data array.
1007 userAgentPreference.setSummary(translatedNewUserAgentName + ":\n" + userAgentDataArray[newUserAgentArrayPosition]);
1009 // Disable the custom user agent preference.
1010 customUserAgentPreference.setEnabled(false);
1012 // Set the custom user agent preference icon according to the theme.
1014 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_dark);
1016 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_light);
1021 case "custom_user_agent":
1022 // Set the new custom user agent as the summary text for the preference.
1023 customUserAgentPreference.setSummary(sharedPreferences.getString("custom_user_agent", getString(R.string.custom_user_agent_default_value)));
1026 case "incognito_mode":
1028 if (sharedPreferences.getBoolean("incognito_mode", false)) {
1030 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_dark);
1032 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_light);
1036 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_dark);
1038 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_light);
1043 case "do_not_track":
1045 if (sharedPreferences.getBoolean("do_not_track", false)) {
1047 doNotTrackPreference.setIcon(R.drawable.block_tracking_enabled_dark);
1049 doNotTrackPreference.setIcon(R.drawable.block_tracking_enabled_light);
1053 doNotTrackPreference.setIcon(R.drawable.block_tracking_disabled_dark);
1055 doNotTrackPreference.setIcon(R.drawable.block_tracking_disabled_light);
1061 case "allow_screenshots":
1063 if (sharedPreferences.getBoolean("allow_screenshots", false)) {
1065 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_dark);
1067 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_light);
1071 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_dark);
1073 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_light);
1077 // Create an intent to restart Privacy Browser.
1078 Intent allowScreenshotsRestartIntent = getActivity().getParentActivityIntent();
1080 // Assert that the intent is not null to remove the lint error below.
1081 assert allowScreenshotsRestartIntent != null;
1083 // `Intent.FLAG_ACTIVITY_CLEAR_TASK` removes all activities from the stack. It requires `Intent.FLAG_ACTIVITY_NEW_TASK`.
1084 allowScreenshotsRestartIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
1086 // Create a handler to restart the activity.
1087 Handler allowScreenshotsRestartHandler = new Handler();
1089 // Create a runnable to restart the activity.
1090 Runnable allowScreenshotsRestartRunnable = () -> {
1091 // Restart the activity.
1092 startActivity(allowScreenshotsRestartIntent);
1094 // Kill this instance of Privacy Browser. Otherwise, the app exhibits sporadic behavior after the restart.
1098 // Restart the activity after 150 milliseconds, so that the app has enough time to save the change to the preference.
1099 allowScreenshotsRestartHandler.postDelayed(allowScreenshotsRestartRunnable, 150);
1104 if (sharedPreferences.getBoolean("easylist", true)) {
1106 easyListPreference.setIcon(R.drawable.block_ads_enabled_dark);
1108 easyListPreference.setIcon(R.drawable.block_ads_enabled_light);
1112 easyListPreference.setIcon(R.drawable.block_ads_disabled_dark);
1114 easyListPreference.setIcon(R.drawable.block_ads_disabled_light);
1121 if (sharedPreferences.getBoolean("easyprivacy", true)) {
1123 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_dark);
1125 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_light);
1129 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_dark);
1131 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_light);
1136 case "fanboys_annoyance_list":
1137 boolean currentFanboyAnnoyanceList = sharedPreferences.getBoolean("fanboys_annoyance_list", true);
1138 boolean currentFanboySocialBlockingList = sharedPreferences.getBoolean("fanboys_social_blocking_list", true);
1140 // Update the Fanboy icons.
1141 if (currentFanboyAnnoyanceList) { // Fanboy's annoyance list is enabled.
1143 // Update the Fanboy's annoyance list icon.
1144 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_dark);
1146 // Update the Fanboy's social blocking list icon.
1147 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_dark);
1149 // Update the Fanboy's annoyance list icon.
1150 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_light);
1152 // Update the Fanboy's social blocking list icon.
1153 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_light);
1155 } else { // Fanboy's annoyance list is disabled.
1157 // Update the Fanboy's annoyance list icon.
1158 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled_dark);
1160 // Update the Fanboy's social blocking list icon.
1161 if (currentFanboySocialBlockingList) {
1162 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_dark);
1164 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_dark);
1167 // Update the Fanboy's annoyance list icon.
1168 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled_light);
1170 // Update the Fanboy's social blocking list icon.
1171 if (currentFanboySocialBlockingList) {
1172 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_light);
1174 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_light);
1179 // Only enable Fanboy's social blocking list preference if Fanboy's annoyance list preference is disabled.
1180 fanboySocialBlockingListPreference.setEnabled(!currentFanboyAnnoyanceList);
1183 case "fanboys_social_blocking_list":
1185 if (sharedPreferences.getBoolean("fanboys_social_blocking_list", true)) {
1187 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_dark);
1189 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_light);
1193 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_dark);
1195 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_light);
1202 if (sharedPreferences.getBoolean("ultralist", true)) {
1204 ultraListPreference.setIcon(R.drawable.block_ads_enabled_dark);
1206 ultraListPreference.setIcon(R.drawable.block_ads_enabled_light);
1210 ultraListPreference.setIcon(R.drawable.block_ads_disabled_dark);
1212 ultraListPreference.setIcon(R.drawable.block_ads_disabled_light);
1217 case "ultraprivacy":
1219 if (sharedPreferences.getBoolean("ultraprivacy", true)) {
1221 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_dark);
1223 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_light);
1227 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_dark);
1229 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_light);
1234 case "block_all_third_party_requests":
1236 if (sharedPreferences.getBoolean("block_all_third_party_requests", false)) {
1238 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_dark);
1240 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_light);
1244 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_dark);
1246 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_light);
1251 case "google_analytics":
1253 if (sharedPreferences.getBoolean("google_analytics", true)) {
1255 googleAnalyticsPreference.setIcon(R.drawable.modify_url_enabled_dark);
1257 googleAnalyticsPreference.setIcon(R.drawable.modify_url_enabled_light);
1261 googleAnalyticsPreference.setIcon(R.drawable.modify_url_disabled_dark);
1263 googleAnalyticsPreference.setIcon(R.drawable.modify_url_disabled_light);
1268 case "facebook_click_ids":
1270 if (sharedPreferences.getBoolean("facebook_click_ids", true)) {
1272 facebookClickIdsPreference.setIcon(R.drawable.modify_url_enabled_dark);
1274 facebookClickIdsPreference.setIcon(R.drawable.modify_url_enabled_light);
1278 facebookClickIdsPreference.setIcon(R.drawable.modify_url_disabled_dark);
1280 facebookClickIdsPreference.setIcon(R.drawable.modify_url_disabled_light);
1285 case "twitter_amp_redirects":
1287 if (sharedPreferences.getBoolean("twitter_amp_redirects", true)) {
1289 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_enabled_dark);
1291 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_enabled_light);
1295 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_disabled_dark);
1297 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_disabled_light);
1303 // Store the new search string.
1304 String newSearchString = sharedPreferences.getString("search", getString(R.string.search_default_value));
1306 // Update `searchPreference` and `searchCustomURLPreference`.
1307 if (newSearchString.equals("Custom URL")) { // `Custom URL` is selected.
1308 // Set the summary text to `R.string.custom_url`, which is translated.
1309 searchPreference.setSummary(R.string.custom_url);
1311 // Enable `searchCustomURLPreference`.
1312 searchCustomURLPreference.setEnabled(true);
1314 // Set the `searchCustomURLPreference` according to the theme.
1316 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_dark);
1318 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_light);
1320 } else { // `Custom URL` is not selected.
1321 // Set the summary text to `newSearchString`.
1322 searchPreference.setSummary(newSearchString);
1324 // Disable `searchCustomURLPreference`.
1325 searchCustomURLPreference.setEnabled(false);
1327 // Set the `searchCustomURLPreference` according to the theme.
1329 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
1331 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
1336 case "search_custom_url":
1337 // Set the new custom search URL as the summary text for `search_custom_url`. The default is `""`.
1338 searchCustomURLPreference.setSummary(sharedPreferences.getString("search_custom_url", getString(R.string.search_custom_url_default_value)));
1342 // Get current proxy string.
1343 String currentProxyString = sharedPreferences.getString("proxy", getString(R.string.proxy_default_value));
1345 // Update the summary text for the proxy preference.
1346 switch (currentProxyString) {
1347 case ProxyHelper.NONE:
1348 proxyPreference.setSummary(getString(R.string.no_proxy_enabled));
1351 case ProxyHelper.TOR:
1352 if (Build.VERSION.SDK_INT == 19) { // Proxying through SOCKS doesn't work on Android KitKat.
1353 proxyPreference.setSummary(getString(R.string.tor_enabled_kitkat));
1355 proxyPreference.setSummary(getString(R.string.tor_enabled));
1359 case ProxyHelper.I2P:
1360 proxyPreference.setSummary(getString(R.string.i2p_enabled));
1363 case ProxyHelper.CUSTOM:
1364 proxyPreference.setSummary(getString(R.string.custom_proxy));
1368 // Update the status of the custom URL preference.
1369 proxyCustomUrlPreference.setEnabled(currentProxyString.equals("Custom"));
1371 // Update the icons.
1372 if (currentProxyString.equals("None")) { // Proxying is disabled.
1373 if (darkTheme) { // Dark theme.
1374 // Set the main proxy icon to be disabled
1375 proxyPreference.setIcon(R.drawable.proxy_disabled_dark);
1377 // Set the custom proxy URL icon to be ghosted.
1378 proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted_dark);
1379 } else { // Light theme.
1380 // Set the main proxy icon to be disabled.
1381 proxyPreference.setIcon(R.drawable.proxy_disabled_light);
1383 // Set the custom proxy URL icon to be ghosted.
1384 proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted_light);
1386 } else { // Proxying is enabled.
1387 if (darkTheme) { // Dark theme.
1388 // Set the main proxy icon to be enabled.
1389 proxyPreference.setIcon(R.drawable.proxy_enabled_dark);
1391 /// Set the custom proxy URL icon according to its status.
1392 if (proxyCustomUrlPreference.isEnabled()) { // Custom proxy is enabled.
1393 proxyCustomUrlPreference.setIcon(R.drawable.proxy_enabled_dark);
1394 } else { // Custom proxy is disabled.
1395 proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted_dark);
1397 } else { // Light theme.
1398 // Set the main proxy icon to be enabled.
1399 proxyPreference.setIcon(R.drawable.proxy_enabled_light);
1401 // Set the custom proxy URL icon according to its status.
1402 if (proxyCustomUrlPreference.isEnabled()) { // Custom proxy is enabled.
1403 proxyCustomUrlPreference.setIcon(R.drawable.proxy_enabled_light);
1404 } else { // Custom proxy is disabled.
1405 proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted_light);
1411 case "proxy_custom_url":
1412 // Set the summary text for the proxy custom URL.
1413 proxyCustomUrlPreference.setSummary(sharedPreferences.getString("proxy_custom_url", getString(R.string.proxy_custom_url_default_value)));
1416 case "full_screen_browsing_mode":
1417 if (sharedPreferences.getBoolean("full_screen_browsing_mode", false)) { // Full screen browsing is enabled.
1418 // Set the full screen browsing mode preference icon according to the theme.
1420 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_dark);
1422 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_light);
1425 // Set the hide app bar preference icon.
1426 if (sharedPreferences.getBoolean("hide_app_bar", true)) { // Hide app bar is enabled.
1427 // Set the icon according to the theme.
1429 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
1431 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
1433 } else { // Hide app bar is disabled.
1434 // Set the icon according to the theme.
1436 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
1438 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
1441 } else { // Full screen browsing is disabled.
1442 // Update the icons according to the theme.
1444 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_dark);
1445 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_dark);
1447 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_light);
1448 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_light);
1453 case "hide_app_bar":
1455 if (sharedPreferences.getBoolean("hide_app_bar", true)) { // Hide app bar is enabled.
1456 // Set the icon according to the theme.
1458 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
1460 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
1462 } else { // Hide app bar is disabled.
1463 // Set the icon according to the theme.
1465 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
1467 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
1472 case "clear_everything":
1473 // Store the new `clear_everything` status
1474 boolean newClearEverythingBoolean = sharedPreferences.getBoolean("clear_everything", true);
1476 // Update the status of the `Clear and Exit` preferences.
1477 clearCookiesPreference.setEnabled(!newClearEverythingBoolean);
1478 clearDomStoragePreference.setEnabled(!newClearEverythingBoolean);
1479 clearFormDataPreference.setEnabled(!newClearEverythingBoolean); // This line can be removed once the minimum API >= 26.
1480 clearCachePreference.setEnabled(!newClearEverythingBoolean);
1482 // Update the `clearEverythingPreference` icon.
1483 if (newClearEverythingBoolean) {
1485 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_dark);
1487 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_light);
1490 clearEverythingPreference.setIcon(R.drawable.clear_everything_disabled);
1493 // Update the `clearCookiesPreference` icon.
1494 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_cookies", true)) {
1496 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_dark);
1498 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_light);
1501 clearCookiesPreference.setIcon(R.drawable.cookies_warning);
1504 // Update the `clearDomStoragePreference` icon.
1505 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_dom_storage", true)) {
1507 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_dark);
1509 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_light);
1512 clearDomStoragePreference.setIcon(R.drawable.dom_storage_warning);
1515 // Update the clear form data preference icon if the API < 26.
1516 if (Build.VERSION.SDK_INT < 26) {
1517 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_form_data", true)) {
1519 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_dark);
1521 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_light);
1524 clearFormDataPreference.setIcon(R.drawable.form_data_warning);
1528 // Update the `clearCachePreference` icon.
1529 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_cache", true)) {
1531 clearCachePreference.setIcon(R.drawable.cache_cleared_dark);
1533 clearCachePreference.setIcon(R.drawable.cache_cleared_light);
1536 clearCachePreference.setIcon(R.drawable.cache_warning);
1540 case "clear_cookies":
1542 if (sharedPreferences.getBoolean("clear_cookies", true)) {
1544 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_dark);
1546 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_light);
1549 clearCookiesPreference.setIcon(R.drawable.cookies_warning);
1553 case "clear_dom_storage":
1555 if (sharedPreferences.getBoolean("clear_dom_storage", true)) {
1557 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_dark);
1559 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_light);
1562 clearDomStoragePreference.setIcon(R.drawable.dom_storage_warning);
1566 // This section can be removed once the minimum API >= 26.
1567 case "clear_form_data":
1569 if (sharedPreferences.getBoolean("clear_form_data", true)) {
1571 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_dark);
1573 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_light);
1576 clearFormDataPreference.setIcon(R.drawable.form_data_warning);
1582 if (sharedPreferences.getBoolean("clear_cache", true)) {
1584 clearCachePreference.setIcon(R.drawable.cache_cleared_dark);
1586 clearCachePreference.setIcon(R.drawable.cache_cleared_light);
1589 clearCachePreference.setIcon(R.drawable.cache_warning);
1594 // Set the new homepage URL as the summary text for the Homepage preference.
1595 homepagePreference.setSummary(sharedPreferences.getString("homepage", getString(R.string.homepage_default_value)));
1599 // Update the font size summary text.
1600 fontSizePreference.setSummary(sharedPreferences.getString("font_size", getString(R.string.font_size_default_value)) + "%");
1603 case "open_intents_in_new_tab":
1605 if (sharedPreferences.getBoolean("open_intents_in_new_tab", true)) {
1607 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_dark);
1609 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_light);
1613 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_dark);
1615 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_light);
1620 case "swipe_to_refresh":
1622 if (sharedPreferences.getBoolean("swipe_to_refresh", true)) {
1624 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_dark);
1626 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_light);
1630 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_dark);
1632 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_light);
1637 case "scroll_app_bar":
1639 if (sharedPreferences.getBoolean("scroll_app_bar", true)) {
1641 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
1643 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
1647 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
1649 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
1654 case "display_additional_app_bar_icons":
1656 if (sharedPreferences.getBoolean("display_additional_app_bar_icons", false)) {
1658 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_dark);
1660 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_light);
1664 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_dark);
1666 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_light);
1673 if (sharedPreferences.getBoolean("dark_theme", false)) {
1674 darkThemePreference.setIcon(R.drawable.theme_dark);
1676 darkThemePreference.setIcon(R.drawable.theme_light);
1679 // Create an intent to restart Privacy Browser.
1680 Intent changeThemeRestartIntent = getActivity().getParentActivityIntent();
1682 // Assert that the intent is not null to remove the lint error below.
1683 assert changeThemeRestartIntent != null;
1685 // `Intent.FLAG_ACTIVITY_CLEAR_TASK` removes all activities from the stack. It requires `Intent.FLAG_ACTIVITY_NEW_TASK`.
1686 changeThemeRestartIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
1688 // Create a handler to restart the activity.
1689 Handler changeThemeRestartHandler = new Handler();
1691 // Create a runnable to restart the activity.
1692 Runnable changeThemeRestartRunnable = () -> {
1693 // Restart the activity.
1694 startActivity(changeThemeRestartIntent);
1696 // Kill this instance of Privacy Browser. Otherwise, the app exhibits sporadic behavior after the restart.
1700 // Restart the activity after 150 milliseconds, so that the app has enough time to save the change to the preference.
1701 changeThemeRestartHandler.postDelayed(changeThemeRestartRunnable, 150);
1705 // Store the current night mode status.
1706 boolean currentNightModeBoolean = sharedPreferences.getBoolean("night_mode", false);
1707 boolean currentJavaScriptBoolean = sharedPreferences.getBoolean("javascript", false);
1710 if (currentNightModeBoolean) {
1712 nightModePreference.setIcon(R.drawable.night_mode_enabled_dark);
1714 nightModePreference.setIcon(R.drawable.night_mode_enabled_light);
1718 nightModePreference.setIcon(R.drawable.night_mode_disabled_dark);
1720 nightModePreference.setIcon(R.drawable.night_mode_disabled_light);
1724 // Update the status of `javaScriptPreference` and `domStoragePreference`.
1725 javaScriptPreference.setEnabled(!currentNightModeBoolean);
1726 domStoragePreference.setEnabled(currentNightModeBoolean || currentJavaScriptBoolean);
1728 // Update the `javaScriptPreference` icon.
1729 if (currentNightModeBoolean || currentJavaScriptBoolean) {
1730 javaScriptPreference.setIcon(R.drawable.javascript_enabled);
1732 javaScriptPreference.setIcon(R.drawable.privacy_mode);
1735 // Update the DOM storage preference icon.
1736 if (currentNightModeBoolean || currentJavaScriptBoolean) { // The preference is enabled.
1737 if (sharedPreferences.getBoolean("dom_storage", false)) { // DOM storage is enabled.
1738 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
1739 } else { // DOM storage is disabled.
1741 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_dark);
1743 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_light);
1746 } else { // The preference is disabled. The icon should be ghosted.
1748 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_dark);
1750 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_light);
1755 case "wide_viewport":
1757 if (sharedPreferences.getBoolean("wide_viewport", true)) {
1759 wideViewportPreference.setIcon(R.drawable.wide_viewport_enabled_dark);
1761 wideViewportPreference.setIcon(R.drawable.wide_viewport_enabled_light);
1765 wideViewportPreference.setIcon(R.drawable.wide_viewport_disabled_dark);
1767 wideViewportPreference.setIcon(R.drawable.wide_viewport_disabled_light);
1772 case "display_webpage_images":
1774 if (sharedPreferences.getBoolean("display_webpage_images", true)) {
1776 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_dark);
1778 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_light);
1782 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_dark);
1784 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_light);
1791 // Register the listener.
1792 savedPreferences.registerOnSharedPreferenceChangeListener(preferencesListener);
1795 // 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.
1797 public void onPause() {
1799 savedPreferences.unregisterOnSharedPreferenceChangeListener(preferencesListener);
1803 public void onResume() {
1805 savedPreferences.registerOnSharedPreferenceChangeListener(preferencesListener);