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;
42 public class SettingsFragment extends PreferenceFragmentCompat {
43 // Define the class variables.
44 private SharedPreferences.OnSharedPreferenceChangeListener preferencesListener;
45 private SharedPreferences savedPreferences;
48 public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
49 // Load the preferences from the XML file.
50 setPreferencesFromResource(R.xml.preferences, rootKey);
52 // Get a handle for the activity.
53 Activity activity = getActivity();
55 // Remove the lint warning below that `getApplicationContext()` might produce a null pointer exception.
56 assert activity != null;
58 // Get a handle for the context.
59 Context context = activity.getApplicationContext();
61 // Initialize savedPreferences.
62 savedPreferences = getPreferenceScreen().getSharedPreferences();
64 // Get handles for the preferences.
65 Preference javaScriptPreference = findPreference("javascript");
66 Preference firstPartyCookiesPreference = findPreference("first_party_cookies");
67 Preference thirdPartyCookiesPreference = findPreference("third_party_cookies");
68 Preference domStoragePreference = findPreference("dom_storage");
69 Preference formDataPreference = findPreference("save_form_data"); // The form data preference can be removed once the minimum API >= 26.
70 Preference userAgentPreference = findPreference("user_agent");
71 Preference customUserAgentPreference = findPreference("custom_user_agent");
72 Preference incognitoModePreference = findPreference("incognito_mode");
73 Preference doNotTrackPreference = findPreference("do_not_track");
74 Preference allowScreenshotsPreference = findPreference("allow_screenshots");
75 Preference easyListPreference = findPreference("easylist");
76 Preference easyPrivacyPreference = findPreference("easyprivacy");
77 Preference fanboyAnnoyanceListPreference = findPreference("fanboys_annoyance_list");
78 Preference fanboySocialBlockingListPreference = findPreference("fanboys_social_blocking_list");
79 Preference ultraListPreference = findPreference("ultralist");
80 Preference ultraPrivacyPreference = findPreference("ultraprivacy");
81 Preference blockAllThirdPartyRequestsPreference = findPreference("block_all_third_party_requests");
82 Preference googleAnalyticsPreference = findPreference("google_analytics");
83 Preference facebookClickIdsPreference = findPreference("facebook_click_ids");
84 Preference twitterAmpRedirectsPreference = findPreference("twitter_amp_redirects");
85 Preference proxyThroughOrbotPreference = findPreference("proxy_through_orbot");
86 Preference torHomepagePreference = findPreference("tor_homepage");
87 Preference torSearchPreference = findPreference("tor_search");
88 Preference torSearchCustomURLPreference = findPreference("tor_search_custom_url");
89 Preference searchPreference = findPreference("search");
90 Preference searchCustomURLPreference = findPreference("search_custom_url");
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 proxyThroughOrbotPreference != null;
132 assert torHomepagePreference != null;
133 assert torSearchPreference != null;
134 assert torSearchCustomURLPreference != null;
135 assert searchPreference != null;
136 assert searchCustomURLPreference != null;
137 assert fullScreenBrowsingModePreference != null;
138 assert hideAppBarPreference != null;
139 assert clearEverythingPreference != null;
140 assert clearCookiesPreference != null;
141 assert clearDomStoragePreference != null;
142 assert clearFormDataPreference != null;
143 assert clearCachePreference != null;
144 assert homepagePreference != null;
145 assert fontSizePreference != null;
146 assert openIntentsInNewTabPreference != null;
147 assert swipeToRefreshPreference != null;
148 assert scrollAppBarPreference != null;
149 assert displayAdditionalAppBarIconsPreference != null;
150 assert downloadWithExternalAppPreference != null;
151 assert darkThemePreference != null;
152 assert nightModePreference != null;
153 assert wideViewportPreference != null;
154 assert displayWebpageImagesPreference != null;
157 torHomepagePreference.setDependency("proxy_through_orbot");
158 torSearchPreference.setDependency("proxy_through_orbot");
159 hideAppBarPreference.setDependency("full_screen_browsing_mode");
161 // Get strings from the preferences.
162 String torSearchString = savedPreferences.getString("tor_search", getString(R.string.tor_search_default_value));
163 String searchString = savedPreferences.getString("search", getString(R.string.search_default_value));
165 // Get booleans that are used in multiple places from the preferences.
166 boolean javaScriptEnabled = savedPreferences.getBoolean("javascript", false);
167 boolean firstPartyCookiesEnabled = savedPreferences.getBoolean("first_party_cookies", false);
168 boolean thirdPartyCookiesEnabled = savedPreferences.getBoolean("third_party_cookies", false);
169 boolean fanboyAnnoyanceListEnabled = savedPreferences.getBoolean("fanboys_annoyance_list", true);
170 boolean fanboySocialBlockingEnabled = savedPreferences.getBoolean("fanboys_social_blocking_list", true);
171 boolean proxyThroughOrbot = savedPreferences.getBoolean("proxy_through_orbot", false);
172 boolean fullScreenBrowsingMode = savedPreferences.getBoolean("full_screen_browsing_mode", false);
173 boolean clearEverything = savedPreferences.getBoolean("clear_everything", true);
174 boolean darkTheme = savedPreferences.getBoolean("dark_theme", false);
175 boolean nightMode = savedPreferences.getBoolean("night_mode", false);
177 // Only enable the third-party cookies preference if first-party cookies are enabled and API >= 21.
178 thirdPartyCookiesPreference.setEnabled(firstPartyCookiesEnabled && (Build.VERSION.SDK_INT >= 21));
180 // Only enable the DOM storage preference if either JavaScript or Night Mode is enabled.
181 domStoragePreference.setEnabled(javaScriptEnabled || nightMode);
183 // Remove the form data preferences if the API is >= 26 as they no longer do anything.
184 if (Build.VERSION.SDK_INT >= 26) {
185 // Get the categories.
186 PreferenceCategory privacyCategory = findPreference("privacy");
187 PreferenceCategory clearAndExitCategory = findPreference("clear_and_exit");
189 // Remove the lint warnings below that the preference categories might be null.
190 assert privacyCategory != null;
191 assert clearAndExitCategory != null;
193 // Remove the form data preferences.
194 privacyCategory.removePreference(formDataPreference);
195 clearAndExitCategory.removePreference(clearFormDataPreference);
198 // Only enable Fanboy's social blocking list preference if Fanboy's annoyance list is disabled.
199 fanboySocialBlockingListPreference.setEnabled(!fanboyAnnoyanceListEnabled);
201 // Inflate a WebView to get the default user agent.
202 LayoutInflater inflater = getActivity().getLayoutInflater();
203 // `@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.
204 @SuppressLint("InflateParams") View bareWebViewLayout = inflater.inflate(R.layout.bare_webview, null, false);
205 WebView bareWebView = bareWebViewLayout.findViewById(R.id.bare_webview);
207 // Get the user agent arrays.
208 ArrayAdapter<CharSequence> userAgentNamesArray = ArrayAdapter.createFromResource(context, R.array.user_agent_names, R.layout.spinner_item);
209 String[] translatedUserAgentNamesArray = getResources().getStringArray(R.array.translated_user_agent_names);
210 String[] userAgentDataArray = getResources().getStringArray(R.array.user_agent_data);
212 // Get the current user agent name from the preference.
213 String userAgentName = savedPreferences.getString("user_agent", getString(R.string.user_agent_default_value));
215 // Get the array position of the user agent name.
216 int userAgentArrayPosition = userAgentNamesArray.getPosition(userAgentName);
218 // Populate the user agent summary.
219 switch (userAgentArrayPosition) {
220 case MainWebViewActivity.UNRECOGNIZED_USER_AGENT: // The user agent name is not on the canonical list.
221 // 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.
222 userAgentPreference.setSummary(userAgentName);
225 case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
226 // Get the user agent text from the webview (which changes based on the version of Android and WebView installed).
227 userAgentPreference.setSummary(translatedUserAgentNamesArray[userAgentArrayPosition] + ":\n" + bareWebView.getSettings().getUserAgentString());
230 case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
231 // Set the summary text.
232 userAgentPreference.setSummary(R.string.custom_user_agent);
236 // Get the user agent summary from the user agent data array.
237 userAgentPreference.setSummary(translatedUserAgentNamesArray[userAgentArrayPosition] + ":\n" + userAgentDataArray[userAgentArrayPosition]);
240 // Set the summary text for the custom user agent preference and enable it if user agent preference is set to custom.
241 customUserAgentPreference.setSummary(savedPreferences.getString("custom_user_agent", getString(R.string.custom_user_agent_default_value)));
242 customUserAgentPreference.setEnabled(userAgentPreference.getSummary().equals(getString(R.string.custom_user_agent)));
245 // Set the Tor homepage URL as the summary text for the `tor_homepage` preference when the preference screen is loaded. The default is Searx: `http://ulrn6sryqaifefld.onion/`.
246 torHomepagePreference.setSummary(savedPreferences.getString("tor_homepage", getString(R.string.tor_homepage_default_value)));
249 // Set the Tor search URL as the summary text for the Tor preference when the preference screen is loaded.
250 if (torSearchString.equals("Custom URL")) {
251 // Use R.string.custom_url, which will be translated, instead of the array value, which will not.
252 torSearchPreference.setSummary(R.string.custom_url);
254 // Set the array value as the summary text.
255 torSearchPreference.setSummary(torSearchString);
258 // Set the summary text for `tor_search_custom_url`. The default is `""`.
259 torSearchCustomURLPreference.setSummary(savedPreferences.getString("tor_search_custom_url", getString(R.string.tor_search_custom_url_default_value)));
261 // Enable the Tor custom URL search options only if proxying through Orbot and the search is set to `Custom URL`.
262 torSearchCustomURLPreference.setEnabled(proxyThroughOrbot && torSearchString.equals("Custom URL"));
265 // Set the search URL as the summary text for the search preference when the preference screen is loaded.
266 if (searchString.equals("Custom URL")) {
267 // Use R.string.custom_url, which will be translated, instead of the array value, which will not.
268 searchPreference.setSummary(R.string.custom_url);
270 // Set the array value as the summary text.
271 searchPreference.setSummary(searchString);
274 // Set the summary text for `search_custom_url` (the default is `""`) and enable it if `search` is set to `Custom URL`.
275 searchCustomURLPreference.setSummary(savedPreferences.getString("search_custom_url", getString(R.string.search_custom_url_default_value)));
276 searchCustomURLPreference.setEnabled(searchString.equals("Custom URL"));
278 // Set the status of the Clear and Exit preferences.
279 clearCookiesPreference.setEnabled(!clearEverything);
280 clearDomStoragePreference.setEnabled(!clearEverything);
281 clearFormDataPreference.setEnabled(!clearEverything); // The form data line can be removed once the minimum API is >= 26.
282 clearCachePreference.setEnabled(!clearEverything);
284 // Set the homepage URL as the summary text for the homepage preference.
285 homepagePreference.setSummary(savedPreferences.getString("homepage", getString(R.string.homepage_default_value)));
287 // Set the font size as the summary text for the preference.
288 fontSizePreference.setSummary(savedPreferences.getString("font_size", getString(R.string.font_size_default_value)) + "%");
290 // Disable the JavaScript preference if Night Mode is enabled. JavaScript will be enabled for all web pages.
291 javaScriptPreference.setEnabled(!nightMode);
293 // Set the JavaScript icon.
294 if (javaScriptEnabled || nightMode) {
295 javaScriptPreference.setIcon(R.drawable.javascript_enabled);
297 javaScriptPreference.setIcon(R.drawable.privacy_mode);
300 // Set the first-party cookies icon.
301 if (firstPartyCookiesEnabled) {
302 firstPartyCookiesPreference.setIcon(R.drawable.cookies_enabled);
305 firstPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
307 firstPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
311 // Set the third party cookies icon.
312 if (firstPartyCookiesEnabled && Build.VERSION.SDK_INT >= 21) {
313 if (thirdPartyCookiesEnabled) {
314 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_warning);
317 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
319 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
324 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_dark);
326 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_light);
330 // Set the DOM storage icon.
331 if (javaScriptEnabled || nightMode) { // The preference is enabled.
332 if (savedPreferences.getBoolean("dom_storage", false)) { // DOM storage is enabled.
333 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
334 } else { // DOM storage is disabled.
336 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_dark);
338 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_light);
341 } else { // The preference is disabled. The icon should be ghosted.
343 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_dark);
345 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_light);
349 // Set the save form data icon if API < 26. Save form data has no effect on API >= 26.
350 if (Build.VERSION.SDK_INT < 26) {
351 if (savedPreferences.getBoolean("save_form_data", false)) {
352 formDataPreference.setIcon(R.drawable.form_data_enabled);
355 formDataPreference.setIcon(R.drawable.form_data_disabled_dark);
357 formDataPreference.setIcon(R.drawable.form_data_disabled_light);
362 // Set the custom user agent icon.
363 if (customUserAgentPreference.isEnabled()) {
365 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_dark);
367 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_light);
371 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_dark);
373 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_light);
377 // Set the incognito mode icon.
378 if (savedPreferences.getBoolean("incognito_mode", false)) {
380 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_dark);
382 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_light);
386 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_dark);
388 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_light);
392 // Set the Do Not Track icon.
393 if (savedPreferences.getBoolean("do_not_track", false)) {
395 doNotTrackPreference.setIcon(R.drawable.block_tracking_enabled_dark);
397 doNotTrackPreference.setIcon(R.drawable.block_tracking_enabled_light);
401 doNotTrackPreference.setIcon(R.drawable.block_tracking_disabled_dark);
403 doNotTrackPreference.setIcon(R.drawable.block_tracking_disabled_light);
407 // Set the allow screenshots icon.
408 if (savedPreferences.getBoolean("allow_screenshots", false)) {
410 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_dark);
412 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_light);
416 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_dark);
418 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_light);
422 // Set the EasyList icon.
423 if (savedPreferences.getBoolean("easylist", true)) {
425 easyListPreference.setIcon(R.drawable.block_ads_enabled_dark);
427 easyListPreference.setIcon(R.drawable.block_ads_enabled_light);
431 easyListPreference.setIcon(R.drawable.block_ads_disabled_dark);
433 easyListPreference.setIcon(R.drawable.block_ads_disabled_light);
437 // Set the EasyPrivacy icon.
438 if (savedPreferences.getBoolean("easyprivacy", true)) {
440 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_dark);
442 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_light);
446 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_dark);
448 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_light);
452 // Set the Fanboy lists icons.
453 if (fanboyAnnoyanceListEnabled) {
455 // Set the Fanboy annoyance list icon.
456 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_dark);
458 // Set the Fanboy social blocking list icon.
459 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_dark);
461 // Set the Fanboy annoyance list icon.
462 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_light);
464 // Set the Fanboy social blocking list icon.
465 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_light);
469 // Set the Fanboy annoyance list icon.
470 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled_dark);
472 // Set the Fanboy social blocking list icon.
473 if (fanboySocialBlockingEnabled) {
474 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_dark);
476 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_dark);
479 // Set the Fanboy annoyance list icon.
480 fanboyAnnoyanceListPreference.setIcon(R.drawable.block_ads_disabled_light);
482 // Set the Fanboy social blocking list icon.
483 if (fanboySocialBlockingEnabled) {
484 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_light);
486 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_light);
491 // Set the UltraList icon.
492 if (savedPreferences.getBoolean("ultralist", true)){
494 ultraListPreference.setIcon(R.drawable.block_ads_enabled_dark);
496 ultraListPreference.setIcon(R.drawable.block_ads_enabled_light);
500 ultraListPreference.setIcon(R.drawable.block_ads_disabled_dark);
502 ultraListPreference.setIcon(R.drawable.block_ads_disabled_light);
506 // Set the UltraPrivacy icon.
507 if (savedPreferences.getBoolean("ultraprivacy", true)) {
509 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_dark);
511 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_light);
515 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_dark);
517 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_light);
521 // Set the block all third-party requests icon.
522 if (savedPreferences.getBoolean("block_all_third_party_requests", false)) {
524 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_dark);
526 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_light);
530 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_dark);
532 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_light);
536 // Set the Google Analytics icon according to the theme.
537 if (savedPreferences.getBoolean("google_analytics", true)) {
539 googleAnalyticsPreference.setIcon(R.drawable.modify_url_enabled_dark);
541 googleAnalyticsPreference.setIcon(R.drawable.modify_url_enabled_light);
545 googleAnalyticsPreference.setIcon(R.drawable.modify_url_disabled_dark);
547 googleAnalyticsPreference.setIcon(R.drawable.modify_url_disabled_light);
551 // Set the Facebook Click IDs icon according to the theme.
552 if (savedPreferences.getBoolean("facebook_click_ids", true)) {
554 facebookClickIdsPreference.setIcon(R.drawable.modify_url_enabled_dark);
556 facebookClickIdsPreference.setIcon(R.drawable.modify_url_enabled_light);
560 facebookClickIdsPreference.setIcon(R.drawable.modify_url_disabled_dark);
562 facebookClickIdsPreference.setIcon(R.drawable.modify_url_disabled_light);
566 // Set the Twitter AMP redirects icon according to the theme.
567 if (savedPreferences.getBoolean("twitter_amp_redirects", true)) {
569 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_enabled_dark);
571 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_enabled_light);
575 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_disabled_dark);
577 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_disabled_light);
581 // Set the Tor icons according to the theme.
582 if (proxyThroughOrbot) { // Proxying is enabled.
584 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_enabled_dark);
585 torHomepagePreference.setIcon(R.drawable.home_enabled_dark);
586 torSearchPreference.setIcon(R.drawable.search_enabled_dark);
588 // Set the custom search icon.
589 if (torSearchCustomURLPreference.isEnabled()) {
590 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_dark);
592 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
595 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_enabled_light);
596 torHomepagePreference.setIcon(R.drawable.home_enabled_light);
597 torSearchPreference.setIcon(R.drawable.search_enabled_light);
599 // Set the custom search icon.
600 if (torSearchCustomURLPreference.isEnabled()) {
601 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_light);
603 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
606 } else { // Proxying is disabled.
608 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_disabled_dark);
609 torHomepagePreference.setIcon(R.drawable.home_ghosted_dark);
610 torSearchPreference.setIcon(R.drawable.search_ghosted_dark);
611 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
613 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_disabled_light);
614 torHomepagePreference.setIcon(R.drawable.home_ghosted_light);
615 torSearchPreference.setIcon(R.drawable.search_ghosted_light);
616 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
620 // Set the search custom URL icon.
621 if (searchCustomURLPreference.isEnabled()) {
623 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_dark);
625 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_light);
629 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
631 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
635 // Set the full screen browsing mode icons.
636 if (fullScreenBrowsingMode) { // Full screen browsing mode is enabled.
637 // Set the `fullScreenBrowsingModePreference` icon according to the theme.
639 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_dark);
641 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_light);
644 // Set the hide app bar icon.
645 if (savedPreferences.getBoolean("hide_app_bar", true)) { // Hide app bar is enabled.
646 // Set the icon according to the theme.
648 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
650 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
652 } else { // Hide app bar is disabled.
653 // Set the icon according to the theme.
655 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
657 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
660 } else { // Full screen browsing mode is disabled.
661 // Set the icons according to the theme.
663 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_dark);
664 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_dark);
666 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_light);
667 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_light);
671 // Set the clear everything preference icon.
672 if (clearEverything) {
674 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_dark);
676 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_light);
679 clearEverythingPreference.setIcon(R.drawable.clear_everything_disabled);
682 // Set the clear cookies preference icon.
683 if (clearEverything || savedPreferences.getBoolean("clear_cookies", true)) {
685 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_dark);
687 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_light);
690 clearCookiesPreference.setIcon(R.drawable.cookies_warning);
693 // Set the clear DOM storage preference icon.
694 if (clearEverything || savedPreferences.getBoolean("clear_dom_storage", true)) {
696 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_dark);
698 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_light);
701 clearDomStoragePreference.setIcon(R.drawable.dom_storage_warning);
704 // Set the clear form data preference icon if the API < 26. It has no effect on newer versions of Android.
705 if (Build.VERSION.SDK_INT < 26) {
706 if (clearEverything || savedPreferences.getBoolean("clear_form_data", true)) {
708 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_dark);
710 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_light);
713 clearFormDataPreference.setIcon(R.drawable.form_data_warning);
717 // Set the clear cache preference icon.
718 if (clearEverything || savedPreferences.getBoolean("clear_cache", true)) {
720 clearCachePreference.setIcon(R.drawable.cache_cleared_dark);
722 clearCachePreference.setIcon(R.drawable.cache_cleared_light);
725 clearCachePreference.setIcon(R.drawable.cache_warning);
728 // Set the open intents in new tab preference icon.
729 if (savedPreferences.getBoolean("open_intents_in_new_tab", true)) {
731 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_dark);
733 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_light);
737 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_dark);
739 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_light);
743 // Set the swipe to refresh preference icon.
744 if (savedPreferences.getBoolean("swipe_to_refresh", true)) {
746 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_dark);
748 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_light);
752 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_dark);
754 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_light);
758 // Set the scroll app bar preference icon.
759 if (savedPreferences.getBoolean("scroll_app_bar", true)) {
761 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
763 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
767 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
769 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
773 // Set the display additional app bar icons preference icon.
774 if (savedPreferences.getBoolean("display_additional_app_bar_icons", false)) {
776 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_dark);
778 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_light);
782 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_dark);
784 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_light);
788 // Set the download with external app preference icon.
789 if (savedPreferences.getBoolean("download_with_external_app", false)) {
791 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_enabled_dark);
793 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_enabled_light);
797 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_disabled_dark);
799 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_disabled_light);
803 // Set the dark theme preference icon.
804 if (savedPreferences.getBoolean("dark_theme", false)) {
805 darkThemePreference.setIcon(R.drawable.theme_dark);
807 darkThemePreference.setIcon(R.drawable.theme_light);
810 // Set the night mode preference icon.
813 nightModePreference.setIcon(R.drawable.night_mode_enabled_dark);
815 nightModePreference.setIcon(R.drawable.night_mode_enabled_light);
819 nightModePreference.setIcon(R.drawable.night_mode_disabled_dark);
821 nightModePreference.setIcon(R.drawable.night_mode_disabled_light);
825 // Set the wide viewport preference icon.
826 if (savedPreferences.getBoolean("wide_viewport", true)) {
828 wideViewportPreference.setIcon(R.drawable.wide_viewport_enabled_dark);
830 wideViewportPreference.setIcon(R.drawable.wide_viewport_enabled_light);
834 wideViewportPreference.setIcon(R.drawable.wide_viewport_disabled_dark);
836 wideViewportPreference.setIcon(R.drawable.wide_viewport_disabled_light);
840 // Set the display webpage images preference icon.
841 if (savedPreferences.getBoolean("display_webpage_images", true)) {
843 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_dark);
845 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_light);
849 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_dark);
851 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_light);
856 // Listen for preference changes.
857 preferencesListener = (SharedPreferences sharedPreferences, String key) -> {
860 // Update the icons and the DOM storage preference status.
861 if (sharedPreferences.getBoolean("javascript", false)) { // The JavaScript preference is enabled.
862 // Update the icon for the JavaScript preference.
863 javaScriptPreference.setIcon(R.drawable.javascript_enabled);
865 // Update the status of the DOM storage preference.
866 domStoragePreference.setEnabled(true);
868 // Update the icon for the DOM storage preference.
869 if (sharedPreferences.getBoolean("dom_storage", false)) {
870 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
873 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_dark);
875 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_light);
878 } else { // The JavaScript preference is disabled.
879 // Update the icon for the JavaScript preference.
880 javaScriptPreference.setIcon(R.drawable.privacy_mode);
882 // Update the status of the DOM storage preference.
883 domStoragePreference.setEnabled(false);
885 // Set the icon for DOM storage preference to be ghosted.
887 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_dark);
889 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_light);
894 case "first_party_cookies":
895 // Update the icons for `first_party_cookies` and `third_party_cookies`.
896 if (sharedPreferences.getBoolean("first_party_cookies", false)) {
897 // Set the icon for `first_party_cookies`.
898 firstPartyCookiesPreference.setIcon(R.drawable.cookies_enabled);
900 // Update the icon for `third_party_cookies`.
901 if (Build.VERSION.SDK_INT >= 21) {
902 if (sharedPreferences.getBoolean("third_party_cookies", false)) {
903 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_warning);
906 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
908 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
913 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_dark);
915 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_light);
918 } else { // `first_party_cookies` is `false`.
919 // Update the icon for `first_party_cookies`.
921 firstPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
923 firstPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
926 // Set the icon for `third_party_cookies` to be ghosted.
928 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_dark);
930 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted_light);
934 // Enable `third_party_cookies` if `first_party_cookies` is `true` and API >= 21.
935 thirdPartyCookiesPreference.setEnabled(sharedPreferences.getBoolean("first_party_cookies", false) && (Build.VERSION.SDK_INT >= 21));
938 case "third_party_cookies":
940 if (sharedPreferences.getBoolean("third_party_cookies", false)) {
941 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_warning);
944 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_dark);
946 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled_light);
953 if (sharedPreferences.getBoolean("dom_storage", false)) {
954 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
957 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_dark);
959 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_light);
964 // Save form data can be removed once the minimum API >= 26.
965 case "save_form_data":
967 if (sharedPreferences.getBoolean("save_form_data", false)) {
968 formDataPreference.setIcon(R.drawable.form_data_enabled);
971 formDataPreference.setIcon(R.drawable.form_data_disabled_dark);
973 formDataPreference.setIcon(R.drawable.form_data_disabled_light);
979 // Get the new user agent name.
980 String newUserAgentName = sharedPreferences.getString("user_agent", getString(R.string.user_agent_default_value));
982 // Get the array position for the new user agent name.
983 int newUserAgentArrayPosition = userAgentNamesArray.getPosition(newUserAgentName);
985 // Get the translated new user agent name.
986 String translatedNewUserAgentName = translatedUserAgentNamesArray[newUserAgentArrayPosition];
988 // Populate the user agent summary.
989 switch (newUserAgentArrayPosition) {
990 case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
991 // Get the user agent text from the webview (which changes based on the version of Android and WebView installed).
992 userAgentPreference.setSummary(translatedNewUserAgentName + ":\n" + bareWebView.getSettings().getUserAgentString());
994 // Disable the custom user agent preference.
995 customUserAgentPreference.setEnabled(false);
997 // Set the custom user agent preference icon according to the theme.
999 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_dark);
1001 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_light);
1005 case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
1006 // Set the summary text.
1007 userAgentPreference.setSummary(R.string.custom_user_agent);
1009 // Enable the custom user agent preference.
1010 customUserAgentPreference.setEnabled(true);
1012 // Set the custom user agent preference icon according to the theme.
1014 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_dark);
1016 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_light);
1021 // Get the user agent summary from the user agent data array.
1022 userAgentPreference.setSummary(translatedNewUserAgentName + ":\n" + userAgentDataArray[newUserAgentArrayPosition]);
1024 // Disable the custom user agent preference.
1025 customUserAgentPreference.setEnabled(false);
1027 // Set the custom user agent preference icon according to the theme.
1029 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_dark);
1031 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_light);
1036 case "custom_user_agent":
1037 // Set the new custom user agent as the summary text for the preference.
1038 customUserAgentPreference.setSummary(sharedPreferences.getString("custom_user_agent", getString(R.string.custom_user_agent_default_value)));
1041 case "incognito_mode":
1043 if (sharedPreferences.getBoolean("incognito_mode", false)) {
1045 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_dark);
1047 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_light);
1051 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_dark);
1053 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_light);
1058 case "do_not_track":
1060 if (sharedPreferences.getBoolean("do_not_track", false)) {
1062 doNotTrackPreference.setIcon(R.drawable.block_tracking_enabled_dark);
1064 doNotTrackPreference.setIcon(R.drawable.block_tracking_enabled_light);
1068 doNotTrackPreference.setIcon(R.drawable.block_tracking_disabled_dark);
1070 doNotTrackPreference.setIcon(R.drawable.block_tracking_disabled_light);
1076 case "allow_screenshots":
1078 if (sharedPreferences.getBoolean("allow_screenshots", false)) {
1080 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_dark);
1082 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_light);
1086 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_dark);
1088 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_light);
1092 // Create an intent to restart Privacy Browser.
1093 Intent allowScreenshotsRestartIntent = getActivity().getParentActivityIntent();
1095 // Assert that the intent is not null to remove the lint error below.
1096 assert allowScreenshotsRestartIntent != null;
1098 // `Intent.FLAG_ACTIVITY_CLEAR_TASK` removes all activities from the stack. It requires `Intent.FLAG_ACTIVITY_NEW_TASK`.
1099 allowScreenshotsRestartIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
1101 // Create a handler to restart the activity.
1102 Handler allowScreenshotsRestartHandler = new Handler();
1104 // Create a runnable to restart the activity.
1105 Runnable allowScreenshotsRestartRunnable = () -> {
1106 // Restart the activity.
1107 startActivity(allowScreenshotsRestartIntent);
1109 // Kill this instance of Privacy Browser. Otherwise, the app exhibits sporadic behavior after the restart.
1113 // Restart the activity after 150 milliseconds, so that the app has enough time to save the change to the preference.
1114 allowScreenshotsRestartHandler.postDelayed(allowScreenshotsRestartRunnable, 150);
1119 if (sharedPreferences.getBoolean("easylist", true)) {
1121 easyListPreference.setIcon(R.drawable.block_ads_enabled_dark);
1123 easyListPreference.setIcon(R.drawable.block_ads_enabled_light);
1127 easyListPreference.setIcon(R.drawable.block_ads_disabled_dark);
1129 easyListPreference.setIcon(R.drawable.block_ads_disabled_light);
1136 if (sharedPreferences.getBoolean("easyprivacy", true)) {
1138 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_dark);
1140 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_light);
1144 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_dark);
1146 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_light);
1151 case "fanboys_annoyance_list":
1152 boolean currentFanboyAnnoyanceList = sharedPreferences.getBoolean("fanboys_annoyance_list", true);
1153 boolean currentFanboySocialBlockingList = sharedPreferences.getBoolean("fanboys_social_blocking_list", true);
1155 // Update the Fanboy icons.
1156 if (currentFanboyAnnoyanceList) { // Fanboy's annoyance list is enabled.
1158 // Update the Fanboy's annoyance list icon.
1159 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_dark);
1161 // Update the Fanboy's social blocking list icon.
1162 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_dark);
1164 // Update the Fanboy's annoyance list icon.
1165 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_light);
1167 // Update the Fanboy's social blocking list icon.
1168 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_light);
1170 } else { // Fanboy's annoyance list is disabled.
1172 // Update the Fanboy's annoyance list icon.
1173 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled_dark);
1175 // Update the Fanboy's social blocking list icon.
1176 if (currentFanboySocialBlockingList) {
1177 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_dark);
1179 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_dark);
1182 // Update the Fanboy's annoyance list icon.
1183 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled_light);
1185 // Update the Fanboy's social blocking list icon.
1186 if (currentFanboySocialBlockingList) {
1187 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_light);
1189 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_light);
1194 // Only enable Fanboy's social blocking list preference if Fanboy's annoyance list preference is disabled.
1195 fanboySocialBlockingListPreference.setEnabled(!currentFanboyAnnoyanceList);
1198 case "fanboys_social_blocking_list":
1200 if (sharedPreferences.getBoolean("fanboys_social_blocking_list", true)) {
1202 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_dark);
1204 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_light);
1208 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_dark);
1210 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_light);
1217 if (sharedPreferences.getBoolean("ultralist", true)) {
1219 ultraListPreference.setIcon(R.drawable.block_ads_enabled_dark);
1221 ultraListPreference.setIcon(R.drawable.block_ads_enabled_light);
1225 ultraListPreference.setIcon(R.drawable.block_ads_disabled_dark);
1227 ultraListPreference.setIcon(R.drawable.block_ads_disabled_light);
1232 case "ultraprivacy":
1234 if (sharedPreferences.getBoolean("ultraprivacy", true)) {
1236 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_dark);
1238 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_light);
1242 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_dark);
1244 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_light);
1249 case "block_all_third_party_requests":
1251 if (sharedPreferences.getBoolean("block_all_third_party_requests", false)) {
1253 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_dark);
1255 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_light);
1259 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_dark);
1261 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_light);
1266 case "google_analytics":
1268 if (sharedPreferences.getBoolean("google_analytics", true)) {
1270 googleAnalyticsPreference.setIcon(R.drawable.modify_url_enabled_dark);
1272 googleAnalyticsPreference.setIcon(R.drawable.modify_url_enabled_light);
1276 googleAnalyticsPreference.setIcon(R.drawable.modify_url_disabled_dark);
1278 googleAnalyticsPreference.setIcon(R.drawable.modify_url_disabled_light);
1283 case "facebook_click_ids":
1285 if (sharedPreferences.getBoolean("facebook_click_ids", true)) {
1287 facebookClickIdsPreference.setIcon(R.drawable.modify_url_enabled_dark);
1289 facebookClickIdsPreference.setIcon(R.drawable.modify_url_enabled_light);
1293 facebookClickIdsPreference.setIcon(R.drawable.modify_url_disabled_dark);
1295 facebookClickIdsPreference.setIcon(R.drawable.modify_url_disabled_light);
1300 case "twitter_amp_redirects":
1302 if (sharedPreferences.getBoolean("twitter_amp_redirects", true)) {
1304 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_enabled_dark);
1306 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_enabled_light);
1310 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_disabled_dark);
1312 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_disabled_light);
1317 case "proxy_through_orbot":
1318 // Get current settings.
1319 boolean currentProxyThroughOrbot = sharedPreferences.getBoolean("proxy_through_orbot", false);
1320 String currentTorSearchString = sharedPreferences.getString("tor_search", getString(R.string.tor_search_default_value));
1322 // Enable the Tor custom URL search option only if `currentProxyThroughOrbot` is true and the search is set to `Custom URL`.
1323 torSearchCustomURLPreference.setEnabled(currentProxyThroughOrbot && currentTorSearchString.equals("Custom URL"));
1325 // Update the icons.
1326 if (currentProxyThroughOrbot) {
1327 // Set the Tor icons according to the theme.
1329 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_enabled_dark);
1330 torHomepagePreference.setIcon(R.drawable.home_enabled_dark);
1331 torSearchPreference.setIcon(R.drawable.search_enabled_dark);
1333 // Set the `torSearchCustomURLPreference` icon.
1334 if (torSearchCustomURLPreference.isEnabled()) {
1335 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_dark);
1337 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
1340 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_enabled_light);
1341 torHomepagePreference.setIcon(R.drawable.home_enabled_light);
1342 torSearchPreference.setIcon(R.drawable.search_enabled_light);
1344 // Set the `torSearchCustomURLPreference` icon.
1345 if (torSearchCustomURLPreference.isEnabled()) {
1346 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_light);
1348 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
1351 } else { // Proxy through Orbot is disabled.
1353 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_disabled_dark);
1354 torHomepagePreference.setIcon(R.drawable.home_ghosted_dark);
1355 torSearchPreference.setIcon(R.drawable.search_ghosted_dark);
1356 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
1358 proxyThroughOrbotPreference.setIcon(R.drawable.orbot_disabled_light);
1359 torHomepagePreference.setIcon(R.drawable.home_ghosted_light);
1360 torSearchPreference.setIcon(R.drawable.search_ghosted_light);
1361 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
1366 case "tor_homepage":
1367 // Set the new tor homepage URL as the summary text for the `tor_homepage` preference. The default is Searx: `http://ulrn6sryqaifefld.onion/`.
1368 torHomepagePreference.setSummary(sharedPreferences.getString("tor_homepage", getString(R.string.tor_homepage_default_value)));
1372 // Get the present search string.
1373 String presentTorSearchString = sharedPreferences.getString("tor_search", getString(R.string.tor_search_default_value));
1375 // Update the preferences.
1376 if (presentTorSearchString.equals("Custom URL")) {
1377 // Use `R.string.custom_url`, which is translated, as the summary instead of the array value, which isn't.
1378 torSearchPreference.setSummary(R.string.custom_url);
1380 // Enable `torSearchCustomURLPreference`.
1381 torSearchCustomURLPreference.setEnabled(true);
1383 // Update the `torSearchCustomURLPreference` icon.
1385 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_dark);
1387 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_light);
1390 // Set the array value as the summary text.
1391 torSearchPreference.setSummary(presentTorSearchString);
1393 // Disable `torSearchCustomURLPreference`.
1394 torSearchCustomURLPreference.setEnabled(false);
1396 // Update the `torSearchCustomURLPreference` icon.
1398 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
1400 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
1405 case "tor_search_custom_url":
1406 // Set the summary text for `tor_search_custom_url`.
1407 torSearchCustomURLPreference.setSummary(sharedPreferences.getString("tor_search_custom_url", getString(R.string.tor_search_custom_url_default_value)));
1411 // Store the new search string.
1412 String newSearchString = sharedPreferences.getString("search", getString(R.string.search_default_value));
1414 // Update `searchPreference` and `searchCustomURLPreference`.
1415 if (newSearchString.equals("Custom URL")) { // `Custom URL` is selected.
1416 // Set the summary text to `R.string.custom_url`, which is translated.
1417 searchPreference.setSummary(R.string.custom_url);
1419 // Enable `searchCustomURLPreference`.
1420 searchCustomURLPreference.setEnabled(true);
1422 // Set the `searchCustomURLPreference` according to the theme.
1424 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_dark);
1426 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_light);
1428 } else { // `Custom URL` is not selected.
1429 // Set the summary text to `newSearchString`.
1430 searchPreference.setSummary(newSearchString);
1432 // Disable `searchCustomURLPreference`.
1433 searchCustomURLPreference.setEnabled(false);
1435 // Set the `searchCustomURLPreference` according to the theme.
1437 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_dark);
1439 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_light);
1444 case "search_custom_url":
1445 // Set the new custom search URL as the summary text for `search_custom_url`. The default is `""`.
1446 searchCustomURLPreference.setSummary(sharedPreferences.getString("search_custom_url", getString(R.string.search_custom_url_default_value)));
1449 case "full_screen_browsing_mode":
1450 if (sharedPreferences.getBoolean("full_screen_browsing_mode", false)) { // Full screen browsing is enabled.
1451 // Set the full screen browsing mode preference icon according to the theme.
1453 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_dark);
1455 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_light);
1458 // Set the hide app bar preference icon.
1459 if (sharedPreferences.getBoolean("hide_app_bar", true)) { // Hide app bar is enabled.
1460 // Set the icon according to the theme.
1462 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
1464 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
1466 } else { // Hide app bar is disabled.
1467 // Set the icon according to the theme.
1469 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
1471 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
1474 } else { // Full screen browsing is disabled.
1475 // Update the icons according to the theme.
1477 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_dark);
1478 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_dark);
1480 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_light);
1481 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_light);
1486 case "hide_app_bar":
1488 if (sharedPreferences.getBoolean("hide_app_bar", true)) { // Hide app bar is enabled.
1489 // Set the icon according to the theme.
1491 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
1493 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
1495 } else { // Hide app bar is disabled.
1496 // Set the icon according to the theme.
1498 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
1500 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
1505 case "clear_everything":
1506 // Store the new `clear_everything` status
1507 boolean newClearEverythingBoolean = sharedPreferences.getBoolean("clear_everything", true);
1509 // Update the status of the `Clear and Exit` preferences.
1510 clearCookiesPreference.setEnabled(!newClearEverythingBoolean);
1511 clearDomStoragePreference.setEnabled(!newClearEverythingBoolean);
1512 clearFormDataPreference.setEnabled(!newClearEverythingBoolean); // This line can be removed once the minimum API >= 26.
1513 clearCachePreference.setEnabled(!newClearEverythingBoolean);
1515 // Update the `clearEverythingPreference` icon.
1516 if (newClearEverythingBoolean) {
1518 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_dark);
1520 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_light);
1523 clearEverythingPreference.setIcon(R.drawable.clear_everything_disabled);
1526 // Update the `clearCookiesPreference` icon.
1527 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_cookies", true)) {
1529 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_dark);
1531 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_light);
1534 clearCookiesPreference.setIcon(R.drawable.cookies_warning);
1537 // Update the `clearDomStoragePreference` icon.
1538 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_dom_storage", true)) {
1540 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_dark);
1542 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_light);
1545 clearDomStoragePreference.setIcon(R.drawable.dom_storage_warning);
1548 // Update the clear form data preference icon if the API < 26.
1549 if (Build.VERSION.SDK_INT < 26) {
1550 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_form_data", true)) {
1552 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_dark);
1554 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_light);
1557 clearFormDataPreference.setIcon(R.drawable.form_data_warning);
1561 // Update the `clearCachePreference` icon.
1562 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_cache", true)) {
1564 clearCachePreference.setIcon(R.drawable.cache_cleared_dark);
1566 clearCachePreference.setIcon(R.drawable.cache_cleared_light);
1569 clearCachePreference.setIcon(R.drawable.cache_warning);
1573 case "clear_cookies":
1575 if (sharedPreferences.getBoolean("clear_cookies", true)) {
1577 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_dark);
1579 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_light);
1582 clearCookiesPreference.setIcon(R.drawable.cookies_warning);
1586 case "clear_dom_storage":
1588 if (sharedPreferences.getBoolean("clear_dom_storage", true)) {
1590 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_dark);
1592 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_light);
1595 clearDomStoragePreference.setIcon(R.drawable.dom_storage_warning);
1599 // This section can be removed once the minimum API >= 26.
1600 case "clear_form_data":
1602 if (sharedPreferences.getBoolean("clear_form_data", true)) {
1604 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_dark);
1606 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_light);
1609 clearFormDataPreference.setIcon(R.drawable.form_data_warning);
1615 if (sharedPreferences.getBoolean("clear_cache", true)) {
1617 clearCachePreference.setIcon(R.drawable.cache_cleared_dark);
1619 clearCachePreference.setIcon(R.drawable.cache_cleared_light);
1622 clearCachePreference.setIcon(R.drawable.cache_warning);
1627 // Set the new homepage URL as the summary text for the Homepage preference.
1628 homepagePreference.setSummary(sharedPreferences.getString("homepage", getString(R.string.homepage_default_value)));
1632 // Update the font size summary text.
1633 fontSizePreference.setSummary(sharedPreferences.getString("font_size", getString(R.string.font_size_default_value)) + "%");
1636 case "open_intents_in_new_tab":
1638 if (sharedPreferences.getBoolean("open_intents_in_new_tab", true)) {
1640 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_dark);
1642 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_light);
1646 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_dark);
1648 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_light);
1653 case "swipe_to_refresh":
1655 if (sharedPreferences.getBoolean("swipe_to_refresh", true)) {
1657 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_dark);
1659 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_light);
1663 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_dark);
1665 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_light);
1670 case "scroll_app_bar":
1672 if (sharedPreferences.getBoolean("scroll_app_bar", true)) {
1674 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_dark);
1676 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_light);
1680 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_dark);
1682 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_light);
1687 case "display_additional_app_bar_icons":
1689 if (sharedPreferences.getBoolean("display_additional_app_bar_icons", false)) {
1691 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_dark);
1693 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_light);
1697 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_dark);
1699 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_light);
1704 case "download_with_external_app":
1706 if (sharedPreferences.getBoolean("download_with_external_app", false)) {
1708 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_enabled_dark);
1710 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_enabled_light);
1714 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_disabled_dark);
1716 downloadWithExternalAppPreference.setIcon(R.drawable.open_with_external_app_disabled_light);
1723 if (sharedPreferences.getBoolean("dark_theme", false)) {
1724 darkThemePreference.setIcon(R.drawable.theme_dark);
1726 darkThemePreference.setIcon(R.drawable.theme_light);
1729 // Create an intent to restart Privacy Browser.
1730 Intent changeThemeRestartIntent = getActivity().getParentActivityIntent();
1732 // Assert that the intent is not null to remove the lint error below.
1733 assert changeThemeRestartIntent != null;
1735 // `Intent.FLAG_ACTIVITY_CLEAR_TASK` removes all activities from the stack. It requires `Intent.FLAG_ACTIVITY_NEW_TASK`.
1736 changeThemeRestartIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
1738 // Create a handler to restart the activity.
1739 Handler changeThemeRestartHandler = new Handler();
1741 // Create a runnable to restart the activity.
1742 Runnable changeThemeRestartRunnable = () -> {
1743 // Restart the activity.
1744 startActivity(changeThemeRestartIntent);
1746 // Kill this instance of Privacy Browser. Otherwise, the app exhibits sporadic behavior after the restart.
1750 // Restart the activity after 150 milliseconds, so that the app has enough time to save the change to the preference.
1751 changeThemeRestartHandler.postDelayed(changeThemeRestartRunnable, 150);
1755 // Store the current night mode status.
1756 boolean currentNightModeBoolean = sharedPreferences.getBoolean("night_mode", false);
1757 boolean currentJavaScriptBoolean = sharedPreferences.getBoolean("javascript", false);
1760 if (currentNightModeBoolean) {
1762 nightModePreference.setIcon(R.drawable.night_mode_enabled_dark);
1764 nightModePreference.setIcon(R.drawable.night_mode_enabled_light);
1768 nightModePreference.setIcon(R.drawable.night_mode_disabled_dark);
1770 nightModePreference.setIcon(R.drawable.night_mode_disabled_light);
1774 // Update the status of `javaScriptPreference` and `domStoragePreference`.
1775 javaScriptPreference.setEnabled(!currentNightModeBoolean);
1776 domStoragePreference.setEnabled(currentNightModeBoolean || currentJavaScriptBoolean);
1778 // Update the `javaScriptPreference` icon.
1779 if (currentNightModeBoolean || currentJavaScriptBoolean) {
1780 javaScriptPreference.setIcon(R.drawable.javascript_enabled);
1782 javaScriptPreference.setIcon(R.drawable.privacy_mode);
1785 // Update the DOM storage preference icon.
1786 if (currentNightModeBoolean || currentJavaScriptBoolean) { // The preference is enabled.
1787 if (sharedPreferences.getBoolean("dom_storage", false)) { // DOM storage is enabled.
1788 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
1789 } else { // DOM storage is disabled.
1791 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_dark);
1793 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_light);
1796 } else { // The preference is disabled. The icon should be ghosted.
1798 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_dark);
1800 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_light);
1805 case "wide_viewport":
1807 if (sharedPreferences.getBoolean("wide_viewport", true)) {
1809 wideViewportPreference.setIcon(R.drawable.wide_viewport_enabled_dark);
1811 wideViewportPreference.setIcon(R.drawable.wide_viewport_enabled_light);
1815 wideViewportPreference.setIcon(R.drawable.wide_viewport_disabled_dark);
1817 wideViewportPreference.setIcon(R.drawable.wide_viewport_disabled_light);
1822 case "display_webpage_images":
1824 if (sharedPreferences.getBoolean("display_webpage_images", true)) {
1826 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_dark);
1828 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_light);
1832 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_dark);
1834 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_light);
1841 // Register the listener.
1842 savedPreferences.registerOnSharedPreferenceChangeListener(preferencesListener);
1845 // 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.
1847 public void onPause() {
1849 savedPreferences.unregisterOnSharedPreferenceChangeListener(preferencesListener);
1853 public void onResume() {
1855 savedPreferences.registerOnSharedPreferenceChangeListener(preferencesListener);