mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 22:32:46 +00:00
Bug 1926591 - PreferencesCleaner support for OriginAttributesPattern. r=mak
Differential Revision: https://phabricator.services.mozilla.com/D221783
This commit is contained in:
parent
09e9104b76
commit
617efd9bd8
@ -87,6 +87,11 @@ interface nsIContentPrefObserver : nsISupports
|
||||
* window or channel whose content pertains to the preferences being modified or
|
||||
* retrieved.
|
||||
*
|
||||
* The remove methods, used to clear prefs, also accept an optional
|
||||
* nsILoadContext. If you pass null, both private and normal browsing data will
|
||||
* be removed. Passing a normal browsing context will remove only normal
|
||||
* browsing data, and passing a private browsing context will remove only
|
||||
* private browsing data.
|
||||
*
|
||||
* Callbacks
|
||||
*
|
||||
@ -255,7 +260,9 @@ interface nsIContentPrefService2 : nsISupports
|
||||
*
|
||||
* @param domain The preference's domain.
|
||||
* @param name The preference's name.
|
||||
* @param context The private-browsing context, if any.
|
||||
* @param [context] Optional context to pass to indicate whether normal or
|
||||
* private-browsing data should be removed. Passing null
|
||||
* removes both private and normal browsing data.
|
||||
* @param callback handleCompletion is called when the operation completes.
|
||||
*/
|
||||
void removeByDomainAndName(in AString domain,
|
||||
@ -269,7 +276,9 @@ interface nsIContentPrefService2 : nsISupports
|
||||
*
|
||||
* @param domain The preferences' domain.
|
||||
* @param name The preferences' name.
|
||||
* @param context The private-browsing context, if any.
|
||||
* @param [context] Optional context to pass to indicate whether normal or
|
||||
* private-browsing data should be removed. Passing null
|
||||
* removes both private and normal browsing data.
|
||||
* @param callback handleCompletion is called when the operation completes.
|
||||
*/
|
||||
void removeBySubdomainAndName(in AString domain,
|
||||
@ -281,7 +290,9 @@ interface nsIContentPrefService2 : nsISupports
|
||||
* Removes the preference with no domain and the given name.
|
||||
*
|
||||
* @param name The preference's name.
|
||||
* @param context The private-browsing context, if any.
|
||||
* @param [context] Optional context to pass to indicate whether normal or
|
||||
* private-browsing data should be removed. Passing null
|
||||
* removes both private and normal browsing data.
|
||||
* @param callback handleCompletion is called when the operation completes.
|
||||
*/
|
||||
void removeGlobal(in AString name,
|
||||
@ -292,7 +303,9 @@ interface nsIContentPrefService2 : nsISupports
|
||||
* Removes all preferences with the given domain.
|
||||
*
|
||||
* @param domain The preferences' domain.
|
||||
* @param context The private-browsing context, if any.
|
||||
* @param [context] Optional context to pass to indicate whether normal or
|
||||
* private-browsing data should be removed. Passing null
|
||||
* removes both private and normal browsing data.
|
||||
* @param callback handleCompletion is called when the operation completes.
|
||||
*/
|
||||
void removeByDomain(in AString domain,
|
||||
@ -304,7 +317,9 @@ interface nsIContentPrefService2 : nsISupports
|
||||
* of the given domain.
|
||||
*
|
||||
* @param domain The preferences' domain.
|
||||
* @param context The private-browsing context, if any.
|
||||
* @param [context] Optional context to pass to indicate whether normal or
|
||||
* private-browsing data should be removed. Passing null
|
||||
* removes both private and normal browsing data.
|
||||
* @param callback handleCompletion is called when the operation completes.
|
||||
*/
|
||||
void removeBySubdomain(in AString domain,
|
||||
@ -316,7 +331,9 @@ interface nsIContentPrefService2 : nsISupports
|
||||
* global preferences with the given name.
|
||||
*
|
||||
* @param name The preferences' name.
|
||||
* @param context The private-browsing context, if any.
|
||||
* @param [context] Optional context to pass to indicate whether normal or
|
||||
* private-browsing data should be removed. Passing null
|
||||
* removes both private and normal browsing data.
|
||||
* @param callback handleCompletion is called when the operation completes.
|
||||
*/
|
||||
void removeByName(in AString name,
|
||||
@ -327,7 +344,9 @@ interface nsIContentPrefService2 : nsISupports
|
||||
* Removes all non-global preferences -- in other words, all preferences that
|
||||
* have a domain.
|
||||
*
|
||||
* @param context The private-browsing context, if any.
|
||||
* @param [context] Optional context to pass to indicate whether normal or
|
||||
* private-browsing data should be removed. Passing null
|
||||
* removes both private and normal browsing data.
|
||||
* @param callback handleCompletion is called when the operation completes.
|
||||
*/
|
||||
void removeAllDomains(in nsILoadContext context,
|
||||
@ -337,7 +356,9 @@ interface nsIContentPrefService2 : nsISupports
|
||||
* Removes all non-global preferences created after and including |since|.
|
||||
*
|
||||
* @param since Timestamp in milliseconds.
|
||||
* @param context The private-browsing context, if any.
|
||||
* @param [context] Optional context to pass to indicate whether normal or
|
||||
* private-browsing data should be removed. Passing null
|
||||
* removes both private and normal browsing data.
|
||||
* @param callback handleCompletion is called when the operation completes.
|
||||
*/
|
||||
void removeAllDomainsSince(in unsigned long long since,
|
||||
@ -348,7 +369,9 @@ interface nsIContentPrefService2 : nsISupports
|
||||
* Removes all global preferences -- in other words, all preferences that have
|
||||
* no domain.
|
||||
*
|
||||
* @param context The private-browsing context, if any.
|
||||
* @param [context] Optional context to pass to indicate whether normal or
|
||||
* private-browsing data should be removed. Passing null
|
||||
* removes both private and normal browsing data.
|
||||
* @param callback handleCompletion is called when the operation completes.
|
||||
*/
|
||||
void removeAllGlobals(in nsILoadContext context,
|
||||
|
@ -1546,13 +1546,26 @@ const PermissionsCleaner = {
|
||||
};
|
||||
|
||||
const PreferencesCleaner = {
|
||||
deleteByHost(aHost) {
|
||||
deleteByHost(aHost, aOriginAttributes = {}) {
|
||||
aOriginAttributes =
|
||||
ChromeUtils.fillNonDefaultOriginAttributes(aOriginAttributes);
|
||||
|
||||
let loadContext;
|
||||
if (
|
||||
aOriginAttributes.privateBrowsingId ==
|
||||
Services.scriptSecurityManager.DEFAULT_PRIVATE_BROWSING_ID
|
||||
) {
|
||||
loadContext = Cu.createLoadContext();
|
||||
} else {
|
||||
loadContext = Cu.createPrivateLoadContext();
|
||||
}
|
||||
|
||||
// Also clears subdomains of aHost.
|
||||
return new Promise((aResolve, aReject) => {
|
||||
let cps2 = Cc["@mozilla.org/content-pref/service;1"].getService(
|
||||
Ci.nsIContentPrefService2
|
||||
);
|
||||
cps2.removeBySubdomain(aHost, null, {
|
||||
cps2.removeBySubdomain(aHost, loadContext, {
|
||||
handleCompletion: aReason => {
|
||||
if (aReason === cps2.COMPLETE_ERROR) {
|
||||
aReject();
|
||||
@ -1560,7 +1573,6 @@ const PreferencesCleaner = {
|
||||
aResolve();
|
||||
}
|
||||
},
|
||||
handleError() {},
|
||||
});
|
||||
});
|
||||
},
|
||||
@ -1569,23 +1581,74 @@ const PreferencesCleaner = {
|
||||
return this.deleteByHost(aPrincipal.host, aPrincipal.originAttributes);
|
||||
},
|
||||
|
||||
deleteBySite(aSchemelessSite, _aOriginAttributesPattern) {
|
||||
// TODO: aOriginAttributesPattern
|
||||
return this.deleteByHost(aSchemelessSite, {});
|
||||
async deleteBySite(aSchemelessSite, aOriginAttributesPattern) {
|
||||
// If aOriginAttributesPattern does not specify private or normal browsing
|
||||
// clear both.
|
||||
let loadContext = null;
|
||||
|
||||
// If the pattern filters by normal or private browsing mode only clear that mode.
|
||||
if (aOriginAttributesPattern.privateBrowsingId != null) {
|
||||
// The default private browsing ID is 0 which is non private browsing mode
|
||||
// / normal mode.
|
||||
let isPrivateBrowsing =
|
||||
aOriginAttributesPattern.privateBrowsingId !=
|
||||
Ci.nsIScriptSecurityManager.DEFAULT_PRIVATE_BROWSING_ID;
|
||||
loadContext = isPrivateBrowsing
|
||||
? Cu.createPrivateLoadContext()
|
||||
: Cu.createLoadContext();
|
||||
}
|
||||
|
||||
let cps2 = Cc["@mozilla.org/content-pref/service;1"].getService(
|
||||
Ci.nsIContentPrefService2
|
||||
);
|
||||
|
||||
await new Promise((aResolve, aReject) => {
|
||||
cps2.removeBySubdomain(aSchemelessSite, loadContext, {
|
||||
handleCompletion: aReason => {
|
||||
if (aReason === cps2.COMPLETE_ERROR) {
|
||||
aReject();
|
||||
} else {
|
||||
aResolve();
|
||||
}
|
||||
},
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
async deleteByRange(aFrom) {
|
||||
let cps2 = Cc["@mozilla.org/content-pref/service;1"].getService(
|
||||
Ci.nsIContentPrefService2
|
||||
);
|
||||
cps2.removeAllDomainsSince(aFrom / 1000, null);
|
||||
|
||||
await new Promise((aResolve, aReject) => {
|
||||
cps2.removeAllDomainsSince(aFrom / 1000, null, {
|
||||
handleCompletion: aReason => {
|
||||
if (aReason === cps2.COMPLETE_ERROR) {
|
||||
aReject();
|
||||
} else {
|
||||
aResolve();
|
||||
}
|
||||
},
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
async deleteAll() {
|
||||
let cps2 = Cc["@mozilla.org/content-pref/service;1"].getService(
|
||||
Ci.nsIContentPrefService2
|
||||
);
|
||||
cps2.removeAllDomains(null);
|
||||
|
||||
await new Promise((aResolve, aReject) => {
|
||||
cps2.removeAllDomains(null, {
|
||||
handleCompletion: aReason => {
|
||||
if (aReason === cps2.COMPLETE_ERROR) {
|
||||
aReject();
|
||||
} else {
|
||||
aResolve();
|
||||
}
|
||||
},
|
||||
});
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -0,0 +1,371 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
https://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
let cps2 = Cc["@mozilla.org/content-pref/service;1"].getService(
|
||||
Ci.nsIContentPrefService2
|
||||
);
|
||||
|
||||
// Async wrappers around content pref service setter / getter. Would be nice if
|
||||
// the service provided that itself.
|
||||
|
||||
async function setContentPref(domain, name, value, isPBM) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let loadContext = isPBM
|
||||
? Cu.createPrivateLoadContext()
|
||||
: Cu.createLoadContext();
|
||||
cps2.set(domain, name, value, loadContext, {
|
||||
handleCompletion: aReason => {
|
||||
if (aReason === cps2.COMPLETE_ERROR) {
|
||||
reject(new Error("Failed to set content pref"));
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function getContentPref(domain, name, isPBM) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let loadContext = isPBM
|
||||
? Cu.createPrivateLoadContext()
|
||||
: Cu.createLoadContext();
|
||||
let result;
|
||||
cps2.getByDomainAndName(domain, name, loadContext, {
|
||||
handleResult({ value }) {
|
||||
result = value;
|
||||
},
|
||||
handleCompletion(aReason) {
|
||||
if (aReason === cps2.COMPLETE_ERROR) {
|
||||
reject(new Error("Failed to get content pref"));
|
||||
} else {
|
||||
resolve(result);
|
||||
}
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
add_task(async function test_deleteByHost() {
|
||||
info("Set content prefs");
|
||||
await setContentPref("example.com", "foo", "foo", false);
|
||||
await setContentPref("example.org", "bar", "bar", false);
|
||||
await setContentPref("example.org", "bar", "bar", true);
|
||||
await setContentPref("foo.example.org", "bar", "bar", false);
|
||||
await setContentPref("foo.example.org", "bar", "bar", true);
|
||||
await setContentPref("bar.foo.example.org", "subsub", "subsub", false);
|
||||
|
||||
info("Verify content prefs have been set");
|
||||
Assert.equal(await getContentPref("example.com", "foo", false), "foo");
|
||||
Assert.equal(await getContentPref("example.org", "bar", false), "bar");
|
||||
Assert.equal(await getContentPref("example.org", "bar", true), "bar");
|
||||
Assert.equal(await getContentPref("foo.example.org", "bar", false), "bar");
|
||||
Assert.equal(await getContentPref("foo.example.org", "bar", true), "bar");
|
||||
Assert.equal(
|
||||
await getContentPref("bar.foo.example.org", "subsub", false),
|
||||
"subsub"
|
||||
);
|
||||
|
||||
await new Promise(aResolve => {
|
||||
Services.clearData.deleteDataFromHost(
|
||||
"foo.example.org",
|
||||
true,
|
||||
Ci.nsIClearDataService.CLEAR_CONTENT_PREFERENCES,
|
||||
value => {
|
||||
Assert.equal(value, 0);
|
||||
aResolve();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
info(
|
||||
"Verify content prefs matching host 'foo.example.org' have been cleared"
|
||||
);
|
||||
Assert.equal(
|
||||
await getContentPref("example.com", "foo", false),
|
||||
"foo",
|
||||
"Unrelated domain entry should still exist."
|
||||
);
|
||||
Assert.equal(
|
||||
await getContentPref("example.org", "bar", false),
|
||||
"bar",
|
||||
"Base domain entry should still exist."
|
||||
);
|
||||
Assert.equal(
|
||||
await getContentPref("example.org", "bar", true),
|
||||
"bar",
|
||||
"Base domain PBM entry should still exist."
|
||||
);
|
||||
Assert.equal(
|
||||
await getContentPref("foo.example.org", "bar", false),
|
||||
undefined,
|
||||
"Exact domain match should have been cleared in normal browsing."
|
||||
);
|
||||
Assert.equal(
|
||||
await getContentPref("foo.example.org", "bar", true),
|
||||
"bar",
|
||||
"Exact domain match should not have been cleared in private browsing."
|
||||
);
|
||||
Assert.equal(
|
||||
await getContentPref("bar.foo.example.org", "subsub", false),
|
||||
undefined,
|
||||
"Subdomain should have been cleared"
|
||||
);
|
||||
|
||||
await SiteDataTestUtils.clear();
|
||||
});
|
||||
|
||||
add_task(async function test_deleteByPrincipal() {
|
||||
info("Set content prefs");
|
||||
await setContentPref("example.com", "foo", "foo", false);
|
||||
await setContentPref("example.org", "bar", "bar", false);
|
||||
await setContentPref("example.org", "bar", "bar", true);
|
||||
await setContentPref("foo.example.org", "bar", "bar", false);
|
||||
await setContentPref("foo.example.org", "bar", "bar", true);
|
||||
await setContentPref("bar.foo.example.org", "subsub", "subsub", false);
|
||||
|
||||
info("Verify content prefs have been set");
|
||||
Assert.equal(await getContentPref("example.com", "foo", false), "foo");
|
||||
Assert.equal(await getContentPref("example.org", "bar", false), "bar");
|
||||
Assert.equal(await getContentPref("example.org", "bar", true), "bar");
|
||||
Assert.equal(await getContentPref("foo.example.org", "bar", false), "bar");
|
||||
Assert.equal(await getContentPref("foo.example.org", "bar", true), "bar");
|
||||
Assert.equal(
|
||||
await getContentPref("bar.foo.example.org", "subsub", false),
|
||||
"subsub"
|
||||
);
|
||||
|
||||
await new Promise(aResolve => {
|
||||
Services.clearData.deleteDataFromPrincipal(
|
||||
Services.scriptSecurityManager.createContentPrincipalFromOrigin(
|
||||
"https://foo.example.org"
|
||||
),
|
||||
true,
|
||||
Ci.nsIClearDataService.CLEAR_CONTENT_PREFERENCES,
|
||||
value => {
|
||||
Assert.equal(value, 0);
|
||||
aResolve();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
info(
|
||||
"Verify content prefs matching principal 'https://foo.example.org' have been cleared"
|
||||
);
|
||||
Assert.equal(
|
||||
await getContentPref("example.com", "foo", false),
|
||||
"foo",
|
||||
"Unrelated domain entry should still exist."
|
||||
);
|
||||
Assert.equal(
|
||||
await getContentPref("example.org", "bar", false),
|
||||
"bar",
|
||||
"Base domain entry should still exist."
|
||||
);
|
||||
Assert.equal(
|
||||
await getContentPref("example.org", "bar", true),
|
||||
"bar",
|
||||
"Base domain PBM entry should still exist."
|
||||
);
|
||||
Assert.equal(
|
||||
await getContentPref("foo.example.org", "bar", false),
|
||||
undefined,
|
||||
"Exact domain match should have been cleared in normal browsing."
|
||||
);
|
||||
Assert.equal(
|
||||
await getContentPref("foo.example.org", "bar", true),
|
||||
"bar",
|
||||
"Exact domain match should NOT have been cleared in private browsing."
|
||||
);
|
||||
// TODO: PreferencesCleaner does not clear by exact principal but includes
|
||||
// subdomains of the given principal.
|
||||
Assert.equal(
|
||||
await getContentPref("bar.foo.example.org", "subsub", false),
|
||||
undefined,
|
||||
"TODO: Subdomain entry should still exist."
|
||||
);
|
||||
|
||||
await SiteDataTestUtils.clear();
|
||||
});
|
||||
|
||||
add_task(async function test_deleteBySite() {
|
||||
info("Set content prefs");
|
||||
await setContentPref("example.com", "foo", "foo", false);
|
||||
await setContentPref("example.org", "bar", "bar", false);
|
||||
await setContentPref("example.org", "bar", "bar", true);
|
||||
await setContentPref("foo.example.org", "bar", "bar", false);
|
||||
|
||||
info("Verify content prefs have been set");
|
||||
Assert.equal(await getContentPref("example.com", "foo", false), "foo");
|
||||
Assert.equal(await getContentPref("example.org", "bar", false), "bar");
|
||||
Assert.equal(await getContentPref("example.org", "bar", true), "bar");
|
||||
Assert.equal(await getContentPref("foo.example.org", "bar", false), "bar");
|
||||
|
||||
await new Promise(aResolve => {
|
||||
Services.clearData.deleteDataFromSite(
|
||||
"example.org",
|
||||
{},
|
||||
true,
|
||||
Ci.nsIClearDataService.CLEAR_CONTENT_PREFERENCES,
|
||||
value => {
|
||||
Assert.equal(value, 0);
|
||||
aResolve();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
info(
|
||||
"Verify content prefs for 'example.org' have been cleared, including PBM."
|
||||
);
|
||||
Assert.equal(await getContentPref("example.com", "foo", false), "foo");
|
||||
Assert.equal(await getContentPref("example.org", "bar", false), undefined);
|
||||
Assert.equal(await getContentPref("example.org", "bar", true), undefined);
|
||||
Assert.equal(
|
||||
await getContentPref("foo.example.org", "bar", false),
|
||||
undefined
|
||||
);
|
||||
|
||||
await SiteDataTestUtils.clear();
|
||||
});
|
||||
|
||||
add_task(async function test_deleteBySite_pattern() {
|
||||
info("Set content prefs");
|
||||
await setContentPref("example.com", "foo", "foo", false);
|
||||
await setContentPref("example.org", "bar", "bar", false);
|
||||
await setContentPref("example.org", "barPBM", "barPBM", true);
|
||||
await setContentPref("foo.example.org", "bar", "bar", false);
|
||||
await setContentPref("foo.example.org", "subPBM", "subPBM", true);
|
||||
|
||||
info("Verify content prefs have been set");
|
||||
Assert.equal(await getContentPref("example.com", "foo", false), "foo");
|
||||
Assert.equal(await getContentPref("example.org", "bar", false), "bar");
|
||||
Assert.equal(await getContentPref("example.org", "barPBM", true), "barPBM");
|
||||
Assert.equal(await getContentPref("foo.example.org", "bar", false), "bar");
|
||||
Assert.equal(
|
||||
await getContentPref("foo.example.org", "subPBM", true),
|
||||
"subPBM"
|
||||
);
|
||||
|
||||
await new Promise(aResolve => {
|
||||
Services.clearData.deleteDataFromSite(
|
||||
"example.org",
|
||||
{ privateBrowsingId: 1 },
|
||||
true,
|
||||
Ci.nsIClearDataService.CLEAR_CONTENT_PREFERENCES,
|
||||
value => {
|
||||
Assert.equal(value, 0);
|
||||
aResolve();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
info(
|
||||
"Verify content prefs for 'example.org' have been cleared, but only for PBM."
|
||||
);
|
||||
Assert.equal(
|
||||
await getContentPref("example.com", "foo", false),
|
||||
"foo",
|
||||
"Unrelated domain should have not been cleared."
|
||||
);
|
||||
Assert.equal(
|
||||
await getContentPref("example.org", "bar", false),
|
||||
"bar",
|
||||
"Base domain entry should NOT have been cleared for normal browsing."
|
||||
);
|
||||
Assert.equal(
|
||||
await getContentPref("example.org", "barPBM", true),
|
||||
undefined,
|
||||
"Base domain entry should have been cleared for private browsing."
|
||||
);
|
||||
Assert.equal(
|
||||
await getContentPref("foo.example.org", "bar", false),
|
||||
"bar",
|
||||
"Subdomain entry should not have been cleared for normal browsing."
|
||||
);
|
||||
Assert.equal(
|
||||
await getContentPref("foo.example.org", "subPBM", true),
|
||||
undefined,
|
||||
"Subdomain entry should have been cleared for private browsing."
|
||||
);
|
||||
|
||||
await SiteDataTestUtils.clear();
|
||||
});
|
||||
|
||||
// TODO: implement a proper range clearing test. We're currently lacking the
|
||||
// capability to set content prefs with a specific creation timestamp. This
|
||||
// tests only clearing everything if the entire time range is passed.
|
||||
add_task(async function test_deleteByRange() {
|
||||
info("Set content prefs");
|
||||
await setContentPref("example.com", "foo", "foo", false);
|
||||
await setContentPref("example.org", "bar", "bar", false);
|
||||
await setContentPref("example.org", "bar", "bar", true);
|
||||
await setContentPref("foo.example.org", "bar", "bar", false);
|
||||
|
||||
info("Verify content prefs have been set");
|
||||
Assert.equal(await getContentPref("example.com", "foo", false), "foo");
|
||||
Assert.equal(await getContentPref("example.org", "bar", false), "bar");
|
||||
Assert.equal(await getContentPref("example.org", "bar", true), "bar");
|
||||
Assert.equal(await getContentPref("foo.example.org", "bar", false), "bar");
|
||||
|
||||
info("Delete entire time range.");
|
||||
await new Promise(aResolve => {
|
||||
Services.clearData.deleteDataInTimeRange(
|
||||
0,
|
||||
Date.now() * 1000,
|
||||
true,
|
||||
Ci.nsIClearDataService.CLEAR_CONTENT_PREFERENCES,
|
||||
value => {
|
||||
Assert.equal(value, 0);
|
||||
aResolve();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
info("Verify all content prefs have been cleared");
|
||||
Assert.equal(await getContentPref("example.com", "foo", false), undefined);
|
||||
Assert.equal(await getContentPref("example.org", "bar", false), undefined);
|
||||
Assert.equal(await getContentPref("example.org", "bar", true), undefined);
|
||||
Assert.equal(
|
||||
await getContentPref("foo.example.org", "bar", false),
|
||||
undefined
|
||||
);
|
||||
|
||||
await SiteDataTestUtils.clear();
|
||||
});
|
||||
|
||||
add_task(async function test_deleteAll() {
|
||||
info("Set content prefs");
|
||||
await setContentPref("example.com", "foo", "foo", false);
|
||||
await setContentPref("example.org", "bar", "bar", false);
|
||||
await setContentPref("example.org", "bar", "bar", true);
|
||||
await setContentPref("foo.example.org", "bar", "bar", false);
|
||||
|
||||
info("Verify content prefs have been set");
|
||||
Assert.equal(await getContentPref("example.com", "foo", false), "foo");
|
||||
Assert.equal(await getContentPref("example.org", "bar", false), "bar");
|
||||
Assert.equal(await getContentPref("example.org", "bar", true), "bar");
|
||||
Assert.equal(await getContentPref("foo.example.org", "bar", false), "bar");
|
||||
|
||||
await new Promise(aResolve => {
|
||||
Services.clearData.deleteData(
|
||||
Ci.nsIClearDataService.CLEAR_CONTENT_PREFERENCES,
|
||||
value => {
|
||||
Assert.equal(value, 0);
|
||||
aResolve();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
info("Verify all content prefs have been cleared");
|
||||
Assert.equal(await getContentPref("example.com", "foo", false), undefined);
|
||||
Assert.equal(await getContentPref("example.org", "bar", false), undefined);
|
||||
Assert.equal(await getContentPref("example.org", "bar", true), undefined);
|
||||
Assert.equal(
|
||||
await getContentPref("foo.example.org", "bar", false),
|
||||
undefined
|
||||
);
|
||||
|
||||
await SiteDataTestUtils.clear();
|
||||
});
|
@ -19,6 +19,8 @@ skip-if = ["condprof"] # Bug 1893058
|
||||
|
||||
["test_clear_data_service_flags.js"]
|
||||
|
||||
["test_content_preferences.js"]
|
||||
|
||||
["test_cookie_banner_handling.js"]
|
||||
|
||||
["test_cookies.js"]
|
||||
|
@ -529,16 +529,18 @@ ContentPrefService2.prototype = {
|
||||
this._cache.remove(sgroup, name);
|
||||
}
|
||||
|
||||
let isPrivate = context && context.usePrivateBrowsing;
|
||||
let stmts = [];
|
||||
|
||||
// First get the matching prefs.
|
||||
stmts.push(this._commonGetStmt(group, name, includeSubdomains));
|
||||
if (context == null || !isPrivate) {
|
||||
// First get the matching prefs.
|
||||
stmts.push(this._commonGetStmt(group, name, includeSubdomains));
|
||||
|
||||
// Delete the matching prefs.
|
||||
let stmt = this._stmtWithGroupClause(
|
||||
group,
|
||||
includeSubdomains,
|
||||
`
|
||||
// Delete the matching prefs.
|
||||
let stmt = this._stmtWithGroupClause(
|
||||
group,
|
||||
includeSubdomains,
|
||||
`
|
||||
DELETE FROM prefs
|
||||
WHERE settingID = (SELECT id FROM settings WHERE name = :name) AND
|
||||
CASE typeof(:group)
|
||||
@ -546,45 +548,69 @@ ContentPrefService2.prototype = {
|
||||
ELSE prefs.groupID IN (${GROUP_CLAUSE})
|
||||
END
|
||||
`
|
||||
);
|
||||
stmt.params.name = name;
|
||||
stmts.push(stmt);
|
||||
);
|
||||
stmt.params.name = name;
|
||||
stmts.push(stmt);
|
||||
|
||||
stmts = stmts.concat(this._settingsAndGroupsCleanupStmts());
|
||||
stmts = stmts.concat(this._settingsAndGroupsCleanupStmts());
|
||||
}
|
||||
|
||||
let prefs = new ContentPrefStore();
|
||||
let prefsNonPrivateBrowsing = new ContentPrefStore();
|
||||
|
||||
let isPrivate = context && context.usePrivateBrowsing;
|
||||
this._execStmts(stmts, {
|
||||
onRow: row => {
|
||||
let grp = row.getResultByName("grp");
|
||||
prefs.set(grp, name, undefined);
|
||||
this._cache.set(grp, name, undefined);
|
||||
},
|
||||
onDone: (reason, ok) => {
|
||||
if (ok) {
|
||||
this._cache.set(group, name, undefined);
|
||||
if (isPrivate) {
|
||||
for (let [sgroup] of this._pbStore.match(
|
||||
group,
|
||||
name,
|
||||
includeSubdomains
|
||||
)) {
|
||||
prefs.set(sgroup, name, undefined);
|
||||
this._pbStore.remove(sgroup, name);
|
||||
}
|
||||
}
|
||||
// Only execute if we have statements to run. stmts is empty for clearing
|
||||
// only private browsing data.
|
||||
let queryPromise = Promise.resolve([
|
||||
Ci.nsIContentPrefService2.COMPLETE_OK,
|
||||
false,
|
||||
]);
|
||||
|
||||
if (stmts.length) {
|
||||
queryPromise = new Promise(resolve => {
|
||||
this._execStmts(stmts, {
|
||||
onRow: row => {
|
||||
let grp = row.getResultByName("grp");
|
||||
prefsNonPrivateBrowsing.set(grp, name, undefined);
|
||||
this._cache.set(grp, name, undefined);
|
||||
},
|
||||
onDone: (reason, ok) => {
|
||||
this._cache.set(group, name, undefined);
|
||||
resolve([reason, ok]);
|
||||
},
|
||||
onError: nsresult => {
|
||||
cbHandleError(callback, nsresult);
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
let prefsPrivateBrowsing = new ContentPrefStore();
|
||||
|
||||
if (isPrivate || context == null) {
|
||||
for (let [sgroup] of this._pbStore.match(
|
||||
group,
|
||||
name,
|
||||
includeSubdomains
|
||||
)) {
|
||||
prefsPrivateBrowsing.set(sgroup, name, undefined);
|
||||
this._pbStore.remove(sgroup, name);
|
||||
}
|
||||
}
|
||||
|
||||
queryPromise.then(([reason, hasNonPrivateEntries]) => {
|
||||
// Notify caller of completion.
|
||||
cbHandleCompletion(callback, reason);
|
||||
|
||||
// Notify for non PBM changes.
|
||||
if (hasNonPrivateEntries) {
|
||||
for (let [sgroup] of prefsNonPrivateBrowsing) {
|
||||
this._notifyPrefRemoved(sgroup, name, false);
|
||||
}
|
||||
cbHandleCompletion(callback, reason);
|
||||
if (ok) {
|
||||
for (let [sgroup, ,] of prefs) {
|
||||
this._notifyPrefRemoved(sgroup, name, isPrivate);
|
||||
}
|
||||
}
|
||||
},
|
||||
onError: nsresult => {
|
||||
cbHandleError(callback, nsresult);
|
||||
},
|
||||
}
|
||||
|
||||
// Notify for PBM changes.
|
||||
for (let [sgroup] of prefsPrivateBrowsing) {
|
||||
this._notifyPrefRemoved(sgroup, name, true);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
@ -634,93 +660,126 @@ ContentPrefService2.prototype = {
|
||||
this._cache.removeGroup(sgroup);
|
||||
}
|
||||
|
||||
let isPrivate = context?.usePrivateBrowsing;
|
||||
let stmts = [];
|
||||
|
||||
// First get the matching prefs, then delete groups and prefs that reference
|
||||
// deleted groups.
|
||||
if (group) {
|
||||
stmts.push(
|
||||
this._stmtWithGroupClause(
|
||||
group,
|
||||
includeSubdomains,
|
||||
`
|
||||
SELECT groups.name AS grp, settings.name AS name
|
||||
FROM prefs
|
||||
JOIN settings ON settings.id = prefs.settingID
|
||||
JOIN groups ON groups.id = prefs.groupID
|
||||
WHERE prefs.groupID IN (${GROUP_CLAUSE})
|
||||
`
|
||||
)
|
||||
);
|
||||
stmts.push(
|
||||
this._stmtWithGroupClause(
|
||||
group,
|
||||
includeSubdomains,
|
||||
`DELETE FROM groups WHERE id IN (${GROUP_CLAUSE})`
|
||||
)
|
||||
);
|
||||
// For null we clear normal and private browsing data. false only clears
|
||||
// normal browsing data. true only clears private browsing data.
|
||||
if (context == null || !isPrivate) {
|
||||
// First get the matching prefs, then delete groups and prefs that reference
|
||||
// deleted groups.
|
||||
if (group) {
|
||||
stmts.push(
|
||||
this._stmtWithGroupClause(
|
||||
group,
|
||||
includeSubdomains,
|
||||
`
|
||||
SELECT groups.name AS grp, settings.name AS name
|
||||
FROM prefs
|
||||
JOIN settings ON settings.id = prefs.settingID
|
||||
JOIN groups ON groups.id = prefs.groupID
|
||||
WHERE prefs.groupID IN (${GROUP_CLAUSE})
|
||||
`
|
||||
)
|
||||
);
|
||||
stmts.push(
|
||||
this._stmtWithGroupClause(
|
||||
group,
|
||||
includeSubdomains,
|
||||
`DELETE FROM groups WHERE id IN (${GROUP_CLAUSE})`
|
||||
)
|
||||
);
|
||||
stmts.push(
|
||||
this._stmt(`
|
||||
DELETE FROM prefs
|
||||
WHERE groupID NOTNULL AND groupID NOT IN (SELECT id FROM groups)
|
||||
`)
|
||||
);
|
||||
} else {
|
||||
stmts.push(
|
||||
this._stmt(`
|
||||
SELECT NULL AS grp, settings.name AS name
|
||||
FROM prefs
|
||||
JOIN settings ON settings.id = prefs.settingID
|
||||
WHERE prefs.groupID IS NULL
|
||||
`)
|
||||
);
|
||||
stmts.push(this._stmt("DELETE FROM prefs WHERE groupID IS NULL"));
|
||||
}
|
||||
|
||||
// Finally delete settings that are no longer referenced.
|
||||
stmts.push(
|
||||
this._stmt(`
|
||||
DELETE FROM prefs
|
||||
WHERE groupID NOTNULL AND groupID NOT IN (SELECT id FROM groups)
|
||||
DELETE FROM settings
|
||||
WHERE id NOT IN (SELECT DISTINCT settingID FROM prefs)
|
||||
`)
|
||||
);
|
||||
} else {
|
||||
stmts.push(
|
||||
this._stmt(`
|
||||
SELECT NULL AS grp, settings.name AS name
|
||||
FROM prefs
|
||||
JOIN settings ON settings.id = prefs.settingID
|
||||
WHERE prefs.groupID IS NULL
|
||||
`)
|
||||
);
|
||||
stmts.push(this._stmt("DELETE FROM prefs WHERE groupID IS NULL"));
|
||||
}
|
||||
|
||||
// Finally delete settings that are no longer referenced.
|
||||
stmts.push(
|
||||
this._stmt(`
|
||||
DELETE FROM settings
|
||||
WHERE id NOT IN (SELECT DISTINCT settingID FROM prefs)
|
||||
`)
|
||||
);
|
||||
let prefsNonPrivateBrowsing = new ContentPrefStore();
|
||||
|
||||
let prefs = new ContentPrefStore();
|
||||
// Only execute if we have statements to run. stmts is empty for clearing
|
||||
// only private browsing data.
|
||||
let queryPromise = Promise.resolve([
|
||||
Ci.nsIContentPrefService2.COMPLETE_OK,
|
||||
false,
|
||||
]);
|
||||
if (stmts.length) {
|
||||
queryPromise = new Promise(resolve => {
|
||||
this._execStmts(stmts, {
|
||||
onRow: row => {
|
||||
let grp = row.getResultByName("grp");
|
||||
let name = row.getResultByName("name");
|
||||
prefsNonPrivateBrowsing.set(grp, name, undefined);
|
||||
this._cache.set(grp, name, undefined);
|
||||
},
|
||||
onDone: (reason, ok) => {
|
||||
resolve([reason, ok]);
|
||||
},
|
||||
onError: nsresult => {
|
||||
cbHandleError(callback, nsresult);
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
let isPrivate = context && context.usePrivateBrowsing;
|
||||
this._execStmts(stmts, {
|
||||
onRow: row => {
|
||||
let grp = row.getResultByName("grp");
|
||||
let name = row.getResultByName("name");
|
||||
prefs.set(grp, name, undefined);
|
||||
this._cache.set(grp, name, undefined);
|
||||
},
|
||||
onDone: (reason, ok) => {
|
||||
if (ok && isPrivate) {
|
||||
for (let [sgroup, sname] of this._pbStore) {
|
||||
if (
|
||||
!group ||
|
||||
(!includeSubdomains && group == sgroup) ||
|
||||
(includeSubdomains &&
|
||||
sgroup &&
|
||||
this._pbStore.groupsMatchIncludingSubdomains(group, sgroup))
|
||||
) {
|
||||
prefs.set(sgroup, sname, undefined);
|
||||
this._pbStore.remove(sgroup, sname);
|
||||
}
|
||||
}
|
||||
let prefsPrivateBrowsing = new ContentPrefStore();
|
||||
|
||||
if (isPrivate || context == null) {
|
||||
for (let [sgroup, sname] of this._pbStore) {
|
||||
if (
|
||||
!group ||
|
||||
(!includeSubdomains && group == sgroup) ||
|
||||
(includeSubdomains &&
|
||||
sgroup &&
|
||||
this._pbStore.groupsMatchIncludingSubdomains(group, sgroup))
|
||||
) {
|
||||
prefsPrivateBrowsing.set(sgroup, sname, undefined);
|
||||
this._pbStore.remove(sgroup, sname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
queryPromise
|
||||
.then(([reason, hasNonPrivateEntries]) => {
|
||||
// Notify caller of completion.
|
||||
cbHandleCompletion(callback, reason);
|
||||
if (ok) {
|
||||
for (let [sgroup, sname] of prefs) {
|
||||
this._notifyPrefRemoved(sgroup, sname, isPrivate);
|
||||
|
||||
// Notify for non PBM changes.
|
||||
if (hasNonPrivateEntries) {
|
||||
for (let [sgroup, sname] of prefsNonPrivateBrowsing) {
|
||||
this._notifyPrefRemoved(sgroup, sname, false);
|
||||
}
|
||||
}
|
||||
},
|
||||
onError: nsresult => {
|
||||
|
||||
// Notify for PBM changes.
|
||||
for (let [sgroup, sname] of prefsPrivateBrowsing) {
|
||||
this._notifyPrefRemoved(sgroup, sname, true);
|
||||
}
|
||||
})
|
||||
.catch(nsresult => {
|
||||
cbHandleError(callback, nsresult);
|
||||
},
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
_removeAllDomainsSince: function CPS2__removeAllDomainsSince(
|
||||
@ -737,60 +796,95 @@ ContentPrefService2.prototype = {
|
||||
// Invalidate all the group cache because we don't know which groups will be removed.
|
||||
this._cache.removeAllGroups();
|
||||
|
||||
let isPrivate = context?.usePrivateBrowsing;
|
||||
let stmts = [];
|
||||
|
||||
// Get prefs that are about to be removed to notify about their removal.
|
||||
let stmt = this._stmt(`
|
||||
SELECT groups.name AS grp, settings.name AS name
|
||||
FROM prefs
|
||||
JOIN settings ON settings.id = prefs.settingID
|
||||
JOIN groups ON groups.id = prefs.groupID
|
||||
WHERE timestamp >= :since
|
||||
`);
|
||||
stmt.params.since = since;
|
||||
stmts.push(stmt);
|
||||
// For null we clear normal and private browsing data. false only clears
|
||||
// normal browsing data. true only clears private browsing data.
|
||||
if (context == null || !isPrivate) {
|
||||
// Get prefs that are about to be removed to notify about their removal.
|
||||
let stmt = this._stmt(`
|
||||
SELECT groups.name AS grp, settings.name AS name
|
||||
FROM prefs
|
||||
JOIN settings ON settings.id = prefs.settingID
|
||||
JOIN groups ON groups.id = prefs.groupID
|
||||
WHERE timestamp >= :since
|
||||
`);
|
||||
stmt.params.since = since;
|
||||
stmts.push(stmt);
|
||||
|
||||
// Do the actual remove.
|
||||
stmt = this._stmt(`
|
||||
DELETE FROM prefs WHERE groupID NOTNULL AND timestamp >= :since
|
||||
`);
|
||||
stmt.params.since = since;
|
||||
stmts.push(stmt);
|
||||
// Do the actual remove.
|
||||
stmt = this._stmt(`
|
||||
DELETE FROM prefs WHERE groupID NOTNULL AND timestamp >= :since
|
||||
`);
|
||||
stmt.params.since = since;
|
||||
stmts.push(stmt);
|
||||
|
||||
// Cleanup no longer used values.
|
||||
stmts = stmts.concat(this._settingsAndGroupsCleanupStmts());
|
||||
// Cleanup no longer used values.
|
||||
stmts = stmts.concat(this._settingsAndGroupsCleanupStmts());
|
||||
}
|
||||
|
||||
let prefs = new ContentPrefStore();
|
||||
let isPrivate = context && context.usePrivateBrowsing;
|
||||
this._execStmts(stmts, {
|
||||
onRow: row => {
|
||||
let grp = row.getResultByName("grp");
|
||||
let name = row.getResultByName("name");
|
||||
prefs.set(grp, name, undefined);
|
||||
this._cache.set(grp, name, undefined);
|
||||
},
|
||||
onDone: (reason, ok) => {
|
||||
// This nukes all the groups in _pbStore since we don't have their timestamp
|
||||
// information.
|
||||
if (ok && isPrivate) {
|
||||
for (let [sgroup, sname] of this._pbStore) {
|
||||
if (sgroup) {
|
||||
prefs.set(sgroup, sname, undefined);
|
||||
}
|
||||
}
|
||||
this._pbStore.removeAllGroups();
|
||||
let prefsNonPrivateBrowsing = new ContentPrefStore();
|
||||
|
||||
// Only execute if we have statements to run. stmts is empty for clearing
|
||||
// only private browsing data.
|
||||
let queryPromise = Promise.resolve([
|
||||
Ci.nsIContentPrefService2.COMPLETE_OK,
|
||||
false,
|
||||
]);
|
||||
|
||||
if (stmts.length) {
|
||||
queryPromise = new Promise(resolve => {
|
||||
this._execStmts(stmts, {
|
||||
onRow: row => {
|
||||
let grp = row.getResultByName("grp");
|
||||
let name = row.getResultByName("name");
|
||||
prefsNonPrivateBrowsing.set(grp, name, undefined);
|
||||
this._cache.set(grp, name, undefined);
|
||||
},
|
||||
onDone: (reason, ok) => {
|
||||
resolve([reason, ok]);
|
||||
},
|
||||
onError: nsresult => {
|
||||
cbHandleError(callback, nsresult);
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
let prefsPrivateBrowsing = new ContentPrefStore();
|
||||
|
||||
// This nukes all the groups in _pbStore since we don't have their timestamp
|
||||
// information.
|
||||
if (isPrivate || context == null) {
|
||||
for (let [sgroup, sname] of this._pbStore) {
|
||||
if (sgroup) {
|
||||
prefsPrivateBrowsing.set(sgroup, sname, undefined);
|
||||
}
|
||||
}
|
||||
this._pbStore.removeAllGroups();
|
||||
}
|
||||
|
||||
queryPromise
|
||||
.then(([reason, hasNonPrivateEntries]) => {
|
||||
// Notify caller of completion.
|
||||
cbHandleCompletion(callback, reason);
|
||||
if (ok) {
|
||||
for (let [sgroup, sname] of prefs) {
|
||||
this._notifyPrefRemoved(sgroup, sname, isPrivate);
|
||||
|
||||
// Notify for non PBM changes.
|
||||
if (hasNonPrivateEntries) {
|
||||
for (let [sgroup, sname] of prefsNonPrivateBrowsing) {
|
||||
this._notifyPrefRemoved(sgroup, sname, false);
|
||||
}
|
||||
}
|
||||
},
|
||||
onError: nsresult => {
|
||||
|
||||
// Notify for PBM changes.
|
||||
for (let [sgroup, sname] of prefsPrivateBrowsing) {
|
||||
this._notifyPrefRemoved(sgroup, sname, true);
|
||||
}
|
||||
})
|
||||
.catch(nsresult => {
|
||||
cbHandleError(callback, nsresult);
|
||||
},
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
removeAllDomainsSince: function CPS2_removeAllDomainsSince(
|
||||
@ -817,76 +911,110 @@ ContentPrefService2.prototype = {
|
||||
}
|
||||
}
|
||||
|
||||
let isPrivate = context?.usePrivateBrowsing;
|
||||
let stmts = [];
|
||||
|
||||
// First get the matching prefs. Include null if any of those prefs are
|
||||
// global.
|
||||
let stmt = this._stmt(`
|
||||
SELECT groups.name AS grp
|
||||
FROM prefs
|
||||
JOIN settings ON settings.id = prefs.settingID
|
||||
JOIN groups ON groups.id = prefs.groupID
|
||||
WHERE settings.name = :name
|
||||
UNION
|
||||
SELECT NULL AS grp
|
||||
WHERE EXISTS (
|
||||
SELECT prefs.id
|
||||
// For null we clear normal and private browsing data. false only clears
|
||||
// normal browsing data. true only clears private browsing data.
|
||||
if (context == null || !isPrivate) {
|
||||
// First get the matching prefs. Include null if any of those prefs are
|
||||
// global.
|
||||
let stmt = this._stmt(`
|
||||
SELECT groups.name AS grp
|
||||
FROM prefs
|
||||
JOIN settings ON settings.id = prefs.settingID
|
||||
WHERE settings.name = :name AND prefs.groupID IS NULL
|
||||
)
|
||||
`);
|
||||
stmt.params.name = name;
|
||||
stmts.push(stmt);
|
||||
JOIN groups ON groups.id = prefs.groupID
|
||||
WHERE settings.name = :name
|
||||
UNION
|
||||
SELECT NULL AS grp
|
||||
WHERE EXISTS (
|
||||
SELECT prefs.id
|
||||
FROM prefs
|
||||
JOIN settings ON settings.id = prefs.settingID
|
||||
WHERE settings.name = :name AND prefs.groupID IS NULL
|
||||
)
|
||||
`);
|
||||
stmt.params.name = name;
|
||||
stmts.push(stmt);
|
||||
|
||||
// Delete the target settings.
|
||||
stmt = this._stmt("DELETE FROM settings WHERE name = :name");
|
||||
stmt.params.name = name;
|
||||
stmts.push(stmt);
|
||||
// Delete the target settings.
|
||||
stmt = this._stmt("DELETE FROM settings WHERE name = :name");
|
||||
stmt.params.name = name;
|
||||
stmts.push(stmt);
|
||||
|
||||
// Delete prefs and groups that are no longer used.
|
||||
stmts.push(
|
||||
this._stmt(
|
||||
"DELETE FROM prefs WHERE settingID NOT IN (SELECT id FROM settings)"
|
||||
)
|
||||
);
|
||||
stmts.push(
|
||||
this._stmt(`
|
||||
DELETE FROM groups WHERE id NOT IN (
|
||||
SELECT DISTINCT groupID FROM prefs WHERE groupID NOTNULL
|
||||
)
|
||||
`)
|
||||
);
|
||||
// Delete prefs and groups that are no longer used.
|
||||
stmts.push(
|
||||
this._stmt(
|
||||
"DELETE FROM prefs WHERE settingID NOT IN (SELECT id FROM settings)"
|
||||
)
|
||||
);
|
||||
stmts.push(
|
||||
this._stmt(`
|
||||
DELETE FROM groups WHERE id NOT IN (
|
||||
SELECT DISTINCT groupID FROM prefs WHERE groupID NOTNULL
|
||||
)
|
||||
`)
|
||||
);
|
||||
}
|
||||
|
||||
let prefs = new ContentPrefStore();
|
||||
let isPrivate = context && context.usePrivateBrowsing;
|
||||
let prefsNonPrivateBrowsing = new ContentPrefStore();
|
||||
|
||||
this._execStmts(stmts, {
|
||||
onRow: row => {
|
||||
let grp = row.getResultByName("grp");
|
||||
prefs.set(grp, name, undefined);
|
||||
this._cache.set(grp, name, undefined);
|
||||
},
|
||||
onDone: (reason, ok) => {
|
||||
if (ok && isPrivate) {
|
||||
for (let [sgroup, sname] of this._pbStore) {
|
||||
if (sname === name) {
|
||||
prefs.set(sgroup, name, undefined);
|
||||
this._pbStore.remove(sgroup, name);
|
||||
}
|
||||
}
|
||||
// Only execute if we have statements to run. stmts is empty for clearing
|
||||
// only private browsing data.
|
||||
let queryPromise = Promise.resolve([
|
||||
Ci.nsIContentPrefService2.COMPLETE_OK,
|
||||
false,
|
||||
]);
|
||||
|
||||
if (stmts.length) {
|
||||
queryPromise = new Promise(resolve => {
|
||||
this._execStmts(stmts, {
|
||||
onRow: row => {
|
||||
let grp = row.getResultByName("grp");
|
||||
prefsNonPrivateBrowsing.set(grp, name, undefined);
|
||||
this._cache.set(grp, name, undefined);
|
||||
},
|
||||
onDone: (reason, ok) => {
|
||||
resolve([reason, ok]);
|
||||
},
|
||||
onError: nsresult => {
|
||||
cbHandleError(callback, nsresult);
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
let prefsPrivateBrowsing = new ContentPrefStore();
|
||||
|
||||
if (isPrivate || context == null) {
|
||||
for (let [sgroup, sname] of this._pbStore) {
|
||||
if (sname === name) {
|
||||
prefsPrivateBrowsing.set(sgroup, name, undefined);
|
||||
this._pbStore.remove(sgroup, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
queryPromise
|
||||
.then(([reason, hasNonPrivateEntries]) => {
|
||||
// Notify caller of completion.
|
||||
cbHandleCompletion(callback, reason);
|
||||
if (ok) {
|
||||
for (let [sgroup, ,] of prefs) {
|
||||
this._notifyPrefRemoved(sgroup, name, isPrivate);
|
||||
|
||||
// Notify for non PBM changes.
|
||||
if (hasNonPrivateEntries) {
|
||||
for (let [sgroup, ,] of prefsNonPrivateBrowsing) {
|
||||
this._notifyPrefRemoved(sgroup, name, false);
|
||||
}
|
||||
}
|
||||
},
|
||||
onError: nsresult => {
|
||||
|
||||
// Notify for PBM changes.
|
||||
for (let [sgroup, ,] of prefsPrivateBrowsing) {
|
||||
this._notifyPrefRemoved(sgroup, name, true);
|
||||
}
|
||||
})
|
||||
.catch(nsresult => {
|
||||
cbHandleError(callback, nsresult);
|
||||
},
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -175,16 +175,18 @@ add_task(async function privateBrowsing() {
|
||||
await set("a.com", "foo", 8, context);
|
||||
await setGlobal("foo", 9, context);
|
||||
await new Promise(resolve =>
|
||||
cps.removeByDomainAndName("a.com", "foo", context, makeCallback(resolve))
|
||||
// Passing context=null clears both normal and private browsing data.
|
||||
cps.removeByDomainAndName("a.com", "foo", null, makeCallback(resolve))
|
||||
);
|
||||
await new Promise(resolve =>
|
||||
cps.removeGlobal("foo", context, makeCallback(resolve))
|
||||
cps.removeGlobal("foo", null, makeCallback(resolve))
|
||||
);
|
||||
await new Promise(resolve =>
|
||||
cps.removeGlobal("qux", context, makeCallback(resolve))
|
||||
cps.removeGlobal("qux", null, makeCallback(resolve))
|
||||
);
|
||||
await new Promise(resolve =>
|
||||
cps.removeByDomainAndName("b.com", "foo", context, makeCallback(resolve))
|
||||
// Passing context=null clears both normal and private browsing data.
|
||||
cps.removeByDomainAndName("b.com", "foo", null, makeCallback(resolve))
|
||||
);
|
||||
await dbOK([
|
||||
["a.com", "bar", 2],
|
||||
@ -209,6 +211,74 @@ add_task(async function privateBrowsing() {
|
||||
await reset();
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests that when clearing data for normal browsing, private browsing is not
|
||||
* affected and vice versa.
|
||||
*/
|
||||
add_task(async function privateBrowsingIsolatedRemoval() {
|
||||
await set("a.com", "foo", 1);
|
||||
await set("a.com", "bar", 2);
|
||||
await setGlobal("foo", 3);
|
||||
await setGlobal("bar", 4);
|
||||
await setGlobal("qux", 5);
|
||||
await set("b.com", "foo", 6);
|
||||
await set("b.com", "bar", 7);
|
||||
|
||||
await set("a.com", "foo", 8, privateLoadContext);
|
||||
await set("b.com", "foo", 9, privateLoadContext);
|
||||
await setGlobal("foo", 10, privateLoadContext);
|
||||
|
||||
info("For a.com only clear the normal browsing entry.");
|
||||
await new Promise(resolve =>
|
||||
cps.removeByDomainAndName(
|
||||
"a.com",
|
||||
"foo",
|
||||
loadContext,
|
||||
makeCallback(resolve)
|
||||
)
|
||||
);
|
||||
|
||||
info("For a.com, 'foo' only the PBM entry should remain.");
|
||||
await getOK(["a.com", "foo", loadContext], undefined);
|
||||
await getOK(["a.com", "bar", loadContext], 2);
|
||||
await getGlobalOK(["foo", loadContext], 3);
|
||||
await getGlobalOK(["bar", loadContext], 4);
|
||||
await getGlobalOK(["qux", loadContext], 5);
|
||||
await getOK(["b.com", "foo", loadContext], 6);
|
||||
await getOK(["b.com", "bar", loadContext], 7);
|
||||
|
||||
await getOK(["a.com", "foo", privateLoadContext], 8);
|
||||
await getOK(["b.com", "foo", privateLoadContext], 9);
|
||||
await getGlobalOK(["foo", privateLoadContext], 10);
|
||||
|
||||
info("For b.com only clear PBM entry.");
|
||||
await new Promise(resolve =>
|
||||
cps.removeByDomainAndName(
|
||||
"b.com",
|
||||
"foo",
|
||||
privateLoadContext,
|
||||
makeCallback(resolve)
|
||||
)
|
||||
);
|
||||
|
||||
info("For b.com, 'foo' only the non PBM entry should remain.");
|
||||
await getOK(["a.com", "foo", loadContext], undefined);
|
||||
await getOK(["a.com", "bar", loadContext], 2);
|
||||
await getGlobalOK(["foo", loadContext], 3);
|
||||
await getGlobalOK(["bar", loadContext], 4);
|
||||
await getGlobalOK(["qux", loadContext], 5);
|
||||
await getOK(["b.com", "foo", loadContext], 6);
|
||||
await getOK(["b.com", "bar", loadContext], 7);
|
||||
|
||||
await getOK(["a.com", "foo", privateLoadContext], 8);
|
||||
// This still returns an entry because even if a PBM load context is passed we
|
||||
// will fall back to non PBM entries with the same key.
|
||||
await getOK(["b.com", "foo", privateLoadContext], 6);
|
||||
await getGlobalOK(["foo", privateLoadContext], 10);
|
||||
|
||||
await reset();
|
||||
});
|
||||
|
||||
add_task(async function erroneous() {
|
||||
do_check_throws(() => cps.removeByDomainAndName(null, "foo", null));
|
||||
do_check_throws(() => cps.removeByDomainAndName("", "foo", null));
|
||||
|
@ -51,7 +51,8 @@ add_task(async function privateBrowsing() {
|
||||
await set("a.com", "foo", 6, context);
|
||||
await setGlobal("foo", 7, context);
|
||||
await new Promise(resolve =>
|
||||
cps.removeAllDomains(context, makeCallback(resolve))
|
||||
// Passing context=null clears both normal and private browsing data.
|
||||
cps.removeAllDomains(null, makeCallback(resolve))
|
||||
);
|
||||
await dbOK([
|
||||
[null, "foo", 3],
|
||||
|
@ -73,7 +73,8 @@ add_task(async function privateBrowsing() {
|
||||
await set("a.com", "foo", 6, context);
|
||||
await setGlobal("foo", 7, context);
|
||||
await new Promise(resolve =>
|
||||
cps.removeAllDomainsSince(0, context, makeCallback(resolve))
|
||||
// Passing context=null clears both normal and private browsing data.
|
||||
cps.removeAllDomainsSince(0, null, makeCallback(resolve))
|
||||
);
|
||||
await dbOK([
|
||||
[null, "foo", 3],
|
||||
@ -93,6 +94,63 @@ add_task(async function privateBrowsing() {
|
||||
await reset();
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests that when clearing data for normal browsing, private browsing is not
|
||||
* affected and vice versa.
|
||||
*/
|
||||
add_task(async function privateBrowsingIsolatedRemoval() {
|
||||
await set("a.com", "foo", 1);
|
||||
await set("a.com", "bar", 2);
|
||||
await setGlobal("foo", 3);
|
||||
await setGlobal("bar", 4);
|
||||
await setGlobal("qux", 5);
|
||||
await set("b.com", "foo", 6);
|
||||
await set("b.com", "bar", 7);
|
||||
|
||||
await set("a.com", "foo", 8, privateLoadContext);
|
||||
await set("b.com", "foo", 9, privateLoadContext);
|
||||
await setGlobal("foo", 10, privateLoadContext);
|
||||
|
||||
info("Clear all PBM data.");
|
||||
await new Promise(resolve =>
|
||||
cps.removeAllDomainsSince(0, privateLoadContext, makeCallback(resolve))
|
||||
);
|
||||
|
||||
await getOK(["a.com", "foo", loadContext], 1);
|
||||
await getOK(["a.com", "bar", loadContext], 2);
|
||||
await getGlobalOK(["foo", loadContext], 3);
|
||||
await getGlobalOK(["bar", loadContext], 4);
|
||||
await getGlobalOK(["qux", loadContext], 5);
|
||||
await getOK(["b.com", "foo", loadContext], 6);
|
||||
await getOK(["b.com", "bar", loadContext], 7);
|
||||
|
||||
// This still returns an entry because even if a PBM load context is passed we
|
||||
// will fall back to non PBM entries with the same key.
|
||||
await getOK(["a.com", "foo", privateLoadContext], 1);
|
||||
await getOK(["b.com", "foo", privateLoadContext], 6);
|
||||
await getGlobalOK(["foo", privateLoadContext], 10);
|
||||
|
||||
info("Clear all non PBM data.");
|
||||
await new Promise(resolve =>
|
||||
cps.removeAllDomainsSince(0, loadContext, makeCallback(resolve))
|
||||
);
|
||||
|
||||
info("Should have cleared all domain keyed entries");
|
||||
await getOK(["a.com", "foo", loadContext], undefined);
|
||||
await getOK(["a.com", "bar", loadContext], undefined);
|
||||
await getGlobalOK(["foo", loadContext], 3);
|
||||
await getGlobalOK(["bar", loadContext], 4);
|
||||
await getGlobalOK(["qux", loadContext], 5);
|
||||
await getOK(["b.com", "foo", loadContext], undefined);
|
||||
await getOK(["b.com", "bar", loadContext], undefined);
|
||||
|
||||
await getOK(["a.com", "foo", privateLoadContext], undefined);
|
||||
await getOK(["b.com", "foo", privateLoadContext], undefined);
|
||||
await getGlobalOK(["foo", privateLoadContext], 10);
|
||||
|
||||
await reset();
|
||||
});
|
||||
|
||||
add_task(async function erroneous() {
|
||||
do_check_throws(() => cps.removeAllDomainsSince(null, "bogus"));
|
||||
await reset();
|
||||
|
@ -149,12 +149,14 @@ add_task(async function privateBrowsing() {
|
||||
await set("b.com", "foo", 7, context);
|
||||
await setGlobal("foo", 8, context);
|
||||
await new Promise(resolve =>
|
||||
cps.removeByDomain("a.com", context, makeCallback(resolve))
|
||||
// Passing context=null clears both normal and private browsing data.
|
||||
cps.removeByDomain("a.com", null, makeCallback(resolve))
|
||||
);
|
||||
await getOK(["b.com", "foo", context], 7);
|
||||
await getGlobalOK(["foo", context], 8);
|
||||
await new Promise(resolve =>
|
||||
cps.removeAllGlobals(context, makeCallback(resolve))
|
||||
// Passing context=null clears both normal and private browsing data.
|
||||
cps.removeAllGlobals(null, makeCallback(resolve))
|
||||
);
|
||||
await dbOK([["b.com", "foo", 5]]);
|
||||
await getOK(["a.com", "foo", context], undefined);
|
||||
@ -171,6 +173,65 @@ add_task(async function privateBrowsing() {
|
||||
await reset();
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests that when clearing data for normal browsing, private browsing is not
|
||||
* affected and vice versa.
|
||||
*/
|
||||
add_task(async function privateBrowsingIsolatedRemoval() {
|
||||
await set("a.com", "foo", 1);
|
||||
await set("a.com", "bar", 2);
|
||||
await setGlobal("foo", 3);
|
||||
await setGlobal("bar", 4);
|
||||
await setGlobal("qux", 5);
|
||||
await set("b.com", "foo", 6);
|
||||
await set("b.com", "bar", 7);
|
||||
|
||||
await set("a.com", "foo", 8, privateLoadContext);
|
||||
await set("b.com", "foo", 9, privateLoadContext);
|
||||
await setGlobal("foo", 10, privateLoadContext);
|
||||
|
||||
info("For a.com only clear the normal browsing entries.");
|
||||
await new Promise(resolve =>
|
||||
cps.removeByDomain("a.com", loadContext, makeCallback(resolve))
|
||||
);
|
||||
|
||||
info("For a.com only the PBM entries should remain.");
|
||||
await getOK(["a.com", "foo", loadContext], undefined);
|
||||
await getOK(["a.com", "bar", loadContext], undefined);
|
||||
await getGlobalOK(["foo", loadContext], 3);
|
||||
await getGlobalOK(["bar", loadContext], 4);
|
||||
await getGlobalOK(["qux", loadContext], 5);
|
||||
await getOK(["b.com", "foo", loadContext], 6);
|
||||
await getOK(["b.com", "bar", loadContext], 7);
|
||||
|
||||
await getOK(["a.com", "foo", privateLoadContext], 8);
|
||||
await getOK(["b.com", "foo", privateLoadContext], 9);
|
||||
await getGlobalOK(["foo", privateLoadContext], 10);
|
||||
|
||||
info("For b.com only clear PBM entries.");
|
||||
await new Promise(resolve =>
|
||||
cps.removeByDomain("b.com", privateLoadContext, makeCallback(resolve))
|
||||
);
|
||||
|
||||
info("For b.com only the non PBM entries should remain.");
|
||||
await getOK(["a.com", "foo", loadContext], undefined);
|
||||
await getOK(["a.com", "bar", loadContext], undefined);
|
||||
await getGlobalOK(["foo", loadContext], 3);
|
||||
await getGlobalOK(["bar", loadContext], 4);
|
||||
await getGlobalOK(["qux", loadContext], 5);
|
||||
await getOK(["b.com", "foo", loadContext], 6);
|
||||
await getOK(["b.com", "bar", loadContext], 7);
|
||||
|
||||
await getOK(["a.com", "foo", privateLoadContext], 8);
|
||||
info("b.com, foo, pbm should be cleared");
|
||||
// This still returns an entry because even if a PBM load context is passed we
|
||||
// will fall back to non PBM entries with the same key.
|
||||
await getOK(["b.com", "foo", privateLoadContext], 6);
|
||||
await getGlobalOK(["foo", privateLoadContext], 10);
|
||||
|
||||
await reset();
|
||||
});
|
||||
|
||||
add_task(async function erroneous() {
|
||||
do_check_throws(() => cps.removeByDomain(null, null));
|
||||
do_check_throws(() => cps.removeByDomain("", null));
|
||||
|
@ -60,7 +60,7 @@ add_task(async function privateBrowsing() {
|
||||
await setGlobal("foo", 8, context);
|
||||
await set("b.com", "bar", 9, context);
|
||||
await new Promise(resolve =>
|
||||
cps.removeByName("bar", context, makeCallback(resolve))
|
||||
cps.removeByName("bar", null, makeCallback(resolve))
|
||||
);
|
||||
await dbOK([
|
||||
["a.com", "foo", 1],
|
||||
@ -83,6 +83,107 @@ add_task(async function privateBrowsing() {
|
||||
await reset();
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests that when clearing data for normal browsing, private browsing is not
|
||||
* affected and vice versa.
|
||||
*/
|
||||
add_task(async function privateBrowsingIsolatedRemoval() {
|
||||
await set("a.com", "foo", 1);
|
||||
await set("a.com", "bar", 2);
|
||||
await setGlobal("foo", 3);
|
||||
await setGlobal("bar", 4);
|
||||
await setGlobal("qux", 5);
|
||||
await set("b.com", "foo", 6);
|
||||
await set("b.com", "bar", 7);
|
||||
|
||||
await set("a.com", "foo", 8, privateLoadContext);
|
||||
await set("b.com", "foo", 9, privateLoadContext);
|
||||
await set("b.com", "bar", 10, privateLoadContext);
|
||||
await setGlobal("foo", 11, privateLoadContext);
|
||||
|
||||
info("Clear 'foo' for non PBM.");
|
||||
await new Promise(resolve =>
|
||||
cps.removeByName("foo", loadContext, makeCallback(resolve))
|
||||
);
|
||||
|
||||
info("For 'foo' only the PBM entries should remain.");
|
||||
await getOK(["a.com", "foo", loadContext], undefined);
|
||||
await getOK(["a.com", "bar", loadContext], 2);
|
||||
await getGlobalOK(["foo", loadContext], undefined);
|
||||
await getGlobalOK(["bar", loadContext], 4);
|
||||
await getGlobalOK(["qux", loadContext], 5);
|
||||
await getOK(["b.com", "foo", loadContext], undefined);
|
||||
await getOK(["b.com", "bar", loadContext], 7);
|
||||
|
||||
await getOK(["a.com", "foo", privateLoadContext], 8);
|
||||
await getOK(["b.com", "foo", privateLoadContext], 9);
|
||||
await getOK(["b.com", "bar", privateLoadContext], 10);
|
||||
await getGlobalOK(["foo", privateLoadContext], 11);
|
||||
|
||||
info("Clear 'bar' for PBM.");
|
||||
await new Promise(resolve =>
|
||||
cps.removeByName("bar", privateLoadContext, makeCallback(resolve))
|
||||
);
|
||||
|
||||
info("For 'bar' only the non PBM entries should remain.");
|
||||
await getOK(["a.com", "foo", loadContext], undefined);
|
||||
await getOK(["a.com", "bar", loadContext], 2);
|
||||
await getGlobalOK(["foo", loadContext], undefined);
|
||||
await getGlobalOK(["bar", loadContext], 4);
|
||||
await getGlobalOK(["qux", loadContext], 5);
|
||||
await getOK(["b.com", "foo", loadContext], undefined);
|
||||
await getOK(["b.com", "bar", loadContext], 7);
|
||||
|
||||
await getOK(["a.com", "foo", privateLoadContext], 8);
|
||||
await getOK(["b.com", "foo", privateLoadContext], 9);
|
||||
// This still returns an entry because even if a PBM load context is passed we
|
||||
// will fall back to non PBM entry with the same key.
|
||||
await getOK(["b.com", "bar", privateLoadContext], 7);
|
||||
await getGlobalOK(["foo", privateLoadContext], 11);
|
||||
|
||||
info("Clear 'foo' for PBM.");
|
||||
await new Promise(resolve =>
|
||||
cps.removeByName("foo", privateLoadContext, makeCallback(resolve))
|
||||
);
|
||||
|
||||
info("All 'foo' entries should have been cleared.");
|
||||
await getOK(["a.com", "foo", loadContext], undefined);
|
||||
await getOK(["a.com", "bar", loadContext], 2);
|
||||
await getGlobalOK(["foo", loadContext], undefined);
|
||||
await getGlobalOK(["bar", loadContext], 4);
|
||||
await getGlobalOK(["qux", loadContext], 5);
|
||||
await getOK(["b.com", "foo", loadContext], undefined);
|
||||
await getOK(["b.com", "bar", loadContext], 7);
|
||||
|
||||
await getOK(["a.com", "foo", privateLoadContext], undefined);
|
||||
await getOK(["b.com", "foo", privateLoadContext], undefined);
|
||||
// This still returns an entry because even if a PBM load context is passed we
|
||||
// will fall back to non PBM entry with the same key.
|
||||
await getOK(["b.com", "bar", privateLoadContext], 7);
|
||||
await getGlobalOK(["foo", privateLoadContext], undefined);
|
||||
|
||||
info("Clear 'bar' for non PBM.");
|
||||
await new Promise(resolve =>
|
||||
cps.removeByName("bar", loadContext, makeCallback(resolve))
|
||||
);
|
||||
|
||||
info("All 'bar' and 'foo' entries should have been cleared.");
|
||||
await getOK(["a.com", "foo", loadContext], undefined);
|
||||
await getOK(["a.com", "bar", loadContext], undefined);
|
||||
await getGlobalOK(["foo", loadContext], undefined);
|
||||
await getGlobalOK(["bar", loadContext], undefined);
|
||||
await getGlobalOK(["qux", loadContext], 5);
|
||||
await getOK(["b.com", "foo", loadContext], undefined);
|
||||
await getOK(["b.com", "bar", loadContext], undefined);
|
||||
|
||||
await getOK(["a.com", "foo", privateLoadContext], undefined);
|
||||
await getOK(["b.com", "foo", privateLoadContext], undefined);
|
||||
await getOK(["b.com", "bar", privateLoadContext], undefined);
|
||||
await getGlobalOK(["foo", privateLoadContext], undefined);
|
||||
|
||||
await reset();
|
||||
});
|
||||
|
||||
add_task(async function erroneous() {
|
||||
do_check_throws(() => cps.removeByName("", null));
|
||||
do_check_throws(() => cps.removeByName(null, null));
|
||||
|
@ -58,23 +58,17 @@ var observer = {
|
||||
if (Services.prefs.prefHasUserValue(LAST_DIR_PREF)) {
|
||||
Services.prefs.clearUserPref(LAST_DIR_PREF);
|
||||
}
|
||||
// Ensure that purging session history causes both the session-only PB cache
|
||||
// and persistent prefs to be cleared.
|
||||
let promises = [
|
||||
new Promise(resolve =>
|
||||
lazy.cps2.removeByName(LAST_DIR_PREF, nonPrivateLoadContext, {
|
||||
handleCompletion: resolve,
|
||||
})
|
||||
),
|
||||
new Promise(resolve =>
|
||||
lazy.cps2.removeByName(LAST_DIR_PREF, privateLoadContext, {
|
||||
handleCompletion: resolve,
|
||||
})
|
||||
),
|
||||
];
|
||||
// Ensure that purging session history causes both the session-only PB
|
||||
// cache and persistent prefs to be cleared. Passing loadContext=null to
|
||||
// cps will clear both.
|
||||
let promise = new Promise(resolve =>
|
||||
lazy.cps2.removeByName(LAST_DIR_PREF, null, {
|
||||
handleCompletion: resolve,
|
||||
})
|
||||
);
|
||||
// This is for testing purposes.
|
||||
if (aSubject && typeof subject == "object") {
|
||||
aSubject.promise = Promise.all(promises);
|
||||
aSubject.promise = promise;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user