<!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>
const HOST = get_host_info();
const BASE = new URL("resources", location).pathname;
async_test(t => {
const frame = document.createElement("iframe");
t.add_cleanup(() => frame.remove());
frame.src = "/common/blank.html";
document.body.append(frame);
// 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.body.localName, "body");
t.step_wait_func_done(() => frame.contentDocument === null);
}, `"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) => {
let payload = event.data;
assert_equals(payload, "loaded");
t.step_wait_func_done(() => frame.contentDocument === null);
});
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());
}, `"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.js", {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_js(t, 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`);
promise_test(t => {
const w = window.open();
return promise_rejects_js(t, w.TypeError, w.fetch(get_host_info().HTTPS_REMOTE_ORIGIN+"/common/blank.html", {mode: "no-cors"}));
}, `"require-corp" top-level: fetch() to response without CORP through a WindowProxy should fail`);
async_test(t => {
let w = window.open();
const frame = w.document.createElement("iframe");
t.add_cleanup(() => {
w.close();
frame.remove();
});
frame.src = "/common/blank.html";
document.body.append(frame);
// 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.body.localName, "body");
t.step_wait_func_done(() => frame.contentDocument === null);
}, `"require-corp" top-level: navigating an iframe to a page without CORP, through a WindowProxy, should fail`);
async_test(t => {
const frame = document.createElement("iframe");
const id = token();
t.add_cleanup(() => frame.remove());
window.addEventListener('message', t.step_func((e) => {
if (e.data === id) {
// Loaded!
t.done();
}
}));
// REMOTE_ORIGIN is cross-origin, same-site.
frame.src = `${HOST.HTTPS_REMOTE_ORIGIN}${BASE}/navigate-require-corp-same-site.sub.html?token=${id}`;
document.body.append(frame);
}, 'CORP: same-site is checked and allowed.');
async_test(t => {
const frame = document.createElement("iframe");
const id = token();
t.add_cleanup(() => frame.remove());
let loaded = false;
window.addEventListener('message', t.step_func((e) => {
if (e.data === id) {
loaded = true;
}
}));
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_false(loaded);
t.done();
}, 2000);
// NOTESAMESITE_ORIGIN is cross-origin, cross-site.
frame.src = `${HOST.HTTPS_NOTSAMESITE_ORIGIN}${BASE}/navigate-require-corp-same-site.sub.html?token=${id}`;
document.body.append(frame);
}, 'CORP: same-site is checked and blocked.');
async_test(t => {
const frame = document.createElement("iframe");
const bc = new BroadcastChannel(token());
t.add_cleanup(() => frame.remove());
bc.onmessage = t.step_func_done((event) => {
const payload = event.data;
assert_equals(payload, "loaded");
});
const dest = `${HOST.ORIGIN}${BASE}/navigate-require-corp.sub.html?channelName=${bc.name}`;
// REMOTE_ORIGIN is cross-origin, same-site.
frame.src = `${HOST.REMOTE_ORIGIN}${BASE}/navigate-require-corp-same-site.sub.html?to=${encodeURIComponent(dest)}`;
document.body.append(frame);
}, 'navigation CORP is checked with the parent frame, not the navigation source - to be allowed');
async_test(t => {
const frame = document.createElement("iframe");
const bc = new BroadcastChannel(token());
t.add_cleanup(() => frame.remove());
let loaded = false;
bc.onmessage = t.step_func((event) => {
loaded = true;
});
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_false(loaded);
t.done();
}, 2000);
const dest = `${HOST.REMOTE_ORIGIN}${BASE}/navigate-require-corp.sub.html?channelName=${bc.name}`;
// REMOTE_ORIGIN is cross-origin, same-site.
frame.src = `${HOST.REMOTE_ORIGIN}${BASE}/navigate-require-corp-same-site.sub.html?to=${encodeURIComponent(dest)}`;
document.body.append(frame);
}, 'navigation CORP is checked with the parent frame, not the navigation source - to be blocked');
async_test(t => {
const bc = new BroadcastChannel(token());
let loaded = false;
bc.onmessage = t.step_func((event) => {
loaded = true;
});
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_false(loaded);
t.done();
}, 2000);
const dest = `${HOST.ORIGIN}${BASE}/navigate-require-corp.sub.html?channelName=${bc.name}`;
const frame = document.createElement("iframe");
t.add_cleanup(() => frame.remove());
// |dest| is a same-origin URL and hence not blocked by CORP but reidirect.py
// is a cross-origin (actually cross-site) URL, so blocked by CORP.
frame.src = `${HOST.HTTPS_NOTSAMESITE_ORIGIN}/common/redirect.py?location=${encodeURIComponent(dest)}`;
document.body.append(frame);
}, 'navigation CORP is checked for each redirect');
</script>