Source code
Revision control
Copy as Markdown
Other Tools
Test Info:
/* Any copyright is dedicated to the Public Domain.
"use strict";
// This function adds the quota storage by simpleDB (one of quota clients
// managed by the QuotaManager). In this function, a directory
// ${profile}/storage/default/${origin}/sdb/ and a file inside are expected to
// be added.
async function addQuotaStorage(principal) {
let connection = Cc["@mozilla.org/dom/sdb-connection;1"].createInstance(
Ci.nsISDBConnection
);
connection.init(principal);
await new Promise((aResolve, aReject) => {
let request = connection.open("db");
request.callback = request => {
if (request.resultCode == Cr.NS_OK) {
aResolve();
} else {
aReject(request.resultCode);
}
};
});
await new Promise((aResolve, aReject) => {
let request = connection.write(new ArrayBuffer(1));
request.callback = request => {
if (request.resultCode == Cr.NS_OK) {
aResolve();
} else {
aReject(request.resultCode);
}
};
});
}
function getPrincipal(url, attr = {}) {
let uri = Services.io.newURI(url);
let ssm = Services.scriptSecurityManager;
return ssm.createContentPrincipal(uri, attr);
}
function getProfileDir() {
let directoryService = Services.dirsvc;
return directoryService.get("ProfD", Ci.nsIFile);
}
function getRelativeFile(relativePath) {
let profileDir = getProfileDir();
let file = profileDir.clone();
relativePath.split("/").forEach(function (component) {
file.append(component);
});
return file;
}
function getPath(origin) {
// Sanitizing
let regex = /[:\/]/g;
return "storage/default/" + origin.replace(regex, "+");
}
// This function checks if the origin has the quota storage by checking whether
// the origin directory of that origin exists or not.
function hasQuotaStorage(origin, attr) {
let path = getPath(origin);
if (attr) {
let principal = Services.scriptSecurityManager.createContentPrincipal(
Services.io.newURI(origin),
attr
);
path += principal.originSuffix;
}
let file = getRelativeFile(path);
return file.exists();
}
async function runTest(sites, deleteDataFunc) {
info(`Adding quota storage`);
for (let site of sites) {
const principal = getPrincipal(site.origin, site.originAttributes);
await addQuotaStorage(principal);
}
info(`Verifying ${deleteDataFunc.name}`);
let site;
while ((site = sites.shift())) {
await new Promise(aResolve => {
deleteDataFunc(...site.args, value => {
Assert.equal(value, 0);
aResolve();
});
});
ok(
!hasQuotaStorage(site.origin, site.originAttributes),
`${site.origin} has no quota storage`
);
sites.forEach(remainSite =>
ok(
hasQuotaStorage(remainSite.origin, remainSite.originAttributes),
`${remainSite.origin} has quota storage`
)
);
}
}
add_setup(async function () {
await SpecialPowers.pushPrefEnv({
set: [
["dom.quotaManager.testing", true],
["dom.simpleDB.enabled", true],
],
});
});
const ORG_DOMAIN = "example.org";
const ORG_DOMAIN_SUB = `test.${ORG_DOMAIN}`;
const COM_DOMAIN = "example.com";
const LH_DOMAIN = "localhost";
const FOO_DOMAIN = "foo.com";
add_task(async function test_deleteFromHost() {
const sites = [
{
args: [ORG_DOMAIN, true, Ci.nsIClearDataService.CLEAR_DOM_QUOTA],
origin: ORG_ORIGIN,
},
{
args: [COM_DOMAIN, true, Ci.nsIClearDataService.CLEAR_DOM_QUOTA],
origin: COM_ORIGIN,
},
{
args: [LH_DOMAIN, true, Ci.nsIClearDataService.CLEAR_DOM_QUOTA],
},
{
args: [FOO_DOMAIN, true, Ci.nsIClearDataService.CLEAR_DOM_QUOTA],
originAttributes: { userContextId: 1 },
},
];
await runTest(sites, Services.clearData.deleteDataFromHost);
});
add_task(async function test_deleteFromPrincipal() {
const sites = [
{
args: [
getPrincipal(ORG_ORIGIN),
true,
Ci.nsIClearDataService.CLEAR_DOM_QUOTA,
],
origin: ORG_ORIGIN,
},
{
args: [
getPrincipal(COM_ORIGIN),
true,
Ci.nsIClearDataService.CLEAR_DOM_QUOTA,
],
origin: COM_ORIGIN,
},
];
await runTest(sites, Services.clearData.deleteDataFromPrincipal);
});
add_task(async function test_deleteFromOriginAttributes() {
const ORG_OA = { userContextId: 1 };
const COM_OA = { userContextId: 2 };
const sites = [
{
args: [ORG_OA],
origin: ORG_ORIGIN,
originAttributes: ORG_OA,
},
{
args: [COM_OA],
origin: COM_ORIGIN,
originAttributes: COM_OA,
},
];
await runTest(
sites,
Services.clearData.deleteDataFromOriginAttributesPattern
);
});
add_task(async function test_deleteAll() {
info(`Adding quota storage`);
await addQuotaStorage(getPrincipal(ORG_ORIGIN));
await addQuotaStorage(getPrincipal(COM_ORIGIN));
info(`Verifying deleteData`);
await new Promise(aResolve => {
Services.clearData.deleteData(
Ci.nsIClearDataService.CLEAR_DOM_QUOTA,
value => {
Assert.equal(value, 0);
aResolve();
}
);
});
ok(!hasQuotaStorage(ORG_ORIGIN), `${ORG_ORIGIN} has no quota storage`);
ok(!hasQuotaStorage(COM_ORIGIN), `${COM_ORIGIN} has no quota storage`);
});
add_task(async function test_deleteSubdomain() {
info(`Adding quota storage`);
await addQuotaStorage(getPrincipal(ORG_ORIGIN));
await addQuotaStorage(getPrincipal(ANOTHER_ORIGIN));
info(`Verifying deleteDataFromHost for subdomain`);
await new Promise(aResolve => {
Services.clearData.deleteDataFromHost(
ORG_DOMAIN,
true,
Ci.nsIClearDataService.CLEAR_DOM_QUOTA,
value => {
Assert.equal(value, 0);
aResolve();
}
);
});
ok(!hasQuotaStorage(ORG_ORIGIN), `${ORG_ORIGIN} has no quota storage`);
ok(!hasQuotaStorage(COM_ORIGIN), `${ANOTHER_ORIGIN} has no quota storage`);
});
function getOAWithPartitionKey(topLevelBaseDomain, originAttributes = {}) {
if (!topLevelBaseDomain) {
return originAttributes;
}
return {
...originAttributes,
partitionKey: `(https,${topLevelBaseDomain})`,
};
}
add_task(async function test_deleteBaseDomain() {
info("Adding quota storage");
await addQuotaStorage(getPrincipal(ORG_ORIGIN));
await addQuotaStorage(getPrincipal(ORG_ORIGIN_SUB));
await addQuotaStorage(getPrincipal(COM_ORIGIN));
info("Adding partitioned quota storage");
// Partitioned
await addQuotaStorage(
getPrincipal(COM_ORIGIN, getOAWithPartitionKey(ORG_DOMAIN))
);
await addQuotaStorage(
getPrincipal(COM_ORIGIN, getOAWithPartitionKey(FOO_DOMAIN))
);
await addQuotaStorage(
getPrincipal(ORG_ORIGIN, getOAWithPartitionKey(COM_DOMAIN))
);
info(`Verifying deleteDataFromSite`);
await new Promise(aResolve => {
Services.clearData.deleteDataFromSite(
ORG_DOMAIN,
{},
true,
Ci.nsIClearDataService.CLEAR_DOM_QUOTA,
value => {
Assert.equal(value, 0);
aResolve();
}
);
});
ok(!hasQuotaStorage(ORG_ORIGIN), `${ORG_ORIGIN} has no quota storage`);
ok(
!hasQuotaStorage(ORG_ORIGIN_SUB),
`${ORG_ORIGIN_SUB} has no quota storage`
);
ok(hasQuotaStorage(COM_ORIGIN), `${COM_ORIGIN} has quota storage`);
// Partitioned
ok(
!hasQuotaStorage(COM_ORIGIN, getOAWithPartitionKey(ORG_DOMAIN)),
`${COM_ORIGIN} under ${ORG_DOMAIN} has no quota storage`
);
ok(
hasQuotaStorage(COM_ORIGIN, getOAWithPartitionKey(FOO_DOMAIN)),
`${COM_ORIGIN} under ${FOO_DOMAIN} has quota storage`
);
ok(
!hasQuotaStorage(ORG_ORIGIN, getOAWithPartitionKey(COM_DOMAIN)),
`${ORG_ORIGIN} under ${COM_DOMAIN} has no quota storage`
);
// Cleanup
await new Promise(aResolve => {
Services.clearData.deleteData(
Ci.nsIClearDataService.CLEAR_DOM_QUOTA,
value => {
Assert.equal(value, 0);
aResolve();
}
);
});
});