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