Bug 974295 - Replacement for getPrefsByName in nsIContentPrefService2; r=adw
authorGeoff Lankow <geoff@darktrojan.net>
Sat, 22 Feb 2014 16:50:53 +1300
changeset 170397 9b59ba1ae73e3714629c6aef9c4fe3e80ca1df1a
parent 170396 ea62c234c00254a96c5418abd116881a7f0a1f13
child 170398 c91a96c71e6206340c2f3390ccff4faea0c68782
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
reviewersadw
bugs974295
milestone30.0a1
Bug 974295 - Replacement for getPrefsByName in nsIContentPrefService2; r=adw
dom/interfaces/base/nsIContentPrefService2.idl
toolkit/components/contentprefs/ContentPrefService2.jsm
toolkit/components/contentprefs/tests/unit_cps2/test_setGet.js
--- a/dom/interfaces/base/nsIContentPrefService2.idl
+++ b/dom/interfaces/base/nsIContentPrefService2.idl
@@ -62,20 +62,33 @@ interface nsIContentPref;
  * The methods of callback objects are always called asynchronously.
  *
  * Observers are called after callbacks are called, but they are called in the
  * same turn of the event loop as callbacks.
  *
  * See nsIContentPrefCallback2 below for more information about callbacks.
  */
 
-[scriptable, uuid(86279644-6b86-4875-a228-2d2ff2f3e33b)]
+[scriptable, uuid(f2507add-dc39-48e0-9147-e0270376148b)]
 interface nsIContentPrefService2 : nsISupports
 {
   /**
+   * Gets all the preferences with the given name.
+   *
+   * @param name      The preferences' name.
+   * @param context   The private-browsing context, if any.
+   * @param callback  handleResult is called once for each preference unless
+   *                  no such preferences exist, in which case handleResult
+   *                  is not called at all.
+   */
+  void getByName(in AString name,
+                 in nsILoadContext context,
+                 in nsIContentPrefCallback2 callback);
+
+  /**
    * Gets the preference with the given domain and name.
    *
    * @param domain    The preference's domain.
    * @param name      The preference's name.
    * @param context   The private-browsing context, if any.
    * @param callback  handleResult is called once unless no such preference
    *                  exists, in which case handleResult is not called at all.
    */
--- a/toolkit/components/contentprefs/ContentPrefService2.jsm
+++ b/toolkit/components/contentprefs/ContentPrefService2.jsm
@@ -35,16 +35,71 @@ Cu.import("resource://gre/modules/Conten
 function ContentPrefService2(cps) {
   this._cps = cps;
   this._cache = cps._cache;
   this._pbStore = cps._privModeStorage;
 }
 
 ContentPrefService2.prototype = {
 
+  getByName: function CPS2_getByName(name, context, callback) {
+    checkNameArg(name);
+    checkCallbackArg(callback, true);
+
+    // Some prefs may be in both the database and the private browsing store.
+    // Notify the caller of such prefs only once, using the values from private
+    // browsing.
+    let pbPrefs = new ContentPrefStore();
+    if (context && context.usePrivateBrowsing) {
+      for (let [sgroup, sname, val] in this._pbStore) {
+        if (sname == name) {
+          pbPrefs.set(sgroup, sname, val);
+        }
+      }
+    }
+
+    let stmt1 = this._stmt(
+      "SELECT groups.name AS grp, prefs.value AS value",
+      "FROM prefs",
+      "JOIN settings ON settings.id = prefs.settingID",
+      "JOIN groups ON groups.id = prefs.groupID",
+      "WHERE settings.name = :name"
+    );
+    stmt1.params.name = name;
+
+    let stmt2 = this._stmt(
+      "SELECT NULL AS grp, prefs.value AS value",
+      "FROM prefs",
+      "JOIN settings ON settings.id = prefs.settingID",
+      "WHERE settings.name = :name AND prefs.groupID ISNULL"
+    );
+    stmt2.params.name = name;
+
+    this._execStmts([stmt1, stmt2], {
+      onRow: function onRow(row) {
+        let grp = row.getResultByName("grp");
+        let val = row.getResultByName("value");
+        this._cache.set(grp, name, val);
+        if (!pbPrefs.has(grp, name))
+          cbHandleResult(callback, new ContentPref(grp, name, val));
+      },
+      onDone: function onDone(reason, ok, gotRow) {
+        if (ok) {
+          for (let [pbGroup, pbName, pbVal] in pbPrefs) {
+            cbHandleResult(callback, new ContentPref(pbGroup, pbName, pbVal));
+          }
+        }
+        cbHandleCompletion(callback, reason);
+      },
+      onError: function onError(nsresult) {
+        cbHandleError(callback, nsresult);
+      }
+    });
+  },
+
   getByDomainAndName: function CPS2_getByDomainAndName(group, name, context,
                                                        callback) {
     checkGroupArg(group);
     this._get(group, name, false, context, callback);
   },
 
   getBySubdomainAndName: function CPS2_getBySubdomainAndName(group, name,
                                                              context,
--- a/toolkit/components/contentprefs/tests/unit_cps2/test_setGet.js
+++ b/toolkit/components/contentprefs/tests/unit_cps2/test_setGet.js
@@ -165,9 +165,31 @@ let tests = [
         do_check_true(!!fetchedPref);
         do_check_eq(fetchedPref.value, 2);
         next();
       },
     });
 
     yield;
   },
+
+  function get_nameOnly() {
+    yield set("a.com", "foo", 1);
+    yield set("a.com", "bar", 2);
+    yield set("b.com", "foo", 3);
+    yield setGlobal("foo", 4);
+
+    yield getOKEx("getByName", ["foo", undefined], [
+      {"domain": "a.com", "name": "foo", "value": 1},
+      {"domain": "b.com", "name": "foo", "value": 3},
+      {"domain": null, "name": "foo", "value": 4}
+    ]);
+
+    let context = { usePrivateBrowsing: true };
+    yield set("b.com", "foo", 5, context);
+
+    yield getOKEx("getByName", ["foo", context], [
+      {"domain": "a.com", "name": "foo", "value": 1},
+      {"domain": null, "name": "foo", "value": 4},
+      {"domain": "b.com", "name": "foo", "value": 5}
+    ]);
+  }
 ];