Expose site-specific settings in CRH dialog. b=380852, r=gavin
authorJohnathan Nightingale <johnath@mozilla.com>
Tue, 20 Jan 2009 10:59:49 -0500
changeset 23972 7b60ede5399de2ad138990b5f1eae6fe06d90dfc
parent 23971 8adfeca108cdad4a94778f84745d49a626946fdf
child 23973 e416d62b69a5565f7f39f5b0f96c457b62fa6e15
push idunknown
push userunknown
push dateunknown
reviewersgavin
bugs380852
milestone1.9.2a1pre
Expose site-specific settings in CRH dialog. b=380852, r=gavin
browser/app/profile/firefox.js
browser/base/content/sanitize.js
browser/base/content/sanitize.xul
browser/base/content/test/Makefile.in
browser/base/content/test/browser_sanitize-sitepermissions.js
browser/base/content/test/browser_sanitize-timespans.js
browser/components/preferences/sanitize.xul
browser/locales/en-US/chrome/browser/sanitize.dtd
toolkit/components/contentprefs/public/nsIContentPrefService.idl
toolkit/components/contentprefs/src/nsContentPrefService.js
toolkit/components/contentprefs/tests/unit/test_contentPrefs.js
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -400,19 +400,19 @@ pref("privacy.popups.firstTime",        
 pref("privacy.popups.showBrowserMessage",   true);
  
 pref("privacy.item.history",     true);
 pref("privacy.item.formdata",    true);
 pref("privacy.item.passwords",   false);
 pref("privacy.item.downloads",   true);
 pref("privacy.item.cookies",     false);
 pref("privacy.item.cache",       true);
-pref("privacy.item.siteprefs",   false);
 pref("privacy.item.sessions",    true);
 pref("privacy.item.offlineApps", false);
+pref("privacy.item.siteSettings", false);
 
 // What default should we use for the time span in the sanitizer:
 // 0 - Clear everything
 // 1 - Last Hour
 // 2 - Last 2 Hours
 // 3 - Last 4 Hours
 // 4 - Today
 pref("privacy.sanitize.timeSpan", 1);
--- a/browser/base/content/sanitize.js
+++ b/browser/base/content/sanitize.js
@@ -332,16 +332,34 @@ Sanitizer.prototype = {
                                 .getService(Components.interfaces.nsIHttpAuthManager);
         authMgr.clearAll();
       },
       
       get canClear()
       {
         return true;
       }
+    },
+    
+    siteSettings: {
+      clear: function ()
+      {
+        var pm = Components.classes["@mozilla.org/permissionmanager;1"]
+                          .getService(Components.interfaces.nsIPermissionManager);
+        pm.removeAll();
+        
+        var cps = Components.classes["@mozilla.org/content-pref/service;1"]
+                           .getService(Components.interfaces.nsIContentPrefService);
+        cps.removeGroupedPrefs();
+      },
+      
+      get canClear()
+      {
+        return true;
+      }
     }
   }
 };
 
 
 
 // "Static" members
 Sanitizer.prefDomain          = "privacy.sanitize.";
--- a/browser/base/content/sanitize.xul
+++ b/browser/base/content/sanitize.xul
@@ -182,16 +182,17 @@
       <preference id="privacy.cpd.history"               name="privacy.cpd.history"               type="bool"/>
       <preference id="privacy.cpd.formdata"              name="privacy.cpd.formdata"              type="bool"/>
       <preference id="privacy.cpd.passwords"             name="privacy.cpd.passwords"             type="bool"/>
       <preference id="privacy.cpd.downloads"             name="privacy.cpd.downloads"             type="bool"/>
       <preference id="privacy.cpd.cookies"               name="privacy.cpd.cookies"               type="bool"/>
       <preference id="privacy.cpd.cache"                 name="privacy.cpd.cache"                 type="bool"/>
       <preference id="privacy.cpd.offlineApps"           name="privacy.cpd.offlineApps"           type="bool"/>
       <preference id="privacy.cpd.sessions"              name="privacy.cpd.sessions"              type="bool"/>
+      <preference id="privacy.cpd.siteSettings"          name="privacy.cpd.siteSettings"          type="bool"/>
     </preferences>
     
     <preferences id="nonItemPreferences">
       <preference id="privacy.sanitize.timeSpan"
                   name="privacy.sanitize.timeSpan"
                   type="int"/>
     </preferences>
 
@@ -249,16 +250,20 @@
     </groupbox>
     <groupbox orient="horizontal">
       <caption label="&dataSection.label;"/>
       <vbox style="width: &column.width;">
         <checkbox label="&itemPasswords.label;"
                   accesskey="&itemPasswords.accesskey;"
                   preference="privacy.cpd.passwords"
                   onsyncfrompreference="return gSanitizePromptDialog.onReadGeneric();"/>
+        <checkbox label="&itemSiteSettings.label;"
+                  accesskey="&itemSiteSettings.accesskey;"
+                  preference="privacy.cpd.siteSettings"
+                  onsyncfrompreference="return gSanitizePromptDialog.onReadGeneric();"/>
       </vbox>
       <vbox style="width: &column.width;">
         <checkbox label="&itemOfflineApps.label;"
                   accesskey="&itemOfflineApps.accesskey;"
                   preference="privacy.cpd.offlineApps"
                   onsyncfrompreference="return gSanitizePromptDialog.onReadGeneric();"/>
       </vbox>
     </groupbox>
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -81,16 +81,17 @@ include $(topsrcdir)/config/rules.mk
                  plugin_both2.html \
                  browser_alltabslistener.js \
                  alltabslistener.html \
                  zoom_test.html \
                  browser_bug416661.js \
                  browser_bug386835.js \
                  bug386835.html \
                  browser_bug422590.js \
+                 browser_sanitize-sitepermissions.js \
     $(NULL)
 
 ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
 _BROWSER_FILES += browser_customize.js \
     $(NULL)
 endif
 
 libs:: $(_TEST_FILES)
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_sanitize-sitepermissions.js
@@ -0,0 +1,43 @@
+// Bug 380852 - Delete permission manager entries in Clear Recent History
+
+Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Components.interfaces.mozIJSSubScriptLoader)
+                                           .loadSubScript("chrome://browser/content/sanitize.js");
+
+function test() {
+  
+  // Add a permission entry
+  var pm = Components.classes["@mozilla.org/permissionmanager;1"]
+                    .getService(Components.interfaces.nsIPermissionManager);
+  pm.add(uri("http://example.com"), "testing", Ci.nsIPermissionManager.ALLOW_ACTION);
+  
+  // Sanity check
+  ok(pm.enumerator.hasMoreElements(), "Permission manager should have elements, since we just added one");
+  
+  // Set up the sanitizer to just clear siteSettings
+  let s = new Sanitizer();
+  s.ignoreTimespan = false;
+  s.prefDomain = "privacy.cpd.";
+  var itemPrefs = Cc["@mozilla.org/preferences-service;1"]
+                  .getService(Components.interfaces.nsIPrefService)
+                  .getBranch(s.prefDomain);
+  itemPrefs.setBoolPref("history", false);
+  itemPrefs.setBoolPref("downloads", false);
+  itemPrefs.setBoolPref("cache", false);
+  itemPrefs.setBoolPref("cookies", false);
+  itemPrefs.setBoolPref("formdata", false);
+  itemPrefs.setBoolPref("offlineApps", false);
+  itemPrefs.setBoolPref("passwords", false);
+  itemPrefs.setBoolPref("sessions", false);
+  itemPrefs.setBoolPref("siteSettings", true);
+  
+  // Clear it
+  s.sanitize();
+  
+  // Make sure it's gone
+  ok(!pm.enumerator.hasMoreElements(), "Permission manager shouldn't have entries after Sanitizing");
+}
+
+function uri(spec) {
+  return Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService)
+                                                .newURI(spec, null, null);
+}
--- a/browser/base/content/test/browser_sanitize-timespans.js
+++ b/browser/base/content/test/browser_sanitize-timespans.js
@@ -29,17 +29,17 @@ function test() {
   itemPrefs.setBoolPref("history", true);
   itemPrefs.setBoolPref("downloads", true);
   itemPrefs.setBoolPref("cache", false);
   itemPrefs.setBoolPref("cookies", false);
   itemPrefs.setBoolPref("formdata", true);
   itemPrefs.setBoolPref("offlineApps", false);
   itemPrefs.setBoolPref("passwords", false);
   itemPrefs.setBoolPref("sessions", false);
-  itemPrefs.setBoolPref("siteprefs", false);
+  itemPrefs.setBoolPref("siteSettings", false);
   
   // Clear 1 hour
   Sanitizer.prefs.setIntPref("timeSpan", 1);
   s.sanitize();
   
   ok(!bhist.isVisited(uri("http://1hour.com")), "1hour.com should now be deleted");
   ok(bhist.isVisited(uri("http://2hour.com")), "Pretend visit to 2hour.com should still exist");
   ok(bhist.isVisited(uri("http://4hour.com")), "Pretend visit to 4hour.com should still exist");
--- a/browser/components/preferences/sanitize.xul
+++ b/browser/components/preferences/sanitize.xul
@@ -63,16 +63,17 @@
       <preference id="privacy.item.history"               name="privacy.item.history"               type="bool"/>
       <preference id="privacy.item.formdata"              name="privacy.item.formdata"              type="bool"/>
       <preference id="privacy.item.passwords"             name="privacy.item.passwords"             type="bool"/>
       <preference id="privacy.item.downloads"             name="privacy.item.downloads"             type="bool"/>
       <preference id="privacy.item.cookies"               name="privacy.item.cookies"               type="bool"/>
       <preference id="privacy.item.cache"                 name="privacy.item.cache"                 type="bool"/>
       <preference id="privacy.item.offlineApps"           name="privacy.item.offlineApps"           type="bool"/>
       <preference id="privacy.item.sessions"              name="privacy.item.sessions"              type="bool"/>
+      <preference id="privacy.item.siteSettings"          name="privacy.item.siteSettings"          type="bool"/>
     </preferences>
 
     <description>&clearDataSettings2.label;</description>
 
     <groupbox orient="horizontal">
       <caption label="&historySection.label;"/>
       <vbox style="width: &column.width;">
         <checkbox label="&itemVisitedPages.label;"
@@ -98,16 +99,19 @@
       </vbox>
     </groupbox>
     <groupbox orient="horizontal">
       <caption label="&dataSection.label;"/>
       <vbox style="width: &column.width;">
         <checkbox label="&itemPasswords.label;"
                   accesskey="&itemPasswords.accesskey;"
                   preference="privacy.item.passwords"/>
+        <checkbox label="&itemSiteSettings.label;"
+                  accesskey="&itemSiteSettings.accesskey;"
+                  preference="privacy.item.siteSettings"/>
       </vbox>
       <vbox style="width: &column.width;">
         <checkbox label="&itemOfflineApps.label;"
                   accesskey="&itemOfflineApps.accesskey;"
                   preference="privacy.item.offlineApps"/>
       </vbox>
     </groupbox>
   </prefpane>
--- a/browser/locales/en-US/chrome/browser/sanitize.dtd
+++ b/browser/locales/en-US/chrome/browser/sanitize.dtd
@@ -31,11 +31,13 @@ that require it.  -->
 <!ENTITY itemWebCache.label           "Web Cache">
 <!ENTITY itemWebCache.accesskey       "W">
 <!ENTITY itemOfflineApps.label        "Offline Website Data">
 <!ENTITY itemOfflineApps.accesskey    "O">
 <!ENTITY itemDownloadList.label       "Download List">
 <!ENTITY itemDownloadList.accesskey   "D">
 <!ENTITY itemActiveLogins.label       "Active Logins">
 <!ENTITY itemActiveLogins.accesskey   "L">
+<!ENTITY itemSiteSettings.label       "Site-specific Settings">
+<!ENTITY itemSiteSettings.accesskey   "S">
 
 <!ENTITY window.width                 "30em">
 <!ENTITY column.width                 "14em">
--- a/toolkit/components/contentprefs/public/nsIContentPrefService.idl
+++ b/toolkit/components/contentprefs/public/nsIContentPrefService.idl
@@ -60,17 +60,17 @@ interface nsIContentPrefObserver : nsISu
    * 
    * @param    aGroup      the group to which the pref belongs, or null
    *                       if it's a global pref (applies to all URIs)
    * @param    aName       the name of the pref that was removed
    */
   void onContentPrefRemoved(in AString aGroup, in AString aName);
 };
 
-[scriptable, uuid(72c05ba2-9d92-4661-b053-f8f869973e6a)]
+[scriptable, uuid(5047e359-dfda-4858-abec-d145c7463250)]
 interface nsIContentPrefService : nsISupports
 {
   /**
    * Get a pref.
    *
    * Besides the regular string, integer, boolean, etc. values, this method
    * may return null (nsIDataType::VTYPE_EMPTY), which means the pref is set
    * to NULL in the database, as well as undefined (nsIDataType::VTYPE_VOID),
@@ -106,16 +106,22 @@ interface nsIContentPrefService : nsISup
    * Remove a pref.
    *
    * @param    aURI        the URI for which to remove the pref
    * @param    aName       the name of the pref to remove
    */
   void removePref(in nsIURI aURI, in AString aName);
 
   /**
+   * Remove all grouped prefs.  Useful for removing references to the sites
+   * the user has visited when the user clears their private data.
+   */
+  void removeGroupedPrefs();
+
+  /**
    * Get the prefs that apply to the given URI.
    *
    * @param    aURI        the URI for which to retrieve prefs
    * 
    * @returns  a property bag of prefs
    */
   nsIPropertyBag2 getPrefs(in nsIURI aURI);
   
--- a/toolkit/components/contentprefs/src/nsContentPrefService.js
+++ b/toolkit/components/contentprefs/src/nsContentPrefService.js
@@ -220,16 +220,29 @@ ContentPrefService.prototype = {
         observer.onContentPrefRemoved(group, aName);
       }
       catch(ex) {
         Cu.reportError(ex);
       }
     }
   },
 
+  removeGroupedPrefs: function ContentPrefService_removeGroupedPrefs() {
+    this._dbConnection.beginTransaction();
+    try {
+      this._dbConnection.executeSimpleSQL("DELETE FROM prefs WHERE groupID IS NOT NULL");
+      this._dbConnection.executeSimpleSQL("DELETE FROM groups");
+      this._dbConnection.commitTransaction();
+    }
+    catch(ex) {
+      this._dbConnection.rollbackTransaction();
+      throw ex;
+    }
+  },
+
   getPrefs: function ContentPrefService_getPrefs(aURI) {
     if (aURI) {
       var group = this.grouper.group(aURI);
       return this._selectPrefs(group);
     }
 
     return this._selectGlobalPrefs();
   },
--- a/toolkit/components/contentprefs/tests/unit/test_contentPrefs.js
+++ b/toolkit/components/contentprefs/tests/unit/test_contentPrefs.js
@@ -342,9 +342,64 @@ function run_test() {
   cps.removeObserver("test.observer.1", specificObserver);
   cps.removeObserver(null, genericObserver);
   cps.setPref(uri, "test.observer.1", "test value");
   cps.removePref(uri, "test.observer.1", "test value");
   do_check_eq(specificObserver.numTimesSetCalled, 1);
   do_check_eq(genericObserver.numTimesSetCalled, 2);
   do_check_eq(specificObserver.numTimesRemovedCalled, 1);
   do_check_eq(genericObserver.numTimesRemovedCalled, 2);
+
+
+  //**************************************************************************//
+  // Clear Private Data Pref Removal
+
+  {
+    let uri1 = ContentPrefTest.getURI("http://www.domain1.com/");
+    let uri2 = ContentPrefTest.getURI("http://www.domain2.com/");
+    let uri3 = ContentPrefTest.getURI("http://www.domain3.com/");
+
+    let dbConnection = cps.DBConnection;
+
+    let prefCount = Cc["@mozilla.org/storage/statement-wrapper;1"].
+                    createInstance(Ci.mozIStorageStatementWrapper);
+    prefCount.initialize(dbConnection.createStatement("SELECT COUNT(*) AS count FROM prefs"));
+
+    let groupCount = Cc["@mozilla.org/storage/statement-wrapper;1"].
+                     createInstance(Ci.mozIStorageStatementWrapper);
+    groupCount.initialize(dbConnection.createStatement("SELECT COUNT(*) AS count FROM groups"));
+
+    // Add some prefs for multiple domains.
+    cps.setPref(uri1, "test.removeAllGroups", 1);
+    cps.setPref(uri2, "test.removeAllGroups", 2);
+    cps.setPref(uri3, "test.removeAllGroups", 3);
+
+    // Add a global pref.
+    cps.setPref(null, "test.removeAllGroups", 1);
+
+    // Make sure there are some prefs and groups in the database.
+    prefCount.step();
+    do_check_true(prefCount.row.count > 0);
+    prefCount.reset();
+    groupCount.step();
+    do_check_true(groupCount.row.count > 0);
+    groupCount.reset();
+
+    // Remove all prefs and groups from the database using the same routine
+    // the Clear Private Data dialog uses.
+    cps.removeGroupedPrefs();
+
+    // Make sure there are no longer any groups in the database and the only pref
+    // is the global one.
+    prefCount.step();
+    do_check_true(prefCount.row.count == 1);
+    prefCount.reset();
+    groupCount.step();
+    do_check_true(groupCount.row.count == 0);
+    groupCount.reset();
+    let globalPref = Cc["@mozilla.org/storage/statement-wrapper;1"].
+                     createInstance(Ci.mozIStorageStatementWrapper);
+    globalPref.initialize(dbConnection.createStatement("SELECT groupID FROM prefs"));
+    globalPref.step();
+    do_check_true(globalPref.row.groupID == null);
+    globalPref.reset();
+  }
 }