2 * Copyright © 2016-2022 Soren Stoutner <soren@stoutner.com>.
4 * This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
6 * Privacy Browser Android 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 Android 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 Android. 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.content.res.Configuration;
28 import android.content.res.Resources;
29 import android.os.Build;
30 import android.os.Bundle;
31 import android.os.Handler;
32 import android.os.Looper;
33 import android.view.LayoutInflater;
34 import android.view.View;
35 import android.webkit.WebView;
36 import android.widget.ArrayAdapter;
38 import androidx.appcompat.app.AppCompatDelegate;
39 import androidx.preference.Preference;
40 import androidx.preference.PreferenceCategory;
41 import androidx.preference.PreferenceFragmentCompat;
43 import com.stoutner.privacybrowser.R;
44 import com.stoutner.privacybrowser.activities.MainWebViewActivity;
45 import com.stoutner.privacybrowser.helpers.ProxyHelper;
47 import java.util.Objects;
49 public class SettingsFragment extends PreferenceFragmentCompat {
50 // Declare the class variables.
51 private String defaultUserAgent;
52 private ArrayAdapter<CharSequence> userAgentNamesArray;
53 private String[] translatedUserAgentNamesArray;
54 private String[] userAgentDataArray;
55 private String[] appThemeEntriesStringArray;
56 private String[] appThemeEntryValuesStringArray;
57 private String[] webViewThemeEntriesStringArray;
58 private String[] webViewThemeEntryValuesStringArray;
59 private SharedPreferences.OnSharedPreferenceChangeListener sharedPreferenceChangeListener;
61 // Declare the class views.
62 private Preference javaScriptPreference;
63 private Preference cookiesPreference;
64 private Preference domStoragePreference;
65 private Preference formDataPreference; // The form data preference can be removed once the minimum API >= 26.
66 private Preference userAgentPreference;
67 private Preference customUserAgentPreference;
68 private Preference xRequestedWithHeaderPreference;
69 private Preference incognitoModePreference;
70 private Preference allowScreenshotsPreference;
71 private Preference easyListPreference;
72 private Preference easyPrivacyPreference;
73 private Preference fanboyAnnoyanceListPreference;
74 private Preference fanboySocialBlockingListPreference;
75 private Preference ultraListPreference;
76 private Preference ultraPrivacyPreference;
77 private Preference blockAllThirdPartyRequestsPreference;
78 private Preference trackingQueriesPreference;
79 private Preference ampRedirectsPreference;
80 private Preference searchPreference;
81 private Preference searchCustomURLPreference;
82 private Preference proxyPreference;
83 private Preference proxyCustomUrlPreference;
84 private Preference fullScreenBrowsingModePreference;
85 private Preference hideAppBarPreference;
86 private Preference clearEverythingPreference;
87 private Preference clearCookiesPreference;
88 private Preference clearDomStoragePreference;
89 private Preference clearFormDataPreference; // The clear form data preference can be removed once the minimum API >= 26.
90 private Preference clearLogcatPreference;
91 private Preference clearCachePreference;
92 private Preference homepagePreference;
93 private Preference fontSizePreference;
94 private Preference openIntentsInNewTabPreference;
95 private Preference swipeToRefreshPreference;
96 private Preference downloadWithExternalAppPreference;
97 private Preference scrollAppBarPreference;
98 private Preference bottomAppBarPreference;
99 private Preference displayAdditionalAppBarIconsPreference;
100 private Preference appThemePreference;
101 private Preference webViewThemePreference;
102 private Preference wideViewportPreference;
103 private Preference displayWebpageImagesPreference;
106 public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
107 // Load the preferences from the XML file.
108 setPreferencesFromResource(R.xml.preferences, rootKey);
110 // Get a handle for the activity.
111 Activity activity = getActivity();
113 // Remove the lint warning below that `getApplicationContext()` might produce a null pointer exception.
114 assert activity != null;
116 // Get a handle for the resources.
117 Resources resources = getResources();
119 // Get a handle for the shared preferences.
120 SharedPreferences sharedPreferences = getPreferenceScreen().getSharedPreferences();
122 // Remove the incorrect warning below that the shared preferences might be null.
123 assert sharedPreferences != null;
125 // Get handles for the preferences.
126 javaScriptPreference = findPreference("javascript");
127 cookiesPreference = findPreference(getString(R.string.cookies_key));
128 domStoragePreference = findPreference("dom_storage");
129 formDataPreference = findPreference("save_form_data"); // The form data preference can be removed once the minimum API >= 26.
130 userAgentPreference = findPreference(getString(R.string.user_agent_key));
131 customUserAgentPreference = findPreference("custom_user_agent");
132 xRequestedWithHeaderPreference = findPreference(getString(R.string.x_requested_with_header_key));
133 incognitoModePreference = findPreference("incognito_mode");
134 allowScreenshotsPreference = findPreference(getString(R.string.allow_screenshots_key));
135 easyListPreference = findPreference("easylist");
136 easyPrivacyPreference = findPreference("easyprivacy");
137 fanboyAnnoyanceListPreference = findPreference("fanboys_annoyance_list");
138 fanboySocialBlockingListPreference = findPreference("fanboys_social_blocking_list");
139 ultraListPreference = findPreference("ultralist");
140 ultraPrivacyPreference = findPreference("ultraprivacy");
141 blockAllThirdPartyRequestsPreference = findPreference("block_all_third_party_requests");
142 trackingQueriesPreference = findPreference(getString(R.string.tracking_queries_key));
143 ampRedirectsPreference = findPreference(getString(R.string.amp_redirects_key));
144 searchPreference = findPreference("search");
145 searchCustomURLPreference = findPreference("search_custom_url");
146 proxyPreference = findPreference("proxy");
147 proxyCustomUrlPreference = findPreference(getString(R.string.proxy_custom_url_key));
148 fullScreenBrowsingModePreference = findPreference("full_screen_browsing_mode");
149 hideAppBarPreference = findPreference("hide_app_bar");
150 clearEverythingPreference = findPreference("clear_everything");
151 clearCookiesPreference = findPreference("clear_cookies");
152 clearDomStoragePreference = findPreference("clear_dom_storage");
153 clearFormDataPreference = findPreference("clear_form_data"); // The clear form data preference can be removed once the minimum API >= 26.
154 clearLogcatPreference = findPreference(getString(R.string.clear_logcat_key));
155 clearCachePreference = findPreference("clear_cache");
156 homepagePreference = findPreference("homepage");
157 fontSizePreference = findPreference(getString(R.string.font_size_key));
158 openIntentsInNewTabPreference = findPreference("open_intents_in_new_tab");
159 swipeToRefreshPreference = findPreference(getString(R.string.swipe_to_refresh_key));
160 downloadWithExternalAppPreference = findPreference(getString(R.string.download_with_external_app_key));
161 scrollAppBarPreference = findPreference(getString(R.string.scroll_app_bar_key));
162 bottomAppBarPreference = findPreference(getString(R.string.bottom_app_bar_key));
163 displayAdditionalAppBarIconsPreference = findPreference(getString(R.string.display_additional_app_bar_icons_key));
164 appThemePreference = findPreference("app_theme");
165 webViewThemePreference = findPreference(getString(R.string.webview_theme_key));
166 wideViewportPreference = findPreference(getString(R.string.wide_viewport_key));
167 displayWebpageImagesPreference = findPreference(getString(R.string.display_webpage_images_key));
169 // Remove the lint warnings below that the preferences might be null.
170 assert javaScriptPreference != null;
171 assert cookiesPreference != null;
172 assert domStoragePreference != null;
173 assert formDataPreference != null;
174 assert userAgentPreference != null;
175 assert customUserAgentPreference != null;
176 assert xRequestedWithHeaderPreference != null;
177 assert incognitoModePreference != null;
178 assert allowScreenshotsPreference != null;
179 assert easyListPreference != null;
180 assert easyPrivacyPreference != null;
181 assert fanboyAnnoyanceListPreference != null;
182 assert fanboySocialBlockingListPreference != null;
183 assert ultraListPreference != null;
184 assert ultraPrivacyPreference != null;
185 assert blockAllThirdPartyRequestsPreference != null;
186 assert trackingQueriesPreference != null;
187 assert ampRedirectsPreference != null;
188 assert searchPreference != null;
189 assert searchCustomURLPreference != null;
190 assert proxyPreference != null;
191 assert proxyCustomUrlPreference != null;
192 assert fullScreenBrowsingModePreference != null;
193 assert hideAppBarPreference != null;
194 assert clearEverythingPreference != null;
195 assert clearCookiesPreference != null;
196 assert clearDomStoragePreference != null;
197 assert clearFormDataPreference != null;
198 assert clearLogcatPreference != null;
199 assert clearCachePreference != null;
200 assert homepagePreference != null;
201 assert fontSizePreference != null;
202 assert openIntentsInNewTabPreference != null;
203 assert swipeToRefreshPreference != null;
204 assert downloadWithExternalAppPreference != null;
205 assert scrollAppBarPreference != null;
206 assert bottomAppBarPreference != null;
207 assert displayAdditionalAppBarIconsPreference != null;
208 assert appThemePreference != null;
209 assert webViewThemePreference != null;
210 assert wideViewportPreference != null;
211 assert displayWebpageImagesPreference != null;
213 // Set the preference dependencies.
214 hideAppBarPreference.setDependency("full_screen_browsing_mode");
215 domStoragePreference.setDependency("javascript");
217 // Get strings from the preferences.
218 String userAgentName = sharedPreferences.getString(getString(R.string.user_agent_key), getString(R.string.user_agent_default_value));
219 String searchString = sharedPreferences.getString("search", getString(R.string.search_default_value));
220 String proxyString = sharedPreferences.getString("proxy", getString(R.string.proxy_default_value));
222 // Get booleans that are used in multiple places from the preferences.
223 boolean javaScriptEnabled = sharedPreferences.getBoolean("javascript", false);
224 boolean fanboyAnnoyanceListEnabled = sharedPreferences.getBoolean("fanboys_annoyance_list", true);
225 boolean fanboySocialBlockingEnabled = sharedPreferences.getBoolean("fanboys_social_blocking_list", true);
226 boolean fullScreenBrowsingMode = sharedPreferences.getBoolean("full_screen_browsing_mode", false);
227 boolean clearEverything = sharedPreferences.getBoolean("clear_everything", true);
229 // Remove the form data preferences if the API is >= 26 as they no longer do anything.
230 if (Build.VERSION.SDK_INT >= 26) {
231 // Get handles for the categories.
232 PreferenceCategory privacyCategory = findPreference("privacy");
233 PreferenceCategory clearAndExitCategory = findPreference("clear_and_exit");
235 // Remove the incorrect lint warnings below that the preference categories might be null.
236 assert privacyCategory != null;
237 assert clearAndExitCategory != null;
239 // Remove the form data preferences.
240 privacyCategory.removePreference(formDataPreference);
241 clearAndExitCategory.removePreference(clearFormDataPreference);
244 // Only enable Fanboy's social blocking list preference if Fanboy's annoyance list is disabled.
245 fanboySocialBlockingListPreference.setEnabled(!fanboyAnnoyanceListEnabled);
248 // Inflate a WebView to get the default user agent.
249 LayoutInflater inflater = getActivity().getLayoutInflater();
251 // `@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.
252 @SuppressLint("InflateParams") View bareWebViewLayout = inflater.inflate(R.layout.bare_webview, null, false);
254 // Get a handle for a bare WebView.
255 WebView bareWebView = bareWebViewLayout.findViewById(R.id.bare_webview);
257 // Get the default user agent.
258 defaultUserAgent = bareWebView.getSettings().getUserAgentString();
260 // Get the user agent arrays.
261 userAgentNamesArray = ArrayAdapter.createFromResource(requireContext(), R.array.user_agent_names, R.layout.spinner_item);
262 translatedUserAgentNamesArray = resources.getStringArray(R.array.translated_user_agent_names);
263 userAgentDataArray = resources.getStringArray(R.array.user_agent_data);
265 // Get the array position of the user agent name.
266 int userAgentArrayPosition = userAgentNamesArray.getPosition(userAgentName);
268 // Populate the user agent summary.
269 switch (userAgentArrayPosition) {
270 case MainWebViewActivity.UNRECOGNIZED_USER_AGENT: // The user agent name is not on the canonical list.
271 // 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.
272 userAgentPreference.setSummary(userAgentName);
275 case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
276 // Get the user agent text from the webview (which changes based on the version of Android and WebView installed).
277 userAgentPreference.setSummary(translatedUserAgentNamesArray[userAgentArrayPosition] + ":\n" + defaultUserAgent);
280 case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
281 // Set the summary text.
282 userAgentPreference.setSummary(R.string.custom_user_agent);
286 // Get the user agent summary from the user agent data array.
287 userAgentPreference.setSummary(translatedUserAgentNamesArray[userAgentArrayPosition] + ":\n" + userAgentDataArray[userAgentArrayPosition]);
290 // Set the summary text for the custom user agent preference.
291 customUserAgentPreference.setSummary(sharedPreferences.getString(getString(R.string.custom_user_agent_key), getString(R.string.custom_user_agent_default_value)));
293 // Only enable the custom user agent preference if the user agent is set to `Custom`.
294 customUserAgentPreference.setEnabled(Objects.equals(userAgentPreference.getSummary(), getString(R.string.custom_user_agent)));
296 // Set the search URL as the summary text for the search preference when the preference screen is loaded.
297 if (searchString.equals("Custom URL")) {
298 // Use R.string.custom_url, which will be translated, instead of the array value, which will not.
299 searchPreference.setSummary(R.string.custom_url);
301 // Set the array value as the summary text.
302 searchPreference.setSummary(searchString);
305 // Set the summary text for the search custom URL (the default is `""`).
306 searchCustomURLPreference.setSummary(sharedPreferences.getString("search_custom_url", getString(R.string.search_custom_url_default_value)));
308 // Only enable the search custom URL preference if the search is set to `Custom URL`.
309 searchCustomURLPreference.setEnabled(searchString.equals("Custom URL"));
312 // Set the summary text for the proxy preference when the preference screen is loaded.
313 switch (proxyString) {
314 case ProxyHelper.NONE:
315 proxyPreference.setSummary(getString(R.string.no_proxy_enabled));
318 case ProxyHelper.TOR:
319 proxyPreference.setSummary(getString(R.string.tor_enabled));
322 case ProxyHelper.I2P:
323 proxyPreference.setSummary(getString(R.string.i2p_enabled));
326 case ProxyHelper.CUSTOM:
327 proxyPreference.setSummary(getString(R.string.custom_proxy));
331 // Set the summary text for the custom proxy URL.
332 proxyCustomUrlPreference.setSummary(sharedPreferences.getString(getString(R.string.proxy_custom_url_key), getString(R.string.proxy_custom_url_default_value)));
334 // Only enable the custom proxy URL if a custom proxy is selected.
335 proxyCustomUrlPreference.setEnabled(proxyString.equals(ProxyHelper.CUSTOM));
338 // Set the status of the clear and exit preferences.
339 clearCookiesPreference.setEnabled(!clearEverything);
340 clearDomStoragePreference.setEnabled(!clearEverything);
341 clearFormDataPreference.setEnabled(!clearEverything); // The form data line can be removed once the minimum API is >= 26.
342 clearLogcatPreference.setEnabled(!clearEverything);
343 clearCachePreference.setEnabled(!clearEverything);
346 // Set the homepage URL as the summary text for the homepage preference.
347 homepagePreference.setSummary(sharedPreferences.getString("homepage", getString(R.string.homepage_default_value)));
350 // Set the font size as the summary text for the preference.
351 fontSizePreference.setSummary(sharedPreferences.getString(getString(R.string.font_size_key), getString(R.string.font_size_default_value)) + "%");
354 // Get the app theme string arrays.
355 appThemeEntriesStringArray = resources.getStringArray(R.array.app_theme_entries);
356 appThemeEntryValuesStringArray = resources.getStringArray(R.array.app_theme_entry_values);
358 // Get the current app theme.
359 String currentAppTheme = sharedPreferences.getString("app_theme", getString(R.string.app_theme_default_value));
361 // Declare an app theme entry number.
362 int appThemeEntryNumber;
364 // Get the app theme entry number that matches the current app theme. A switch statement cannot be used because the theme entry values string array is not a compile time constant.
365 if (currentAppTheme.equals(appThemeEntryValuesStringArray[1])) { // The light theme is selected.
366 // Store the app theme entry number.
367 appThemeEntryNumber = 1;
368 } else if (currentAppTheme.equals(appThemeEntryValuesStringArray[2])) { // The dark theme is selected.
369 // Store the app theme entry number.
370 appThemeEntryNumber = 2;
371 } else { // The system default theme is selected.
372 // Store the app theme entry number.
373 appThemeEntryNumber = 0;
376 // Set the current theme as the summary text for the preference.
377 appThemePreference.setSummary(appThemeEntriesStringArray[appThemeEntryNumber]);
379 // Disable the WebView theme preference if the API >= 33 and the app theme is set to light.
380 webViewThemePreference.setEnabled((Build.VERSION.SDK_INT < 33) || (appThemeEntryNumber != 1));
383 // Get the WebView theme string arrays.
384 webViewThemeEntriesStringArray = resources.getStringArray(R.array.webview_theme_entries);
385 webViewThemeEntryValuesStringArray = resources.getStringArray(R.array.webview_theme_entry_values);
387 // Get the current WebView theme.
388 String currentWebViewTheme = sharedPreferences.getString(getString(R.string.webview_theme_key), getString(R.string.webview_theme_default_value));
390 // Define a WebView theme entry number.
391 int webViewThemeEntryNumber;
393 // Get the WebView theme entry number that matches the current WebView theme. A switch statement cannot be used because the WebView theme entry values string array is not a compile time constant.
394 if (currentWebViewTheme.equals(webViewThemeEntryValuesStringArray[1])) { // The light theme is selected.
395 // Store the WebView theme entry number.
396 webViewThemeEntryNumber = 1;
397 } else if (currentWebViewTheme.equals(webViewThemeEntryValuesStringArray[2])) { // The dark theme is selected.
398 // Store the WebView theme entry number.
399 webViewThemeEntryNumber = 2;
400 } else { // The system default theme is selected.
401 // Store the WebView theme entry number.
402 webViewThemeEntryNumber = 0;
405 // Set the current theme as the summary text for the preference.
406 webViewThemePreference.setSummary(webViewThemeEntriesStringArray[webViewThemeEntryNumber]);
409 // Set the JavaScript icon.
410 if (javaScriptEnabled) {
411 javaScriptPreference.setIcon(R.drawable.javascript_enabled);
413 javaScriptPreference.setIcon(R.drawable.privacy_mode);
416 // Set the cookies icon.
417 if (sharedPreferences.getBoolean(getString(R.string.cookies_key), false)) {
418 cookiesPreference.setIcon(R.drawable.cookies_enabled);
420 cookiesPreference.setIcon(R.drawable.cookies_disabled);
423 // Set the DOM storage icon.
424 if (javaScriptEnabled) { // The preference is enabled.
425 if (sharedPreferences.getBoolean("dom_storage", false)) { // DOM storage is enabled.
426 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
427 } else { // DOM storage is disabled.
428 domStoragePreference.setIcon(R.drawable.dom_storage_disabled);
430 } else { // The preference is disabled. The icon should be ghosted.
431 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted);
434 // Set the save form data icon if API < 26. Save form data has no effect on API >= 26.
435 if (Build.VERSION.SDK_INT < 26) {
436 if (sharedPreferences.getBoolean("save_form_data", false))
437 formDataPreference.setIcon(R.drawable.form_data_enabled);
439 formDataPreference.setIcon(R.drawable.form_data_disabled);
442 // Set the custom user agent icon.
443 if (customUserAgentPreference.isEnabled())
444 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled);
446 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted);
448 // Set the X-Requested With header icon.
449 if (sharedPreferences.getBoolean(getString(R.string.x_requested_with_header_key), true))
450 xRequestedWithHeaderPreference.setIcon(R.drawable.x_requested_with_header_enabled);
452 xRequestedWithHeaderPreference.setIcon(R.drawable.x_requested_with_header_disabled);
454 // Set the incognito mode icon.
455 if (sharedPreferences.getBoolean("incognito_mode", false))
456 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled);
458 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled);
460 // Set the allow screenshots icon.
461 if (sharedPreferences.getBoolean(getString(R.string.allow_screenshots_key), false))
462 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled);
464 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled);
466 // Set the EasyList icon.
467 if (sharedPreferences.getBoolean("easylist", true))
468 easyListPreference.setIcon(R.drawable.block_ads_enabled);
470 easyListPreference.setIcon(R.drawable.block_ads_disabled);
472 // Set the EasyPrivacy icon.
473 if (sharedPreferences.getBoolean("easyprivacy", true))
474 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled);
476 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled);
478 // Set the Fanboy lists icons.
479 if (fanboyAnnoyanceListEnabled) {
480 // Set the Fanboy annoyance list icon.
481 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled);
483 // Set the Fanboy social blocking list icon.
484 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted);
486 // Set the Fanboy annoyance list icon.
487 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled);
489 // Set the Fanboy social blocking list icon.
490 if (fanboySocialBlockingEnabled) {
491 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled);
493 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled);
497 // Set the UltraList icon.
498 if (sharedPreferences.getBoolean("ultralist", true)){
499 ultraListPreference.setIcon(R.drawable.block_ads_enabled);
501 ultraListPreference.setIcon(R.drawable.block_ads_disabled);
504 // Set the UltraPrivacy icon.
505 if (sharedPreferences.getBoolean("ultraprivacy", true)) {
506 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled);
508 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled);
511 // Set the block all third-party requests icon.
512 if (sharedPreferences.getBoolean("block_all_third_party_requests", false)) {
513 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled);
515 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled);
518 // Set the Tracking Queries icon.
519 if (sharedPreferences.getBoolean(getString(R.string.tracking_queries_key), true)) {
520 trackingQueriesPreference.setIcon(R.drawable.modify_url_enabled);
522 trackingQueriesPreference.setIcon(R.drawable.modify_url_disabled);
525 // Set the AMP Redirects icon.
526 if (sharedPreferences.getBoolean(getString(R.string.amp_redirects_key), true)) {
527 ampRedirectsPreference.setIcon(R.drawable.modify_url_enabled);
529 ampRedirectsPreference.setIcon(R.drawable.modify_url_disabled);
532 // Set the search custom URL icon.
533 if (searchCustomURLPreference.isEnabled()) {
534 searchCustomURLPreference.setIcon(R.drawable.search_custom_enabled);
536 searchCustomURLPreference.setIcon(R.drawable.search_custom_ghosted);
539 // Set the Proxy icons according to the theme and status.
540 if (proxyString.equals(ProxyHelper.NONE)) { // Proxying is disabled.
541 // Set the main proxy icon to be disabled.
542 proxyPreference.setIcon(R.drawable.proxy_disabled);
544 // Set the custom proxy URL icon to be ghosted.
545 proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted);
546 } else { // Proxying is enabled.
547 // Set the main proxy icon to be enabled.
548 proxyPreference.setIcon(R.drawable.proxy_enabled);
550 // Set the custom proxy URL icon according to its status.
551 if (proxyCustomUrlPreference.isEnabled()) {
552 proxyCustomUrlPreference.setIcon(R.drawable.proxy_enabled);
554 proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted);
558 // Set the full screen browsing mode icons.
559 if (fullScreenBrowsingMode) { // Full screen browsing mode is enabled.
560 // Set the full screen browsing mode preference icon.
561 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled);
563 // Set the hide app bar icon.
564 if (sharedPreferences.getBoolean("hide_app_bar", true)) {
565 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled);
567 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled);
569 } else { // Full screen browsing mode is disabled.
571 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled);
572 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted);
575 // Set the clear everything preference icon.
576 if (clearEverything) {
577 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled);
579 clearEverythingPreference.setIcon(R.drawable.clear_everything_disabled);
582 // Set the clear cookies preference icon.
583 if (clearEverything || sharedPreferences.getBoolean("clear_cookies", true)) {
584 clearCookiesPreference.setIcon(R.drawable.clear_cookies_enabled);
586 clearCookiesPreference.setIcon(R.drawable.clear_cookies_disabled);
589 // Set the clear DOM storage preference icon.
590 if (clearEverything || sharedPreferences.getBoolean("clear_dom_storage", true)) {
591 clearDomStoragePreference.setIcon(R.drawable.clear_dom_storage_enabled);
593 clearDomStoragePreference.setIcon(R.drawable.clear_dom_storage_disabled);
596 // Set the clear form data preference icon if the API < 26. It has no effect on newer versions of Android.
597 if (Build.VERSION.SDK_INT < 26) {
598 if (clearEverything || sharedPreferences.getBoolean("clear_form_data", true)) {
599 clearFormDataPreference.setIcon(R.drawable.clear_form_data_enabled);
601 clearFormDataPreference.setIcon(R.drawable.clear_form_data_disabled);
605 // Set the clear logcat preference icon.
606 if (clearEverything || sharedPreferences.getBoolean(getString(R.string.clear_logcat_key), true)) {
607 clearLogcatPreference.setIcon(R.drawable.clear_logcat_enabled);
609 clearLogcatPreference.setIcon(R.drawable.clear_logcat_disabled);
612 // Set the clear cache preference icon.
613 if (clearEverything || sharedPreferences.getBoolean("clear_cache", true)) {
614 clearCachePreference.setIcon(R.drawable.clear_cache_enabled);
616 clearCachePreference.setIcon(R.drawable.clear_cache_disabled);
619 // Set the open intents in new tab preference icon.
620 if (sharedPreferences.getBoolean("open_intents_in_new_tab", true)) {
621 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled);
623 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled);
626 // Set the swipe to refresh preference icon.
627 if (sharedPreferences.getBoolean(getString(R.string.swipe_to_refresh_key), true))
628 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled);
630 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled);
632 // Set the download with external app preference icon.
633 if (sharedPreferences.getBoolean(getString(R.string.download_with_external_app_key), false))
634 downloadWithExternalAppPreference.setIcon(R.drawable.download_with_external_app_enabled);
636 downloadWithExternalAppPreference.setIcon(R.drawable.download_with_external_app_disabled);
638 // Set the scroll app bar preference icon.
639 if (sharedPreferences.getBoolean(getString(R.string.scroll_app_bar_key), true))
640 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled);
642 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled);
644 // Set the bottom app bar preference icon.
645 if (sharedPreferences.getBoolean(getString(R.string.bottom_app_bar_key), false))
646 bottomAppBarPreference.setIcon(R.drawable.bottom_app_bar_enabled);
648 bottomAppBarPreference.setIcon(R.drawable.bottom_app_bar_disabled);
650 // Set the display additional app bar icons preference icon.
651 if (sharedPreferences.getBoolean(getString(R.string.display_additional_app_bar_icons_key), false))
652 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled);
654 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled);
656 // Set the WebView theme preference icon.
657 if (webViewThemePreference.isEnabled()) { // The WebView theme preference is enabled.
658 switch (webViewThemeEntryNumber) {
659 case 0: // The system default WebView theme is selected.
660 // Get the current theme status.
661 int currentThemeStatus = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
663 // Set the icon according to the app theme.
664 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO)
665 webViewThemePreference.setIcon(R.drawable.webview_light_theme);
667 webViewThemePreference.setIcon(R.drawable.webview_dark_theme);
670 case 1: // The light WebView theme is selected.
672 webViewThemePreference.setIcon(R.drawable.webview_light_theme);
675 case 2: // The dark WebView theme is selected.
677 webViewThemePreference.setIcon(R.drawable.webview_dark_theme);
680 } else { // The WebView theme preference is disabled.
681 webViewThemePreference.setIcon(R.drawable.webview_theme_ghosted);
684 // Set the wide viewport preference icon.
685 if (sharedPreferences.getBoolean(getString(R.string.wide_viewport_key), true)) {
686 wideViewportPreference.setIcon(R.drawable.wide_viewport_enabled);
688 wideViewportPreference.setIcon(R.drawable.wide_viewport_disabled);
691 // Set the display webpage images preference icon.
692 if (sharedPreferences.getBoolean(getString(R.string.display_webpage_images_key), true)) {
693 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled);
695 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled);
699 // The listener should be unregistered when the app is paused.
701 public void onPause() {
702 // Run the default commands.
705 // Get a handle for the shared preferences.
706 SharedPreferences sharedPreferences = getPreferenceScreen().getSharedPreferences();
708 // Remove the incorrect lint warning below that the shared preferences might be null.
709 assert sharedPreferences != null;
711 // Unregister the shared preference listener.
712 sharedPreferences.unregisterOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
715 // The listener should be re-registered when the app is resumed.
717 public void onResume() {
718 // Run the default commands.
721 // Get a new shared preference change listener.
722 sharedPreferenceChangeListener = getSharedPreferenceChangeListener(requireContext());
724 // Get a handle for the shared preferences.
725 SharedPreferences sharedPreferences = getPreferenceScreen().getSharedPreferences();
727 // Remove the incorrect lint warning below that the shared preferences might be null.
728 assert sharedPreferences != null;
730 // Re-register the shared preference listener.
731 sharedPreferences.registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
734 // The context must be passed to the shared preference change listener or else any calls to the system `getString()` will crash if the app has been restarted.
735 // This can be removed at some future point, perhaps after the switch to PreferenceScreenCompat. It isn't an issue in Privacy Cell.
736 private SharedPreferences.OnSharedPreferenceChangeListener getSharedPreferenceChangeListener(Context context) {
737 // Return the shared preference change listener.
738 return (SharedPreferences sharedPreferences, String key) -> {
741 // Update the icons and the DOM storage preference status.
742 if (sharedPreferences.getBoolean("javascript", false)) { // The JavaScript preference is enabled.
743 // Update the icon for the JavaScript preference.
744 javaScriptPreference.setIcon(R.drawable.javascript_enabled);
746 // Update the status of the DOM storage preference.
747 domStoragePreference.setEnabled(true);
749 // Update the icon for the DOM storage preference.
750 if (sharedPreferences.getBoolean("dom_storage", false)) {
751 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
753 domStoragePreference.setIcon(R.drawable.dom_storage_disabled);
755 } else { // The JavaScript preference is disabled.
756 // Update the icon for the JavaScript preference.
757 javaScriptPreference.setIcon(R.drawable.privacy_mode);
759 // Update the status of the DOM storage preference.
760 domStoragePreference.setEnabled(false);
762 // Set the icon for DOM storage preference to be ghosted.
763 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted);
769 if (sharedPreferences.getBoolean(context.getString(R.string.cookies_key), false)) {
770 cookiesPreference.setIcon(R.drawable.cookies_enabled);
772 cookiesPreference.setIcon(R.drawable.cookies_disabled);
778 if (sharedPreferences.getBoolean("dom_storage", false)) {
779 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
781 domStoragePreference.setIcon(R.drawable.dom_storage_disabled);
785 // Save form data can be removed once the minimum API >= 26.
786 case "save_form_data":
788 if (sharedPreferences.getBoolean("save_form_data", false)) {
789 formDataPreference.setIcon(R.drawable.form_data_enabled);
791 formDataPreference.setIcon(R.drawable.form_data_disabled);
796 // Get the new user agent name.
797 String newUserAgentName = sharedPreferences.getString(context.getString(R.string.user_agent_key), context.getString(R.string.user_agent_default_value));
799 // Get the array position for the new user agent name.
800 int newUserAgentArrayPosition = userAgentNamesArray.getPosition(newUserAgentName);
802 // Get the translated new user agent name.
803 String translatedNewUserAgentName = translatedUserAgentNamesArray[newUserAgentArrayPosition];
805 // Populate the user agent summary.
806 switch (newUserAgentArrayPosition) {
807 case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
808 // Get the user agent text from the webview (which changes based on the version of Android and WebView installed).
809 userAgentPreference.setSummary(translatedNewUserAgentName + ":\n" + defaultUserAgent);
811 // Disable the custom user agent preference.
812 customUserAgentPreference.setEnabled(false);
814 // Set the custom user agent preference icon.
815 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted);
818 case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
819 // Set the summary text.
820 userAgentPreference.setSummary(R.string.custom_user_agent);
822 // Enable the custom user agent preference.
823 customUserAgentPreference.setEnabled(true);
825 // Set the custom user agent preference icon.
826 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled);
830 // Get the user agent summary from the user agent data array.
831 userAgentPreference.setSummary(translatedNewUserAgentName + ":\n" + userAgentDataArray[newUserAgentArrayPosition]);
833 // Disable the custom user agent preference.
834 customUserAgentPreference.setEnabled(false);
836 // Set the custom user agent preference icon.
837 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted);
841 case "custom_user_agent":
842 // Set the new custom user agent as the summary text for the preference.
843 customUserAgentPreference.setSummary(sharedPreferences.getString(context.getString(R.string.custom_user_agent_key), context.getString(R.string.custom_user_agent_default_value)));
846 case "x_requested_with_header":
848 if (sharedPreferences.getBoolean(context.getString(R.string.x_requested_with_header_key), true))
849 xRequestedWithHeaderPreference.setIcon(R.drawable.x_requested_with_header_enabled);
851 xRequestedWithHeaderPreference.setIcon(R.drawable.x_requested_with_header_disabled);
853 // Restart Privacy Browser.
854 restartPrivacyBrowser();
857 case "incognito_mode":
859 if (sharedPreferences.getBoolean("incognito_mode", false))
860 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled);
862 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled);
865 case "allow_screenshots":
867 if (sharedPreferences.getBoolean(context.getString(R.string.allow_screenshots_key), false))
868 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled);
870 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled);
872 // Restart Privacy Browser.
873 restartPrivacyBrowser();
878 if (sharedPreferences.getBoolean("easylist", true))
879 easyListPreference.setIcon(R.drawable.block_ads_enabled);
881 easyListPreference.setIcon(R.drawable.block_ads_disabled);
886 if (sharedPreferences.getBoolean("easyprivacy", true))
887 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled);
889 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled);
892 case "fanboys_annoyance_list":
893 boolean currentFanboyAnnoyanceList = sharedPreferences.getBoolean("fanboys_annoyance_list", true);
894 boolean currentFanboySocialBlockingList = sharedPreferences.getBoolean("fanboys_social_blocking_list", true);
896 // Update the Fanboy icons.
897 if (currentFanboyAnnoyanceList) { // Fanboy's annoyance list is enabled.
898 // Update the Fanboy's annoyance list icon.
899 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled);
901 // Update the Fanboy's social blocking list icon.
902 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted);
903 } else { // Fanboy's annoyance list is disabled.
904 // Update the Fanboy's annoyance list icon.
905 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled);
907 // Update the Fanboy's social blocking list icon.
908 if (currentFanboySocialBlockingList) {
909 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled);
911 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled);
915 // Only enable Fanboy's social blocking list preference if Fanboy's annoyance list preference is disabled.
916 fanboySocialBlockingListPreference.setEnabled(!currentFanboyAnnoyanceList);
919 case "fanboys_social_blocking_list":
921 if (sharedPreferences.getBoolean("fanboys_social_blocking_list", true)) {
922 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled);
924 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled);
930 if (sharedPreferences.getBoolean("ultralist", true)) {
931 ultraListPreference.setIcon(R.drawable.block_ads_enabled);
933 ultraListPreference.setIcon(R.drawable.block_ads_disabled);
939 if (sharedPreferences.getBoolean("ultraprivacy", true)) {
940 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled);
942 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled);
946 case "block_all_third_party_requests":
948 if (sharedPreferences.getBoolean("block_all_third_party_requests", false)) {
949 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled);
951 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled);
955 case "tracking_queries":
957 if (sharedPreferences.getBoolean(context.getString(R.string.tracking_queries_key), true)) {
958 trackingQueriesPreference.setIcon(R.drawable.modify_url_enabled);
960 trackingQueriesPreference.setIcon(R.drawable.modify_url_disabled);
964 case "amp_redirects":
966 if (sharedPreferences.getBoolean(context.getString(R.string.amp_redirects_key), true)) {
967 ampRedirectsPreference.setIcon(R.drawable.modify_url_enabled);
969 ampRedirectsPreference.setIcon(R.drawable.modify_url_disabled);
974 // Store the new search string.
975 String newSearchString = sharedPreferences.getString("search", context.getString(R.string.search_default_value));
977 // Update the search and search custom URL preferences.
978 if (newSearchString.equals("Custom URL")) { // `Custom URL` is selected.
979 // Set the summary text to `R.string.custom_url`, which is translated.
980 searchPreference.setSummary(R.string.custom_url);
982 // Enable the search custom URL preference.
983 searchCustomURLPreference.setEnabled(true);
985 // Set the search custom URL preference icon.
986 searchCustomURLPreference.setIcon(R.drawable.search_custom_enabled);
987 } else { // `Custom URL` is not selected.
988 // Set the summary text to `newSearchString`.
989 searchPreference.setSummary(newSearchString);
991 // Disable `searchCustomURLPreference`.
992 searchCustomURLPreference.setEnabled(false);
994 // Set the search custom URL preference icon.
995 searchCustomURLPreference.setIcon(R.drawable.search_custom_ghosted);
999 case "search_custom_url":
1000 // Set the new search custom URL as the summary text for the preference.
1001 searchCustomURLPreference.setSummary(sharedPreferences.getString("search_custom_url", context.getString(R.string.search_custom_url_default_value)));
1005 // Get current proxy string.
1006 String currentProxyString = sharedPreferences.getString("proxy", context.getString(R.string.proxy_default_value));
1008 // Update the summary text for the proxy preference.
1009 switch (currentProxyString) {
1010 case ProxyHelper.NONE:
1011 proxyPreference.setSummary(context.getString(R.string.no_proxy_enabled));
1014 case ProxyHelper.TOR:
1015 proxyPreference.setSummary(context.getString(R.string.tor_enabled));
1018 case ProxyHelper.I2P:
1019 proxyPreference.setSummary(context.getString(R.string.i2p_enabled));
1022 case ProxyHelper.CUSTOM:
1023 proxyPreference.setSummary(context.getString(R.string.custom_proxy));
1027 // Update the status of the custom URL preference.
1028 proxyCustomUrlPreference.setEnabled(currentProxyString.equals(ProxyHelper.CUSTOM));
1030 // Update the icons.
1031 if (currentProxyString.equals(ProxyHelper.NONE)) { // Proxying is disabled.
1032 // Set the main proxy icon to be disabled
1033 proxyPreference.setIcon(R.drawable.proxy_disabled);
1035 // Set the custom proxy URL icon to be ghosted.
1036 proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted);
1037 } else { // Proxying is enabled.
1038 // Set the main proxy icon to be enabled.
1039 proxyPreference.setIcon(R.drawable.proxy_enabled);
1041 /// Set the custom proxy URL icon according to its status.
1042 if (proxyCustomUrlPreference.isEnabled()) {
1043 proxyCustomUrlPreference.setIcon(R.drawable.proxy_enabled);
1045 proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted);
1050 case "proxy_custom_url":
1051 // Set the summary text for the proxy custom URL.
1052 proxyCustomUrlPreference.setSummary(sharedPreferences.getString(context.getString(R.string.proxy_custom_url_key), context.getString(R.string.proxy_custom_url_default_value)));
1055 case "full_screen_browsing_mode":
1056 if (sharedPreferences.getBoolean("full_screen_browsing_mode", false)) { // Full screen browsing is enabled.
1057 // Set the full screen browsing mode preference icon.
1058 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled);
1060 // Set the hide app bar preference icon.
1061 if (sharedPreferences.getBoolean("hide_app_bar", true)) {
1062 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled);
1064 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled);
1066 } else { // Full screen browsing is disabled.
1067 // Update the icons.
1068 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled);
1069 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted);
1073 case "hide_app_bar":
1075 if (sharedPreferences.getBoolean("hide_app_bar", true)) {
1076 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled);
1077 } else { // Hide app bar is disabled.
1078 // Set the icon according to the theme.
1079 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled);
1083 case "clear_everything":
1084 // Store the new clear everything status
1085 boolean newClearEverythingBoolean = sharedPreferences.getBoolean("clear_everything", true);
1087 // Update the status of the clear and exit preferences.
1088 clearCookiesPreference.setEnabled(!newClearEverythingBoolean);
1089 clearDomStoragePreference.setEnabled(!newClearEverythingBoolean);
1090 clearFormDataPreference.setEnabled(!newClearEverythingBoolean); // This line can be removed once the minimum API >= 26.
1091 clearLogcatPreference.setEnabled(!newClearEverythingBoolean);
1092 clearCachePreference.setEnabled(!newClearEverythingBoolean);
1094 // Update the clear everything preference icon.
1095 if (newClearEverythingBoolean) {
1096 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled);
1098 clearEverythingPreference.setIcon(R.drawable.clear_everything_disabled);
1101 // Update the clear cookies preference icon.
1102 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_cookies", true)) {
1103 clearCookiesPreference.setIcon(R.drawable.clear_cookies_enabled);
1105 clearCookiesPreference.setIcon(R.drawable.clear_cookies_disabled);
1108 // Update the clear dom storage preference icon.
1109 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_dom_storage", true)) {
1110 clearDomStoragePreference.setIcon(R.drawable.clear_dom_storage_enabled);
1112 clearDomStoragePreference.setIcon(R.drawable.clear_dom_storage_disabled);
1115 // Update the clear form data preference icon if the API < 26.
1116 if (Build.VERSION.SDK_INT < 26) {
1117 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_form_data", true)) {
1118 clearFormDataPreference.setIcon(R.drawable.clear_form_data_enabled);
1120 clearFormDataPreference.setIcon(R.drawable.clear_form_data_disabled);
1124 // Update the clear logcat preference icon.
1125 if (newClearEverythingBoolean || sharedPreferences.getBoolean(context.getString(R.string.clear_logcat_key), true)) {
1126 clearLogcatPreference.setIcon(R.drawable.clear_logcat_enabled);
1128 clearLogcatPreference.setIcon(R.drawable.clear_cache_disabled);
1131 // Update the clear cache preference icon.
1132 if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_cache", true)) {
1133 clearCachePreference.setIcon(R.drawable.clear_cache_enabled);
1135 clearCachePreference.setIcon(R.drawable.clear_cache_disabled);
1139 case "clear_cookies":
1141 if (sharedPreferences.getBoolean("clear_cookies", true)) {
1142 clearCookiesPreference.setIcon(R.drawable.clear_cookies_enabled);
1144 clearCookiesPreference.setIcon(R.drawable.clear_cookies_disabled);
1148 case "clear_dom_storage":
1150 if (sharedPreferences.getBoolean("clear_dom_storage", true)) {
1151 clearDomStoragePreference.setIcon(R.drawable.clear_dom_storage_enabled);
1153 clearDomStoragePreference.setIcon(R.drawable.clear_dom_storage_disabled);
1157 // This section can be removed once the minimum API >= 26.
1158 case "clear_form_data":
1160 if (sharedPreferences.getBoolean("clear_form_data", true)) {
1161 clearFormDataPreference.setIcon(R.drawable.clear_form_data_enabled);
1163 clearFormDataPreference.setIcon(R.drawable.clear_form_data_disabled);
1167 case "clear_logcat":
1169 if (sharedPreferences.getBoolean(context.getString(R.string.clear_logcat_key), true)) {
1170 clearLogcatPreference.setIcon(R.drawable.clear_logcat_enabled);
1172 clearLogcatPreference.setIcon(R.drawable.clear_logcat_disabled);
1178 if (sharedPreferences.getBoolean("clear_cache", true)) {
1179 clearCachePreference.setIcon(R.drawable.clear_cache_enabled);
1181 clearCachePreference.setIcon(R.drawable.clear_cache_disabled);
1186 // Set the new homepage URL as the summary text for the Homepage preference.
1187 homepagePreference.setSummary(sharedPreferences.getString("homepage", context.getString(R.string.homepage_default_value)));
1191 // Update the font size summary text.
1192 fontSizePreference.setSummary(sharedPreferences.getString(context.getString(R.string.font_size_key), context.getString(R.string.font_size_default_value)) + "%");
1195 case "open_intents_in_new_tab":
1197 if (sharedPreferences.getBoolean("open_intents_in_new_tab", true))
1198 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled);
1200 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled);
1203 case "swipe_to_refresh":
1205 if (sharedPreferences.getBoolean(context.getString(R.string.swipe_to_refresh_key), true))
1206 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled);
1208 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled);
1211 case "download_with_external_app":
1213 if (sharedPreferences.getBoolean(context.getString(R.string.download_with_external_app_key), false))
1214 downloadWithExternalAppPreference.setIcon(R.drawable.download_with_external_app_enabled);
1216 downloadWithExternalAppPreference.setIcon(R.drawable.download_with_external_app_disabled);
1219 case "scroll_app_bar":
1221 if (sharedPreferences.getBoolean(context.getString(R.string.scroll_app_bar_key), true))
1222 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled);
1224 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled);
1228 case "bottom_app_bar":
1230 if (sharedPreferences.getBoolean(context.getString(R.string.bottom_app_bar_key), false))
1231 bottomAppBarPreference.setIcon(R.drawable.bottom_app_bar_enabled);
1233 bottomAppBarPreference.setIcon(R.drawable.bottom_app_bar_disabled);
1235 // Restart Privacy Browser.
1236 restartPrivacyBrowser();
1239 case "display_additional_app_bar_icons":
1241 if (sharedPreferences.getBoolean(context.getString(R.string.display_additional_app_bar_icons_key), false))
1242 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled);
1244 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled);
1248 // Get the new theme.
1249 String newAppTheme = sharedPreferences.getString("app_theme", context.getString(R.string.app_theme_default_value));
1251 // Declare an app theme entry number.
1252 int appThemeEntryNumber;
1254 // Get the app theme entry number that matches the current app theme. A switch statement cannot be used because the theme entry values string array is not a compile time constant.
1255 if (newAppTheme.equals(appThemeEntryValuesStringArray[1])) { // The light theme is selected.
1256 // Store the app theme entry number.
1257 appThemeEntryNumber = 1;
1258 } else if (newAppTheme.equals(appThemeEntryValuesStringArray[2])) { // The dark theme is selected.
1259 // Store the app theme entry number.
1260 appThemeEntryNumber = 2;
1261 } else { // The system default theme is selected.
1262 // Store the app theme entry number.
1263 appThemeEntryNumber = 0;
1266 // Update the system according to the new theme. A switch statement cannot be used because the theme entry values string array is not a compile-time constant.
1267 switch (appThemeEntryNumber) {
1268 case 0: // The system default theme is selected.
1269 // Update the theme preference summary text.
1270 appThemePreference.setSummary(appThemeEntriesStringArray[0]);
1272 // Apply the new theme.
1273 if (Build.VERSION.SDK_INT >= 28) { // The system default theme is supported.
1274 // Follow the system default theme.
1275 AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
1276 } else {// The system default theme is not supported.
1277 // Follow the battery saver mode.
1278 AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY);
1282 case 1: // The light theme is selected.
1283 // Update the theme preference summary text.
1284 appThemePreference.setSummary(appThemeEntriesStringArray[1]);
1286 // Apply the new theme.
1287 AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
1291 // Update the theme preference summary text.
1292 appThemePreference.setSummary(appThemeEntriesStringArray[2]);
1294 // Apply the new theme.
1295 AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
1299 // Disable the WebView theme preference if the API >= 33 and the app theme is set to light.
1300 webViewThemePreference.setEnabled((Build.VERSION.SDK_INT < 33) || (appThemeEntryNumber != 1));
1302 // Get the WebView theme.
1303 String webViewTheme = sharedPreferences.getString(context.getString(R.string.webview_theme_key), context.getString(R.string.webview_theme_default_value));
1305 // Declare a WebView theme entry number.
1306 int webViewThemeEntryNumber;
1308 // Get the webView theme entry number that matches the new WebView theme. A switch statement cannot be used because the theme entry values string array is not a compile time constant.
1309 if (webViewTheme.equals(webViewThemeEntriesStringArray[1])) { // The light theme is selected.
1310 // Store the WebView theme entry number.
1311 webViewThemeEntryNumber = 1;
1312 } else if (webViewTheme.equals(webViewThemeEntryValuesStringArray[2])) { // The dark theme is selected.
1313 // Store the WebView theme entry number.
1314 webViewThemeEntryNumber = 2;
1315 } else { // The system default theme is selected.
1316 // Store the WebView theme entry number.
1317 webViewThemeEntryNumber = 0;
1320 // Update the WebView theme preference icon.
1321 if (webViewThemePreference.isEnabled()) { // The WebView theme preference is enabled.
1322 switch (webViewThemeEntryNumber) {
1323 case 0: // The system default WebView theme is selected.
1324 // Get the current theme status.
1325 int currentThemeStatus = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
1327 // Set the icon according to the app theme.
1328 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO)
1329 webViewThemePreference.setIcon(R.drawable.webview_light_theme);
1331 webViewThemePreference.setIcon(R.drawable.webview_dark_theme);
1334 case 1: // The light WebView theme is selected.
1336 webViewThemePreference.setIcon(R.drawable.webview_light_theme);
1339 case 2: // The dark WebView theme is selected.
1341 webViewThemePreference.setIcon(R.drawable.webview_dark_theme);
1344 } else { // The WebView theme preference is disabled.
1345 webViewThemePreference.setIcon(R.drawable.webview_theme_ghosted);
1349 case "webview_theme":
1350 // Get the new WebView theme.
1351 String newWebViewTheme = sharedPreferences.getString(context.getString(R.string.webview_theme_key), context.getString(R.string.webview_theme_default_value));
1353 // Declare a new WebView theme entry number.
1354 int newWebViewThemeEntryNumber;
1356 // Get the webView theme entry number that matches the new WebView theme. A switch statement cannot be used because the theme entry values string array is not a compile time constant.
1357 if (newWebViewTheme.equals(webViewThemeEntriesStringArray[1])) { // The light theme is selected.
1358 // Store the new WebView theme entry number.
1359 newWebViewThemeEntryNumber = 1;
1360 } else if (newWebViewTheme.equals(webViewThemeEntryValuesStringArray[2])) { // The dark theme is selected.
1361 // Store the new WebView theme entry number.
1362 newWebViewThemeEntryNumber = 2;
1363 } else { // The system default theme is selected.
1364 // Store the new WebView theme entry number.
1365 newWebViewThemeEntryNumber = 0;
1369 switch (newWebViewThemeEntryNumber) {
1370 case 0: // The system default WebView theme is selected.
1371 // Get the current theme status.
1372 int currentThemeStatus = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
1375 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1376 webViewThemePreference.setIcon(R.drawable.webview_light_theme);
1378 webViewThemePreference.setIcon(R.drawable.webview_dark_theme);
1382 case 1: // The light theme is selected.
1384 webViewThemePreference.setIcon(R.drawable.webview_light_theme);
1387 case 2: // The dark theme is selected.
1389 webViewThemePreference.setIcon(R.drawable.webview_dark_theme);
1393 // Set the current theme as the summary text for the preference.
1394 webViewThemePreference.setSummary(webViewThemeEntriesStringArray[newWebViewThemeEntryNumber]);
1397 case "wide_viewport":
1399 if (sharedPreferences.getBoolean(context.getString(R.string.wide_viewport_key), true)) {
1400 wideViewportPreference.setIcon(R.drawable.wide_viewport_enabled);
1402 wideViewportPreference.setIcon(R.drawable.wide_viewport_disabled);
1406 case "display_webpage_images":
1408 if (sharedPreferences.getBoolean(context.getString(R.string.display_webpage_images_key), true)) {
1409 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled);
1411 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled);
1418 private void restartPrivacyBrowser() {
1419 // Create an intent to restart Privacy Browser.
1420 Intent restartIntent = requireActivity().getParentActivityIntent();
1422 // Assert that the intent is not null to remove the lint error below.
1423 assert restartIntent != null;
1425 // `Intent.FLAG_ACTIVITY_CLEAR_TASK` removes all activities from the stack. It requires `Intent.FLAG_ACTIVITY_NEW_TASK`.
1426 restartIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
1428 // Create a handler to restart the activity.
1429 Handler restartHandler = new Handler(Looper.getMainLooper());
1431 // Create a runnable to restart the activity.
1432 Runnable restartRunnable = () -> {
1433 // Restart the activity.
1434 startActivity(restartIntent);
1436 // Kill this instance of Privacy Browser. Otherwise, the app exhibits sporadic behavior after the restart.
1440 // Restart the activity after 400 milliseconds, so that the app has enough time to save the change to the preference.
1441 restartHandler.postDelayed(restartRunnable, 400);