Bug 762064 - Part 2: Enable clearing individual privacy items. r=mfinkle
authorBrian Nicholson <bnicholson@mozilla.com>
Tue, 26 Jun 2012 23:15:24 -0700
changeset 100477 03cd608177cc216c3af3c73cfeda9527903880bd
parent 100476 f3c2734016bda42fac2199de8aa19ba47cf08dd3
child 100478 dfced0e2fdaf01caba89de29aa8c3f3d101e2d7f
push idunknown
push userunknown
push dateunknown
reviewersmfinkle
bugs762064
milestone16.0a1
Bug 762064 - Part 2: Enable clearing individual privacy items. r=mfinkle
mobile/android/base/ConfirmPreference.java
mobile/android/base/Makefile.in
mobile/android/base/PrivateDataPreference.java
mobile/android/base/locales/en-US/android_strings.dtd
mobile/android/base/resources/values/arrays.xml
mobile/android/base/resources/xml/preferences.xml.in
mobile/android/base/strings.xml.in
mobile/android/chrome/content/browser.js
deleted file mode 100644
--- a/mobile/android/base/ConfirmPreference.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko;
-
-import org.mozilla.gecko.db.BrowserDB;
-
-import android.content.Context;
-import android.preference.DialogPreference;
-import android.util.AttributeSet;
-import android.util.Log;
-
-class ConfirmPreference extends DialogPreference {
-    private static final String LOGTAG = "GeckoConfirmPreference";
-
-    private String mAction = null;
-    private Context mContext = null;
-    public ConfirmPreference(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        mAction = attrs.getAttributeValue(null, "action");
-        mContext = context;
-    }
-    public ConfirmPreference(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-        mAction = attrs.getAttributeValue(null, "action");
-        mContext = context;
-    }
-    protected void onDialogClosed(boolean positiveResult) {
-        if (!positiveResult)
-            return;
-        if ("clear_history".equalsIgnoreCase(mAction)) {
-            GeckoAppShell.getHandler().post(new Runnable(){
-                public void run() {
-                    BrowserDB.clearHistory(mContext.getContentResolver());
-                    GeckoApp.mAppContext.mFavicons.clearFavicons();
-                    GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("browser:purge-session-history", null));
-                    GeckoApp.mAppContext.handleClearHistory();
-                }
-            });
-        } else if ("clear_private_data".equalsIgnoreCase(mAction)) {
-            GeckoAppShell.getHandler().post(new Runnable(){
-                public void run() {
-                    GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Sanitize:ClearAll", null));
-                }
-            });
-        }
-        Log.i(LOGTAG, "action: " + mAction);
-    }
-}
--- a/mobile/android/base/Makefile.in
+++ b/mobile/android/base/Makefile.in
@@ -25,17 +25,16 @@ FENNEC_JAVA_FILES = \
   AboutHomeSection.java \
   AndroidImport.java \
   AndroidImportPreference.java \
   AlertNotification.java \
   AwesomeBar.java \
   AwesomeBarTabs.java \
   BrowserApp.java \
   BrowserToolbar.java \
-  ConfirmPreference.java \
   SyncPreference.java \
   db/AndroidBrowserDB.java \
   db/BrowserDB.java \
   db/LocalBrowserDB.java \
   db/DBUtils.java \
   DoorHanger.java \
   DoorHangerPopup.java \
   Favicons.java \
@@ -68,16 +67,17 @@ FENNEC_JAVA_FILES = \
   INIParser.java \
   INISection.java \
   LinkPreference.java \
   LinkTextView.java \
   MenuItemActionBar.java \
   MenuItemDefault.java \
   MultiChoicePreference.java \
   NSSBridge.java \
+  PrivateDataPreference.java \
   PropertyAnimator.java \
   ProfileMigrator.java \
   PromptService.java \
   sqlite/ByteBufferInputStream.java \
   sqlite/MatrixBlobCursor.java \
   sqlite/SQLiteBridge.java \
   sqlite/SQLiteBridgeException.java \
   RemoteTabs.java \
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/PrivateDataPreference.java
@@ -0,0 +1,72 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.gecko;
+
+import org.mozilla.gecko.db.BrowserDB;
+
+import org.json.JSONObject;
+import org.json.JSONException;
+
+import java.util.Map;
+
+import android.app.AlertDialog.Builder;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.util.AttributeSet;
+import android.util.Log;
+
+class PrivateDataPreference extends MultiChoicePreference {
+    private static final String LOGTAG = "GeckoPrivateDataPreference";
+    private static final String PREF_KEY_PREFIX = "private.data.";
+
+    private Context mContext;
+
+    public PrivateDataPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mContext = context;
+    }
+
+    @Override
+    protected void onDialogClosed(boolean positiveResult) {
+        super.onDialogClosed(positiveResult);
+
+        if (!positiveResult)
+            return;
+
+        CharSequence keys[] = getEntryKeys();
+        boolean values[] = getValues();
+        JSONObject json = new JSONObject();
+
+        for (int i = 0; i < keys.length; i++) {
+            // Privacy pref checkbox values are stored in Android prefs to
+            // remember their check states. The key names are private.data.X,
+            // where X is a string from Gecko sanitization. This prefix is
+            // removed here so we can send the values to Gecko, which then does
+            // the sanitization for each key.
+            String key = keys[i].toString().substring(PREF_KEY_PREFIX.length());
+            boolean value = values[i];
+            try {
+                json.put(key, value);
+            } catch (JSONException e) {
+                Log.e(LOGTAG, "JSON error", e);
+            }
+
+            // clear private data in java
+            if (key.equals("history") && value) {
+                GeckoAppShell.getHandler().post(new Runnable() {
+                    public void run() {
+                        BrowserDB.clearHistory(mContext.getContentResolver());
+                        GeckoApp.mAppContext.mFavicons.clearFavicons();
+                        GeckoApp.mAppContext.handleClearHistory();
+                    }
+                });
+            }
+        }
+
+        // clear private data in gecko
+        GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Sanitize:ClearData", json.toString()));
+    }
+}
--- a/mobile/android/base/locales/en-US/android_strings.dtd
+++ b/mobile/android/base/locales/en-US/android_strings.dtd
@@ -68,34 +68,38 @@
 <!ENTITY pref_about_firefox "About &brandShortName;">
 <!ENTITY pref_do_not_track "Tell sites not to track me">
 <!ENTITY pref_telemetry "Send performance data">
 <!ENTITY pref_remember_signons "Remember passwords">
 <!ENTITY pref_cookies "Enable cookies">
 <!ENTITY pref_char_encoding "Character encoding">
 <!ENTITY pref_char_encoding_on "Show menu">
 <!ENTITY pref_char_encoding_off "Don\'t show menu">
-<!ENTITY pref_clear_history "Clear history">
-<!ENTITY pref_clear_history_confirm "Browsing history will be deleted">
 <!ENTITY pref_clear_private_data "Clear private data">
-<!ENTITY pref_clear_private_data_confirm "Browsing settings, including passwords and cookies, will be deleted">
 <!ENTITY pref_plugins "Plugins">
 <!ENTITY pref_plugins_enabled "Enabled">
 <!ENTITY pref_plugins_tap_to_play "Tap to play">
 <!ENTITY pref_plugins_disabled "Disabled">
 <!ENTITY pref_text_size "Text size">
 <!ENTITY pref_font_size_tiny "Tiny">
 <!ENTITY pref_font_size_small "Small">
 <!ENTITY pref_font_size_medium "Medium">
 <!ENTITY pref_font_size_large "Large">
 <!ENTITY pref_font_size_xlarge "Extra Large">
 <!ENTITY pref_use_master_password "Use master password">
 <!ENTITY pref_sync "Sync">
 <!ENTITY pref_search_suggestions "Show search suggestions">
 <!ENTITY pref_import_android "Import from Android">
+<!ENTITY pref_private_data_history "Browsing &amp; download history">
+<!ENTITY pref_private_data_formdata "Form &amp; search history">
+<!ENTITY pref_private_data_cookies "Cookies">
+<!ENTITY pref_private_data_cache "Cache">
+<!ENTITY pref_private_data_sessions "Active logins">
+<!ENTITY pref_private_data_offlineApps "Offline website data">
+<!ENTITY pref_private_data_siteSettings "Site preferences">
 
 <!ENTITY quit "Quit">
 
 <!ENTITY addons "Add-ons">
 <!ENTITY downloads "Downloads">
 <!ENTITY apps "Apps">
 <!ENTITY char_encoding "Character Encoding">
 
@@ -144,16 +148,17 @@
 
 <!ENTITY masterpassword_create_title "Create Master Password">
 <!ENTITY masterpassword_remove_title "Remove Master Password">
 <!ENTITY masterpassword_password "Password">
 <!ENTITY masterpassword_confirm "Confirm password">
 
 <!ENTITY button_ok "OK">
 <!ENTITY button_cancel "Cancel">
+<!ENTITY button_clear_data "Clear data">
 
 <!ENTITY abouthome_addons_title "Add-ons for your &brandShortName;">
 <!ENTITY abouthome_addons_browse "Browse all &brandShortName; add-ons">
 <!ENTITY abouthome_last_tabs_title "Your tabs from last time">
 <!ENTITY abouthome_last_tabs_open "Open all tabs from last time">
 <!ENTITY abouthome_top_sites_title "Top sites">
 <!ENTITY abouthome_top_sites_browse "Browse all your top sites">
 <!ENTITY abouthome_no_top_sites "You do not have any top sites yet. Tap the Title Bar to start browsing.">
--- a/mobile/android/base/resources/values/arrays.xml
+++ b/mobile/android/base/resources/values/arrays.xml
@@ -36,9 +36,36 @@
     <string-array name="pref_char_encoding_values">
         <item>true</item>
         <item>false</item>
     </string-array>
     <string-array name="pref_android_import_select">
         <item>@string/awesomebar_bookmarks_title</item>
         <item>@string/awesomebar_history_title</item>
     </string-array>
+    <string-array name="pref_private_data_entries">
+        <item>@string/pref_private_data_history</item>
+        <item>@string/pref_private_data_formdata</item>
+        <item>@string/pref_private_data_cookies</item>
+        <item>@string/pref_private_data_cache</item>
+        <item>@string/pref_private_data_sessions</item>
+        <item>@string/pref_private_data_offlineApps</item>
+        <item>@string/pref_private_data_siteSettings</item>
+    </string-array>
+    <string-array name="pref_private_data_values">
+        <item>true</item>
+        <item>true</item>
+        <item>true</item>
+        <item>true</item>
+        <item>true</item>
+        <item>true</item>
+        <item>true</item>
+    </string-array>
+    <string-array name="pref_private_data_keys">
+        <item>private.data.history</item>
+        <item>private.data.formdata</item>
+        <item>private.data.cookies</item>
+        <item>private.data.cache</item>
+        <item>private.data.sessions</item>
+        <item>private.data.offlineApps</item>
+        <item>private.data.siteSettings</item>
+    </string-array>
 </resources>
--- a/mobile/android/base/resources/xml/preferences.xml.in
+++ b/mobile/android/base/resources/xml/preferences.xml.in
@@ -1,16 +1,18 @@
+#filter substitution
 <?xml version="1.0" encoding="utf-8"?>
 <!-- This Source Code Form is subject to the terms of the Mozilla Public
    - License, v. 2.0. If a copy of the MPL was not distributed with this
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 
 
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
-                        android:enabled="false">
+                  xmlns:gecko="http://schemas.android.com/apk/res/@ANDROID_PACKAGE_NAME@"
+                  android:enabled="false">
 
     <PreferenceCategory android:title="@string/pref_category_general">
         <org.mozilla.gecko.LinkPreference android:title="@string/pref_about_firefox"
                                           url="about:" />
 
         <org.mozilla.gecko.SyncPreference android:title="@string/pref_sync"
                                           android:persistent="false" />
 
@@ -35,27 +37,22 @@
                             android:entries="@array/pref_font_size_entries"
                             android:entryValues="@array/pref_font_size_values"
                             android:persistent="false" />
 
     </PreferenceCategory>
 
     <PreferenceCategory android:title="@string/pref_category_privacy">
 
-        <org.mozilla.gecko.ConfirmPreference android:title="@string/pref_clear_history"
-                                             android:dialogMessage="@string/pref_clear_history_confirm"
-                                             android:positiveButtonText="@android:string/yes"
-                                             android:negativeButtonText="@android:string/no"
-                                             action="clear_history" />
-
-        <org.mozilla.gecko.ConfirmPreference android:title="@string/pref_clear_private_data"
-                                             android:dialogMessage="@string/pref_clear_private_data_confirm"
-                                             android:positiveButtonText="@android:string/yes"
-                                             android:negativeButtonText="@android:string/no"
-                                             action="clear_private_data" />
+        <org.mozilla.gecko.PrivateDataPreference android:title="@string/pref_clear_private_data"
+                                                 android:persistent="true"
+                                                 android:positiveButtonText="@string/button_clear_data"
+                                                 gecko:entries="@array/pref_private_data_entries"
+                                                 gecko:entryKeys="@array/pref_private_data_keys"
+                                                 gecko:initialValues="@array/pref_private_data_values" />
 
         <CheckBoxPreference android:key="privacy.donottrackheader.enabled"
                             android:title="@string/pref_do_not_track"
                             android:defaultValue="false"
                             android:persistent="false" />
 
         <CheckBoxPreference android:key="signon.rememberSignons"
                             android:title="@string/pref_remember_signons"
--- a/mobile/android/base/strings.xml.in
+++ b/mobile/android/base/strings.xml.in
@@ -74,32 +74,36 @@
   <string name="pref_about_firefox">&pref_about_firefox;</string>
   <string name="pref_do_not_track">&pref_do_not_track;</string>
   <string name="pref_telemetry">&pref_telemetry;</string>
   <string name="pref_remember_signons">&pref_remember_signons;</string>
   <string name="pref_cookies">&pref_cookies;</string>
   <string name="pref_char_encoding">&pref_char_encoding;</string>
   <string name="pref_char_encoding_on">&pref_char_encoding_on;</string>
   <string name="pref_char_encoding_off">&pref_char_encoding_off;</string>
-  <string name="pref_clear_history">&pref_clear_history;</string>
-  <string name="pref_clear_history_confirm">&pref_clear_history_confirm;</string>
   <string name="pref_clear_private_data">&pref_clear_private_data;</string>
-  <string name="pref_clear_private_data_confirm">&pref_clear_private_data_confirm;</string>
   <string name="pref_plugins">&pref_plugins;</string>
   <string name="pref_plugins_enabled">&pref_plugins_enabled;</string>
   <string name="pref_plugins_tap_to_play">&pref_plugins_tap_to_play;</string>
   <string name="pref_plugins_disabled">&pref_plugins_disabled;</string>
   <string name="pref_text_size">&pref_text_size;</string>
   <string name="pref_font_size_tiny">&pref_font_size_tiny;</string>
   <string name="pref_font_size_small">&pref_font_size_small;</string>
   <string name="pref_font_size_medium">&pref_font_size_medium;</string>
   <string name="pref_font_size_large">&pref_font_size_large;</string>
   <string name="pref_font_size_xlarge">&pref_font_size_xlarge;</string>
   <string name="pref_sync">&pref_sync;</string>
   <string name="pref_search_suggestions">&pref_search_suggestions;</string>
+  <string name="pref_private_data_history">&pref_private_data_history;</string>
+  <string name="pref_private_data_formdata">&pref_private_data_formdata;</string>
+  <string name="pref_private_data_cookies">&pref_private_data_cookies;</string>
+  <string name="pref_private_data_cache">&pref_private_data_cache;</string>
+  <string name="pref_private_data_sessions">&pref_private_data_sessions;</string>
+  <string name="pref_private_data_offlineApps">&pref_private_data_offlineApps;</string>
+  <string name="pref_private_data_siteSettings">&pref_private_data_siteSettings;</string>
   <string name="pref_import_android">&pref_import_android;</string>
 
   <string name="reload">&reload;</string>
   <string name="forward">&forward;</string>
   <string name="menu">&menu;</string>
   <string name="back">&back;</string>
   <string name="stop">&stop;</string>
   <string name="site_security">&site_security;</string>
@@ -146,16 +150,17 @@
   <string name="pref_use_master_password">&pref_use_master_password;</string>
   <string name="masterpassword_create_title">&masterpassword_create_title;</string>
   <string name="masterpassword_remove_title">&masterpassword_remove_title;</string>
   <string name="masterpassword_password">&masterpassword_password;</string>
   <string name="masterpassword_confirm">&masterpassword_confirm;</string>
 
   <string name="button_ok">&button_ok;</string>
   <string name="button_cancel">&button_cancel;</string>
+  <string name="button_clear_data">&button_clear_data;</string>
 
   <string name="abouthome_addons_title">&abouthome_addons_title;</string>
   <string name="abouthome_addons_browse">&abouthome_addons_browse;</string>
   <string name="abouthome_last_tabs_title">&abouthome_last_tabs_title;</string>
   <string name="abouthome_last_tabs_open">&abouthome_last_tabs_open;</string>
   <string name="abouthome_top_sites_title">&abouthome_top_sites_title;</string>
   <string name="abouthome_top_sites_browse">&abouthome_top_sites_browse;</string>
   <string name="abouthome_no_top_sites">&abouthome_no_top_sites;</string>
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -149,17 +149,17 @@ var BrowserApp = {
     Services.obs.addObserver(this, "Session:Forward", false);
     Services.obs.addObserver(this, "Session:Reload", false);
     Services.obs.addObserver(this, "Session:Stop", false);
     Services.obs.addObserver(this, "SaveAs:PDF", false);
     Services.obs.addObserver(this, "Browser:Quit", false);
     Services.obs.addObserver(this, "Preferences:Get", false);
     Services.obs.addObserver(this, "Preferences:Set", false);
     Services.obs.addObserver(this, "ScrollTo:FocusedInput", false);
-    Services.obs.addObserver(this, "Sanitize:ClearAll", false);
+    Services.obs.addObserver(this, "Sanitize:ClearData", false);
     Services.obs.addObserver(this, "PanZoom:PanZoom", false);
     Services.obs.addObserver(this, "FullScreen:Exit", false);
     Services.obs.addObserver(this, "Viewport:Change", false);
     Services.obs.addObserver(this, "Passwords:Init", false);
     Services.obs.addObserver(this, "FormHistory:Init", false);
     Services.obs.addObserver(this, "ToggleProfiling", false);
 
     Services.obs.addObserver(this, "sessionstore-state-purge-complete", false);
@@ -775,16 +775,32 @@ var BrowserApp = {
       Services.prefs.setIntPref(json.name, json.value);
     } else {
       let pref = Cc["@mozilla.org/pref-localizedstring;1"].createInstance(Ci.nsIPrefLocalizedString);
       pref.data = json.value;
       Services.prefs.setComplexValue(json.name, Ci.nsISupportsString, pref);
     }
   },
 
+  sanitize: function (aItems) {
+    let sanitizer = new Sanitizer();
+    let json = JSON.parse(aItems);
+
+    for (let key in json) {
+      if (!json[key])
+        continue;
+
+      try {
+        sanitizer.clearItem(key);
+      } catch (e) {
+        dump("sanitize error: " + e);
+      }
+    }
+  },
+
   scrollToFocusedInput: function(aBrowser) {
     let doc = aBrowser.contentDocument;
     if (!doc)
       return;
 
     let focused = doc.activeElement;
     if ((focused instanceof HTMLInputElement && focused.mozIsTextField(false)) || (focused instanceof HTMLTextAreaElement)) {
       let tab = BrowserApp.getTabForBrowser(aBrowser);
@@ -891,18 +907,18 @@ var BrowserApp = {
     } else if (aTopic == "SaveAs:PDF") {
       this.saveAsPDF(browser);
     } else if (aTopic == "Preferences:Get") {
       this.getPreferences(aData);
     } else if (aTopic == "Preferences:Set") {
       this.setPreferences(aData);
     } else if (aTopic == "ScrollTo:FocusedInput") {
       this.scrollToFocusedInput(browser);
-    } else if (aTopic == "Sanitize:ClearAll") {
-      Sanitizer.sanitize();
+    } else if (aTopic == "Sanitize:ClearData") {
+      this.sanitize(aData);
     } else if (aTopic == "FullScreen:Exit") {
       browser.contentDocument.mozCancelFullScreen();
     } else if (aTopic == "Viewport:Change") {
       if (this.isBrowserContentDocumentDisplayed())
         this.selectedTab.setViewport(JSON.parse(aData));
     } else if (aTopic == "Passwords:Init") {
       let storage = Components.classes["@mozilla.org/login-manager/storage/mozStorage;1"].
         getService(Components.interfaces.nsILoginManagerStorage);