From: Soren Stoutner Date: Wed, 31 May 2017 00:16:35 +0000 (-0700) Subject: Add controls for `Clear and Exit`. Implements https://redmine.stoutner.com/issues... X-Git-Tag: v2.4~18 X-Git-Url: https://gitweb.stoutner.com/?a=commitdiff_plain;h=4d7e0bfa2399670591dc585f94a976b904787a9d;p=PrivacyBrowserAndroid.git Add controls for `Clear and Exit`. Implements https://redmine.stoutner.com/issues/133. --- diff --git a/app/src/main/assets/de/about_licenses.html b/app/src/main/assets/de/about_licenses.html index 8f99162a..f26e12fb 100644 --- a/app/src/main/assets/de/about_licenses.html +++ b/app/src/main/assets/de/about_licenses.html @@ -79,7 +79,9 @@

ic_create_new_folder.

ic_devices_other.

ic_delete.

+

ic_delete_forever.

ic_dns.

+

ic_donut_small.

ic_edit.

ic_exit_to_app.

ic_expand_less.

@@ -98,6 +100,7 @@

ic_list.

ic_local_activity.

ic_location_off.

+

ic_map.

ic_more.

ic_question_answer.

ic_refresh.

diff --git a/app/src/main/assets/en/about_licenses.html b/app/src/main/assets/en/about_licenses.html index 01ebe5d1..5b858444 100644 --- a/app/src/main/assets/en/about_licenses.html +++ b/app/src/main/assets/en/about_licenses.html @@ -73,7 +73,9 @@

ic_create_new_folder.

ic_devices_other.

ic_delete.

+

ic_delete_forever.

ic_dns.

+

ic_donut_small.

ic_edit.

ic_exit_to_app.

ic_expand_less.

@@ -92,6 +94,7 @@

ic_list.

ic_local_activity.

ic_location_off.

+

ic_map.

ic_more.

ic_question_answer.

ic_refresh.

diff --git a/app/src/main/assets/en/images/ic_delete_forever.png b/app/src/main/assets/en/images/ic_delete_forever.png new file mode 100644 index 00000000..a4e87cc9 Binary files /dev/null and b/app/src/main/assets/en/images/ic_delete_forever.png differ diff --git a/app/src/main/assets/en/images/ic_donut_small.png b/app/src/main/assets/en/images/ic_donut_small.png new file mode 100644 index 00000000..1ec1ca88 Binary files /dev/null and b/app/src/main/assets/en/images/ic_donut_small.png differ diff --git a/app/src/main/assets/es/about_licenses.html b/app/src/main/assets/es/about_licenses.html index 220c15ee..726f2740 100644 --- a/app/src/main/assets/es/about_licenses.html +++ b/app/src/main/assets/es/about_licenses.html @@ -77,7 +77,9 @@

ic_create_new_folder.

ic_devices_other.

ic_delete.

+

ic_delete_forever.

ic_dns.

+

ic_donut_small.

ic_edit.

ic_exit_to_app.

ic_expand_less.

@@ -96,6 +98,7 @@

ic_list.

ic_local_activity.

ic_location_off.

+

ic_map.

ic_more.

ic_question_answer.

ic_refresh.

diff --git a/app/src/main/assets/es/about_links.html b/app/src/main/assets/es/about_links.html index c35dc2ea..489d7078 100644 --- a/app/src/main/assets/es/about_links.html +++ b/app/src/main/assets/es/about_links.html @@ -37,7 +37,7 @@

Noticias

-

Roadmap

+

Hoja de ruta

Seguimiento de errores y petición de funciones

diff --git a/app/src/main/assets/it/about_licenses.html b/app/src/main/assets/it/about_licenses.html index 96194b23..585eca4a 100644 --- a/app/src/main/assets/it/about_licenses.html +++ b/app/src/main/assets/it/about_licenses.html @@ -80,7 +80,9 @@

ic_create_new_folder.

ic_devices_other.

ic_delete.

+

ic_delete_forever.

ic_dns.

+

ic_donut_small.

ic_edit.

ic_exit_to_app.

ic_expand_less.

@@ -99,6 +101,7 @@

ic_list.

ic_local_activity.

ic_location_off.

+

ic_map.

ic_more.

ic_question_answer.

ic_refresh.

diff --git a/app/src/main/assets/zh-rTW/about_licenses.html b/app/src/main/assets/zh-rTW/about_licenses.html index 9b32ce20..5226d733 100644 --- a/app/src/main/assets/zh-rTW/about_licenses.html +++ b/app/src/main/assets/zh-rTW/about_licenses.html @@ -73,7 +73,9 @@

ic_create_new_folder.

ic_devices_other.

ic_delete.

+

ic_delete_forever.

ic_dns.

+

ic_donut_small.

ic_edit.

ic_exit_to_app.

ic_expand_less.

@@ -92,6 +94,7 @@

ic_list.

ic_local_activity.

ic_location_off.

+

ic_map.

ic_more.

ic_question_answer.

ic_refresh.

diff --git a/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java b/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java index f21cae48..63617b69 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java +++ b/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java @@ -1547,30 +1547,83 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation break; case R.id.clearAndExit: - // Clear cookies. The commands changed slightly in API 21. - if (Build.VERSION.SDK_INT >= 21) { - cookieManager.removeAllCookies(null); - } else { - cookieManager.removeAllCookie(); + // Get a handle for `sharedPreferences`. `this` references the current context. + SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); + + boolean clearEverything = sharedPreferences.getBoolean("clear_everything", true); + + // Clear cookies. + if (clearEverything || sharedPreferences.getBoolean("clear_cookies", true)) { + // The command to remove cookies changed slightly in API 21. + if (Build.VERSION.SDK_INT >= 21) { + cookieManager.removeAllCookies(null); + } else { + cookieManager.removeAllCookie(); + } + + // Manually delete the cookies database, as `CookieManager` sometimes will not flush its changes to disk before `System.exit(0)` is run. + try { + // We have to use two commands because `Runtime.exec()` does not like `*`. + privacyBrowserRuntime.exec("rm -f " + privateDataDirectoryString + "/app_webview/Cookies"); + privacyBrowserRuntime.exec("rm -f " + privateDataDirectoryString + "/app_webview/Cookies-journal"); + } catch (IOException e) { + // Do nothing if an error is thrown. + } } // Clear DOM storage. - WebStorage domStorage = WebStorage.getInstance(); - domStorage.deleteAllData(); + if (clearEverything || sharedPreferences.getBoolean("clear_dom_storage", true)) { + // Ask `WebStorage` to clear the DOM storage. + WebStorage webStorage = WebStorage.getInstance(); + webStorage.deleteAllData(); + + // Manually delete the DOM storage directory, as `WebStorage` sometimes will not flush its changes to disk before `System.exit(0)` is run. + try { + // We have to use a `String[]` because the directory contains a space and `Runtime.exec` will not escape the string correctly otherwise. + privacyBrowserRuntime.exec(new String[] {"rm", "-rf", privateDataDirectoryString + "/app_webview/Local Storage/"}); + } catch (IOException e) { + // Do nothing if an error is thrown. + } + } // Clear form data. - WebViewDatabase webViewDatabase = WebViewDatabase.getInstance(this); - webViewDatabase.clearFormData(); + if (clearEverything || sharedPreferences.getBoolean("clear_form_data", true)) { + WebViewDatabase webViewDatabase = WebViewDatabase.getInstance(this); + webViewDatabase.clearFormData(); - // Clear the cache. `true` includes disk files. - mainWebView.clearCache(true); + // Manually delete the form data database, as `WebViewDatabase` sometimes will not flush its changes to disk before `System.exit(0)` is run. + try { + // We have to use a `String[]` because the database contains a space and `Runtime.exec` will not escape the string correctly otherwise. + privacyBrowserRuntime.exec(new String[] {"rm", "-f", privateDataDirectoryString + "/app_webview/Web Data"}); + privacyBrowserRuntime.exec(new String[] {"rm", "-f", privateDataDirectoryString + "/app_webview/Web Data-journal"}); + } catch (IOException e) { + // Do nothing if an error is thrown. + } + } - // Clear the back/forward history. - mainWebView.clearHistory(); + // Clear the cache. + if (clearEverything || sharedPreferences.getBoolean("clear_cache", true)) { + // `true` includes disk files. + mainWebView.clearCache(true); + + // Manually delete the cache directories. + try { + // Delete the main cache directory. + privacyBrowserRuntime.exec("rm -rf " + privateDataDirectoryString + "/cache"); + + // Delete the secondary `Service Worker` cache directory. We have to use a `String[]` because the directory contains a space and `Runtime.exec` will not escape the string correctly otherwise. + privacyBrowserRuntime.exec(new String[] {"rm", "-rf", privateDataDirectoryString + "/app_webview/Service Worker/"}); + } catch (IOException e) { + // Do nothing if an error is thrown. + } + } - // Clear any SSL certificate preferences. + // Clear SSL certificate preferences. mainWebView.clearSslPreferences(); + // Clear the back/forward history. + mainWebView.clearHistory(); + // Clear `formattedUrlString`. formattedUrlString = null; @@ -1583,15 +1636,14 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation // Destroy the internal state of `mainWebView`. mainWebView.destroy(); - // Manually delete cache folders. - try { - // Delete the main `cache` folder. - privacyBrowserRuntime.exec("rm -rf " + privateDataDirectoryString + "/cache"); - - // Delete the `app_webview` folder, which contains an additional `WebView` cache. See `https://code.google.com/p/android/issues/detail?id=233826&thanks=233826&ts=1486670530`. - privacyBrowserRuntime.exec("rm -rf " + privateDataDirectoryString + "/app_webview"); - } catch (IOException e) { - // Do nothing if an error is thrown. + // Manually delete the `app_webview` folder, which contains the cookies, DOM storage, form data, and `Service Worker` cache. + // See `https://code.google.com/p/android/issues/detail?id=233826&thanks=233826&ts=1486670530`. + if (clearEverything) { + try { + privacyBrowserRuntime.exec("rm -rf " + privateDataDirectoryString + "/app_webview"); + } catch (IOException e) { + // Do nothing if an error is thrown. + } } // Close Privacy Browser. `finishAndRemoveTask` also removes Privacy Browser from the recent app list. @@ -1604,9 +1656,6 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation // Remove the terminated program from RAM. The status code is `0`. System.exit(0); break; - - default: - break; } // Close the navigation drawer. @@ -2073,7 +2122,7 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation } private void applyAppSettings() { - // Get the shared preference values. `this` references the current context. + // Get a handle for `sharedPreferences`. `this` references the current context. SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); // Store the values from `sharedPreferences` in variables. diff --git a/app/src/main/java/com/stoutner/privacybrowser/fragments/SettingsFragment.java b/app/src/main/java/com/stoutner/privacybrowser/fragments/SettingsFragment.java index 2ca68461..6d317f06 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/fragments/SettingsFragment.java +++ b/app/src/main/java/com/stoutner/privacybrowser/fragments/SettingsFragment.java @@ -63,6 +63,11 @@ public class SettingsFragment extends PreferenceFragment { final Preference fullScreenBrowsingModePreference = findPreference("full_screen_browsing_mode"); final Preference hideSystemBarsPreference = findPreference("hide_system_bars"); final Preference translucentNavigationBarPreference = findPreference("translucent_navigation_bar"); + final Preference clearEverythingPreference = findPreference("clear_everything"); + final Preference clearCookiesPreference = findPreference("clear_cookies"); + final Preference clearDomStoragePreference = findPreference("clear_dom_storage"); + final Preference clearFormDataPreference = findPreference("clear_form_data"); + final Preference clearCachePreference = findPreference("clear_cache"); final Preference homepagePreference = findPreference("homepage"); final Preference defaultFontSizePreference = findPreference("default_font_size"); final Preference swipeToRefreshPreference = findPreference("swipe_to_refresh"); @@ -86,6 +91,7 @@ public class SettingsFragment extends PreferenceFragment { boolean proxyThroughOrbotBoolean = savedPreferences.getBoolean("proxy_through_orbot", false); boolean fullScreenBrowsingModeBoolean = savedPreferences.getBoolean("full_screen_browsing_mode", false); boolean hideSystemBarsBoolean = savedPreferences.getBoolean("hide_system_bars", false); + boolean clearEverythingBoolean = savedPreferences.getBoolean("clear_everything", true); // Only enable `thirdPartyCookiesPreference` if `firstPartyCookiesEnabledBoolean` is `true` and API >= 21. thirdPartyCookiesPreference.setEnabled(firstPartyCookiesEnabledBoolean && (Build.VERSION.SDK_INT >= 21)); @@ -156,6 +162,11 @@ public class SettingsFragment extends PreferenceFragment { // Enable `translucentNavigationBarPreference` only if full screen browsing mode is enabled and `hide_system_bars` is disabled. translucentNavigationBarPreference.setEnabled(fullScreenBrowsingModeBoolean && !hideSystemBarsBoolean); + // Set the status of the `Clear and Exit` preferences. + clearCookiesPreference.setEnabled(!clearEverythingBoolean); + clearDomStoragePreference.setEnabled(!clearEverythingBoolean); + clearFormDataPreference.setEnabled(!clearEverythingBoolean); + clearCachePreference.setEnabled(!clearEverythingBoolean); // Set the homepage URL as the summary text for the `Homepage` preference when the preference screen is loaded. The default is `https://duckduckgo.com`. homepagePreference.setSummary(savedPreferences.getString("homepage", "https://duckduckgo.com")); @@ -295,6 +306,41 @@ public class SettingsFragment extends PreferenceFragment { translucentNavigationBarPreference.setIcon(R.drawable.translucent_bar_ghosted); } + // Set the `clearEverythingPreference` icon. + if (clearEverythingBoolean) { + clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled); + } else { + clearEverythingPreference.setIcon(R.drawable.clear_everything_disabled); + } + + // Set the `clearCookiesPreference` icon. + if (clearEverythingBoolean || savedPreferences.getBoolean("clear_cookies", true)) { + clearCookiesPreference.setIcon(R.drawable.cookies_cleared); + } else { + clearCookiesPreference.setIcon(R.drawable.cookies_warning); + } + + // Set the `clearDomStoragePreference` icon. + if (clearEverythingBoolean || savedPreferences.getBoolean("clear_dom_storage", true)) { + clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared); + } else { + clearDomStoragePreference.setIcon(R.drawable.dom_storage_warning); + } + + // Set the `clearFormDataPreference` icon. + if (clearEverythingBoolean || savedPreferences.getBoolean("clear_form_data", true)) { + clearFormDataPreference.setIcon(R.drawable.form_data_cleared); + } else { + clearFormDataPreference.setIcon(R.drawable.form_data_warning); + } + + // Set the `clearCachePreference` icon. + if (clearEverythingBoolean || savedPreferences.getBoolean("clear_cache", true)) { + clearCachePreference.setIcon(R.drawable.cache_cleared); + } else { + clearCachePreference.setIcon(R.drawable.cache_warning); + } + // Set the `swipeToRefreshPreference` icon. if (savedPreferences.getBoolean("swipe_to_refresh", false)) { swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled); @@ -620,6 +666,88 @@ public class SettingsFragment extends PreferenceFragment { } break; + case "clear_everything": + // Store the new `clear_everything` status + boolean newClearEverythingBoolean = sharedPreferences.getBoolean("clear_everything", true); + + // Update the status of the `Clear and Exit` preferences. + clearCookiesPreference.setEnabled(!newClearEverythingBoolean); + clearDomStoragePreference.setEnabled(!newClearEverythingBoolean); + clearFormDataPreference.setEnabled(!newClearEverythingBoolean); + clearCachePreference.setEnabled(!newClearEverythingBoolean); + + // Update the `clearEverythingPreference` icon. + if (newClearEverythingBoolean) { + clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled); + } else { + clearEverythingPreference.setIcon(R.drawable.clear_everything_disabled); + } + + // Update the `clearCookiesPreference` icon. + if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_cookies", true)) { + clearCookiesPreference.setIcon(R.drawable.cookies_cleared); + } else { + clearCookiesPreference.setIcon(R.drawable.cookies_warning); + } + + // Update the `clearDomStoragePreference` icon. + if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_dom_storage", true)) { + clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared); + } else { + clearDomStoragePreference.setIcon(R.drawable.dom_storage_warning); + } + + // Update the `clearFormDataPreference` icon. + if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_form_data", true)) { + clearFormDataPreference.setIcon(R.drawable.form_data_cleared); + } else { + clearFormDataPreference.setIcon(R.drawable.form_data_warning); + } + + // Update the `clearCachePreference` icon. + if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_cache", true)) { + clearCachePreference.setIcon(R.drawable.cache_cleared); + } else { + clearCachePreference.setIcon(R.drawable.cache_warning); + } + break; + + case "clear_cookies": + // Update the icon. + if (sharedPreferences.getBoolean("clear_cookies", true)) { + clearCookiesPreference.setIcon(R.drawable.cookies_cleared); + } else { + clearCookiesPreference.setIcon(R.drawable.cookies_warning); + } + break; + + case "clear_dom_storage": + // Update the icon. + if (sharedPreferences.getBoolean("clear_dom_storage", true)) { + clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared); + } else { + clearDomStoragePreference.setIcon(R.drawable.dom_storage_warning); + } + break; + + case "clear_form_data": + // Update the icon. + if (sharedPreferences.getBoolean("clear_form_data", true)) { + clearFormDataPreference.setIcon(R.drawable.form_data_cleared); + } else { + clearFormDataPreference.setIcon(R.drawable.form_data_warning); + } + break; + + case "clear_cache": + // Update the icon. + if (sharedPreferences.getBoolean("clear_cache", true)) { + clearCachePreference.setIcon(R.drawable.cache_cleared); + } else { + clearCachePreference.setIcon(R.drawable.cache_warning); + } + break; + case "homepage": // Set the new homepage URL as the summary text for the Homepage preference. The default is `https://www.duckduckgo.com`. homepagePreference.setSummary(sharedPreferences.getString("homepage", "https://www.duckduckgo.com")); diff --git a/app/src/main/res/drawable/cache_cleared.xml b/app/src/main/res/drawable/cache_cleared.xml new file mode 100644 index 00000000..4edfd872 --- /dev/null +++ b/app/src/main/res/drawable/cache_cleared.xml @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/app/src/main/res/drawable/cache_warning.xml b/app/src/main/res/drawable/cache_warning.xml new file mode 100644 index 00000000..add2185f --- /dev/null +++ b/app/src/main/res/drawable/cache_warning.xml @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/app/src/main/res/drawable/clear_everything_disabled.xml b/app/src/main/res/drawable/clear_everything_disabled.xml new file mode 100644 index 00000000..fcf007af --- /dev/null +++ b/app/src/main/res/drawable/clear_everything_disabled.xml @@ -0,0 +1,13 @@ + + + + + + diff --git a/app/src/main/res/drawable/clear_everything_enabled.xml b/app/src/main/res/drawable/clear_everything_enabled.xml new file mode 100644 index 00000000..6c901aba --- /dev/null +++ b/app/src/main/res/drawable/clear_everything_enabled.xml @@ -0,0 +1,13 @@ + + + + + + diff --git a/app/src/main/res/drawable/cookies_cleared.xml b/app/src/main/res/drawable/cookies_cleared.xml new file mode 100644 index 00000000..f0ba32b1 --- /dev/null +++ b/app/src/main/res/drawable/cookies_cleared.xml @@ -0,0 +1,18 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/dom_storage_cleared.xml b/app/src/main/res/drawable/dom_storage_cleared.xml new file mode 100644 index 00000000..a20c8ca2 --- /dev/null +++ b/app/src/main/res/drawable/dom_storage_cleared.xml @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/app/src/main/res/drawable/dom_storage_warning.xml b/app/src/main/res/drawable/dom_storage_warning.xml new file mode 100644 index 00000000..ee18ccf1 --- /dev/null +++ b/app/src/main/res/drawable/dom_storage_warning.xml @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/app/src/main/res/drawable/form_data_cleared.xml b/app/src/main/res/drawable/form_data_cleared.xml new file mode 100644 index 00000000..4437a3e0 --- /dev/null +++ b/app/src/main/res/drawable/form_data_cleared.xml @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/app/src/main/res/drawable/form_data_warning.xml b/app/src/main/res/drawable/form_data_warning.xml new file mode 100644 index 00000000..71d77a71 --- /dev/null +++ b/app/src/main/res/drawable/form_data_warning.xml @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 5d1b86ae..d8eb744d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -310,6 +310,16 @@ Hide the status and navigation bars in full screen browsing mode. This doesn’t work well if the keyboard is displayed during full screen browsing mode. Translucent navigation bar Make the navigation bar translucent in full screen browsing mode. + Clear everything + Clear cookies, DOM storage, form data, and the cache. Then manually delete the entire “app_webview” and “cache” directories. + Clear cookies + Clears first and third-party cookies. + Clear DOM storage + Clear DOM storage. + Clear form data + Clears form data. + Clear cache + Clear WebView’s cache. General Homepage Default font size diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 87b2eac2..162d932b 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -119,7 +119,7 @@ + android:title="@string/search" > + android:title="@string/full_screen" > + + + + + + + + + + + + +