mirror of
https://github.com/servo/servo.git
synced 2025-06-25 01:24:37 +01:00
212 lines
7.1 KiB
JavaScript
212 lines
7.1 KiB
JavaScript
'use strict';
|
|
|
|
function processQueryParams() {
|
|
const url = new URL(window.location);
|
|
const queryParams = url.searchParams;
|
|
return {
|
|
topLevelDocument: window === window.top,
|
|
testPrefix: queryParams.get("testCase") || "top-level-context",
|
|
};
|
|
}
|
|
|
|
// Create an iframe element, set it up using `setUpFrame`, and optionally fetch
|
|
// tests in it. Returns the created frame, after it has loaded.
|
|
async function CreateFrameHelper(setUpFrame, fetchTests) {
|
|
const frame = document.createElement('iframe');
|
|
const promise = new Promise((resolve, reject) => {
|
|
frame.onload = () => resolve(frame);
|
|
frame.onerror = reject;
|
|
});
|
|
|
|
setUpFrame(frame);
|
|
|
|
if (fetchTests) {
|
|
await fetch_tests_from_window(frame.contentWindow);
|
|
}
|
|
return promise;
|
|
}
|
|
|
|
// Create an iframe element with content loaded from `sourceURL`, append it to
|
|
// the document, and optionally fetch tests. Returns the loaded frame, once
|
|
// ready.
|
|
function CreateFrame(sourceURL, fetchTests = false) {
|
|
return CreateFrameHelper((frame) => {
|
|
frame.src = sourceURL;
|
|
document.body.appendChild(frame);
|
|
}, fetchTests);
|
|
}
|
|
|
|
// Create a new iframe with content loaded from `sourceURL`, and fetches tests.
|
|
// Returns the loaded frame, once ready.
|
|
function RunTestsInIFrame(sourceURL) {
|
|
return CreateFrame(sourceURL, true);
|
|
}
|
|
|
|
function RunTestsInNestedIFrame(sourceURL) {
|
|
return CreateFrameHelper((frame) => {
|
|
document.body.appendChild(frame);
|
|
frame.contentDocument.write(`
|
|
<script src="/resources/testharness.js"></script>
|
|
<script src="helpers.js"></script>
|
|
<body>
|
|
<script>
|
|
RunTestsInIFrame("${sourceURL}");
|
|
</script>
|
|
`);
|
|
frame.contentDocument.close();
|
|
}, true);
|
|
}
|
|
|
|
function RunRequestStorageAccessInDetachedFrame() {
|
|
const frame = document.createElement('iframe');
|
|
document.body.append(frame);
|
|
const inner_doc = frame.contentDocument;
|
|
frame.remove();
|
|
return inner_doc.requestStorageAccess();
|
|
}
|
|
|
|
function RunRequestStorageAccessViaDomParser() {
|
|
const parser = new DOMParser();
|
|
const doc = parser.parseFromString('<html></html>', 'text/html');
|
|
return doc.requestStorageAccess();
|
|
}
|
|
|
|
function RunCallbackWithGesture(callback) {
|
|
return test_driver.bless('run callback with user gesture', callback);
|
|
}
|
|
|
|
// Sends a message to the given target window and returns a promise that
|
|
// resolves when a reply was sent.
|
|
function PostMessageAndAwaitReply(message, targetWindow) {
|
|
const timestamp = window.performance.now();
|
|
const reply = ReplyPromise(timestamp);
|
|
targetWindow.postMessage({timestamp, ...message}, "*");
|
|
return reply;
|
|
}
|
|
|
|
// Returns a promise that resolves when the next "reply" is received via
|
|
// postMessage. Takes a "timestamp" argument to validate that the received
|
|
// message belongs to its original counterpart.
|
|
function ReplyPromise(timestamp) {
|
|
return new Promise((resolve) => {
|
|
const listener = (event) => {
|
|
if (event.data.timestamp == timestamp) {
|
|
window.removeEventListener("message", listener);
|
|
resolve(event.data.data);
|
|
}
|
|
};
|
|
window.addEventListener("message", listener);
|
|
});
|
|
}
|
|
|
|
// Returns a promise that resolves when the given frame fires its load event.
|
|
function LoadPromise(frame) {
|
|
return new Promise((resolve) => {
|
|
frame.addEventListener("load", (event) => {
|
|
resolve();
|
|
}, { once: true });
|
|
});
|
|
}
|
|
|
|
// Writes cookies via document.cookie in the given frame.
|
|
function SetDocumentCookieFromFrame(frame, cookie) {
|
|
return PostMessageAndAwaitReply(
|
|
{ command: "write document.cookie", cookie }, frame.contentWindow);
|
|
}
|
|
|
|
// Reads cookies via document.cookie in the given frame.
|
|
function GetJSCookiesFromFrame(frame) {
|
|
return PostMessageAndAwaitReply(
|
|
{ command: "document.cookie" }, frame.contentWindow);
|
|
}
|
|
|
|
async function DeleteCookieInFrame(frame, name, params) {
|
|
await SetDocumentCookieFromFrame(frame, `${name}=0; expires=${new Date(0).toUTCString()}; ${params};`);
|
|
assert_false(cookieStringHasCookie(name, '0', await GetJSCookiesFromFrame(frame)), `Verify that cookie '${name}' has been deleted.`);
|
|
}
|
|
|
|
// Tests whether the frame can write cookies via document.cookie. Note that this
|
|
// overwrites, then deletes, cookies named "cookie" and "foo".
|
|
//
|
|
// This function requires the caller to have included
|
|
// /cookies/resources/cookie-helper.sub.js.
|
|
async function CanFrameWriteCookies(frame) {
|
|
const cookie_suffix = "Secure;SameSite=None;Path=/";
|
|
await DeleteCookieInFrame(frame, "cookie", cookie_suffix);
|
|
await DeleteCookieInFrame(frame, "foo", cookie_suffix);
|
|
|
|
await SetDocumentCookieFromFrame(frame, `cookie=monster;${cookie_suffix}`);
|
|
await SetDocumentCookieFromFrame(frame, `foo=bar;${cookie_suffix}`);
|
|
|
|
const cookies = await GetJSCookiesFromFrame(frame);
|
|
const can_write = cookieStringHasCookie("cookie", "monster", cookies) &&
|
|
cookieStringHasCookie("foo", "bar", cookies);
|
|
|
|
await DeleteCookieInFrame(frame, "cookie", cookie_suffix);
|
|
await DeleteCookieInFrame(frame, "foo", cookie_suffix);
|
|
|
|
return can_write;
|
|
}
|
|
|
|
// Reads cookies via the `httpCookies` variable in the given frame.
|
|
function GetHTTPCookiesFromFrame(frame) {
|
|
return PostMessageAndAwaitReply(
|
|
{ command: "httpCookies" }, frame.contentWindow);
|
|
}
|
|
|
|
// Executes document.hasStorageAccess in the given frame.
|
|
function FrameHasStorageAccess(frame) {
|
|
return PostMessageAndAwaitReply(
|
|
{ command: "hasStorageAccess" }, frame.contentWindow);
|
|
}
|
|
|
|
// Executes document.requestStorageAccess in the given frame.
|
|
function RequestStorageAccessInFrame(frame) {
|
|
return PostMessageAndAwaitReply(
|
|
{ command: "requestStorageAccess" }, frame.contentWindow);
|
|
}
|
|
|
|
// Executes test_driver.set_permission in the given frame, with the provided
|
|
// arguments.
|
|
function SetPermissionInFrame(frame, args = []) {
|
|
return PostMessageAndAwaitReply(
|
|
{ command: "set_permission", args }, frame.contentWindow);
|
|
}
|
|
|
|
// Waits for a storage-access permission change and resolves with the current
|
|
// state.
|
|
function ObservePermissionChange(frame, args = []) {
|
|
return PostMessageAndAwaitReply(
|
|
{ command: "observe_permission_change", args }, frame.contentWindow);
|
|
}
|
|
|
|
// Executes `location.reload()` in the given frame. The returned promise
|
|
// resolves when the frame has finished reloading.
|
|
function FrameInitiatedReload(frame) {
|
|
const reload = LoadPromise(frame);
|
|
frame.contentWindow.postMessage({ command: "reload" }, "*");
|
|
return reload;
|
|
}
|
|
|
|
// Executes `location.href = url` in the given frame. The returned promise
|
|
// resolves when the frame has finished navigating.
|
|
function FrameInitiatedNavigation(frame, url) {
|
|
const load = LoadPromise(frame);
|
|
frame.contentWindow.postMessage({ command: "navigate", url }, "*");
|
|
return load;
|
|
}
|
|
|
|
// Tries to set storage access policy, ignoring any errors.
|
|
//
|
|
// Note: to discourage the writing of tests that assume unpartitioned cookie
|
|
// access by default, any test that calls this with `value` == "blocked" should
|
|
// do so as the first step in the test.
|
|
async function MaybeSetStorageAccess(origin, embedding_origin, value) {
|
|
try {
|
|
await test_driver.set_storage_access(origin, embedding_origin, value);
|
|
} catch (e) {
|
|
// Ignore, can be unimplemented if the platform blocks cross-site cookies
|
|
// by default. If this failed without default blocking we'll notice it later
|
|
// in the test.
|
|
}
|
|
}
|