From 4d7e0bfa2399670591dc585f94a976b904787a9d Mon Sep 17 00:00:00 2001
From: Soren Stoutner 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. ic_list. ic_local_activity. ic_location_off. ic_map. ic_more. ic_question_answer. ic_refresh. 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. ic_list. ic_local_activity. ic_location_off. ic_map. ic_more. ic_question_answer. ic_refresh.
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 @@ - +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 @@ + + + +