diff --git a/browser/base/content/browser-fullZoom.js b/browser/base/content/browser-fullZoom.js index 14e43c4c0e0..5ad89ddf798 100644 --- a/browser/base/content/browser-fullZoom.js +++ b/browser/base/content/browser-fullZoom.js @@ -115,8 +115,8 @@ var FullZoom = { this._onContentPrefChanged(aGroup, aValue, aIsPrivate); }, - onContentPrefRemoved: function FullZoom_onContentPrefRemoved(aGroup, aName) { - this._onContentPrefChanged(aGroup, undefined); + onContentPrefRemoved: function FullZoom_onContentPrefRemoved(aGroup, aName, aIsPrivate) { + this._onContentPrefChanged(aGroup, undefined, aIsPrivate); }, /** diff --git a/dom/interfaces/base/nsIContentPrefService.idl b/dom/interfaces/base/nsIContentPrefService.idl index 204650f211e..9c3cf366542 100644 --- a/dom/interfaces/base/nsIContentPrefService.idl +++ b/dom/interfaces/base/nsIContentPrefService.idl @@ -34,8 +34,12 @@ interface nsIContentPrefObserver : nsISupports * @param aGroup the group to which the pref belongs, or null * if it's a global pref (applies to all sites) * @param aName the name of the pref that was removed + * @param aIsPrivate an optional flag determining whether the + * original context is private or not */ - void onContentPrefRemoved(in AString aGroup, in AString aName); + void onContentPrefRemoved(in AString aGroup, + in AString aName, + [optional] in boolean aIsPrivate); }; [scriptable, function, uuid(c1b3d6df-5373-4606-8494-8bcf14a7fc62)] diff --git a/toolkit/components/contentprefs/ContentPrefService2.jsm b/toolkit/components/contentprefs/ContentPrefService2.jsm index e4273165e9b..f98afa09375 100644 --- a/toolkit/components/contentprefs/ContentPrefService2.jsm +++ b/toolkit/components/contentprefs/ContentPrefService2.jsm @@ -386,6 +386,7 @@ ContentPrefService2.prototype = { let prefs = new ContentPrefStore(); + let isPrivate = context && context.usePrivateBrowsing; this._execStmts(stmts, { onRow: function onRow(row) { let grp = row.getResultByName("grp"); @@ -395,7 +396,7 @@ ContentPrefService2.prototype = { onDone: function onDone(reason, ok) { if (ok) { this._cache.set(group, name, undefined); - if (context && context.usePrivateBrowsing) { + if (isPrivate) { for (let [sgroup, ] of this._pbStore.match(group, name, includeSubdomains)) { prefs.set(sgroup, name, undefined); @@ -406,7 +407,7 @@ ContentPrefService2.prototype = { cbHandleCompletion(callback, reason); if (ok) { for (let [sgroup, , ] of prefs) { - this._cps._notifyPrefRemoved(sgroup, name); + this._cps._notifyPrefRemoved(sgroup, name, isPrivate); } } }, @@ -498,6 +499,7 @@ ContentPrefService2.prototype = { let prefs = new ContentPrefStore(); + let isPrivate = context && context.usePrivateBrowsing; this._execStmts(stmts, { onRow: function onRow(row) { let grp = row.getResultByName("grp"); @@ -506,16 +508,20 @@ ContentPrefService2.prototype = { this._cache.set(grp, name, undefined); }, onDone: function onDone(reason, ok) { - if (ok && context && context.usePrivateBrowsing) { + if (ok && isPrivate) { for (let [sgroup, sname, ] of this._pbStore) { - prefs.set(sgroup, sname, undefined); - this._pbStore.remove(sgroup, sname); + if (!group || + (!includeSubdomains && group == sgroup) || + (includeSubdomains && sgroup && this._pbStore.groupsMatchIncludingSubdomains(group, sgroup))) { + prefs.set(sgroup, sname, undefined); + this._pbStore.remove(sgroup, sname); + } } } cbHandleCompletion(callback, reason); if (ok) { for (let [sgroup, sname, ] of prefs) { - this._cps._notifyPrefRemoved(sgroup, sname); + this._cps._notifyPrefRemoved(sgroup, sname, isPrivate); } } }, @@ -559,6 +565,7 @@ ContentPrefService2.prototype = { stmts = stmts.concat(this._settingsAndGroupsCleanupStmts()); let prefs = new ContentPrefStore(); + let isPrivate = context && context.usePrivateBrowsing; this._execStmts(stmts, { onRow: function onRow(row) { let grp = row.getResultByName("grp"); @@ -569,16 +576,18 @@ ContentPrefService2.prototype = { onDone: function onDone(reason, ok) { // This nukes all the groups in _pbStore since we don't have their timestamp // information. - if (ok && context && context.usePrivateBrowsing) { + if (ok && isPrivate) { for (let [sgroup, sname, ] of this._pbStore) { - prefs.set(sgroup, sname, undefined); + if (sgroup) { + prefs.set(sgroup, sname, undefined); + } } this._pbStore.removeAllGroups(); } cbHandleCompletion(callback, reason); if (ok) { for (let [sgroup, sname, ] of prefs) { - this._cps._notifyPrefRemoved(sgroup, sname); + this._cps._notifyPrefRemoved(sgroup, sname, isPrivate); } } }, @@ -647,6 +656,7 @@ ContentPrefService2.prototype = { `)); let prefs = new ContentPrefStore(); + let isPrivate = context && context.usePrivateBrowsing; this._execStmts(stmts, { onRow: function onRow(row) { @@ -655,7 +665,7 @@ ContentPrefService2.prototype = { this._cache.set(grp, name, undefined); }, onDone: function onDone(reason, ok) { - if (ok && context && context.usePrivateBrowsing) { + if (ok && isPrivate) { for (let [sgroup, sname, ] of this._pbStore) { if (sname === name) { prefs.set(sgroup, name, undefined); @@ -666,7 +676,7 @@ ContentPrefService2.prototype = { cbHandleCompletion(callback, reason); if (ok) { for (let [sgroup, , ] of prefs) { - this._cps._notifyPrefRemoved(sgroup, name); + this._cps._notifyPrefRemoved(sgroup, name, isPrivate); } } }, diff --git a/toolkit/components/contentprefs/ContentPrefStore.jsm b/toolkit/components/contentprefs/ContentPrefStore.jsm index 0494f371ce5..7a552662ffc 100644 --- a/toolkit/components/contentprefs/ContentPrefStore.jsm +++ b/toolkit/components/contentprefs/ContentPrefStore.jsm @@ -77,6 +77,12 @@ ContentPrefStore.prototype = { this._globalNames.clear(); }, + groupsMatchIncludingSubdomains: function CPS_groupsMatchIncludingSubdomains(group, group2) { + let idx = group2.indexOf(group); + return (idx == group2.length - group.length && + (idx == 0 || group2[idx - 1] == ".")); + }, + * [Symbol.iterator]() { for (let [group, names] of this._groups) { for (let [name, val] of names) { @@ -100,10 +106,9 @@ ContentPrefStore.prototype = { if (includeSubdomains) { for (let [sgroup, , ] of this) { if (sgroup) { - let idx = sgroup.indexOf(group); - if (idx == sgroup.length - group.length && - (idx == 0 || sgroup[idx - 1] == ".")) + if (this.groupsMatchIncludingSubdomains(group, sgroup)) { yield sgroup; + } } } } diff --git a/toolkit/components/contentprefs/nsContentPrefService.js b/toolkit/components/contentprefs/nsContentPrefService.js index 99d53a564ce..68a5c9c3a02 100644 --- a/toolkit/components/contentprefs/nsContentPrefService.js +++ b/toolkit/components/contentprefs/nsContentPrefService.js @@ -314,7 +314,7 @@ ContentPrefService.prototype = { if (aContext && aContext.usePrivateBrowsing) { this._privModeStorage.remove(group, aName); - this._notifyPrefRemoved(group, aName); + this._notifyPrefRemoved(group, aName, true); return; } @@ -337,7 +337,7 @@ ContentPrefService.prototype = { this._deleteGroupIfUnused(groupID); this._cache.remove(group, aName); - this._notifyPrefRemoved(group, aName); + this._notifyPrefRemoved(group, aName, false); }, removeGroupedPrefs: function ContentPrefService_removeGroupedPrefs(aContext) { @@ -376,7 +376,7 @@ ContentPrefService.prototype = { for (let [group, name, ] of this._privModeStorage) { if (name === aName) { this._privModeStorage.remove(group, aName); - this._notifyPrefRemoved(group, aName); + this._notifyPrefRemoved(group, aName, true); } } } @@ -418,7 +418,7 @@ ContentPrefService.prototype = { if (groupNames[i]) // ie. not null, which will be last (and i == groupIDs.length) this._deleteGroupIfUnused(groupIDs[i]); if (!aContext || !aContext.usePrivateBrowsing) { - this._notifyPrefRemoved(groupNames[i], aName); + this._notifyPrefRemoved(groupNames[i], aName, false); } } }, @@ -526,10 +526,10 @@ ContentPrefService.prototype = { /** * Notify all observers about the removal of a preference. */ - _notifyPrefRemoved: function ContentPrefService__notifyPrefRemoved(aGroup, aName) { + _notifyPrefRemoved: function ContentPrefService__notifyPrefRemoved(aGroup, aName, aIsPrivate) { for (var observer of this._getObservers(aName)) { try { - observer.onContentPrefRemoved(aGroup, aName); + observer.onContentPrefRemoved(aGroup, aName, aIsPrivate); } catch(ex) { Cu.reportError(ex); diff --git a/toolkit/components/contentprefs/tests/unit/test_contentPrefs.js b/toolkit/components/contentprefs/tests/unit/test_contentPrefs.js index 90713aa66d8..0f92c3b8118 100644 --- a/toolkit/components/contentprefs/tests/unit/test_contentPrefs.js +++ b/toolkit/components/contentprefs/tests/unit/test_contentPrefs.js @@ -284,9 +284,13 @@ function run_test() { }, numTimesRemovedCalled: 0, - onContentPrefRemoved: function genericObserver_onContentPrefRemoved(group, name) { + onContentPrefRemoved: function genericObserver_onContentPrefRemoved(group, name, isPrivate) { ++this.numTimesRemovedCalled; do_check_eq(group, "www.example.com"); + if (name == "test.observer.private") + do_check_true(isPrivate); + else if (name == "test.observer.normal") + do_check_false(isPrivate); if (name != "test.observer.1" && name != "test.observer.2" && name != "test.observer.normal" && name != "test.observer.private") { do_throw("genericObserver.onContentPrefSet: " + diff --git a/toolkit/components/contentprefs/tests/unit_cps2/test_observers.js b/toolkit/components/contentprefs/tests/unit_cps2/test_observers.js index 3c0a5d8a771..c48918cd927 100644 --- a/toolkit/components/contentprefs/tests/unit_cps2/test_observers.js +++ b/toolkit/components/contentprefs/tests/unit_cps2/test_observers.js @@ -2,149 +2,128 @@ * 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/. */ +let global = this; + function run_test() { - runAsyncTests(tests); + var allTests = []; + for (var i = 0; i < tests.length; i++) { + // Generate two wrappers of each test function that invoke the original test with an + // appropriate privacy context. + var pub = eval('var f = function* ' + tests[i].name + '() { yield tests[' + i + ']({ usePrivateBrowsing: false }); }; f'); + var priv = eval('var f = function* ' + tests[i].name + '_private() { yield tests[' + i + ']({ usePrivateBrowsing: true }); }; f'); + allTests.push(pub); + allTests.push(priv); + } + allTests = allTests.concat(specialTests); + runAsyncTests(allTests); } var tests = [ - function* observerForName_set() { - yield set("a.com", "foo", 1); + function* observerForName_set(context) { + yield set("a.com", "foo", 1, context); let args = yield on("Set", ["foo", null, "bar"]); - observerArgsOK(args.foo, [["a.com", "foo", 1, false]]); - observerArgsOK(args.null, [["a.com", "foo", 1, false]]); + observerArgsOK(args.foo, [["a.com", "foo", 1, context.usePrivateBrowsing]]); + observerArgsOK(args.null, [["a.com", "foo", 1, context.usePrivateBrowsing]]); observerArgsOK(args.bar, []); - yield setGlobal("foo", 2); + yield setGlobal("foo", 2, context); args = yield on("Set", ["foo", null, "bar"]); - observerArgsOK(args.foo, [[null, "foo", 2, false]]); - observerArgsOK(args.null, [[null, "foo", 2, false]]); + observerArgsOK(args.foo, [[null, "foo", 2, context.usePrivateBrowsing]]); + observerArgsOK(args.null, [[null, "foo", 2, context.usePrivateBrowsing]]); observerArgsOK(args.bar, []); }, - function* observerForName_set_private() { - yield set("a.com", "foo", 1, { usePrivateBrowsing: true }); - let args = yield on("Set", ["foo", null, "bar"]); - observerArgsOK(args.foo, [["a.com", "foo", 1, true]]); - observerArgsOK(args.null, [["a.com", "foo", 1, true]]); - observerArgsOK(args.bar, []); + function* observerForName_remove(context) { + yield set("a.com", "foo", 1, context); + yield setGlobal("foo", 2, context); - yield setGlobal("foo", 2, { usePrivateBrowsing: true }); - args = yield on("Set", ["foo", null, "bar"]); - observerArgsOK(args.foo, [[null, "foo", 2, true]]); - observerArgsOK(args.null, [[null, "foo", 2, true]]); - observerArgsOK(args.bar, []); - }, - - function* observerForName_remove() { - yield set("a.com", "foo", 1); - yield setGlobal("foo", 2); - - yield cps.removeByDomainAndName("a.com", "bogus", null, makeCallback()); + yield cps.removeByDomainAndName("a.com", "bogus", context, makeCallback()); let args = yield on("Removed", ["foo", null, "bar"]); observerArgsOK(args.foo, []); observerArgsOK(args.null, []); observerArgsOK(args.bar, []); - yield cps.removeByDomainAndName("a.com", "foo", null, makeCallback()); + yield cps.removeByDomainAndName("a.com", "foo", context, makeCallback()); args = yield on("Removed", ["foo", null, "bar"]); - observerArgsOK(args.foo, [["a.com", "foo"]]); - observerArgsOK(args.null, [["a.com", "foo"]]); + observerArgsOK(args.foo, [["a.com", "foo", context.usePrivateBrowsing]]); + observerArgsOK(args.null, [["a.com", "foo", context.usePrivateBrowsing]]); observerArgsOK(args.bar, []); - yield cps.removeGlobal("foo", null, makeCallback()); + yield cps.removeGlobal("foo", context, makeCallback()); args = yield on("Removed", ["foo", null, "bar"]); - observerArgsOK(args.foo, [[null, "foo"]]); - observerArgsOK(args.null, [[null, "foo"]]); + observerArgsOK(args.foo, [[null, "foo", context.usePrivateBrowsing]]); + observerArgsOK(args.null, [[null, "foo", context.usePrivateBrowsing]]); observerArgsOK(args.bar, []); }, - function* observerForName_removeByDomain() { - yield set("a.com", "foo", 1); - yield set("b.a.com", "bar", 2); - yield setGlobal("foo", 3); + function* observerForName_removeByDomain(context) { + yield set("a.com", "foo", 1, context); + yield set("b.a.com", "bar", 2, context); + yield setGlobal("foo", 3, context); - yield cps.removeByDomain("bogus", null, makeCallback()); + yield cps.removeByDomain("bogus", context, makeCallback()); let args = yield on("Removed", ["foo", null, "bar"]); observerArgsOK(args.foo, []); observerArgsOK(args.null, []); observerArgsOK(args.bar, []); - yield cps.removeBySubdomain("a.com", null, makeCallback()); + yield cps.removeBySubdomain("a.com", context, makeCallback()); args = yield on("Removed", ["foo", null, "bar"]); - observerArgsOK(args.foo, [["a.com", "foo"]]); - observerArgsOK(args.null, [["a.com", "foo"], ["b.a.com", "bar"]]); - observerArgsOK(args.bar, [["b.a.com", "bar"]]); + observerArgsOK(args.foo, [["a.com", "foo", context.usePrivateBrowsing]]); + observerArgsOK(args.null, [["a.com", "foo", context.usePrivateBrowsing], ["b.a.com", "bar", context.usePrivateBrowsing]]); + observerArgsOK(args.bar, [["b.a.com", "bar", context.usePrivateBrowsing]]); - yield cps.removeAllGlobals(null, makeCallback()); + yield cps.removeAllGlobals(context, makeCallback()); args = yield on("Removed", ["foo", null, "bar"]); - observerArgsOK(args.foo, [[null, "foo"]]); - observerArgsOK(args.null, [[null, "foo"]]); + observerArgsOK(args.foo, [[null, "foo", context.usePrivateBrowsing]]); + observerArgsOK(args.null, [[null, "foo", context.usePrivateBrowsing]]); observerArgsOK(args.bar, []); }, - function* observerForName_removeAllDomainsSince() { - yield setWithDate("a.com", "foo", 1, 100); - yield setWithDate("b.com", "foo", 2, 200); - yield setWithDate("c.com", "foo", 3, 300); + function* observerForName_removeAllDomains(context) { + yield set("a.com", "foo", 1, context); + yield setGlobal("foo", 2, context); + yield set("b.com", "bar", 3, context); - yield setWithDate("a.com", "bar", 1, 0); - yield setWithDate("b.com", "bar", 2, 100); - yield setWithDate("c.com", "bar", 3, 200); - yield setGlobal("foo", 2); - - yield cps.removeAllDomainsSince(200, null, makeCallback()); - - let args = yield on("Removed", ["foo", "bar", null]); - - observerArgsOK(args.foo, [["b.com", "foo"], ["c.com", "foo"]]); - observerArgsOK(args.bar, [["c.com", "bar"]]); - observerArgsOK(args.null, [["b.com", "foo"], ["c.com", "bar"], ["c.com", "foo"]]); - }, - - function* observerForName_removeAllDomains() { - yield set("a.com", "foo", 1); - yield setGlobal("foo", 2); - yield set("b.com", "bar", 3); - - yield cps.removeAllDomains(null, makeCallback()); + yield cps.removeAllDomains(context, makeCallback()); let args = yield on("Removed", ["foo", null, "bar"]); - observerArgsOK(args.foo, [["a.com", "foo"]]); - observerArgsOK(args.null, [["a.com", "foo"], ["b.com", "bar"]]); - observerArgsOK(args.bar, [["b.com", "bar"]]); + observerArgsOK(args.foo, [["a.com", "foo", context.usePrivateBrowsing]]); + observerArgsOK(args.null, [["a.com", "foo", context.usePrivateBrowsing], ["b.com", "bar", context.usePrivateBrowsing]]); + observerArgsOK(args.bar, [["b.com", "bar", context.usePrivateBrowsing]]); }, - function* observerForName_removeByName() { - yield set("a.com", "foo", 1); - yield set("a.com", "bar", 2); - yield setGlobal("foo", 3); + function* observerForName_removeByName(context) { + yield set("a.com", "foo", 1, context); + yield set("a.com", "bar", 2, context); + yield setGlobal("foo", 3, context); - yield cps.removeByName("bogus", null, makeCallback()); + yield cps.removeByName("bogus", context, makeCallback()); let args = yield on("Removed", ["foo", null, "bar"]); observerArgsOK(args.foo, []); observerArgsOK(args.null, []); observerArgsOK(args.bar, []); - yield cps.removeByName("foo", null, makeCallback()); + yield cps.removeByName("foo", context, makeCallback()); args = yield on("Removed", ["foo", null, "bar"]); - observerArgsOK(args.foo, [["a.com", "foo"], [null, "foo"]]); - observerArgsOK(args.null, [["a.com", "foo"], [null, "foo"]]); + observerArgsOK(args.foo, [["a.com", "foo", context.usePrivateBrowsing], [null, "foo", context.usePrivateBrowsing]]); + observerArgsOK(args.null, [["a.com", "foo", context.usePrivateBrowsing], [null, "foo", context.usePrivateBrowsing]]); observerArgsOK(args.bar, []); }, - function* removeObserverForName() { + function* removeObserverForName(context) { let args = yield on("Set", ["foo", null, "bar"], true); cps.removeObserverForName("foo", args.foo.observer); - yield set("a.com", "foo", 1); + yield set("a.com", "foo", 1, context); yield wait(); observerArgsOK(args.foo, []); - observerArgsOK(args.null, [["a.com", "foo", 1, false]]); + observerArgsOK(args.null, [["a.com", "foo", 1, context.usePrivateBrowsing]]); observerArgsOK(args.bar, []); args.reset(); cps.removeObserverForName(null, args.null.observer); - yield set("a.com", "foo", 2); + yield set("a.com", "foo", 2, context); yield wait(); observerArgsOK(args.foo, []); observerArgsOK(args.null, []); @@ -152,3 +131,48 @@ var tests = [ args.reset(); }, ]; + +// These tests are for functionality that doesn't behave the same way in private and public +// contexts, so the expected results cannot be automatically generated like the previous tests. +var specialTests = [ + function* observerForName_removeAllDomainsSince() { + yield setWithDate("a.com", "foo", 1, 100, null); + yield setWithDate("b.com", "foo", 2, 200, null); + yield setWithDate("c.com", "foo", 3, 300, null); + + yield setWithDate("a.com", "bar", 1, 0, null); + yield setWithDate("b.com", "bar", 2, 100, null); + yield setWithDate("c.com", "bar", 3, 200, null); + yield setGlobal("foo", 2, null); + + yield cps.removeAllDomainsSince(200, null, makeCallback()); + + let args = yield on("Removed", ["foo", "bar", null]); + + observerArgsOK(args.foo, [["b.com", "foo", false], ["c.com", "foo", false]]); + observerArgsOK(args.bar, [["c.com", "bar", false]]); + observerArgsOK(args.null, [["b.com", "foo", false], ["c.com", "bar", false], ["c.com", "foo", false]]); + }, + + function* observerForName_removeAllDomainsSince_private() { + let context = {usePrivateBrowsing: true}; + yield setWithDate("a.com", "foo", 1, 100, context); + yield setWithDate("b.com", "foo", 2, 200, context); + yield setWithDate("c.com", "foo", 3, 300, context); + + yield setWithDate("a.com", "bar", 1, 0, context); + yield setWithDate("b.com", "bar", 2, 100, context); + yield setWithDate("c.com", "bar", 3, 200, context); + yield setGlobal("foo", 2, context); + + yield cps.removeAllDomainsSince(200, context, makeCallback()); + + let args = yield on("Removed", ["foo", "bar", null]); + + observerArgsOK(args.foo, [["a.com", "foo", true], ["b.com", "foo", true], ["c.com", "foo", true]]); + observerArgsOK(args.bar, [["a.com", "bar", true], ["b.com", "bar", true], ["c.com", "bar", true]]); + observerArgsOK(args.null, [["a.com", "foo", true], ["a.com", "bar", true], + ["b.com", "foo", true], ["b.com", "bar", true], + ["c.com", "foo", true], ["c.com", "bar", true]]); + }, +]; diff --git a/toolkit/components/contentprefs/tests/unit_cps2/test_removeByDomain.js b/toolkit/components/contentprefs/tests/unit_cps2/test_removeByDomain.js index e9ed2fbe216..1cf6bd8f2e8 100644 --- a/toolkit/components/contentprefs/tests/unit_cps2/test_removeByDomain.js +++ b/toolkit/components/contentprefs/tests/unit_cps2/test_removeByDomain.js @@ -130,8 +130,11 @@ var tests = [ let context = { usePrivateBrowsing: true }; yield set("a.com", "foo", 6, context); - yield setGlobal("foo", 7, context); + yield set("b.com", "foo", 7, context); + yield setGlobal("foo", 8, context); yield cps.removeByDomain("a.com", context, makeCallback()); + yield getOK(["b.com", "foo", context], 7); + yield getGlobalOK(["foo", context], 8); yield cps.removeAllGlobals(context, makeCallback()); yield dbOK([ ["b.com", "foo", 5],