Skip to content

Commit

Permalink
COOP and COEP tests
Browse files Browse the repository at this point in the history
See the added html/cross-origin-opener-policy/README.md for details. See #18354 for remaining work.
  • Loading branch information
annevk authored Aug 14, 2019
1 parent 33a1cca commit 5690096
Show file tree
Hide file tree
Showing 72 changed files with 785 additions and 501 deletions.
1 change: 1 addition & 0 deletions html/cross-origin-embedder-policy/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
See `../cross-origin-opener-policy/README.md`.
44 changes: 44 additions & 0 deletions html/cross-origin-embedder-policy/blob.https.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<!doctype html>
<meta charset=utf-8>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
<script src="/common/utils.js"></script>
<div id=log></div>
<script>
const origins = get_host_info();
[
{
"origin": origins.HTTPS_ORIGIN,
"crossOrigin": origins.HTTPS_REMOTE_ORIGIN
},
{
"origin": origins.HTTPS_REMOTE_ORIGIN,
"crossOrigin": origins.HTTPS_NOTSAMESITE_ORIGIN
},
{
"origin": origins.HTTPS_NOTSAMESITE_ORIGIN,
"crossOrigin": origins.HTTPS_ORIGIN
}
].forEach(({ origin, crossOrigin }) => {
["subframe", "navigate"].forEach(variant => {
async_test(t => {
const id = token();
const frame = document.createElement("iframe");
t.add_cleanup(() => { frame.remove(); });
const path = new URL("resources/blob-url-factory.html", window.location).pathname;
frame.src = `${origin}${path}?id=${id}&variant=${variant}&crossOrigin=${crossOrigin}`;
window.addEventListener("message", t.step_func(({ data }) => {
if (data.id !== id) {
return;
}
assert_equals(data.origin, origin);
assert_true(data.sameOriginNoCORPSuccess, "Same-origin without CORP did not succeed");
assert_true(data.crossOriginNoCORPFailure, "Cross-origin without CORP did not fail");
t.done();
}));
document.body.append(frame);
}, `Cross-Origin-Embedder-Policy and blob: URL from ${origin} in subframe via ${variant}`);
});
});
</script>
1 change: 1 addition & 0 deletions html/cross-origin-embedder-policy/blob.https.html.headers
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Cross-Origin-Embedder-Policy: require-corp
20 changes: 20 additions & 0 deletions html/cross-origin-embedder-policy/data.https.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!doctype html>
<meta charset=utf-8>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/script-factory.js"></script>
<div id=log></div>
<script>
async_test(t => {
window.addEventListener("message", t.step_func_done(({ data }) => {
assert_equals(data.id, "");
assert_equals(data.origin, "null");
assert_false(data.sameOriginNoCORPSuccess); // This is effectively a no-op for this test
assert_true(data.crossOriginNoCORPFailure, "Cross-origin without CORP did not fail");
}));
const frame = document.createElement("iframe");
t.add_cleanup(() => frame.remove());
frame.src = `data:text/html,${createScript("null", window.origin)}`;
document.body.append(frame);
}, "Cross-Origin-Embedder-Policy and data: URLs");
</script>
1 change: 1 addition & 0 deletions html/cross-origin-embedder-policy/data.https.html.headers
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Cross-Origin-Embedder-Policy: require-corp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!doctype html>
<meta charset=utf-8>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<div id=log></div>
<script>
async_test(t => {
const frame = document.createElement("iframe");
t.add_cleanup(() => frame.remove());
let i = 0;
frame.onload = t.step_func(() => {
i++;
assert_equals(frame.contentDocument.URL, "about:blank");
frame.src = "about:blank";
if (i == 2) {
t.done();
}
});
document.body.append(frame);
}, "Cross-Origin-Embedder-Policy and about:blank");
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Cross-Origin-Embedder-Policy: require-corp
79 changes: 79 additions & 0 deletions html/cross-origin-embedder-policy/none.https.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<!doctype html>
<meta name="timeout" content="long">
<title>Cross-Origin-Embedder-Policy header and nested navigable resource without such header</title>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src=/common/utils.js></script> <!-- Use token() to allow running tests in parallel -->
<div id=log></div>
<script>
async_test(t => {
const frame = document.createElement("iframe");
t.add_cleanup(() => frame.remove());
frame.onload = t.step_func_done(() => {
assert_not_equals(frame.contentDocument, null);
});
frame.src = "/common/blank.html";
document.body.append(frame);
assert_equals(frame.contentDocument.body.localName, "body");
}, `"none" top-level: navigating a frame to "none" should succeed`);

async_test(t => {
const frame = document.createElement("iframe");
t.add_cleanup(() => frame.remove());
const blank = "/common/blank.html";
let firstNavOk = false;
frame.onload = t.step_func(() => {
if (!firstNavOk) {
assert_not_equals(frame.contentDocument, null);
firstNavOk = true;
} else {
assert_not_equals(frame.contentDocument, null);
assert_equals(frame.contentWindow.location.pathname, blank);
t.done();
}
});
frame.src = `resources/navigate-require-corp.sub.html?to=${blank}`;
document.body.append(frame);
assert_equals(frame.contentDocument.body.localName, "body");
}, `"none" top-level: navigating a frame from "require-corp" to "none" should succeed`);

async_test(t => {
const w = window.open(`resources/navigate-none.sub.html?to=navigate-require-corp.sub.html`, "window_name");
t.add_cleanup(() => w.close());

t.step_timeout(() => {
w.history.back();
t.step_timeout(() => {
assert_not_equals(w.document, null);
t.done();
}, 500);
}, 500);
}, `"none" top-level: navigating a frame back from "require-corp" should succeed`);

async_test(t => {
let pageLoaded = false;
const bc = new BroadcastChannel(token());
let finished = false;
bc.onmessage = t.step_func((event) => {
pageLoaded = true;
let payload = event.data;
assert_equals(payload, "loaded");
});

const bc2 = new BroadcastChannel(token());
bc2.onmessage = t.step_func((event) => {
finished = true;
let payload = event.data;
assert_equals(payload, "loaded");
});

const win = window.open(`resources/navigate-require-corp.sub.html?channelName=${bc.name}&to=navigate-none.sub.html?channelName=${bc2.name}`, "_blank", "noopener");
assert_equals(win, null);

t.step_timeout(() => {
assert_true(pageLoaded);
assert_true(finished);
t.done();
}, 500);
}, `"require-corp" top-level noopener popup: navigating to "none" should succeed`);
</script>
1 change: 1 addition & 0 deletions html/cross-origin-embedder-policy/none.https.html.headers
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Cross-Origin-Embedder-Policy: unknown-should-be-parsed-as-null
138 changes: 138 additions & 0 deletions html/cross-origin-embedder-policy/require-corp.https.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
<!doctype html>
<meta name="timeout" content="long">
<title>Cross-Origin-Embedder-Policy header and nested navigable resource without such header</title>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src="/common/get-host-info.sub.js"></script>
<script src="/common/utils.js"></script> <!-- Use token() to allow running tests in parallel -->
<div id=log></div>
<script>
async_test(t => {
const frame = document.createElement("iframe");
t.add_cleanup(() => frame.remove());
t.step_timeout(() => {
// Make sure the iframe didn't load. See https://github.com/whatwg/html/issues/125 for why a
// timeout is used here. Long term all network error handling should be similar and have a
// reliable event.
assert_equals(frame.contentDocument, null);
t.done();
}, 500);
frame.src = "/common/blank.html";
document.body.append(frame);
assert_equals(frame.contentDocument.body.localName, "body");
}, `"require-corp" top-level: navigating a frame to "none" should fail`);

async_test(t => {
const frame = document.createElement("iframe");
t.add_cleanup(() => frame.remove());
const bc = new BroadcastChannel(token());
bc.onmessage = t.step_func((event) => {
assert_not_equals(frame.contentDocument, null);
let payload = event.data;
assert_equals(payload, "loaded");
t.step_timeout(() => {
assert_equals(frame.contentDocument, null);
t.done();
}, 500);
});
frame.src = `resources/navigate-require-corp.sub.html?channelName=${bc.name}&to=/common/blank.html`;
document.body.append(frame);
assert_equals(frame.contentDocument.body.localName, "body");
}, `"require-corp" top-level: navigating a frame from "require-corp" to "none" should fail`);

async_test(t => {
let pageLoaded = false;
const bc = new BroadcastChannel(token());
let finished = false;
bc.onmessage = t.step_func((event) => {
let payload = event.data;
assert_equals(payload, "loaded");
pageLoaded = true;
});

const bc2 = new BroadcastChannel(token());
bc2.onmessage = t.step_func_done((event) => {
let payload = event.data;
assert_equals(payload, "loaded");
assert_equals(pageLoaded, true);
});

const win = window.open(`resources/navigate-none.sub.html?channelName=${bc.name}&to=navigate-none.sub.html?channelName=${bc2.name}`, "_blank", "noopener");
assert_equals(win, null);
}, `"require-corp" top-level: creating a noopener "none" popup should succeed`);

async_test(t => {
let pageLoaded = false;
const bc = new BroadcastChannel(token());
bc.onmessage = t.step_func_done((event) => {
pageLoaded = true;
let payload = event.data;
assert_equals(payload, "loaded");
});

const win = window.open(`resources/navigate-none.sub.html?channelName=${bc.name}&to=/common/blank.html`, "_blank");
t.add_cleanup(() => win.close());
t.step_timeout(() => {
assert_equals(pageLoaded, true);
t.done();
}, 500);
}, `"require-corp" top-level: creating a "none" popup should succeed.`);

[
{
"name": "",
"title": "as popup"
},
{
"name": "noopener",
"title": "as noopener popup"
},
{
"name": "clear opener",
"title": "as popup with opener set to null"
}
].forEach(({name, title}) => {
async_test(t => {
let pageLoaded = false;
const bc = new BroadcastChannel(token());
bc.onmessage = t.step_func(event => {
pageLoaded = true;
const payload = event.data;
assert_equals(payload, "loaded");
});

const bc2 = new BroadcastChannel(token());
bc2.onmessage = t.step_func_done(event => {
const payload = event.data;
assert_equals(payload, "loaded");
assert_equals(pageLoaded, true);
});

let clearOpener = "";
if (name === "clear opener") {
clearOpener = "&clearOpener=true"
}

let noopener = undefined;
if (name === "noopener") {
noopener = "noopener"
}

const win = window.open(`resources/navigate-require-corp.sub.html?channelName=${bc.name}${clearOpener}&to=navigate-none.sub.html?channelName=${bc2.name}`, "_blank", noopener);
if (name === "noopener") {
assert_equals(win, null);
} else {
t.add_cleanup(() => win.close());
}
}, `"require-corp" top-level (${title}): navigating to "none" should succeed`);
});

promise_test(async t => {
const response = await fetch(get_host_info().HTTPS_REMOTE_ORIGIN+"/html/cross-origin-embedder-policy/resources/nothing-cross-origin-corp.txt", {mode: "no-cors"});
assert_equals(response.type, "opaque");
}, `"require-corp" top-level: fetch() to CORP: cross-origin response should succeed`);

promise_test(t => {
return promise_rejects(t, new TypeError(), fetch(get_host_info().HTTPS_REMOTE_ORIGIN+"/common/blank.html", {mode: "no-cors"}));
}, `"require-corp" top-level: fetch() to response without CORP should fail`);
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Cross-Origin-Embedder-Policy: require-corp
17 changes: 17 additions & 0 deletions html/cross-origin-embedder-policy/resources/blob-url-factory.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<body>
<script src="script-factory.js"></script>
<script>
const query = new URLSearchParams(window.location.search);
const id = query.get("id");
const variant = query.get("variant");
const parent = (variant === "subframe") ? "parent.parent" : "parent";
const blob = new Blob([createScript(window.origin, query.get("crossOrigin"), parent, id)], { type: "text/html" });
const blobURL = URL.createObjectURL(blob);
if (variant === "subframe") {
const frame = document.createElement("iframe");
frame.src = blobURL;
document.body.append(frame);
} else {
window.location = blobURL;
}
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Resource-Policy: cross-origin
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Cross-Origin-Embedder-Policy: require-corp
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
nothing with cross-origin CORP
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Cross-Origin-Resource-Policy: cross-origin
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
nothing with same-origin CORP
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Cross-Origin-Resource-Policy: same-origin
23 changes: 23 additions & 0 deletions html/cross-origin-embedder-policy/resources/script-factory.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// This creates a serialized <script> element that is useful for blob/data/srcdoc-style tests.

function createScript(sameOrigin, crossOrigin, parent="parent", id="") {
return `<script>
const data = { id: "${id}",
origin: window.origin,
sameOriginNoCORPSuccess: false,
crossOriginNoCORPFailure: false };
function record(promise, token, expectation) {
return promise.then(() => data[token] = expectation, () => data[token] = !expectation);
}
const records = [
record(fetch("${crossOrigin}/common/blank.html", { mode: "no-cors" }), "crossOriginNoCORPFailure", false)
];
if ("${sameOrigin}" !== "null") {
records.push(record(fetch("${sameOrigin}/common/blank.html", { mode: "no-cors" }), "sameOriginNoCORPSuccess", true));
}
Promise.all(records).then(() => window.${parent}.postMessage(data, "*"));
<\/script>`;
}
Loading

0 comments on commit 5690096

Please sign in to comment.