michael@0: /** michael@0: * Any copyright is dedicated to the Public Domain. michael@0: * http://creativecommons.org/publicdomain/zero/1.0/ michael@0: */ michael@0: michael@0: var testGenerator = testSteps(); michael@0: var archiveReaderEnabled = false; michael@0: michael@0: // The test js is shared between xpcshell (which has no SpecialPowers object) michael@0: // and content mochitests (where the |Components| object is accessible only as michael@0: // SpecialPowers.Components). Expose Components if necessary here to make things michael@0: // work everywhere. michael@0: // michael@0: // Even if the real |Components| doesn't exist, we might shim in a simple JS michael@0: // placebo for compat. An easy way to differentiate this from the real thing michael@0: // is whether the property is read-only or not. michael@0: var c = Object.getOwnPropertyDescriptor(this, 'Components'); michael@0: if ((!c.value || c.writable) && typeof SpecialPowers === 'object') michael@0: Components = SpecialPowers.Components; michael@0: michael@0: function executeSoon(aFun) michael@0: { michael@0: let comp = SpecialPowers.wrap(Components); michael@0: michael@0: let thread = comp.classes["@mozilla.org/thread-manager;1"] michael@0: .getService(comp.interfaces.nsIThreadManager) michael@0: .mainThread; michael@0: michael@0: thread.dispatch({ michael@0: run: function() { michael@0: aFun(); michael@0: } michael@0: }, Components.interfaces.nsIThread.DISPATCH_NORMAL); michael@0: } michael@0: michael@0: function clearAllDatabases(callback) { michael@0: function runCallback() { michael@0: SimpleTest.executeSoon(function () { callback(); }); michael@0: } michael@0: michael@0: if (!SpecialPowers.isMainProcess()) { michael@0: runCallback(); michael@0: return; michael@0: } michael@0: michael@0: let comp = SpecialPowers.wrap(Components); michael@0: michael@0: let quotaManager = michael@0: comp.classes["@mozilla.org/dom/quota/manager;1"] michael@0: .getService(comp.interfaces.nsIQuotaManager); michael@0: michael@0: let uri = SpecialPowers.wrap(document).documentURIObject; michael@0: michael@0: // We need to pass a JS callback to getUsageForURI. However, that callback michael@0: // takes an XPCOM URI object, which will cause us to throw when we wrap it michael@0: // for the content compartment. So we need to define the function in a michael@0: // privileged scope, which we do using a sandbox. michael@0: var sysPrin = SpecialPowers.Services.scriptSecurityManager.getSystemPrincipal(); michael@0: var sb = new SpecialPowers.Cu.Sandbox(sysPrin); michael@0: sb.ok = ok; michael@0: sb.runCallback = runCallback; michael@0: var cb = SpecialPowers.Cu.evalInSandbox((function(uri, usage, fileUsage) { michael@0: if (usage) { michael@0: ok(false, michael@0: "getUsageForURI returned non-zero usage after clearing all " + michael@0: "storages!"); michael@0: } michael@0: runCallback(); michael@0: }).toSource(), sb); michael@0: michael@0: quotaManager.clearStoragesForURI(uri); michael@0: quotaManager.getUsageForURI(uri, cb); michael@0: } michael@0: michael@0: if (!window.runTest) { michael@0: window.runTest = function(limitedQuota) michael@0: { michael@0: SimpleTest.waitForExplicitFinish(); michael@0: michael@0: if (limitedQuota) { michael@0: denyUnlimitedQuota(); michael@0: } michael@0: else { michael@0: allowUnlimitedQuota(); michael@0: } michael@0: michael@0: enableExperimental(); michael@0: enableArchiveReader(); michael@0: michael@0: clearAllDatabases(function () { testGenerator.next(); }); michael@0: } michael@0: } michael@0: michael@0: function finishTest() michael@0: { michael@0: resetUnlimitedQuota(); michael@0: resetExperimental(); michael@0: resetArchiveReader(); michael@0: SpecialPowers.notifyObserversInParentProcess(null, "disk-space-watcher", michael@0: "free"); michael@0: michael@0: SimpleTest.executeSoon(function() { michael@0: testGenerator.close(); michael@0: //clearAllDatabases(function() { SimpleTest.finish(); }); michael@0: SimpleTest.finish(); michael@0: }); michael@0: } michael@0: michael@0: function browserRunTest() michael@0: { michael@0: testGenerator.next(); michael@0: } michael@0: michael@0: function browserFinishTest() michael@0: { michael@0: setTimeout(function() { testGenerator.close(); }, 0); michael@0: } michael@0: michael@0: function grabEventAndContinueHandler(event) michael@0: { michael@0: testGenerator.send(event); michael@0: } michael@0: michael@0: function continueToNextStep() michael@0: { michael@0: SimpleTest.executeSoon(function() { michael@0: testGenerator.next(); michael@0: }); michael@0: } michael@0: michael@0: function continueToNextStepSync() michael@0: { michael@0: testGenerator.next(); michael@0: } michael@0: michael@0: function errorHandler(event) michael@0: { michael@0: ok(false, "indexedDB error, '" + event.target.error.name + "'"); michael@0: finishTest(); michael@0: } michael@0: michael@0: function browserErrorHandler(event) michael@0: { michael@0: browserFinishTest(); michael@0: throw new Error("indexedDB error (" + event.code + "): " + event.message); michael@0: } michael@0: michael@0: function unexpectedSuccessHandler() michael@0: { michael@0: ok(false, "Got success, but did not expect it!"); michael@0: finishTest(); michael@0: } michael@0: michael@0: function expectedErrorHandler(name) michael@0: { michael@0: return function(event) { michael@0: is(event.type, "error", "Got an error event"); michael@0: is(event.target.error.name, name, "Expected error was thrown."); michael@0: event.preventDefault(); michael@0: grabEventAndContinueHandler(event); michael@0: }; michael@0: } michael@0: michael@0: function ExpectError(name, preventDefault) michael@0: { michael@0: this._name = name; michael@0: this._preventDefault = preventDefault; michael@0: } michael@0: ExpectError.prototype = { michael@0: handleEvent: function(event) michael@0: { michael@0: is(event.type, "error", "Got an error event"); michael@0: is(event.target.error.name, this._name, "Expected error was thrown."); michael@0: if (this._preventDefault) { michael@0: event.preventDefault(); michael@0: event.stopPropagation(); michael@0: } michael@0: grabEventAndContinueHandler(event); michael@0: } michael@0: }; michael@0: michael@0: function compareKeys(k1, k2) { michael@0: let t = typeof k1; michael@0: if (t != typeof k2) michael@0: return false; michael@0: michael@0: if (t !== "object") michael@0: return k1 === k2; michael@0: michael@0: if (k1 instanceof Date) { michael@0: return (k2 instanceof Date) && michael@0: k1.getTime() === k2.getTime(); michael@0: } michael@0: michael@0: if (k1 instanceof Array) { michael@0: if (!(k2 instanceof Array) || michael@0: k1.length != k2.length) michael@0: return false; michael@0: michael@0: for (let i = 0; i < k1.length; ++i) { michael@0: if (!compareKeys(k1[i], k2[i])) michael@0: return false; michael@0: } michael@0: michael@0: return true; michael@0: } michael@0: michael@0: return false; michael@0: } michael@0: michael@0: function addPermission(type, allow, url) michael@0: { michael@0: if (!url) { michael@0: url = window.document; michael@0: } michael@0: SpecialPowers.addPermission(type, allow, url); michael@0: } michael@0: michael@0: function removePermission(type, url) michael@0: { michael@0: if (!url) { michael@0: url = window.document; michael@0: } michael@0: SpecialPowers.removePermission(type, url); michael@0: } michael@0: michael@0: function setQuota(quota) michael@0: { michael@0: SpecialPowers.setIntPref("dom.indexedDB.warningQuota", quota); michael@0: } michael@0: michael@0: function allowUnlimitedQuota(url) michael@0: { michael@0: addPermission("indexedDB-unlimited", true, url); michael@0: } michael@0: michael@0: function denyUnlimitedQuota(url) michael@0: { michael@0: addPermission("indexedDB-unlimited", false, url); michael@0: } michael@0: michael@0: function resetUnlimitedQuota(url) michael@0: { michael@0: removePermission("indexedDB-unlimited", url); michael@0: } michael@0: michael@0: function enableArchiveReader() michael@0: { michael@0: archiveReaderEnabled = SpecialPowers.getBoolPref("dom.archivereader.enabled"); michael@0: SpecialPowers.setBoolPref("dom.archivereader.enabled", true); michael@0: } michael@0: michael@0: function resetArchiveReader() michael@0: { michael@0: SpecialPowers.setBoolPref("dom.archivereader.enabled", archiveReaderEnabled); michael@0: } michael@0: michael@0: function enableExperimental() michael@0: { michael@0: SpecialPowers.setBoolPref("dom.indexedDB.experimental", true); michael@0: } michael@0: michael@0: function resetExperimental() michael@0: { michael@0: SpecialPowers.clearUserPref("dom.indexedDB.experimental"); michael@0: } michael@0: michael@0: function gc() michael@0: { michael@0: SpecialPowers.forceGC(); michael@0: SpecialPowers.forceCC(); michael@0: } michael@0: michael@0: function scheduleGC() michael@0: { michael@0: SpecialPowers.exactGC(window, continueToNextStep); michael@0: }