mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-20 22:27:31 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
75
toolkit/components/contentprefs/ContentPrefInstance.jsm
Normal file
75
toolkit/components/contentprefs/ContentPrefInstance.jsm
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
this.EXPORTED_SYMBOLS = ['ContentPrefInstance'];
|
||||
|
||||
// This is a wrapper for nsIContentPrefService that alleviates the need to pass
|
||||
// an nsILoadContext argument to every method. Pass the context to the constructor
|
||||
// instead and continue on your way in blissful ignorance.
|
||||
|
||||
this.ContentPrefInstance = function ContentPrefInstance(aContext) {
|
||||
this._contentPrefSvc = Cc["@mozilla.org/content-pref/service;1"].
|
||||
getService(Ci.nsIContentPrefService);
|
||||
this._context = aContext;
|
||||
};
|
||||
|
||||
ContentPrefInstance.prototype = {
|
||||
getPref: function ContentPrefInstance_init(aName, aGroup, aCallback) {
|
||||
return this._contentPrefSvc.getPref(aName, aGroup, this._context, aCallback);
|
||||
},
|
||||
|
||||
setPref: function ContentPrefInstance_setPref(aGroup, aName, aValue, aContext) {
|
||||
return this._contentPrefSvc.setPref(aGroup, aName, aValue,
|
||||
aContext ? aContext : this._context);
|
||||
},
|
||||
|
||||
hasPref: function ContentPrefInstance_hasPref(aGroup, aName) {
|
||||
return this._contentPrefSvc.hasPref(aGroup, aName, this._context);
|
||||
},
|
||||
|
||||
hasCachedPref: function ContentPrefInstance_hasCachedPref(aGroup, aName) {
|
||||
return this._contentPrefSvc.hasCachedPref(aGroup, aName, this._context);
|
||||
},
|
||||
|
||||
removePref: function ContentPrefInstance_removePref(aGroup, aName) {
|
||||
return this._contentPrefSvc.removePref(aGroup, aName, this._context);
|
||||
},
|
||||
|
||||
removeGroupedPrefs: function ContentPrefInstance_removeGroupedPrefs() {
|
||||
return this._contentPrefSvc.removeGroupedPrefs(this._context);
|
||||
},
|
||||
|
||||
removePrefsByName: function ContentPrefInstance_removePrefsByName(aName) {
|
||||
return this._contentPrefSvc.removePrefsByName(aName, this._context);
|
||||
},
|
||||
|
||||
getPrefs: function ContentPrefInstance_getPrefs(aGroup) {
|
||||
return this._contentPrefSvc.getPrefs(aGroup, this._context);
|
||||
},
|
||||
|
||||
getPrefsByName: function ContentPrefInstance_getPrefsByName(aName) {
|
||||
return this._contentPrefSvc.getPrefsByName(aName, this._context);
|
||||
},
|
||||
|
||||
addObserver: function ContentPrefInstance_addObserver(aName, aObserver) {
|
||||
return this._contentPrefSvc.addObserver(aName, aObserver);
|
||||
},
|
||||
|
||||
removeObserver: function ContentPrefInstance_removeObserver(aName, aObserver) {
|
||||
return this._contentPrefSvc.removeObserver(aName, aObserver);
|
||||
},
|
||||
|
||||
get grouper() {
|
||||
return this._contentPrefSvc.grouper;
|
||||
},
|
||||
|
||||
get DBConnection() {
|
||||
return this._contentPrefSvc.DBConnection;
|
||||
}
|
||||
};
|
||||
885
toolkit/components/contentprefs/ContentPrefService2.jsm
Normal file
885
toolkit/components/contentprefs/ContentPrefService2.jsm
Normal file
|
|
@ -0,0 +1,885 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// This file is an XPCOM component that implements nsIContentPrefService2.
|
||||
// Although it's a JSM, it's not intended to be imported by consumers like JSMs
|
||||
// are usually imported. It's only a JSM so that nsContentPrefService.js can
|
||||
// easily use it. Consumers should access this component with the usual XPCOM
|
||||
// rigmarole:
|
||||
//
|
||||
// Cc["@mozilla.org/content-pref/service;1"].
|
||||
// getService(Ci.nsIContentPrefService2);
|
||||
//
|
||||
// That contract ID actually belongs to nsContentPrefService.js, which, when
|
||||
// QI'ed to nsIContentPrefService2, returns an instance of this component.
|
||||
//
|
||||
// The plan is to eventually remove nsIContentPrefService and its
|
||||
// implementation, nsContentPrefService.js. At such time this file can stop
|
||||
// being a JSM, and the "_cps" parts that ContentPrefService2 relies on and
|
||||
// NSGetFactory and all the other XPCOM initialization goop in
|
||||
// nsContentPrefService.js can be moved here.
|
||||
//
|
||||
// See https://bugzilla.mozilla.org/show_bug.cgi?id=699859
|
||||
|
||||
var EXPORTED_SYMBOLS = [
|
||||
"ContentPrefService2",
|
||||
];
|
||||
|
||||
const { interfaces: Ci, classes: Cc, results: Cr, utils: Cu } = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/ContentPrefUtils.jsm");
|
||||
Cu.import("resource://gre/modules/ContentPrefStore.jsm");
|
||||
|
||||
const GROUP_CLAUSE = `
|
||||
SELECT id
|
||||
FROM groups
|
||||
WHERE name = :group OR
|
||||
(:includeSubdomains AND name LIKE :pattern ESCAPE '/')
|
||||
`;
|
||||
|
||||
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] of 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] of 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,
|
||||
callback) {
|
||||
checkGroupArg(group);
|
||||
this._get(group, name, true, context, callback);
|
||||
},
|
||||
|
||||
getGlobal: function CPS2_getGlobal(name, context, callback) {
|
||||
this._get(null, name, false, context, callback);
|
||||
},
|
||||
|
||||
_get: function CPS2__get(group, name, includeSubdomains, context, callback) {
|
||||
group = this._parseGroup(group);
|
||||
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, val] of
|
||||
this._pbStore.match(group, name, includeSubdomains)) {
|
||||
pbPrefs.set(sgroup, name, val);
|
||||
}
|
||||
}
|
||||
|
||||
this._execStmts([this._commonGetStmt(group, name, includeSubdomains)], {
|
||||
onRow: function onRow(row) {
|
||||
let grp = row.getResultByName("grp");
|
||||
let val = row.getResultByName("value");
|
||||
this._cache.set(grp, name, val);
|
||||
if (!pbPrefs.has(group, name))
|
||||
cbHandleResult(callback, new ContentPref(grp, name, val));
|
||||
},
|
||||
onDone: function onDone(reason, ok, gotRow) {
|
||||
if (ok) {
|
||||
if (!gotRow)
|
||||
this._cache.set(group, name, undefined);
|
||||
for (let [pbGroup, pbName, pbVal] of pbPrefs) {
|
||||
cbHandleResult(callback, new ContentPref(pbGroup, pbName, pbVal));
|
||||
}
|
||||
}
|
||||
cbHandleCompletion(callback, reason);
|
||||
},
|
||||
onError: function onError(nsresult) {
|
||||
cbHandleError(callback, nsresult);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
_commonGetStmt: function CPS2__commonGetStmt(group, name, includeSubdomains) {
|
||||
let stmt = group ?
|
||||
this._stmtWithGroupClause(group, includeSubdomains, `
|
||||
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 AND prefs.groupID IN (${GROUP_CLAUSE})
|
||||
`) :
|
||||
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
|
||||
`);
|
||||
stmt.params.name = name;
|
||||
return stmt;
|
||||
},
|
||||
|
||||
_stmtWithGroupClause: function CPS2__stmtWithGroupClause(group,
|
||||
includeSubdomains,
|
||||
sql) {
|
||||
let stmt = this._stmt(sql);
|
||||
stmt.params.group = group;
|
||||
stmt.params.includeSubdomains = includeSubdomains || false;
|
||||
stmt.params.pattern = "%." + stmt.escapeStringForLIKE(group, "/");
|
||||
return stmt;
|
||||
},
|
||||
|
||||
getCachedByDomainAndName: function CPS2_getCachedByDomainAndName(group,
|
||||
name,
|
||||
context) {
|
||||
checkGroupArg(group);
|
||||
let prefs = this._getCached(group, name, false, context);
|
||||
return prefs[0] || null;
|
||||
},
|
||||
|
||||
getCachedBySubdomainAndName: function CPS2_getCachedBySubdomainAndName(group,
|
||||
name,
|
||||
context,
|
||||
len) {
|
||||
checkGroupArg(group);
|
||||
let prefs = this._getCached(group, name, true, context);
|
||||
if (len)
|
||||
len.value = prefs.length;
|
||||
return prefs;
|
||||
},
|
||||
|
||||
getCachedGlobal: function CPS2_getCachedGlobal(name, context) {
|
||||
let prefs = this._getCached(null, name, false, context);
|
||||
return prefs[0] || null;
|
||||
},
|
||||
|
||||
_getCached: function CPS2__getCached(group, name, includeSubdomains,
|
||||
context) {
|
||||
group = this._parseGroup(group);
|
||||
checkNameArg(name);
|
||||
|
||||
let storesToCheck = [this._cache];
|
||||
if (context && context.usePrivateBrowsing)
|
||||
storesToCheck.push(this._pbStore);
|
||||
|
||||
let outStore = new ContentPrefStore();
|
||||
storesToCheck.forEach(function (store) {
|
||||
for (let [sgroup, val] of store.match(group, name, includeSubdomains)) {
|
||||
outStore.set(sgroup, name, val);
|
||||
}
|
||||
});
|
||||
|
||||
let prefs = [];
|
||||
for (let [sgroup, sname, val] of outStore) {
|
||||
prefs.push(new ContentPref(sgroup, sname, val));
|
||||
}
|
||||
return prefs;
|
||||
},
|
||||
|
||||
set: function CPS2_set(group, name, value, context, callback) {
|
||||
checkGroupArg(group);
|
||||
this._set(group, name, value, context, callback);
|
||||
},
|
||||
|
||||
setGlobal: function CPS2_setGlobal(name, value, context, callback) {
|
||||
this._set(null, name, value, context, callback);
|
||||
},
|
||||
|
||||
_set: function CPS2__set(group, name, value, context, callback) {
|
||||
group = this._parseGroup(group);
|
||||
checkNameArg(name);
|
||||
checkValueArg(value);
|
||||
checkCallbackArg(callback, false);
|
||||
|
||||
if (context && context.usePrivateBrowsing) {
|
||||
this._pbStore.set(group, name, value);
|
||||
this._schedule(function () {
|
||||
cbHandleCompletion(callback, Ci.nsIContentPrefCallback2.COMPLETE_OK);
|
||||
this._cps._notifyPrefSet(group, name, value, context.usePrivateBrowsing);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Invalidate the cached value so consumers accessing the cache between now
|
||||
// and when the operation finishes don't get old data.
|
||||
this._cache.remove(group, name);
|
||||
|
||||
let stmts = [];
|
||||
|
||||
// Create the setting if it doesn't exist.
|
||||
let stmt = this._stmt(`
|
||||
INSERT OR IGNORE INTO settings (id, name)
|
||||
VALUES((SELECT id FROM settings WHERE name = :name), :name)
|
||||
`);
|
||||
stmt.params.name = name;
|
||||
stmts.push(stmt);
|
||||
|
||||
// Create the group if it doesn't exist.
|
||||
if (group) {
|
||||
stmt = this._stmt(`
|
||||
INSERT OR IGNORE INTO groups (id, name)
|
||||
VALUES((SELECT id FROM groups WHERE name = :group), :group)
|
||||
`);
|
||||
stmt.params.group = group;
|
||||
stmts.push(stmt);
|
||||
}
|
||||
|
||||
// Finally create or update the pref.
|
||||
if (group) {
|
||||
stmt = this._stmt(`
|
||||
INSERT OR REPLACE INTO prefs (id, groupID, settingID, value, timestamp)
|
||||
VALUES(
|
||||
(SELECT prefs.id
|
||||
FROM prefs
|
||||
JOIN groups ON groups.id = prefs.groupID
|
||||
JOIN settings ON settings.id = prefs.settingID
|
||||
WHERE groups.name = :group AND settings.name = :name),
|
||||
(SELECT id FROM groups WHERE name = :group),
|
||||
(SELECT id FROM settings WHERE name = :name),
|
||||
:value,
|
||||
:now
|
||||
)
|
||||
`);
|
||||
stmt.params.group = group;
|
||||
}
|
||||
else {
|
||||
stmt = this._stmt(`
|
||||
INSERT OR REPLACE INTO prefs (id, groupID, settingID, value, timestamp)
|
||||
VALUES(
|
||||
(SELECT prefs.id
|
||||
FROM prefs
|
||||
JOIN settings ON settings.id = prefs.settingID
|
||||
WHERE prefs.groupID IS NULL AND settings.name = :name),
|
||||
NULL,
|
||||
(SELECT id FROM settings WHERE name = :name),
|
||||
:value,
|
||||
:now
|
||||
)
|
||||
`);
|
||||
}
|
||||
stmt.params.name = name;
|
||||
stmt.params.value = value;
|
||||
stmt.params.now = Date.now() / 1000;
|
||||
stmts.push(stmt);
|
||||
|
||||
this._execStmts(stmts, {
|
||||
onDone: function onDone(reason, ok) {
|
||||
if (ok)
|
||||
this._cache.setWithCast(group, name, value);
|
||||
cbHandleCompletion(callback, reason);
|
||||
if (ok)
|
||||
this._cps._notifyPrefSet(group, name, value, context && context.usePrivateBrowsing);
|
||||
},
|
||||
onError: function onError(nsresult) {
|
||||
cbHandleError(callback, nsresult);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
removeByDomainAndName: function CPS2_removeByDomainAndName(group, name,
|
||||
context,
|
||||
callback) {
|
||||
checkGroupArg(group);
|
||||
this._remove(group, name, false, context, callback);
|
||||
},
|
||||
|
||||
removeBySubdomainAndName: function CPS2_removeBySubdomainAndName(group, name,
|
||||
context,
|
||||
callback) {
|
||||
checkGroupArg(group);
|
||||
this._remove(group, name, true, context, callback);
|
||||
},
|
||||
|
||||
removeGlobal: function CPS2_removeGlobal(name, context, callback) {
|
||||
this._remove(null, name, false, context, callback);
|
||||
},
|
||||
|
||||
_remove: function CPS2__remove(group, name, includeSubdomains, context,
|
||||
callback) {
|
||||
group = this._parseGroup(group);
|
||||
checkNameArg(name);
|
||||
checkCallbackArg(callback, false);
|
||||
|
||||
// Invalidate the cached values so consumers accessing the cache between now
|
||||
// and when the operation finishes don't get old data.
|
||||
for (let sgroup of this._cache.matchGroups(group, includeSubdomains)) {
|
||||
this._cache.remove(sgroup, name);
|
||||
}
|
||||
|
||||
let stmts = [];
|
||||
|
||||
// First get the matching prefs.
|
||||
stmts.push(this._commonGetStmt(group, name, 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)
|
||||
WHEN 'null' THEN prefs.groupID IS NULL
|
||||
ELSE prefs.groupID IN (${GROUP_CLAUSE})
|
||||
END
|
||||
`);
|
||||
stmt.params.name = name;
|
||||
stmts.push(stmt);
|
||||
|
||||
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");
|
||||
prefs.set(grp, name, undefined);
|
||||
this._cache.set(grp, name, undefined);
|
||||
},
|
||||
onDone: function 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
cbHandleCompletion(callback, reason);
|
||||
if (ok) {
|
||||
for (let [sgroup, , ] of prefs) {
|
||||
this._cps._notifyPrefRemoved(sgroup, name, isPrivate);
|
||||
}
|
||||
}
|
||||
},
|
||||
onError: function onError(nsresult) {
|
||||
cbHandleError(callback, nsresult);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// Deletes settings and groups that are no longer used.
|
||||
_settingsAndGroupsCleanupStmts: function() {
|
||||
// The NOTNULL term in the subquery of the second statment is needed because of
|
||||
// SQLite's weird IN behavior vis-a-vis NULLs. See http://sqlite.org/lang_expr.html.
|
||||
return [
|
||||
this._stmt(`
|
||||
DELETE FROM settings
|
||||
WHERE id NOT IN (SELECT DISTINCT settingID FROM prefs)
|
||||
`),
|
||||
this._stmt(`
|
||||
DELETE FROM groups WHERE id NOT IN (
|
||||
SELECT DISTINCT groupID FROM prefs WHERE groupID NOTNULL
|
||||
)
|
||||
`)
|
||||
];
|
||||
},
|
||||
|
||||
removeByDomain: function CPS2_removeByDomain(group, context, callback) {
|
||||
checkGroupArg(group);
|
||||
this._removeByDomain(group, false, context, callback);
|
||||
},
|
||||
|
||||
removeBySubdomain: function CPS2_removeBySubdomain(group, context, callback) {
|
||||
checkGroupArg(group);
|
||||
this._removeByDomain(group, true, context, callback);
|
||||
},
|
||||
|
||||
removeAllGlobals: function CPS2_removeAllGlobals(context, callback) {
|
||||
this._removeByDomain(null, false, context, callback);
|
||||
},
|
||||
|
||||
_removeByDomain: function CPS2__removeByDomain(group, includeSubdomains,
|
||||
context, callback) {
|
||||
group = this._parseGroup(group);
|
||||
checkCallbackArg(callback, false);
|
||||
|
||||
// Invalidate the cached values so consumers accessing the cache between now
|
||||
// and when the operation finishes don't get old data.
|
||||
for (let sgroup of this._cache.matchGroups(group, includeSubdomains)) {
|
||||
this._cache.removeGroup(sgroup);
|
||||
}
|
||||
|
||||
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})`
|
||||
));
|
||||
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 settings
|
||||
WHERE id NOT IN (SELECT DISTINCT settingID FROM prefs)
|
||||
`));
|
||||
|
||||
let prefs = new ContentPrefStore();
|
||||
|
||||
let isPrivate = context && context.usePrivateBrowsing;
|
||||
this._execStmts(stmts, {
|
||||
onRow: function onRow(row) {
|
||||
let grp = row.getResultByName("grp");
|
||||
let name = row.getResultByName("name");
|
||||
prefs.set(grp, name, undefined);
|
||||
this._cache.set(grp, name, undefined);
|
||||
},
|
||||
onDone: function 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
cbHandleCompletion(callback, reason);
|
||||
if (ok) {
|
||||
for (let [sgroup, sname, ] of prefs) {
|
||||
this._cps._notifyPrefRemoved(sgroup, sname, isPrivate);
|
||||
}
|
||||
}
|
||||
},
|
||||
onError: function onError(nsresult) {
|
||||
cbHandleError(callback, nsresult);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
_removeAllDomainsSince: function CPS2__removeAllDomainsSince(since, context, callback) {
|
||||
checkCallbackArg(callback, false);
|
||||
|
||||
since /= 1000;
|
||||
|
||||
// Invalidate the cached values so consumers accessing the cache between now
|
||||
// and when the operation finishes don't get old data.
|
||||
// Invalidate all the group cache because we don't know which groups will be removed.
|
||||
this._cache.removeAllGroups();
|
||||
|
||||
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);
|
||||
|
||||
// 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());
|
||||
|
||||
let prefs = new ContentPrefStore();
|
||||
let isPrivate = context && context.usePrivateBrowsing;
|
||||
this._execStmts(stmts, {
|
||||
onRow: function onRow(row) {
|
||||
let grp = row.getResultByName("grp");
|
||||
let name = row.getResultByName("name");
|
||||
prefs.set(grp, name, undefined);
|
||||
this._cache.set(grp, name, undefined);
|
||||
},
|
||||
onDone: function 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();
|
||||
}
|
||||
cbHandleCompletion(callback, reason);
|
||||
if (ok) {
|
||||
for (let [sgroup, sname, ] of prefs) {
|
||||
this._cps._notifyPrefRemoved(sgroup, sname, isPrivate);
|
||||
}
|
||||
}
|
||||
},
|
||||
onError: function onError(nsresult) {
|
||||
cbHandleError(callback, nsresult);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
removeAllDomainsSince: function CPS2_removeAllDomainsSince(since, context, callback) {
|
||||
this._removeAllDomainsSince(since, context, callback);
|
||||
},
|
||||
|
||||
removeAllDomains: function CPS2_removeAllDomains(context, callback) {
|
||||
this._removeAllDomainsSince(0, context, callback);
|
||||
},
|
||||
|
||||
removeByName: function CPS2_removeByName(name, context, callback) {
|
||||
checkNameArg(name);
|
||||
checkCallbackArg(callback, false);
|
||||
|
||||
// Invalidate the cached values so consumers accessing the cache between now
|
||||
// and when the operation finishes don't get old data.
|
||||
for (let [group, sname, ] of this._cache) {
|
||||
if (sname == name)
|
||||
this._cache.remove(group, name);
|
||||
}
|
||||
|
||||
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
|
||||
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 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;
|
||||
|
||||
this._execStmts(stmts, {
|
||||
onRow: function onRow(row) {
|
||||
let grp = row.getResultByName("grp");
|
||||
prefs.set(grp, name, undefined);
|
||||
this._cache.set(grp, name, undefined);
|
||||
},
|
||||
onDone: function 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
cbHandleCompletion(callback, reason);
|
||||
if (ok) {
|
||||
for (let [sgroup, , ] of prefs) {
|
||||
this._cps._notifyPrefRemoved(sgroup, name, isPrivate);
|
||||
}
|
||||
}
|
||||
},
|
||||
onError: function onError(nsresult) {
|
||||
cbHandleError(callback, nsresult);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
destroy: function CPS2_destroy() {
|
||||
if (this._statements) {
|
||||
for (let sql in this._statements) {
|
||||
let stmt = this._statements[sql];
|
||||
stmt.finalize();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the cached mozIStorageAsyncStatement for the given SQL. If no such
|
||||
* statement is cached, one is created and cached.
|
||||
*
|
||||
* @param sql The SQL query string.
|
||||
* @return The cached, possibly new, statement.
|
||||
*/
|
||||
_stmt: function CPS2__stmt(sql) {
|
||||
if (!this._statements)
|
||||
this._statements = {};
|
||||
if (!this._statements[sql])
|
||||
this._statements[sql] = this._cps._dbConnection.createAsyncStatement(sql);
|
||||
return this._statements[sql];
|
||||
},
|
||||
|
||||
/**
|
||||
* Executes some async statements.
|
||||
*
|
||||
* @param stmts An array of mozIStorageAsyncStatements.
|
||||
* @param callbacks An object with the following methods:
|
||||
* onRow(row) (optional)
|
||||
* Called once for each result row.
|
||||
* row: A mozIStorageRow.
|
||||
* onDone(reason, reasonOK, didGetRow) (required)
|
||||
* Called when done.
|
||||
* reason: A nsIContentPrefService2.COMPLETE_* value.
|
||||
* reasonOK: reason == nsIContentPrefService2.COMPLETE_OK.
|
||||
* didGetRow: True if onRow was ever called.
|
||||
* onError(nsresult) (optional)
|
||||
* Called on error.
|
||||
* nsresult: The error code.
|
||||
*/
|
||||
_execStmts: function CPS2__execStmts(stmts, callbacks) {
|
||||
let self = this;
|
||||
let gotRow = false;
|
||||
this._cps._dbConnection.executeAsync(stmts, stmts.length, {
|
||||
handleResult: function handleResult(results) {
|
||||
try {
|
||||
let row = null;
|
||||
while ((row = results.getNextRow())) {
|
||||
gotRow = true;
|
||||
if (callbacks.onRow)
|
||||
callbacks.onRow.call(self, row);
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
Cu.reportError(err);
|
||||
}
|
||||
},
|
||||
handleCompletion: function handleCompletion(reason) {
|
||||
try {
|
||||
let ok = reason == Ci.mozIStorageStatementCallback.REASON_FINISHED;
|
||||
callbacks.onDone.call(self,
|
||||
ok ? Ci.nsIContentPrefCallback2.COMPLETE_OK :
|
||||
Ci.nsIContentPrefCallback2.COMPLETE_ERROR,
|
||||
ok, gotRow);
|
||||
}
|
||||
catch (err) {
|
||||
Cu.reportError(err);
|
||||
}
|
||||
},
|
||||
handleError: function handleError(error) {
|
||||
try {
|
||||
if (callbacks.onError)
|
||||
callbacks.onError.call(self, Cr.NS_ERROR_FAILURE);
|
||||
}
|
||||
catch (err) {
|
||||
Cu.reportError(err);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Parses the domain (the "group", to use the database's term) from the given
|
||||
* string.
|
||||
*
|
||||
* @param groupStr Assumed to be either a string or falsey.
|
||||
* @return If groupStr is a valid URL string, returns the domain of
|
||||
* that URL. If groupStr is some other nonempty string,
|
||||
* returns groupStr itself. Otherwise returns null.
|
||||
*/
|
||||
_parseGroup: function CPS2__parseGroup(groupStr) {
|
||||
if (!groupStr)
|
||||
return null;
|
||||
try {
|
||||
var groupURI = Services.io.newURI(groupStr, null, null);
|
||||
}
|
||||
catch (err) {
|
||||
return groupStr;
|
||||
}
|
||||
return this._cps._grouper.group(groupURI);
|
||||
},
|
||||
|
||||
_schedule: function CPS2__schedule(fn) {
|
||||
Services.tm.mainThread.dispatch(fn.bind(this),
|
||||
Ci.nsIThread.DISPATCH_NORMAL);
|
||||
},
|
||||
|
||||
addObserverForName: function CPS2_addObserverForName(name, observer) {
|
||||
this._cps._addObserver(name, observer);
|
||||
},
|
||||
|
||||
removeObserverForName: function CPS2_removeObserverForName(name, observer) {
|
||||
this._cps._removeObserver(name, observer);
|
||||
},
|
||||
|
||||
extractDomain: function CPS2_extractDomain(str) {
|
||||
return this._parseGroup(str);
|
||||
},
|
||||
|
||||
/**
|
||||
* Tests use this as a backchannel by calling it directly.
|
||||
*
|
||||
* @param subj This value depends on topic.
|
||||
* @param topic The backchannel "method" name.
|
||||
* @param data This value depends on topic.
|
||||
*/
|
||||
observe: function CPS2_observe(subj, topic, data) {
|
||||
switch (topic) {
|
||||
case "test:reset":
|
||||
let fn = subj.QueryInterface(Ci.xpcIJSWeakReference).get();
|
||||
this._reset(fn);
|
||||
break;
|
||||
case "test:db":
|
||||
let obj = subj.QueryInterface(Ci.xpcIJSWeakReference).get();
|
||||
obj.value = this._cps._dbConnection;
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes all state from the service. Used by tests.
|
||||
*
|
||||
* @param callback A function that will be called when done.
|
||||
*/
|
||||
_reset: function CPS2__reset(callback) {
|
||||
this._pbStore.removeAll();
|
||||
this._cache.removeAll();
|
||||
|
||||
let cps = this._cps;
|
||||
cps._observers = {};
|
||||
cps._genericObservers = [];
|
||||
|
||||
let tables = ["prefs", "groups", "settings"];
|
||||
let stmts = tables.map(t => this._stmt(`DELETE FROM ${t}`));
|
||||
this._execStmts(stmts, { onDone: () => callback() });
|
||||
},
|
||||
|
||||
QueryInterface: function CPS2_QueryInterface(iid) {
|
||||
let supportedIIDs = [
|
||||
Ci.nsIContentPrefService2,
|
||||
Ci.nsIObserver,
|
||||
Ci.nsISupports,
|
||||
];
|
||||
if (supportedIIDs.some(i => iid.equals(i)))
|
||||
return this;
|
||||
if (iid.equals(Ci.nsIContentPrefService))
|
||||
return this._cps;
|
||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
};
|
||||
|
||||
function checkGroupArg(group) {
|
||||
if (!group || typeof(group) != "string")
|
||||
throw invalidArg("domain must be nonempty string.");
|
||||
}
|
||||
|
||||
function checkNameArg(name) {
|
||||
if (!name || typeof(name) != "string")
|
||||
throw invalidArg("name must be nonempty string.");
|
||||
}
|
||||
|
||||
function checkValueArg(value) {
|
||||
if (value === undefined)
|
||||
throw invalidArg("value must not be undefined.");
|
||||
}
|
||||
|
||||
function checkCallbackArg(callback, required) {
|
||||
if (callback && !(callback instanceof Ci.nsIContentPrefCallback2))
|
||||
throw invalidArg("callback must be an nsIContentPrefCallback2.");
|
||||
if (!callback && required)
|
||||
throw invalidArg("callback must be given.");
|
||||
}
|
||||
|
||||
function invalidArg(msg) {
|
||||
return Components.Exception(msg, Cr.NS_ERROR_INVALID_ARG);
|
||||
}
|
||||
182
toolkit/components/contentprefs/ContentPrefServiceChild.jsm
Normal file
182
toolkit/components/contentprefs/ContentPrefServiceChild.jsm
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
/* vim: set ts=2 sw=2 sts=2 et tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = [ "ContentPrefServiceChild" ];
|
||||
|
||||
const Ci = Components.interfaces;
|
||||
const Cc = Components.classes;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/ContentPrefUtils.jsm");
|
||||
Cu.import("resource://gre/modules/ContentPrefStore.jsm");
|
||||
|
||||
// We only need one bit of information out of the context.
|
||||
function contextArg(context) {
|
||||
return (context && context.usePrivateBrowsing) ?
|
||||
{ usePrivateBrowsing: true } :
|
||||
null;
|
||||
}
|
||||
|
||||
function NYI() {
|
||||
throw new Error("Do not add any new users of these functions");
|
||||
}
|
||||
|
||||
function CallbackCaller(callback) {
|
||||
this._callback = callback;
|
||||
}
|
||||
|
||||
CallbackCaller.prototype = {
|
||||
handleResult: function(contentPref) {
|
||||
cbHandleResult(this._callback,
|
||||
new ContentPref(contentPref.domain,
|
||||
contentPref.name,
|
||||
contentPref.value));
|
||||
},
|
||||
|
||||
handleError: function(result) {
|
||||
cbHandleError(this._callback, result);
|
||||
},
|
||||
|
||||
handleCompletion: function(reason) {
|
||||
cbHandleCompletion(this._callback, reason);
|
||||
},
|
||||
};
|
||||
|
||||
var ContentPrefServiceChild = {
|
||||
QueryInterface: XPCOMUtils.generateQI([ Ci.nsIContentPrefService2 ]),
|
||||
|
||||
// Map from pref name -> set of observers
|
||||
_observers: new Map(),
|
||||
|
||||
_mm: Cc["@mozilla.org/childprocessmessagemanager;1"]
|
||||
.getService(Ci.nsIMessageSender),
|
||||
|
||||
_getRandomId: function() {
|
||||
return Cc["@mozilla.org/uuid-generator;1"]
|
||||
.getService(Ci.nsIUUIDGenerator).generateUUID().toString();
|
||||
},
|
||||
|
||||
// Map from random ID string -> CallbackCaller, per request
|
||||
_requests: new Map(),
|
||||
|
||||
init: function() {
|
||||
this._mm.addMessageListener("ContentPrefs:HandleResult", this);
|
||||
this._mm.addMessageListener("ContentPrefs:HandleError", this);
|
||||
this._mm.addMessageListener("ContentPrefs:HandleCompletion", this);
|
||||
},
|
||||
|
||||
receiveMessage: function(msg) {
|
||||
let data = msg.data;
|
||||
let callback;
|
||||
switch (msg.name) {
|
||||
case "ContentPrefs:HandleResult":
|
||||
callback = this._requests.get(data.requestId);
|
||||
callback.handleResult(data.contentPref);
|
||||
break;
|
||||
|
||||
case "ContentPrefs:HandleError":
|
||||
callback = this._requests.get(data.requestId);
|
||||
callback.handleError(data.error);
|
||||
break;
|
||||
|
||||
case "ContentPrefs:HandleCompletion":
|
||||
callback = this._requests.get(data.requestId);
|
||||
this._requests.delete(data.requestId);
|
||||
callback.handleCompletion(data.reason);
|
||||
break;
|
||||
|
||||
case "ContentPrefs:NotifyObservers": {
|
||||
let observerList = this._observers.get(data.name);
|
||||
if (!observerList)
|
||||
break;
|
||||
|
||||
for (let observer of observerList) {
|
||||
safeCallback(observer, data.callback, data.args);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_callFunction: function(call, args, callback) {
|
||||
let requestId = this._getRandomId();
|
||||
let data = { call: call, args: args, requestId: requestId };
|
||||
|
||||
this._mm.sendAsyncMessage("ContentPrefs:FunctionCall", data);
|
||||
|
||||
this._requests.set(requestId, new CallbackCaller(callback));
|
||||
},
|
||||
|
||||
getCachedByDomainAndName: NYI,
|
||||
getCachedBySubdomainAndName: NYI,
|
||||
getCachedGlobal: NYI,
|
||||
|
||||
addObserverForName: function(name, observer) {
|
||||
let set = this._observers.get(name);
|
||||
if (!set) {
|
||||
set = new Set();
|
||||
if (this._observers.size === 0) {
|
||||
// This is the first observer of any kind. Start listening for changes.
|
||||
this._mm.addMessageListener("ContentPrefs:NotifyObservers", this);
|
||||
}
|
||||
|
||||
// This is the first observer for this name. Start listening for changes
|
||||
// to it.
|
||||
this._mm.sendAsyncMessage("ContentPrefs:AddObserverForName", { name: name });
|
||||
this._observers.set(name, set);
|
||||
}
|
||||
|
||||
set.add(observer);
|
||||
},
|
||||
|
||||
removeObserverForName: function(name, observer) {
|
||||
let set = this._observers.get(name);
|
||||
if (!set)
|
||||
return;
|
||||
|
||||
set.delete(observer);
|
||||
if (set.size === 0) {
|
||||
// This was the last observer for this name. Stop listening for changes.
|
||||
this._mm.sendAsyncMessage("ContentPrefs:RemoveObserverForName", { name: name });
|
||||
|
||||
this._observers.delete(name);
|
||||
if (this._observers.size === 0) {
|
||||
// This was the last observer for this process. Stop listing for all
|
||||
// changes.
|
||||
this._mm.removeMessageListener("ContentPrefs:NotifyObservers", this);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
extractDomain: NYI
|
||||
};
|
||||
|
||||
function forwardMethodToParent(method, signature, ...args) {
|
||||
// Ignore superfluous arguments
|
||||
args = args.slice(0, signature.length);
|
||||
|
||||
// Process context argument for forwarding
|
||||
let contextIndex = signature.indexOf("context");
|
||||
if (contextIndex > -1) {
|
||||
args[contextIndex] = contextArg(args[contextIndex]);
|
||||
}
|
||||
// Take out the callback argument, if present.
|
||||
let callbackIndex = signature.indexOf("callback");
|
||||
let callback = null;
|
||||
if (callbackIndex > -1 && args.length > callbackIndex) {
|
||||
callback = args.splice(callbackIndex, 1)[0];
|
||||
}
|
||||
this._callFunction(method, args, callback);
|
||||
}
|
||||
|
||||
for (let [method, signature] of _methodsCallableFromChild) {
|
||||
ContentPrefServiceChild[method] = forwardMethodToParent.bind(ContentPrefServiceChild, method, signature);
|
||||
}
|
||||
|
||||
ContentPrefServiceChild.init();
|
||||
137
toolkit/components/contentprefs/ContentPrefServiceParent.jsm
Normal file
137
toolkit/components/contentprefs/ContentPrefServiceParent.jsm
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
/* vim: set ts=2 sw=2 sts=2 et tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = [ "ContentPrefServiceParent" ];
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/ContentPrefUtils.jsm");
|
||||
|
||||
var ContentPrefServiceParent = {
|
||||
_cps2: null,
|
||||
|
||||
init: function() {
|
||||
let globalMM = Cc["@mozilla.org/parentprocessmessagemanager;1"]
|
||||
.getService(Ci.nsIMessageListenerManager);
|
||||
|
||||
this._cps2 = Cc["@mozilla.org/content-pref/service;1"]
|
||||
.getService(Ci.nsIContentPrefService2);
|
||||
|
||||
globalMM.addMessageListener("ContentPrefs:FunctionCall", this);
|
||||
|
||||
let observerChangeHandler = this.handleObserverChange.bind(this);
|
||||
globalMM.addMessageListener("ContentPrefs:AddObserverForName", observerChangeHandler);
|
||||
globalMM.addMessageListener("ContentPrefs:RemoveObserverForName", observerChangeHandler);
|
||||
globalMM.addMessageListener("child-process-shutdown", observerChangeHandler);
|
||||
},
|
||||
|
||||
// Map from message manager -> content pref observer.
|
||||
_observers: new Map(),
|
||||
|
||||
handleObserverChange: function(msg) {
|
||||
let observer = this._observers.get(msg.target);
|
||||
if (msg.name === "child-process-shutdown") {
|
||||
// If we didn't have any observers for this child process, don't do
|
||||
// anything.
|
||||
if (!observer)
|
||||
return;
|
||||
|
||||
for (let i of observer._names) {
|
||||
this._cps2.removeObserverForName(i, observer);
|
||||
}
|
||||
|
||||
this._observers.delete(msg.target);
|
||||
return;
|
||||
}
|
||||
|
||||
let prefName = msg.data.name;
|
||||
if (msg.name === "ContentPrefs:AddObserverForName") {
|
||||
// The child process is responsible for not adding multiple parent
|
||||
// observers for the same name.
|
||||
if (!observer) {
|
||||
observer = {
|
||||
onContentPrefSet: function(group, name, value, isPrivate) {
|
||||
msg.target.sendAsyncMessage("ContentPrefs:NotifyObservers",
|
||||
{ name: name, callback: "onContentPrefSet",
|
||||
args: [ group, name, value, isPrivate ] });
|
||||
},
|
||||
|
||||
onContentPrefRemoved: function(group, name, isPrivate) {
|
||||
msg.target.sendAsyncMessage("ContentPrefs:NotifyObservers",
|
||||
{ name: name, callback: "onContentPrefRemoved",
|
||||
args: [ group, name, isPrivate ] });
|
||||
},
|
||||
|
||||
// The names we're using this observer object for, used to keep track
|
||||
// of the number of names we care about as well as for removing this
|
||||
// observer if its associated process goes away.
|
||||
_names: new Set()
|
||||
};
|
||||
|
||||
this._observers.set(msg.target, observer);
|
||||
}
|
||||
|
||||
observer._names.add(prefName);
|
||||
|
||||
this._cps2.addObserverForName(prefName, observer);
|
||||
} else {
|
||||
// RemoveObserverForName
|
||||
|
||||
// We must have an observer.
|
||||
this._cps2.removeObserverForName(prefName, observer);
|
||||
|
||||
observer._names.delete(prefName);
|
||||
if (observer._names.size === 0) {
|
||||
// This was the last use for this observer.
|
||||
this._observers.delete(msg.target);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
receiveMessage: function(msg) {
|
||||
let data = msg.data;
|
||||
|
||||
if (!_methodsCallableFromChild.some(([method, args]) => method == data.call)) {
|
||||
throw new Error(`Can't call ${data.call} from child!`);
|
||||
}
|
||||
|
||||
let args = data.args;
|
||||
let requestId = data.requestId;
|
||||
|
||||
let listener = {
|
||||
handleResult: function(pref) {
|
||||
msg.target.sendAsyncMessage("ContentPrefs:HandleResult",
|
||||
{ requestId: requestId,
|
||||
contentPref: {
|
||||
domain: pref.domain,
|
||||
name: pref.name,
|
||||
value: pref.value
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
handleError: function(error) {
|
||||
msg.target.sendAsyncMessage("ContentPrefs:HandleError",
|
||||
{ requestId: requestId,
|
||||
error: error });
|
||||
},
|
||||
handleCompletion: function(reason) {
|
||||
msg.target.sendAsyncMessage("ContentPrefs:HandleCompletion",
|
||||
{ requestId: requestId,
|
||||
reason: reason });
|
||||
}
|
||||
};
|
||||
|
||||
// Push our special listener.
|
||||
args.push(listener);
|
||||
|
||||
// And call the function.
|
||||
this._cps2[data.call](...args);
|
||||
}
|
||||
};
|
||||
123
toolkit/components/contentprefs/ContentPrefStore.jsm
Normal file
123
toolkit/components/contentprefs/ContentPrefStore.jsm
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
var EXPORTED_SYMBOLS = [
|
||||
"ContentPrefStore",
|
||||
];
|
||||
|
||||
function ContentPrefStore() {
|
||||
this._groups = new Map();
|
||||
this._globalNames = new Map();
|
||||
}
|
||||
|
||||
ContentPrefStore.prototype = {
|
||||
|
||||
set: function CPS_set(group, name, val) {
|
||||
if (group) {
|
||||
if (!this._groups.has(group))
|
||||
this._groups.set(group, new Map());
|
||||
this._groups.get(group).set(name, val);
|
||||
}
|
||||
else {
|
||||
this._globalNames.set(name, val);
|
||||
}
|
||||
},
|
||||
|
||||
setWithCast: function CPS_setWithCast(group, name, val) {
|
||||
if (typeof(val) == "boolean")
|
||||
val = val ? 1 : 0;
|
||||
else if (val === undefined)
|
||||
val = null;
|
||||
this.set(group, name, val);
|
||||
},
|
||||
|
||||
has: function CPS_has(group, name) {
|
||||
if (group) {
|
||||
return this._groups.has(group) &&
|
||||
this._groups.get(group).has(name);
|
||||
}
|
||||
return this._globalNames.has(name);
|
||||
},
|
||||
|
||||
get: function CPS_get(group, name) {
|
||||
if (group && this._groups.has(group))
|
||||
return this._groups.get(group).get(name);
|
||||
return this._globalNames.get(name);
|
||||
},
|
||||
|
||||
remove: function CPS_remove(group, name) {
|
||||
if (group) {
|
||||
if (this._groups.has(group)) {
|
||||
this._groups.get(group).delete(name);
|
||||
if (this._groups.get(group).size == 0)
|
||||
this._groups.delete(group);
|
||||
}
|
||||
}
|
||||
else {
|
||||
this._globalNames.delete(name);
|
||||
}
|
||||
},
|
||||
|
||||
removeGroup: function CPS_removeGroup(group) {
|
||||
if (group) {
|
||||
this._groups.delete(group);
|
||||
}
|
||||
else {
|
||||
this._globalNames.clear();
|
||||
}
|
||||
},
|
||||
|
||||
removeAllGroups: function CPS_removeAllGroups() {
|
||||
this._groups.clear();
|
||||
},
|
||||
|
||||
removeAll: function CPS_removeAll() {
|
||||
this.removeAllGroups();
|
||||
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) {
|
||||
yield [group, name, val];
|
||||
}
|
||||
}
|
||||
for (let [name, val] of this._globalNames) {
|
||||
yield [null, name, val];
|
||||
}
|
||||
},
|
||||
|
||||
* match(group, name, includeSubdomains) {
|
||||
for (let sgroup of this.matchGroups(group, includeSubdomains)) {
|
||||
if (this.has(sgroup, name))
|
||||
yield [sgroup, this.get(sgroup, name)];
|
||||
}
|
||||
},
|
||||
|
||||
* matchGroups(group, includeSubdomains) {
|
||||
if (group) {
|
||||
if (includeSubdomains) {
|
||||
for (let [sgroup, , ] of this) {
|
||||
if (sgroup) {
|
||||
if (this.groupsMatchIncludingSubdomains(group, sgroup)) {
|
||||
yield sgroup;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (this._groups.has(group)) {
|
||||
yield group;
|
||||
}
|
||||
}
|
||||
else if (this._globalNames.size) {
|
||||
yield null;
|
||||
}
|
||||
},
|
||||
};
|
||||
70
toolkit/components/contentprefs/ContentPrefUtils.jsm
Normal file
70
toolkit/components/contentprefs/ContentPrefUtils.jsm
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
/* vim: set ts=2 sw=2 sts=2 et tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = [
|
||||
"ContentPref",
|
||||
"cbHandleResult",
|
||||
"cbHandleError",
|
||||
"cbHandleCompletion",
|
||||
"safeCallback",
|
||||
"_methodsCallableFromChild",
|
||||
];
|
||||
|
||||
const { interfaces: Ci, classes: Cc, results: Cr, utils: Cu } = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
function ContentPref(domain, name, value) {
|
||||
this.domain = domain;
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
ContentPref.prototype = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPref]),
|
||||
};
|
||||
|
||||
function cbHandleResult(callback, pref) {
|
||||
safeCallback(callback, "handleResult", [pref]);
|
||||
}
|
||||
|
||||
function cbHandleCompletion(callback, reason) {
|
||||
safeCallback(callback, "handleCompletion", [reason]);
|
||||
}
|
||||
|
||||
function cbHandleError(callback, nsresult) {
|
||||
safeCallback(callback, "handleError", [nsresult]);
|
||||
}
|
||||
|
||||
function safeCallback(callbackObj, methodName, args) {
|
||||
if (!callbackObj || typeof(callbackObj[methodName]) != "function")
|
||||
return;
|
||||
try {
|
||||
callbackObj[methodName].apply(callbackObj, args);
|
||||
}
|
||||
catch (err) {
|
||||
Cu.reportError(err);
|
||||
}
|
||||
}
|
||||
|
||||
const _methodsCallableFromChild = Object.freeze([
|
||||
["getByName", ["name", "context", "callback"]],
|
||||
["getByDomainAndName", ["domain", "name", "context", "callback"]],
|
||||
["getBySubdomainAndName", ["domain", "name", "context", "callback"]],
|
||||
["getGlobal", ["name", "context", "callback"]],
|
||||
["set", ["domain", "name", "value", "context", "callback"]],
|
||||
["setGlobal", ["name", "value", "context", "callback"]],
|
||||
["removeByDomainAndName", ["domain", "name", "context", "callback"]],
|
||||
["removeBySubdomainAndName", ["domain", "name", "context", "callback"]],
|
||||
["removeGlobal", ["name", "context", "callback"]],
|
||||
["removeByDomain", ["domain", "context", "callback"]],
|
||||
["removeBySubdomain", ["domain", "context", "callback"]],
|
||||
["removeByName", ["name", "context", "callback"]],
|
||||
["removeAllDomains", ["context", "callback"]],
|
||||
["removeAllGlobals", ["context", "callback"]],
|
||||
]);
|
||||
31
toolkit/components/contentprefs/moz.build
Normal file
31
toolkit/components/contentprefs/moz.build
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
XPCSHELL_TESTS_MANIFESTS += [
|
||||
'tests/unit/xpcshell.ini',
|
||||
'tests/unit_cps2/xpcshell.ini',
|
||||
]
|
||||
|
||||
MOCHITEST_MANIFESTS += [
|
||||
'tests/mochitest/mochitest.ini'
|
||||
]
|
||||
|
||||
EXTRA_COMPONENTS += [
|
||||
'nsContentPrefService.js',
|
||||
'nsContentPrefService.manifest',
|
||||
]
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'ContentPrefInstance.jsm',
|
||||
'ContentPrefService2.jsm',
|
||||
'ContentPrefServiceChild.jsm',
|
||||
'ContentPrefServiceParent.jsm',
|
||||
'ContentPrefStore.jsm',
|
||||
'ContentPrefUtils.jsm',
|
||||
]
|
||||
|
||||
with Files('**'):
|
||||
BUG_COMPONENT = ('Toolkit', 'Preferences')
|
||||
1332
toolkit/components/contentprefs/nsContentPrefService.js
Normal file
1332
toolkit/components/contentprefs/nsContentPrefService.js
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,5 @@
|
|||
component {e3f772f3-023f-4b32-b074-36cf0fd5d414} nsContentPrefService.js
|
||||
contract @mozilla.org/content-pref/service;1 {e3f772f3-023f-4b32-b074-36cf0fd5d414}
|
||||
component {8df290ae-dcaa-4c11-98a5-2429a4dc97bb} nsContentPrefService.js
|
||||
contract @mozilla.org/content-pref/hostname-grouper;1 {8df290ae-dcaa-4c11-98a5-2429a4dc97bb}
|
||||
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
"extends": [
|
||||
"../../../../../testing/mochitest/mochitest.eslintrc.js"
|
||||
]
|
||||
};
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
[DEFAULT]
|
||||
|
||||
[test_remoteContentPrefs.html]
|
||||
skip-if = toolkit == 'android' || e10s # bug 783513
|
||||
|
|
@ -0,0 +1,311 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for nsIContentPrefService2 in child processes</title>
|
||||
<script type="application/javascript"
|
||||
src="/tests/SimpleTest/SimpleTest.js">
|
||||
</script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<script type="application/javascript;version=1.8">
|
||||
"use strict";
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
const childFrameURL =
|
||||
"data:text/html,<!DOCTYPE HTML><html><body></body></html>";
|
||||
|
||||
function childFrameScript(isFramePrivate) {
|
||||
"use strict";
|
||||
|
||||
function Tester(resultArray) {
|
||||
this.results = [];
|
||||
}
|
||||
|
||||
Tester.prototype.is =
|
||||
function(a, b, note) {
|
||||
this.results.push([a === b, note + " (" + a + ", " + b + ")"]);
|
||||
};
|
||||
Tester.prototype.ok =
|
||||
function(b, note) {
|
||||
this.results.push([b != false, note]);
|
||||
};
|
||||
|
||||
var cps = Components.classes["@mozilla.org/content-pref/service;1"]
|
||||
.getService(Components.interfaces.nsIContentPrefService2);
|
||||
|
||||
let test = null;
|
||||
function* test1(message) {
|
||||
let tester = new Tester();
|
||||
|
||||
tester.ok(cps !== null, "got the content pref service");
|
||||
|
||||
cps.setGlobal("testing", 42, null, {
|
||||
handleCompletion: function(reason) {
|
||||
tester.is(reason, 0, "set a pref?");
|
||||
test.next();
|
||||
}
|
||||
});
|
||||
|
||||
yield;
|
||||
|
||||
let numResults = 0;
|
||||
cps.getGlobal("testing", null, {
|
||||
handleResult: function(pref) {
|
||||
numResults++;
|
||||
tester.is(pref.name, "testing", "pref has the right name");
|
||||
tester.is(pref.value, 42, "pref has the right value");
|
||||
},
|
||||
|
||||
handleCompletion: function(reason) {
|
||||
tester.is(reason, 0, "get a pref?");
|
||||
tester.is(numResults, 1, "got the right number of prefs");
|
||||
tester.is(test.next().done, true, "done with test1");
|
||||
message.target.sendAsyncMessage("testRemoteContentPrefs:test1Finished",
|
||||
{ results: tester.results });
|
||||
}
|
||||
});
|
||||
|
||||
yield;
|
||||
}
|
||||
|
||||
function* test2(message) {
|
||||
let tester = new Tester();
|
||||
|
||||
let observer;
|
||||
let removed = false;
|
||||
cps.addObserverForName("testName", observer = {
|
||||
onContentPrefSet: function(group, name, value, isPrivate) {
|
||||
if (removed) {
|
||||
message.target.sendAsyncMessage("testRemoteContentPrefs:fail",
|
||||
{ reason: "unexpected notification" });
|
||||
}
|
||||
tester.is(group, null, "group should be null");
|
||||
tester.is(name, "testName", "should only see testName");
|
||||
tester.is(value, 42, "value should be correct");
|
||||
tester.is(isPrivate, isFramePrivate, "privacy should match");
|
||||
|
||||
message.target.sendAsyncMessage("testRemoteContentPrefs:test2poke2", {})
|
||||
},
|
||||
|
||||
onContentPrefRemoved: function(group, name, isPrivate) {
|
||||
tester.is(group, null, "group should be null");
|
||||
tester.is(name, "testName");
|
||||
tester.is(isPrivate, isFramePrivate, "privacy should match");
|
||||
tester.is(test.next().done, true, "should be done with test2");
|
||||
|
||||
cps.removeObserverForName("testName", observer);
|
||||
removed = true;
|
||||
|
||||
message.target.sendAsyncMessage("testRemoteContentPrefs:test2Finished",
|
||||
{ results: tester.results });
|
||||
}
|
||||
});
|
||||
|
||||
message.target.sendAsyncMessage("testRemoteContentPrefs:test2poke", {});
|
||||
yield;
|
||||
}
|
||||
|
||||
function* test3(message) {
|
||||
let tester = new Tester();
|
||||
|
||||
cps.setGlobal("testName", 42, null, {
|
||||
handleCompletion: function(reason) {
|
||||
tester.is(reason, 0, "set a pref");
|
||||
cps.set("http://mochi.test", "testpref", "str", null, {
|
||||
handleCompletion: function(reason) {
|
||||
tester.is(reason, 0, "set a pref");
|
||||
test.next();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
yield;
|
||||
|
||||
cps.removeByDomain("http://mochi.test", null, {
|
||||
handleCompletion: function(reason) {
|
||||
tester.is(reason, 0, "remove succeeded");
|
||||
cps.getByDomainAndName("http://mochi.test", "testpref", null, {
|
||||
handleResult: function() {
|
||||
message.target.sendAsyncMessage("testRemoteContentPrefs:fail",
|
||||
{ reason: "got removed pref in test3" });
|
||||
},
|
||||
handleCompletion: function() {
|
||||
test.next();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
yield;
|
||||
|
||||
message.target.sendAsyncMessage("testRemoteContentPrefs:test3Finished",
|
||||
{ results: tester.results });
|
||||
}
|
||||
|
||||
function* test4(message) {
|
||||
let tester = new Tester();
|
||||
|
||||
let prefObserver = {
|
||||
onContentPrefSet: function(group, name, value, isPrivate) {
|
||||
test.next({ group: group, name: name, value: value, isPrivate: isPrivate });
|
||||
},
|
||||
onContentPrefRemoved: function(group, name, isPrivate) {
|
||||
test.next({ group: group, name: name, isPrivate: isPrivate });
|
||||
}
|
||||
};
|
||||
|
||||
addMessageListener("testRemoteContentPrefs:prefResults", (msg) => {
|
||||
test.next(msg.data.results);
|
||||
});
|
||||
|
||||
cps.addObserverForName("test", prefObserver);
|
||||
|
||||
cps.set("http://mochi.test", "test", 42, { usePrivateBrowsing: true });
|
||||
let event = yield;
|
||||
tester.is(event.name, "test");
|
||||
tester.is(event.isPrivate, true);
|
||||
|
||||
message.target.sendAsyncMessage("testRemoteContentPrefs:getPref",
|
||||
{ group: "http://mochi.test", name: "test" });
|
||||
|
||||
let results = yield;
|
||||
tester.is(results.length, 0, "should not have seen the pb pref");
|
||||
|
||||
message.target.sendAsyncMessage("testRemoteContentPrefs:test4Finished",
|
||||
{ results: tester.results });
|
||||
}
|
||||
|
||||
addMessageListener("testRemoteContentPrefs:test1", function(message) {
|
||||
test = test1(message);
|
||||
test.next();
|
||||
});
|
||||
addMessageListener("testRemoteContentPrefs:test2", function(message) {
|
||||
test = test2(message);
|
||||
test.next();
|
||||
});
|
||||
addMessageListener("testRemoteContentPrefs:test3", function(message) {
|
||||
test = test3(message);
|
||||
test.next();
|
||||
});
|
||||
addMessageListener("testRemoteContentPrefs:test4", function(message) {
|
||||
test = test4(message);
|
||||
test.next();
|
||||
});
|
||||
}
|
||||
|
||||
function processResults(results) {
|
||||
for (let i of results) {
|
||||
ok(...i);
|
||||
}
|
||||
}
|
||||
|
||||
let test;
|
||||
function* testStructure(mm, isPrivate, callback) {
|
||||
let lastResult;
|
||||
|
||||
function testDone(msg) {
|
||||
test.next(msg.data);
|
||||
}
|
||||
|
||||
mm.addMessageListener("testRemoteContentPrefs:test1Finished", testDone);
|
||||
mm.addMessageListener("testRemoteContentPrefs:test2Finished", testDone);
|
||||
mm.addMessageListener("testRemoteContentPrefs:test3Finished", testDone);
|
||||
mm.addMessageListener("testRemoteContentPrefs:test4Finished", testDone);
|
||||
|
||||
mm.addMessageListener("testRemoteContentPrefs:fail", function(msg) {
|
||||
ok(false, msg.data.reason);
|
||||
});
|
||||
|
||||
mm.sendAsyncMessage("testRemoteContentPrefs:test1", {});
|
||||
lastResult = yield;
|
||||
processResults(lastResult.results);
|
||||
|
||||
var cps = SpecialPowers.Cc["@mozilla.org/content-pref/service;1"]
|
||||
.getService(SpecialPowers.Ci.nsIContentPrefService2);
|
||||
mm.sendAsyncMessage("testRemoteContentPrefs:test2", {});
|
||||
mm.addMessageListener("testRemoteContentPrefs:test2poke", function() {
|
||||
cps.setGlobal("testName", 42, {usePrivateBrowsing: isPrivate});
|
||||
});
|
||||
mm.addMessageListener("testRemoteContentPrefs:test2poke2", function() {
|
||||
cps.removeGlobal("testName", {usePrivateBrowsing: isPrivate});
|
||||
});
|
||||
|
||||
lastResult = yield;
|
||||
processResults(lastResult.results);
|
||||
|
||||
mm.sendAsyncMessage("testRemoteContentPrefs:test3", {});
|
||||
lastResult = yield;
|
||||
processResults(lastResult.results);
|
||||
|
||||
mm.addMessageListener("testRemoteContentPrefs:getPref", function(msg) {
|
||||
let results = [];
|
||||
cps.getByDomainAndName(msg.data.group, msg.data.name, null, {
|
||||
handleResult: function(pref) {
|
||||
results.push(pref);
|
||||
},
|
||||
handleCompletion: function(reason) {
|
||||
mm.sendAsyncMessage("testRemoteContentPrefs:prefResults",
|
||||
{ results: results });
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
mm.sendAsyncMessage("testRemoteContentPrefs:test4", {});
|
||||
lastResult = yield;
|
||||
processResults(lastResult.results);
|
||||
|
||||
document.getElementById('iframe').remove();
|
||||
setTimeout(callback, 0);
|
||||
}
|
||||
|
||||
function runTest(isPrivate, callback) {
|
||||
info("testing with isPrivate=" + isPrivate);
|
||||
let iframe = document.createElement("iframe");
|
||||
SpecialPowers.wrap(iframe).mozbrowser = true;
|
||||
if (isPrivate) {
|
||||
SpecialPowers.wrap(iframe).mozprivatebrowsing = true;
|
||||
}
|
||||
iframe.id = "iframe";
|
||||
iframe.src = childFrameURL;
|
||||
|
||||
iframe.addEventListener("mozbrowserloadend", function() {
|
||||
info("Got iframe load event.");
|
||||
let mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
|
||||
mm.loadFrameScript("data:,(" + childFrameScript.toString() + ")(" + isPrivate + ");",
|
||||
false);
|
||||
|
||||
test = testStructure(mm, isPrivate, callback);
|
||||
test.next();
|
||||
});
|
||||
|
||||
document.body.appendChild(iframe);
|
||||
}
|
||||
|
||||
function runTests() {
|
||||
info("Browser prefs set.");
|
||||
runTest(false, function() {
|
||||
runTest(true, function() {
|
||||
SimpleTest.finish();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
addEventListener("load", function() {
|
||||
info("Got load event.");
|
||||
|
||||
SpecialPowers.addPermission("browser", true, document);
|
||||
SpecialPowers.pushPrefEnv({
|
||||
"set": [
|
||||
["dom.ipc.browser_frames.oop_by_default", true],
|
||||
["dom.mozBrowserFramesEnabled", true],
|
||||
["browser.pagethumbnails.capturing_disabled", true]
|
||||
]
|
||||
}, runTests);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
7
toolkit/components/contentprefs/tests/unit/.eslintrc.js
Normal file
7
toolkit/components/contentprefs/tests/unit/.eslintrc.js
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
"extends": [
|
||||
"../../../../../testing/xpcshell/xpcshell.eslintrc.js"
|
||||
]
|
||||
};
|
||||
162
toolkit/components/contentprefs/tests/unit/head_contentPrefs.js
Normal file
162
toolkit/components/contentprefs/tests/unit/head_contentPrefs.js
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// Inspired by the Places infrastructure in head_bookmarks.js
|
||||
|
||||
var Cc = Components.classes;
|
||||
var Ci = Components.interfaces;
|
||||
var Cr = Components.results;
|
||||
var Cu = Components.utils;
|
||||
|
||||
Cu.import('resource://gre/modules/Services.jsm');
|
||||
Cu.import('resource://gre/modules/ContentPrefInstance.jsm');
|
||||
|
||||
const CONTENT_PREFS_DB_FILENAME = "content-prefs.sqlite";
|
||||
const CONTENT_PREFS_BACKUP_DB_FILENAME = "content-prefs.sqlite.corrupt";
|
||||
|
||||
var ContentPrefTest = {
|
||||
// Convenience Getters
|
||||
|
||||
__dirSvc: null,
|
||||
get _dirSvc() {
|
||||
if (!this.__dirSvc)
|
||||
this.__dirSvc = Cc["@mozilla.org/file/directory_service;1"].
|
||||
getService(Ci.nsIProperties);
|
||||
return this.__dirSvc;
|
||||
},
|
||||
|
||||
__consoleSvc: null,
|
||||
get _consoleSvc() {
|
||||
if (!this.__consoleSvc)
|
||||
this.__consoleSvc = Cc["@mozilla.org/consoleservice;1"].
|
||||
getService(Ci.nsIConsoleService);
|
||||
return this.__consoleSvc;
|
||||
},
|
||||
|
||||
__ioSvc: null,
|
||||
get _ioSvc() {
|
||||
if (!this.__ioSvc)
|
||||
this.__ioSvc = Cc["@mozilla.org/network/io-service;1"].
|
||||
getService(Ci.nsIIOService);
|
||||
return this.__ioSvc;
|
||||
},
|
||||
|
||||
|
||||
// nsISupports
|
||||
|
||||
interfaces: [Ci.nsIDirectoryServiceProvider, Ci.nsISupports],
|
||||
|
||||
QueryInterface: function ContentPrefTest_QueryInterface(iid) {
|
||||
if (!this.interfaces.some( function(v) { return iid.equals(v) } ))
|
||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||
return this;
|
||||
},
|
||||
|
||||
|
||||
// nsIDirectoryServiceProvider
|
||||
|
||||
getFile: function ContentPrefTest_getFile(property, persistent) {
|
||||
persistent.value = true;
|
||||
|
||||
if (property == "ProfD")
|
||||
return this._dirSvc.get("CurProcD", Ci.nsIFile);
|
||||
|
||||
// This causes extraneous errors to show up in the log when the directory
|
||||
// service asks us first for CurProcD and MozBinD. I wish there was a way
|
||||
// to suppress those errors.
|
||||
throw Cr.NS_ERROR_FAILURE;
|
||||
},
|
||||
|
||||
|
||||
// Utilities
|
||||
|
||||
getURI: function ContentPrefTest_getURI(spec) {
|
||||
return this._ioSvc.newURI(spec, null, null);
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the profile directory.
|
||||
*/
|
||||
getProfileDir: function ContentPrefTest_getProfileDir() {
|
||||
// do_get_profile can be only called from a parent process
|
||||
if (runningInParent) {
|
||||
return do_get_profile();
|
||||
}
|
||||
// if running in a content process, this just returns the path
|
||||
// profile was initialized in the ipc head file
|
||||
let env = Components.classes["@mozilla.org/process/environment;1"]
|
||||
.getService(Components.interfaces.nsIEnvironment);
|
||||
// the python harness sets this in the environment for us
|
||||
let profd = env.get("XPCSHELL_TEST_PROFILE_DIR");
|
||||
let file = Components.classes["@mozilla.org/file/local;1"]
|
||||
.createInstance(Components.interfaces.nsILocalFile);
|
||||
file.initWithPath(profd);
|
||||
return file;
|
||||
},
|
||||
|
||||
/**
|
||||
* Delete the content pref service's persistent datastore. We do this before
|
||||
* and after running tests to make sure we start from scratch each time. We
|
||||
* also do it during the database creation, schema migration, and backup tests.
|
||||
*/
|
||||
deleteDatabase: function ContentPrefTest_deleteDatabase() {
|
||||
var file = this.getProfileDir();
|
||||
file.append(CONTENT_PREFS_DB_FILENAME);
|
||||
if (file.exists())
|
||||
try { file.remove(false); } catch (e) { /* stupid windows box */ }
|
||||
return file;
|
||||
},
|
||||
|
||||
/**
|
||||
* Delete the backup of the content pref service's persistent datastore.
|
||||
* We do this during the database creation, schema migration, and backup tests.
|
||||
*/
|
||||
deleteBackupDatabase: function ContentPrefTest_deleteBackupDatabase() {
|
||||
var file = this.getProfileDir();
|
||||
file.append(CONTENT_PREFS_BACKUP_DB_FILENAME);
|
||||
if (file.exists())
|
||||
file.remove(false);
|
||||
return file;
|
||||
},
|
||||
|
||||
/**
|
||||
* Log a message to the console and the test log.
|
||||
*/
|
||||
log: function ContentPrefTest_log(message) {
|
||||
message = "*** ContentPrefTest: " + message;
|
||||
this._consoleSvc.logStringMessage(message);
|
||||
print(message);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
var gInPrivateBrowsing = false;
|
||||
function enterPBMode() {
|
||||
gInPrivateBrowsing = true;
|
||||
}
|
||||
function exitPBMode() {
|
||||
gInPrivateBrowsing = false;
|
||||
Services.obs.notifyObservers(null, "last-pb-context-exited", null);
|
||||
}
|
||||
|
||||
ContentPrefTest.deleteDatabase();
|
||||
|
||||
function inChildProcess() {
|
||||
var appInfo = Cc["@mozilla.org/xre/app-info;1"];
|
||||
if (!appInfo || appInfo.getService(Ci.nsIXULRuntime).processType ==
|
||||
Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Turn on logging for the content preferences service so we can troubleshoot
|
||||
// problems with the tests. Note that we cannot do this in a child process
|
||||
// without crashing (but we don't need it anyhow)
|
||||
if (!inChildProcess()) {
|
||||
var prefBranch = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefBranch);
|
||||
prefBranch.setBoolPref("browser.preferences.content.log", true);
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
ContentPrefTest.deleteDatabase();
|
||||
ContentPrefTest.__dirSvc = null;
|
||||
42
toolkit/components/contentprefs/tests/unit/test_bug248970.js
Normal file
42
toolkit/components/contentprefs/tests/unit/test_bug248970.js
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
function run_test() {
|
||||
let loadContext = { get usePrivateBrowsing() { return gInPrivateBrowsing; } };
|
||||
|
||||
ContentPrefTest.deleteDatabase();
|
||||
var cp = new ContentPrefInstance(loadContext);
|
||||
do_check_neq(cp, null, "Retrieving the content prefs service failed");
|
||||
|
||||
try {
|
||||
const uri1 = ContentPrefTest.getURI("http://www.example.com/");
|
||||
const uri2 = ContentPrefTest.getURI("http://www.anotherexample.com/");
|
||||
const pref_name = "browser.content.full-zoom";
|
||||
const zoomA = 1.5, zoomA_new = 0.8, zoomB = 1.3;
|
||||
// save Zoom-A
|
||||
cp.setPref(uri1, pref_name, zoomA);
|
||||
// make sure Zoom-A is retrievable
|
||||
do_check_eq(cp.getPref(uri1, pref_name), zoomA);
|
||||
// enter private browsing mode
|
||||
enterPBMode();
|
||||
// make sure Zoom-A is retrievable
|
||||
do_check_eq(cp.getPref(uri1, pref_name), zoomA);
|
||||
// save Zoom-B
|
||||
cp.setPref(uri2, pref_name, zoomB);
|
||||
// make sure Zoom-B is retrievable
|
||||
do_check_eq(cp.getPref(uri2, pref_name), zoomB);
|
||||
// update Zoom-A
|
||||
cp.setPref(uri1, pref_name, zoomA_new);
|
||||
// make sure Zoom-A has changed
|
||||
do_check_eq(cp.getPref(uri1, pref_name), zoomA_new);
|
||||
// exit private browsing mode
|
||||
exitPBMode();
|
||||
// make sure Zoom-A change has not persisted
|
||||
do_check_eq(cp.getPref(uri1, pref_name), zoomA);
|
||||
// make sure Zoom-B change has not persisted
|
||||
do_check_eq(cp.hasPref(uri2, pref_name), false);
|
||||
} catch (e) {
|
||||
do_throw("Unexpected exception: " + e);
|
||||
}
|
||||
}
|
||||
35
toolkit/components/contentprefs/tests/unit/test_bug503971.js
Normal file
35
toolkit/components/contentprefs/tests/unit/test_bug503971.js
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
function run_test() {
|
||||
var cps = new ContentPrefInstance(null);
|
||||
|
||||
var uri = ContentPrefTest.getURI("http://www.example.com/");
|
||||
|
||||
do_check_thrown(function () { cps.setPref(uri, null, 8); });
|
||||
do_check_thrown(function () { cps.hasPref(uri, null); });
|
||||
do_check_thrown(function () { cps.getPref(uri, null); });
|
||||
do_check_thrown(function () { cps.removePref(uri, null); });
|
||||
do_check_thrown(function () { cps.getPrefsByName(null); });
|
||||
do_check_thrown(function () { cps.removePrefsByName(null); });
|
||||
|
||||
do_check_thrown(function () { cps.setPref(uri, "", 21); });
|
||||
do_check_thrown(function () { cps.hasPref(uri, ""); });
|
||||
do_check_thrown(function () { cps.getPref(uri, ""); });
|
||||
do_check_thrown(function () { cps.removePref(uri, ""); });
|
||||
do_check_thrown(function () { cps.getPrefsByName(""); });
|
||||
do_check_thrown(function () { cps.removePrefsByName(""); });
|
||||
}
|
||||
|
||||
function do_check_thrown (aCallback) {
|
||||
var exThrown = false;
|
||||
try {
|
||||
aCallback();
|
||||
do_throw("NS_ERROR_ILLEGAL_VALUE should have been thrown here");
|
||||
} catch (e) {
|
||||
do_check_eq(e.result, Cr.NS_ERROR_ILLEGAL_VALUE);
|
||||
exThrown = true;
|
||||
}
|
||||
do_check_true(exThrown);
|
||||
}
|
||||
103
toolkit/components/contentprefs/tests/unit/test_bug679784.js
Normal file
103
toolkit/components/contentprefs/tests/unit/test_bug679784.js
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
|
||||
var prefObserver = {
|
||||
setCalledNum: 0,
|
||||
onContentPrefSet: function(aGroup, aName, aValue) {
|
||||
this.setCalledNum++;
|
||||
},
|
||||
removedCalledNum: 0,
|
||||
onContentPrefRemoved: function(aGroup, aName) {
|
||||
this.removedCalledNum++;
|
||||
}
|
||||
};
|
||||
|
||||
function run_test() {
|
||||
let loadContext = { get usePrivateBrowsing() { return gInPrivateBrowsing; } };
|
||||
|
||||
var cps = new ContentPrefInstance(loadContext);
|
||||
cps.removeGroupedPrefs();
|
||||
|
||||
var uri = ContentPrefTest.getURI("http://www.example.com/");
|
||||
var group = cps.grouper.group(uri);
|
||||
|
||||
// first, set a pref in normal mode
|
||||
cps.setPref(uri, "value", "foo");
|
||||
cps.setPref(null, "value-global", "foo-global");
|
||||
|
||||
var num;
|
||||
cps.addObserver("value", prefObserver);
|
||||
cps.addObserver("value-global", prefObserver);
|
||||
|
||||
enterPBMode();
|
||||
|
||||
// test setPref
|
||||
num = prefObserver.setCalledNum;
|
||||
cps.setPref(uri, "value", "foo-private-browsing");
|
||||
do_check_eq(cps.hasPref(uri, "value"), true);
|
||||
do_check_eq(cps.getPref(uri, "value"), "foo-private-browsing");
|
||||
do_check_eq(prefObserver.setCalledNum, num + 1);
|
||||
|
||||
num = prefObserver.setCalledNum;
|
||||
cps.setPref(null, "value-global", "foo-private-browsing-global");
|
||||
do_check_eq(cps.hasPref(null, "value-global"), true);
|
||||
do_check_eq(cps.getPref(null, "value-global"), "foo-private-browsing-global");
|
||||
do_check_eq(prefObserver.setCalledNum, num + 1);
|
||||
|
||||
// test removePref
|
||||
num = prefObserver.removedCalledNum;
|
||||
cps.removePref(uri, "value");
|
||||
do_check_eq(cps.hasPref(uri, "value"), true);
|
||||
// fallback to non private mode value
|
||||
do_check_eq(cps.getPref(uri, "value"), "foo");
|
||||
do_check_eq(prefObserver.removedCalledNum, num + 1);
|
||||
|
||||
num = prefObserver.removedCalledNum;
|
||||
cps.removePref(null, "value-global");
|
||||
do_check_eq(cps.hasPref(null, "value-global"), true);
|
||||
// fallback to non private mode value
|
||||
do_check_eq(cps.getPref(null, "value-global"), "foo-global") ;
|
||||
do_check_eq(prefObserver.removedCalledNum, num + 1);
|
||||
|
||||
// test removeGroupedPrefs
|
||||
cps.setPref(uri, "value", "foo-private-browsing");
|
||||
cps.removeGroupedPrefs();
|
||||
do_check_eq(cps.hasPref(uri, "value"), false);
|
||||
do_check_eq(cps.getPref(uri, "value"), undefined);
|
||||
|
||||
cps.setPref(null, "value-global", "foo-private-browsing-global");
|
||||
cps.removeGroupedPrefs();
|
||||
do_check_eq(cps.hasPref(null, "value-global"), true);
|
||||
do_check_eq(cps.getPref(null, "value-global"), "foo-private-browsing-global");
|
||||
|
||||
// test removePrefsByName
|
||||
num = prefObserver.removedCalledNum;
|
||||
cps.setPref(uri, "value", "foo-private-browsing");
|
||||
cps.removePrefsByName("value");
|
||||
do_check_eq(cps.hasPref(uri, "value"), false);
|
||||
do_check_eq(cps.getPref(uri, "value"), undefined);
|
||||
do_check_true(prefObserver.removedCalledNum > num);
|
||||
|
||||
num = prefObserver.removedCalledNum;
|
||||
cps.setPref(null, "value-global", "foo-private-browsing");
|
||||
cps.removePrefsByName("value-global");
|
||||
do_check_eq(cps.hasPref(null, "value-global"), false);
|
||||
do_check_eq(cps.getPref(null, "value-global"), undefined);
|
||||
do_check_true(prefObserver.removedCalledNum > num);
|
||||
|
||||
// test getPrefs
|
||||
cps.setPref(uri, "value", "foo-private-browsing");
|
||||
do_check_eq(cps.getPrefs(uri).getProperty("value"), "foo-private-browsing");
|
||||
|
||||
cps.setPref(null, "value-global", "foo-private-browsing-global");
|
||||
do_check_eq(cps.getPrefs(null).getProperty("value-global"), "foo-private-browsing-global");
|
||||
|
||||
// test getPrefsByName
|
||||
do_check_eq(cps.getPrefsByName("value").getProperty(group), "foo-private-browsing");
|
||||
do_check_eq(cps.getPrefsByName("value-global").getProperty(null), "foo-private-browsing-global");
|
||||
|
||||
cps.removeObserver("value", prefObserver);
|
||||
cps.removeObserver("value-global", prefObserver);
|
||||
}
|
||||
463
toolkit/components/contentprefs/tests/unit/test_contentPrefs.js
Normal file
463
toolkit/components/contentprefs/tests/unit/test_contentPrefs.js
Normal file
|
|
@ -0,0 +1,463 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
function run_test() {
|
||||
// Database Creation, Schema Migration, and Backup
|
||||
|
||||
// Note: in these tests we use createInstance instead of getService
|
||||
// so we can instantiate the service multiple times and make it run
|
||||
// its database initialization code each time.
|
||||
|
||||
// Create a new database.
|
||||
{
|
||||
ContentPrefTest.deleteDatabase();
|
||||
|
||||
// Get the service and make sure it has a ready database connection.
|
||||
let cps = Cc["@mozilla.org/content-pref/service;1"].
|
||||
createInstance(Ci.nsIContentPrefService);
|
||||
do_check_true(cps.DBConnection.connectionReady);
|
||||
cps.DBConnection.close();
|
||||
}
|
||||
|
||||
// Open an existing database.
|
||||
{
|
||||
let dbFile = ContentPrefTest.deleteDatabase();
|
||||
|
||||
let cps = Cc["@mozilla.org/content-pref/service;1"].
|
||||
createInstance(Ci.nsIContentPrefService);
|
||||
cps.DBConnection.close();
|
||||
do_check_true(dbFile.exists());
|
||||
|
||||
// Get the service and make sure it has a ready database connection.
|
||||
cps = Cc["@mozilla.org/content-pref/service;1"].
|
||||
createInstance(Ci.nsIContentPrefService);
|
||||
do_check_true(cps.DBConnection.connectionReady);
|
||||
cps.DBConnection.close();
|
||||
}
|
||||
|
||||
// Open an empty database.
|
||||
{
|
||||
let dbFile = ContentPrefTest.deleteDatabase();
|
||||
|
||||
// Create an empty database.
|
||||
let dbService = Cc["@mozilla.org/storage/service;1"].
|
||||
getService(Ci.mozIStorageService);
|
||||
let dbConnection = dbService.openDatabase(dbFile);
|
||||
do_check_eq(dbConnection.schemaVersion, 0);
|
||||
dbConnection.close();
|
||||
do_check_true(dbFile.exists());
|
||||
|
||||
// Get the service and make sure it has created the schema.
|
||||
let cps = Cc["@mozilla.org/content-pref/service;1"].
|
||||
createInstance(Ci.nsIContentPrefService);
|
||||
do_check_neq(cps.DBConnection.schemaVersion, 0);
|
||||
cps.DBConnection.close();
|
||||
}
|
||||
|
||||
// Open a corrupted database.
|
||||
{
|
||||
let dbFile = ContentPrefTest.deleteDatabase();
|
||||
let backupDBFile = ContentPrefTest.deleteBackupDatabase();
|
||||
|
||||
// Create a corrupted database.
|
||||
let foStream = Cc["@mozilla.org/network/file-output-stream;1"].
|
||||
createInstance(Ci.nsIFileOutputStream);
|
||||
foStream.init(dbFile, 0x02 | 0x08 | 0x20, 0o666, 0);
|
||||
let garbageData = "garbage that makes SQLite think the file is corrupted";
|
||||
foStream.write(garbageData, garbageData.length);
|
||||
foStream.close();
|
||||
|
||||
// Get the service and make sure it backs up and recreates the database.
|
||||
let cps = Cc["@mozilla.org/content-pref/service;1"].
|
||||
createInstance(Ci.nsIContentPrefService);
|
||||
do_check_true(backupDBFile.exists());
|
||||
do_check_true(cps.DBConnection.connectionReady);
|
||||
|
||||
cps.DBConnection.close();
|
||||
}
|
||||
|
||||
// Open a database with a corrupted schema.
|
||||
{
|
||||
let dbFile = ContentPrefTest.deleteDatabase();
|
||||
let backupDBFile = ContentPrefTest.deleteBackupDatabase();
|
||||
|
||||
// Create an empty database and set the schema version to a number
|
||||
// that will trigger a schema migration that will fail.
|
||||
let dbService = Cc["@mozilla.org/storage/service;1"].
|
||||
getService(Ci.mozIStorageService);
|
||||
let dbConnection = dbService.openDatabase(dbFile);
|
||||
dbConnection.schemaVersion = -1;
|
||||
dbConnection.close();
|
||||
do_check_true(dbFile.exists());
|
||||
|
||||
// Get the service and make sure it backs up and recreates the database.
|
||||
let cps = Cc["@mozilla.org/content-pref/service;1"].
|
||||
createInstance(Ci.nsIContentPrefService);
|
||||
do_check_true(backupDBFile.exists());
|
||||
do_check_true(cps.DBConnection.connectionReady);
|
||||
|
||||
cps.DBConnection.close();
|
||||
}
|
||||
|
||||
|
||||
// Now get the content pref service for real for use by the rest of the tests.
|
||||
let cps = new ContentPrefInstance(null);
|
||||
|
||||
var uri = ContentPrefTest.getURI("http://www.example.com/");
|
||||
|
||||
// Make sure disk synchronization checking is turned off by default.
|
||||
var statement = cps.DBConnection.createStatement("PRAGMA synchronous");
|
||||
statement.executeStep();
|
||||
do_check_eq(0, statement.getInt32(0));
|
||||
|
||||
// Nonexistent Pref
|
||||
|
||||
do_check_eq(cps.getPref(uri, "test.nonexistent.getPref"), undefined);
|
||||
do_check_eq(cps.setPref(uri, "test.nonexistent.setPref", 5), undefined);
|
||||
do_check_false(cps.hasPref(uri, "test.nonexistent.hasPref"));
|
||||
do_check_eq(cps.removePref(uri, "test.nonexistent.removePref"), undefined);
|
||||
|
||||
|
||||
// Existing Pref
|
||||
|
||||
cps.setPref(uri, "test.existing", 5);
|
||||
|
||||
// getPref should return the pref value
|
||||
do_check_eq(cps.getPref(uri, "test.existing"), 5);
|
||||
|
||||
// setPref should return undefined and change the value of the pref
|
||||
do_check_eq(cps.setPref(uri, "test.existing", 6), undefined);
|
||||
do_check_eq(cps.getPref(uri, "test.existing"), 6);
|
||||
|
||||
// hasPref should return true
|
||||
do_check_true(cps.hasPref(uri, "test.existing"));
|
||||
|
||||
// removePref should return undefined and remove the pref
|
||||
do_check_eq(cps.removePref(uri, "test.existing"), undefined);
|
||||
do_check_false(cps.hasPref(uri, "test.existing"));
|
||||
|
||||
|
||||
// Round-Trip Data Integrity
|
||||
|
||||
// Make sure pref values remain the same from setPref to getPref.
|
||||
|
||||
cps.setPref(uri, "test.data-integrity.integer", 5);
|
||||
do_check_eq(cps.getPref(uri, "test.data-integrity.integer"), 5);
|
||||
|
||||
cps.setPref(uri, "test.data-integrity.float", 5.5);
|
||||
do_check_eq(cps.getPref(uri, "test.data-integrity.float"), 5.5);
|
||||
|
||||
cps.setPref(uri, "test.data-integrity.boolean", true);
|
||||
do_check_eq(cps.getPref(uri, "test.data-integrity.boolean"), true);
|
||||
|
||||
cps.setPref(uri, "test.data-integrity.string", "test");
|
||||
do_check_eq(cps.getPref(uri, "test.data-integrity.string"), "test");
|
||||
|
||||
cps.setPref(uri, "test.data-integrity.null", null);
|
||||
do_check_eq(cps.getPref(uri, "test.data-integrity.null"), null);
|
||||
|
||||
// XXX Test arbitrary binary data.
|
||||
|
||||
// Make sure hasPref and removePref work on all data types.
|
||||
|
||||
do_check_true(cps.hasPref(uri, "test.data-integrity.integer"));
|
||||
do_check_true(cps.hasPref(uri, "test.data-integrity.float"));
|
||||
do_check_true(cps.hasPref(uri, "test.data-integrity.boolean"));
|
||||
do_check_true(cps.hasPref(uri, "test.data-integrity.string"));
|
||||
do_check_true(cps.hasPref(uri, "test.data-integrity.null"));
|
||||
|
||||
do_check_eq(cps.removePref(uri, "test.data-integrity.integer"), undefined);
|
||||
do_check_eq(cps.removePref(uri, "test.data-integrity.float"), undefined);
|
||||
do_check_eq(cps.removePref(uri, "test.data-integrity.boolean"), undefined);
|
||||
do_check_eq(cps.removePref(uri, "test.data-integrity.string"), undefined);
|
||||
do_check_eq(cps.removePref(uri, "test.data-integrity.null"), undefined);
|
||||
|
||||
do_check_false(cps.hasPref(uri, "test.data-integrity.integer"));
|
||||
do_check_false(cps.hasPref(uri, "test.data-integrity.float"));
|
||||
do_check_false(cps.hasPref(uri, "test.data-integrity.boolean"));
|
||||
do_check_false(cps.hasPref(uri, "test.data-integrity.string"));
|
||||
do_check_false(cps.hasPref(uri, "test.data-integrity.null"));
|
||||
|
||||
|
||||
// getPrefs
|
||||
|
||||
cps.setPref(uri, "test.getPrefs.a", 1);
|
||||
cps.setPref(uri, "test.getPrefs.b", 2);
|
||||
cps.setPref(uri, "test.getPrefs.c", 3);
|
||||
|
||||
var prefs = cps.getPrefs(uri);
|
||||
do_check_true(prefs.hasKey("test.getPrefs.a"));
|
||||
do_check_eq(prefs.get("test.getPrefs.a"), 1);
|
||||
do_check_true(prefs.hasKey("test.getPrefs.b"));
|
||||
do_check_eq(prefs.get("test.getPrefs.b"), 2);
|
||||
do_check_true(prefs.hasKey("test.getPrefs.c"));
|
||||
do_check_eq(prefs.get("test.getPrefs.c"), 3);
|
||||
|
||||
|
||||
// Site-Specificity
|
||||
|
||||
{
|
||||
// These are all different sites, and setting a pref for one of them
|
||||
// shouldn't set it for the others.
|
||||
let uri1 = ContentPrefTest.getURI("http://www.domain1.com/");
|
||||
let uri2 = ContentPrefTest.getURI("http://foo.domain1.com/");
|
||||
let uri3 = ContentPrefTest.getURI("http://domain1.com/");
|
||||
let uri4 = ContentPrefTest.getURI("http://www.domain2.com/");
|
||||
|
||||
cps.setPref(uri1, "test.site-specificity.uri1", 5);
|
||||
do_check_false(cps.hasPref(uri2, "test.site-specificity.uri1"));
|
||||
do_check_false(cps.hasPref(uri3, "test.site-specificity.uri1"));
|
||||
do_check_false(cps.hasPref(uri4, "test.site-specificity.uri1"));
|
||||
|
||||
cps.setPref(uri2, "test.site-specificity.uri2", 5);
|
||||
do_check_false(cps.hasPref(uri1, "test.site-specificity.uri2"));
|
||||
do_check_false(cps.hasPref(uri3, "test.site-specificity.uri2"));
|
||||
do_check_false(cps.hasPref(uri4, "test.site-specificity.uri2"));
|
||||
|
||||
cps.setPref(uri3, "test.site-specificity.uri3", 5);
|
||||
do_check_false(cps.hasPref(uri1, "test.site-specificity.uri3"));
|
||||
do_check_false(cps.hasPref(uri2, "test.site-specificity.uri3"));
|
||||
do_check_false(cps.hasPref(uri4, "test.site-specificity.uri3"));
|
||||
|
||||
cps.setPref(uri4, "test.site-specificity.uri4", 5);
|
||||
do_check_false(cps.hasPref(uri1, "test.site-specificity.uri4"));
|
||||
do_check_false(cps.hasPref(uri2, "test.site-specificity.uri4"));
|
||||
do_check_false(cps.hasPref(uri3, "test.site-specificity.uri4"));
|
||||
}
|
||||
|
||||
// Observers
|
||||
|
||||
var specificObserver = {
|
||||
interfaces: [Ci.nsIContentPrefObserver, Ci.nsISupports],
|
||||
|
||||
QueryInterface: function ContentPrefTest_QueryInterface(iid) {
|
||||
if (!this.interfaces.some( function(v) { return iid.equals(v) } ))
|
||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||
return this;
|
||||
},
|
||||
|
||||
numTimesSetCalled: 0,
|
||||
onContentPrefSet: function specificObserver_onContentPrefSet(group, name, value) {
|
||||
++this.numTimesSetCalled;
|
||||
do_check_eq(group, "www.example.com");
|
||||
do_check_eq(name, "test.observer.1");
|
||||
do_check_eq(value, "test value");
|
||||
},
|
||||
|
||||
numTimesRemovedCalled: 0,
|
||||
onContentPrefRemoved: function specificObserver_onContentPrefRemoved(group, name) {
|
||||
++this.numTimesRemovedCalled;
|
||||
do_check_eq(group, "www.example.com");
|
||||
do_check_eq(name, "test.observer.1");
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
var genericObserver = {
|
||||
interfaces: [Ci.nsIContentPrefObserver, Ci.nsISupports],
|
||||
|
||||
QueryInterface: function ContentPrefTest_QueryInterface(iid) {
|
||||
if (!this.interfaces.some( function(v) { return iid.equals(v) } ))
|
||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||
return this;
|
||||
},
|
||||
|
||||
numTimesSetCalled: 0,
|
||||
onContentPrefSet: function genericObserver_onContentPrefSet(group, name, value, isPrivate) {
|
||||
++this.numTimesSetCalled;
|
||||
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);
|
||||
else if (name != "test.observer.1" && name != "test.observer.2")
|
||||
do_throw("genericObserver.onContentPrefSet: " +
|
||||
"name not in (test.observer.(1|2|normal|private))");
|
||||
do_check_eq(value, "test value");
|
||||
},
|
||||
|
||||
numTimesRemovedCalled: 0,
|
||||
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: " +
|
||||
"name not in (test.observer.(1|2|normal|private))");
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Make sure we can add observers, observers get notified about changes,
|
||||
// specific observers only get notified about changes to the specific setting,
|
||||
// and generic observers get notified about changes to all settings.
|
||||
cps.addObserver("test.observer.1", specificObserver);
|
||||
cps.addObserver(null, genericObserver);
|
||||
cps.setPref(uri, "test.observer.1", "test value");
|
||||
cps.setPref(uri, "test.observer.2", "test value");
|
||||
cps.removePref(uri, "test.observer.1");
|
||||
cps.removePref(uri, "test.observer.2");
|
||||
do_check_eq(specificObserver.numTimesSetCalled, 1);
|
||||
do_check_eq(genericObserver.numTimesSetCalled, 2);
|
||||
do_check_eq(specificObserver.numTimesRemovedCalled, 1);
|
||||
do_check_eq(genericObserver.numTimesRemovedCalled, 2);
|
||||
|
||||
// Make sure information about private context is properly
|
||||
// retrieved by the observer.
|
||||
cps.setPref(uri, "test.observer.private", "test value", {usePrivateBrowsing: true});
|
||||
cps.setPref(uri, "test.observer.normal", "test value", {usePrivateBrowsing: false});
|
||||
cps.removePref(uri, "test.observer.private");
|
||||
cps.removePref(uri, "test.observer.normal");
|
||||
|
||||
// Make sure we can remove observers and they don't get notified
|
||||
// about changes anymore.
|
||||
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, 4);
|
||||
do_check_eq(specificObserver.numTimesRemovedCalled, 1);
|
||||
do_check_eq(genericObserver.numTimesRemovedCalled, 3);
|
||||
|
||||
|
||||
// Get/Remove Prefs By Name
|
||||
|
||||
{
|
||||
var anObserver = {
|
||||
interfaces: [Ci.nsIContentPrefObserver, Ci.nsISupports],
|
||||
|
||||
QueryInterface: function ContentPrefTest_QueryInterface(iid) {
|
||||
if (!this.interfaces.some( function(v) { return iid.equals(v) } ))
|
||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||
return this;
|
||||
},
|
||||
|
||||
onContentPrefSet: function anObserver_onContentPrefSet(group, name, value) {
|
||||
},
|
||||
|
||||
expectedDomains: [],
|
||||
numTimesRemovedCalled: 0,
|
||||
onContentPrefRemoved: function anObserver_onContentPrefRemoved(group, name) {
|
||||
++this.numTimesRemovedCalled;
|
||||
|
||||
// remove the domain from the list of expected domains
|
||||
var index = this.expectedDomains.indexOf(group);
|
||||
do_check_true(index >= 0);
|
||||
this.expectedDomains.splice(index, 1);
|
||||
}
|
||||
};
|
||||
|
||||
let uri1 = ContentPrefTest.getURI("http://www.domain1.com/");
|
||||
let uri2 = ContentPrefTest.getURI("http://foo.domain1.com/");
|
||||
let uri3 = ContentPrefTest.getURI("http://domain1.com/");
|
||||
let uri4 = ContentPrefTest.getURI("http://www.domain2.com/");
|
||||
|
||||
cps.setPref(uri1, "test.byname.1", 1);
|
||||
cps.setPref(uri1, "test.byname.2", 2);
|
||||
cps.setPref(uri2, "test.byname.1", 4);
|
||||
cps.setPref(uri3, "test.byname.3", 8);
|
||||
cps.setPref(uri4, "test.byname.1", 16);
|
||||
cps.setPref(null, "test.byname.1", 32);
|
||||
cps.setPref(null, "test.byname.2", false);
|
||||
|
||||
function enumerateAndCheck(testName, expectedSum, expectedDomains) {
|
||||
var prefsByName = cps.getPrefsByName(testName);
|
||||
var enumerator = prefsByName.enumerator;
|
||||
var sum = 0;
|
||||
while (enumerator.hasMoreElements()) {
|
||||
var property = enumerator.getNext().QueryInterface(Components.interfaces.nsIProperty);
|
||||
sum += parseInt(property.value);
|
||||
|
||||
// remove the domain from the list of expected domains
|
||||
var index = expectedDomains.indexOf(property.name);
|
||||
do_check_true(index >= 0);
|
||||
expectedDomains.splice(index, 1);
|
||||
}
|
||||
do_check_eq(sum, expectedSum);
|
||||
// check all domains have been removed from the array
|
||||
do_check_eq(expectedDomains.length, 0);
|
||||
}
|
||||
|
||||
enumerateAndCheck("test.byname.1", 53,
|
||||
["foo.domain1.com", null, "www.domain1.com", "www.domain2.com"]);
|
||||
enumerateAndCheck("test.byname.2", 2, ["www.domain1.com", null]);
|
||||
enumerateAndCheck("test.byname.3", 8, ["domain1.com"]);
|
||||
|
||||
cps.addObserver("test.byname.1", anObserver);
|
||||
anObserver.expectedDomains = ["foo.domain1.com", null, "www.domain1.com", "www.domain2.com"];
|
||||
|
||||
cps.removePrefsByName("test.byname.1");
|
||||
do_check_false(cps.hasPref(uri1, "test.byname.1"));
|
||||
do_check_false(cps.hasPref(uri2, "test.byname.1"));
|
||||
do_check_false(cps.hasPref(uri3, "test.byname.1"));
|
||||
do_check_false(cps.hasPref(uri4, "test.byname.1"));
|
||||
do_check_false(cps.hasPref(null, "test.byname.1"));
|
||||
do_check_true(cps.hasPref(uri1, "test.byname.2"));
|
||||
do_check_true(cps.hasPref(uri3, "test.byname.3"));
|
||||
|
||||
do_check_eq(anObserver.numTimesRemovedCalled, 4);
|
||||
do_check_eq(anObserver.expectedDomains.length, 0);
|
||||
|
||||
cps.removeObserver("test.byname.1", anObserver);
|
||||
|
||||
// Clean up after ourselves
|
||||
cps.removePref(uri1, "test.byname.2");
|
||||
cps.removePref(uri3, "test.byname.3");
|
||||
cps.removePref(null, "test.byname.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 = dbConnection.createStatement("SELECT COUNT(*) AS count FROM prefs");
|
||||
|
||||
let groupCount = 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.executeStep();
|
||||
do_check_true(prefCount.row.count > 0);
|
||||
prefCount.reset();
|
||||
groupCount.executeStep();
|
||||
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.executeStep();
|
||||
do_check_true(prefCount.row.count == 1);
|
||||
prefCount.reset();
|
||||
groupCount.executeStep();
|
||||
do_check_true(groupCount.row.count == 0);
|
||||
groupCount.reset();
|
||||
let globalPref = dbConnection.createStatement("SELECT groupID FROM prefs");
|
||||
globalPref.executeStep();
|
||||
do_check_true(globalPref.row.groupID == null);
|
||||
globalPref.reset();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,244 @@
|
|||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
var cps = new ContentPrefInstance(null);
|
||||
|
||||
function run_test() {
|
||||
testCacheWorks("test1.example.com", "test-pref1");
|
||||
testHasCachedPrefFunction("test2.example.com", "test-pref2");
|
||||
testSetCaches("test3.example.com", "test-pref3");
|
||||
testGetCaches("test4.example.com", "test-pref4");
|
||||
testRemovePrefs("test5.example.com", "test-pref5");
|
||||
testTypeConversions("test6.example.com", "test-pref6");
|
||||
testNonExistingPrefCachesAsUndefined("test7.example.com", "test-pref7");
|
||||
testCacheEviction("test8.example.com", "test-pref8");
|
||||
}
|
||||
|
||||
function testCacheWorks(uri, prefName) {
|
||||
const CACHED_VALUE = 3;
|
||||
const NEW_VALUE = 5;
|
||||
|
||||
cps.setPref(uri, prefName, CACHED_VALUE);
|
||||
do_check_eq(cps.getPref(uri, prefName), CACHED_VALUE);
|
||||
|
||||
// Now change the value directly through the DB and check
|
||||
// that the cached value is different
|
||||
|
||||
let groupId = selectValue("SELECT id FROM groups WHERE name = :param1", "id", uri);
|
||||
let settingId = selectValue("SELECT id FROM settings WHERE name = :param1", "id", prefName);
|
||||
let prefId = selectValue("SELECT id FROM prefs WHERE groupID = :param1 AND settingID = :param2",
|
||||
"id", groupId, settingId);
|
||||
|
||||
let stmt = cps.DBConnection.createStatement("UPDATE prefs SET value = :value WHERE id = :id");
|
||||
stmt.params.value = NEW_VALUE;
|
||||
stmt.params.id = prefId;
|
||||
stmt.execute();
|
||||
|
||||
let dbValue = selectValue("SELECT value FROM prefs WHERE id = :param1", "value", prefId);
|
||||
let cacheValue = cps.getPref(uri, prefName);
|
||||
|
||||
do_check_eq(dbValue, NEW_VALUE);
|
||||
do_check_eq(cacheValue, CACHED_VALUE);
|
||||
do_check_neq(cacheValue, dbValue);
|
||||
|
||||
do_test_pending();
|
||||
cps.getPref(uri, prefName, function (value) {
|
||||
do_check_eq(dbValue, NEW_VALUE);
|
||||
do_check_eq(value, CACHED_VALUE);
|
||||
do_check_neq(value, dbValue);
|
||||
do_test_finished();
|
||||
});
|
||||
}
|
||||
|
||||
function testHasCachedPrefFunction(uri, prefName) {
|
||||
const STARTING_VALUE = 3;
|
||||
const NEW_VALUE = 5;
|
||||
|
||||
do_check_false(isCached(uri, prefName));
|
||||
|
||||
cps.setPref(uri, prefName, STARTING_VALUE);
|
||||
|
||||
let groupId = selectValue("SELECT id FROM groups WHERE name = :param1", "id", uri);
|
||||
let settingId = selectValue("SELECT id FROM settings WHERE name = :param1", "id", prefName);
|
||||
let prefId = selectValue("SELECT id FROM prefs WHERE groupID = :param1 AND settingID = :param2",
|
||||
"id", groupId, settingId);
|
||||
|
||||
do_check_neq(prefId, undefined);
|
||||
|
||||
let originalValue = selectValue("SELECT value FROM prefs WHERE id = :param1", "value", prefId);
|
||||
do_check_eq(originalValue, STARTING_VALUE);
|
||||
|
||||
let stmt = cps.DBConnection.createStatement("UPDATE prefs SET value = :value WHERE id = :id");
|
||||
stmt.params.value = NEW_VALUE;
|
||||
stmt.params.id = prefId;
|
||||
stmt.execute();
|
||||
|
||||
let newValue = selectValue("SELECT value FROM prefs WHERE id = :param1", "value", prefId);
|
||||
do_check_eq(newValue, NEW_VALUE);
|
||||
|
||||
let cachedValue = cps.getPref(uri, prefName);
|
||||
do_check_eq(cachedValue, STARTING_VALUE);
|
||||
do_check_true(isCached(uri, prefName));
|
||||
}
|
||||
|
||||
function testSetCaches(uri, prefName) {
|
||||
cps.setPref(uri, prefName, 0);
|
||||
do_check_true(isCached(uri, prefName));
|
||||
}
|
||||
|
||||
function testRemovePrefs(uri, prefName) {
|
||||
|
||||
/* removePref */
|
||||
cps.setPref("www1." + uri, prefName, 1);
|
||||
|
||||
do_check_eq(cps.getPref("www1." + uri, prefName), 1);
|
||||
|
||||
cps.removePref("www1." + uri, prefName);
|
||||
|
||||
do_check_false(isCached("www1." + uri, prefName));
|
||||
do_check_false(cps.hasPref("www1." + uri, prefName));
|
||||
do_check_neq(cps.getPref("www1." + uri, prefName), 1);
|
||||
|
||||
/* removeGroupedPrefs */
|
||||
cps.setPref("www2." + uri, prefName, 2);
|
||||
cps.setPref("www3." + uri, prefName, 3);
|
||||
|
||||
do_check_eq(cps.getPref("www2." + uri, prefName), 2);
|
||||
do_check_eq(cps.getPref("www3." + uri, prefName), 3);
|
||||
|
||||
cps.removeGroupedPrefs();
|
||||
|
||||
do_check_false(isCached("www2." + uri, prefName));
|
||||
do_check_false(isCached("www3." + uri, prefName));
|
||||
do_check_false(cps.hasPref("www2." + uri, prefName));
|
||||
do_check_false(cps.hasPref("www3." + uri, prefName));
|
||||
do_check_neq(cps.getPref("www2." + uri, prefName), 2);
|
||||
do_check_neq(cps.getPref("www3." + uri, prefName), 3);
|
||||
|
||||
/* removePrefsByName */
|
||||
cps.setPref("www4." + uri, prefName, 4);
|
||||
cps.setPref("www5." + uri, prefName, 5);
|
||||
|
||||
do_check_eq(cps.getPref("www4." + uri, prefName), 4);
|
||||
do_check_eq(cps.getPref("www5." + uri, prefName), 5);
|
||||
|
||||
cps.removePrefsByName(prefName);
|
||||
|
||||
do_check_false(isCached("www4." + uri, prefName));
|
||||
do_check_false(isCached("www5." + uri, prefName));
|
||||
do_check_false(cps.hasPref("www4." + uri, prefName));
|
||||
do_check_false(cps.hasPref("www5." + uri, prefName));
|
||||
do_check_neq(cps.getPref("www4." + uri, prefName), 4);
|
||||
do_check_neq(cps.getPref("www5." + uri, prefName), 5);
|
||||
}
|
||||
|
||||
function testGetCaches(uri, prefName) {
|
||||
const VALUE = 4;
|
||||
|
||||
let insertGroup = cps.DBConnection.createStatement("INSERT INTO groups (name) VALUES (:name)");
|
||||
insertGroup.params.name = uri;
|
||||
insertGroup.execute();
|
||||
let groupId = cps.DBConnection.lastInsertRowID;
|
||||
|
||||
let insertSetting = cps.DBConnection.createStatement("INSERT INTO settings (name) VALUES (:name)");
|
||||
insertSetting.params.name = prefName;
|
||||
insertSetting.execute();
|
||||
let settingId = cps.DBConnection.lastInsertRowID;
|
||||
|
||||
let insertPref = cps.DBConnection.createStatement(`
|
||||
INSERT INTO prefs (groupID, settingID, value)
|
||||
VALUES (:groupId, :settingId, :value)
|
||||
`);
|
||||
insertPref.params.groupId = groupId;
|
||||
insertPref.params.settingId = settingId;
|
||||
insertPref.params.value = VALUE;
|
||||
insertPref.execute();
|
||||
let prefId = cps.DBConnection.lastInsertRowID;
|
||||
|
||||
let dbValue = selectValue("SELECT value FROM prefs WHERE id = :param1", "value", prefId);
|
||||
|
||||
// First access from service should hit the DB
|
||||
let svcValue = cps.getPref(uri, prefName);
|
||||
|
||||
// Second time should get the value from cache
|
||||
let cacheValue = cps.getPref(uri, prefName);
|
||||
|
||||
do_check_eq(VALUE, dbValue);
|
||||
do_check_eq(VALUE, svcValue);
|
||||
do_check_eq(VALUE, cacheValue);
|
||||
|
||||
do_check_true(isCached(uri, prefName));
|
||||
}
|
||||
|
||||
function testTypeConversions(uri, prefName) {
|
||||
let value;
|
||||
|
||||
cps.setPref(uri, prefName, true);
|
||||
value = cps.getPref(uri, prefName);
|
||||
do_check_true(value === 1);
|
||||
|
||||
cps.setPref(uri, prefName, false);
|
||||
value = cps.getPref(uri, prefName);
|
||||
do_check_true(value === 0);
|
||||
|
||||
cps.setPref(uri, prefName, null);
|
||||
value = cps.getPref(uri, prefName);
|
||||
do_check_true(value === null);
|
||||
|
||||
cps.setPref(uri, prefName, undefined);
|
||||
value = cps.getPref(uri, prefName);
|
||||
do_check_true(value === null);
|
||||
}
|
||||
|
||||
function testNonExistingPrefCachesAsUndefined(uri, prefName) {
|
||||
|
||||
do_check_false(isCached(uri, prefName));
|
||||
|
||||
// Cache the pref
|
||||
let value = cps.getPref(uri, prefName);
|
||||
do_check_true(value === undefined);
|
||||
|
||||
do_check_true(isCached(uri, prefName));
|
||||
|
||||
// Cached pref
|
||||
value = cps.getPref(uri, prefName);
|
||||
do_check_true(value === undefined);
|
||||
}
|
||||
|
||||
function testCacheEviction(uri, prefName) {
|
||||
|
||||
cps.setPref(uri, prefName, 5);
|
||||
do_check_eq(cps.getPref(uri, prefName), 5);
|
||||
do_check_true(isCached(uri, prefName));
|
||||
|
||||
// try to evict value from cache by adding various other entries
|
||||
const ENTRIES_TO_ADD = 200;
|
||||
for (let i = 0; i < ENTRIES_TO_ADD; i++) {
|
||||
let uriToAdd = "www" + i + uri;
|
||||
cps.setPref(uriToAdd, prefName, 0);
|
||||
}
|
||||
|
||||
do_check_false(isCached(uri, prefName));
|
||||
|
||||
}
|
||||
|
||||
function selectValue(stmt, columnName, param1, param2) {
|
||||
stmt = cps.DBConnection.createStatement(stmt);
|
||||
if (param1)
|
||||
stmt.params.param1 = param1;
|
||||
|
||||
if (param2)
|
||||
stmt.params.param2 = param2;
|
||||
|
||||
stmt.executeStep();
|
||||
let val = stmt.row[columnName];
|
||||
stmt.reset();
|
||||
stmt.finalize();
|
||||
return val;
|
||||
}
|
||||
|
||||
function isCached(uri, prefName) {
|
||||
return cps.hasCachedPref(uri, prefName);
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
var cps = new ContentPrefInstance(null);
|
||||
var uri = ContentPrefTest.getURI("http://www.example.com/");
|
||||
|
||||
function run_test() {
|
||||
do_test_pending();
|
||||
|
||||
cps.setPref(uri, "asynctest", "pie");
|
||||
do_check_eq(cps.getPref(uri, "asynctest"), "pie");
|
||||
|
||||
cps.getPref(uri, "asynctest", function(aValue) {
|
||||
do_check_eq(aValue, "pie");
|
||||
testCallbackObj();
|
||||
});
|
||||
}
|
||||
|
||||
function testCallbackObj() {
|
||||
cps.getPref(uri, "asynctest", {
|
||||
onResult: function(aValue) {
|
||||
do_check_eq(aValue, "pie");
|
||||
cps.removePref(uri, "asynctest");
|
||||
testNoResult();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function testNoResult() {
|
||||
cps.getPref(uri, "asynctest", function(aValue) {
|
||||
do_check_eq(aValue, undefined);
|
||||
do_test_finished();
|
||||
});
|
||||
}
|
||||
128
toolkit/components/contentprefs/tests/unit/test_stringGroups.js
Normal file
128
toolkit/components/contentprefs/tests/unit/test_stringGroups.js
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
function run_test() {
|
||||
|
||||
var cps = new ContentPrefInstance(null);
|
||||
|
||||
// Make sure disk synchronization checking is turned off by default.
|
||||
var statement = cps.DBConnection.createStatement("PRAGMA synchronous");
|
||||
statement.executeStep();
|
||||
do_check_eq(0, statement.getInt32(0));
|
||||
|
||||
// These are the different types of aGroup arguments we'll test.
|
||||
var anObject = {"foo":"bar"}; // a simple object
|
||||
var uri = ContentPrefTest.getURI("http://www.example.com/"); // nsIURI
|
||||
var stringURI = "www.example.com"; // typeof = "string"
|
||||
var stringObjectURI = new String("www.example.com"); // typeof = "object"
|
||||
|
||||
{
|
||||
// First check that all the methods work or don't work.
|
||||
function simple_test_methods(aGroup, shouldThrow) {
|
||||
var prefName = "test.pref.0";
|
||||
var prefValue = Math.floor(Math.random() * 100);
|
||||
|
||||
if (shouldThrow) {
|
||||
do_check_thrown(function () { cps.getPref(aGroup, prefName); });
|
||||
do_check_thrown(function () { cps.setPref(aGroup, prefName, prefValue); });
|
||||
do_check_thrown(function () { cps.hasPref(aGroup, prefName); });
|
||||
do_check_thrown(function () { cps.removePref(aGroup, prefName); });
|
||||
do_check_thrown(function () { cps.getPrefs(aGroup); });
|
||||
} else {
|
||||
do_check_eq(cps.setPref(aGroup, prefName, prefValue), undefined);
|
||||
do_check_true(cps.hasPref(aGroup, prefName));
|
||||
do_check_eq(cps.getPref(aGroup, prefName), prefValue);
|
||||
do_check_eq(cps.removePref(aGroup, prefName), undefined);
|
||||
do_check_false(cps.hasPref(aGroup, prefName));
|
||||
}
|
||||
}
|
||||
|
||||
simple_test_methods(cps, true); // arbitrary nsISupports object, should throw too
|
||||
simple_test_methods(anObject, true);
|
||||
simple_test_methods(uri, false);
|
||||
simple_test_methods(stringURI, false);
|
||||
simple_test_methods(stringObjectURI, false);
|
||||
}
|
||||
|
||||
{
|
||||
// Now we'll check that each argument produces the same result.
|
||||
function complex_test_methods(aGroup) {
|
||||
var prefName = "test.pref.1";
|
||||
var prefValue = Math.floor(Math.random() * 100);
|
||||
|
||||
do_check_eq(cps.setPref(aGroup, prefName, prefValue), undefined);
|
||||
|
||||
do_check_true(cps.hasPref(uri, prefName));
|
||||
do_check_true(cps.hasPref(stringURI, prefName));
|
||||
do_check_true(cps.hasPref(stringObjectURI, prefName));
|
||||
|
||||
do_check_eq(cps.getPref(uri, prefName), prefValue);
|
||||
do_check_eq(cps.getPref(stringURI, prefName), prefValue);
|
||||
do_check_eq(cps.getPref(stringObjectURI, prefName), prefValue);
|
||||
|
||||
do_check_eq(cps.removePref(aGroup, prefName), undefined);
|
||||
|
||||
do_check_false(cps.hasPref(uri, prefName));
|
||||
do_check_false(cps.hasPref(stringURI, prefName));
|
||||
do_check_false(cps.hasPref(stringObjectURI, prefName));
|
||||
}
|
||||
|
||||
complex_test_methods(uri);
|
||||
complex_test_methods(stringURI);
|
||||
complex_test_methods(stringObjectURI);
|
||||
}
|
||||
|
||||
{
|
||||
// test getPrefs returns the same prefs
|
||||
do_check_eq(cps.setPref(stringObjectURI, "test.5", 5), undefined);
|
||||
do_check_eq(cps.setPref(stringURI, "test.2", 2), undefined);
|
||||
do_check_eq(cps.setPref(uri, "test.1", 1), undefined);
|
||||
|
||||
enumerateAndCheck(cps.getPrefs(uri), 8, ["test.1", "test.2", "test.5"]);
|
||||
enumerateAndCheck(cps.getPrefs(stringURI), 8, ["test.1", "test.2", "test.5"]);
|
||||
enumerateAndCheck(cps.getPrefs(stringObjectURI), 8, ["test.1", "test.2", "test.5"]);
|
||||
|
||||
do_check_eq(cps.setPref(uri, "test.4", 4), undefined);
|
||||
do_check_eq(cps.setPref(stringObjectURI, "test.0", 0), undefined);
|
||||
|
||||
enumerateAndCheck(cps.getPrefs(uri), 12, ["test.0", "test.1", "test.2", "test.4", "test.5"]);
|
||||
enumerateAndCheck(cps.getPrefs(stringURI), 12, ["test.0", "test.1", "test.2", "test.4", "test.5"]);
|
||||
enumerateAndCheck(cps.getPrefs(stringObjectURI), 12, ["test.0", "test.1", "test.2", "test.4", "test.5"]);
|
||||
|
||||
do_check_eq(cps.setPref(stringURI, "test.3", 3), undefined);
|
||||
|
||||
enumerateAndCheck(cps.getPrefs(uri), 15, ["test.0", "test.1", "test.2", "test.3", "test.4", "test.5"]);
|
||||
enumerateAndCheck(cps.getPrefs(stringURI), 15, ["test.0", "test.1", "test.2", "test.3", "test.4", "test.5"]);
|
||||
enumerateAndCheck(cps.getPrefs(stringObjectURI), 15, ["test.0", "test.1", "test.2", "test.3", "test.4", "test.5"]);
|
||||
}
|
||||
}
|
||||
|
||||
function do_check_thrown (aCallback) {
|
||||
var exThrown = false;
|
||||
try {
|
||||
aCallback();
|
||||
do_throw("NS_ERROR_ILLEGAL_VALUE should have been thrown here");
|
||||
} catch (e) {
|
||||
do_check_eq(e.result, Cr.NS_ERROR_ILLEGAL_VALUE);
|
||||
exThrown = true;
|
||||
}
|
||||
do_check_true(exThrown);
|
||||
}
|
||||
|
||||
function enumerateAndCheck(prefs, expectedSum, expectedNames) {
|
||||
var enumerator = prefs.enumerator;
|
||||
var sum = 0;
|
||||
while (enumerator.hasMoreElements()) {
|
||||
var property = enumerator.getNext().QueryInterface(Components.interfaces.nsIProperty);
|
||||
sum += parseInt(property.value);
|
||||
|
||||
// remove the pref name from the list of expected names
|
||||
var index = expectedNames.indexOf(property.name);
|
||||
do_check_true(index >= 0);
|
||||
expectedNames.splice(index, 1);
|
||||
}
|
||||
do_check_eq(sum, expectedSum);
|
||||
// check all pref names have been removed from the array
|
||||
do_check_eq(expectedNames.length, 0);
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
var cps = new ContentPrefInstance(null);
|
||||
|
||||
function run_test() {
|
||||
var uri1 = ContentPrefTest.getURI("http://www.domain1.com/");
|
||||
var uri2 = ContentPrefTest.getURI("http://foo.domain1.com/");
|
||||
var uri3 = ContentPrefTest.getURI("http://domain1.com/");
|
||||
var uri4 = ContentPrefTest.getURI("http://www.domain2.com/");
|
||||
|
||||
cps.setPref(uri1, "one", 1);
|
||||
cps.setPref(uri1, "two", 2);
|
||||
cps.setPref(uri2, "one", 4);
|
||||
cps.setPref(uri3, "three", 8);
|
||||
cps.setPref(uri4, "two", 16);
|
||||
|
||||
cps.removePref(uri3, "three"); // uri3 should be removed now
|
||||
checkForUnusedGroups();
|
||||
checkForUnusedSettings();
|
||||
|
||||
cps.removePrefsByName("two"); // uri4 should be removed now
|
||||
checkForUnusedGroups();
|
||||
checkForUnusedSettings();
|
||||
|
||||
cps.removeGroupedPrefs();
|
||||
checkForUnusedGroups();
|
||||
checkForUnusedSettings();
|
||||
}
|
||||
|
||||
function checkForUnusedGroups() {
|
||||
var stmt = cps.DBConnection.createStatement(`
|
||||
SELECT COUNT(*) AS count FROM groups
|
||||
WHERE id NOT IN (SELECT DISTINCT groupID FROM prefs)
|
||||
`);
|
||||
stmt.executeStep();
|
||||
do_check_eq(0, stmt.row.count);
|
||||
stmt.reset();
|
||||
stmt.finalize();
|
||||
}
|
||||
|
||||
function checkForUnusedSettings() {
|
||||
var stmt = cps.DBConnection.createStatement(`
|
||||
SELECT COUNT(*) AS count FROM settings
|
||||
WHERE id NOT IN (SELECT DISTINCT settingID FROM prefs)
|
||||
`);
|
||||
stmt.executeStep();
|
||||
do_check_eq(0, stmt.row.count);
|
||||
stmt.reset();
|
||||
stmt.finalize();
|
||||
}
|
||||
12
toolkit/components/contentprefs/tests/unit/xpcshell.ini
Normal file
12
toolkit/components/contentprefs/tests/unit/xpcshell.ini
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
[DEFAULT]
|
||||
head = head_contentPrefs.js
|
||||
tail = tail_contentPrefs.js
|
||||
|
||||
[test_bug248970.js]
|
||||
[test_bug503971.js]
|
||||
[test_bug679784.js]
|
||||
[test_contentPrefs.js]
|
||||
[test_contentPrefsCache.js]
|
||||
[test_getPrefAsync.js]
|
||||
[test_stringGroups.js]
|
||||
[test_unusedGroupsAndSettings.js]
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
"extends": [
|
||||
"../../../../../testing/xpcshell/xpcshell.eslintrc.js"
|
||||
]
|
||||
};
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
var EXPORTED_SYMBOLS = [
|
||||
"AsyncRunner",
|
||||
];
|
||||
|
||||
const { interfaces: Ci, classes: Cc } = Components;
|
||||
|
||||
function AsyncRunner(callbacks) {
|
||||
this._callbacks = callbacks;
|
||||
this._iteratorQueue = [];
|
||||
|
||||
// This catches errors reported to the console, e.g., via Cu.reportError.
|
||||
Cc["@mozilla.org/consoleservice;1"].
|
||||
getService(Ci.nsIConsoleService).
|
||||
registerListener(this);
|
||||
}
|
||||
|
||||
AsyncRunner.prototype = {
|
||||
|
||||
appendIterator: function AR_appendIterator(iter) {
|
||||
this._iteratorQueue.push(iter);
|
||||
},
|
||||
|
||||
next: function AR_next(arg) {
|
||||
if (!this._iteratorQueue.length) {
|
||||
this.destroy();
|
||||
this._callbacks.done();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
var { done, value } = this._iteratorQueue[0].next(arg);
|
||||
if (done) {
|
||||
this._iteratorQueue.shift();
|
||||
this.next();
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
this._callbacks.error(err);
|
||||
}
|
||||
|
||||
// val is truthy => call next
|
||||
// val is an iterator => prepend it to the queue and start on it
|
||||
if (value) {
|
||||
if (typeof(value) != "boolean")
|
||||
this._iteratorQueue.unshift(value);
|
||||
this.next();
|
||||
}
|
||||
},
|
||||
|
||||
destroy: function AR_destroy() {
|
||||
Cc["@mozilla.org/consoleservice;1"].
|
||||
getService(Ci.nsIConsoleService).
|
||||
unregisterListener(this);
|
||||
this.destroy = function AR_alreadyDestroyed() {};
|
||||
},
|
||||
|
||||
observe: function AR_consoleServiceListener(msg) {
|
||||
if (msg instanceof Ci.nsIScriptError &&
|
||||
!(msg.flags & Ci.nsIScriptError.warningFlag))
|
||||
{
|
||||
this._callbacks.consoleError(msg);
|
||||
}
|
||||
},
|
||||
};
|
||||
401
toolkit/components/contentprefs/tests/unit_cps2/head.js
Normal file
401
toolkit/components/contentprefs/tests/unit_cps2/head.js
Normal file
|
|
@ -0,0 +1,401 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
var { interfaces: Ci, classes: Cc, results: Cr, utils: Cu } = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
var cps;
|
||||
var asyncRunner;
|
||||
var next;
|
||||
|
||||
(function init() {
|
||||
// There has to be a profile directory before the CPS service is gotten.
|
||||
do_get_profile();
|
||||
})();
|
||||
|
||||
function runAsyncTests(tests, dontResetBefore = false) {
|
||||
do_test_pending();
|
||||
|
||||
cps = Cc["@mozilla.org/content-pref/service;1"].
|
||||
getService(Ci.nsIContentPrefService2);
|
||||
|
||||
let s = {};
|
||||
Cu.import("resource://test/AsyncRunner.jsm", s);
|
||||
asyncRunner = new s.AsyncRunner({
|
||||
done: do_test_finished,
|
||||
error: function (err) {
|
||||
// xpcshell test functions like equal throw NS_ERROR_ABORT on
|
||||
// failure. Ignore those and catch only uncaught exceptions.
|
||||
if (err !== Cr.NS_ERROR_ABORT) {
|
||||
if (err.stack) {
|
||||
err = err + "\n\nTraceback (most recent call first):\n" + err.stack +
|
||||
"\nUseless do_throw stack:";
|
||||
}
|
||||
do_throw(err);
|
||||
}
|
||||
},
|
||||
consoleError: function (scriptErr) {
|
||||
// Previously, this code checked for console errors related to the test,
|
||||
// and treated them as failures. This was problematic, because our current
|
||||
// very-broken exception reporting machinery in XPCWrappedJSClass reports
|
||||
// errors to the console even if there's actually JS on the stack above
|
||||
// that will catch them. And a lot of the tests here intentionally trigger
|
||||
// error conditions on the JS-implemented XPCOM component (see erroneous()
|
||||
// in test_getSubdomains.js, for example). In the old world, we got lucky,
|
||||
// and the errors were never reported to the console due to happenstantial
|
||||
// JSContext reasons that aren't really worth going into.
|
||||
//
|
||||
// So. We make sure to dump this stuff so that it shows up in the logs, but
|
||||
// don't turn them into duplicate failures of the exception that was already
|
||||
// propagated to the caller.
|
||||
dump("AsyncRunner.jsm observed console error: " + scriptErr + "\n");
|
||||
}
|
||||
});
|
||||
|
||||
next = asyncRunner.next.bind(asyncRunner);
|
||||
|
||||
do_register_cleanup(function () {
|
||||
asyncRunner.destroy();
|
||||
asyncRunner = null;
|
||||
});
|
||||
|
||||
tests.forEach(function (test) {
|
||||
function* gen() {
|
||||
do_print("Running " + test.name);
|
||||
yield test();
|
||||
yield reset();
|
||||
}
|
||||
asyncRunner.appendIterator(gen());
|
||||
});
|
||||
|
||||
// reset() ends up calling asyncRunner.next(), starting the tests.
|
||||
if (dontResetBefore) {
|
||||
next();
|
||||
} else {
|
||||
reset();
|
||||
}
|
||||
}
|
||||
|
||||
function makeCallback(callbacks, success = null) {
|
||||
callbacks = callbacks || {};
|
||||
if (!callbacks.handleError) {
|
||||
callbacks.handleError = function (error) {
|
||||
do_throw("handleError call was not expected, error: " + error);
|
||||
};
|
||||
}
|
||||
if (!callbacks.handleResult) {
|
||||
callbacks.handleResult = function() {
|
||||
do_throw("handleResult call was not expected");
|
||||
};
|
||||
}
|
||||
if (!callbacks.handleCompletion)
|
||||
callbacks.handleCompletion = function (reason) {
|
||||
equal(reason, Ci.nsIContentPrefCallback2.COMPLETE_OK);
|
||||
if (success) {
|
||||
success();
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
};
|
||||
return callbacks;
|
||||
}
|
||||
|
||||
function do_check_throws(fn) {
|
||||
let threw = false;
|
||||
try {
|
||||
fn();
|
||||
}
|
||||
catch (err) {
|
||||
threw = true;
|
||||
}
|
||||
ok(threw);
|
||||
}
|
||||
|
||||
function sendMessage(msg, callback) {
|
||||
let obj = callback || {};
|
||||
let ref = Cu.getWeakReference(obj);
|
||||
cps.QueryInterface(Ci.nsIObserver).observe(ref, "test:" + msg, null);
|
||||
return "value" in obj ? obj.value : undefined;
|
||||
}
|
||||
|
||||
function reset() {
|
||||
sendMessage("reset", next);
|
||||
}
|
||||
|
||||
function setWithDate(group, name, val, timestamp, context) {
|
||||
function updateDate() {
|
||||
let db = sendMessage("db");
|
||||
let stmt = db.createAsyncStatement(`
|
||||
UPDATE prefs SET timestamp = :timestamp
|
||||
WHERE
|
||||
settingID = (SELECT id FROM settings WHERE name = :name)
|
||||
AND groupID = (SELECT id FROM groups WHERE name = :group)
|
||||
`);
|
||||
stmt.params.timestamp = timestamp / 1000;
|
||||
stmt.params.name = name;
|
||||
stmt.params.group = group;
|
||||
|
||||
stmt.executeAsync({
|
||||
handleCompletion: function (reason) {
|
||||
next();
|
||||
},
|
||||
handleError: function (err) {
|
||||
do_throw(err);
|
||||
}
|
||||
});
|
||||
stmt.finalize();
|
||||
}
|
||||
|
||||
cps.set(group, name, val, context, makeCallback(null, updateDate));
|
||||
}
|
||||
|
||||
function getDate(group, name, context) {
|
||||
let db = sendMessage("db");
|
||||
let stmt = db.createAsyncStatement(`
|
||||
SELECT timestamp FROM prefs
|
||||
WHERE
|
||||
settingID = (SELECT id FROM settings WHERE name = :name)
|
||||
AND groupID = (SELECT id FROM groups WHERE name = :group)
|
||||
`);
|
||||
stmt.params.name = name;
|
||||
stmt.params.group = group;
|
||||
|
||||
let res;
|
||||
stmt.executeAsync({
|
||||
handleResult: function (results) {
|
||||
let row = results.getNextRow();
|
||||
res = row.getResultByName("timestamp");
|
||||
},
|
||||
handleCompletion: function (reason) {
|
||||
next(res * 1000);
|
||||
},
|
||||
handleError: function (err) {
|
||||
do_throw(err);
|
||||
}
|
||||
});
|
||||
stmt.finalize();
|
||||
}
|
||||
|
||||
function set(group, name, val, context) {
|
||||
cps.set(group, name, val, context, makeCallback());
|
||||
}
|
||||
|
||||
function setGlobal(name, val, context) {
|
||||
cps.setGlobal(name, val, context, makeCallback());
|
||||
}
|
||||
|
||||
function prefOK(actual, expected, strict) {
|
||||
ok(actual instanceof Ci.nsIContentPref);
|
||||
equal(actual.domain, expected.domain);
|
||||
equal(actual.name, expected.name);
|
||||
if (strict)
|
||||
strictEqual(actual.value, expected.value);
|
||||
else
|
||||
equal(actual.value, expected.value);
|
||||
}
|
||||
|
||||
function* getOK(args, expectedVal, expectedGroup, strict) {
|
||||
if (args.length == 2)
|
||||
args.push(undefined);
|
||||
let expectedPrefs = expectedVal === undefined ? [] :
|
||||
[{ domain: expectedGroup || args[0],
|
||||
name: args[1],
|
||||
value: expectedVal }];
|
||||
yield getOKEx("getByDomainAndName", args, expectedPrefs, strict);
|
||||
}
|
||||
|
||||
function* getSubdomainsOK(args, expectedGroupValPairs) {
|
||||
if (args.length == 2)
|
||||
args.push(undefined);
|
||||
let expectedPrefs = expectedGroupValPairs.map(function ([group, val]) {
|
||||
return { domain: group, name: args[1], value: val };
|
||||
});
|
||||
yield getOKEx("getBySubdomainAndName", args, expectedPrefs);
|
||||
}
|
||||
|
||||
function* getGlobalOK(args, expectedVal) {
|
||||
if (args.length == 1)
|
||||
args.push(undefined);
|
||||
let expectedPrefs = expectedVal === undefined ? [] :
|
||||
[{ domain: null, name: args[0], value: expectedVal }];
|
||||
yield getOKEx("getGlobal", args, expectedPrefs);
|
||||
}
|
||||
|
||||
function* getOKEx(methodName, args, expectedPrefs, strict, context) {
|
||||
let actualPrefs = [];
|
||||
args.push(makeCallback({
|
||||
handleResult: pref => actualPrefs.push(pref)
|
||||
}));
|
||||
yield cps[methodName].apply(cps, args);
|
||||
arraysOfArraysOK([actualPrefs], [expectedPrefs], function (actual, expected) {
|
||||
prefOK(actual, expected, strict);
|
||||
});
|
||||
}
|
||||
|
||||
function getCachedOK(args, expectedIsCached, expectedVal, expectedGroup,
|
||||
strict) {
|
||||
if (args.length == 2)
|
||||
args.push(undefined);
|
||||
let expectedPref = !expectedIsCached ? null : {
|
||||
domain: expectedGroup || args[0],
|
||||
name: args[1],
|
||||
value: expectedVal
|
||||
};
|
||||
getCachedOKEx("getCachedByDomainAndName", args, expectedPref, strict);
|
||||
}
|
||||
|
||||
function getCachedSubdomainsOK(args, expectedGroupValPairs) {
|
||||
if (args.length == 2)
|
||||
args.push(undefined);
|
||||
let len = {};
|
||||
args.push(len);
|
||||
let actualPrefs = cps.getCachedBySubdomainAndName.apply(cps, args);
|
||||
actualPrefs = actualPrefs.sort(function (a, b) {
|
||||
return a.domain.localeCompare(b.domain);
|
||||
});
|
||||
equal(actualPrefs.length, len.value);
|
||||
let expectedPrefs = expectedGroupValPairs.map(function ([group, val]) {
|
||||
return { domain: group, name: args[1], value: val };
|
||||
});
|
||||
arraysOfArraysOK([actualPrefs], [expectedPrefs], prefOK);
|
||||
}
|
||||
|
||||
function getCachedGlobalOK(args, expectedIsCached, expectedVal) {
|
||||
if (args.length == 1)
|
||||
args.push(undefined);
|
||||
let expectedPref = !expectedIsCached ? null : {
|
||||
domain: null,
|
||||
name: args[0],
|
||||
value: expectedVal
|
||||
};
|
||||
getCachedOKEx("getCachedGlobal", args, expectedPref);
|
||||
}
|
||||
|
||||
function getCachedOKEx(methodName, args, expectedPref, strict) {
|
||||
let actualPref = cps[methodName].apply(cps, args);
|
||||
if (expectedPref)
|
||||
prefOK(actualPref, expectedPref, strict);
|
||||
else
|
||||
strictEqual(actualPref, null);
|
||||
}
|
||||
|
||||
function arraysOK(actual, expected, cmp) {
|
||||
if (actual.length != expected.length) {
|
||||
do_throw("Length is not equal: " + JSON.stringify(actual) + "==" + JSON.stringify(expected));
|
||||
} else {
|
||||
actual.forEach(function (actualElt, j) {
|
||||
let expectedElt = expected[j];
|
||||
cmp(actualElt, expectedElt);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function arraysOfArraysOK(actual, expected, cmp) {
|
||||
cmp = cmp || equal;
|
||||
arraysOK(actual, expected, function (act, exp) {
|
||||
arraysOK(act, exp, cmp)
|
||||
});
|
||||
}
|
||||
|
||||
function dbOK(expectedRows) {
|
||||
let db = sendMessage("db");
|
||||
let stmt = db.createAsyncStatement(`
|
||||
SELECT groups.name AS grp, settings.name AS name, prefs.value AS value
|
||||
FROM prefs
|
||||
LEFT JOIN groups ON groups.id = prefs.groupID
|
||||
LEFT JOIN settings ON settings.id = prefs.settingID
|
||||
UNION
|
||||
|
||||
/*
|
||||
These second two SELECTs get the rows of the groups and settings tables
|
||||
that aren't referenced by the prefs table. Neither should return any
|
||||
rows if the component is working properly.
|
||||
*/
|
||||
SELECT groups.name AS grp, NULL AS name, NULL AS value
|
||||
FROM groups
|
||||
WHERE id NOT IN (
|
||||
SELECT DISTINCT groupID
|
||||
FROM prefs
|
||||
WHERE groupID NOTNULL
|
||||
)
|
||||
UNION
|
||||
SELECT NULL AS grp, settings.name AS name, NULL AS value
|
||||
FROM settings
|
||||
WHERE id NOT IN (
|
||||
SELECT DISTINCT settingID
|
||||
FROM prefs
|
||||
WHERE settingID NOTNULL
|
||||
)
|
||||
|
||||
ORDER BY value ASC, grp ASC, name ASC
|
||||
`);
|
||||
|
||||
let actualRows = [];
|
||||
let cols = ["grp", "name", "value"];
|
||||
|
||||
db.executeAsync([stmt], 1, {
|
||||
handleCompletion: function (reason) {
|
||||
arraysOfArraysOK(actualRows, expectedRows);
|
||||
next();
|
||||
},
|
||||
handleResult: function (results) {
|
||||
let row = null;
|
||||
while (row = results.getNextRow()) {
|
||||
actualRows.push(cols.map(c => row.getResultByName(c)));
|
||||
}
|
||||
},
|
||||
handleError: function (err) {
|
||||
do_throw(err);
|
||||
}
|
||||
});
|
||||
stmt.finalize();
|
||||
}
|
||||
|
||||
function on(event, names, dontRemove) {
|
||||
let args = {
|
||||
reset: function () {
|
||||
for (let prop in this) {
|
||||
if (Array.isArray(this[prop]))
|
||||
this[prop].splice(0, this[prop].length);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
let observers = {};
|
||||
|
||||
names.forEach(function (name) {
|
||||
let obs = {};
|
||||
["onContentPrefSet", "onContentPrefRemoved"].forEach(function (meth) {
|
||||
obs[meth] = () => do_throw(meth + " should not be called");
|
||||
});
|
||||
obs["onContentPref" + event] = function () {
|
||||
args[name].push(Array.slice(arguments));
|
||||
};
|
||||
observers[name] = obs;
|
||||
args[name] = [];
|
||||
args[name].observer = obs;
|
||||
cps.addObserverForName(name, obs);
|
||||
});
|
||||
|
||||
do_execute_soon(function () {
|
||||
if (!dontRemove)
|
||||
names.forEach(n => cps.removeObserverForName(n, observers[n]));
|
||||
next(args);
|
||||
});
|
||||
}
|
||||
|
||||
function schemaVersionIs(expectedVersion) {
|
||||
let db = sendMessage("db");
|
||||
equal(db.schemaVersion, expectedVersion);
|
||||
}
|
||||
|
||||
function wait() {
|
||||
do_execute_soon(next);
|
||||
}
|
||||
|
||||
function observerArgsOK(actualArgs, expectedArgs) {
|
||||
notEqual(actualArgs, undefined);
|
||||
arraysOfArraysOK(actualArgs, expectedArgs);
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
function run_test() {
|
||||
let tests = {
|
||||
"http://example.com": "example.com",
|
||||
"http://example.com/": "example.com",
|
||||
"http://example.com/foo/bar/baz": "example.com",
|
||||
"http://subdomain.example.com/foo/bar/baz": "subdomain.example.com",
|
||||
"http://qix.quux.example.com/foo/bar/baz": "qix.quux.example.com",
|
||||
"file:///home/foo/bar": "file:///home/foo/bar",
|
||||
"not a url": "not a url",
|
||||
};
|
||||
let cps = Cc["@mozilla.org/content-pref/service;1"].
|
||||
getService(Ci.nsIContentPrefService2);
|
||||
for (let url in tests) {
|
||||
do_check_eq(cps.extractDomain(url), tests[url]);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
function run_test() {
|
||||
runAsyncTests(tests);
|
||||
}
|
||||
|
||||
var tests = [
|
||||
|
||||
function* nonexistent() {
|
||||
getCachedOK(["a.com", "foo"], false, undefined);
|
||||
getCachedGlobalOK(["foo"], false, undefined);
|
||||
yield true;
|
||||
},
|
||||
|
||||
function* isomorphicDomains() {
|
||||
yield set("a.com", "foo", 1);
|
||||
getCachedOK(["a.com", "foo"], true, 1);
|
||||
getCachedOK(["http://a.com/huh", "foo"], true, 1, "a.com");
|
||||
},
|
||||
|
||||
function* names() {
|
||||
yield set("a.com", "foo", 1);
|
||||
getCachedOK(["a.com", "foo"], true, 1);
|
||||
|
||||
yield set("a.com", "bar", 2);
|
||||
getCachedOK(["a.com", "foo"], true, 1);
|
||||
getCachedOK(["a.com", "bar"], true, 2);
|
||||
|
||||
yield setGlobal("foo", 3);
|
||||
getCachedOK(["a.com", "foo"], true, 1);
|
||||
getCachedOK(["a.com", "bar"], true, 2);
|
||||
getCachedGlobalOK(["foo"], true, 3);
|
||||
|
||||
yield setGlobal("bar", 4);
|
||||
getCachedOK(["a.com", "foo"], true, 1);
|
||||
getCachedOK(["a.com", "bar"], true, 2);
|
||||
getCachedGlobalOK(["foo"], true, 3);
|
||||
getCachedGlobalOK(["bar"], true, 4);
|
||||
},
|
||||
|
||||
function* subdomains() {
|
||||
yield set("a.com", "foo", 1);
|
||||
yield set("b.a.com", "foo", 2);
|
||||
getCachedOK(["a.com", "foo"], true, 1);
|
||||
getCachedOK(["b.a.com", "foo"], true, 2);
|
||||
},
|
||||
|
||||
function* privateBrowsing() {
|
||||
yield set("a.com", "foo", 1);
|
||||
yield set("a.com", "bar", 2);
|
||||
yield setGlobal("foo", 3);
|
||||
yield setGlobal("bar", 4);
|
||||
yield set("b.com", "foo", 5);
|
||||
|
||||
let context = { usePrivateBrowsing: true };
|
||||
yield set("a.com", "foo", 6, context);
|
||||
yield setGlobal("foo", 7, context);
|
||||
getCachedOK(["a.com", "foo", context], true, 6);
|
||||
getCachedOK(["a.com", "bar", context], true, 2);
|
||||
getCachedGlobalOK(["foo", context], true, 7);
|
||||
getCachedGlobalOK(["bar", context], true, 4);
|
||||
getCachedOK(["b.com", "foo", context], true, 5);
|
||||
|
||||
getCachedOK(["a.com", "foo"], true, 1);
|
||||
getCachedOK(["a.com", "bar"], true, 2);
|
||||
getCachedGlobalOK(["foo"], true, 3);
|
||||
getCachedGlobalOK(["bar"], true, 4);
|
||||
getCachedOK(["b.com", "foo"], true, 5);
|
||||
},
|
||||
|
||||
function* erroneous() {
|
||||
do_check_throws(() => cps.getCachedByDomainAndName(null, "foo", null));
|
||||
do_check_throws(() => cps.getCachedByDomainAndName("", "foo", null));
|
||||
do_check_throws(() => cps.getCachedByDomainAndName("a.com", "", null));
|
||||
do_check_throws(() => cps.getCachedByDomainAndName("a.com", null, null));
|
||||
do_check_throws(() => cps.getCachedGlobal("", null));
|
||||
do_check_throws(() => cps.getCachedGlobal(null, null));
|
||||
yield true;
|
||||
},
|
||||
|
||||
function* casts() {
|
||||
// SQLite casts booleans to integers. This makes sure the values stored in
|
||||
// the cache are the same as the casted values in the database.
|
||||
|
||||
yield set("a.com", "foo", false);
|
||||
yield getOK(["a.com", "foo"], 0, "a.com", true);
|
||||
getCachedOK(["a.com", "foo"], true, 0, "a.com", true);
|
||||
|
||||
yield set("a.com", "bar", true);
|
||||
yield getOK(["a.com", "bar"], 1, "a.com", true);
|
||||
getCachedOK(["a.com", "bar"], true, 1, "a.com", true);
|
||||
},
|
||||
];
|
||||
|
|
@ -0,0 +1,186 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
function run_test() {
|
||||
runAsyncTests(tests);
|
||||
}
|
||||
|
||||
var tests = [
|
||||
|
||||
function* nonexistent() {
|
||||
getCachedSubdomainsOK(["a.com", "foo"], []);
|
||||
yield true;
|
||||
},
|
||||
|
||||
function* isomorphicDomains() {
|
||||
yield set("a.com", "foo", 1);
|
||||
getCachedSubdomainsOK(["a.com", "foo"], [["a.com", 1]]);
|
||||
getCachedSubdomainsOK(["http://a.com/huh", "foo"], [["a.com", 1]]);
|
||||
},
|
||||
|
||||
function* names() {
|
||||
yield set("a.com", "foo", 1);
|
||||
getCachedSubdomainsOK(["a.com", "foo"], [["a.com", 1]]);
|
||||
|
||||
yield set("a.com", "bar", 2);
|
||||
getCachedSubdomainsOK(["a.com", "foo"], [["a.com", 1]]);
|
||||
getCachedSubdomainsOK(["a.com", "bar"], [["a.com", 2]]);
|
||||
|
||||
yield setGlobal("foo", 3);
|
||||
getCachedSubdomainsOK(["a.com", "foo"], [["a.com", 1]]);
|
||||
getCachedSubdomainsOK(["a.com", "bar"], [["a.com", 2]]);
|
||||
getCachedGlobalOK(["foo"], true, 3);
|
||||
|
||||
yield setGlobal("bar", 4);
|
||||
getCachedSubdomainsOK(["a.com", "foo"], [["a.com", 1]]);
|
||||
getCachedSubdomainsOK(["a.com", "bar"], [["a.com", 2]]);
|
||||
getCachedGlobalOK(["foo"], true, 3);
|
||||
getCachedGlobalOK(["bar"], true, 4);
|
||||
},
|
||||
|
||||
function* subdomains() {
|
||||
yield set("a.com", "foo", 1);
|
||||
yield set("b.a.com", "foo", 2);
|
||||
getCachedSubdomainsOK(["a.com", "foo"], [["a.com", 1], ["b.a.com", 2]]);
|
||||
getCachedSubdomainsOK(["b.a.com", "foo"], [["b.a.com", 2]]);
|
||||
},
|
||||
|
||||
function* populateViaGet() {
|
||||
yield cps.getByDomainAndName("a.com", "foo", null, makeCallback());
|
||||
getCachedSubdomainsOK(["a.com", "foo"], [["a.com", undefined]]);
|
||||
|
||||
yield cps.getGlobal("foo", null, makeCallback());
|
||||
getCachedSubdomainsOK(["a.com", "foo"], [["a.com", undefined]]);
|
||||
getCachedGlobalOK(["foo"], true, undefined);
|
||||
},
|
||||
|
||||
function* populateViaGetSubdomains() {
|
||||
yield cps.getBySubdomainAndName("a.com", "foo", null, makeCallback());
|
||||
getCachedSubdomainsOK(["a.com", "foo"], [["a.com", undefined]]);
|
||||
},
|
||||
|
||||
function* populateViaRemove() {
|
||||
yield cps.removeByDomainAndName("a.com", "foo", null, makeCallback());
|
||||
getCachedSubdomainsOK(["a.com", "foo"], [["a.com", undefined]]);
|
||||
|
||||
yield cps.removeBySubdomainAndName("b.com", "foo", null, makeCallback());
|
||||
getCachedSubdomainsOK(["a.com", "foo"], [["a.com", undefined]]);
|
||||
getCachedSubdomainsOK(["b.com", "foo"], [["b.com", undefined]]);
|
||||
|
||||
yield cps.removeGlobal("foo", null, makeCallback());
|
||||
getCachedSubdomainsOK(["a.com", "foo"], [["a.com", undefined]]);
|
||||
getCachedSubdomainsOK(["b.com", "foo"], [["b.com", undefined]]);
|
||||
getCachedGlobalOK(["foo"], true, undefined);
|
||||
|
||||
yield set("a.com", "foo", 1);
|
||||
yield cps.removeByDomainAndName("a.com", "foo", null, makeCallback());
|
||||
getCachedSubdomainsOK(["a.com", "foo"], [["a.com", undefined]]);
|
||||
getCachedSubdomainsOK(["b.com", "foo"], [["b.com", undefined]]);
|
||||
getCachedGlobalOK(["foo"], true, undefined);
|
||||
|
||||
yield set("a.com", "foo", 2);
|
||||
yield set("b.a.com", "foo", 3);
|
||||
yield cps.removeBySubdomainAndName("a.com", "foo", null, makeCallback());
|
||||
getCachedSubdomainsOK(["a.com", "foo"],
|
||||
[["a.com", undefined], ["b.a.com", undefined]]);
|
||||
getCachedSubdomainsOK(["b.com", "foo"], [["b.com", undefined]]);
|
||||
getCachedGlobalOK(["foo"], true, undefined);
|
||||
getCachedSubdomainsOK(["b.a.com", "foo"], [["b.a.com", undefined]]);
|
||||
|
||||
yield setGlobal("foo", 4);
|
||||
yield cps.removeGlobal("foo", null, makeCallback());
|
||||
getCachedSubdomainsOK(["a.com", "foo"],
|
||||
[["a.com", undefined], ["b.a.com", undefined]]);
|
||||
getCachedSubdomainsOK(["b.com", "foo"], [["b.com", undefined]]);
|
||||
getCachedGlobalOK(["foo"], true, undefined);
|
||||
getCachedSubdomainsOK(["b.a.com", "foo"], [["b.a.com", undefined]]);
|
||||
},
|
||||
|
||||
function* populateViaRemoveByDomain() {
|
||||
yield set("a.com", "foo", 1);
|
||||
yield set("a.com", "bar", 2);
|
||||
yield set("b.a.com", "foo", 3);
|
||||
yield set("b.a.com", "bar", 4);
|
||||
yield cps.removeByDomain("a.com", null, makeCallback());
|
||||
getCachedSubdomainsOK(["a.com", "foo"],
|
||||
[["a.com", undefined], ["b.a.com", 3]]);
|
||||
getCachedSubdomainsOK(["a.com", "bar"],
|
||||
[["a.com", undefined], ["b.a.com", 4]]);
|
||||
|
||||
yield set("a.com", "foo", 5);
|
||||
yield set("a.com", "bar", 6);
|
||||
yield cps.removeBySubdomain("a.com", null, makeCallback());
|
||||
getCachedSubdomainsOK(["a.com", "foo"],
|
||||
[["a.com", undefined], ["b.a.com", undefined]]);
|
||||
getCachedSubdomainsOK(["a.com", "bar"],
|
||||
[["a.com", undefined], ["b.a.com", undefined]]);
|
||||
|
||||
yield setGlobal("foo", 7);
|
||||
yield setGlobal("bar", 8);
|
||||
yield cps.removeAllGlobals(null, makeCallback());
|
||||
getCachedGlobalOK(["foo"], true, undefined);
|
||||
getCachedGlobalOK(["bar"], true, undefined);
|
||||
},
|
||||
|
||||
function* populateViaRemoveAllDomains() {
|
||||
yield set("a.com", "foo", 1);
|
||||
yield set("a.com", "bar", 2);
|
||||
yield set("b.com", "foo", 3);
|
||||
yield set("b.com", "bar", 4);
|
||||
yield cps.removeAllDomains(null, makeCallback());
|
||||
getCachedSubdomainsOK(["a.com", "foo"], [["a.com", undefined]]);
|
||||
getCachedSubdomainsOK(["a.com", "bar"], [["a.com", undefined]]);
|
||||
getCachedSubdomainsOK(["b.com", "foo"], [["b.com", undefined]]);
|
||||
getCachedSubdomainsOK(["b.com", "bar"], [["b.com", undefined]]);
|
||||
},
|
||||
|
||||
function* populateViaRemoveByName() {
|
||||
yield set("a.com", "foo", 1);
|
||||
yield set("a.com", "bar", 2);
|
||||
yield setGlobal("foo", 3);
|
||||
yield setGlobal("bar", 4);
|
||||
yield cps.removeByName("foo", null, makeCallback());
|
||||
getCachedSubdomainsOK(["a.com", "foo"], [["a.com", undefined]]);
|
||||
getCachedSubdomainsOK(["a.com", "bar"], [["a.com", 2]]);
|
||||
getCachedGlobalOK(["foo"], true, undefined);
|
||||
getCachedGlobalOK(["bar"], true, 4);
|
||||
|
||||
yield cps.removeByName("bar", null, makeCallback());
|
||||
getCachedSubdomainsOK(["a.com", "foo"], [["a.com", undefined]]);
|
||||
getCachedSubdomainsOK(["a.com", "bar"], [["a.com", undefined]]);
|
||||
getCachedGlobalOK(["foo"], true, undefined);
|
||||
getCachedGlobalOK(["bar"], true, undefined);
|
||||
},
|
||||
|
||||
function* privateBrowsing() {
|
||||
yield set("a.com", "foo", 1);
|
||||
yield set("a.com", "bar", 2);
|
||||
yield setGlobal("foo", 3);
|
||||
yield setGlobal("bar", 4);
|
||||
yield set("b.com", "foo", 5);
|
||||
|
||||
let context = { usePrivateBrowsing: true };
|
||||
yield set("a.com", "foo", 6, context);
|
||||
yield setGlobal("foo", 7, context);
|
||||
getCachedSubdomainsOK(["a.com", "foo", context], [["a.com", 6]]);
|
||||
getCachedSubdomainsOK(["a.com", "bar", context], [["a.com", 2]]);
|
||||
getCachedGlobalOK(["foo", context], true, 7);
|
||||
getCachedGlobalOK(["bar", context], true, 4);
|
||||
getCachedSubdomainsOK(["b.com", "foo", context], [["b.com", 5]]);
|
||||
|
||||
getCachedSubdomainsOK(["a.com", "foo"], [["a.com", 1]]);
|
||||
getCachedSubdomainsOK(["a.com", "bar"], [["a.com", 2]]);
|
||||
getCachedGlobalOK(["foo"], true, 3);
|
||||
getCachedGlobalOK(["bar"], true, 4);
|
||||
getCachedSubdomainsOK(["b.com", "foo"], [["b.com", 5]]);
|
||||
},
|
||||
|
||||
function* erroneous() {
|
||||
do_check_throws(() => cps.getCachedBySubdomainAndName(null, "foo", null));
|
||||
do_check_throws(() => cps.getCachedBySubdomainAndName("", "foo", null));
|
||||
do_check_throws(() => cps.getCachedBySubdomainAndName("a.com", "", null));
|
||||
do_check_throws(() => cps.getCachedBySubdomainAndName("a.com", null, null));
|
||||
yield true;
|
||||
},
|
||||
];
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
function run_test() {
|
||||
runAsyncTests(tests);
|
||||
}
|
||||
|
||||
var tests = [
|
||||
|
||||
function* get_nonexistent() {
|
||||
yield getSubdomainsOK(["a.com", "foo"], []);
|
||||
},
|
||||
|
||||
function* isomorphicDomains() {
|
||||
yield set("a.com", "foo", 1);
|
||||
yield getSubdomainsOK(["a.com", "foo"], [["a.com", 1]]);
|
||||
yield getSubdomainsOK(["http://a.com/huh", "foo"], [["a.com", 1]]);
|
||||
},
|
||||
|
||||
function* names() {
|
||||
yield set("a.com", "foo", 1);
|
||||
yield getSubdomainsOK(["a.com", "foo"], [["a.com", 1]]);
|
||||
|
||||
yield set("a.com", "bar", 2);
|
||||
yield getSubdomainsOK(["a.com", "foo"], [["a.com", 1]]);
|
||||
yield getSubdomainsOK(["a.com", "bar"], [["a.com", 2]]);
|
||||
|
||||
yield setGlobal("foo", 3);
|
||||
yield getSubdomainsOK(["a.com", "foo"], [["a.com", 1]]);
|
||||
yield getSubdomainsOK(["a.com", "bar"], [["a.com", 2]]);
|
||||
},
|
||||
|
||||
function* subdomains() {
|
||||
yield set("a.com", "foo", 1);
|
||||
yield set("b.a.com", "foo", 2);
|
||||
yield getSubdomainsOK(["a.com", "foo"], [["a.com", 1], ["b.a.com", 2]]);
|
||||
yield getSubdomainsOK(["b.a.com", "foo"], [["b.a.com", 2]]);
|
||||
},
|
||||
|
||||
function* privateBrowsing() {
|
||||
yield set("a.com", "foo", 1);
|
||||
yield set("a.com", "bar", 2);
|
||||
yield setGlobal("foo", 3);
|
||||
yield setGlobal("bar", 4);
|
||||
yield set("b.com", "foo", 5);
|
||||
|
||||
let context = { usePrivateBrowsing: true };
|
||||
yield set("a.com", "foo", 6, context);
|
||||
yield setGlobal("foo", 7, context);
|
||||
yield getSubdomainsOK(["a.com", "foo", context], [["a.com", 6]]);
|
||||
yield getSubdomainsOK(["a.com", "bar", context], [["a.com", 2]]);
|
||||
yield getSubdomainsOK(["b.com", "foo", context], [["b.com", 5]]);
|
||||
|
||||
yield getSubdomainsOK(["a.com", "foo"], [["a.com", 1]]);
|
||||
yield getSubdomainsOK(["a.com", "bar"], [["a.com", 2]]);
|
||||
yield getSubdomainsOK(["b.com", "foo"], [["b.com", 5]]);
|
||||
},
|
||||
|
||||
function* erroneous() {
|
||||
do_check_throws(() => cps.getBySubdomainAndName(null, "foo", null, {}));
|
||||
do_check_throws(() => cps.getBySubdomainAndName("", "foo", null, {}));
|
||||
do_check_throws(() => cps.getBySubdomainAndName("a.com", "", null, {}));
|
||||
do_check_throws(() => cps.getBySubdomainAndName("a.com", null, null, {}));
|
||||
do_check_throws(() => cps.getBySubdomainAndName("a.com", "foo", null, null));
|
||||
yield true;
|
||||
},
|
||||
];
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// Dump of version we migrate from
|
||||
var schema_version3 = `
|
||||
PRAGMA foreign_keys=OFF;
|
||||
BEGIN TRANSACTION;
|
||||
CREATE TABLE groups (id INTEGER PRIMARY KEY, name TEXT NOT NULL);
|
||||
INSERT INTO "groups" VALUES(1,'foo.com');
|
||||
INSERT INTO "groups" VALUES(2,'bar.com');
|
||||
|
||||
CREATE TABLE settings (id INTEGER PRIMARY KEY, name TEXT NOT NULL);
|
||||
INSERT INTO "settings" VALUES(1,'zoom-setting');
|
||||
INSERT INTO "settings" VALUES(2,'dir-setting');
|
||||
|
||||
CREATE TABLE prefs (id INTEGER PRIMARY KEY, groupID INTEGER REFERENCES groups(id), settingID INTEGER NOT NULL REFERENCES settings(id), value BLOB);
|
||||
INSERT INTO "prefs" VALUES(1,1,1,0.5);
|
||||
INSERT INTO "prefs" VALUES(2,1,2,'/download/dir');
|
||||
INSERT INTO "prefs" VALUES(3,2,1,0.3);
|
||||
INSERT INTO "prefs" VALUES(4,NULL,1,0.1);
|
||||
|
||||
CREATE INDEX groups_idx ON groups(name);
|
||||
CREATE INDEX settings_idx ON settings(name);
|
||||
CREATE INDEX prefs_idx ON prefs(groupID, settingID);
|
||||
COMMIT;`;
|
||||
|
||||
function prepareVersion3Schema(callback) {
|
||||
var dirService = Cc["@mozilla.org/file/directory_service;1"].
|
||||
getService(Ci.nsIProperties);
|
||||
|
||||
var dbFile = dirService.get("ProfD", Ci.nsIFile);
|
||||
dbFile.append("content-prefs.sqlite");
|
||||
|
||||
var dbService = Cc["@mozilla.org/storage/service;1"].
|
||||
getService(Ci.mozIStorageService);
|
||||
ok(!dbFile.exists(), "Db should not exist yet.");
|
||||
|
||||
var dbConnection = dbService.openDatabase(dbFile);
|
||||
equal(dbConnection.schemaVersion, 0);
|
||||
|
||||
dbConnection.executeSimpleSQL(schema_version3);
|
||||
dbConnection.schemaVersion = 3;
|
||||
|
||||
dbConnection.close();
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
prepareVersion3Schema();
|
||||
runAsyncTests(tests, true);
|
||||
}
|
||||
|
||||
|
||||
// WARNING: Database will reset after every test. This limitation comes from
|
||||
// the fact that we ContentPrefService constructor is run only once per test file
|
||||
// and so migration will be run only once.
|
||||
var tests = [
|
||||
function* testMigration() {
|
||||
// Test migrated db content.
|
||||
schemaVersionIs(4);
|
||||
let dbExpectedState = [
|
||||
[null, "zoom-setting", 0.1],
|
||||
["bar.com", "zoom-setting", 0.3],
|
||||
["foo.com", "zoom-setting", 0.5],
|
||||
["foo.com", "dir-setting", "/download/dir"],
|
||||
];
|
||||
yield dbOK(dbExpectedState);
|
||||
|
||||
// Migrated fields should have timestamp set to 0.
|
||||
yield cps.removeAllDomainsSince(1000, null, makeCallback());
|
||||
yield dbOK(dbExpectedState);
|
||||
|
||||
yield cps.removeAllDomainsSince(0, null, makeCallback());
|
||||
yield dbOK([[null, "zoom-setting", 0.1]]);
|
||||
|
||||
// Test that dates are present after migration (column is added).
|
||||
const timestamp = 1234;
|
||||
yield setWithDate("a.com", "pref-name", "val", timestamp);
|
||||
let actualTimestamp = yield getDate("a.com", "pref-name");
|
||||
equal(actualTimestamp, timestamp);
|
||||
}
|
||||
];
|
||||
|
|
@ -0,0 +1,178 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
let global = this;
|
||||
|
||||
function run_test() {
|
||||
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(context) {
|
||||
yield set("a.com", "foo", 1, context);
|
||||
let args = yield on("Set", ["foo", null, "bar"]);
|
||||
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, context);
|
||||
args = yield on("Set", ["foo", null, "bar"]);
|
||||
observerArgsOK(args.foo, [[null, "foo", 2, context.usePrivateBrowsing]]);
|
||||
observerArgsOK(args.null, [[null, "foo", 2, context.usePrivateBrowsing]]);
|
||||
observerArgsOK(args.bar, []);
|
||||
},
|
||||
|
||||
function* observerForName_remove(context) {
|
||||
yield set("a.com", "foo", 1, context);
|
||||
yield setGlobal("foo", 2, context);
|
||||
|
||||
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", context, makeCallback());
|
||||
args = yield on("Removed", ["foo", null, "bar"]);
|
||||
observerArgsOK(args.foo, [["a.com", "foo", context.usePrivateBrowsing]]);
|
||||
observerArgsOK(args.null, [["a.com", "foo", context.usePrivateBrowsing]]);
|
||||
observerArgsOK(args.bar, []);
|
||||
|
||||
yield cps.removeGlobal("foo", context, makeCallback());
|
||||
args = yield on("Removed", ["foo", null, "bar"]);
|
||||
observerArgsOK(args.foo, [[null, "foo", context.usePrivateBrowsing]]);
|
||||
observerArgsOK(args.null, [[null, "foo", context.usePrivateBrowsing]]);
|
||||
observerArgsOK(args.bar, []);
|
||||
},
|
||||
|
||||
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", context, makeCallback());
|
||||
let args = yield on("Removed", ["foo", null, "bar"]);
|
||||
observerArgsOK(args.foo, []);
|
||||
observerArgsOK(args.null, []);
|
||||
observerArgsOK(args.bar, []);
|
||||
|
||||
yield cps.removeBySubdomain("a.com", context, makeCallback());
|
||||
args = yield on("Removed", ["foo", null, "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(context, makeCallback());
|
||||
args = yield on("Removed", ["foo", null, "bar"]);
|
||||
observerArgsOK(args.foo, [[null, "foo", context.usePrivateBrowsing]]);
|
||||
observerArgsOK(args.null, [[null, "foo", context.usePrivateBrowsing]]);
|
||||
observerArgsOK(args.bar, []);
|
||||
},
|
||||
|
||||
function* observerForName_removeAllDomains(context) {
|
||||
yield set("a.com", "foo", 1, context);
|
||||
yield setGlobal("foo", 2, context);
|
||||
yield set("b.com", "bar", 3, context);
|
||||
|
||||
yield cps.removeAllDomains(context, makeCallback());
|
||||
let args = yield on("Removed", ["foo", null, "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(context) {
|
||||
yield set("a.com", "foo", 1, context);
|
||||
yield set("a.com", "bar", 2, context);
|
||||
yield setGlobal("foo", 3, context);
|
||||
|
||||
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", context, makeCallback());
|
||||
args = yield on("Removed", ["foo", null, "bar"]);
|
||||
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(context) {
|
||||
let args = yield on("Set", ["foo", null, "bar"], true);
|
||||
|
||||
cps.removeObserverForName("foo", args.foo.observer);
|
||||
yield set("a.com", "foo", 1, context);
|
||||
yield wait();
|
||||
observerArgsOK(args.foo, []);
|
||||
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, context);
|
||||
yield wait();
|
||||
observerArgsOK(args.foo, []);
|
||||
observerArgsOK(args.null, []);
|
||||
observerArgsOK(args.bar, []);
|
||||
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]]);
|
||||
},
|
||||
];
|
||||
222
toolkit/components/contentprefs/tests/unit_cps2/test_remove.js
Normal file
222
toolkit/components/contentprefs/tests/unit_cps2/test_remove.js
Normal file
|
|
@ -0,0 +1,222 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
function run_test() {
|
||||
runAsyncTests(tests);
|
||||
}
|
||||
|
||||
var tests = [
|
||||
|
||||
function* nonexistent() {
|
||||
yield set("a.com", "foo", 1);
|
||||
yield setGlobal("foo", 2);
|
||||
|
||||
yield cps.removeByDomainAndName("a.com", "bogus", null, makeCallback());
|
||||
yield dbOK([
|
||||
["a.com", "foo", 1],
|
||||
[null, "foo", 2],
|
||||
]);
|
||||
yield getOK(["a.com", "foo"], 1);
|
||||
yield getGlobalOK(["foo"], 2);
|
||||
|
||||
yield cps.removeBySubdomainAndName("a.com", "bogus", null, makeCallback());
|
||||
yield dbOK([
|
||||
["a.com", "foo", 1],
|
||||
[null, "foo", 2],
|
||||
]);
|
||||
yield getOK(["a.com", "foo"], 1);
|
||||
yield getGlobalOK(["foo"], 2);
|
||||
|
||||
yield cps.removeGlobal("bogus", null, makeCallback());
|
||||
yield dbOK([
|
||||
["a.com", "foo", 1],
|
||||
[null, "foo", 2],
|
||||
]);
|
||||
yield getOK(["a.com", "foo"], 1);
|
||||
yield getGlobalOK(["foo"], 2);
|
||||
|
||||
yield cps.removeByDomainAndName("bogus", "bogus", null, makeCallback());
|
||||
yield dbOK([
|
||||
["a.com", "foo", 1],
|
||||
[null, "foo", 2],
|
||||
]);
|
||||
yield getOK(["a.com", "foo"], 1);
|
||||
yield getGlobalOK(["foo"], 2);
|
||||
},
|
||||
|
||||
function* isomorphicDomains() {
|
||||
yield set("a.com", "foo", 1);
|
||||
yield cps.removeByDomainAndName("a.com", "foo", null, makeCallback());
|
||||
yield dbOK([]);
|
||||
yield getOK(["a.com", "foo"], undefined);
|
||||
|
||||
yield set("a.com", "foo", 2);
|
||||
yield cps.removeByDomainAndName("http://a.com/huh", "foo", null,
|
||||
makeCallback());
|
||||
yield dbOK([]);
|
||||
yield getOK(["a.com", "foo"], undefined);
|
||||
},
|
||||
|
||||
function* names() {
|
||||
yield set("a.com", "foo", 1);
|
||||
yield set("a.com", "bar", 2);
|
||||
yield setGlobal("foo", 3);
|
||||
yield setGlobal("bar", 4);
|
||||
|
||||
yield cps.removeByDomainAndName("a.com", "foo", null, makeCallback());
|
||||
yield dbOK([
|
||||
["a.com", "bar", 2],
|
||||
[null, "foo", 3],
|
||||
[null, "bar", 4],
|
||||
]);
|
||||
yield getOK(["a.com", "foo"], undefined);
|
||||
yield getOK(["a.com", "bar"], 2);
|
||||
yield getGlobalOK(["foo"], 3);
|
||||
yield getGlobalOK(["bar"], 4);
|
||||
|
||||
yield cps.removeGlobal("foo", null, makeCallback());
|
||||
yield dbOK([
|
||||
["a.com", "bar", 2],
|
||||
[null, "bar", 4],
|
||||
]);
|
||||
yield getOK(["a.com", "foo"], undefined);
|
||||
yield getOK(["a.com", "bar"], 2);
|
||||
yield getGlobalOK(["foo"], undefined);
|
||||
yield getGlobalOK(["bar"], 4);
|
||||
|
||||
yield cps.removeByDomainAndName("a.com", "bar", null, makeCallback());
|
||||
yield dbOK([
|
||||
[null, "bar", 4],
|
||||
]);
|
||||
yield getOK(["a.com", "foo"], undefined);
|
||||
yield getOK(["a.com", "bar"], undefined);
|
||||
yield getGlobalOK(["foo"], undefined);
|
||||
yield getGlobalOK(["bar"], 4);
|
||||
|
||||
yield cps.removeGlobal("bar", null, makeCallback());
|
||||
yield dbOK([
|
||||
]);
|
||||
yield getOK(["a.com", "foo"], undefined);
|
||||
yield getOK(["a.com", "bar"], undefined);
|
||||
yield getGlobalOK(["foo"], undefined);
|
||||
yield getGlobalOK(["bar"], undefined);
|
||||
},
|
||||
|
||||
function* subdomains() {
|
||||
yield set("a.com", "foo", 1);
|
||||
yield set("b.a.com", "foo", 2);
|
||||
yield cps.removeByDomainAndName("a.com", "foo", null, makeCallback());
|
||||
yield dbOK([
|
||||
["b.a.com", "foo", 2],
|
||||
]);
|
||||
yield getSubdomainsOK(["a.com", "foo"], [["b.a.com", 2]]);
|
||||
yield getSubdomainsOK(["b.a.com", "foo"], [["b.a.com", 2]]);
|
||||
|
||||
yield set("a.com", "foo", 3);
|
||||
yield cps.removeBySubdomainAndName("a.com", "foo", null, makeCallback());
|
||||
yield dbOK([
|
||||
]);
|
||||
yield getSubdomainsOK(["a.com", "foo"], []);
|
||||
yield getSubdomainsOK(["b.a.com", "foo"], []);
|
||||
|
||||
yield set("a.com", "foo", 4);
|
||||
yield set("b.a.com", "foo", 5);
|
||||
yield cps.removeByDomainAndName("b.a.com", "foo", null, makeCallback());
|
||||
yield dbOK([
|
||||
["a.com", "foo", 4],
|
||||
]);
|
||||
yield getSubdomainsOK(["a.com", "foo"], [["a.com", 4]]);
|
||||
yield getSubdomainsOK(["b.a.com", "foo"], []);
|
||||
|
||||
yield set("b.a.com", "foo", 6);
|
||||
yield cps.removeBySubdomainAndName("b.a.com", "foo", null, makeCallback());
|
||||
yield dbOK([
|
||||
["a.com", "foo", 4],
|
||||
]);
|
||||
yield getSubdomainsOK(["a.com", "foo"], [["a.com", 4]]);
|
||||
yield getSubdomainsOK(["b.a.com", "foo"], []);
|
||||
},
|
||||
|
||||
function* privateBrowsing() {
|
||||
yield set("a.com", "foo", 1);
|
||||
yield set("a.com", "bar", 2);
|
||||
yield setGlobal("foo", 3);
|
||||
yield setGlobal("bar", 4);
|
||||
yield setGlobal("qux", 5);
|
||||
yield set("b.com", "foo", 6);
|
||||
yield set("b.com", "bar", 7);
|
||||
|
||||
let context = { usePrivateBrowsing: true };
|
||||
yield set("a.com", "foo", 8, context);
|
||||
yield setGlobal("foo", 9, context);
|
||||
yield cps.removeByDomainAndName("a.com", "foo", context, makeCallback());
|
||||
yield cps.removeGlobal("foo", context, makeCallback());
|
||||
yield cps.removeGlobal("qux", context, makeCallback());
|
||||
yield cps.removeByDomainAndName("b.com", "foo", context, makeCallback());
|
||||
yield dbOK([
|
||||
["a.com", "bar", 2],
|
||||
[null, "bar", 4],
|
||||
["b.com", "bar", 7],
|
||||
]);
|
||||
yield getOK(["a.com", "foo", context], undefined);
|
||||
yield getOK(["a.com", "bar", context], 2);
|
||||
yield getGlobalOK(["foo", context], undefined);
|
||||
yield getGlobalOK(["bar", context], 4);
|
||||
yield getGlobalOK(["qux", context], undefined);
|
||||
yield getOK(["b.com", "foo", context], undefined);
|
||||
yield getOK(["b.com", "bar", context], 7);
|
||||
|
||||
yield getOK(["a.com", "foo"], undefined);
|
||||
yield getOK(["a.com", "bar"], 2);
|
||||
yield getGlobalOK(["foo"], undefined);
|
||||
yield getGlobalOK(["bar"], 4);
|
||||
yield getGlobalOK(["qux"], undefined);
|
||||
yield getOK(["b.com", "foo"], undefined);
|
||||
yield getOK(["b.com", "bar"], 7);
|
||||
},
|
||||
|
||||
function* erroneous() {
|
||||
do_check_throws(() => cps.removeByDomainAndName(null, "foo", null));
|
||||
do_check_throws(() => cps.removeByDomainAndName("", "foo", null));
|
||||
do_check_throws(() => cps.removeByDomainAndName("a.com", "foo", null,
|
||||
"bogus"));
|
||||
do_check_throws(() => cps.removeBySubdomainAndName(null, "foo",
|
||||
null));
|
||||
do_check_throws(() => cps.removeBySubdomainAndName("", "foo", null));
|
||||
do_check_throws(() => cps.removeBySubdomainAndName("a.com", "foo",
|
||||
null, "bogus"));
|
||||
do_check_throws(() => cps.removeGlobal("", null));
|
||||
do_check_throws(() => cps.removeGlobal(null, null));
|
||||
do_check_throws(() => cps.removeGlobal("foo", null, "bogus"));
|
||||
yield true;
|
||||
},
|
||||
|
||||
function* removeByDomainAndName_invalidateCache() {
|
||||
yield set("a.com", "foo", 1);
|
||||
getCachedOK(["a.com", "foo"], true, 1);
|
||||
cps.removeByDomainAndName("a.com", "foo", null, makeCallback());
|
||||
getCachedOK(["a.com", "foo"], false);
|
||||
yield;
|
||||
},
|
||||
|
||||
function* removeBySubdomainAndName_invalidateCache() {
|
||||
yield set("a.com", "foo", 1);
|
||||
yield set("b.a.com", "foo", 2);
|
||||
getCachedSubdomainsOK(["a.com", "foo"], [
|
||||
["a.com", 1],
|
||||
["b.a.com", 2],
|
||||
]);
|
||||
cps.removeBySubdomainAndName("a.com", "foo", null, makeCallback());
|
||||
getCachedSubdomainsOK(["a.com", "foo"], []);
|
||||
yield;
|
||||
},
|
||||
|
||||
function* removeGlobal_invalidateCache() {
|
||||
yield setGlobal("foo", 1);
|
||||
getCachedGlobalOK(["foo"], true, 1);
|
||||
cps.removeGlobal("foo", null, makeCallback());
|
||||
getCachedGlobalOK(["foo"], false);
|
||||
yield;
|
||||
},
|
||||
];
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
function run_test() {
|
||||
runAsyncTests(tests);
|
||||
}
|
||||
|
||||
var tests = [
|
||||
|
||||
function* nonexistent() {
|
||||
yield setGlobal("foo", 1);
|
||||
yield cps.removeAllDomains(null, makeCallback());
|
||||
yield dbOK([
|
||||
[null, "foo", 1],
|
||||
]);
|
||||
yield getGlobalOK(["foo"], 1);
|
||||
},
|
||||
|
||||
function* domains() {
|
||||
yield set("a.com", "foo", 1);
|
||||
yield set("a.com", "bar", 2);
|
||||
yield setGlobal("foo", 3);
|
||||
yield setGlobal("bar", 4);
|
||||
yield set("b.com", "foo", 5);
|
||||
yield set("b.com", "bar", 6);
|
||||
|
||||
yield cps.removeAllDomains(null, makeCallback());
|
||||
yield dbOK([
|
||||
[null, "foo", 3],
|
||||
[null, "bar", 4],
|
||||
]);
|
||||
yield getOK(["a.com", "foo"], undefined);
|
||||
yield getOK(["a.com", "bar"], undefined);
|
||||
yield getGlobalOK(["foo"], 3);
|
||||
yield getGlobalOK(["bar"], 4);
|
||||
yield getOK(["b.com", "foo"], undefined);
|
||||
yield getOK(["b.com", "bar"], undefined);
|
||||
},
|
||||
|
||||
function* privateBrowsing() {
|
||||
yield set("a.com", "foo", 1);
|
||||
yield set("a.com", "bar", 2);
|
||||
yield setGlobal("foo", 3);
|
||||
yield setGlobal("bar", 4);
|
||||
yield set("b.com", "foo", 5);
|
||||
|
||||
let context = { usePrivateBrowsing: true };
|
||||
yield set("a.com", "foo", 6, context);
|
||||
yield setGlobal("foo", 7, context);
|
||||
yield cps.removeAllDomains(context, makeCallback());
|
||||
yield dbOK([
|
||||
[null, "foo", 3],
|
||||
[null, "bar", 4],
|
||||
]);
|
||||
yield getOK(["a.com", "foo", context], undefined);
|
||||
yield getOK(["a.com", "bar", context], undefined);
|
||||
yield getGlobalOK(["foo", context], 7);
|
||||
yield getGlobalOK(["bar", context], 4);
|
||||
yield getOK(["b.com", "foo", context], undefined);
|
||||
|
||||
yield getOK(["a.com", "foo"], undefined);
|
||||
yield getOK(["a.com", "bar"], undefined);
|
||||
yield getGlobalOK(["foo"], 3);
|
||||
yield getGlobalOK(["bar"], 4);
|
||||
yield getOK(["b.com", "foo"], undefined);
|
||||
},
|
||||
|
||||
function* erroneous() {
|
||||
do_check_throws(() => cps.removeAllDomains(null, "bogus"));
|
||||
yield true;
|
||||
},
|
||||
|
||||
function* invalidateCache() {
|
||||
yield set("a.com", "foo", 1);
|
||||
yield set("b.com", "bar", 2);
|
||||
yield setGlobal("baz", 3);
|
||||
getCachedOK(["a.com", "foo"], true, 1);
|
||||
getCachedOK(["b.com", "bar"], true, 2);
|
||||
getCachedGlobalOK(["baz"], true, 3);
|
||||
cps.removeAllDomains(null, makeCallback());
|
||||
getCachedOK(["a.com", "foo"], false);
|
||||
getCachedOK(["b.com", "bar"], false);
|
||||
getCachedGlobalOK(["baz"], true, 3);
|
||||
yield;
|
||||
},
|
||||
];
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
function run_test() {
|
||||
runAsyncTests(tests);
|
||||
}
|
||||
|
||||
var tests = [
|
||||
|
||||
function* nonexistent() {
|
||||
yield setGlobal("foo", 1);
|
||||
yield cps.removeAllDomainsSince(0, null, makeCallback());
|
||||
yield getGlobalOK(["foo"], 1);
|
||||
},
|
||||
|
||||
function* domainsAll() {
|
||||
yield set("a.com", "foo", 1);
|
||||
yield set("a.com", "bar", 2);
|
||||
yield setGlobal("foo", 3);
|
||||
yield setGlobal("bar", 4);
|
||||
yield set("b.com", "foo", 5);
|
||||
yield set("b.com", "bar", 6);
|
||||
|
||||
yield cps.removeAllDomainsSince(0, null, makeCallback());
|
||||
yield dbOK([
|
||||
[null, "foo", 3],
|
||||
[null, "bar", 4],
|
||||
]);
|
||||
yield getOK(["a.com", "foo"], undefined);
|
||||
yield getOK(["a.com", "bar"], undefined);
|
||||
yield getGlobalOK(["foo"], 3);
|
||||
yield getGlobalOK(["bar"], 4);
|
||||
yield getOK(["b.com", "foo"], undefined);
|
||||
yield getOK(["b.com", "bar"], undefined);
|
||||
},
|
||||
|
||||
function* domainsWithDate() {
|
||||
yield setWithDate("a.com", "foobar", 0, 0);
|
||||
yield setWithDate("a.com", "foo", 1, 1000);
|
||||
yield setWithDate("a.com", "bar", 2, 4000);
|
||||
yield setGlobal("foo", 3);
|
||||
yield setGlobal("bar", 4);
|
||||
yield setWithDate("b.com", "foo", 5, 2000);
|
||||
yield setWithDate("b.com", "bar", 6, 3000);
|
||||
yield setWithDate("b.com", "foobar", 7, 1000);
|
||||
|
||||
yield cps.removeAllDomainsSince(2000, null, makeCallback());
|
||||
yield dbOK([
|
||||
["a.com", "foobar", 0],
|
||||
["a.com", "foo", 1],
|
||||
[null, "foo", 3],
|
||||
[null, "bar", 4],
|
||||
["b.com", "foobar", 7],
|
||||
]);
|
||||
},
|
||||
|
||||
function* privateBrowsing() {
|
||||
yield set("a.com", "foo", 1);
|
||||
yield set("a.com", "bar", 2);
|
||||
yield setGlobal("foo", 3);
|
||||
yield setGlobal("bar", 4);
|
||||
yield set("b.com", "foo", 5);
|
||||
|
||||
let context = { usePrivateBrowsing: true };
|
||||
yield set("a.com", "foo", 6, context);
|
||||
yield setGlobal("foo", 7, context);
|
||||
yield cps.removeAllDomainsSince(0, context, makeCallback());
|
||||
yield dbOK([
|
||||
[null, "foo", 3],
|
||||
[null, "bar", 4],
|
||||
]);
|
||||
yield getOK(["a.com", "foo", context], undefined);
|
||||
yield getOK(["a.com", "bar", context], undefined);
|
||||
yield getGlobalOK(["foo", context], 7);
|
||||
yield getGlobalOK(["bar", context], 4);
|
||||
yield getOK(["b.com", "foo", context], undefined);
|
||||
|
||||
yield getOK(["a.com", "foo"], undefined);
|
||||
yield getOK(["a.com", "bar"], undefined);
|
||||
yield getGlobalOK(["foo"], 3);
|
||||
yield getGlobalOK(["bar"], 4);
|
||||
yield getOK(["b.com", "foo"], undefined);
|
||||
},
|
||||
|
||||
function* erroneous() {
|
||||
do_check_throws(() => cps.removeAllDomainsSince(null, "bogus"));
|
||||
yield true;
|
||||
},
|
||||
|
||||
function* invalidateCache() {
|
||||
yield setWithDate("a.com", "foobar", 0, 0);
|
||||
yield setWithDate("a.com", "foo", 1, 1000);
|
||||
yield setWithDate("a.com", "bar", 2, 4000);
|
||||
yield setGlobal("foo", 3);
|
||||
yield setGlobal("bar", 4);
|
||||
yield setWithDate("b.com", "foo", 5, 2000);
|
||||
yield setWithDate("b.com", "bar", 6, 3000);
|
||||
yield setWithDate("b.com", "foobar", 7, 1000);
|
||||
cps.removeAllDomainsSince(0, null, makeCallback());
|
||||
getCachedOK(["a.com", "foobar"], false);
|
||||
getCachedOK(["a.com", "foo"], false);
|
||||
getCachedOK(["a.com", "bar"], false);
|
||||
getCachedGlobalOK(["foo"], true, 3);
|
||||
getCachedGlobalOK(["bar"], true, 4);
|
||||
getCachedOK(["b.com", "foo"], false);
|
||||
getCachedOK(["b.com", "bar"], false);
|
||||
getCachedOK(["b.com", "foobar"], false);
|
||||
yield true;
|
||||
},
|
||||
];
|
||||
|
|
@ -0,0 +1,199 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
function run_test() {
|
||||
runAsyncTests(tests);
|
||||
}
|
||||
|
||||
var tests = [
|
||||
|
||||
function* nonexistent() {
|
||||
yield set("a.com", "foo", 1);
|
||||
yield setGlobal("foo", 2);
|
||||
|
||||
yield cps.removeByDomain("bogus", null, makeCallback());
|
||||
yield dbOK([
|
||||
["a.com", "foo", 1],
|
||||
[null, "foo", 2],
|
||||
]);
|
||||
yield getOK(["a.com", "foo"], 1);
|
||||
yield getGlobalOK(["foo"], 2);
|
||||
|
||||
yield cps.removeBySubdomain("bogus", null, makeCallback());
|
||||
yield dbOK([
|
||||
["a.com", "foo", 1],
|
||||
[null, "foo", 2],
|
||||
]);
|
||||
yield getOK(["a.com", "foo"], 1);
|
||||
yield getGlobalOK(["foo"], 2);
|
||||
},
|
||||
|
||||
function* isomorphicDomains() {
|
||||
yield set("a.com", "foo", 1);
|
||||
yield cps.removeByDomain("a.com", null, makeCallback());
|
||||
yield dbOK([]);
|
||||
yield getOK(["a.com", "foo"], undefined);
|
||||
|
||||
yield set("a.com", "foo", 2);
|
||||
yield cps.removeByDomain("http://a.com/huh", null, makeCallback());
|
||||
yield dbOK([]);
|
||||
yield getOK(["a.com", "foo"], undefined);
|
||||
},
|
||||
|
||||
function* domains() {
|
||||
yield set("a.com", "foo", 1);
|
||||
yield set("a.com", "bar", 2);
|
||||
yield setGlobal("foo", 3);
|
||||
yield setGlobal("bar", 4);
|
||||
yield set("b.com", "foo", 5);
|
||||
yield set("b.com", "bar", 6);
|
||||
|
||||
yield cps.removeByDomain("a.com", null, makeCallback());
|
||||
yield dbOK([
|
||||
[null, "foo", 3],
|
||||
[null, "bar", 4],
|
||||
["b.com", "foo", 5],
|
||||
["b.com", "bar", 6],
|
||||
]);
|
||||
yield getOK(["a.com", "foo"], undefined);
|
||||
yield getOK(["a.com", "bar"], undefined);
|
||||
yield getGlobalOK(["foo"], 3);
|
||||
yield getGlobalOK(["bar"], 4);
|
||||
yield getOK(["b.com", "foo"], 5);
|
||||
yield getOK(["b.com", "bar"], 6);
|
||||
|
||||
yield cps.removeAllGlobals(null, makeCallback());
|
||||
yield dbOK([
|
||||
["b.com", "foo", 5],
|
||||
["b.com", "bar", 6],
|
||||
]);
|
||||
yield getOK(["a.com", "foo"], undefined);
|
||||
yield getOK(["a.com", "bar"], undefined);
|
||||
yield getGlobalOK(["foo"], undefined);
|
||||
yield getGlobalOK(["bar"], undefined);
|
||||
yield getOK(["b.com", "foo"], 5);
|
||||
yield getOK(["b.com", "bar"], 6);
|
||||
|
||||
yield cps.removeByDomain("b.com", null, makeCallback());
|
||||
yield dbOK([
|
||||
]);
|
||||
yield getOK(["a.com", "foo"], undefined);
|
||||
yield getOK(["a.com", "bar"], undefined);
|
||||
yield getGlobalOK(["foo"], undefined);
|
||||
yield getGlobalOK(["bar"], undefined);
|
||||
yield getOK(["b.com", "foo"], undefined);
|
||||
yield getOK(["b.com", "bar"], undefined);
|
||||
},
|
||||
|
||||
function* subdomains() {
|
||||
yield set("a.com", "foo", 1);
|
||||
yield set("b.a.com", "foo", 2);
|
||||
yield cps.removeByDomain("a.com", null, makeCallback());
|
||||
yield dbOK([
|
||||
["b.a.com", "foo", 2],
|
||||
]);
|
||||
yield getSubdomainsOK(["a.com", "foo"], [["b.a.com", 2]]);
|
||||
yield getSubdomainsOK(["b.a.com", "foo"], [["b.a.com", 2]]);
|
||||
|
||||
yield set("a.com", "foo", 3);
|
||||
yield cps.removeBySubdomain("a.com", null, makeCallback());
|
||||
yield dbOK([
|
||||
]);
|
||||
yield getSubdomainsOK(["a.com", "foo"], []);
|
||||
yield getSubdomainsOK(["b.a.com", "foo"], []);
|
||||
|
||||
yield set("a.com", "foo", 4);
|
||||
yield set("b.a.com", "foo", 5);
|
||||
yield cps.removeByDomain("b.a.com", null, makeCallback());
|
||||
yield dbOK([
|
||||
["a.com", "foo", 4],
|
||||
]);
|
||||
yield getSubdomainsOK(["a.com", "foo"], [["a.com", 4]]);
|
||||
yield getSubdomainsOK(["b.a.com", "foo"], []);
|
||||
|
||||
yield set("b.a.com", "foo", 6);
|
||||
yield cps.removeBySubdomain("b.a.com", null, makeCallback());
|
||||
yield dbOK([
|
||||
["a.com", "foo", 4],
|
||||
]);
|
||||
yield getSubdomainsOK(["a.com", "foo"], [["a.com", 4]]);
|
||||
yield getSubdomainsOK(["b.a.com", "foo"], []);
|
||||
},
|
||||
|
||||
function* privateBrowsing() {
|
||||
yield set("a.com", "foo", 1);
|
||||
yield set("a.com", "bar", 2);
|
||||
yield setGlobal("foo", 3);
|
||||
yield setGlobal("bar", 4);
|
||||
yield set("b.com", "foo", 5);
|
||||
|
||||
let context = { usePrivateBrowsing: true };
|
||||
yield set("a.com", "foo", 6, 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],
|
||||
]);
|
||||
yield getOK(["a.com", "foo", context], undefined);
|
||||
yield getOK(["a.com", "bar", context], undefined);
|
||||
yield getGlobalOK(["foo", context], undefined);
|
||||
yield getGlobalOK(["bar", context], undefined);
|
||||
yield getOK(["b.com", "foo", context], 5);
|
||||
|
||||
yield getOK(["a.com", "foo"], undefined);
|
||||
yield getOK(["a.com", "bar"], undefined);
|
||||
yield getGlobalOK(["foo"], undefined);
|
||||
yield getGlobalOK(["bar"], undefined);
|
||||
yield getOK(["b.com", "foo"], 5);
|
||||
},
|
||||
|
||||
function* erroneous() {
|
||||
do_check_throws(() => cps.removeByDomain(null, null));
|
||||
do_check_throws(() => cps.removeByDomain("", null));
|
||||
do_check_throws(() => cps.removeByDomain("a.com", null, "bogus"));
|
||||
do_check_throws(() => cps.removeBySubdomain(null, null));
|
||||
do_check_throws(() => cps.removeBySubdomain("", null));
|
||||
do_check_throws(() => cps.removeBySubdomain("a.com", null, "bogus"));
|
||||
do_check_throws(() => cps.removeAllGlobals(null, "bogus"));
|
||||
yield true;
|
||||
},
|
||||
|
||||
function* removeByDomain_invalidateCache() {
|
||||
yield set("a.com", "foo", 1);
|
||||
yield set("a.com", "bar", 2);
|
||||
getCachedOK(["a.com", "foo"], true, 1);
|
||||
getCachedOK(["a.com", "bar"], true, 2);
|
||||
cps.removeByDomain("a.com", null, makeCallback());
|
||||
getCachedOK(["a.com", "foo"], false);
|
||||
getCachedOK(["a.com", "bar"], false);
|
||||
yield;
|
||||
},
|
||||
|
||||
function* removeBySubdomain_invalidateCache() {
|
||||
yield set("a.com", "foo", 1);
|
||||
yield set("b.a.com", "foo", 2);
|
||||
getCachedSubdomainsOK(["a.com", "foo"], [
|
||||
["a.com", 1],
|
||||
["b.a.com", 2],
|
||||
]);
|
||||
cps.removeBySubdomain("a.com", null, makeCallback());
|
||||
getCachedSubdomainsOK(["a.com", "foo"], []);
|
||||
yield;
|
||||
},
|
||||
|
||||
function* removeAllGlobals_invalidateCache() {
|
||||
yield setGlobal("foo", 1);
|
||||
yield setGlobal("bar", 2);
|
||||
getCachedGlobalOK(["foo"], true, 1);
|
||||
getCachedGlobalOK(["bar"], true, 2);
|
||||
cps.removeAllGlobals(null, makeCallback());
|
||||
getCachedGlobalOK(["foo"], false);
|
||||
getCachedGlobalOK(["bar"], false);
|
||||
yield;
|
||||
},
|
||||
];
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
function run_test() {
|
||||
runAsyncTests(tests);
|
||||
}
|
||||
|
||||
var tests = [
|
||||
|
||||
function* nonexistent() {
|
||||
yield set("a.com", "foo", 1);
|
||||
yield setGlobal("foo", 2);
|
||||
|
||||
yield cps.removeByName("bogus", null, makeCallback());
|
||||
yield dbOK([
|
||||
["a.com", "foo", 1],
|
||||
[null, "foo", 2],
|
||||
]);
|
||||
yield getOK(["a.com", "foo"], 1);
|
||||
yield getGlobalOK(["foo"], 2);
|
||||
},
|
||||
|
||||
function* names() {
|
||||
yield set("a.com", "foo", 1);
|
||||
yield set("a.com", "bar", 2);
|
||||
yield setGlobal("foo", 3);
|
||||
yield setGlobal("bar", 4);
|
||||
yield set("b.com", "foo", 5);
|
||||
yield set("b.com", "bar", 6);
|
||||
|
||||
yield cps.removeByName("foo", null, makeCallback());
|
||||
yield dbOK([
|
||||
["a.com", "bar", 2],
|
||||
[null, "bar", 4],
|
||||
["b.com", "bar", 6],
|
||||
]);
|
||||
yield getOK(["a.com", "foo"], undefined);
|
||||
yield getOK(["a.com", "bar"], 2);
|
||||
yield getGlobalOK(["foo"], undefined);
|
||||
yield getGlobalOK(["bar"], 4);
|
||||
yield getOK(["b.com", "foo"], undefined);
|
||||
yield getOK(["b.com", "bar"], 6);
|
||||
},
|
||||
|
||||
function* privateBrowsing() {
|
||||
yield set("a.com", "foo", 1);
|
||||
yield set("a.com", "bar", 2);
|
||||
yield setGlobal("foo", 3);
|
||||
yield setGlobal("bar", 4);
|
||||
yield set("b.com", "foo", 5);
|
||||
yield set("b.com", "bar", 6);
|
||||
|
||||
let context = { usePrivateBrowsing: true };
|
||||
yield set("a.com", "foo", 7, context);
|
||||
yield setGlobal("foo", 8, context);
|
||||
yield set("b.com", "bar", 9, context);
|
||||
yield cps.removeByName("bar", context, makeCallback());
|
||||
yield dbOK([
|
||||
["a.com", "foo", 1],
|
||||
[null, "foo", 3],
|
||||
["b.com", "foo", 5],
|
||||
]);
|
||||
yield getOK(["a.com", "foo", context], 7);
|
||||
yield getOK(["a.com", "bar", context], undefined);
|
||||
yield getGlobalOK(["foo", context], 8);
|
||||
yield getGlobalOK(["bar", context], undefined);
|
||||
yield getOK(["b.com", "foo", context], 5);
|
||||
yield getOK(["b.com", "bar", context], undefined);
|
||||
|
||||
yield getOK(["a.com", "foo"], 1);
|
||||
yield getOK(["a.com", "bar"], undefined);
|
||||
yield getGlobalOK(["foo"], 3);
|
||||
yield getGlobalOK(["bar"], undefined);
|
||||
yield getOK(["b.com", "foo"], 5);
|
||||
yield getOK(["b.com", "bar"], undefined);
|
||||
},
|
||||
|
||||
function* erroneous() {
|
||||
do_check_throws(() => cps.removeByName("", null));
|
||||
do_check_throws(() => cps.removeByName(null, null));
|
||||
do_check_throws(() => cps.removeByName("foo", null, "bogus"));
|
||||
yield true;
|
||||
},
|
||||
|
||||
function* invalidateCache() {
|
||||
yield set("a.com", "foo", 1);
|
||||
yield set("b.com", "foo", 2);
|
||||
getCachedOK(["a.com", "foo"], true, 1);
|
||||
getCachedOK(["b.com", "foo"], true, 2);
|
||||
cps.removeByName("foo", null, makeCallback());
|
||||
getCachedOK(["a.com", "foo"], false);
|
||||
getCachedOK(["b.com", "foo"], false);
|
||||
yield;
|
||||
},
|
||||
];
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
function run_test() {
|
||||
let serv = Cc["@mozilla.org/content-pref/service;1"].
|
||||
getService(Ci.nsIContentPrefService2);
|
||||
do_check_eq(serv.QueryInterface(Ci.nsIContentPrefService2), serv);
|
||||
do_check_eq(serv.QueryInterface(Ci.nsISupports), serv);
|
||||
let val = serv.QueryInterface(Ci.nsIContentPrefService);
|
||||
do_check_true(val instanceof Ci.nsIContentPrefService);
|
||||
}
|
||||
206
toolkit/components/contentprefs/tests/unit_cps2/test_setGet.js
Normal file
206
toolkit/components/contentprefs/tests/unit_cps2/test_setGet.js
Normal file
|
|
@ -0,0 +1,206 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
function run_test() {
|
||||
runAsyncTests(tests);
|
||||
}
|
||||
|
||||
var tests = [
|
||||
|
||||
function* get_nonexistent() {
|
||||
yield getOK(["a.com", "foo"], undefined);
|
||||
yield getGlobalOK(["foo"], undefined);
|
||||
},
|
||||
|
||||
function* isomorphicDomains() {
|
||||
yield set("a.com", "foo", 1);
|
||||
yield dbOK([
|
||||
["a.com", "foo", 1],
|
||||
]);
|
||||
yield getOK(["a.com", "foo"], 1);
|
||||
yield getOK(["http://a.com/huh", "foo"], 1, "a.com");
|
||||
|
||||
yield set("http://a.com/huh", "foo", 2);
|
||||
yield dbOK([
|
||||
["a.com", "foo", 2],
|
||||
]);
|
||||
yield getOK(["a.com", "foo"], 2);
|
||||
yield getOK(["http://a.com/yeah", "foo"], 2, "a.com");
|
||||
},
|
||||
|
||||
function* names() {
|
||||
yield set("a.com", "foo", 1);
|
||||
yield dbOK([
|
||||
["a.com", "foo", 1],
|
||||
]);
|
||||
yield getOK(["a.com", "foo"], 1);
|
||||
|
||||
yield set("a.com", "bar", 2);
|
||||
yield dbOK([
|
||||
["a.com", "foo", 1],
|
||||
["a.com", "bar", 2],
|
||||
]);
|
||||
yield getOK(["a.com", "foo"], 1);
|
||||
yield getOK(["a.com", "bar"], 2);
|
||||
|
||||
yield setGlobal("foo", 3);
|
||||
yield dbOK([
|
||||
["a.com", "foo", 1],
|
||||
["a.com", "bar", 2],
|
||||
[null, "foo", 3],
|
||||
]);
|
||||
yield getOK(["a.com", "foo"], 1);
|
||||
yield getOK(["a.com", "bar"], 2);
|
||||
yield getGlobalOK(["foo"], 3);
|
||||
|
||||
yield setGlobal("bar", 4);
|
||||
yield dbOK([
|
||||
["a.com", "foo", 1],
|
||||
["a.com", "bar", 2],
|
||||
[null, "foo", 3],
|
||||
[null, "bar", 4],
|
||||
]);
|
||||
yield getOK(["a.com", "foo"], 1);
|
||||
yield getOK(["a.com", "bar"], 2);
|
||||
yield getGlobalOK(["foo"], 3);
|
||||
yield getGlobalOK(["bar"], 4);
|
||||
},
|
||||
|
||||
function* subdomains() {
|
||||
yield set("a.com", "foo", 1);
|
||||
yield set("b.a.com", "foo", 2);
|
||||
yield dbOK([
|
||||
["a.com", "foo", 1],
|
||||
["b.a.com", "foo", 2],
|
||||
]);
|
||||
yield getOK(["a.com", "foo"], 1);
|
||||
yield getOK(["b.a.com", "foo"], 2);
|
||||
},
|
||||
|
||||
function* privateBrowsing() {
|
||||
yield set("a.com", "foo", 1);
|
||||
yield set("a.com", "bar", 2);
|
||||
yield setGlobal("foo", 3);
|
||||
yield setGlobal("bar", 4);
|
||||
yield set("b.com", "foo", 5);
|
||||
|
||||
let context = { usePrivateBrowsing: true };
|
||||
yield set("a.com", "foo", 6, context);
|
||||
yield setGlobal("foo", 7, context);
|
||||
yield dbOK([
|
||||
["a.com", "foo", 1],
|
||||
["a.com", "bar", 2],
|
||||
[null, "foo", 3],
|
||||
[null, "bar", 4],
|
||||
["b.com", "foo", 5],
|
||||
]);
|
||||
yield getOK(["a.com", "foo", context], 6, "a.com");
|
||||
yield getOK(["a.com", "bar", context], 2);
|
||||
yield getGlobalOK(["foo", context], 7);
|
||||
yield getGlobalOK(["bar", context], 4);
|
||||
yield getOK(["b.com", "foo", context], 5);
|
||||
|
||||
yield getOK(["a.com", "foo"], 1);
|
||||
yield getOK(["a.com", "bar"], 2);
|
||||
yield getGlobalOK(["foo"], 3);
|
||||
yield getGlobalOK(["bar"], 4);
|
||||
yield getOK(["b.com", "foo"], 5);
|
||||
},
|
||||
|
||||
function* set_erroneous() {
|
||||
do_check_throws(() => cps.set(null, "foo", 1, null));
|
||||
do_check_throws(() => cps.set("", "foo", 1, null));
|
||||
do_check_throws(() => cps.set("a.com", "", 1, null));
|
||||
do_check_throws(() => cps.set("a.com", null, 1, null));
|
||||
do_check_throws(() => cps.set("a.com", "foo", undefined, null));
|
||||
do_check_throws(() => cps.set("a.com", "foo", 1, null, "bogus"));
|
||||
do_check_throws(() => cps.setGlobal("", 1, null));
|
||||
do_check_throws(() => cps.setGlobal(null, 1, null));
|
||||
do_check_throws(() => cps.setGlobal("foo", undefined, null));
|
||||
do_check_throws(() => cps.setGlobal("foo", 1, null, "bogus"));
|
||||
yield true;
|
||||
},
|
||||
|
||||
function* get_erroneous() {
|
||||
do_check_throws(() => cps.getByDomainAndName(null, "foo", null, {}));
|
||||
do_check_throws(() => cps.getByDomainAndName("", "foo", null, {}));
|
||||
do_check_throws(() => cps.getByDomainAndName("a.com", "", null, {}));
|
||||
do_check_throws(() => cps.getByDomainAndName("a.com", null, null, {}));
|
||||
do_check_throws(() => cps.getByDomainAndName("a.com", "foo", null, null));
|
||||
do_check_throws(() => cps.getGlobal("", null, {}));
|
||||
do_check_throws(() => cps.getGlobal(null, null, {}));
|
||||
do_check_throws(() => cps.getGlobal("foo", null, null));
|
||||
yield true;
|
||||
},
|
||||
|
||||
function* set_invalidateCache() {
|
||||
// (1) Set a pref and wait for it to finish.
|
||||
yield set("a.com", "foo", 1);
|
||||
|
||||
// (2) It should be cached.
|
||||
getCachedOK(["a.com", "foo"], true, 1);
|
||||
|
||||
// (3) Set the pref to a new value but don't wait for it to finish.
|
||||
cps.set("a.com", "foo", 2, null, {
|
||||
handleCompletion: function () {
|
||||
// (6) The pref should be cached after setting it.
|
||||
getCachedOK(["a.com", "foo"], true, 2);
|
||||
},
|
||||
});
|
||||
|
||||
// (4) Group "a.com" and name "foo" should no longer be cached.
|
||||
getCachedOK(["a.com", "foo"], false);
|
||||
|
||||
// (5) Call getByDomainAndName.
|
||||
var fetchedPref;
|
||||
cps.getByDomainAndName("a.com", "foo", null, {
|
||||
handleResult: function (pref) {
|
||||
fetchedPref = pref;
|
||||
},
|
||||
handleCompletion: function () {
|
||||
// (7) Finally, this callback should be called after set's above.
|
||||
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}
|
||||
]);
|
||||
},
|
||||
|
||||
function* setSetsCurrentDate() {
|
||||
// Because Date.now() is not guaranteed to be monotonically increasing
|
||||
// we just do here rough sanity check with one minute tolerance.
|
||||
const MINUTE = 60 * 1000;
|
||||
let now = Date.now();
|
||||
let start = now - MINUTE;
|
||||
let end = now + MINUTE;
|
||||
yield set("a.com", "foo", 1);
|
||||
let timestamp = yield getDate("a.com", "foo");
|
||||
ok(start <= timestamp, "Timestamp is not too early (" + start + "<=" + timestamp + ").");
|
||||
ok(timestamp <= end, "Timestamp is not too late (" + timestamp + "<=" + end + ").");
|
||||
},
|
||||
];
|
||||
19
toolkit/components/contentprefs/tests/unit_cps2/xpcshell.ini
Normal file
19
toolkit/components/contentprefs/tests/unit_cps2/xpcshell.ini
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
[DEFAULT]
|
||||
head = head.js
|
||||
tail =
|
||||
skip-if = toolkit == 'android'
|
||||
support-files = AsyncRunner.jsm
|
||||
|
||||
[test_service.js]
|
||||
[test_setGet.js]
|
||||
[test_getSubdomains.js]
|
||||
[test_remove.js]
|
||||
[test_removeByDomain.js]
|
||||
[test_removeAllDomains.js]
|
||||
[test_removeByName.js]
|
||||
[test_getCached.js]
|
||||
[test_getCachedSubdomains.js]
|
||||
[test_observers.js]
|
||||
[test_extractDomain.js]
|
||||
[test_migrationToSchema4.js]
|
||||
[test_removeAllDomainsSince.js]
|
||||
Loading…
Add table
Add a link
Reference in a new issue