380 lines
9.5 KiB
JavaScript
380 lines
9.5 KiB
JavaScript
const BEHAVIOR_ACCEPT = 0;
|
|
const BEHAVIOR_REJECT_FOREIGN = 1;
|
|
const BEHAVIOR_REJECT = 2;
|
|
const BEHAVIOR_LIMIT_FOREIGN = 3;
|
|
|
|
const kPrefName = "network.cookie.cookieBehavior";
|
|
|
|
// Check if we are in frame, and declare ok and finishTest appropriately
|
|
const inFrame = ("" + location).match(/frame/);
|
|
if (inFrame) {
|
|
ok = function (a, message) {
|
|
if (!a) {
|
|
parent.postMessage("FAILURE: " + message, "http://mochi.test:8888");
|
|
} else {
|
|
parent.postMessage(message, "http://mochi.test:8888");
|
|
}
|
|
};
|
|
|
|
finishTest = function () {
|
|
parent.postMessage("done", "http://mochi.test:8888");
|
|
};
|
|
} else {
|
|
finishTest = function () {
|
|
SimpleTest.finish();
|
|
};
|
|
}
|
|
|
|
function setCookieBehavior(behavior) {
|
|
return SpecialPowers.pushPrefEnv({ set: [[kPrefName, behavior]] });
|
|
}
|
|
|
|
function runIFrame(url) {
|
|
return new Promise((resolve, reject) => {
|
|
function onMessage(e) {
|
|
if (e.data == "done") {
|
|
resolve();
|
|
window.removeEventListener("message", onMessage);
|
|
return;
|
|
}
|
|
|
|
const isFail = e.data.match(/^FAILURE/);
|
|
ok(!isFail, e.data + " (IFRAME = " + url + ")");
|
|
if (isFail) {
|
|
reject(e);
|
|
}
|
|
}
|
|
window.addEventListener("message", onMessage);
|
|
|
|
document.querySelector("iframe").src = url;
|
|
});
|
|
}
|
|
|
|
function runWorker(url) {
|
|
return new Promise((resolve, reject) => {
|
|
var worker = new Worker(url);
|
|
worker.addEventListener("message", function (e) {
|
|
if (e.data == "done") {
|
|
resolve();
|
|
return;
|
|
}
|
|
|
|
ok(!e.data.match(/^FAILURE/), e.data + " (WORKER = " + url + ")");
|
|
});
|
|
|
|
worker.addEventListener("error", function (e) {
|
|
ok(false, e.data + " (WORKER = " + url + ")");
|
|
reject(e);
|
|
});
|
|
});
|
|
}
|
|
|
|
function chromePower(allowed, blockSessionStorage) {
|
|
// localStorage is affected by storage policy.
|
|
try {
|
|
SpecialPowers.wrap(window).localStorage.getItem("X");
|
|
ok(allowed, "getting localStorage from chrome didn't throw");
|
|
} catch (e) {
|
|
ok(!allowed, "getting localStorage from chrome threw");
|
|
}
|
|
|
|
// sessionStorage is not. See bug 1183968.
|
|
try {
|
|
SpecialPowers.wrap(window).sessionStorage.getItem("X");
|
|
ok(!blockSessionStorage, "getting sessionStorage from chrome didn't throw");
|
|
} catch (e) {
|
|
ok(blockSessionStorage, "getting sessionStorage from chrome threw");
|
|
}
|
|
|
|
// indexedDB is affected by storage policy.
|
|
try {
|
|
SpecialPowers.wrap(window).indexedDB;
|
|
ok(allowed, "getting indexedDB from chrome didn't throw");
|
|
} catch (e) {
|
|
ok(!allowed, "getting indexedDB from chrome threw");
|
|
}
|
|
|
|
// Same with caches, along with the additional https-only requirement.
|
|
try {
|
|
var shouldResolve = allowed && location.protocol == "https:";
|
|
var promise = SpecialPowers.wrap(window).caches.keys();
|
|
ok(true, "getting caches from chrome should never throw");
|
|
return new Promise((resolve, reject) => {
|
|
promise.then(
|
|
function () {
|
|
ok(shouldResolve, "The promise was resolved for chrome");
|
|
resolve();
|
|
},
|
|
function (e) {
|
|
ok(!shouldResolve, "The promise was rejected for chrome: " + e);
|
|
resolve();
|
|
}
|
|
);
|
|
});
|
|
} catch (e) {
|
|
ok(false, "getting caches from chrome threw");
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
function storageAllowed() {
|
|
try {
|
|
localStorage.getItem("X");
|
|
ok(true, "getting localStorage didn't throw");
|
|
} catch (e) {
|
|
ok(false, "getting localStorage should not throw");
|
|
}
|
|
|
|
try {
|
|
sessionStorage.getItem("X");
|
|
ok(true, "getting sessionStorage didn't throw");
|
|
} catch (e) {
|
|
ok(false, "getting sessionStorage should not throw");
|
|
}
|
|
|
|
try {
|
|
indexedDB;
|
|
ok(true, "getting indexedDB didn't throw");
|
|
} catch (e) {
|
|
ok(false, "getting indexedDB should not throw");
|
|
}
|
|
|
|
const dbName = "db";
|
|
|
|
try {
|
|
var promise = caches.keys();
|
|
ok(true, "getting caches didn't throw");
|
|
|
|
return new Promise((resolve, reject) => {
|
|
const checkCacheKeys = () => {
|
|
promise.then(
|
|
() => {
|
|
ok(location.protocol == "https:", "The promise was not rejected");
|
|
resolve();
|
|
},
|
|
() => {
|
|
ok(
|
|
location.protocol !== "https:",
|
|
"The promise should not have been rejected"
|
|
);
|
|
resolve();
|
|
}
|
|
);
|
|
};
|
|
|
|
const checkDeleteDbAndTheRest = dbs => {
|
|
ok(
|
|
dbs.some(elem => elem.name === dbName),
|
|
"Expected database should be found"
|
|
);
|
|
|
|
const end = indexedDB.deleteDatabase(dbName);
|
|
end.onsuccess = checkCacheKeys;
|
|
end.onerror = err => {
|
|
ok(false, "querying indexedDB databases should not throw");
|
|
reject(err);
|
|
};
|
|
};
|
|
|
|
const checkDatabasesAndTheRest = () => {
|
|
indexedDB
|
|
.databases()
|
|
.then(checkDeleteDbAndTheRest)
|
|
.catch(err => {
|
|
ok(false, "deleting an indexedDB database should not throw");
|
|
reject(err);
|
|
});
|
|
};
|
|
|
|
const begin = indexedDB.open(dbName);
|
|
begin.onsuccess = checkDatabasesAndTheRest;
|
|
begin.onerror = err => {
|
|
ok(false, "opening an indexedDB database should not throw");
|
|
reject(err);
|
|
};
|
|
});
|
|
} catch (e) {
|
|
ok(location.protocol !== "https:", "getting caches should not have thrown");
|
|
return Promise.resolve();
|
|
}
|
|
}
|
|
|
|
function storagePrevented() {
|
|
try {
|
|
localStorage.getItem("X");
|
|
ok(false, "getting localStorage should have thrown");
|
|
} catch (e) {
|
|
ok(true, "getting localStorage threw");
|
|
}
|
|
|
|
if (location.hash == "#thirdparty") {
|
|
// No matter what the user's preferences are, we don't block
|
|
// sessionStorage in 3rd-party iframes. We do block them everywhere
|
|
// else however.
|
|
try {
|
|
sessionStorage.getItem("X");
|
|
ok(true, "getting sessionStorage didn't throw");
|
|
} catch (e) {
|
|
ok(false, "getting sessionStorage should not have thrown");
|
|
}
|
|
} else {
|
|
try {
|
|
sessionStorage.getItem("X");
|
|
ok(false, "getting sessionStorage should have thrown");
|
|
} catch (e) {
|
|
ok(true, "getting sessionStorage threw");
|
|
}
|
|
}
|
|
|
|
try {
|
|
indexedDB;
|
|
ok(true, "getting indexedDB didn't throw");
|
|
} catch (e) {
|
|
ok(false, "getting indexedDB should not have thrown");
|
|
}
|
|
|
|
const dbName = "album";
|
|
|
|
try {
|
|
indexedDB.open(dbName);
|
|
ok(false, "opening an indexedDB database didn't throw");
|
|
} catch (e) {
|
|
ok(true, "opening an indexedDB database threw");
|
|
ok(
|
|
e.name == "SecurityError",
|
|
"opening indexedDB database emitted a security error"
|
|
);
|
|
}
|
|
|
|
// Note: Security error is expected to be thrown synchronously.
|
|
indexedDB.databases().then(
|
|
() => {
|
|
ok(false, "querying indexedDB databases didn't reject");
|
|
},
|
|
e => {
|
|
ok(true, "querying indexedDB databases rejected");
|
|
ok(
|
|
e.name == "SecurityError",
|
|
"querying indexedDB databases emitted a security error"
|
|
);
|
|
}
|
|
);
|
|
|
|
try {
|
|
indexedDB.deleteDatabase(dbName);
|
|
ok(false, "deleting an indexedDB database didn't throw");
|
|
} catch (e) {
|
|
ok(true, "deleting an indexedDB database threw");
|
|
ok(
|
|
e.name == "SecurityError",
|
|
"deleting indexedDB database emitted a security error"
|
|
);
|
|
}
|
|
|
|
try {
|
|
var promise = caches.keys();
|
|
ok(true, "getting caches didn't throw");
|
|
|
|
return new Promise((resolve, reject) => {
|
|
promise.then(
|
|
function () {
|
|
ok(false, "The promise should have rejected");
|
|
resolve();
|
|
},
|
|
function () {
|
|
ok(true, "The promise was rejected");
|
|
resolve();
|
|
}
|
|
);
|
|
});
|
|
} catch (e) {
|
|
ok(location.protocol !== "https:", "getting caches should not have thrown");
|
|
|
|
return Promise.resolve();
|
|
}
|
|
}
|
|
|
|
function task(fn) {
|
|
if (!inFrame) {
|
|
SimpleTest.waitForExplicitFinish();
|
|
}
|
|
|
|
var gen = fn();
|
|
|
|
function next_step(val, e) {
|
|
var it;
|
|
try {
|
|
if (typeof e !== "undefined") {
|
|
it = gen.throw(e);
|
|
} else {
|
|
it = gen.next(val);
|
|
}
|
|
} catch (e) {
|
|
ok(false, "An error was thrown while stepping: " + e);
|
|
ok(false, "Stack: " + e.stack);
|
|
finishTest();
|
|
}
|
|
|
|
if (it.done) {
|
|
finishTest();
|
|
return;
|
|
}
|
|
it.value.then(next_step, e => next_step(null, e));
|
|
}
|
|
|
|
if (!gen.then) {
|
|
next_step();
|
|
} else {
|
|
gen.then(finishTest, e => {
|
|
ok(false, "An error was thrown while stepping: " + e);
|
|
ok(false, "Stack: " + e.stack);
|
|
finishTest();
|
|
});
|
|
}
|
|
}
|
|
|
|
// The test will run on a separate window in order to apply the new cookie jar settings.
|
|
async function runTestInWindow(test) {
|
|
let w = window.open("window_storagePermissions.html");
|
|
await new Promise(resolve => {
|
|
w.onload = e => {
|
|
resolve();
|
|
};
|
|
});
|
|
|
|
return new Promise((resolve, reject) => {
|
|
onmessage = e => {
|
|
if (!e.data.type) {
|
|
w.postMessage("FAILURE: " + e.data, document.referrer);
|
|
ok(false, "No error data type");
|
|
reject(e);
|
|
return;
|
|
}
|
|
|
|
if (e.data.type == "finish") {
|
|
w.close();
|
|
resolve();
|
|
return;
|
|
}
|
|
|
|
if (e.data.type == "check") {
|
|
const payload = e.data.msg ? e.data.msg : e.data;
|
|
ok(e.data.test, payload);
|
|
const isFail = payload.match(/^FAILURE/) || !e.data.test;
|
|
if (isFail) {
|
|
w.postMessage("FAILURE: " + e.data, document.referrer);
|
|
ok(false, payload);
|
|
w.close();
|
|
reject(e);
|
|
}
|
|
return;
|
|
}
|
|
|
|
ok(false, "Unknown message");
|
|
};
|
|
|
|
w.postMessage(test.toString(), "*");
|
|
});
|
|
}
|
|
|
|
var thirdparty = "https://example.com/tests/dom/tests/mochitest/general/";
|