From a28488d4f4d041e09a547683df74586f02146b0d Mon Sep 17 00:00:00 2001 From: Soren Stoutner Date: Mon, 27 Jun 2016 12:13:02 -0700 Subject: [PATCH] Add controls for form data. Fixes https://redmine.stoutner.com/issues/29 --- .idea/dictionaries/soren.xml | 1 + app/build.gradle | 2 +- app/src/main/assets/guide_local_storage.html | 18 ++++++--- app/src/main/assets/guide_overview.html | 4 +- .../privacybrowser/MainWebViewActivity.java | 40 +++++++++++++++++-- .../privacybrowser/SettingsFragment.java | 13 ++++++ app/src/main/res/menu/menu_options.xml | 23 ++++++++--- app/src/main/res/values/strings.xml | 4 ++ app/src/main/res/xml/preferences.xml | 6 +++ 9 files changed, 95 insertions(+), 16 deletions(-) diff --git a/.idea/dictionaries/soren.xml b/.idea/dictionaries/soren.xml index b0b4df8f..2fcbda73 100644 --- a/.idea/dictionaries/soren.xml +++ b/.idea/dictionaries/soren.xml @@ -26,6 +26,7 @@ orbot panopticlick redmine + referer relativelayout robinlinus samsung diff --git a/app/build.gradle b/app/build.gradle index ed3da87c..9b770e4e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -55,5 +55,5 @@ dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:design:23.4.0' // Only compile com.google.android.gms:play-services-ads for the free version. - freeCompile 'com.google.android.gms:play-services-ads:9.0.2' + freeCompile 'com.google.android.gms:play-services-ads:9.2.0' } diff --git a/app/src/main/assets/guide_local_storage.html b/app/src/main/assets/guide_local_storage.html index 07a1eeff..ae110a6b 100644 --- a/app/src/main/assets/guide_local_storage.html +++ b/app/src/main/assets/guide_local_storage.html @@ -59,15 +59,15 @@ the ads is loaded from the third-party broker's server instead of the main server.

Because most of the advertisements on the internet are displayed from only a few brokers, it didn't take long for them to realize - that they could set a tracking cookie on the user's device and know every place that user goes. Every time an ad loads from a broker, - the first thing it does it check to see if if the device already has a unique serial number in a tracking cookie. If it does, it looks up - the profile for that serial number and makes a note of the new site. This is why a user can do a search on one website for a + that they could set a tracking cookie on the user's device and know every place that user goes. Every time an ad loads from a broker, + the first thing it does it check to see if if the device already has a unique serial number in a tracking cookie. If it does, it looks up + the profile for that serial number and makes a note of the new site. This is why a user can do a search on one website for a product that they typically don't look for, like walnuts, and then suddenly start seeing advertisements for walnuts on every website they visit.

-

In addition to ad brokers, social media sites discovered they could get in on the action. A few years ago, the major social media sites +

In addition to ad brokers, social media sites discovered they could get in on the action. A few years ago, the major social media sites like Facebook and Twitter convinced a large number of websites that it would be in there best interest to place little social media - icons on their pages. These are not just images. They contain imbedded code that + icons on their pages. These are not just images. They contain imbedded code that links back to the social media site, and, among other things, loads a third-party cookie on the device. These cookies are placed even if the user does not have an account with the social media platform. Over time, companies like Facebook (which also run an ad network) have built up quite a large number of detailed profiles about people who have never even @@ -80,8 +80,14 @@

DOM Storage

-

Document Object Model storage, also known as web storage, is like cookies on steroids. Whereas the maximum combined storage size for all cookies from +

Document Object Model storage, also known as web storage, is like cookies on steroids. Whereas the maximum combined storage size for all cookies from a single URL is 4 kilobytes, DOM storage can hold between 5-25 megabytes per site. Because DOM storage uses JavaScript to read and write data, enabling it will do nothing unless JavaScript is also enabled.

+ + +

Form Data

+ +

Form data contains information typed into web forms, like user names, addresses, phone numbers, etc., and lists them in a drop-down box on future visits. + Unlike the other forms of local storage, form data is not sent to the web server without specific user interaction.

\ No newline at end of file diff --git a/app/src/main/assets/guide_overview.html b/app/src/main/assets/guide_overview.html index 6f7ae182..a1c5701e 100644 --- a/app/src/main/assets/guide_overview.html +++ b/app/src/main/assets/guide_overview.html @@ -41,7 +41,9 @@

WebView Limitations

-

Privacy Browser uses Android's built-in WebView to render websites. There are some limitations in the controls WebView exposes for managing privacy settings. +

Privacy Browser uses Android's built-in WebView to render websites. There are some limitations in the controls WebView exposes for managing privacy settings. For example, + it isn't possible to enable some JavaScript commands while disabling others. It also isn't possible to control the + referer header. Once Privacy Browser has matured to take full advantage of all the privacy options WebView does offer, some consideration might be made to imbedding a customized WebView or using a different rendering engine.

diff --git a/app/src/main/java/com/stoutner/privacybrowser/MainWebViewActivity.java b/app/src/main/java/com/stoutner/privacybrowser/MainWebViewActivity.java index e4e68c36..66fe512e 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/MainWebViewActivity.java +++ b/app/src/main/java/com/stoutner/privacybrowser/MainWebViewActivity.java @@ -53,6 +53,7 @@ import android.webkit.WebChromeClient; import android.webkit.WebStorage; import android.webkit.WebView; import android.webkit.WebViewClient; +import android.webkit.WebViewDatabase; import android.widget.EditText; import android.widget.FrameLayout; import android.widget.ImageView; @@ -82,6 +83,8 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation public static boolean thirdPartyCookiesEnabled; // domStorageEnabled is public static so it can be accessed from SettingsFragment. It is also used in onCreate(), onCreateOptionsMenu(), and onOptionsItemSelected(). public static boolean domStorageEnabled; + // saveFormDataEnabled is public static so it can be accessed from SettingsFragment. It is also used in onCreate(), onCreateOptionsMenu(), and onOptionsItemSelected(). + public static boolean saveFormDataEnabled; // javaScriptDisabledSearchURL is public static so it can be accessed from SettingsFragment. It is also used in onCreate() and loadURLFromTextBox(). public static String javaScriptDisabledSearchURL; // javaScriptEnabledSearchURL is public static so it can be accessed from SettingsFragment. It is also used in onCreate() and loadURLFromTextBox(). @@ -321,6 +324,10 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation domStorageEnabled = savedPreferences.getBoolean("dom_storage_enabled", false); mainWebView.getSettings().setDomStorageEnabled(domStorageEnabled); + // Set the saved form data initial status. The default is false. + saveFormDataEnabled = savedPreferences.getBoolean("save_form_data_enabled", false); + mainWebView.getSettings().setSaveFormData(saveFormDataEnabled); + // Set the user agent initial status. String userAgentString = savedPreferences.getString("user_agent", "Default user agent"); switch (userAgentString) { @@ -427,6 +434,7 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation MenuItem toggleFirstPartyCookies = menu.findItem(R.id.toggleFirstPartyCookies); MenuItem toggleThirdPartyCookies = menu.findItem(R.id.toggleThirdPartyCookies); MenuItem toggleDomStorage = menu.findItem(R.id.toggleDomStorage); + MenuItem toggleSaveFormData = menu.findItem(R.id.toggleSaveFormData); // Set the initial status of the privacy icon. updatePrivacyIcon(); @@ -435,6 +443,7 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation toggleFirstPartyCookies.setChecked(firstPartyCookiesEnabled); toggleThirdPartyCookies.setChecked(thirdPartyCookiesEnabled); toggleDomStorage.setChecked(domStorageEnabled); + toggleSaveFormData.setChecked(saveFormDataEnabled); return true; } @@ -449,13 +458,18 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation toggleThirdPartyCookies.setEnabled(false); } + // Enable DOM Storage if JavaScript is enabled. + MenuItem toggleDomStorage = menu.findItem(R.id.toggleDomStorage); + toggleDomStorage.setEnabled(javaScriptEnabled); + // Enable Clear Cookies if there are any. MenuItem clearCookies = menu.findItem(R.id.clearCookies); clearCookies.setEnabled(cookieManager.hasCookies()); - // Enable DOM Storage if JavaScript is enabled. - MenuItem toggleDomStorage = menu.findItem(R.id.toggleDomStorage); - toggleDomStorage.setEnabled(javaScriptEnabled); + // Enable Clear Form Data is there is any. + MenuItem clearFormData = menu.findItem(R.id.clearFormData); + WebViewDatabase mainWebViewDatabase = WebViewDatabase.getInstance(this); + clearFormData.setEnabled(mainWebViewDatabase.hasFormData()); // Run all the other default commands. super.onPrepareOptionsMenu(menu); @@ -546,6 +560,20 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation mainWebView.reload(); return true; + case R.id.toggleSaveFormData: + // Switch the status of saveFormDataEnabled. + saveFormDataEnabled = !saveFormDataEnabled; + + // Update the menu checkbox. + menuItem.setChecked(saveFormDataEnabled); + + // Apply the new form data status. + mainWebView.getSettings().setSaveFormData(saveFormDataEnabled); + + // Reload the WebView. + mainWebView.reload(); + return true; + case R.id.clearCookies: if (Build.VERSION.SDK_INT < 21) { cookieManager.removeAllCookie(); @@ -561,6 +589,12 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation Snackbar.make(findViewById(R.id.mainWebView), R.string.dom_storage_deleted, Snackbar.LENGTH_SHORT).show(); return true; + case R.id.clearFormData: + WebViewDatabase mainWebViewDatabase = WebViewDatabase.getInstance(this); + mainWebViewDatabase.clearFormData(); + mainWebView.reload(); + return true; + case R.id.share: Intent shareIntent = new Intent(); shareIntent.setAction(Intent.ACTION_SEND); diff --git a/app/src/main/java/com/stoutner/privacybrowser/SettingsFragment.java b/app/src/main/java/com/stoutner/privacybrowser/SettingsFragment.java index 132de65c..2afa9e78 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/SettingsFragment.java +++ b/app/src/main/java/com/stoutner/privacybrowser/SettingsFragment.java @@ -189,6 +189,19 @@ public class SettingsFragment extends PreferenceFragment { updatePrivacyIcon(); break; + case "save_form_data_enabled": + // Set saveFormDataEnabled to the new state. The default is false. + MainWebViewActivity.saveFormDataEnabled = sharedPreferences.getBoolean("save_form_data_enabled", false); + + // Update the checkbox in the options menu. + MenuItem saveFormDataMenuItem = MainWebViewActivity.mainMenu.findItem(R.id.toggleSaveFormData); + saveFormDataMenuItem.setChecked(MainWebViewActivity.saveFormDataEnabled); + + // Update mainWebView and reload the website. + MainWebViewActivity.mainWebView.getSettings().setSaveFormData(MainWebViewActivity.saveFormDataEnabled); + MainWebViewActivity.mainWebView.reload(); + break; + case "user_agent": String userAgentString = sharedPreferences.getString("user_agent", "Default user agent"); diff --git a/app/src/main/res/menu/menu_options.xml b/app/src/main/res/menu/menu_options.xml index 5655644a..d380a060 100644 --- a/app/src/main/res/menu/menu_options.xml +++ b/app/src/main/res/menu/menu_options.xml @@ -51,33 +51,46 @@ android:checkable="true" app:showAsAction="never" /> + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index eaaf2cd7..eabe4beb 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -53,8 +53,10 @@ First-Party Cookies Third-Party Cookies DOM Storage + Form Data Clear Cookies Clear DOM Storage + Clear Form Data Share Add to Home Screen Refresh @@ -82,6 +84,8 @@ This setting requires Android Lollipop (version 5.0) or higher. It has no effect if first-party cookies are disabled. Enable DOM storage by default JavaScript must be enabled for DOM storage to function. + Enable saving of form data by default + Saved form data can auto-populate fields on websites. User agent WebView Default diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index e08c71e5..702db50e 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -47,6 +47,12 @@ android:summary="@string/dom_storage_preference_summary" android:defaultValue="false" /> + +