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.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 downloadWithExternalAppPreference = findPreference("download_with_external_app");
104 Preference darkThemePreference = findPreference("dark_theme");
105 Preference nightModePreference = findPreference("night_mode");
106 Preference wideViewportPreference = findPreference("wide_viewport");
107 Preference displayWebpageImagesPreference = findPreference("display_webpage_images");
109 // Remove the lint warnings below that the preferences might be null.
110 assert javaScriptPreference != null;
111 assert firstPartyCookiesPreference != null;
112 assert thirdPartyCookiesPreference != null;
113 assert domStoragePreference != null;
114 assert formDataPreference != null;
115 assert userAgentPreference != null;
116 assert customUserAgentPreference != null;
117 assert incognitoModePreference != null;
118 assert doNotTrackPreference != null;
119 assert allowScreenshotsPreference != null;
120 assert easyListPreference != null;
121 assert easyPrivacyPreference != null;
122 assert fanboyAnnoyanceListPreference != null;
123 assert fanboySocialBlockingListPreference != null;
124 assert ultraListPreference != null;
125 assert ultraPrivacyPreference != null;
126 assert blockAllThirdPartyRequestsPreference != null;
127 assert googleAnalyticsPreference != null;
128 assert facebookClickIdsPreference != null;
129 assert twitterAmpRedirectsPreference != null;
130 assert searchPreference != null;
131 assert searchCustomURLPreference != null;
132 assert proxyPreference != null;
133 assert proxyCustomUrlPreference != null;
134 assert fullScreenBrowsingModePreference != null;
135 assert hideAppBarPreference != null;
136 assert clearEverythingPreference != null;
137 assert clearCookiesPreference != null;
138 assert clearDomStoragePreference != null;
139 assert clearFormDataPreference != null;
140 assert clearCachePreference != null;
141 assert homepagePreference != null;
142 assert fontSizePreference != null;
143 assert openIntentsInNewTabPreference != null;
144 assert swipeToRefreshPreference != null;
145 assert scrollAppBarPreference != null;
146 assert displayAdditionalAppBarIconsPreference != null;
147 assert downloadWithExternalAppPreference != null;
148 assert darkThemePreference != null;
149 assert nightModePreference != null;
150 assert wideViewportPreference != null;
151 assert displayWebpageImagesPreference != null;
153 // Set the hide app bar preference dependency.
154 hideAppBarPreference.setDependency("full_screen_browsing_mode");
156 // Get strings from the preferences.
157 String searchString = savedPreferences.getString("search", getString(R.string.search_default_value));
158 String proxyString = savedPreferences.getString("proxy", getString(R.string.proxy_default_value));
160 // Get booleans that are used in multiple places from the preferences.
161 boolean javaScriptEnabled = savedPreferences.getBoolean("javascript", false);
162 boolean firstPartyCookiesEnabled = savedPreferences.getBoolean("first_party_cookies", false);
163 boolean thirdPartyCookiesEnabled = savedPreferences.getBoolean("third_party_cookies", false);
164 boolean fanboyAnnoyanceListEnabled = savedPreferences.getBoolean("fanboys_annoyance_list", true);
165 boolean fanboySocialBlockingEnabled = savedPreferences.getBoolean("fanboys_social_blocking_list", true);
166 boolean fullScreenBrowsingMode = savedPreferences.getBoolean("full_screen_browsing_mode", false);
167 boolean clearEverything = savedPreferences.getBoolean("clear_everything", true);
168 boolean darkTheme = savedPreferences.getBoolean("dark_theme", false);
169 boolean nightMode = savedPreferences.getBoolean("night_mode", false);
171 // Only enable the third-party cookies preference if first-party cookies are enabled and API >= 21.
172 thirdPartyCookiesPreference.setEnabled(firstPartyCookiesEnabled && (Build.VERSION.SDK_INT >= 21));
174 // Only enable the DOM storage preference if either JavaScript or Night Mode is enabled.
175 domStoragePreference.setEnabled(javaScriptEnabled || nightMode);
177 // Remove the form data preferences if the API is >= 26 as they no longer do anything.
178 if (Build.VERSION.SDK_INT >= 26) {
179 // Get the categories.
180 PreferenceCategory privacyCategory = findPreference("privacy");
181 PreferenceCategory clearAndExitCategory = findPreference("clear_and_exit");
183 // Remove the lint warnings below that the preference categories might be null.
184 assert privacyCategory != null;
185 assert clearAndExitCategory != null;
187 // Remove the form data preferences.
188 privacyCategory.removePreference(formDataPreference);
189 clearAndExitCategory.removePreference(clearFormDataPreference);
192 // Only enable Fanboy's social blocking list preference if Fanboy's annoyance list is disabled.
193 fanboySocialBlockingListPreference.setEnabled(!fanboyAnnoyanceListEnabled);
195 // Inflate a WebView to get the default user agent.
196 LayoutInflater inflater = getActivity().getLayoutInflater();
197 // `@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.
198 @SuppressLint("InflateParams") View bareWebViewLayout = inflater.inflate(R.layout.bare_webview, null, false);
199 WebView bareWebView = bareWebViewLayout.findViewById(R.id.bare_webview);
201 // Get the user agent arrays.
202 ArrayAdapter<CharSequence> userAgentNamesArray = ArrayAdapter.createFromResource(context, R.array.user_agent_names, R.layout.spinner_item);
203 String[] translatedUserAgentNamesArray = getResources().getStringArray(R.array.translated_user_agent_names);
204 String[] userAgentDataArray = getResources().getStringArray(R.array.user_agent_data);
206 // Get the current user agent name from the preference.
207 String userAgentName = savedPreferences.getString("user_agent", getString(R.string.user_agent_default_value));
209 // Get the array position of the user agent name.
210 int userAgentArrayPosition = userAgentNamesArray.getPosition(userAgentName);
212 // Populate the user agent summary.
213 switch (userAgentArrayPosition) {
214 case MainWebViewActivity.UNRECOGNIZED_USER_AGENT: // The user agent name is not on the canonical list.
215 // 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.
216 userAgentPreference.setSummary(userAgentName);
219 case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
220 // Get the user agent text from the webview (which changes based on the version of Android and WebView installed).
221 userAgentPreference.setSummary(translatedUserAgentNamesArray[userAgentArrayPosition] + ":\n" + bareWebView.getSettings().getUserAgentString());
224 case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
225 // Set the summary text.
226 userAgentPreference.setSummary(R.string.custom_user_agent);
230 // Get the user agent summary from the user agent data array.
231 userAgentPreference.setSummary(translatedUserAgentNamesArray[userAgentArrayPosition] + ":\n" + userAgentDataArray[userAgentArrayPosition]);
234 // Set the summary text for the custom user agent preference and enable it if user agent preference is set to custom.
235 customUserAgentPreference.setSummary(savedPreferences.getString("custom_user_agent", getString(R.string.custom_user_agent_default_value)));
236 customUserAgentPreference.setEnabled(userAgentPreference.getSummary().equals(getString(R.string.custom_user_agent)));
238 // Set the search URL as the summary text for the search preference when the preference screen is loaded.
239 if (searchString.equals("Custom URL")) {
240 // Use R.string.custom_url, which will be translated, instead of the array value, which will not.
241 searchPreference.setSummary(R.string.custom_url);
243 // Set the array value as the summary text.
244 searchPreference.setSummary(searchString);
247 // Set the summary text for `search_custom_url` (the default is `""`) and enable it if `search` is set to `Custom URL`.
248 searchCustomURLPreference.setSummary(savedPreferences.getString("search_custom_url", getString(R.string.search_custom_url_default_value)));
249 searchCustomURLPreference.setEnabled(searchString.equals("Custom URL"));
251 // Set the summary text for the proxy preference when the preference screen is loaded.
252 switch (proxyString) {
253 case ProxyHelper.NONE:
254 proxyPreference.setSummary(getString(R.string.no_proxy_enabled));
257 case ProxyHelper.TOR:
258 if (Build.VERSION.SDK_INT == 19) { // Proxying through SOCKS doesn't work on Android KitKat.
259 proxyPreference.setSummary(getString(R.string.tor_enabled_kitkat));
261 proxyPreference.setSummary(getString(R.string.tor_enabled));
265 case ProxyHelper.I2P:
266 proxyPreference.setSummary(getString(R.string.i2p_enabled));
269 case ProxyHelper.CUSTOM:
270 proxyPreference.setSummary(getString(R.string.custom_proxy));
274 // Only enable the custom proxy URL if a custom proxy is selected.
275 proxyCustomUrlPreference.setEnabled(proxyString.equals("Custom"));
277 // Set the summary text for the custom proxy URL.
278 proxyCustomUrlPreference.setSummary(savedPreferences.getString("proxy_custom_url", getString(R.string.proxy_custom_url_default_value)));
280 // Set the status of the Clear and Exit preferences.
281 clearCookiesPreference.setEnabled(!clearEverything);
282 clearDomStoragePreference.setEnabled(!clearEverything);
283 clearFormDataPreference.setEnabled(!clearEverything); // The form data line can be removed once the minimum API is >= 26.
284 clearCachePreference.setEnabled(!clearEverything);
286 // Set the homepage URL as the summary text for the homepage preference.
287 homepagePreference.setSummary(savedPreferences.getString("homepage", getString(R.string.homepage_default_value)));
289 // Set the font size as the summary text for the preference.
290 fontSizePreference.setSummary(savedPreferences.getString("font_size", getString(R.string.font_size_default_value)) + "%");
292 // Disable the JavaScript preference if Night Mode is enabled. JavaScript will be enabled for all web pages.
293 javaScriptPreference.setEnabled(!nightMode);
295 // Set the JavaScript icon.
296 if (javaScriptEnabled || nightMode) {
297 javaScriptPreference.setIcon(R.drawable.javascript_enabled);
299 javaScriptPreference.setIcon(R.drawable.privacy_mode);
302 // Set the first-party cookies icon.
303 if (firstPartyCookiesEnabled) {
304 firstPartyCookiesPreference.setIcon(R.drawable.cookies_enabled);
307 firstPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
309 firstPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
313 // Set the third party cookies icon.
314 if (firstPartyCookiesEnabled && Build.VERSION.SDK_INT >= 21) {
315 if (thirdPartyCookiesEnabled) {
316 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_warning);
319 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
321 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
326 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_dark);
328 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_light);
332 // Set the DOM storage icon.
333 if (javaScriptEnabled || nightMode) { // The preference is enabled.
334 if (savedPreferences.getBoolean("dom_storage", false)) { // DOM storage is enabled.
335 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
336 } else { // DOM storage is disabled.
338 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_dark);
340 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_light);
343 } else { // The preference is disabled. The icon should be ghosted.
345 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_dark);
347 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_light);
351 // Set the save form data icon if API < 26. Save form data has no effect on API >= 26.
352 if (Build.VERSION.SDK_INT < 26) {
353 if (savedPreferences.getBoolean("save_form_data", false)) {
354 formDataPreference.setIcon(R.drawable.form_data_enabled);
357 formDataPreference.setIcon(R.drawable.form_data_disabled_dark);
359 formDataPreference.setIcon(R.drawable.form_data_disabled_light);
364 // Set the custom user agent icon.
365 if (customUserAgentPreference.isEnabled()) {
367 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_dark);
369 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_light);
373 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_dark);
375 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_light);
379 // Set the incognito mode icon.
380 if (savedPreferences.getBoolean("incognito_mode", false)) {
382 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_dark);
384 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_light);
388 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_dark);
390 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_light);
394 // Set the Do Not Track icon.
395 if (savedPreferences.getBoolean("do_not_track", false)) {
397 doNotTrackPreference.setIcon(R.drawable.block_tracking_enabled_dark);
399 doNotTrackPreference.setIcon(R.drawable.block_tracking_enabled_light);
403 doNotTrackPreference.setIcon(R.drawable.block_tracking_disabled_dark);
405 doNotTrackPreference.setIcon(R.drawable.block_tracking_disabled_light);
409 // Set the allow screenshots icon.
410 if (savedPreferences.getBoolean("allow_screenshots", false)) {
412 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_dark);
414 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_light);
418 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_dark);
420 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_light);
424 // Set the EasyList icon.
425 if (savedPreferences.getBoolean("easylist", true)) {
427 easyListPreference.setIcon(R.drawable.block_ads_enabled_dark);
429 easyListPreference.setIcon(R.drawable.block_ads_enabled_light);
433 easyListPreference.setIcon(R.drawable.block_ads_disabled_dark);
435 easyListPreference.setIcon(R.drawable.block_ads_disabled_light);
439 // Set the EasyPrivacy icon.
440 if (savedPreferences.getBoolean("easyprivacy", true)) {
442 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_dark);
444 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_light);
448 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_dark);
450 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_light);
454 // Set the Fanboy lists icons.
455 if (fanboyAnnoyanceListEnabled) {
457 // Set the Fanboy annoyance list icon.
458 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_dark);
460 // Set the Fanboy social blocking list icon.
461 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_dark);
463 // Set the Fanboy annoyance list icon.
464 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_light);
466 // Set the Fanboy social blocking list icon.
467 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_light);
471 // Set the Fanboy annoyance list icon.
472 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled_dark);
474 // Set the Fanboy social blocking list icon.
475 if (fanboySocialBlockingEnabled) {
476 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_dark);
478 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_dark);
481 // Set the Fanboy annoyance list icon.
482 fanboyAnnoyanceListPreference.setIcon(R.drawable.block_ads_disabled_light);
484 // Set the Fanboy social blocking list icon.
485 if (fanboySocialBlockingEnabled) {
486 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_light);
488 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_light);
493 // Set the UltraList icon.
494 if (savedPreferences.getBoolean("ultralist", true)){
496 ultraListPreference.setIcon(R.drawable.block_ads_enabled_dark);
498 ultraListPreference.setIcon(R.drawable.block_ads_enabled_light);
502 ultraListPreference.setIcon(R.drawable.block_ads_disabled_dark);
504 ultraListPreference.setIcon(R.drawable.block_ads_disabled_light);
508 // Set the UltraPrivacy icon.
509 if (savedPreferences.getBoolean("ultraprivacy", true)) {
511 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_dark);
513 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_light);
517 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_dark);
519 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_light);
523 // Set the block all third-party requests icon.
524 if (savedPreferences.getBoolean("block_all_third_party_requests", false)) {
526 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_dark);
528 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_light);
532 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_dark);
534 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_light);
538 // Set the Google Analytics icon according to the theme.
539 if (savedPreferences.getBoolean("google_analytics", true)) {
541 googleAnalyticsPreference.setIcon(R.drawable.modify_url_enabled_dark);
543 googleAnalyticsPreference.setIcon(R.drawable.modify_url_enabled_light);
547 googleAnalyticsPreference.setIcon(R.drawable.modify_url_disabled_dark);
549 googleAnalyticsPreference.setIcon(R.drawable.modify_url_disabled_light);
553 // Set the Facebook Click IDs icon according to the theme.
554 if (savedPreferences.getBoolean("facebook_click_ids", true)) {
556 facebookClickIdsPreference.setIcon(R.drawable.modify_url_enabled_dark);
558 facebookClickIdsPreference.setIcon(R.drawable.modify_url_enabled_light);
562 facebookClickIdsPreference.setIcon(R.drawable.modify_url_disabled_dark);
564 facebookClickIdsPreference.setIcon(R.drawable.modify_url_disabled_light);
568 // Set the Twitter AMP redirects icon according to the theme.
569 if (savedPreferences.getBoolean("twitter_amp_redirects", true)) {
571 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_enabled_dark);
573 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_enabled_light);
577 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_disabled_dark);
579 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_disabled_light);
583 // Set the search custom URL icon.
584 if (searchCustomURLPreference.isEnabled()) {
586 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_dark);
588 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_light);
592 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
594 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
598 // Set the Proxy icons according to the theme and status.
599 if (proxyString.equals("None")) { // Proxying is disabled.
600 if (darkTheme) { // Dark theme.
601 // Set the main proxy icon to be disabled.
602 proxyPreference.setIcon(R.drawable.proxy_disabled_dark);
604 // Set the custom proxy URL icon to be ghosted.
605 proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted_dark);
606 } else { // Light theme.
607 // Set the main proxy icon to be disabled.
608 proxyPreference.setIcon(R.drawable.proxy_disabled_light);
610 // Set the custom proxy URL icon to be ghosted.
611 proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted_light);
613 } else { // Proxying is enabled.
614 if (darkTheme) { // Dark theme.
615 // Set the main proxy icon to be enabled.
616 proxyPreference.setIcon(R.drawable.proxy_enabled_dark);
618 // Set the custom proxy URL icon according to its status.
619 if (proxyCustomUrlPreference.isEnabled()) { // Custom proxy is enabled.
620 proxyCustomUrlPreference.setIcon(R.drawable.proxy_enabled_dark);
621 } else { // Custom proxy is disabled.
622 proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted_dark);
624 } else { // Light theme.
625 // Set the main proxy icon to be enabled.
626 proxyPreference.setIcon(R.drawable.proxy_enabled_light);
628 // Set the custom proxy URL icon according to its status.
629 if (proxyCustomUrlPreference.isEnabled()) { // Custom proxy is enabled.
630 proxyCustomUrlPreference.setIcon(R.drawable.proxy_enabled_light);
631 } else { // Custom proxy is disabled.
632 proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted_light);
637 // Set the full screen browsing mode icons.
638 if (fullScreenBrowsingMode) { // Full screen browsing mode is enabled.
639 // Set the `fullScreenBrowsingModePreference` icon according to the theme.
641 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_dark);
643 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_light);
646 // Set the hide app bar icon.
647 if (savedPreferences.getBoolean("hide_app_bar", true)) { // Hide app bar is enabled.
648 // Set the icon according to the theme.
650 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
652 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
654 } else { // Hide app bar is disabled.
655 // Set the icon according to the theme.
657 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
659 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
662 } else { // Full screen browsing mode is disabled.
663 // Set the icons according to the theme.
665 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_dark);
666 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_dark);
668 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_light);
669 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_light);
673 // Set the clear everything preference icon.
674 if (clearEverything) {
676 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_dark);
678 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_light);
681 clearEverythingPreference.setIcon(R.drawable.clear_everything_disabled);
684 // Set the clear cookies preference icon.
685 if (clearEverything || savedPreferences.getBoolean("clear_cookies", true)) {
687 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_dark);
689 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_light);
692 clearCookiesPreference.setIcon(R.drawable.cookies_warning);
695 // Set the clear DOM storage preference icon.
696 if (clearEverything || savedPreferences.getBoolean("clear_dom_storage", true)) {
698 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_dark);
700 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_light);
703 clearDomStoragePreference.setIcon(R.drawable.dom_storage_warning);
706 // Set the clear form data preference icon if the API < 26. It has no effect on newer versions of Android.
707 if (Build.VERSION.SDK_INT < 26) {
708 if (clearEverything || savedPreferences.getBoolean("clear_form_data", true)) {
710 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_dark);
712 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_light);
715 clearFormDataPreference.setIcon(R.drawable.form_data_warning);
719 // Set the clear cache preference icon.
720 if (clearEverything || savedPreferences.getBoolean("clear_cache", true)) {
722 clearCachePreference.setIcon(R.drawable.cache_cleared_dark);
724 clearCachePreference.setIcon(R.drawable.cache_cleared_light);
727 clearCachePreference.setIcon(R.drawable.cache_warning);
730 // Set the open intents in new tab preference icon.
731 if (savedPreferences.getBoolean("open_intents_in_new_tab", true)) {
733 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_dark);
735 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_light);
739 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_dark);
741 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_light);
745 // Set the swipe to refresh preference icon.
746 if (savedPreferences.getBoolean("swipe_to_refresh", true)) {
748 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_dark);
750 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_light);
754 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_dark);
756 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_light);
760 // Set the scroll app bar preference icon.
761 if (savedPreferences.getBoolean("scroll_app_bar", true)) {
763 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
765 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
769 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
771 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
775 // Set the display additional app bar icons preference icon.
776 if (savedPreferences.getBoolean("display_additional_app_bar_icons", false)) {
778 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_dark);
780 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_light);
784 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_dark);
786 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_light);
790 // Set the download with external app preference icon.
791 if (savedPreferences.getBoolean("download_with_external_app", false)) {
793 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_enabled_dark);
795 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_enabled_light);
799 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_disabled_dark);
801 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_disabled_light);
805 // Set the dark theme preference icon.
806 if (savedPreferences.getBoolean("dark_theme", false)) {
807 darkThemePreference.setIcon(R.drawable.theme_dark);
809 darkThemePreference.setIcon(R.drawable.theme_light);
812 // Set the night mode preference icon.
815 nightModePreference.setIcon(R.drawable.night_mode_enabled_dark);
817 nightModePreference.setIcon(R.drawable.night_mode_enabled_light);
821 nightModePreference.setIcon(R.drawable.night_mode_disabled_dark);
823 nightModePreference.setIcon(R.drawable.night_mode_disabled_light);
827 // Set the wide viewport preference icon.
828 if (savedPreferences.getBoolean("wide_viewport", true)) {
830 wideViewportPreference.setIcon(R.drawable.wide_viewport_enabled_dark);
832 wideViewportPreference.setIcon(R.drawable.wide_viewport_enabled_light);
836 wideViewportPreference.setIcon(R.drawable.wide_viewport_disabled_dark);
838 wideViewportPreference.setIcon(R.drawable.wide_viewport_disabled_light);
842 // Set the display webpage images preference icon.
843 if (savedPreferences.getBoolean("display_webpage_images", true)) {
845 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_dark);
847 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_light);
851 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_dark);
853 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_light);
858 // Listen for preference changes.
859 preferencesListener = (SharedPreferences sharedPreferences, String key) -> {
862 // Update the icons and the DOM storage preference status.
863 if (sharedPreferences.getBoolean("javascript", false)) { // The JavaScript preference is enabled.
864 // Update the icon for the JavaScript preference.
865 javaScriptPreference.setIcon(R.drawable.javascript_enabled);
867 // Update the status of the DOM storage preference.
868 domStoragePreference.setEnabled(true);
870 // Update the icon for the DOM storage preference.
871 if (sharedPreferences.getBoolean("dom_storage", false)) {
872 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
875 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_dark);
877 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_light);
880 } else { // The JavaScript preference is disabled.
881 // Update the icon for the JavaScript preference.
882 javaScriptPreference.setIcon(R.drawable.privacy_mode);
884 // Update the status of the DOM storage preference.
885 domStoragePreference.setEnabled(false);
887 // Set the icon for DOM storage preference to be ghosted.
889 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_dark);
891 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_light);
896 case "first_party_cookies":
897 // Update the icons for `first_party_cookies` and `third_party_cookies`.
898 if (sharedPreferences.getBoolean("first_party_cookies", false)) {
899 // Set the icon for `first_party_cookies`.
900 firstPartyCookiesPreference.setIcon(R.drawable.cookies_enabled);
902 // Update the icon for `third_party_cookies`.
903 if (Build.VERSION.SDK_INT >= 21) {
904 if (sharedPreferences.getBoolean("third_party_cookies", false)) {
905 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_warning);
908 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
910 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
915 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_dark);
917 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_light);
920 } else { // `first_party_cookies` is `false`.
921 // Update the icon for `first_party_cookies`.
923 firstPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
925 firstPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
928 // Set the icon for `third_party_cookies` to be ghosted.
930 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_dark);
932 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_light);
936 // Enable `third_party_cookies` if `first_party_cookies` is `true` and API >= 21.
937 thirdPartyCookiesPreference.setEnabled(sharedPreferences.getBoolean("first_party_cookies", false) && (Build.VERSION.SDK_INT >= 21));
940 case "third_party_cookies":
942 if (sharedPreferences.getBoolean("third_party_cookies", false)) {
943 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_warning);
946 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
948 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
955 if (sharedPreferences.getBoolean("dom_storage", false)) {
956 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
959 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_dark);
961 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_light);
966 // Save form data can be removed once the minimum API >= 26.
967 case "save_form_data":
969 if (sharedPreferences.getBoolean("save_form_data", false)) {
970 formDataPreference.setIcon(R.drawable.form_data_enabled);
973 formDataPreference.setIcon(R.drawable.form_data_disabled_dark);
975 formDataPreference.setIcon(R.drawable.form_data_disabled_light);
981 // Get the new user agent name.
982 String newUserAgentName = sharedPreferences.getString("user_agent", getString(R.string.user_agent_default_value));
984 // Get the array position for the new user agent name.
985 int newUserAgentArrayPosition = userAgentNamesArray.getPosition(newUserAgentName);
987 // Get the translated new user agent name.
988 String translatedNewUserAgentName = translatedUserAgentNamesArray[newUserAgentArrayPosition];
990 // Populate the user agent summary.
991 switch (newUserAgentArrayPosition) {
992 case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
993 // Get the user agent text from the webview (which changes based on the version of Android and WebView installed).
994 userAgentPreference.setSummary(translatedNewUserAgentName + ":\n" + bareWebView.getSettings().getUserAgentString());
996 // Disable the custom user agent preference.
997 customUserAgentPreference.setEnabled(false);
999 // Set the custom user agent preference icon according to the theme.
1001 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_dark);
1003 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_light);
1007 case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
1008 // Set the summary text.
1009 userAgentPreference.setSummary(R.string.custom_user_agent);
1011 // Enable the custom user agent preference.
1012 customUserAgentPreference.setEnabled(true);
1014 // Set the custom user agent preference icon according to the theme.
1016 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_dark);
1018 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_light);
1023 // Get the user agent summary from the user agent data array.
1024 userAgentPreference.setSummary(translatedNewUserAgentName + ":\n" + userAgentDataArray[newUserAgentArrayPosition]);
1026 // Disable the custom user agent preference.
1027 customUserAgentPreference.setEnabled(false);
1029 // Set the custom user agent preference icon according to the theme.
1031 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_dark);
1033 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_light);
1038 case "custom_user_agent":
1039 // Set the new custom user agent as the summary text for the preference.
1040 customUserAgentPreference.setSummary(sharedPreferences.getString("custom_user_agent", getString(R.string.custom_user_agent_default_value)));
1043 case "incognito_mode":
1045 if (sharedPreferences.getBoolean("incognito_mode", false)) {
1047 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_dark);
1049 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_light);
1053 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_dark);
1055 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_light);
1060 case "do_not_track":
1062 if (sharedPreferences.getBoolean("do_not_track", false)) {
1064 doNotTrackPreference.setIcon(R.drawable.block_tracking_enabled_dark);
1066 doNotTrackPreference.setIcon(R.drawable.block_tracking_enabled_light);
1070 doNotTrackPreference.setIcon(R.drawable.block_tracking_disabled_dark);
1072 doNotTrackPreference.setIcon(R.drawable.block_tracking_disabled_light);
1078 case "allow_screenshots":
1080 if (sharedPreferences.getBoolean("allow_screenshots", false)) {
1082 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_dark);
1084 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_light);
1088 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_dark);
1090 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_light);
1094 // Create an intent to restart Privacy Browser.
1095 Intent allowScreenshotsRestartIntent = getActivity().getParentActivityIntent();
1097 // Assert that the intent is not null to remove the lint error below.
1098 assert allowScreenshotsRestartIntent != null;
1100 // `Intent.FLAG_ACTIVITY_CLEAR_TASK` removes all activities from the stack. It requires `Intent.FLAG_ACTIVITY_NEW_TASK`.
1101 allowScreenshotsRestartIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
1103 // Create a handler to restart the activity.
1104 Handler allowScreenshotsRestartHandler = new Handler();
1106 // Create a runnable to restart the activity.
1107 Runnable allowScreenshotsRestartRunnable = () -> {
1108 // Restart the activity.
1109 startActivity(allowScreenshotsRestartIntent);
1111 // Kill this instance of Privacy Browser. Otherwise, the app exhibits sporadic behavior after the restart.
1115 // Restart the activity after 150 milliseconds, so that the app has enough time to save the change to the preference.
1116 allowScreenshotsRestartHandler.postDelayed(allowScreenshotsRestartRunnable, 150);
1121 if (sharedPreferences.getBoolean("easylist", true)) {
1123 easyListPreference.setIcon(R.drawable.block_ads_enabled_dark);
1125 easyListPreference.setIcon(R.drawable.block_ads_enabled_light);
1129 easyListPreference.setIcon(R.drawable.block_ads_disabled_dark);
1131 easyListPreference.setIcon(R.drawable.block_ads_disabled_light);
1138 if (sharedPreferences.getBoolean("easyprivacy", true)) {
1140 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_dark);
1142 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_light);
1146 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_dark);
1148 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_light);
1153 case "fanboys_annoyance_list":
1154 boolean currentFanboyAnnoyanceList = sharedPreferences.getBoolean("fanboys_annoyance_list", true);
1155 boolean currentFanboySocialBlockingList = sharedPreferences.getBoolean("fanboys_social_blocking_list", true);
1157 // Update the Fanboy icons.
1158 if (currentFanboyAnnoyanceList) { // Fanboy's annoyance list is enabled.
1160 // Update the Fanboy's annoyance list icon.
1161 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_dark);
1163 // Update the Fanboy's social blocking list icon.
1164 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_dark);
1166 // Update the Fanboy's annoyance list icon.
1167 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_light);
1169 // Update the Fanboy's social blocking list icon.
1170 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_light);
1172 } else { // Fanboy's annoyance list is disabled.
1174 // Update the Fanboy's annoyance list icon.
1175 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled_dark);
1177 // Update the Fanboy's social blocking list icon.
1178 if (currentFanboySocialBlockingList) {
1179 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_dark);
1181 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_dark);
1184 // Update the Fanboy's annoyance list icon.
1185 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled_light);
1187 // Update the Fanboy's social blocking list icon.
1188 if (currentFanboySocialBlockingList) {
1189 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_light);
1191 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_light);
1196 // Only enable Fanboy's social blocking list preference if Fanboy's annoyance list preference is disabled.
1197 fanboySocialBlockingListPreference.setEnabled(!currentFanboyAnnoyanceList);
1200 case "fanboys_social_blocking_list":
1202 if (sharedPreferences.getBoolean("fanboys_social_blocking_list", true)) {
1204 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_dark);
1206 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_light);
1210 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_dark);
1212 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_light);
1219 if (sharedPreferences.getBoolean("ultralist", true)) {
1221 ultraListPreference.setIcon(R.drawable.block_ads_enabled_dark);
1223 ultraListPreference.setIcon(R.drawable.block_ads_enabled_light);
1227 ultraListPreference.setIcon(R.drawable.block_ads_disabled_dark);
1229 ultraListPreference.setIcon(R.drawable.block_ads_disabled_light);
1234 case "ultraprivacy":
1236 if (sharedPreferences.getBoolean("ultraprivacy", true)) {
1238 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_dark);
1240 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_light);
1244 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_dark);
1246 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_light);
1251 case "block_all_third_party_requests":
1253 if (sharedPreferences.getBoolean("block_all_third_party_requests", false)) {
1255 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_dark);
1257 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_light);
1261 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_dark);
1263 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_light);
1268 case "google_analytics":
1270 if (sharedPreferences.getBoolean("google_analytics", true)) {
1272 googleAnalyticsPreference.setIcon(R.drawable.modify_url_enabled_dark);
1274 googleAnalyticsPreference.setIcon(R.drawable.modify_url_enabled_light);
1278 googleAnalyticsPreference.setIcon(R.drawable.modify_url_disabled_dark);
1280 googleAnalyticsPreference.setIcon(R.drawable.modify_url_disabled_light);
1285 case "facebook_click_ids":
1287 if (sharedPreferences.getBoolean("facebook_click_ids", true)) {
1289 facebookClickIdsPreference.setIcon(R.drawable.modify_url_enabled_dark);
1291 facebookClickIdsPreference.setIcon(R.drawable.modify_url_enabled_light);
1295 facebookClickIdsPreference.setIcon(R.drawable.modify_url_disabled_dark);
1297 facebookClickIdsPreference.setIcon(R.drawable.modify_url_disabled_light);
1302 case "twitter_amp_redirects":
1304 if (sharedPreferences.getBoolean("twitter_amp_redirects", true)) {
1306 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_enabled_dark);
1308 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_enabled_light);
1312 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_disabled_dark);
1314 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_disabled_light);
1320 // Store the new search string.
1321 String newSearchString = sharedPreferences.getString("search", getString(R.string.search_default_value));
1323 // Update `searchPreference` and `searchCustomURLPreference`.
1324 if (newSearchString.equals("Custom URL")) { // `Custom URL` is selected.
1325 // Set the summary text to `R.string.custom_url`, which is translated.
1326 searchPreference.setSummary(R.string.custom_url);
1328 // Enable `searchCustomURLPreference`.
1329 searchCustomURLPreference.setEnabled(true);
1331 // Set the `searchCustomURLPreference` according to the theme.
1333 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_dark);
1335 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_light);
1337 } else { // `Custom URL` is not selected.
1338 // Set the summary text to `newSearchString`.
1339 searchPreference.setSummary(newSearchString);
1341 // Disable `searchCustomURLPreference`.
1342 searchCustomURLPreference.setEnabled(false);
1344 // Set the `searchCustomURLPreference` according to the theme.
1346 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
1348 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
1353 case "search_custom_url":
1354 // Set the new custom search URL as the summary text for `search_custom_url`. The default is `""`.
1355 searchCustomURLPreference.setSummary(sharedPreferences.getString("search_custom_url", getString(R.string.search_custom_url_default_value)));
1359 // Get current proxy string.
1360 String currentProxyString = sharedPreferences.getString("proxy", getString(R.string.proxy_default_value));
1362 // Update the summary text for the proxy preference.
1363 switch (currentProxyString) {
1364 case ProxyHelper.NONE:
1365 proxyPreference.setSummary(getString(R.string.no_proxy_enabled));
1368 case ProxyHelper.TOR:
1369 if (Build.VERSION.SDK_INT == 19) { // Proxying through SOCKS doesn't work on Android KitKat.
1370 proxyPreference.setSummary(getString(R.string.tor_enabled_kitkat));
1372 proxyPreference.setSummary(getString(R.string.tor_enabled));
1376 case ProxyHelper.I2P:
1377 proxyPreference.setSummary(getString(R.string.i2p_enabled));
1380 case ProxyHelper.CUSTOM:
1381 proxyPreference.setSummary(getString(R.string.custom_proxy));
1385 // Update the status of the custom URL preference.
1386 proxyCustomUrlPreference.setEnabled(currentProxyString.equals("Custom"));
1388 // Update the icons.
1389 if (currentProxyString.equals("None")) { // Proxying is disabled.
1390 if (darkTheme) { // Dark theme.
1391 // Set the main proxy icon to be disabled
1392 proxyPreference.setIcon(R.drawable.proxy_disabled_dark);
1394 // Set the custom proxy URL icon to be ghosted.
1395 proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted_dark);
1396 } else { // Light theme.
1397 // Set the main proxy icon to be disabled.
1398 proxyPreference.setIcon(R.drawable.proxy_disabled_light);
1400 // Set the custom proxy URL icon to be ghosted.
1401 proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted_light);
1403 } else { // Proxying is enabled.
1404 if (darkTheme) { // Dark theme.
1405 // Set the main proxy icon to be enabled.
1406 proxyPreference.setIcon(R.drawable.proxy_enabled_dark);
1408 /// Set the custom proxy URL icon according to its status.
1409 if (proxyCustomUrlPreference.isEnabled()) { // Custom proxy is enabled.
1410 proxyCustomUrlPreference.setIcon(R.drawable.proxy_enabled_dark);
1411 } else { // Custom proxy is disabled.
1412 proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted_dark);
1414 } else { // Light theme.
1415 // Set the main proxy icon to be enabled.
1416 proxyPreference.setIcon(R.drawable.proxy_enabled_light);
1418 // Set the custom proxy URL icon according to its status.
1419 if (proxyCustomUrlPreference.isEnabled()) { // Custom proxy is enabled.
1420 proxyCustomUrlPreference.setIcon(R.drawable.proxy_enabled_light);
1421 } else { // Custom proxy is disabled.
1422 proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted_light);
1428 case "proxy_custom_url":
1429 // Set the summary text for the proxy custom URL.
1430 proxyCustomUrlPreference.setSummary(sharedPreferences.getString("proxy_custom_url", getString(R.string.proxy_custom_url_default_value)));
1433 case "full_screen_browsing_mode":
1434 if (sharedPreferences.getBoolean("full_screen_browsing_mode", false)) { // Full screen browsing is enabled.
1435 // Set the full screen browsing mode preference icon according to the theme.
1437 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_dark);
1439 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_light);
1442 // Set the hide app bar preference icon.
1443 if (sharedPreferences.getBoolean("hide_app_bar", true)) { // Hide app bar is enabled.
1444 // Set the icon according to the theme.
1446 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
1448 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
1450 } else { // Hide app bar is disabled.
1451 // Set the icon according to the theme.
1453 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
1455 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
1458 } else { // Full screen browsing is disabled.
1459 // Update the icons according to the theme.
1461 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_dark);
1462 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_dark);
1464 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_light);
1465 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_light);
1470 case "hide_app_bar":
1472 if (sharedPreferences.getBoolean("hide_app_bar", true)) { // Hide app bar is enabled.
1473 // Set the icon according to the theme.
1475 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
1477 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
1479 } else { // Hide app bar is disabled.
1480 // Set the icon according to the theme.
1482 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
1484 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
1489 case "clear_everything":
1490 // Store the new `clear_everything` status
1491 boolean newClearEverythingBoolean = sharedPreferences.getBoolean("clear_everything", true);
1493 // Update the status of the `Clear and Exit` preferences.
1494 clearCookiesPreference.setEnabled(!newClearEverythingBoolean);
1495 clearDomStoragePreference.setEnabled(!newClearEverythingBoolean);
1496 clearFormDataPreference.setEnabled(!newClearEverythingBoolean); // This line can be removed once the minimum API >= 26.
1497 clearCachePreference.setEnabled(!newClearEverythingBoolean);
1499 // Update the `clearEverythingPreference` icon.
1500 if (newClearEverythingBoolean) {
1502 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_dark);
1504 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_light);
1507 clearEverythingPreference.setIcon(R.drawable.clear_everything_disabled);
1510 // Update the `clearCookiesPreference` icon.
1511 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_cookies", true)) {
1513 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_dark);
1515 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_light);
1518 clearCookiesPreference.setIcon(R.drawable.cookies_warning);
1521 // Update the `clearDomStoragePreference` icon.
1522 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_dom_storage", true)) {
1524 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_dark);
1526 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_light);
1529 clearDomStoragePreference.setIcon(R.drawable.dom_storage_warning);
1532 // Update the clear form data preference icon if the API < 26.
1533 if (Build.VERSION.SDK_INT < 26) {
1534 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_form_data", true)) {
1536 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_dark);
1538 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_light);
1541 clearFormDataPreference.setIcon(R.drawable.form_data_warning);
1545 // Update the `clearCachePreference` icon.
1546 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_cache", true)) {
1548 clearCachePreference.setIcon(R.drawable.cache_cleared_dark);
1550 clearCachePreference.setIcon(R.drawable.cache_cleared_light);
1553 clearCachePreference.setIcon(R.drawable.cache_warning);
1557 case "clear_cookies":
1559 if (sharedPreferences.getBoolean("clear_cookies", true)) {
1561 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_dark);
1563 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_light);
1566 clearCookiesPreference.setIcon(R.drawable.cookies_warning);
1570 case "clear_dom_storage":
1572 if (sharedPreferences.getBoolean("clear_dom_storage", true)) {
1574 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_dark);
1576 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_light);
1579 clearDomStoragePreference.setIcon(R.drawable.dom_storage_warning);
1583 // This section can be removed once the minimum API >= 26.
1584 case "clear_form_data":
1586 if (sharedPreferences.getBoolean("clear_form_data", true)) {
1588 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_dark);
1590 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_light);
1593 clearFormDataPreference.setIcon(R.drawable.form_data_warning);
1599 if (sharedPreferences.getBoolean("clear_cache", true)) {
1601 clearCachePreference.setIcon(R.drawable.cache_cleared_dark);
1603 clearCachePreference.setIcon(R.drawable.cache_cleared_light);
1606 clearCachePreference.setIcon(R.drawable.cache_warning);
1611 // Set the new homepage URL as the summary text for the Homepage preference.
1612 homepagePreference.setSummary(sharedPreferences.getString("homepage", getString(R.string.homepage_default_value)));
1616 // Update the font size summary text.
1617 fontSizePreference.setSummary(sharedPreferences.getString("font_size", getString(R.string.font_size_default_value)) + "%");
1620 case "open_intents_in_new_tab":
1622 if (sharedPreferences.getBoolean("open_intents_in_new_tab", true)) {
1624 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_dark);
1626 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_light);
1630 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_dark);
1632 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_light);
1637 case "swipe_to_refresh":
1639 if (sharedPreferences.getBoolean("swipe_to_refresh", true)) {
1641 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_dark);
1643 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_light);
1647 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_dark);
1649 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_light);
1654 case "scroll_app_bar":
1656 if (sharedPreferences.getBoolean("scroll_app_bar", true)) {
1658 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
1660 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
1664 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
1666 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
1671 case "display_additional_app_bar_icons":
1673 if (sharedPreferences.getBoolean("display_additional_app_bar_icons", false)) {
1675 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_dark);
1677 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_light);
1681 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_dark);
1683 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_light);
1688 case "download_with_external_app":
1690 if (sharedPreferences.getBoolean("download_with_external_app", false)) {
1692 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_enabled_dark);
1694 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_enabled_light);
1698 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_disabled_dark);
1700 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_disabled_light);
1707 if (sharedPreferences.getBoolean("dark_theme", false)) {
1708 darkThemePreference.setIcon(R.drawable.theme_dark);
1710 darkThemePreference.setIcon(R.drawable.theme_light);
1713 // Create an intent to restart Privacy Browser.
1714 Intent changeThemeRestartIntent = getActivity().getParentActivityIntent();
1716 // Assert that the intent is not null to remove the lint error below.
1717 assert changeThemeRestartIntent != null;
1719 // `Intent.FLAG_ACTIVITY_CLEAR_TASK` removes all activities from the stack. It requires `Intent.FLAG_ACTIVITY_NEW_TASK`.
1720 changeThemeRestartIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
1722 // Create a handler to restart the activity.
1723 Handler changeThemeRestartHandler = new Handler();
1725 // Create a runnable to restart the activity.
1726 Runnable changeThemeRestartRunnable = () -> {
1727 // Restart the activity.
1728 startActivity(changeThemeRestartIntent);
1730 // Kill this instance of Privacy Browser. Otherwise, the app exhibits sporadic behavior after the restart.
1734 // Restart the activity after 150 milliseconds, so that the app has enough time to save the change to the preference.
1735 changeThemeRestartHandler.postDelayed(changeThemeRestartRunnable, 150);
1739 // Store the current night mode status.
1740 boolean currentNightModeBoolean = sharedPreferences.getBoolean("night_mode", false);
1741 boolean currentJavaScriptBoolean = sharedPreferences.getBoolean("javascript", false);
1744 if (currentNightModeBoolean) {
1746 nightModePreference.setIcon(R.drawable.night_mode_enabled_dark);
1748 nightModePreference.setIcon(R.drawable.night_mode_enabled_light);
1752 nightModePreference.setIcon(R.drawable.night_mode_disabled_dark);
1754 nightModePreference.setIcon(R.drawable.night_mode_disabled_light);
1758 // Update the status of `javaScriptPreference` and `domStoragePreference`.
1759 javaScriptPreference.setEnabled(!currentNightModeBoolean);
1760 domStoragePreference.setEnabled(currentNightModeBoolean || currentJavaScriptBoolean);
1762 // Update the `javaScriptPreference` icon.
1763 if (currentNightModeBoolean || currentJavaScriptBoolean) {
1764 javaScriptPreference.setIcon(R.drawable.javascript_enabled);
1766 javaScriptPreference.setIcon(R.drawable.privacy_mode);
1769 // Update the DOM storage preference icon.
1770 if (currentNightModeBoolean || currentJavaScriptBoolean) { // The preference is enabled.
1771 if (sharedPreferences.getBoolean("dom_storage", false)) { // DOM storage is enabled.
1772 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
1773 } else { // DOM storage is disabled.
1775 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_dark);
1777 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_light);
1780 } else { // The preference is disabled. The icon should be ghosted.
1782 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_dark);
1784 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_light);
1789 case "wide_viewport":
1791 if (sharedPreferences.getBoolean("wide_viewport", true)) {
1793 wideViewportPreference.setIcon(R.drawable.wide_viewport_enabled_dark);
1795 wideViewportPreference.setIcon(R.drawable.wide_viewport_enabled_light);
1799 wideViewportPreference.setIcon(R.drawable.wide_viewport_disabled_dark);
1801 wideViewportPreference.setIcon(R.drawable.wide_viewport_disabled_light);
1806 case "display_webpage_images":
1808 if (sharedPreferences.getBoolean("display_webpage_images", true)) {
1810 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_dark);
1812 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_light);
1816 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_dark);
1818 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_light);
1825 // Register the listener.
1826 savedPreferences.registerOnSharedPreferenceChangeListener(preferencesListener);
1829 // 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.
1831 public void onPause() {
1833 savedPreferences.unregisterOnSharedPreferenceChangeListener(preferencesListener);
1837 public void onResume() {
1839 savedPreferences.registerOnSharedPreferenceChangeListener(preferencesListener);