Source code

Revision control

Copy as Markdown

Other Tools

/**
* Any copyright is dedicated to the Public Domain.
*/
// Tests are expected to define testSteps.
/* globals testSteps */
const NS_ERROR_DOM_QUOTA_EXCEEDED_ERR = 22;
function is(a, b, msg) {
Assert.equal(a, b, msg);
}
function ok(cond, msg) {
Assert.ok(!!cond, msg);
}
add_setup(function () {
do_get_profile();
enableTesting();
registerCleanupFunction(resetTesting);
});
function returnToEventLoop() {
return new Promise(function (resolve) {
executeSoon(resolve);
});
}
function enableTesting() {
Services.prefs.setBoolPref("dom.simpleDB.enabled", true);
Services.prefs.setBoolPref("dom.storage.testing", true);
// xpcshell globals don't have associated clients in the Clients API sense, so
// we need to disable client validation so that the unit tests are allowed to
// use LocalStorage.
Services.prefs.setBoolPref("dom.storage.client_validation", false);
Services.prefs.setBoolPref("dom.quotaManager.testing", true);
}
function resetTesting() {
Services.prefs.clearUserPref("dom.quotaManager.testing");
Services.prefs.clearUserPref("dom.storage.client_validation");
Services.prefs.clearUserPref("dom.storage.testing");
Services.prefs.clearUserPref("dom.simpleDB.enabled");
}
function setGlobalLimit(globalLimit) {
Services.prefs.setIntPref(
"dom.quotaManager.temporaryStorage.fixedLimit",
globalLimit
);
}
function resetGlobalLimit() {
Services.prefs.clearUserPref("dom.quotaManager.temporaryStorage.fixedLimit");
}
function setOriginLimit(originLimit) {
Services.prefs.setIntPref("dom.storage.default_quota", originLimit);
}
function resetOriginLimit() {
Services.prefs.clearUserPref("dom.storage.default_quota");
}
function setTimeout(callback, timeout) {
let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
timer.initWithCallback(
{
notify() {
callback();
},
},
timeout,
Ci.nsITimer.TYPE_ONE_SHOT
);
return timer;
}
function initStorage() {
return Services.qms.init();
}
function initTemporaryStorage() {
return Services.qms.initTemporaryStorage();
}
function initPersistentOrigin(principal) {
return Services.qms.initializePersistentOrigin(principal);
}
function initTemporaryOrigin(persistence, principal) {
return Services.qms.initializeTemporaryOrigin(persistence, principal);
}
function getOriginUsage(principal, fromMemory = false) {
let request = Services.qms.getUsageForPrincipal(
principal,
function () {},
fromMemory
);
return request;
}
function clear() {
let request = Services.qms.clear();
return request;
}
function clearOriginsByPattern(pattern) {
let request = Services.qms.clearStoragesForOriginAttributesPattern(pattern);
return request;
}
function clearOriginsByPrefix(principal, persistence) {
let request = Services.qms.clearStoragesForOriginPrefix(
principal,
persistence
);
return request;
}
function clearOrigin(principal, persistence) {
let request = Services.qms.clearStoragesForPrincipal(principal, persistence);
return request;
}
function reset() {
let request = Services.qms.reset();
return request;
}
function resetOrigin(principal) {
let request = Services.qms.resetStoragesForPrincipal(
principal,
"default",
"ls"
);
return request;
}
function installPackage(packageName) {
let currentDir = Services.dirsvc.get("CurWorkD", Ci.nsIFile);
let packageFile = currentDir.clone();
packageFile.append(packageName + ".zip");
let zipReader = Cc["@mozilla.org/libjar/zip-reader;1"].createInstance(
Ci.nsIZipReader
);
zipReader.open(packageFile);
let entryNames = [];
let entries = zipReader.findEntries(null);
while (entries.hasMore()) {
let entry = entries.getNext();
entryNames.push(entry);
}
entryNames.sort();
for (let entryName of entryNames) {
let zipentry = zipReader.getEntry(entryName);
let file = getRelativeFile(entryName);
if (zipentry.isDirectory) {
file.create(Ci.nsIFile.DIRECTORY_TYPE, parseInt("0755", 8));
} else {
let istream = zipReader.getInputStream(entryName);
var ostream = Cc[
"@mozilla.org/network/file-output-stream;1"
].createInstance(Ci.nsIFileOutputStream);
ostream.init(file, -1, parseInt("0644", 8), 0);
let bostream = Cc[
"@mozilla.org/network/buffered-output-stream;1"
].createInstance(Ci.nsIBufferedOutputStream);
bostream.init(ostream, 32768);
bostream.writeFrom(istream, istream.available());
istream.close();
bostream.close();
}
}
zipReader.close();
}
function getProfileDir() {
return Services.dirsvc.get("ProfD", Ci.nsIFile);
}
// Given a "/"-delimited path relative to the profile directory,
// return an nsIFile representing the path. This does not test
// for the existence of the file or parent directories.
// It is safe even on Windows where the directory separator is not "/",
// but make sure you're not passing in a "\"-delimited path.
function getRelativeFile(relativePath) {
let profileDir = getProfileDir();
let file = profileDir.clone();
relativePath.split("/").forEach(function (component) {
file.append(component);
});
return file;
}
function repeatChar(count, ch) {
if (count == 0) {
return "";
}
let result = ch;
let count2 = count / 2;
// Double the input until it is long enough.
while (result.length <= count2) {
result += result;
}
// Use substring to hit the precise length target without using extra memory.
return result + result.substring(0, count - result.length);
}
function getPrincipal(url, attrs) {
let uri = Services.io.newURI(url);
if (!attrs) {
attrs = {};
}
return Services.scriptSecurityManager.createContentPrincipal(uri, attrs);
}
function getCurrentPrincipal() {
return Cc["@mozilla.org/systemprincipal;1"].createInstance(Ci.nsIPrincipal);
}
function getDefaultPrincipal() {
return getPrincipal("http://example.com");
}
function getSimpleDatabase(principal, persistence) {
let connection = Cc["@mozilla.org/dom/sdb-connection;1"].createInstance(
Ci.nsISDBConnection
);
if (!principal) {
principal = getDefaultPrincipal();
}
connection.init(principal, persistence);
return connection;
}
function getLocalStorage(principal) {
if (!principal) {
principal = getDefaultPrincipal();
}
return Services.domStorageManager.createStorage(
null,
principal,
principal,
""
);
}
class RequestError extends Error {
constructor(resultCode, resultName) {
super(`Request failed (code: ${resultCode}, name: ${resultName})`);
this.name = "RequestError";
this.resultCode = resultCode;
this.resultName = resultName;
}
}
async function requestFinished(request) {
await new Promise(function (resolve) {
request.callback = function () {
resolve();
};
});
if (request.resultCode !== Cr.NS_OK) {
throw new RequestError(request.resultCode, request.resultName);
}
return request.result;
}
function loadSubscript(path) {
let file = do_get_file(path, false);
let uri = Services.io.newFileURI(file);
Services.scriptloader.loadSubScript(uri.spec);
}
async function readUsageFromUsageFile(usageFile) {
let file = await File.createFromNsIFile(usageFile);
let buffer = await new Promise(resolve => {
let reader = new FileReader();
reader.onloadend = () => resolve(reader.result);
reader.readAsArrayBuffer(file);
});
// Manually getting the lower 32-bits because of the lack of support for
// 64-bit values currently from DataView/JS (other than the BigInt support
// that's currently behind a flag).
let view = new DataView(buffer, 8, 4);
return view.getUint32();
}