Only reload the `WebView` on restart when displaying of images has just been disabled...
[PrivacyBrowser.git] / app / src / main / java / com / stoutner / privacybrowser / fragments / SettingsFragment.java
1 /*
2  * Copyright © 2016-2017 Soren Stoutner <soren@stoutner.com>.
3  *
4  * This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
5  *
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.
10  *
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.
15  *
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/>.
18  */
19
20 package com.stoutner.privacybrowser.fragments;
21
22 import android.annotation.SuppressLint;
23 import android.content.SharedPreferences;
24 import android.os.Build;
25 import android.os.Bundle;
26 import android.preference.Preference;
27 import android.preference.PreferenceFragment;
28 import android.view.LayoutInflater;
29 import android.view.View;
30 import android.webkit.WebView;
31
32 import com.stoutner.privacybrowser.R;
33 import com.stoutner.privacybrowser.activities.MainWebViewActivity;
34
35 public class SettingsFragment extends PreferenceFragment {
36     private SharedPreferences.OnSharedPreferenceChangeListener preferencesListener;
37     private SharedPreferences savedPreferences;
38
39     @Override
40     public void onCreate(Bundle savedInstanceState) {
41         super.onCreate(savedInstanceState);
42         addPreferencesFromResource(R.xml.preferences);
43
44         // Initialize savedPreferences.
45         savedPreferences = getPreferenceScreen().getSharedPreferences();
46
47         // Get handles for the preferences we need to modify.
48         final Preference javaScriptPreference = findPreference("javascript_enabled");
49         final Preference firstPartyCookiesPreference = findPreference("first_party_cookies_enabled");
50         final Preference thirdPartyCookiesPreference = findPreference("third_party_cookies_enabled");
51         final Preference domStoragePreference = findPreference("dom_storage_enabled");
52         final Preference saveFormDataPreference = findPreference("save_form_data_enabled");
53         final Preference userAgentPreference = findPreference("user_agent");
54         final Preference customUserAgentPreference = findPreference("custom_user_agent");
55         final Preference blockAdsPreference = findPreference("block_ads");
56         final Preference incognitoModePreference = findPreference("incognito_mode");
57         final Preference doNotTrackPreference = findPreference("do_not_track");
58         final Preference proxyThroughOrbotPreference = findPreference("proxy_through_orbot");
59         final Preference torHomepagePreference = findPreference("tor_homepage");
60         final Preference torSearchPreference = findPreference("tor_search");
61         final Preference torSearchCustomURLPreference = findPreference("tor_search_custom_url");
62         final Preference searchPreference = findPreference("search");
63         final Preference searchCustomURLPreference = findPreference("search_custom_url");
64         final Preference fullScreenBrowsingModePreference = findPreference("full_screen_browsing_mode");
65         final Preference hideSystemBarsPreference = findPreference("hide_system_bars");
66         final Preference translucentNavigationBarPreference = findPreference("translucent_navigation_bar");
67         final Preference clearEverythingPreference = findPreference("clear_everything");
68         final Preference clearCookiesPreference = findPreference("clear_cookies");
69         final Preference clearDomStoragePreference = findPreference("clear_dom_storage");
70         final Preference clearFormDataPreference = findPreference("clear_form_data");
71         final Preference clearCachePreference = findPreference("clear_cache");
72         final Preference homepagePreference = findPreference("homepage");
73         final Preference defaultFontSizePreference = findPreference("default_font_size");
74         final Preference swipeToRefreshPreference = findPreference("swipe_to_refresh");
75         final Preference displayAdditionalAppBarIconsPreference = findPreference("display_additional_app_bar_icons");
76         final Preference displayWebpageImagesPreference = findPreference("display_webpage_images");
77
78         // Set dependencies.
79         domStoragePreference.setDependency("javascript_enabled");
80         torHomepagePreference.setDependency("proxy_through_orbot");
81         torSearchPreference.setDependency("proxy_through_orbot");
82         hideSystemBarsPreference.setDependency("full_screen_browsing_mode");
83
84         // Get strings from the preferences.
85         String torSearchString = savedPreferences.getString("tor_search", "https://3g2upl4pq6kufc4m.onion/html/?q=");
86         String searchString = savedPreferences.getString("search", "https://duckduckgo.com/html/?q=");
87
88         // Get booleans from the preferences.
89         boolean javaScriptEnabledBoolean = savedPreferences.getBoolean("javascript_enabled", false);
90         boolean firstPartyCookiesEnabledBoolean = savedPreferences.getBoolean("first_party_cookies_enabled", false);
91         boolean thirdPartyCookiesEnabledBoolean = savedPreferences.getBoolean("third_party_cookies_enabled", false);
92         boolean proxyThroughOrbotBoolean = savedPreferences.getBoolean("proxy_through_orbot", false);
93         boolean fullScreenBrowsingModeBoolean = savedPreferences.getBoolean("full_screen_browsing_mode", false);
94         boolean hideSystemBarsBoolean = savedPreferences.getBoolean("hide_system_bars", false);
95         boolean clearEverythingBoolean = savedPreferences.getBoolean("clear_everything", true);
96
97         // Only enable `thirdPartyCookiesPreference` if `firstPartyCookiesEnabledBoolean` is `true` and API >= 21.
98         thirdPartyCookiesPreference.setEnabled(firstPartyCookiesEnabledBoolean && (Build.VERSION.SDK_INT >= 21));
99
100         // We need to inflated a `WebView` to get the default user agent.
101         LayoutInflater inflater = getActivity().getLayoutInflater();
102         // `@SuppressLint("InflateParams")` removes the warning about using `null` as the `ViewGroup`, which in this case makes sense because we don't want to display `bare_webview` on the screen.  `false` does not attach the view to the root.
103         @SuppressLint("InflateParams") View bareWebViewLayout = inflater.inflate(R.layout.bare_webview, null, false);
104         final WebView bareWebView = (WebView) bareWebViewLayout.findViewById(R.id.bare_webview);
105
106         // Set the current user-agent as the summary text for the "user_agent" preference when the preference screen is loaded.
107         switch (savedPreferences.getString("user_agent", "PrivacyBrowser/1.0")) {
108             case "WebView default user agent":
109                 // Get the user agent text from the webview (which changes based on the version of Android and WebView installed).
110                 userAgentPreference.setSummary(bareWebView.getSettings().getUserAgentString());
111                 break;
112
113             case "Custom user agent":
114                 // We can't use the string from the array because it is referenced in code and can't be translated.
115                 userAgentPreference.setSummary(R.string.custom_user_agent);
116                 break;
117
118             default:
119                 // Display the user agent from the preference as the summary text.
120                 userAgentPreference.setSummary(savedPreferences.getString("user_agent", "PrivacyBrowser/1.0"));
121                 break;
122         }
123
124         // Set the summary text for "customUserAgentPreference" (the default is `PrivacyBrowser/1.0`) and enable it if `userAgentPreference` it set to `Custom user agent`.
125         customUserAgentPreference.setSummary(savedPreferences.getString("custom_user_agent", "PrivacyBrowser/1.0"));
126         customUserAgentPreference.setEnabled(userAgentPreference.getSummary().equals("Custom user agent"));
127
128
129         // Set the Tor homepage URL as the summary text for the `tor_homepage` preference when the preference screen is loaded.  The default is DuckDuckGo: `https://3g2upl4pq6kufc4m.onion`.
130         torHomepagePreference.setSummary(savedPreferences.getString("tor_homepage", "https://3g2upl4pq6kufc4m.onion"));
131
132
133         // Set the Tor search URL as the summary text for the Tor preference when the preference screen is loaded.  The default is `https://3g2upl4pq6kufc4m.onion/html/?q=`
134         if (torSearchString.equals("Custom URL")) {
135             // Use R.string.custom_url, which will be translated, instead of the array value, which will not.
136             torSearchPreference.setSummary(R.string.custom_url);
137         } else {
138             // Set the array value as the summary text.
139             torSearchPreference.setSummary(torSearchString);
140         }
141
142         // Set the summary text for `tor_search_custom_url`.  The default is `""`.
143         torSearchCustomURLPreference.setSummary(savedPreferences.getString("tor_search_custom_url", ""));
144
145         // Enable the Tor custom URL search options only if proxying through Orbot and the search is set to `Custom URL`.
146         torSearchCustomURLPreference.setEnabled(proxyThroughOrbotBoolean && torSearchString.equals("Custom URL"));
147
148
149         // Set the search URL as the summary text for the search preference when the preference screen is loaded.  The default is `https://duckduckgo.com/html/?q=`.
150         if (searchString.equals("Custom URL")) {
151             // Use R.string.custom_url, which will be translated, instead of the array value, which will not.
152             searchPreference.setSummary(R.string.custom_url);
153         } else {
154             // Set the array value as the summary text.
155             searchPreference.setSummary(searchString);
156         }
157
158         // Set the summary text for `search_custom_url` (the default is `""`) and enable it if `search` is set to `Custom URL`.
159         searchCustomURLPreference.setSummary(savedPreferences.getString("search_custom_url", ""));
160         searchCustomURLPreference.setEnabled(searchString.equals("Custom URL"));
161
162
163         // Enable `translucentNavigationBarPreference` only if full screen browsing mode is enabled and `hide_system_bars` is disabled.
164         translucentNavigationBarPreference.setEnabled(fullScreenBrowsingModeBoolean && !hideSystemBarsBoolean);
165
166         // Set the status of the `Clear and Exit` preferences.
167         clearCookiesPreference.setEnabled(!clearEverythingBoolean);
168         clearDomStoragePreference.setEnabled(!clearEverythingBoolean);
169         clearFormDataPreference.setEnabled(!clearEverythingBoolean);
170         clearCachePreference.setEnabled(!clearEverythingBoolean);
171
172         // Set the homepage URL as the summary text for the `Homepage` preference when the preference screen is loaded.  The default is `https://duckduckgo.com`.
173         homepagePreference.setSummary(savedPreferences.getString("homepage", "https://duckduckgo.com"));
174
175         // Set the default font size as the summary text for the `Default Font Size` preference when the preference screen is loaded.  The default is `100`.
176         defaultFontSizePreference.setSummary(savedPreferences.getString("default_font_size", "100") + "%%");
177
178
179         // Set the `javaScriptPreference` icon.
180         if (javaScriptEnabledBoolean) {
181             javaScriptPreference.setIcon(R.drawable.javascript_enabled);
182         } else {
183             javaScriptPreference.setIcon(R.drawable.privacy_mode);
184         }
185
186         // Set the `firstPartyCookiesPreference` icon.
187         if (firstPartyCookiesEnabledBoolean) {
188             firstPartyCookiesPreference.setIcon(R.drawable.cookies_enabled);
189         } else {
190             firstPartyCookiesPreference.setIcon(R.drawable.cookies_disabled);
191         }
192
193         // Set the `thirdPartyCookiesPreference` icon.
194         if (firstPartyCookiesEnabledBoolean && Build.VERSION.SDK_INT >= 21) {
195             if (thirdPartyCookiesEnabledBoolean) {
196                 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_warning);
197             } else {
198                 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled);
199             }
200         } else {
201             thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted);
202         }
203
204         // Set the `domStoragePreference` icon.
205         if (javaScriptEnabledBoolean) {
206             if (savedPreferences.getBoolean("dom_storage_enabled", false)) {
207                 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
208             } else {
209                 domStoragePreference.setIcon(R.drawable.dom_storage_disabled);
210             }
211         } else {
212             domStoragePreference.setIcon(R.drawable.dom_storage_ghosted);
213         }
214
215         // Set the `saveFormDataPreference` icon.
216         if (savedPreferences.getBoolean("save_form_data_enabled", false)) {
217             saveFormDataPreference.setIcon(R.drawable.form_data_enabled);
218         } else {
219             saveFormDataPreference.setIcon(R.drawable.form_data_disabled);
220         }
221
222         // Set the `customUserAgentPreference` icon.
223         if (customUserAgentPreference.isEnabled()) {
224             customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled);
225         } else {
226             customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted);
227         }
228
229         // Set the `blockAdsPreference` icon.
230         if (savedPreferences.getBoolean("block_ads", true)) {
231             blockAdsPreference.setIcon(R.drawable.block_ads_enabled);
232         } else {
233             blockAdsPreference.setIcon(R.drawable.block_ads_disabled);
234         }
235
236         // Set the `incognitoModePreference` icon.
237         if (savedPreferences.getBoolean("incognito_mode", false)) {
238             incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled);
239         } else {
240             incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled);
241         }
242
243         // Set the `doNotTrackPreference` icon.
244         if (savedPreferences.getBoolean("do_not_track", false)) {
245             doNotTrackPreference.setIcon(R.drawable.do_not_track_enabled);
246         } else {
247             doNotTrackPreference.setIcon(R.drawable.do_not_track_disabled);
248         }
249
250         // Set the `proxyThroughOrbotPreference` icon.
251         if (proxyThroughOrbotBoolean) {
252             proxyThroughOrbotPreference.setIcon(R.drawable.orbot_enabled);
253         } else {
254             proxyThroughOrbotPreference.setIcon(R.drawable.orbot_disabled);
255         }
256
257         // Set the `torSearchPreference` and `torSearchCustomURLPreference` icons.
258         if (proxyThroughOrbotBoolean) {
259             // Set the `torHomepagePreference` and `torSearchPreference` icons.
260             torHomepagePreference.setIcon(R.drawable.home_enabled);
261             torSearchPreference.setIcon(R.drawable.search_enabled);
262
263             // Set the `torSearchCustomURLPreference` icon.
264             if (torSearchCustomURLPreference.isEnabled()) {
265                 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled);
266             } else {
267                 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_disabled);
268             }
269         } else {  // Proxy through Orbot is disabled.
270             torHomepagePreference.setIcon(R.drawable.home_ghosted);
271             torSearchPreference.setIcon(R.drawable.search_ghosted);
272             torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted);
273         }
274
275         // Set the `searchCustomURLPreference` icon.
276         if (searchCustomURLPreference.isEnabled()) {
277             searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled);
278         } else {
279             searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted);
280         }
281
282         // Set the full screen browsing mode icons.
283         if (fullScreenBrowsingModeBoolean) {
284             // Set the `fullScreenBrowsingModePreference` icon.
285             fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled);
286
287             if (hideSystemBarsBoolean) {
288                 // Set `hideSystemBarsPreference` to use the enabled icon.
289                 hideSystemBarsPreference.setIcon(R.drawable.hide_system_bars_enabled);
290
291                 // Set `translucentNavigationBarPreference` to use the ghosted icon.
292                 translucentNavigationBarPreference.setIcon(R.drawable.translucent_bar_ghosted);
293             } else {  // `hideSystemBarsBoolean` is false.
294                 // Set `hideSystemBarsPreference` to use the disabled icon.
295                 hideSystemBarsPreference.setIcon(R.drawable.hide_system_bars_disabled);
296
297                 // Set the correct icon for `translucentNavigationBarPreference`.
298                 if (savedPreferences.getBoolean("translucent_navigation_bar", true)) {
299                     translucentNavigationBarPreference.setIcon(R.drawable.translucent_bar_enabled);
300                 } else {
301                     translucentNavigationBarPreference.setIcon(R.drawable.translucent_bar_disabled);
302                 }
303             }
304         } else {  // `fullScreenBrowsingModeBoolean` is false.
305             fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled);
306             hideSystemBarsPreference.setIcon(R.drawable.hide_system_bars_ghosted);
307             translucentNavigationBarPreference.setIcon(R.drawable.translucent_bar_ghosted);
308         }
309
310         // Set the `clearEverythingPreference` icon.
311         if (clearEverythingBoolean) {
312             clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled);
313         } else {
314             clearEverythingPreference.setIcon(R.drawable.clear_everything_disabled);
315         }
316
317         // Set the `clearCookiesPreference` icon.
318         if (clearEverythingBoolean || savedPreferences.getBoolean("clear_cookies", true)) {
319             clearCookiesPreference.setIcon(R.drawable.cookies_cleared);
320         } else {
321             clearCookiesPreference.setIcon(R.drawable.cookies_warning);
322         }
323
324         // Set the `clearDomStoragePreference` icon.
325         if (clearEverythingBoolean || savedPreferences.getBoolean("clear_dom_storage", true)) {
326             clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared);
327         } else {
328             clearDomStoragePreference.setIcon(R.drawable.dom_storage_warning);
329         }
330
331         // Set the `clearFormDataPreference` icon.
332         if (clearEverythingBoolean || savedPreferences.getBoolean("clear_form_data", true)) {
333             clearFormDataPreference.setIcon(R.drawable.form_data_cleared);
334         } else {
335             clearFormDataPreference.setIcon(R.drawable.form_data_warning);
336         }
337
338         // Set the `clearCachePreference` icon.
339         if (clearEverythingBoolean || savedPreferences.getBoolean("clear_cache", true)) {
340             clearCachePreference.setIcon(R.drawable.cache_cleared);
341         } else {
342             clearCachePreference.setIcon(R.drawable.cache_warning);
343         }
344
345         // Set the `swipeToRefreshPreference` icon.
346         if (savedPreferences.getBoolean("swipe_to_refresh", false)) {
347             swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled);
348         } else {
349             swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled);
350         }
351
352         // Set the `displayAdditionalAppBarIconsPreference` icon.
353         if (savedPreferences.getBoolean("display_additional_app_bar_icons", false)) {
354             displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled);
355         } else {
356             displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled);
357         }
358
359         // Set the `displayWebpageImagesPreference` icon.
360         if (savedPreferences.getBoolean("display_webpage_images", true)) {
361             displayWebpageImagesPreference.setIcon(R.drawable.images_enabled);
362         } else {
363             displayWebpageImagesPreference.setIcon(R.drawable.images_disabled);
364         }
365
366
367         // Listen for preference changes.
368         preferencesListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
369             @Override
370             // Remove Android Studio's warning about the dangers of using SetJavaScriptEnabled.  We know.
371             @SuppressLint("SetJavaScriptEnabled")
372             public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
373
374                 switch (key) {
375                     case "javascript_enabled":
376                         // Update the icons.
377                         if (sharedPreferences.getBoolean("javascript_enabled", false)) {
378                             // Update the icon for `javascript_enabled`.
379                             javaScriptPreference.setIcon(R.drawable.javascript_enabled);
380
381                             // Update the icon for `dom_storage_enabled`.
382                             if (sharedPreferences.getBoolean("dom_storage_enabled", false)) {
383                                 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
384                             } else {
385                                 domStoragePreference.setIcon(R.drawable.dom_storage_disabled);
386                             }
387                         } else {  // `javascript_enabled` is `false`.
388                             // Update the icon for `javascript_enabled`.
389                             javaScriptPreference.setIcon(R.drawable.privacy_mode);
390
391                             // Set the icon for `dom_storage_disabled` to be ghosted.
392                             domStoragePreference.setIcon(R.drawable.dom_storage_ghosted);
393                         }
394                         break;
395
396                     case "first_party_cookies_enabled":
397                         // Update the icons for `first_party_cookies_enabled` and `third_party_cookies_enabled`.
398                         if (sharedPreferences.getBoolean("first_party_cookies_enabled", false)) {
399                             // Set the icon for `first_party_cookies_enabled`.
400                             firstPartyCookiesPreference.setIcon(R.drawable.cookies_enabled);
401
402                             // Update the icon for `third_party_cookies_enabled`.
403                             if (Build.VERSION.SDK_INT >= 21) {
404                                 if (sharedPreferences.getBoolean("third_party_cookies_enabled", false)) {
405                                     thirdPartyCookiesPreference.setIcon(R.drawable.cookies_warning);
406                                 } else {
407                                     thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled);
408                                 }
409                             } else {
410                                 thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted);
411                             }
412                         } else {  // `first_party_cookies_enabled` is `false`.
413                             // Update the icon for `first_party_cookies_enabled`.
414                             firstPartyCookiesPreference.setIcon(R.drawable.cookies_disabled);
415
416                             // Set the icon for `third_party_cookies_enabled` to be ghosted.
417                             thirdPartyCookiesPreference.setIcon(R.drawable.cookies_ghosted);
418                         }
419
420                         // Enable `third_party_cookies_enabled` if `first_party_cookies_enabled` is `true` and API >= 21.
421                         thirdPartyCookiesPreference.setEnabled(sharedPreferences.getBoolean("first_party_cookies_enabled", false) && (Build.VERSION.SDK_INT >= 21));
422                         break;
423
424                     case "third_party_cookies_enabled":
425                         // Update the icon.
426                         if (sharedPreferences.getBoolean("third_party_cookies_enabled", false)) {
427                             thirdPartyCookiesPreference.setIcon(R.drawable.cookies_warning);
428                         } else {
429                             thirdPartyCookiesPreference.setIcon(R.drawable.cookies_disabled);
430                         }
431                         break;
432
433                     case "dom_storage_enabled":
434                         // Update the icon.
435                         if (sharedPreferences.getBoolean("dom_storage_enabled", false)) {
436                             domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
437                         } else {
438                             domStoragePreference.setIcon(R.drawable.dom_storage_disabled);
439                         }
440                         break;
441
442                     case "save_form_data_enabled":
443                         // Update the icon.
444                         if (sharedPreferences.getBoolean("save_form_data_enabled", false)) {
445                             saveFormDataPreference.setIcon(R.drawable.form_data_enabled);
446                         } else {
447                             saveFormDataPreference.setIcon(R.drawable.form_data_disabled);
448                         }
449
450                     case "user_agent":
451                         String userAgentString = sharedPreferences.getString("user_agent", "PrivacyBrowser/1.0");
452
453                         switch (userAgentString) {
454                             case "WebView default user agent":
455                                 // Display the user agent as the summary text for `userAgentPreference`.
456                                 userAgentPreference.setSummary(bareWebView.getSettings().getUserAgentString());
457
458                                 // Update `customUserAgentPreference`.
459                                 customUserAgentPreference.setEnabled(false);
460                                 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted);
461                                 break;
462
463                             case "Custom user agent":
464                                 // Display `Custom user agent` as the summary text for `userAgentPreference`.
465                                 userAgentPreference.setSummary(R.string.custom_user_agent);
466
467                                 // Update `customUserAgentPreference`.
468                                 customUserAgentPreference.setEnabled(true);
469                                 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled);
470                                 break;
471
472                             default:
473                                 // Display the user agent as the summary text for `userAgentPreference`.
474                                 userAgentPreference.setSummary(sharedPreferences.getString("user_agent", "PrivacyBrowser/1.0"));
475
476                                 // Update `customUserAgentPreference`.
477                                 customUserAgentPreference.setEnabled(false);
478                                 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted);
479                                 break;
480                         }
481                         break;
482
483                     case "custom_user_agent":
484                         // Set the new custom user agent as the summary text for `custom_user_agent`.  The default is `PrivacyBrowser/1.0`.
485                         customUserAgentPreference.setSummary(sharedPreferences.getString("custom_user_agent", "PrivacyBrowser/1.0"));
486                         break;
487
488                     case "block_ads":
489                         // Update the icon.
490                         if (sharedPreferences.getBoolean("block_ads", true)) {
491                             blockAdsPreference.setIcon(R.drawable.block_ads_enabled);
492                         } else {
493                             blockAdsPreference.setIcon(R.drawable.block_ads_disabled);
494                         }
495                         break;
496
497                     case "incognito_mode":
498                         // Update the icon.
499                         if (sharedPreferences.getBoolean("incognito_mode", false)) {
500                             incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled);
501                         } else {
502                             incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled);
503                         }
504                         break;
505
506                     case "do_not_track":
507                         // Update the icon.
508                         if (sharedPreferences.getBoolean("do_not_track", false)) {
509                             doNotTrackPreference.setIcon(R.drawable.do_not_track_enabled);
510                         } else {
511                             doNotTrackPreference.setIcon(R.drawable.do_not_track_disabled);
512                         }
513
514                         break;
515
516                     case "proxy_through_orbot":
517                         // Get current settings.
518                         boolean currentProxyThroughOrbot = sharedPreferences.getBoolean("proxy_through_orbot", false);
519                         String currentTorSearchString = sharedPreferences.getString("tor_search", "https://3g2upl4pq6kufc4m.onion/html/?q=");
520
521                         // Enable the Tor custom URL search option only if `currentProxyThroughOrbot` is true and the search is set to `Custom URL`.
522                         torSearchCustomURLPreference.setEnabled(currentProxyThroughOrbot && currentTorSearchString.equals("Custom URL"));
523
524                         // Update the icons.
525                         if (currentProxyThroughOrbot) {
526                             // Set the `proxyThroughOrbotPreference`, `torHomepagePreference`, and `torSearchPreference` icons.
527                             proxyThroughOrbotPreference.setIcon(R.drawable.orbot_enabled);
528                             torHomepagePreference.setIcon(R.drawable.home_enabled);
529                             torSearchPreference.setIcon(R.drawable.search_enabled);
530
531                             // Set the `torSearchCustomURLPreference` icon.
532                             if (torSearchCustomURLPreference.isEnabled()) {
533                                 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled);
534                             } else {
535                                 torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_disabled);
536                             }
537                         } else {  // Proxy through Orbot is disabled.
538                             proxyThroughOrbotPreference.setIcon(R.drawable.orbot_disabled);
539                             torHomepagePreference.setIcon(R.drawable.home_ghosted);
540                             torSearchPreference.setIcon(R.drawable.search_ghosted);
541                             torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted);
542                         }
543                         break;
544
545                     case "tor_homepage":
546                         // Set the new tor homepage URL as the summary text for the `tor_homepage` preference.  The default is DuckDuckGo:  `https://3g2upl4pq6kufc4m.onion`.
547                         torHomepagePreference.setSummary(sharedPreferences.getString("tor_homepage", "https://3g2upl4pq6kufc4m.onion"));
548                         break;
549
550                     case "tor_search":
551                         // Get the present search string.
552                         String presentTorSearchString = sharedPreferences.getString("tor_search", "https://3g2upl4pq6kufc4m.onion/html/?q=");
553
554                         // Update the preferences.
555                         if (presentTorSearchString.equals("Custom URL")) {
556                             // Use `R.string.custom_url`, which is translated, as the summary instead of the array value, which isn't.
557                             torSearchPreference.setSummary(R.string.custom_url);
558
559                             // Update `torSearchCustomURLPreference`.
560                             torSearchCustomURLPreference.setEnabled(true);
561                             torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled);
562                         } else {
563                             // Set the array value as the summary text.
564                             torSearchPreference.setSummary(presentTorSearchString);
565
566                             // Update `torSearchCustomURLPreference`.
567                             torSearchCustomURLPreference.setEnabled(false);
568                             torSearchCustomURLPreference.setIcon(R.drawable.search_custom_url_disabled);
569                         }
570                         break;
571
572                     case "tor_search_custom_url":
573                         // Set the summary text for `tor_search_custom_url`.
574                         torSearchCustomURLPreference.setSummary(sharedPreferences.getString("tor_search_custom_url", ""));
575                         break;
576
577                     case "search":
578                         // Store the new search string.
579                         String newSearchString = sharedPreferences.getString("search", "https://duckduckgo.com/html/?q=");
580
581                         // Update `searchPreference` and `searchCustomURLPreference`.
582                         if (newSearchString.equals("Custom URL")) {  // `Custom URL` is selected.
583                             // Set the summary text to `R.string.custom_url`, which is translated.
584                             searchPreference.setSummary(R.string.custom_url);
585
586                             // Update `searchCustomURLPreference`.
587                             searchCustomURLPreference.setEnabled(true);
588                             searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled);
589                         } else {  // `Custom URL` is not selected.
590                             // Set the summary text to `newSearchString`.
591                             searchPreference.setSummary(newSearchString);
592
593                             // Update `searchCustomURLPreference`.
594                             searchCustomURLPreference.setEnabled(false);
595                             searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted);
596                         }
597                         break;
598
599                     case "search_custom_url":
600                         // Set the new custom search URL as the summary text for `search_custom_url`.  The default is `""`.
601                         searchCustomURLPreference.setSummary(sharedPreferences.getString("search_custom_url", ""));
602                         break;
603
604                     case "full_screen_browsing_mode":
605                         if (sharedPreferences.getBoolean("full_screen_browsing_mode", false)) {
606                             // Set `fullScreenBrowsingModePreference` to use the enabled icon.
607                             fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled);
608
609                             if (sharedPreferences.getBoolean("hide_system_bars", false)) {
610                                 // Set `hideSystemBarsPreference` to use the enabled icon.
611                                 hideSystemBarsPreference.setIcon(R.drawable.hide_system_bars_enabled);
612
613                                 // Update `translucentNavigationBarPreference`.
614                                 translucentNavigationBarPreference.setEnabled(false);
615                                 translucentNavigationBarPreference.setIcon(R.drawable.translucent_bar_ghosted);
616                             } else {  // `hide_system_bars` is false.
617                                 // Set `hideSystemBarsPreference` to use the disabled icon.
618                                 hideSystemBarsPreference.setIcon(R.drawable.hide_system_bars_disabled);
619
620                                 // Update `translucentNavigationBarPreference`.
621                                 translucentNavigationBarPreference.setEnabled(true);
622                                 if (sharedPreferences.getBoolean("translucent_navigation_bar", true)) {
623                                     translucentNavigationBarPreference.setIcon(R.drawable.translucent_bar_enabled);
624                                 } else {
625                                     translucentNavigationBarPreference.setIcon(R.drawable.translucent_bar_disabled);
626                                 }
627                             }
628                         } else {  // `full_screen_browsing_mode` is false.
629                             // Disable `translucentNavigationBarPreference`.
630                             translucentNavigationBarPreference.setEnabled(false);
631
632                             // Update the icons.
633                             fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled);
634                             hideSystemBarsPreference.setIcon(R.drawable.hide_system_bars_ghosted);
635                             translucentNavigationBarPreference.setIcon(R.drawable.translucent_bar_ghosted);
636                         }
637                         break;
638
639                     case "hide_system_bars":
640                         if (sharedPreferences.getBoolean("hide_system_bars", false)) {
641                             // Set `hideSystemBarsPreference` to use the enabled icon.
642                             hideSystemBarsPreference.setIcon(R.drawable.hide_system_bars_enabled);
643
644                             // Update `translucentNavigationBarPreference`.
645                             translucentNavigationBarPreference.setEnabled(false);
646                             translucentNavigationBarPreference.setIcon(R.drawable.translucent_bar_ghosted);
647                         } else {  // `hide_system_bars` is false.
648                             // Set `hideSystemBarsPreference` to use the disabled icon.
649                             hideSystemBarsPreference.setIcon(R.drawable.hide_system_bars_disabled);
650
651                             // Update `translucentNavigationBarPreference`.
652                             translucentNavigationBarPreference.setEnabled(true);
653                             if (sharedPreferences.getBoolean("translucent_navigation_bar", true)) {
654                                 translucentNavigationBarPreference.setIcon(R.drawable.translucent_bar_enabled);
655                             } else {
656                                 translucentNavigationBarPreference.setIcon(R.drawable.translucent_bar_disabled);
657                             }
658                         }
659                         break;
660
661                     case "translucent_navigation_bar":
662                         // Update the icon.
663                         if (sharedPreferences.getBoolean("translucent_navigation_bar", true)) {
664                             translucentNavigationBarPreference.setIcon(R.drawable.translucent_bar_enabled);
665                         } else {
666                             translucentNavigationBarPreference.setIcon(R.drawable.translucent_bar_disabled);
667                         }
668                         break;
669
670                     case "clear_everything":
671                         // Store the new `clear_everything` status
672                         boolean newClearEverythingBoolean = sharedPreferences.getBoolean("clear_everything", true);
673
674                         // Update the status of the `Clear and Exit` preferences.
675                         clearCookiesPreference.setEnabled(!newClearEverythingBoolean);
676                         clearDomStoragePreference.setEnabled(!newClearEverythingBoolean);
677                         clearFormDataPreference.setEnabled(!newClearEverythingBoolean);
678                         clearCachePreference.setEnabled(!newClearEverythingBoolean);
679
680                         // Update the `clearEverythingPreference` icon.
681                         if (newClearEverythingBoolean) {
682                             clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled);
683                         } else {
684                             clearEverythingPreference.setIcon(R.drawable.clear_everything_disabled);
685                         }
686
687                         // Update the `clearCookiesPreference` icon.
688                         if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_cookies", true)) {
689                             clearCookiesPreference.setIcon(R.drawable.cookies_cleared);
690                         } else {
691                             clearCookiesPreference.setIcon(R.drawable.cookies_warning);
692                         }
693
694                         // Update the `clearDomStoragePreference` icon.
695                         if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_dom_storage", true)) {
696                             clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared);
697                         } else {
698                             clearDomStoragePreference.setIcon(R.drawable.dom_storage_warning);
699                         }
700
701                         // Update the `clearFormDataPreference` icon.
702                         if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_form_data", true)) {
703                             clearFormDataPreference.setIcon(R.drawable.form_data_cleared);
704                         } else {
705                             clearFormDataPreference.setIcon(R.drawable.form_data_warning);
706                         }
707
708                         // Update the `clearCachePreference` icon.
709                         if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_cache", true)) {
710                             clearCachePreference.setIcon(R.drawable.cache_cleared);
711                         } else {
712                             clearCachePreference.setIcon(R.drawable.cache_warning);
713                         }
714                         break;
715
716                     case "clear_cookies":
717                         // Update the icon.
718                         if (sharedPreferences.getBoolean("clear_cookies", true)) {
719                             clearCookiesPreference.setIcon(R.drawable.cookies_cleared);
720                         } else {
721                             clearCookiesPreference.setIcon(R.drawable.cookies_warning);
722                         }
723                         break;
724
725                     case "clear_dom_storage":
726                         // Update the icon.
727                         if (sharedPreferences.getBoolean("clear_dom_storage", true)) {
728                             clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared);
729                         } else {
730                             clearDomStoragePreference.setIcon(R.drawable.dom_storage_warning);
731                         }
732                         break;
733
734                     case "clear_form_data":
735                         // Update the icon.
736                         if (sharedPreferences.getBoolean("clear_form_data", true)) {
737                             clearFormDataPreference.setIcon(R.drawable.form_data_cleared);
738                         } else {
739                             clearFormDataPreference.setIcon(R.drawable.form_data_warning);
740                         }
741                         break;
742
743                     case "clear_cache":
744                         // Update the icon.
745                         if (sharedPreferences.getBoolean("clear_cache", true)) {
746                             clearCachePreference.setIcon(R.drawable.cache_cleared);
747                         } else {
748                             clearCachePreference.setIcon(R.drawable.cache_warning);
749                         }
750                         break;
751
752                     case "homepage":
753                         // Set the new homepage URL as the summary text for the Homepage preference.  The default is `https://www.duckduckgo.com`.
754                         homepagePreference.setSummary(sharedPreferences.getString("homepage", "https://www.duckduckgo.com"));
755                         break;
756
757                     case "default_font_size":
758                         // Update the summary text of `default_font_size`.
759                         defaultFontSizePreference.setSummary(sharedPreferences.getString("default_font_size", "100") + "%%");
760                         break;
761
762                     case "swipe_to_refresh":
763                         // Update the icon.
764                         if (sharedPreferences.getBoolean("swipe_to_refresh", false)) {
765                             swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled);
766                         } else {
767                             swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled);
768                         }
769                         break;
770
771                     case "display_additional_app_bar_icons":
772                         // Update the icon.
773                         if (sharedPreferences.getBoolean("display_additional_app_bar_icons", false)) {
774                             displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled);
775                         } else {
776                             displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled);
777                         }
778                         break;
779
780                     case "display_webpage_images":
781                         if (sharedPreferences.getBoolean("display_webpage_images", true)) {
782                             // Update the icon.
783                             displayWebpageImagesPreference.setIcon(R.drawable.images_enabled);
784
785                             // `mainWebView` does not need to be reloaded because unloaded images will load automatically.
786                             MainWebViewActivity.reloadOnRestartBoolean = false;
787                         } else {
788                             // Update the icon.
789                             displayWebpageImagesPreference.setIcon(R.drawable.images_disabled);
790
791                             // Set `mainWebView` to reload on restart to remove the current images.
792                             MainWebViewActivity.reloadOnRestartBoolean = true;
793                         }
794                         break;
795
796                     default:
797                         // If no match, do nothing.
798                         break;
799                 }
800             }
801         };
802
803         // Register the listener.
804         savedPreferences.registerOnSharedPreferenceChangeListener(preferencesListener);
805     }
806
807     // 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
808     // even while running in the foreground.
809     @Override
810     public void onPause() {
811         super.onPause();
812         savedPreferences.unregisterOnSharedPreferenceChangeListener(preferencesListener);
813     }
814
815     @Override
816     public void onResume() {
817         super.onResume();
818         savedPreferences.registerOnSharedPreferenceChangeListener(preferencesListener);
819     }
820 }