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 proxyCustomHostPreference = findPreference("proxy_custom_host");
90 Preference proxyCustomPortPreference = findPreference("proxy_custom_port");
91 Preference fullScreenBrowsingModePreference = findPreference("full_screen_browsing_mode");
92 Preference hideAppBarPreference = findPreference("hide_app_bar");
93 Preference clearEverythingPreference = findPreference("clear_everything");
94 Preference clearCookiesPreference = findPreference("clear_cookies");
95 Preference clearDomStoragePreference = findPreference("clear_dom_storage");
96 Preference clearFormDataPreference = findPreference("clear_form_data"); // The clear form data preference can be removed once the minimum API >= 26.
97 Preference clearCachePreference = findPreference("clear_cache");
98 Preference homepagePreference = findPreference("homepage");
99 Preference fontSizePreference = findPreference("font_size");
100 Preference openIntentsInNewTabPreference = findPreference("open_intents_in_new_tab");
101 Preference swipeToRefreshPreference = findPreference("swipe_to_refresh");
102 Preference scrollAppBarPreference = findPreference("scroll_app_bar");
103 Preference displayAdditionalAppBarIconsPreference = findPreference("display_additional_app_bar_icons");
104 Preference downloadWithExternalAppPreference = findPreference("download_with_external_app");
105 Preference darkThemePreference = findPreference("dark_theme");
106 Preference nightModePreference = findPreference("night_mode");
107 Preference wideViewportPreference = findPreference("wide_viewport");
108 Preference displayWebpageImagesPreference = findPreference("display_webpage_images");
110 // Remove the lint warnings below that the preferences might be null.
111 assert javaScriptPreference != null;
112 assert firstPartyCookiesPreference != null;
113 assert thirdPartyCookiesPreference != null;
114 assert domStoragePreference != null;
115 assert formDataPreference != null;
116 assert userAgentPreference != null;
117 assert customUserAgentPreference != null;
118 assert incognitoModePreference != null;
119 assert doNotTrackPreference != null;
120 assert allowScreenshotsPreference != null;
121 assert easyListPreference != null;
122 assert easyPrivacyPreference != null;
123 assert fanboyAnnoyanceListPreference != null;
124 assert fanboySocialBlockingListPreference != null;
125 assert ultraListPreference != null;
126 assert ultraPrivacyPreference != null;
127 assert blockAllThirdPartyRequestsPreference != null;
128 assert googleAnalyticsPreference != null;
129 assert facebookClickIdsPreference != null;
130 assert twitterAmpRedirectsPreference != null;
131 assert searchPreference != null;
132 assert searchCustomURLPreference != null;
133 assert proxyPreference != null;
134 assert proxyCustomHostPreference != null;
135 assert proxyCustomPortPreference != null;
136 assert fullScreenBrowsingModePreference != null;
137 assert hideAppBarPreference != null;
138 assert clearEverythingPreference != null;
139 assert clearCookiesPreference != null;
140 assert clearDomStoragePreference != null;
141 assert clearFormDataPreference != null;
142 assert clearCachePreference != null;
143 assert homepagePreference != null;
144 assert fontSizePreference != null;
145 assert openIntentsInNewTabPreference != null;
146 assert swipeToRefreshPreference != null;
147 assert scrollAppBarPreference != null;
148 assert displayAdditionalAppBarIconsPreference != null;
149 assert downloadWithExternalAppPreference != null;
150 assert darkThemePreference != null;
151 assert nightModePreference != null;
152 assert wideViewportPreference != null;
153 assert displayWebpageImagesPreference != null;
155 // Set the hide app bar preference dependency.
156 hideAppBarPreference.setDependency("full_screen_browsing_mode");
158 // Get strings from the preferences.
159 String searchString = savedPreferences.getString("search", getString(R.string.search_default_value));
160 String proxyString = savedPreferences.getString("proxy", getString(R.string.proxy_default_value));
162 // Get booleans that are used in multiple places from the preferences.
163 boolean javaScriptEnabled = savedPreferences.getBoolean("javascript", false);
164 boolean firstPartyCookiesEnabled = savedPreferences.getBoolean("first_party_cookies", false);
165 boolean thirdPartyCookiesEnabled = savedPreferences.getBoolean("third_party_cookies", false);
166 boolean fanboyAnnoyanceListEnabled = savedPreferences.getBoolean("fanboys_annoyance_list", true);
167 boolean fanboySocialBlockingEnabled = savedPreferences.getBoolean("fanboys_social_blocking_list", true);
168 boolean fullScreenBrowsingMode = savedPreferences.getBoolean("full_screen_browsing_mode", false);
169 boolean clearEverything = savedPreferences.getBoolean("clear_everything", true);
170 boolean darkTheme = savedPreferences.getBoolean("dark_theme", false);
171 boolean nightMode = savedPreferences.getBoolean("night_mode", false);
173 // Only enable the third-party cookies preference if first-party cookies are enabled and API >= 21.
174 thirdPartyCookiesPreference.setEnabled(firstPartyCookiesEnabled && (Build.VERSION.SDK_INT >= 21));
176 // Only enable the DOM storage preference if either JavaScript or Night Mode is enabled.
177 domStoragePreference.setEnabled(javaScriptEnabled || nightMode);
179 // Remove the form data preferences if the API is >= 26 as they no longer do anything.
180 if (Build.VERSION.SDK_INT >= 26) {
181 // Get the categories.
182 PreferenceCategory privacyCategory = findPreference("privacy");
183 PreferenceCategory clearAndExitCategory = findPreference("clear_and_exit");
185 // Remove the lint warnings below that the preference categories might be null.
186 assert privacyCategory != null;
187 assert clearAndExitCategory != null;
189 // Remove the form data preferences.
190 privacyCategory.removePreference(formDataPreference);
191 clearAndExitCategory.removePreference(clearFormDataPreference);
194 // Only enable Fanboy's social blocking list preference if Fanboy's annoyance list is disabled.
195 fanboySocialBlockingListPreference.setEnabled(!fanboyAnnoyanceListEnabled);
197 // Inflate a WebView to get the default user agent.
198 LayoutInflater inflater = getActivity().getLayoutInflater();
199 // `@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.
200 @SuppressLint("InflateParams") View bareWebViewLayout = inflater.inflate(R.layout.bare_webview, null, false);
201 WebView bareWebView = bareWebViewLayout.findViewById(R.id.bare_webview);
203 // Get the user agent arrays.
204 ArrayAdapter<CharSequence> userAgentNamesArray = ArrayAdapter.createFromResource(context, R.array.user_agent_names, R.layout.spinner_item);
205 String[] translatedUserAgentNamesArray = getResources().getStringArray(R.array.translated_user_agent_names);
206 String[] userAgentDataArray = getResources().getStringArray(R.array.user_agent_data);
208 // Get the current user agent name from the preference.
209 String userAgentName = savedPreferences.getString("user_agent", getString(R.string.user_agent_default_value));
211 // Get the array position of the user agent name.
212 int userAgentArrayPosition = userAgentNamesArray.getPosition(userAgentName);
214 // Populate the user agent summary.
215 switch (userAgentArrayPosition) {
216 case MainWebViewActivity.UNRECOGNIZED_USER_AGENT: // The user agent name is not on the canonical list.
217 // 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.
218 userAgentPreference.setSummary(userAgentName);
221 case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
222 // Get the user agent text from the webview (which changes based on the version of Android and WebView installed).
223 userAgentPreference.setSummary(translatedUserAgentNamesArray[userAgentArrayPosition] + ":\n" + bareWebView.getSettings().getUserAgentString());
226 case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
227 // Set the summary text.
228 userAgentPreference.setSummary(R.string.custom_user_agent);
232 // Get the user agent summary from the user agent data array.
233 userAgentPreference.setSummary(translatedUserAgentNamesArray[userAgentArrayPosition] + ":\n" + userAgentDataArray[userAgentArrayPosition]);
236 // Set the summary text for the custom user agent preference and enable it if user agent preference is set to custom.
237 customUserAgentPreference.setSummary(savedPreferences.getString("custom_user_agent", getString(R.string.custom_user_agent_default_value)));
238 customUserAgentPreference.setEnabled(userAgentPreference.getSummary().equals(getString(R.string.custom_user_agent)));
240 // Set the search URL as the summary text for the search preference when the preference screen is loaded.
241 if (searchString.equals("Custom URL")) {
242 // Use R.string.custom_url, which will be translated, instead of the array value, which will not.
243 searchPreference.setSummary(R.string.custom_url);
245 // Set the array value as the summary text.
246 searchPreference.setSummary(searchString);
249 // Set the summary text for `search_custom_url` (the default is `""`) and enable it if `search` is set to `Custom URL`.
250 searchCustomURLPreference.setSummary(savedPreferences.getString("search_custom_url", getString(R.string.search_custom_url_default_value)));
251 searchCustomURLPreference.setEnabled(searchString.equals("Custom URL"));
253 // Set the summary text for the proxy preference when the preference screen is loaded.
254 switch (proxyString) {
255 case ProxyHelper.NONE:
256 proxyPreference.setSummary(getString(R.string.no_proxy_enabled));
259 case ProxyHelper.TOR:
260 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 options if a custom proxy is selected.
273 proxyCustomHostPreference.setEnabled(proxyString.equals("Custom"));
274 proxyCustomPortPreference.setEnabled(proxyString.equals("Custom"));
276 // Set the summary text for the custom proxy options.
277 proxyCustomHostPreference.setSummary(savedPreferences.getString("proxy_custom_host", getString(R.string.proxy_custom_host_default_value)));
278 proxyCustomPortPreference.setSummary(savedPreferences.getString("proxy_custom_port", getString(R.string.proxy_custom_port_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 icons to be ghosted.
605 proxyCustomHostPreference.setIcon(R.drawable.proxy_ghosted_dark);
606 proxyCustomPortPreference.setIcon(R.drawable.proxy_ghosted_dark);
607 } else { // Light theme.
608 // Set the main proxy icon to be disabled.
609 proxyPreference.setIcon(R.drawable.proxy_disabled_light);
611 // Set the custom proxy icons to be ghosted.
612 proxyCustomHostPreference.setIcon(R.drawable.proxy_ghosted_light);
613 proxyCustomPortPreference.setIcon(R.drawable.proxy_ghosted_light);
615 } else { // Proxying is enabled.
616 if (darkTheme) { // Dark theme.
617 // Set the main proxy icon to be enabled.
618 proxyPreference.setIcon(R.drawable.proxy_enabled_dark);
620 // Set the custom proxy icons according to their status.
621 if (proxyCustomHostPreference.isEnabled()) { // Custom proxy is enabled.
622 proxyCustomHostPreference.setIcon(R.drawable.proxy_enabled_dark);
623 proxyCustomPortPreference.setIcon(R.drawable.proxy_enabled_dark);
624 } else { // Custom proxy is disabled.
625 proxyCustomHostPreference.setIcon(R.drawable.proxy_ghosted_dark);
626 proxyCustomPortPreference.setIcon(R.drawable.proxy_ghosted_dark);
628 } else { // Light theme.
629 // Set the main proxy icon to be enabled.
630 proxyPreference.setIcon(R.drawable.proxy_enabled_light);
632 // Set the custom proxy icons according to their status.
633 if (proxyCustomHostPreference.isEnabled()) { // Custom proxy is enabled.
634 proxyCustomHostPreference.setIcon(R.drawable.proxy_enabled_light);
635 proxyCustomPortPreference.setIcon(R.drawable.proxy_enabled_light);
636 } else { // Custom proxy is disabled.
637 proxyCustomHostPreference.setIcon(R.drawable.proxy_ghosted_light);
638 proxyCustomPortPreference.setIcon(R.drawable.proxy_ghosted_light);
643 // Set the full screen browsing mode icons.
644 if (fullScreenBrowsingMode) { // Full screen browsing mode is enabled.
645 // Set the `fullScreenBrowsingModePreference` icon according to the theme.
647 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_dark);
649 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_light);
652 // Set the hide app bar icon.
653 if (savedPreferences.getBoolean("hide_app_bar", true)) { // Hide app bar is enabled.
654 // Set the icon according to the theme.
656 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
658 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
660 } else { // Hide app bar is disabled.
661 // Set the icon according to the theme.
663 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
665 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
668 } else { // Full screen browsing mode is disabled.
669 // Set the icons according to the theme.
671 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_dark);
672 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_dark);
674 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_light);
675 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_light);
679 // Set the clear everything preference icon.
680 if (clearEverything) {
682 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_dark);
684 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_light);
687 clearEverythingPreference.setIcon(R.drawable.clear_everything_disabled);
690 // Set the clear cookies preference icon.
691 if (clearEverything || savedPreferences.getBoolean("clear_cookies", true)) {
693 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_dark);
695 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_light);
698 clearCookiesPreference.setIcon(R.drawable.cookies_warning);
701 // Set the clear DOM storage preference icon.
702 if (clearEverything || savedPreferences.getBoolean("clear_dom_storage", true)) {
704 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_dark);
706 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_light);
709 clearDomStoragePreference.setIcon(R.drawable.dom_storage_warning);
712 // Set the clear form data preference icon if the API < 26. It has no effect on newer versions of Android.
713 if (Build.VERSION.SDK_INT < 26) {
714 if (clearEverything || savedPreferences.getBoolean("clear_form_data", true)) {
716 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_dark);
718 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_light);
721 clearFormDataPreference.setIcon(R.drawable.form_data_warning);
725 // Set the clear cache preference icon.
726 if (clearEverything || savedPreferences.getBoolean("clear_cache", true)) {
728 clearCachePreference.setIcon(R.drawable.cache_cleared_dark);
730 clearCachePreference.setIcon(R.drawable.cache_cleared_light);
733 clearCachePreference.setIcon(R.drawable.cache_warning);
736 // Set the open intents in new tab preference icon.
737 if (savedPreferences.getBoolean("open_intents_in_new_tab", true)) {
739 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_dark);
741 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_light);
745 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_dark);
747 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_light);
751 // Set the swipe to refresh preference icon.
752 if (savedPreferences.getBoolean("swipe_to_refresh", true)) {
754 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_dark);
756 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_light);
760 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_dark);
762 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_light);
766 // Set the scroll app bar preference icon.
767 if (savedPreferences.getBoolean("scroll_app_bar", true)) {
769 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
771 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
775 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
777 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
781 // Set the display additional app bar icons preference icon.
782 if (savedPreferences.getBoolean("display_additional_app_bar_icons", false)) {
784 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_dark);
786 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_light);
790 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_dark);
792 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_light);
796 // Set the download with external app preference icon.
797 if (savedPreferences.getBoolean("download_with_external_app", false)) {
799 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_enabled_dark);
801 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_enabled_light);
805 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_disabled_dark);
807 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_disabled_light);
811 // Set the dark theme preference icon.
812 if (savedPreferences.getBoolean("dark_theme", false)) {
813 darkThemePreference.setIcon(R.drawable.theme_dark);
815 darkThemePreference.setIcon(R.drawable.theme_light);
818 // Set the night mode preference icon.
821 nightModePreference.setIcon(R.drawable.night_mode_enabled_dark);
823 nightModePreference.setIcon(R.drawable.night_mode_enabled_light);
827 nightModePreference.setIcon(R.drawable.night_mode_disabled_dark);
829 nightModePreference.setIcon(R.drawable.night_mode_disabled_light);
833 // Set the wide viewport preference icon.
834 if (savedPreferences.getBoolean("wide_viewport", true)) {
836 wideViewportPreference.setIcon(R.drawable.wide_viewport_enabled_dark);
838 wideViewportPreference.setIcon(R.drawable.wide_viewport_enabled_light);
842 wideViewportPreference.setIcon(R.drawable.wide_viewport_disabled_dark);
844 wideViewportPreference.setIcon(R.drawable.wide_viewport_disabled_light);
848 // Set the display webpage images preference icon.
849 if (savedPreferences.getBoolean("display_webpage_images", true)) {
851 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_dark);
853 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_light);
857 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_dark);
859 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_light);
864 // Listen for preference changes.
865 preferencesListener = (SharedPreferences sharedPreferences, String key) -> {
868 // Update the icons and the DOM storage preference status.
869 if (sharedPreferences.getBoolean("javascript", false)) { // The JavaScript preference is enabled.
870 // Update the icon for the JavaScript preference.
871 javaScriptPreference.setIcon(R.drawable.javascript_enabled);
873 // Update the status of the DOM storage preference.
874 domStoragePreference.setEnabled(true);
876 // Update the icon for the DOM storage preference.
877 if (sharedPreferences.getBoolean("dom_storage", false)) {
878 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
881 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_dark);
883 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_light);
886 } else { // The JavaScript preference is disabled.
887 // Update the icon for the JavaScript preference.
888 javaScriptPreference.setIcon(R.drawable.privacy_mode);
890 // Update the status of the DOM storage preference.
891 domStoragePreference.setEnabled(false);
893 // Set the icon for DOM storage preference to be ghosted.
895 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_dark);
897 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_light);
902 case "first_party_cookies":
903 // Update the icons for `first_party_cookies` and `third_party_cookies`.
904 if (sharedPreferences.getBoolean("first_party_cookies", false)) {
905 // Set the icon for `first_party_cookies`.
906 firstPartyCookiesPreference.setIcon(R.drawable.cookies_enabled);
908 // Update the icon for `third_party_cookies`.
909 if (Build.VERSION.SDK_INT >= 21) {
910 if (sharedPreferences.getBoolean("third_party_cookies", false)) {
911 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_warning);
914 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
916 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
921 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_dark);
923 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_light);
926 } else { // `first_party_cookies` is `false`.
927 // Update the icon for `first_party_cookies`.
929 firstPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
931 firstPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
934 // Set the icon for `third_party_cookies` to be ghosted.
936 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_dark);
938 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_light);
942 // Enable `third_party_cookies` if `first_party_cookies` is `true` and API >= 21.
943 thirdPartyCookiesPreference.setEnabled(sharedPreferences.getBoolean("first_party_cookies", false) && (Build.VERSION.SDK_INT >= 21));
946 case "third_party_cookies":
948 if (sharedPreferences.getBoolean("third_party_cookies", false)) {
949 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_warning);
952 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
954 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
961 if (sharedPreferences.getBoolean("dom_storage", false)) {
962 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
965 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_dark);
967 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_light);
972 // Save form data can be removed once the minimum API >= 26.
973 case "save_form_data":
975 if (sharedPreferences.getBoolean("save_form_data", false)) {
976 formDataPreference.setIcon(R.drawable.form_data_enabled);
979 formDataPreference.setIcon(R.drawable.form_data_disabled_dark);
981 formDataPreference.setIcon(R.drawable.form_data_disabled_light);
987 // Get the new user agent name.
988 String newUserAgentName = sharedPreferences.getString("user_agent", getString(R.string.user_agent_default_value));
990 // Get the array position for the new user agent name.
991 int newUserAgentArrayPosition = userAgentNamesArray.getPosition(newUserAgentName);
993 // Get the translated new user agent name.
994 String translatedNewUserAgentName = translatedUserAgentNamesArray[newUserAgentArrayPosition];
996 // Populate the user agent summary.
997 switch (newUserAgentArrayPosition) {
998 case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
999 // Get the user agent text from the webview (which changes based on the version of Android and WebView installed).
1000 userAgentPreference.setSummary(translatedNewUserAgentName + ":\n" + bareWebView.getSettings().getUserAgentString());
1002 // Disable the custom user agent preference.
1003 customUserAgentPreference.setEnabled(false);
1005 // Set the custom user agent preference icon according to the theme.
1007 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_dark);
1009 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_light);
1013 case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
1014 // Set the summary text.
1015 userAgentPreference.setSummary(R.string.custom_user_agent);
1017 // Enable the custom user agent preference.
1018 customUserAgentPreference.setEnabled(true);
1020 // Set the custom user agent preference icon according to the theme.
1022 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_dark);
1024 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_light);
1029 // Get the user agent summary from the user agent data array.
1030 userAgentPreference.setSummary(translatedNewUserAgentName + ":\n" + userAgentDataArray[newUserAgentArrayPosition]);
1032 // Disable the custom user agent preference.
1033 customUserAgentPreference.setEnabled(false);
1035 // Set the custom user agent preference icon according to the theme.
1037 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_dark);
1039 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_light);
1044 case "custom_user_agent":
1045 // Set the new custom user agent as the summary text for the preference.
1046 customUserAgentPreference.setSummary(sharedPreferences.getString("custom_user_agent", getString(R.string.custom_user_agent_default_value)));
1049 case "incognito_mode":
1051 if (sharedPreferences.getBoolean("incognito_mode", false)) {
1053 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_dark);
1055 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_light);
1059 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_dark);
1061 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_light);
1066 case "do_not_track":
1068 if (sharedPreferences.getBoolean("do_not_track", false)) {
1070 doNotTrackPreference.setIcon(R.drawable.block_tracking_enabled_dark);
1072 doNotTrackPreference.setIcon(R.drawable.block_tracking_enabled_light);
1076 doNotTrackPreference.setIcon(R.drawable.block_tracking_disabled_dark);
1078 doNotTrackPreference.setIcon(R.drawable.block_tracking_disabled_light);
1084 case "allow_screenshots":
1086 if (sharedPreferences.getBoolean("allow_screenshots", false)) {
1088 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_dark);
1090 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_light);
1094 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_dark);
1096 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_light);
1100 // Create an intent to restart Privacy Browser.
1101 Intent allowScreenshotsRestartIntent = getActivity().getParentActivityIntent();
1103 // Assert that the intent is not null to remove the lint error below.
1104 assert allowScreenshotsRestartIntent != null;
1106 // `Intent.FLAG_ACTIVITY_CLEAR_TASK` removes all activities from the stack. It requires `Intent.FLAG_ACTIVITY_NEW_TASK`.
1107 allowScreenshotsRestartIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
1109 // Create a handler to restart the activity.
1110 Handler allowScreenshotsRestartHandler = new Handler();
1112 // Create a runnable to restart the activity.
1113 Runnable allowScreenshotsRestartRunnable = () -> {
1114 // Restart the activity.
1115 startActivity(allowScreenshotsRestartIntent);
1117 // Kill this instance of Privacy Browser. Otherwise, the app exhibits sporadic behavior after the restart.
1121 // Restart the activity after 150 milliseconds, so that the app has enough time to save the change to the preference.
1122 allowScreenshotsRestartHandler.postDelayed(allowScreenshotsRestartRunnable, 150);
1127 if (sharedPreferences.getBoolean("easylist", true)) {
1129 easyListPreference.setIcon(R.drawable.block_ads_enabled_dark);
1131 easyListPreference.setIcon(R.drawable.block_ads_enabled_light);
1135 easyListPreference.setIcon(R.drawable.block_ads_disabled_dark);
1137 easyListPreference.setIcon(R.drawable.block_ads_disabled_light);
1144 if (sharedPreferences.getBoolean("easyprivacy", true)) {
1146 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_dark);
1148 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_light);
1152 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_dark);
1154 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_light);
1159 case "fanboys_annoyance_list":
1160 boolean currentFanboyAnnoyanceList = sharedPreferences.getBoolean("fanboys_annoyance_list", true);
1161 boolean currentFanboySocialBlockingList = sharedPreferences.getBoolean("fanboys_social_blocking_list", true);
1163 // Update the Fanboy icons.
1164 if (currentFanboyAnnoyanceList) { // Fanboy's annoyance list is enabled.
1166 // Update the Fanboy's annoyance list icon.
1167 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_dark);
1169 // Update the Fanboy's social blocking list icon.
1170 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_dark);
1172 // Update the Fanboy's annoyance list icon.
1173 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_light);
1175 // Update the Fanboy's social blocking list icon.
1176 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_light);
1178 } else { // Fanboy's annoyance list is disabled.
1180 // Update the Fanboy's annoyance list icon.
1181 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled_dark);
1183 // Update the Fanboy's social blocking list icon.
1184 if (currentFanboySocialBlockingList) {
1185 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_dark);
1187 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_dark);
1190 // Update the Fanboy's annoyance list icon.
1191 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled_light);
1193 // Update the Fanboy's social blocking list icon.
1194 if (currentFanboySocialBlockingList) {
1195 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_light);
1197 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_light);
1202 // Only enable Fanboy's social blocking list preference if Fanboy's annoyance list preference is disabled.
1203 fanboySocialBlockingListPreference.setEnabled(!currentFanboyAnnoyanceList);
1206 case "fanboys_social_blocking_list":
1208 if (sharedPreferences.getBoolean("fanboys_social_blocking_list", true)) {
1210 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_dark);
1212 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_light);
1216 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_dark);
1218 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_light);
1225 if (sharedPreferences.getBoolean("ultralist", true)) {
1227 ultraListPreference.setIcon(R.drawable.block_ads_enabled_dark);
1229 ultraListPreference.setIcon(R.drawable.block_ads_enabled_light);
1233 ultraListPreference.setIcon(R.drawable.block_ads_disabled_dark);
1235 ultraListPreference.setIcon(R.drawable.block_ads_disabled_light);
1240 case "ultraprivacy":
1242 if (sharedPreferences.getBoolean("ultraprivacy", true)) {
1244 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_dark);
1246 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_light);
1250 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_dark);
1252 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_light);
1257 case "block_all_third_party_requests":
1259 if (sharedPreferences.getBoolean("block_all_third_party_requests", false)) {
1261 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_dark);
1263 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_light);
1267 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_dark);
1269 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_light);
1274 case "google_analytics":
1276 if (sharedPreferences.getBoolean("google_analytics", true)) {
1278 googleAnalyticsPreference.setIcon(R.drawable.modify_url_enabled_dark);
1280 googleAnalyticsPreference.setIcon(R.drawable.modify_url_enabled_light);
1284 googleAnalyticsPreference.setIcon(R.drawable.modify_url_disabled_dark);
1286 googleAnalyticsPreference.setIcon(R.drawable.modify_url_disabled_light);
1291 case "facebook_click_ids":
1293 if (sharedPreferences.getBoolean("facebook_click_ids", true)) {
1295 facebookClickIdsPreference.setIcon(R.drawable.modify_url_enabled_dark);
1297 facebookClickIdsPreference.setIcon(R.drawable.modify_url_enabled_light);
1301 facebookClickIdsPreference.setIcon(R.drawable.modify_url_disabled_dark);
1303 facebookClickIdsPreference.setIcon(R.drawable.modify_url_disabled_light);
1308 case "twitter_amp_redirects":
1310 if (sharedPreferences.getBoolean("twitter_amp_redirects", true)) {
1312 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_enabled_dark);
1314 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_enabled_light);
1318 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_disabled_dark);
1320 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_disabled_light);
1326 // Store the new search string.
1327 String newSearchString = sharedPreferences.getString("search", getString(R.string.search_default_value));
1329 // Update `searchPreference` and `searchCustomURLPreference`.
1330 if (newSearchString.equals("Custom URL")) { // `Custom URL` is selected.
1331 // Set the summary text to `R.string.custom_url`, which is translated.
1332 searchPreference.setSummary(R.string.custom_url);
1334 // Enable `searchCustomURLPreference`.
1335 searchCustomURLPreference.setEnabled(true);
1337 // Set the `searchCustomURLPreference` according to the theme.
1339 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_dark);
1341 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_light);
1343 } else { // `Custom URL` is not selected.
1344 // Set the summary text to `newSearchString`.
1345 searchPreference.setSummary(newSearchString);
1347 // Disable `searchCustomURLPreference`.
1348 searchCustomURLPreference.setEnabled(false);
1350 // Set the `searchCustomURLPreference` according to the theme.
1352 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
1354 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
1359 case "search_custom_url":
1360 // Set the new custom search URL as the summary text for `search_custom_url`. The default is `""`.
1361 searchCustomURLPreference.setSummary(sharedPreferences.getString("search_custom_url", getString(R.string.search_custom_url_default_value)));
1365 // Get current proxy string.
1366 String currentProxyString = sharedPreferences.getString("proxy", getString(R.string.proxy_default_value));
1368 // Update the summary text for the proxy preference.
1369 switch (currentProxyString) {
1370 case ProxyHelper.NONE:
1371 proxyPreference.setSummary(getString(R.string.no_proxy_enabled));
1374 case ProxyHelper.TOR:
1375 proxyPreference.setSummary(getString(R.string.tor_enabled));
1378 case ProxyHelper.I2P:
1379 proxyPreference.setSummary(getString(R.string.i2p_enabled));
1382 case ProxyHelper.CUSTOM:
1383 proxyPreference.setSummary(getString(R.string.custom_proxy));
1387 // Update the status of the custom proxy options.
1388 proxyCustomHostPreference.setEnabled(currentProxyString.equals("Custom"));
1389 proxyCustomPortPreference.setEnabled(currentProxyString.equals("Custom"));
1391 // Update the icons.
1392 if (currentProxyString.equals("None")) { // Proxying is disabled.
1393 if (darkTheme) { // Dark theme.
1394 // Set the main proxy icon to be disabled
1395 proxyPreference.setIcon(R.drawable.proxy_disabled_dark);
1397 // Set the custom proxy icons to be ghosted.
1398 proxyCustomHostPreference.setIcon(R.drawable.proxy_ghosted_dark);
1399 proxyCustomPortPreference.setIcon(R.drawable.proxy_ghosted_dark);
1400 } else { // Light theme.
1401 // Set the main proxy icon to be disabled.
1402 proxyPreference.setIcon(R.drawable.proxy_disabled_light);
1404 // Set the custom proxy icons to be ghosted.
1405 proxyCustomHostPreference.setIcon(R.drawable.proxy_ghosted_light);
1406 proxyCustomPortPreference.setIcon(R.drawable.proxy_ghosted_light);
1408 } else { // Proxying is enabled.
1409 if (darkTheme) { // Dark theme.
1410 // Set the main proxy icon to be enabled.
1411 proxyPreference.setIcon(R.drawable.proxy_enabled_dark);
1413 /// Set the custom proxy icons according to their status.
1414 if (proxyCustomHostPreference.isEnabled()) { // Custom proxy is enabled.
1415 proxyCustomHostPreference.setIcon(R.drawable.proxy_enabled_dark);
1416 proxyCustomPortPreference.setIcon(R.drawable.proxy_enabled_dark);
1417 } else { // Custom proxy is disabled.
1418 proxyCustomHostPreference.setIcon(R.drawable.proxy_ghosted_dark);
1419 proxyCustomPortPreference.setIcon(R.drawable.proxy_ghosted_dark);
1421 } else { // Light theme.
1422 // Set the main proxy icon to be enabled.
1423 proxyPreference.setIcon(R.drawable.proxy_enabled_light);
1425 // Set the custom proxy icons according to their status.
1426 if (proxyCustomHostPreference.isEnabled()) { // Custom proxy is enabled.
1427 proxyCustomHostPreference.setIcon(R.drawable.proxy_enabled_light);
1428 proxyCustomPortPreference.setIcon(R.drawable.proxy_enabled_light);
1429 } else { // Custom proxy is disabled.
1430 proxyCustomHostPreference.setIcon(R.drawable.proxy_ghosted_light);
1431 proxyCustomPortPreference.setIcon(R.drawable.proxy_ghosted_light);
1437 case "proxy_custom_host":
1438 // Set the summary text for the proxy custom host.
1439 proxyCustomHostPreference.setSummary(sharedPreferences.getString("proxy_custom_host", getString(R.string.proxy_custom_host_default_value)));
1442 case "proxy_custom_port":
1443 // Set the summary text for the proxy custom port.
1444 proxyCustomPortPreference.setSummary(sharedPreferences.getString("proxy_custom_port", getString(R.string.proxy_custom_port_default_value)));
1446 case "full_screen_browsing_mode":
1447 if (sharedPreferences.getBoolean("full_screen_browsing_mode", false)) { // Full screen browsing is enabled.
1448 // Set the full screen browsing mode preference icon according to the theme.
1450 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_dark);
1452 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_light);
1455 // Set the hide app bar preference icon.
1456 if (sharedPreferences.getBoolean("hide_app_bar", true)) { // Hide app bar is enabled.
1457 // Set the icon according to the theme.
1459 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
1461 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
1463 } else { // Hide app bar is disabled.
1464 // Set the icon according to the theme.
1466 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
1468 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
1471 } else { // Full screen browsing is disabled.
1472 // Update the icons according to the theme.
1474 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_dark);
1475 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_dark);
1477 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_light);
1478 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_light);
1483 case "hide_app_bar":
1485 if (sharedPreferences.getBoolean("hide_app_bar", true)) { // Hide app bar is enabled.
1486 // Set the icon according to the theme.
1488 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
1490 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
1492 } else { // Hide app bar is disabled.
1493 // Set the icon according to the theme.
1495 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
1497 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
1502 case "clear_everything":
1503 // Store the new `clear_everything` status
1504 boolean newClearEverythingBoolean = sharedPreferences.getBoolean("clear_everything", true);
1506 // Update the status of the `Clear and Exit` preferences.
1507 clearCookiesPreference.setEnabled(!newClearEverythingBoolean);
1508 clearDomStoragePreference.setEnabled(!newClearEverythingBoolean);
1509 clearFormDataPreference.setEnabled(!newClearEverythingBoolean); // This line can be removed once the minimum API >= 26.
1510 clearCachePreference.setEnabled(!newClearEverythingBoolean);
1512 // Update the `clearEverythingPreference` icon.
1513 if (newClearEverythingBoolean) {
1515 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_dark);
1517 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_light);
1520 clearEverythingPreference.setIcon(R.drawable.clear_everything_disabled);
1523 // Update the `clearCookiesPreference` icon.
1524 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_cookies", true)) {
1526 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_dark);
1528 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_light);
1531 clearCookiesPreference.setIcon(R.drawable.cookies_warning);
1534 // Update the `clearDomStoragePreference` icon.
1535 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_dom_storage", true)) {
1537 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_dark);
1539 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_light);
1542 clearDomStoragePreference.setIcon(R.drawable.dom_storage_warning);
1545 // Update the clear form data preference icon if the API < 26.
1546 if (Build.VERSION.SDK_INT < 26) {
1547 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_form_data", true)) {
1549 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_dark);
1551 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_light);
1554 clearFormDataPreference.setIcon(R.drawable.form_data_warning);
1558 // Update the `clearCachePreference` icon.
1559 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_cache", true)) {
1561 clearCachePreference.setIcon(R.drawable.cache_cleared_dark);
1563 clearCachePreference.setIcon(R.drawable.cache_cleared_light);
1566 clearCachePreference.setIcon(R.drawable.cache_warning);
1570 case "clear_cookies":
1572 if (sharedPreferences.getBoolean("clear_cookies", true)) {
1574 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_dark);
1576 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_light);
1579 clearCookiesPreference.setIcon(R.drawable.cookies_warning);
1583 case "clear_dom_storage":
1585 if (sharedPreferences.getBoolean("clear_dom_storage", true)) {
1587 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_dark);
1589 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_light);
1592 clearDomStoragePreference.setIcon(R.drawable.dom_storage_warning);
1596 // This section can be removed once the minimum API >= 26.
1597 case "clear_form_data":
1599 if (sharedPreferences.getBoolean("clear_form_data", true)) {
1601 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_dark);
1603 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_light);
1606 clearFormDataPreference.setIcon(R.drawable.form_data_warning);
1612 if (sharedPreferences.getBoolean("clear_cache", true)) {
1614 clearCachePreference.setIcon(R.drawable.cache_cleared_dark);
1616 clearCachePreference.setIcon(R.drawable.cache_cleared_light);
1619 clearCachePreference.setIcon(R.drawable.cache_warning);
1624 // Set the new homepage URL as the summary text for the Homepage preference.
1625 homepagePreference.setSummary(sharedPreferences.getString("homepage", getString(R.string.homepage_default_value)));
1629 // Update the font size summary text.
1630 fontSizePreference.setSummary(sharedPreferences.getString("font_size", getString(R.string.font_size_default_value)) + "%");
1633 case "open_intents_in_new_tab":
1635 if (sharedPreferences.getBoolean("open_intents_in_new_tab", true)) {
1637 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_dark);
1639 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_light);
1643 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_dark);
1645 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_light);
1650 case "swipe_to_refresh":
1652 if (sharedPreferences.getBoolean("swipe_to_refresh", true)) {
1654 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_dark);
1656 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_light);
1660 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_dark);
1662 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_light);
1667 case "scroll_app_bar":
1669 if (sharedPreferences.getBoolean("scroll_app_bar", true)) {
1671 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
1673 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
1677 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
1679 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
1684 case "display_additional_app_bar_icons":
1686 if (sharedPreferences.getBoolean("display_additional_app_bar_icons", false)) {
1688 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_dark);
1690 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_light);
1694 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_dark);
1696 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_light);
1701 case "download_with_external_app":
1703 if (sharedPreferences.getBoolean("download_with_external_app", false)) {
1705 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_enabled_dark);
1707 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_enabled_light);
1711 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_disabled_dark);
1713 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_disabled_light);
1720 if (sharedPreferences.getBoolean("dark_theme", false)) {
1721 darkThemePreference.setIcon(R.drawable.theme_dark);
1723 darkThemePreference.setIcon(R.drawable.theme_light);
1726 // Create an intent to restart Privacy Browser.
1727 Intent changeThemeRestartIntent = getActivity().getParentActivityIntent();
1729 // Assert that the intent is not null to remove the lint error below.
1730 assert changeThemeRestartIntent != null;
1732 // `Intent.FLAG_ACTIVITY_CLEAR_TASK` removes all activities from the stack. It requires `Intent.FLAG_ACTIVITY_NEW_TASK`.
1733 changeThemeRestartIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
1735 // Create a handler to restart the activity.
1736 Handler changeThemeRestartHandler = new Handler();
1738 // Create a runnable to restart the activity.
1739 Runnable changeThemeRestartRunnable = () -> {
1740 // Restart the activity.
1741 startActivity(changeThemeRestartIntent);
1743 // Kill this instance of Privacy Browser. Otherwise, the app exhibits sporadic behavior after the restart.
1747 // Restart the activity after 150 milliseconds, so that the app has enough time to save the change to the preference.
1748 changeThemeRestartHandler.postDelayed(changeThemeRestartRunnable, 150);
1752 // Store the current night mode status.
1753 boolean currentNightModeBoolean = sharedPreferences.getBoolean("night_mode", false);
1754 boolean currentJavaScriptBoolean = sharedPreferences.getBoolean("javascript", false);
1757 if (currentNightModeBoolean) {
1759 nightModePreference.setIcon(R.drawable.night_mode_enabled_dark);
1761 nightModePreference.setIcon(R.drawable.night_mode_enabled_light);
1765 nightModePreference.setIcon(R.drawable.night_mode_disabled_dark);
1767 nightModePreference.setIcon(R.drawable.night_mode_disabled_light);
1771 // Update the status of `javaScriptPreference` and `domStoragePreference`.
1772 javaScriptPreference.setEnabled(!currentNightModeBoolean);
1773 domStoragePreference.setEnabled(currentNightModeBoolean || currentJavaScriptBoolean);
1775 // Update the `javaScriptPreference` icon.
1776 if (currentNightModeBoolean || currentJavaScriptBoolean) {
1777 javaScriptPreference.setIcon(R.drawable.javascript_enabled);
1779 javaScriptPreference.setIcon(R.drawable.privacy_mode);
1782 // Update the DOM storage preference icon.
1783 if (currentNightModeBoolean || currentJavaScriptBoolean) { // The preference is enabled.
1784 if (sharedPreferences.getBoolean("dom_storage", false)) { // DOM storage is enabled.
1785 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
1786 } else { // DOM storage is disabled.
1788 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_dark);
1790 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_light);
1793 } else { // The preference is disabled. The icon should be ghosted.
1795 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_dark);
1797 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_light);
1802 case "wide_viewport":
1804 if (sharedPreferences.getBoolean("wide_viewport", true)) {
1806 wideViewportPreference.setIcon(R.drawable.wide_viewport_enabled_dark);
1808 wideViewportPreference.setIcon(R.drawable.wide_viewport_enabled_light);
1812 wideViewportPreference.setIcon(R.drawable.wide_viewport_disabled_dark);
1814 wideViewportPreference.setIcon(R.drawable.wide_viewport_disabled_light);
1819 case "display_webpage_images":
1821 if (sharedPreferences.getBoolean("display_webpage_images", true)) {
1823 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_dark);
1825 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_light);
1829 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_dark);
1831 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_light);
1838 // Register the listener.
1839 savedPreferences.registerOnSharedPreferenceChangeListener(preferencesListener);
1842 // 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.
1844 public void onPause() {
1846 savedPreferences.unregisterOnSharedPreferenceChangeListener(preferencesListener);
1850 public void onResume() {
1852 savedPreferences.registerOnSharedPreferenceChangeListener(preferencesListener);