75e008ad12cceaf6a9c61d6e7e0f7f20fe2ee563
[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
34 public class SettingsFragment extends PreferenceFragment {
35     private SharedPreferences.OnSharedPreferenceChangeListener preferencesListener;
36     private SharedPreferences savedPreferences;
37
38     @Override
39     public void onCreate(Bundle savedInstanceState) {
40         super.onCreate(savedInstanceState);
41         addPreferencesFromResource(R.xml.preferences);
42
43         // Initialize savedPreferences.
44         savedPreferences = getPreferenceScreen().getSharedPreferences();
45
46         // Get handles for the preferences we need to modify.
47         final Preference javaScriptEnabled = findPreference("javascript_enabled");
48         final Preference firstPartyCookiesEnabled = findPreference("first_party_cookies_enabled");
49         final Preference thirdPartyCookiesEnabled = findPreference("third_party_cookies_enabled");
50         final Preference domStorageEnabled = findPreference("dom_storage_enabled");
51         final Preference userAgentPreference = findPreference("user_agent");
52         final Preference customUserAgent = findPreference("custom_user_agent");
53         final Preference torHomepagePreference = findPreference("tor_homepage");
54         final Preference torSearchPreference = findPreference("tor_search");
55         final Preference torSearchCustomURLPreference = findPreference("tor_search_custom_url");
56         final Preference searchPreference = findPreference("search");
57         final Preference searchCustomURLPreference = findPreference("search_custom_url");
58         final Preference hideSystemBarsPreference = findPreference("hide_system_bars");
59         final Preference translucentNavigationBarPreference = findPreference("translucent_navigation_bar");
60         final Preference homepagePreference = findPreference("homepage");
61         final Preference defaultFontSizePreference = findPreference("default_font_size");
62
63         // Set dependencies.
64         domStorageEnabled.setDependency("javascript_enabled");
65         torHomepagePreference.setDependency("proxy_through_orbot");
66         torSearchPreference.setDependency("proxy_through_orbot");
67         hideSystemBarsPreference.setDependency("enable_full_screen_browsing_mode");
68
69         // Get strings from the preferences.
70         String torSearchString = savedPreferences.getString("tor_search", "https://3g2upl4pq6kufc4m.onion/html/?q=");
71         String searchString = savedPreferences.getString("search", "https://duckduckgo.com/html/?q=");
72
73         // Get booleans from the preferences.
74         boolean javaScriptEnabledBoolean = savedPreferences.getBoolean("javascript_enabled", false);
75         boolean firstPartyCookiesEnabledBoolean = savedPreferences.getBoolean("first_party_cookies_enabled", false);
76         boolean thirdPartyCookiesEnabledBoolean = savedPreferences.getBoolean("third_party_cookies_enabled", false);
77
78         // Only enable `third_party_cookies_enabled` if `first_party_cookies_enabled` is `true` and API >= 21.
79         thirdPartyCookiesEnabled.setEnabled(firstPartyCookiesEnabledBoolean && (Build.VERSION.SDK_INT >= 21));
80
81         // We need to inflated a `WebView` to get the default user agent.
82         LayoutInflater inflater = getActivity().getLayoutInflater();
83         // `@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.
84         @SuppressLint("InflateParams") View bareWebViewLayout = inflater.inflate(R.layout.bare_webview, null, false);
85         final WebView bareWebView = (WebView) bareWebViewLayout.findViewById(R.id.bare_webview);
86
87         // Set the current user-agent as the summary text for the "user_agent" preference when the preference screen is loaded.
88         switch (savedPreferences.getString("user_agent", "PrivacyBrowser/1.0")) {
89             case "WebView default user agent":
90                 // Get the user agent text from the webview (which changes based on the version of Android and WebView installed).
91                 userAgentPreference.setSummary(bareWebView.getSettings().getUserAgentString());
92                 break;
93
94             case "Custom user agent":
95                 // We can't use the string from the array because it is referenced in code and can't be translated.
96                 userAgentPreference.setSummary(R.string.custom_user_agent);
97                 break;
98
99             default:
100                 // Display the user agent from the preference as the summary text.
101                 userAgentPreference.setSummary(savedPreferences.getString("user_agent", "PrivacyBrowser/1.0"));
102                 break;
103         }
104
105         // Set the summary text for "custom_user_agent" (the default is "PrivacyBrowser/1.0") and enable it if "user_agent" it set to "Custom user agent".
106         customUserAgent.setSummary(savedPreferences.getString("custom_user_agent", "PrivacyBrowser/1.0"));
107         customUserAgent.setEnabled(userAgentPreference.getSummary().equals("Custom user agent"));
108
109
110         // 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`.
111         torHomepagePreference.setSummary(savedPreferences.getString("tor_homepage", "https://3g2upl4pq6kufc4m.onion"));
112
113
114         // 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=`
115         if (torSearchString.equals("Custom URL")) {
116             // Use R.string.custom_url, which will be translated, instead of the array value, which will not.
117             torSearchPreference.setSummary(R.string.custom_url);
118         } else {
119             // Set the array value as the summary text.
120             torSearchPreference.setSummary(torSearchString);
121         }
122
123         // Set the summary text for `tor_search_custom_url`.  The default is `""`.
124         torSearchCustomURLPreference.setSummary(savedPreferences.getString("tor_search_custom_url", ""));
125
126         // Enable the Tor custom URL search options only if proxying through Orbot and the search is set to `Custom URL`.
127         torSearchCustomURLPreference.setEnabled(savedPreferences.getBoolean("proxy_through_orbot", false) && torSearchString.equals("Custom URL"));
128
129
130         // 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=`.
131         if (searchString.equals("Custom URL")) {
132             // Use R.string.custom_url, which will be translated, instead of the array value, which will not.
133             searchPreference.setSummary(R.string.custom_url);
134         } else {
135             // Set the array value as the summary text.
136             searchPreference.setSummary(searchString);
137         }
138
139         // Set the summary text for `search_custom_url` (the default is `""`) and enable it if `search` is set to `Custom URL`.
140         searchCustomURLPreference.setSummary(savedPreferences.getString("search_custom_url", ""));
141         searchCustomURLPreference.setEnabled(searchString.equals("Custom URL"));
142
143
144         // Enable `transparent_navigation_bar` only if full screen browsing mode is enabled and `hide_system_bars` is disabled.
145         translucentNavigationBarPreference.setEnabled(savedPreferences.getBoolean("enable_full_screen_browsing_mode", false) && !savedPreferences.getBoolean("hide_system_bars", false));
146
147
148         // Set the homepage URL as the summary text for the `Homepage` preference when the preference screen is loaded.  The default is `https://duckduckgo.com`.
149         homepagePreference.setSummary(savedPreferences.getString("homepage", "https://duckduckgo.com"));
150
151         // 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`.
152         defaultFontSizePreference.setSummary(savedPreferences.getString("default_font_size", "100") + "%%");
153
154
155         // Set the `javascript_enabled` icon.
156         if (javaScriptEnabledBoolean) {
157             javaScriptEnabled.setIcon(R.drawable.javascript_enabled);
158         } else {
159             javaScriptEnabled.setIcon(R.drawable.privacy_mode);
160         }
161
162         // Set the `first_party_cookies_enabled` icon.
163         if (firstPartyCookiesEnabledBoolean) {
164             firstPartyCookiesEnabled.setIcon(R.drawable.cookies_enabled);
165         } else {
166             firstPartyCookiesEnabled.setIcon(R.drawable.cookies_disabled);
167         }
168
169         // Set the `third_party_cookies_enabled` icon.
170         if (firstPartyCookiesEnabledBoolean && Build.VERSION.SDK_INT >= 21) {
171             if (thirdPartyCookiesEnabledBoolean) {
172                 thirdPartyCookiesEnabled.setIcon(R.drawable.cookies_warning);
173             } else {
174                 thirdPartyCookiesEnabled.setIcon(R.drawable.cookies_disabled);
175             }
176         } else {
177             thirdPartyCookiesEnabled.setIcon(R.drawable.cookies_ghosted);
178         }
179
180         // Set the `dom_storage_enabled` icon.
181         if (javaScriptEnabledBoolean) {
182             if (savedPreferences.getBoolean("dom_storage_enabled", false)) {
183                 domStorageEnabled.setIcon(R.drawable.dom_storage_enabled);
184             } else {
185                 domStorageEnabled.setIcon(R.drawable.dom_storage_disabled);
186             }
187         } else {
188             domStorageEnabled.setIcon(R.drawable.dom_storage_ghosted);
189         }
190
191         // Listen for preference changes.
192         preferencesListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
193             @Override
194             // Remove Android Studio's warning about the dangers of using SetJavaScriptEnabled.  We know.
195             @SuppressLint("SetJavaScriptEnabled")
196             public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
197
198                 switch (key) {
199                     case "javascript_enabled":
200                         // Update the icons.
201                         if (sharedPreferences.getBoolean("javascript_enabled", false)) {
202                             // Update the icon for `javascript_enabled`.
203                             javaScriptEnabled.setIcon(R.drawable.javascript_enabled);
204
205                             // Update the icon for `dom_storage_enabled`.
206                             if (sharedPreferences.getBoolean("dom_storage_enabled", false)) {
207                                 domStorageEnabled.setIcon(R.drawable.dom_storage_enabled);
208                             } else {
209                                 domStorageEnabled.setIcon(R.drawable.dom_storage_disabled);
210                             }
211                         } else {  // `javascript_enabled` is `false`.
212                             // Update the icon for `javascript_enabled`.
213                             javaScriptEnabled.setIcon(R.drawable.privacy_mode);
214
215                             // Set the icon for `dom_storage_disabled` to be ghosted.
216                             domStorageEnabled.setIcon(R.drawable.dom_storage_ghosted);
217                         }
218                         break;
219
220                     case "first_party_cookies_enabled":
221                         // Update the icons for `first_party_cookies_enabled` and `third_party_cookies_enabled`.
222                         if (sharedPreferences.getBoolean("first_party_cookies_enabled", false)) {
223                             // Set the icon for `first_party_cookies_enabled`.
224                             firstPartyCookiesEnabled.setIcon(R.drawable.cookies_enabled);
225
226                             // Update the icon for `third_party_cookies_enabled`.
227                             if (Build.VERSION.SDK_INT >= 21) {
228                                 if (sharedPreferences.getBoolean("third_party_cookies_enabled", false)) {
229                                     thirdPartyCookiesEnabled.setIcon(R.drawable.cookies_warning);
230                                 } else {
231                                     thirdPartyCookiesEnabled.setIcon(R.drawable.cookies_disabled);
232                                 }
233                             } else {
234                                 thirdPartyCookiesEnabled.setIcon(R.drawable.cookies_ghosted);
235                             }
236                         } else {  // `first_party_cookies_enabled` is `false`.
237                             // Update the icon for `first_party_cookies_enabled`.
238                             firstPartyCookiesEnabled.setIcon(R.drawable.cookies_disabled);
239
240                             // Set the icon for `third_party_cookies_enabled` to be ghosted.
241                             thirdPartyCookiesEnabled.setIcon(R.drawable.cookies_ghosted);
242                         }
243
244                         // Enable `third_party_cookies_enabled` if `first_party_cookies_enabled` is `true` and API >= 21.
245                         thirdPartyCookiesEnabled.setEnabled(sharedPreferences.getBoolean("first_party_cookies_enabled", false) && (Build.VERSION.SDK_INT >= 21));
246                         break;
247
248                     case "third_party_cookies_enabled":
249                         // Update the icon.
250                         if (sharedPreferences.getBoolean("third_party_cookies_enabled", false)) {
251                             thirdPartyCookiesEnabled.setIcon(R.drawable.cookies_warning);
252                         } else {
253                             thirdPartyCookiesEnabled.setIcon(R.drawable.cookies_disabled);
254                         }
255                         break;
256
257                     case "dom_storage_enabled":
258                         // Update the icon.
259                         if (sharedPreferences.getBoolean("dom_storage_enabled", false)) {
260                             domStorageEnabled.setIcon(R.drawable.dom_storage_enabled);
261                         } else {
262                             domStorageEnabled.setIcon(R.drawable.dom_storage_disabled);
263                         }
264                         break;
265
266                     case "user_agent":
267                         String userAgentString = sharedPreferences.getString("user_agent", "PrivacyBrowser/1.0");
268
269                         switch (userAgentString) {
270                             case "WebView default user agent":
271                                 // Display the user agent as the summary text for `userAgentPreference`, and disable `customUserAgent`.
272                                 userAgentPreference.setSummary(bareWebView.getSettings().getUserAgentString());
273                                 customUserAgent.setEnabled(false);
274                                 break;
275
276                             case "Custom user agent":
277                                 // Display `Custom user agent` as the summary text for `userAgentPreference`, and enable `customUserAgent`.
278                                 userAgentPreference.setSummary(R.string.custom_user_agent);
279                                 customUserAgent.setEnabled(true);
280                                 break;
281
282                             default:
283                                 // Display the user agent as the summary text for `userAgentPreference`, and disable `customUserAgent`.
284                                 userAgentPreference.setSummary(sharedPreferences.getString("user_agent", "PrivacyBrowser/1.0"));
285                                 customUserAgent.setEnabled(false);
286                                 break;
287                         }
288                         break;
289
290                     case "custom_user_agent":
291                         // Set the new custom user agent as the summary text for `custom_user_agent`.  The default is `PrivacyBrowser/1.0`.
292                         customUserAgent.setSummary(sharedPreferences.getString("custom_user_agent", "PrivacyBrowser/1.0"));
293                         break;
294
295                     case "proxy_through_orbot":
296                         // Get current settings.
297                         boolean currentProxyThroughOrbot = sharedPreferences.getBoolean("proxy_through_orbot", false);
298                         String currentTorSearchString = sharedPreferences.getString("tor_search", "https://3g2upl4pq6kufc4m.onion/html/?q=");
299
300                         // Enable the Tor custom URL search option only if `currentProxyThroughOrbot` is true and the search is set to `Custom URL`.
301                         torSearchCustomURLPreference.setEnabled(currentProxyThroughOrbot && currentTorSearchString.equals("Custom URL"));
302                         break;
303
304                     case "tor_homepage":
305                         // Set the new tor homepage URL as the summary text for the `tor_homepage` preference.  The default is DuckDuckGo:  `https://3g2upl4pq6kufc4m.onion`.
306                         torHomepagePreference.setSummary(sharedPreferences.getString("tor_homepage", "https://3g2upl4pq6kufc4m.onion"));
307                         break;
308
309                     case "tor_search":
310                         // Get the present search string.
311                         String presentTorSearchString = sharedPreferences.getString("tor_search", "https://3g2upl4pq6kufc4m.onion/html/?q=");
312
313                         // Set the summary text for `tor_search`.
314                         if (presentTorSearchString.equals("Custom URL")) {
315                             // Use R.string.custom_url, which is translated, instead of the array value, which isn't.
316                             torSearchPreference.setSummary(R.string.custom_url);
317                         } else {
318                             // Set the array value as the summary text.
319                             torSearchPreference.setSummary(presentTorSearchString);
320                         }
321
322                         // Set the status of `torJavaScriptDisabledSearchCustomURLPreference`.
323                         torSearchCustomURLPreference.setEnabled(presentTorSearchString.equals("Custom URL"));
324                         break;
325
326                     case "tor_search_custom_url":
327                         // Set the summary text for `tor_search_custom_url`.
328                         torSearchCustomURLPreference.setSummary(sharedPreferences.getString("tor_search_custom_url", ""));
329                         break;
330
331                     case "search":
332                         String newSearchString = sharedPreferences.getString("search", "https://duckduckgo.com/html/?q=");
333                         if (newSearchString.equals("Custom URL")) {  // Set the summary text to `R.string.custom_url`, which is translated.
334                             searchPreference.setSummary(R.string.custom_url);
335                         } else {  // Set the new search URL as the summary text for the JavaScript-disabled search preference.
336                             searchPreference.setSummary(newSearchString);
337                         }
338
339                         // Enable or disable `searchCustomURLPreference`.
340                         searchCustomURLPreference.setEnabled(newSearchString.equals("Custom URL"));
341                         break;
342
343                     case "search_custom_url":
344                         // Set the new custom search URL as the summary text for `search_custom_url`.  The default is `""`.
345                         searchCustomURLPreference.setSummary(sharedPreferences.getString("search_custom_url", ""));
346                         break;
347
348                     case "enable_full_screen_browsing_mode":
349                         // Enable `transparent_navigation_bar` only if full screen browsing mode is enabled and `hide_system_bars` is disabled.
350                         translucentNavigationBarPreference.setEnabled(sharedPreferences.getBoolean("enable_full_screen_browsing_mode", false) && !sharedPreferences.getBoolean("hide_system_bars", false));
351                         break;
352
353                     case "hide_system_bars":
354                         // Enable `translucentNavigationBarPreference` if `hide_system_bars` is disabled.
355                         translucentNavigationBarPreference.setEnabled(!sharedPreferences.getBoolean("hide_system_bars", false));
356                         break;
357
358                     case "homepage":
359                         // Set the new homepage URL as the summary text for the Homepage preference.  The default is `https://www.duckduckgo.com`.
360                         homepagePreference.setSummary(sharedPreferences.getString("homepage", "https://www.duckduckgo.com"));
361                         break;
362
363                     case "default_font_size":
364                         // Update the summary text of `default_font_size`.
365                         defaultFontSizePreference.setSummary(sharedPreferences.getString("default_font_size", "100") + "%%");
366                         break;
367
368                     default:
369                         // If no match, do nothing.
370                         break;
371                 }
372             }
373         };
374
375         // Register the listener.
376         savedPreferences.registerOnSharedPreferenceChangeListener(preferencesListener);
377     }
378
379     // 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
380     // even while running in the foreground.
381     @Override
382     public void onPause() {
383         super.onPause();
384         savedPreferences.unregisterOnSharedPreferenceChangeListener(preferencesListener);
385     }
386
387     @Override
388     public void onResume() {
389         super.onResume();
390         savedPreferences.registerOnSharedPreferenceChangeListener(preferencesListener);
391     }
392 }