diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
commit | 43a97878ce14b72f0981164f87f2e35e14151312 (patch) | |
tree | 620249daf56c0258faa40cbdcf9cfba06de2a846 /testing/web-platform/tests/html/cross-origin-opener-policy | |
parent | Initial commit. (diff) | |
download | firefox-43a97878ce14b72f0981164f87f2e35e14151312.tar.xz firefox-43a97878ce14b72f0981164f87f2e35e14151312.zip |
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/html/cross-origin-opener-policy')
214 files changed, 9588 insertions, 0 deletions
diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/META.yml b/testing/web-platform/tests/html/cross-origin-opener-policy/META.yml new file mode 100644 index 0000000000..b9d578d22f --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/META.yml @@ -0,0 +1,9 @@ +spec: https://html.spec.whatwg.org/multipage/origin.html#cross-origin-opener-policies +suggested_reviewers: + - mikewest + - jugglinmike + - arturjanc + - lweichselbaum + - hemeryar + - ParisMeuleman + - valenting diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/README.md b/testing/web-platform/tests/html/cross-origin-opener-policy/README.md new file mode 100644 index 0000000000..3f080c82d2 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/README.md @@ -0,0 +1,11 @@ +This directory as well as `../cross-origin-embedder-policy/` contains tests for `Cross-Origin-Opener-Policy` and `Cross-Origin-Embedder-Policy`. Some light background reading: + +* [COOP and COEP explained](https://docs.google.com/document/d/1zDlfvfTJ_9e8Jdc8ehuV4zMEu9ySMCiTGMS9y0GU92k/edit) +* [COOP processing model](https://gist.github.com/annevk/6f2dd8c79c77123f39797f6bdac43f3e) (also defines interaction with COEP) +* [COEP processing model](https://mikewest.github.io/corpp/) +* [Open COOP issues](https://github.com/whatwg/html/labels/topic%3A%20cross-origin-opener-policy) +* [Open COEP issues](https://github.com/whatwg/html/labels/topic%3A%20cross-origin-embedder-policy) + +Notes: + +* Top-level navigation to a `data:` URL does not work in Chrome and Firefox and is therefore not tested. (This should probably be standardized.) diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/blob-popup.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/blob-popup.https.html new file mode 100644 index 0000000000..eda150eb34 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/blob-popup.https.html @@ -0,0 +1,40 @@ +<!doctype html> +<title>Cross-Origin-Opener-Policy and a blob URL popup</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> +<script> +async_test(t => { + window.test = t; // Make the test available globally so the blob URL can use it + window.furtherPopup = null; + + const bc = new BroadcastChannel(token()); + bc.onmessage = t.step_func_done(({ data }) => { + assert_equals(data.name.length, 0); + assert_false(data.opener); + assert_true(furtherPopup.closed); + }); + + const blobContents = `<script> +const w = window.open("${get_host_info().HTTPS_REMOTE_ORIGIN}/html/cross-origin-opener-policy/resources/coop-coep.py?coop=x&coep=x&channel=${bc.name}", "${bc.name}"); +window.opener.furtherPopup = w; +<\/script>`; + const blob = new Blob([blobContents], { type: "text/html" }); + const blobURL = URL.createObjectURL(blob); + const popup = window.open(blobURL); + t.add_cleanup(() => { + // Close the popups once the test is complete. + // The browsing context of the second popup is closed hence use the + // broadcast channel to trigger the closure. + bc.postMessage("close"); + popup.close(); + }); + popup.onload = t.step_func(() => { + assert_equals(popup.opener, window); + assert_equals(popup.location.href, blobURL); + assert_equals(popup.document.URL, blobURL); + assert_equals(popup.origin, window.origin); + }); +}); +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/blob-popup.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/blob-popup.https.html.headers new file mode 100644 index 0000000000..46ad58d83b --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/blob-popup.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: same-origin diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/coep-blob-popup.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/coep-blob-popup.https.html new file mode 100644 index 0000000000..08f70181fc --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/coep-blob-popup.https.html @@ -0,0 +1,51 @@ +<!doctype html> +<title>Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy: blob URL popup</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src=/common/get-host-info.sub.js></script> +<script src=../cross-origin-embedder-policy/resources/script-factory.js></script> +<script> +["window.open()", "<a>", "<a rel=noopener>"].forEach(type => { + promise_test(t => { + const origins = get_host_info(); + const id = `tut mir leid ${type}`; + const blob = new Blob([`<script>${createScript(origins.ORIGIN, origins.HTTPS_REMOTE_ORIGIN, "channel", id)}<\/script>`], {type: "text/html"}); + const blobURL = URL.createObjectURL(blob); + const bc = new BroadcastChannel(id); + + if (type === "window.open()") { + const popup = window.open(blobURL); + t.add_cleanup(() => popup.close()); + popup.onload = t.step_func(() => { + assert_equals(popup.opener, window); + assert_equals(popup.location.href, blobURL); + assert_equals(popup.document.URL, blobURL); + assert_equals(popup.origin, window.origin); + }); + } else { + const a = document.createElement("a"); + a.target = type; + if (type === "<a rel=noopener>") { + a.rel = "noopener"; + } + a.href = blobURL; + a.click(); + } + + return new Promise(resolve => { + bc.onmessage = t.step_func(({ data }) => { + assert_equals(data.id, id); + assert_equals(data.origin, window.origin); + assert_true(data.sameOriginNoCORPSuccess, "Same-origin without CORP did not succeed"); + assert_true(data.crossOriginNoCORPFailure, "Cross-origin without CORP did not fail"); + if (type === "<a rel=noopener>") { + assert_false(data.opener, 'opener'); + } else { + assert_true(data.opener, 'opener'); + } + resolve(); + }); + }); + }, `COOP+COEP blob URL popup: ${type}`); +}); +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/coep-blob-popup.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/coep-blob-popup.https.html.headers new file mode 100644 index 0000000000..63b60e490f --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/coep-blob-popup.https.html.headers @@ -0,0 +1,2 @@ +Cross-Origin-Opener-Policy: same-origin +Cross-Origin-Embedder-Policy: require-corp diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/coep-navigate-popup.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/coep-navigate-popup.https.html new file mode 100644 index 0000000000..714a4b6c42 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/coep-navigate-popup.https.html @@ -0,0 +1,72 @@ +<!doctype html> +<title>Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy: a navigating popup</title> +<meta name=timeout content=long> +<meta name=variant content=?0-1> +<meta name=variant content=?2-3> +<meta name=variant content=?4-last> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/subset-tests.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="resources/common.js"></script> +<script> +[ + { + "title": "coop/coep", + "coop": "same-origin", + "coep": "require-corp", + "opener": true + }, + { + "title": "no coop/coep", + "coop": "", + "coep": "require-corp", + "opener": false + }, + { + "title": "coop/no coep", + "coop": "same-origin", + "coep": "", + "opener": false + }, + { + "title": "no coop/no coep", + "coop": "", + "coep": "", + "opener": false + }, + { + "title": "coop unsafe-none/coep", + "coop": "unsafe-none", + "coep": "require-corp", + "opener": false + }, + { + "title": "coop unsafe-none/no coep", + "coop": "unsafe-none", + "coep": "", + "opener": false + } +].forEach((variant, i) => { + // Only run specified variants + if (!shouldRunSubTest(i)) { + return; + } + + ["same-origin", "same-site"].forEach(site => { + const title = `Popup navigating to ${site} with ${variant.title}`; + const channel = title.replace(/ /g,"-"); + const navigateHost = site === "same-origin" ? SAME_ORIGIN : SAME_SITE; + const navigateURL = `${navigateHost.origin}/html/cross-origin-opener-policy/resources/coop-coep.py?coop=${variant.coop}&coep=${variant.coep}&channel=${channel}`; + const opener = site === "same-origin" ? variant.opener : false; + + async_test(t => { + // For each test we open a COOP: same-origin/COEP: require-corp document in a popup and then + // navigate that to either a same-origin (site=="same-origin") or same-site (site=="same-site") + // document whose COOP and COEP are set as per the top-most array. We then verify that this + // document has the correct opener for its specific setup. + url_test(t, `${SAME_ORIGIN.origin}/html/cross-origin-opener-policy/resources/coop-coep.py?coop=same-origin&coep=require-corp&navigate=${encodeURIComponent(navigateURL)}`, channel, opener); + }, title); + }); +}); +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/coep-navigate-popup.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/coep-navigate-popup.https.html.headers new file mode 100644 index 0000000000..63b60e490f --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/coep-navigate-popup.https.html.headers @@ -0,0 +1,2 @@ +Cross-Origin-Opener-Policy: same-origin +Cross-Origin-Embedder-Policy: require-corp diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/coep-redirect.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/coep-redirect.https.html new file mode 100644 index 0000000000..83f8f8a33d --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/coep-redirect.https.html @@ -0,0 +1,68 @@ +<!doctype html> +<title>Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy: redirects</title> +<meta name=timeout content=long> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="resources/common.js"></script> +<script> +const coopCOEPPath = new URL("resources/coop-coep.py", window.location).pathname; + +[ + { + "title": "coop/coep to coop/coep", + "redirectCOOP": "same-origin", + "redirectCOEP": "require-corp", + "coop": "same-origin", + "coep": "require-corp", + "opener": true + }, + { + "title": "coop/coep to no coop/coep", + "redirectCOOP": "same-origin", + "redirectCOEP": "require-corp", + "coop": "", + "coep": "require-corp", + "opener": false + }, + { + "title": "no coop/no coep to coop/coep", + "redirectCOOP": "", + "redirectCOEP": "", + "coop": "same-origin", + "coep": "require-corp", + "opener": false + }, + { + "title": "coop/no coep to coop/coep", + "redirectCOOP": "same-origin", + "redirectCOEP": "", + "coop": "same-origin", + "coep": "require-corp", + "opener": false + }, + { + "title": "coop unsafe-none/coep to coop/coep", + "redirectCOOP": "unsafe-none", + "redirectCOEP": "require-corp", + "coop": "same-origin", + "coep": "require-corp", + "opener": false + }, + { + "title": "coop unsafe-none/coep to coop unsafe-inherit/coep", + "redirectCOOP": "unsafe-none", + "redirectCOEP": "require-corp", + "coop": "unsafe-none", + "coep": "require-corp", + "opener": false + } +].forEach(variant => { + const title = `Redirect from ${variant.title}`; + async_test(t => { + const channel = title.replace(/ /g,"-"); + const redirectLocation = `${SAME_ORIGIN.origin}${coopCOEPPath}?coop=${variant.coop}&coep=${variant.coep}&channel=${channel}`; + url_test(t, `${SAME_ORIGIN.origin}${coopCOEPPath}?coop=${variant.redirectCOOP}&coep=${variant.redirectCOEP}&redirect=${encodeURIComponent(redirectLocation)}`, channel, variant.opener); + }, title); +}); +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/coep-redirect.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/coep-redirect.https.html.headers new file mode 100644 index 0000000000..63b60e490f --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/coep-redirect.https.html.headers @@ -0,0 +1,2 @@ +Cross-Origin-Opener-Policy: same-origin +Cross-Origin-Embedder-Policy: require-corp diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/coep-with-cross-origin.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/coep-with-cross-origin.https.html new file mode 100644 index 0000000000..3f6256bcd2 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/coep-with-cross-origin.https.html @@ -0,0 +1,44 @@ +<!doctype html> +<title>Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy</title> +<meta name=timeout content=long> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/utils.js"></script> +<script src="resources/common.js"></script> +<script src="resources/popup-test.js"></script> +<script> +[ + { + "title": "popup with coop/coep", + "coop": "same-origin", + "coep": "require-corp", + "opener": "severed" + }, + { + "title": "popup with coop unsafe-none/coep", + "coop": "unsafe-none", + "coep": "require-corp", + "opener": "severed" + }, + { + "title": "popup with coop unsafe-none without coep", + "coop": "unsafe-none", + "coep": "", + "opener": "severed" + }, + { + "title": "popup without coep", + "coop": "same-origin", + "coep": "", + "opener": "severed" + } +].forEach(variant => { + popup_test(`Cross-origin ${variant.title}`, CROSS_ORIGIN, { coop: variant.coop, coep: variant.coep }, variant.opener); +}); + +test(() => { + assert_true(window.crossOriginIsolated); +}, "Bonus: window.crossOriginIsolated"); +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/coep-with-cross-origin.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/coep-with-cross-origin.https.html.headers new file mode 100644 index 0000000000..63b60e490f --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/coep-with-cross-origin.https.html.headers @@ -0,0 +1,2 @@ +Cross-Origin-Opener-Policy: same-origin +Cross-Origin-Embedder-Policy: require-corp diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/coep-with-same-origin.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/coep-with-same-origin.https.html new file mode 100644 index 0000000000..66e7aaf88e --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/coep-with-same-origin.https.html @@ -0,0 +1,44 @@ +<!doctype html> +<title>Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy</title> +<meta name=timeout content=long> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/utils.js"></script> +<script src="resources/common.js"></script> +<script src="resources/popup-test.js"></script> +<script> +[ + { + "title": "popup with coop/coep", + "coop": "same-origin", + "coep": "require-corp", + "opener": "preserved" + }, + { + "title": "popup with coop unsafe-none/coep", + "coop": "unsafe-none", + "coep": "require-corp", + "opener": "severed" + }, + { + "title": "popup with coop unsafe-none without coep", + "coop": "unsafe-none", + "coep": "", + "opener": "severed" + }, + { + "title": "popup without coep", + "coop": "same-origin", + "coep": "", + "opener": "severed" + } +].forEach(variant => { + popup_test(`Same-origin ${variant.title}`, SAME_ORIGIN, { coop: variant.coop, coep: variant.coep }, variant.opener); +}); + +test(() => { + assert_true(window.crossOriginIsolated); +}, "Bonus: window.crossOriginIsolated"); +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/coep-with-same-origin.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/coep-with-same-origin.https.html.headers new file mode 100644 index 0000000000..63b60e490f --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/coep-with-same-origin.https.html.headers @@ -0,0 +1,2 @@ +Cross-Origin-Opener-Policy: same-origin +Cross-Origin-Embedder-Policy: require-corp diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/coep-with-same-site.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/coep-with-same-site.https.html new file mode 100644 index 0000000000..abce659790 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/coep-with-same-site.https.html @@ -0,0 +1,44 @@ +<!doctype html> +<title>Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy</title> +<meta name=timeout content=long> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/utils.js"></script> +<script src="resources/common.js"></script> +<script src="resources/popup-test.js"></script> +<script> +[ + { + "title": "popup with coop/coep", + "coop": "same-origin", + "coep": "require-corp", + "opener": "severed" + }, + { + "title": "popup with coop unsafe-none/coep", + "coop": "unsafe-none", + "coep": "require-corp", + "opener": "severed" + }, + { + "title": "popup with coop unsafe-none without coep", + "coop": "unsafe-none", + "coep": "", + "opener": "severed" + }, + { + "title": "popup without coep", + "coop": "same-origin", + "coep": "", + "opener": "severed" + } +].forEach(variant => { + popup_test(`Same-site ${variant.title}`, SAME_SITE, { coop: variant.coop, coep: variant.coep }, variant.opener); +}); + +test(() => { + assert_true(window.crossOriginIsolated); +}, "Bonus: window.crossOriginIsolated"); +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/coep-with-same-site.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/coep-with-same-site.https.html.headers new file mode 100644 index 0000000000..63b60e490f --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/coep-with-same-site.https.html.headers @@ -0,0 +1,2 @@ +Cross-Origin-Opener-Policy: same-origin +Cross-Origin-Embedder-Policy: require-corp diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/coop-coep-sandbox.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/coop-coep-sandbox.https.html new file mode 100644 index 0000000000..4b94435119 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/coop-coep-sandbox.https.html @@ -0,0 +1,59 @@ +<!doctype html> +<title>Sandboxed Cross-Origin-Opener-Policy popup should result in a network error</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> +<script> +[ + "allow-popups allow-scripts allow-same-origin", + "allow-popups allow-scripts", +].forEach(sandboxValue => { + async_test(t => { + const frame = document.createElement("iframe"); + const channel = new BroadcastChannel(token()); + channel.onmessage = t.unreached_func("A COOP popup was created from a sandboxed frame"); + t.add_cleanup(() => frame.remove()); + frame.sandbox = sandboxValue; + frame.srcdoc = `<script> + const popup = window.open("resources/coop-coep.py?coop=same-origin&coep=&channel=${channel.name}"); + <\/script>`; + document.body.append(frame); + addEventListener('load', t.step_func(() => { + // This uses a timeout to give some time for incorrect implementations to broadcast. A + // theoretical testdriver.js API for browsing contexts could be used to speed this up. + t.step_timeout(() => { + t.done() + }, 1500); + })); + }, `<iframe sandbox="${sandboxValue}"> ${document.title}`); +}); + +// Verify that the popup does not have sandboxing flags set +async_test(t => { + const frame = document.createElement("iframe"); + const channel = new BroadcastChannel(token()); + channel.onmessage = t.step_func_done(); + t.add_cleanup(() => frame.remove()); + frame.sandbox = "allow-popups allow-scripts allow-popups-to-escape-sandbox"; + frame.srcdoc = `<script> +window.open("resources/coop-coep.py?coop=same-origin&coep=require-corp&channel=${channel.name}"); +<\/script>`; + document.body.append(frame); +}, `<iframe sandbox="allow-popups allow-scripts allow-popups-to-escape-sandbox"> ${document.title}`); + +async_test(t => { + const frame = document.createElement("iframe"); + const channel = new BroadcastChannel(token()); + frame.sandbox = "allow-scripts allow-same-origin"; + frame.name = `iframe-${channel.name}`; + frame.src = `resources/coop-coep.py?coop=same-origin&coep=require-corp&channel=${channel.name}`; + channel.onmessage = t.step_func( event => { + const payload = event.data; + assert_equals(payload.name, frame.name, "name"); + t.done(); + }); + t.add_cleanup(() => frame.remove()); + document.body.append(frame); +}, `Iframe with sandbox and COOP must load.`); +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/coop-coep-sandbox.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/coop-coep-sandbox.https.html.headers new file mode 100644 index 0000000000..4fff9d9fba --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/coop-coep-sandbox.https.html.headers @@ -0,0 +1,2 @@ +Cross-Origin-Opener-Policy: same-origin +Cross-Origin-Embedder-Policy: require-corp
\ No newline at end of file diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/coop-csp-sandbox-navigate.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/coop-csp-sandbox-navigate.https.html new file mode 100644 index 0000000000..be2d83214a --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/coop-csp-sandbox-navigate.https.html @@ -0,0 +1,40 @@ +<!doctype html> +<title>CSP sandbox popup navigate to Cross-Origin-Opener-Policy document should work</title> +<meta name="timeout" content="long"> +<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> +<script> +[ + "allow-popups allow-scripts allow-same-origin", + "allow-popups allow-scripts", +].forEach(sandboxValue => { + async_test(t => { + const channel = new BroadcastChannel(token()); + let popup; + channel.onmessage = t.step_func_done(e => { + assert_equals(e.data.name, '', 'e.data.name'); + assert_false(e.data.opener, 'e.data.opener'); + // `popup` is still the WindowProxy that holds the CSP sandbox document, not the + // after-navigation COOP document. The CSP sandbox only applies to the before navigation + // document/window. + assert_true(popup.closed, 'popup.closed'); + // Same-origin check (with the CSP sandbox document) should not throw when 'allow-same-origin' + if (sandboxValue.includes('allow-same-origin')) { + assert_true(!!popup.document, 'same-origin check'); + } else { + assert_throws_dom("SecurityError", () => { popup.document; }, 'same-origin check'); + } + }); + const navigateTo = `/html/cross-origin-opener-policy/resources/coop-coep.py?coop=same-origin&coep=&channel=${channel.name}`; + popup = window.open(`resources/csp-sandbox.py?coop=&coep=&sandbox=${sandboxValue}&channel=&navigate=${encodeURIComponent(navigateTo)}`, sandboxValue.replace(/ /g, '_')); + t.add_cleanup(() => { popup.close(); }); + addEventListener('load', t.step_func(() => { + t.step_timeout(() => { + assert_unreached('Navigation from CSP sandbox to COOP document failed') + }, 10000); + })); + }, `CSP: sandbox ${sandboxValue}; ${document.title}`); +}); +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/coop-csp-sandbox.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/coop-csp-sandbox.https.html new file mode 100644 index 0000000000..259d484df2 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/coop-csp-sandbox.https.html @@ -0,0 +1,24 @@ +<!doctype html> +<title>CSP sandboxed Cross-Origin-Opener-Policy popup should result in a network error</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> +<script> +[ + "allow-popups allow-scripts allow-same-origin", + "allow-popups allow-scripts", +].forEach(sandboxValue => { + async_test(t => { + const channel = new BroadcastChannel(token()); + channel.onmessage = t.unreached_func("A COOP popup was created from a CSP-sandboxed popup"); + const popup = window.open(`resources/csp-sandbox.py?coop=same-origin&coep=&sandbox=${sandboxValue}&channel=${channel.name}`); + t.add_cleanup(() => { popup.close(); }); + addEventListener('load', t.step_func(() => { + t.step_timeout(() => { + t.done() + }, 1500); + })); + }, `CSP: sandbox ${sandboxValue}; ${document.title}`); +}); +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/coop-navigate-same-origin-csp-sandbox.html b/testing/web-platform/tests/html/cross-origin-opener-policy/coop-navigate-same-origin-csp-sandbox.html new file mode 100644 index 0000000000..83113de376 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/coop-navigate-same-origin-csp-sandbox.html @@ -0,0 +1,63 @@ +<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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="./resources/common.js"></script> +<script> + +const executor_path = '/common/dispatcher/executor.html?pipe='; + +const https_origin = get_host_info().HTTPS_ORIGIN; +const coop_same_origin = + '|header(Cross-Origin-Opener-Policy,same-origin)'; +const csp_sandbox = + '|header(Content-Security-Policy, sandbox allow-scripts)'; + +promise_test(async test => { + const driver_token = token(); + + // 1. Start from a COOP:same-origin document. + const opener_token = token(); + const opener_url = https_origin + executor_path + coop_same_origin + + `&uuid=${opener_token}`; + const w = window.open(opener_url); + add_completion_callback(() => w.close()); + + // 2. It opens a popups, and then navigates the popup toward a same-origin + // COOP:same-origin document with CSP:sandbox + const openee_token = token(); + const openee_url = https_origin + executor_path + coop_same_origin + + csp_sandbox + `&uuid=${openee_token}`; + send(opener_token, ` + openee = window.open("${openee_url}"); + `); + add_completion_callback(() => send(openee_token, "close()")); + + // Because of CSP:sandbox, the popup is not considered same-origin with + // its openee. Check the openee/opener relationship is now closed. + send(openee_token, ` + if (opener) + send("${driver_token}", "Error: have opener"); + else + send("${driver_token}", "Success: no opener"); + `); + assert_equals(await receive(driver_token), "Success: no opener"); + + // Technically, the opener's "openee" WindowProxy should appear as closed at + // this time. The popup loaded a new document, and at least two fetch requests + // were made. This is more than enough. However, in theory, there is nothing + // to guarantee we can observe "openee.close". Wait a bit to ensure this will + // never flake. + await new Promise(r => test.step_timeout(r, 1000)); + + send(opener_token, ` + if (openee.closed) + send("${driver_token}", "Success: openee closed"); + else + send("${driver_token}", "Error: can still access openee"); + `); + assert_equals(await receive(driver_token), "Success: openee closed"); +}); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/coop-navigated-history-popup.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/coop-navigated-history-popup.https.html new file mode 100644 index 0000000000..a061be992c --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/coop-navigated-history-popup.https.html @@ -0,0 +1,18 @@ +<!doctype html> +<title>Cross-Origin-Opener-Policy: a navigating popup that then goes back in history</title> +<meta name=timeout content=long> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="resources/common.js"></script> +<script> +const title = `Popup navigating to other origin with COOP: same-origin and back in history`; +const channel = title.replace(/ /g,"-"); +const opener = false; +const openerDOMAccess = false; +const navigateURL = `${CROSS_ORIGIN.origin}/html/cross-origin-opener-policy/resources/coop-coep.py?coop=same-origin&coep=&navHistory=-1`; + +async_test(t => { + url_test(t, `${SAME_ORIGIN.origin}/html/cross-origin-opener-policy/resources/coop-coep.py?coop=&coep=&navigate=${encodeURIComponent(navigateURL)}&avoidBackAndForth=1&channel=${channel}`, channel, opener, openerDOMAccess); +}, title); +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/coop-navigated-popup.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/coop-navigated-popup.https.html new file mode 100644 index 0000000000..ef610a488f --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/coop-navigated-popup.https.html @@ -0,0 +1,37 @@ +<!doctype html> +<title>Cross-Origin-Opener-Policy: a navigated popup</title> +<!-- In particular this is different from coep-navigate-popup.https.html as this document initiates + the navigation (and uses same-origin-allow-popups and no COEP as without that it cannot be + observed). COOP should work identically, but implementations might have used the wrong + authority. --> +<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 --> +<script> +async_test(t => { + const noCOOP = "/common/blank.html"; + const popupName = token(); + const popup = window.open(noCOOP, popupName); + const channel = new BroadcastChannel(token()); + // Close the popup once the test is complete. + // The browsing context is closed after the navigation hence use the broadcast channel + // to trigger the closure. + t.add_cleanup(() => { + channel.postMessage("close"); + }); + popup.onload = t.step_func(() => { + assert_equals(popup.name, popupName); + assert_equals(new URL(popup.document.URL).pathname, noCOOP); + channel.onmessage = t.step_func_done(event => { + const payload = event.data; + // The name should be empty, but we're checking the length rather than a + // string comparison to "" to keep the random token out of error messages. + assert_equals(payload.name.length, 0); + assert_false(payload.opener); + assert_true(popup.closed); + }); + const coop = `resources/coop-coep.py?coop=same-origin&coep=&channel=${channel.name}`; + popup.location = coop; + }); +}, "Open a popup to a document without COOP, then navigate it to a document with"); +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/coop-navigated-popup.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/coop-navigated-popup.https.html.headers new file mode 100644 index 0000000000..d83ed86fb9 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/coop-navigated-popup.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: same-origin-allow-popups diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/coop-popup-opener-navigates.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/coop-popup-opener-navigates.https.html new file mode 100644 index 0000000000..a6c63654a9 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/coop-popup-opener-navigates.https.html @@ -0,0 +1,84 @@ +<!doctype html> +<title> + Cross-Origin-Opener-Policy: opener is lost because the opener navigates. +</title> +<!-- + COOP tests usually assume that the opener is lost because it navigated to a + page that triggered a browsing context group swap. It can also happen when + the opener navigates instead. This test verifies the behavior. +--> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/utils.js"></script> +<script src="resources/common.js"></script> +<script> + +const executor_path = "/common/dispatcher/executor.html?pipe="; +const coop_same_origin_header = + '|header(Cross-Origin-Opener-Policy,same-origin)'; +const coop_unsafe_none_header = + '|header(Cross-Origin-Opener-Policy,unsafe-none)'; + +function getExecutorPath(uuid, origin, coop_header) { + return origin.origin + executor_path + coop_header + `&uuid=${uuid}`; +} + +// Note: Because we can not navigate the main page to verify the behavior, +// we instead create another layer of popup, and navigate the intermediate +// one. We can verify the opener behavior from this page, and the openee +// behavior from the second popup. +promise_test(async t => { + // Set up dispatcher communications. + const first_popup_token = token(); + const post_navigate_first_popup_token = token(); + const second_popup_token = token(); + const reply_token = token(); + + const first_popup_url = getExecutorPath( + first_popup_token, + SAME_ORIGIN, + coop_same_origin_header); + + const post_navigate_first_popup_url = getExecutorPath( + post_navigate_first_popup_token, + SAME_ORIGIN, + coop_unsafe_none_header); + + const second_popup_url = getExecutorPath( + second_popup_token, + SAME_ORIGIN, + coop_same_origin_header); + + // We open the first popup and then ping it, it will respond after loading. + const first_popup = window.open(first_popup_url); + send(first_popup_token, `send('${reply_token}', 'Popup loaded');`); + assert_equals(await receive(reply_token), "Popup loaded"); + + // We open the second popup and the ping it, it will respond after loading. + send(first_popup_token, + `opener.second_popup_url = window.open('${second_popup_url}');`); + send(second_popup_token, `send('${reply_token}', 'Popup loaded');`); + assert_equals(await receive(reply_token), "Popup loaded"); + + // Both popups are now loaded. We navigate the middle one to a page that + // does not have COOP, this should trigger a browsing context group swap. + send(first_popup_token, `location.href = '${post_navigate_first_popup_url}'`); + send(post_navigate_first_popup_token, + `send('${reply_token}', 'Popup navigated');`); + assert_equals(await receive(reply_token), "Popup navigated"); + + // Give some time for things to settle across processes etc. before + // proceeding with verifications. + await new Promise((resolve, reject) => { t.step_timeout(resolve, 1500); }); + + // The reference held by the main page to the first popup should be closed. + assert_equals(first_popup.closed, true); + + // The second popup, opened by the first one should have its opener unset. + send(second_popup_token, `send('${reply_token}', opener);`); + assert_equals(await receive(reply_token), ""); + +}, "Verify that having the opener navigate instead of the openee also triggers COOP swaps."); + </script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/coop-popup-opener-navigates.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/coop-popup-opener-navigates.https.html.headers new file mode 100644 index 0000000000..46ad58d83b --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/coop-popup-opener-navigates.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: same-origin diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/coop-same-origin-allow-popups-document-write.html b/testing/web-platform/tests/html/cross-origin-opener-policy/coop-same-origin-allow-popups-document-write.html new file mode 100644 index 0000000000..82dd4541b6 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/coop-same-origin-allow-popups-document-write.html @@ -0,0 +1,62 @@ +<!doctype html> +<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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script> + +/* + Regression test for: https://crbug.com/1216244 + From a window using Cross-Origin-Opener-Policy:same-origin-allow-popup, open + a new blank window and navigate it cross-origin using document.write and a + meta refresh. The openee/opener relationship must hold. +*/ + +const executor_path = '/common/dispatcher/executor.html?pipe='; +const coep_soap = + "|header(Cross-Origin-Opener-Policy,same-origin-allow-popups)"; +const same_origin = get_host_info().HTTPS_ORIGIN; +const cross_origin = get_host_info().HTTPS_REMOTE_ORIGIN; + +promise_test(async t => { + // This window: + const this_window_token = token(); + + // The opener, using COEP:same-origin-allow-popups: + const opener_token = token(); + const opener_url = same_origin + executor_path + coep_soap + + `&uuid=${opener_token}`; + const opener = window.open(opener_url); + + // Open a blank window, then use document.write and a meta refresh to navigate + // cross-origin. + const openee_token = token(); + const openee_url = cross_origin + executor_path + `&uuid=${openee_token}`; + send(opener_token, ` + openee = window.open(); + openee.document.write(\` + <meta http-equiv="refresh" content="0; url=${openee_url}"> + \`); + openee.document.close(); + `); + + // Check the openee is loaded without access to the opener. + send(openee_token, ` + send("${this_window_token}", opener == null) + `); + assert_equals(await receive(this_window_token), "true", "opener == null"); + + // To get the state of the openee reflected into the opener's process, waiting + // for the openee' document to load and the various fetch() with the + // dispatcher should be largely enough. However these aren't causal guarantee. + // So wait a bit to be sure: + await new Promise(r => t.step_timeout(r, 1000)); + + // Check the opener see the openee as 'closed' after the navigation. + send(opener_token, ` + send("${this_window_token}", openee.closed) + `); + assert_equals(await receive(this_window_token), "true", "openee.closed"); +}); +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/coop-sandbox-cuts-opener.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/coop-sandbox-cuts-opener.https.html new file mode 100644 index 0000000000..47e6d0d6fe --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/coop-sandbox-cuts-opener.https.html @@ -0,0 +1,66 @@ +<!doctype html> +<title> + Sandboxed Cross-Origin-Opener-Policy popup should cut the opener if necessary +</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/utils.js"></script> +<script src="resources/common.js"></script> +<body> +<script> +const executor_path = "/common/dispatcher/executor.html?pipe="; +const coop_same_origin_header = + '|header(Cross-Origin-Opener-Policy,same-origin)'; +const coop_unsafe_none_header = + '|header(Cross-Origin-Opener-Policy,unsafe-none)'; + +function getExecutorPath(uuid, origin, coop_header) { + return origin.origin + executor_path + coop_header + `&uuid=${uuid}`; +} + +[ + "allow-popups allow-scripts allow-same-origin", + "allow-popups allow-scripts", +].forEach(sandboxValue => { + async_test(t => { + // Set up dispatcher communications. + const iframe_token = token(); + const popup_token = token(); + const main_frame_token_for_popup = token(); + const main_frame_token_for_iframe = token(); + + // Create a sandboxed iframe. + const iframe = document.createElement("iframe"); + iframe.sandbox = sandboxValue; + iframe.src = getExecutorPath(iframe_token, SAME_ORIGIN, + coop_unsafe_none_header); + document.body.append(iframe); + t.add_cleanup(() => iframe.remove()); + + // Open a COOP popup from the sandboxed iframe. + const popup_url = getExecutorPath(popup_token, + SAME_ORIGIN, + coop_same_origin_header); + send(iframe_token, `window.popup = window.open('${popup_url}')`); + + // This should fail. We ping the popup, if we get an answer it loaded. + send(popup_token, ` + send('${main_frame_token_for_popup}', 'Popup loaded'); + `); + receive(main_frame_token_for_popup) + .then(t.unreached_func("A COOP popup was created from a sandboxed frame")); + + // We delay probing the popup.closed property to give it time to settle. + t.step_timeout(() => { + send(iframe_token, + `send('${main_frame_token_for_iframe}', window.popup.closed);`); + }, 1500); + receive(main_frame_token_for_iframe) + .then(t.step_func_done(data => assert_equals(data, "true"))); + + }, `<iframe sandbox="${sandboxValue}"> ${document.title}`); +}); +</script> +</body> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/coop-sandbox-redirects-cuts-opener.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/coop-sandbox-redirects-cuts-opener.https.html new file mode 100644 index 0000000000..01f60b425d --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/coop-sandbox-redirects-cuts-opener.https.html @@ -0,0 +1,68 @@ +<!doctype html> +<title> + Sandboxed Cross-Origin-Opener-Policy popup should cut the opener if necessary + including during redirects. +</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/utils.js"></script> +<script src="resources/common.js"></script> +<body> +<script> +const executor_path = "/common/dispatcher/executor.html?pipe="; +const coop_same_origin_header = + '|header(Cross-Origin-Opener-Policy,same-origin)'; +const coop_unsafe_none_header = + '|header(Cross-Origin-Opener-Policy,unsafe-none)'; + +function getExecutorPath(uuid, origin) { + return origin.origin + executor_path + `&uuid=${uuid}`; +} + +[ + "allow-popups allow-scripts allow-same-origin", + "allow-popups allow-scripts", +].forEach(sandboxValue => { + async_test(t => { + // Set up dispatcher communications. + const iframe_token = token(); + const popup_token = token(); + const main_frame_token_for_popup = token(); + const main_frame_token_for_iframe = token(); + + // Create a sandboxed iframe. + const iframe = document.createElement("iframe"); + iframe.sandbox = sandboxValue; + iframe.src = getExecutorPath(iframe_token, SAME_ORIGIN); + document.body.append(iframe); + t.add_cleanup(() => iframe.remove()); + + // Open a COOP popup from the sandboxed iframe. + // Instead of navigating directly we go through a redirect. + const popup_url = getExecutorPath(popup_token, SAME_ORIGIN); + const redirect_url = SAME_ORIGIN.origin + "/common/redirect.py?pipe=" + + coop_same_origin_header + "&location=" + + encodeURIComponent(popup_url); + send(iframe_token, `window.popup = window.open('${redirect_url}')`); + + // This should fail. We ping the popup, if we get an answer it loaded. + send(popup_token, ` + send('${main_frame_token_for_popup}', 'Popup loaded'); + `); + receive(main_frame_token_for_popup) + .then(t.unreached_func("A COOP popup was created from a sandboxed frame")); + + // We delay probing the popup.closed property to give it time to settle. + t.step_timeout(() => { + send(iframe_token, + `send('${main_frame_token_for_iframe}', window.popup.closed);`); + }, 1500); + receive(main_frame_token_for_iframe) + .then(t.step_func_done(data => assert_equals(data, "true"))); + + }, `<iframe sandbox="${sandboxValue}"> ${document.title}`); +}); +</script> +</body> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/coop-sandbox.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/coop-sandbox.https.html new file mode 100644 index 0000000000..6f250c1b09 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/coop-sandbox.https.html @@ -0,0 +1,59 @@ +<!doctype html> +<title>Sandboxed Cross-Origin-Opener-Policy popup should result in a network error</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> +<script> +[ + "allow-popups allow-scripts allow-same-origin", + "allow-popups allow-scripts", +].forEach(sandboxValue => { + async_test(t => { + const frame = document.createElement("iframe"); + const channel = new BroadcastChannel(token()); + channel.onmessage = t.unreached_func("A COOP popup was created from a sandboxed frame"); + t.add_cleanup(() => frame.remove()); + frame.sandbox = sandboxValue; + frame.srcdoc = `<script> + const popup = window.open("resources/coop-coep.py?coop=same-origin&coep=&channel=${channel.name}"); + <\/script>`; + document.body.append(frame); + addEventListener('load', t.step_func(() => { + // This uses a timeout to give some time for incorrect implementations to broadcast. A + // theoretical testdriver.js API for browsing contexts could be used to speed this up. + t.step_timeout(() => { + t.done() + }, 1500); + })); + }, `<iframe sandbox="${sandboxValue}"> ${document.title}`); +}); + +// Verify that the popup does not have sandboxing flags set +async_test(t => { + const frame = document.createElement("iframe"); + const channel = new BroadcastChannel(token()); + channel.onmessage = t.step_func_done(); + t.add_cleanup(() => frame.remove()); + frame.sandbox = "allow-popups allow-scripts allow-popups-to-escape-sandbox"; + frame.srcdoc = `<script> +window.open("resources/coop-coep.py?coop=same-origin&coep=&channel=${channel.name}"); +<\/script>`; + document.body.append(frame); +}, `<iframe sandbox="allow-popups allow-scripts allow-popups-to-escape-sandbox"> ${document.title}`); + +async_test(t => { + const frame = document.createElement("iframe"); + const channel = new BroadcastChannel(token()); + frame.sandbox = "allow-scripts allow-same-origin"; + frame.name = `iframe-${channel.name}`; + frame.src = `resources/coop-coep.py?coop=same-origin&coep=&channel=${channel.name}`; + channel.onmessage = t.step_func( event => { + const payload = event.data; + assert_equals(payload.name, frame.name, "name"); + t.done(); + }); + t.add_cleanup(() => frame.remove()); + document.body.append(frame); +}, `Iframe with sandbox and COOP must load.`); +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/coop-sandbox.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/coop-sandbox.https.html.headers new file mode 100644 index 0000000000..46ad58d83b --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/coop-sandbox.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: same-origin diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/header-parsing-failures.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/header-parsing-failures.https.html new file mode 100644 index 0000000000..55b126ff37 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/header-parsing-failures.https.html @@ -0,0 +1,90 @@ +<!doctype html> +<meta charset=utf-8> +<meta name=timeout content=long> +<meta name="variant" content="?1-4"> +<meta name="variant" content="?5-8"> +<meta name="variant" content="?9-12"> +<meta name="variant" content="?12-last"> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/subset-tests.js"></script> +<script src="/common/utils.js"></script> +<script src="resources/common.js"></script> +<script src="resources/popup-test.js"></script> +<script> + +[ + // None of the following should be recognized as "same-origin" (hence the + // preserved opener). + { + "title": "coop with semi-column", + "coop": "same-origin;", + }, + { + "title": "coop with vertical tab", + "coop": "\u000bsame-origin\u000b", + }, + { + "title": "coop with form feed", + "coop": "\u000csame-origin\u000c", + }, + { + "title": "coop with carriage return", + "coop": "\u000dsame-origin\u000d", + }, + { + "title": "coop with capital letter", + "coop": "Same-origin", + }, + { + "title": "coop with bad structured header 1", + "coop": "same-origin;\tfoo=bar", + }, + { + "title": "coop with bad structured header 2", + "coop": "same-origin ;foo=bar", + }, + { + "title": "coop with bad structured header 3", + "coop": "same-origin; foo=bar;", + }, + { + "title": "coop as a structured header 'string' item", + "coop": "\"same-origin\"", + }, + { + "title": "coop as a structured header 'byte sequence' item", + "coop": ":c2FtZS1vcmlnaW4=:", + }, + { + "title": "coop as a structured header 'boolean' item", + "coop": "?1", + }, + { + "title": "coop as a structured header 'integer or decimal' item", + "coop": "1", + }, + { + "title": "coop as an unrecognized structured header type", + "coop": "$same-origin", + }, + { + "title": "coop with duplicate value", + "coop": "same-origin same-origin", + }, + { + // Note: comma must be escaped here to not mess with the WPT pipe function. + "title": "coop with duplicate value, separated by a comma", + "coop": "same-origin\\,same-origin", + }, + { + "title": "coop with preceding asterisk character", + "coop": "*same-origin ", + } +].forEach(variant => { + subsetTest(popup_test, `Parsing ${variant.title}`, SAME_ORIGIN, { coop: variant.coop }, "preserved"); +}); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/header-parsing-non-ascii.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/header-parsing-non-ascii.https.html new file mode 100644 index 0000000000..b5f20f88f4 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/header-parsing-non-ascii.https.html @@ -0,0 +1,17 @@ +<!doctype html> +<meta charset=utf-8> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/utils.js"></script> +<script src="resources/common.js"></script> +<script src="resources/popup-test.js"></script> +<script> + popup_test( + `Simple document with non-ascii COOP header opening a same-origin popup`, + SAME_ORIGIN, + "unsafe-none", + "preserved"); +</script> + diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/header-parsing-non-ascii.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/header-parsing-non-ascii.https.html.headers new file mode 100644 index 0000000000..54e44a7113 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/header-parsing-non-ascii.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: same%FForigin diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/header-parsing-repeated.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/header-parsing-repeated.https.html new file mode 100644 index 0000000000..a1430cbf57 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/header-parsing-repeated.https.html @@ -0,0 +1,16 @@ +<!doctype html> +<meta charset=utf-8> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/utils.js"></script> +<script src="resources/common.js"></script> +<script src="resources/popup-test.js"></script> +<script> + popup_test( + `Simple document with duplicated COOP header opening a same-origin popup`, + SAME_ORIGIN, + "unsafe-none", + "preserved"); +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/header-parsing-repeated.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/header-parsing-repeated.https.html.headers new file mode 100644 index 0000000000..85c58be8a1 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/header-parsing-repeated.https.html.headers @@ -0,0 +1,2 @@ +Cross-Origin-Opener-Policy: same-origin +Cross-Origin-Opener-Policy: same-origin diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/header-parsing-successes.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/header-parsing-successes.https.html new file mode 100644 index 0000000000..8e055669ad --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/header-parsing-successes.https.html @@ -0,0 +1,44 @@ +<!doctype html> +<meta charset=utf-8> +<meta name=timeout content=long> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/utils.js"></script> +<script src="resources/common.js"></script> +<script src="resources/popup-test.js"></script> +<script> + +[ + // All of the following should be recognized as "same-origin" (hence the + // severed opener link). + { + "title": "coop with leading space", + "coop": " same-origin", + }, + { + "title": "coop with trailing space", + "coop": "same-origin ", + }, + { + "title": "coop with leading tab", + "coop": "\tsame-origin", + }, + { + "title": "coop with trailing tab", + "coop": "same-origin\t", + }, + { + "title": "coop with duplicate value, separated by semi-column", + "coop": "same-origin;same-origin", + }, + { + "title": "coop with valid structured header", + "coop": "same-origin; foo=bar", + } +].forEach(variant => { + popup_test(`Parsing ${variant.title}`, SAME_ORIGIN, { coop: variant.coop }, "severed"); +}); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/historical/coep-navigate-popup-unsafe-inherit.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/historical/coep-navigate-popup-unsafe-inherit.https.html new file mode 100644 index 0000000000..8368dc4c81 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/historical/coep-navigate-popup-unsafe-inherit.https.html @@ -0,0 +1,40 @@ +<!doctype html> +<title>Historical: Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy: a navigating popup</title> +<meta name=timeout content=long> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="../resources/common.js"></script> +<script src="/common/subset-tests.js"></script> +<script> +[ + { + "title": "coop unsafe-inherit/coep", + "coop": "unsafe-inherit", // historical value, equivalent to "unsafe-none" + "coep": "require-corp", + "opener": false + }, + { + "title": "coop unsafe-inherit/no coep", + "coop": "unsafe-inherit", // historical value, equivalent to "unsafe-none" + "coep": "", + "opener": false + } +].forEach((variant) => { + ["same-origin", "same-site"].forEach((site) => { + const title = `Popup navigating to ${site} with ${variant.title}`; + const channel = title.replace(/ /g,"-"); + const navigateHost = site === "same-origin" ? SAME_ORIGIN : SAME_SITE; + const navigateURL = `${navigateHost.origin}/html/cross-origin-opener-policy/resources/coop-coep.py?coop=${variant.coop}&coep=${variant.coep}&channel=${channel}`; + const opener = site === "same-origin" ? variant.opener : false; + + async_test(t => { + // For each test we open a COOP: same-origin/COEP: require-corp document in a popup and then + // navigate that to either a document with same origin (site=="same-origin") or + // not-same-origin (site=="same-site") whose COOP and COEP are set as per the top-most array. + // We then verify that this document has the correct opener for its specific setup. + url_test(t, `${SAME_ORIGIN.origin}/html/cross-origin-opener-policy/resources/coop-coep.py?coop=same-origin&coep=require-corp&navigate=${encodeURIComponent(navigateURL)}`, channel, opener); + }, title); + }); +}); +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-origin-unsafe-allow-outgoing-with-cross-origin.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-origin-unsafe-allow-outgoing-with-cross-origin.https.html new file mode 100644 index 0000000000..21e0875f41 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-origin-unsafe-allow-outgoing-with-cross-origin.https.html @@ -0,0 +1,58 @@ +<!doctype html> +<meta charset=utf-8> +<meta name=timeout content=long> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/utils.js"></script> +<script src="../resources/common.js"></script> +<script src="../resources/popup-test.js"></script> +<script> + +[ + { + "title": "popup with empty coop", + "coop": "", + "opener": "preserved" + }, + { + "title": "popup with coop unsafe-none", + "coop": "unsafe-none", + "opener": "preserved" + }, + { + "title": "popup with jibberish coop", + "coop": "jibberish", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop", + "coop": "same-site", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop 2", + "coop": "same-site unsafe-allow-outgoing", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop 3", + "coop": "same-origin unsafe-allow-outgoing", + "opener": "preserved" + }, + { + "title": "popup with coop same-origin", + "coop": "same-origin", + "opener": "severed" + }, + { + "title": "popup with coop same-origin-allow-popups", + "coop": "same-origin-allow-popups", + "opener": "severed" + } +].forEach(variant => { + popup_test(`Cross-origin ${variant.title}`, CROSS_ORIGIN, { coop: variant.coop }, variant.opener); +}); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-origin-unsafe-allow-outgoing-with-cross-origin.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-origin-unsafe-allow-outgoing-with-cross-origin.https.html.headers new file mode 100644 index 0000000000..a19f4400ce --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-origin-unsafe-allow-outgoing-with-cross-origin.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: same-origin unsafe-allow-outgoing diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-origin-unsafe-allow-outgoing-with-same-origin.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-origin-unsafe-allow-outgoing-with-same-origin.https.html new file mode 100644 index 0000000000..89b0b4934e --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-origin-unsafe-allow-outgoing-with-same-origin.https.html @@ -0,0 +1,58 @@ +<!doctype html> +<meta charset=utf-8> +<meta name=timeout content=long> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/utils.js"></script> +<script src="../resources/common.js"></script> +<script src="../resources/popup-test.js"></script> +<script> + +[ + { + "title": "popup with empty coop", + "coop": "", + "opener": "preserved" + }, + { + "title": "popup with coop unsafe-none", + "coop": "unsafe-none", + "opener": "preserved" + }, + { + "title": "popup with jibberish coop", + "coop": "jibberish", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop", + "coop": "same-site", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop 2", + "coop": "same-site unsafe-allow-outgoing", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop 3", + "coop": "same-origin unsafe-allow-outgoing", + "opener": "preserved" + }, + { + "title": "popup with coop same-origin", + "coop": "same-origin", + "opener": "severed" + }, + { + "title": "popup with coop same-origin-allow-popups", + "coop": "same-origin-allow-popups", + "opener": "severed" + } +].forEach(variant => { + popup_test(`Same-origin ${variant.title}`, SAME_ORIGIN, { coop: variant.coop }, variant.opener); +}); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-origin-unsafe-allow-outgoing-with-same-origin.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-origin-unsafe-allow-outgoing-with-same-origin.https.html.headers new file mode 100644 index 0000000000..a19f4400ce --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-origin-unsafe-allow-outgoing-with-same-origin.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: same-origin unsafe-allow-outgoing diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-origin-unsafe-allow-outgoing-with-same-site.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-origin-unsafe-allow-outgoing-with-same-site.https.html new file mode 100644 index 0000000000..fb3330365f --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-origin-unsafe-allow-outgoing-with-same-site.https.html @@ -0,0 +1,58 @@ +<!doctype html> +<meta charset=utf-8> +<meta name=timeout content=long> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/utils.js"></script> +<script src="../resources/common.js"></script> +<script src="../resources/popup-test.js"></script> +<script> + +[ + { + "title": "popup with empty coop", + "coop": "", + "opener": "preserved" + }, + { + "title": "popup with coop unsafe-none", + "coop": "unsafe-none", + "opener": "preserved" + }, + { + "title": "popup with jibberish coop", + "coop": "jibberish", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop", + "coop": "same-site", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop 2", + "coop": "same-site unsafe-allow-outgoing", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop 3", + "coop": "same-origin unsafe-allow-outgoing", + "opener": "preserved" + }, + { + "title": "popup with coop same-origin", + "coop": "same-origin", + "opener": "severed" + }, + { + "title": "popup with coop same-origin-allow-popups", + "coop": "same-origin-allow-popups", + "opener": "severed" + } +].forEach(variant => { + popup_test(`Same-site ${variant.title}`, SAME_SITE, { coop: variant.coop }, variant.opener); +}); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-origin-unsafe-allow-outgoing-with-same-site.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-origin-unsafe-allow-outgoing-with-same-site.https.html.headers new file mode 100644 index 0000000000..a19f4400ce --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-origin-unsafe-allow-outgoing-with-same-site.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: same-origin unsafe-allow-outgoing diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-site-unsafe-allow-outgoing-with-cross-origin.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-site-unsafe-allow-outgoing-with-cross-origin.https.html new file mode 100644 index 0000000000..21e0875f41 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-site-unsafe-allow-outgoing-with-cross-origin.https.html @@ -0,0 +1,58 @@ +<!doctype html> +<meta charset=utf-8> +<meta name=timeout content=long> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/utils.js"></script> +<script src="../resources/common.js"></script> +<script src="../resources/popup-test.js"></script> +<script> + +[ + { + "title": "popup with empty coop", + "coop": "", + "opener": "preserved" + }, + { + "title": "popup with coop unsafe-none", + "coop": "unsafe-none", + "opener": "preserved" + }, + { + "title": "popup with jibberish coop", + "coop": "jibberish", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop", + "coop": "same-site", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop 2", + "coop": "same-site unsafe-allow-outgoing", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop 3", + "coop": "same-origin unsafe-allow-outgoing", + "opener": "preserved" + }, + { + "title": "popup with coop same-origin", + "coop": "same-origin", + "opener": "severed" + }, + { + "title": "popup with coop same-origin-allow-popups", + "coop": "same-origin-allow-popups", + "opener": "severed" + } +].forEach(variant => { + popup_test(`Cross-origin ${variant.title}`, CROSS_ORIGIN, { coop: variant.coop }, variant.opener); +}); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-site-unsafe-allow-outgoing-with-cross-origin.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-site-unsafe-allow-outgoing-with-cross-origin.https.html.headers new file mode 100644 index 0000000000..ab7b289481 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-site-unsafe-allow-outgoing-with-cross-origin.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: same-site unsafe-allow-outgoing diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-site-unsafe-allow-outgoing-with-same-origin.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-site-unsafe-allow-outgoing-with-same-origin.https.html new file mode 100644 index 0000000000..89b0b4934e --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-site-unsafe-allow-outgoing-with-same-origin.https.html @@ -0,0 +1,58 @@ +<!doctype html> +<meta charset=utf-8> +<meta name=timeout content=long> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/utils.js"></script> +<script src="../resources/common.js"></script> +<script src="../resources/popup-test.js"></script> +<script> + +[ + { + "title": "popup with empty coop", + "coop": "", + "opener": "preserved" + }, + { + "title": "popup with coop unsafe-none", + "coop": "unsafe-none", + "opener": "preserved" + }, + { + "title": "popup with jibberish coop", + "coop": "jibberish", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop", + "coop": "same-site", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop 2", + "coop": "same-site unsafe-allow-outgoing", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop 3", + "coop": "same-origin unsafe-allow-outgoing", + "opener": "preserved" + }, + { + "title": "popup with coop same-origin", + "coop": "same-origin", + "opener": "severed" + }, + { + "title": "popup with coop same-origin-allow-popups", + "coop": "same-origin-allow-popups", + "opener": "severed" + } +].forEach(variant => { + popup_test(`Same-origin ${variant.title}`, SAME_ORIGIN, { coop: variant.coop }, variant.opener); +}); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-site-unsafe-allow-outgoing-with-same-origin.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-site-unsafe-allow-outgoing-with-same-origin.https.html.headers new file mode 100644 index 0000000000..ab7b289481 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-site-unsafe-allow-outgoing-with-same-origin.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: same-site unsafe-allow-outgoing diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-site-unsafe-allow-outgoing-with-same-site.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-site-unsafe-allow-outgoing-with-same-site.https.html new file mode 100644 index 0000000000..fb3330365f --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-site-unsafe-allow-outgoing-with-same-site.https.html @@ -0,0 +1,58 @@ +<!doctype html> +<meta charset=utf-8> +<meta name=timeout content=long> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/utils.js"></script> +<script src="../resources/common.js"></script> +<script src="../resources/popup-test.js"></script> +<script> + +[ + { + "title": "popup with empty coop", + "coop": "", + "opener": "preserved" + }, + { + "title": "popup with coop unsafe-none", + "coop": "unsafe-none", + "opener": "preserved" + }, + { + "title": "popup with jibberish coop", + "coop": "jibberish", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop", + "coop": "same-site", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop 2", + "coop": "same-site unsafe-allow-outgoing", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop 3", + "coop": "same-origin unsafe-allow-outgoing", + "opener": "preserved" + }, + { + "title": "popup with coop same-origin", + "coop": "same-origin", + "opener": "severed" + }, + { + "title": "popup with coop same-origin-allow-popups", + "coop": "same-origin-allow-popups", + "opener": "severed" + } +].forEach(variant => { + popup_test(`Same-site ${variant.title}`, SAME_SITE, { coop: variant.coop }, variant.opener); +}); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-site-unsafe-allow-outgoing-with-same-site.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-site-unsafe-allow-outgoing-with-same-site.https.html.headers new file mode 100644 index 0000000000..ab7b289481 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-site-unsafe-allow-outgoing-with-same-site.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: same-site unsafe-allow-outgoing diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-site-with-cross-origin.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-site-with-cross-origin.https.html new file mode 100644 index 0000000000..21e0875f41 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-site-with-cross-origin.https.html @@ -0,0 +1,58 @@ +<!doctype html> +<meta charset=utf-8> +<meta name=timeout content=long> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/utils.js"></script> +<script src="../resources/common.js"></script> +<script src="../resources/popup-test.js"></script> +<script> + +[ + { + "title": "popup with empty coop", + "coop": "", + "opener": "preserved" + }, + { + "title": "popup with coop unsafe-none", + "coop": "unsafe-none", + "opener": "preserved" + }, + { + "title": "popup with jibberish coop", + "coop": "jibberish", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop", + "coop": "same-site", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop 2", + "coop": "same-site unsafe-allow-outgoing", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop 3", + "coop": "same-origin unsafe-allow-outgoing", + "opener": "preserved" + }, + { + "title": "popup with coop same-origin", + "coop": "same-origin", + "opener": "severed" + }, + { + "title": "popup with coop same-origin-allow-popups", + "coop": "same-origin-allow-popups", + "opener": "severed" + } +].forEach(variant => { + popup_test(`Cross-origin ${variant.title}`, CROSS_ORIGIN, { coop: variant.coop }, variant.opener); +}); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-site-with-cross-origin.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-site-with-cross-origin.https.html.headers new file mode 100644 index 0000000000..34bd099a30 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-site-with-cross-origin.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: same-site diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-site-with-same-origin.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-site-with-same-origin.https.html new file mode 100644 index 0000000000..89b0b4934e --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-site-with-same-origin.https.html @@ -0,0 +1,58 @@ +<!doctype html> +<meta charset=utf-8> +<meta name=timeout content=long> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/utils.js"></script> +<script src="../resources/common.js"></script> +<script src="../resources/popup-test.js"></script> +<script> + +[ + { + "title": "popup with empty coop", + "coop": "", + "opener": "preserved" + }, + { + "title": "popup with coop unsafe-none", + "coop": "unsafe-none", + "opener": "preserved" + }, + { + "title": "popup with jibberish coop", + "coop": "jibberish", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop", + "coop": "same-site", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop 2", + "coop": "same-site unsafe-allow-outgoing", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop 3", + "coop": "same-origin unsafe-allow-outgoing", + "opener": "preserved" + }, + { + "title": "popup with coop same-origin", + "coop": "same-origin", + "opener": "severed" + }, + { + "title": "popup with coop same-origin-allow-popups", + "coop": "same-origin-allow-popups", + "opener": "severed" + } +].forEach(variant => { + popup_test(`Same-origin ${variant.title}`, SAME_ORIGIN, { coop: variant.coop }, variant.opener); +}); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-site-with-same-origin.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-site-with-same-origin.https.html.headers new file mode 100644 index 0000000000..34bd099a30 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-site-with-same-origin.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: same-site diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-site-with-same-site.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-site-with-same-site.https.html new file mode 100644 index 0000000000..fb3330365f --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-site-with-same-site.https.html @@ -0,0 +1,58 @@ +<!doctype html> +<meta charset=utf-8> +<meta name=timeout content=long> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/utils.js"></script> +<script src="../resources/common.js"></script> +<script src="../resources/popup-test.js"></script> +<script> + +[ + { + "title": "popup with empty coop", + "coop": "", + "opener": "preserved" + }, + { + "title": "popup with coop unsafe-none", + "coop": "unsafe-none", + "opener": "preserved" + }, + { + "title": "popup with jibberish coop", + "coop": "jibberish", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop", + "coop": "same-site", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop 2", + "coop": "same-site unsafe-allow-outgoing", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop 3", + "coop": "same-origin unsafe-allow-outgoing", + "opener": "preserved" + }, + { + "title": "popup with coop same-origin", + "coop": "same-origin", + "opener": "severed" + }, + { + "title": "popup with coop same-origin-allow-popups", + "coop": "same-origin-allow-popups", + "opener": "severed" + } +].forEach(variant => { + popup_test(`Same-site ${variant.title}`, SAME_SITE, { coop: variant.coop }, variant.opener); +}); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-site-with-same-site.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-site-with-same-site.https.html.headers new file mode 100644 index 0000000000..34bd099a30 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/historical/popup-same-site-with-same-site.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: same-site diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/iframe-popup-same-origin-allow-popups-to-same-origin-allow-popups.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/iframe-popup-same-origin-allow-popups-to-same-origin-allow-popups.https.html new file mode 100644 index 0000000000..099424790a --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/iframe-popup-same-origin-allow-popups-to-same-origin-allow-popups.https.html @@ -0,0 +1,88 @@ +<!doctype html> +<meta charset=utf-8> +<meta name=timeout content=long> +<meta name="variant" content="?1-2"> +<meta name="variant" content="?3-4"> +<meta name="variant" content="?5-6"> +<meta name="variant" content="?7-8"> +<meta name="variant" content="?9-last"> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src=/common/dispatcher/dispatcher.js></script> +<script src=/common/get-host-info.sub.js></script> +<script src=/common/subset-tests.js></script> +<script src=/common/utils.js></script> +<script src="resources/common.js"></script> +<script src="resources/iframe-test.js"></script> + +<body> +<script> +// This document has COOP: same-origin-allow-popups. The popup has COOP: +// same-origin-allow-popups. Therefore there should only be an opener and name +// if the frameOrigin and popupOrigin are same-origin with this document. +[ + { + "title": "same origin iframe, same origin popup", + "iframeOrigin": SAME_ORIGIN, + "popupOrigin": SAME_ORIGIN, + "opener": "preserved" + }, + { + "title": "same site iframe, same origin popup", + "iframeOrigin": SAME_SITE, + "popupOrigin": SAME_ORIGIN, + "opener": "severed" + }, + { + "title": "cross origin iframe, same origin popup", + "iframeOrigin": CROSS_ORIGIN, + "popupOrigin": SAME_ORIGIN, + "opener": "severed" + }, + { + "title": "same origin iframe, same site popup", + "iframeOrigin": SAME_ORIGIN, + "popupOrigin": SAME_SITE, + "opener": "severed" + }, + { + "title": "same site iframe, same site popup", + "iframeOrigin": SAME_SITE, + "popupOrigin": SAME_SITE, + "opener": "severed" + }, + { + "title": "cross origin iframe, same site popup", + "iframeOrigin": CROSS_ORIGIN, + "popupOrigin": SAME_SITE, + "opener": "severed" + }, + { + "title": "same origin iframe, cross origin popup", + "iframeOrigin": SAME_ORIGIN, + "popupOrigin": CROSS_ORIGIN, + "opener": "severed" + }, + { + "title": "same site iframe, cross origin popup", + "iframeOrigin": SAME_SITE, + "popupOrigin": CROSS_ORIGIN, + "opener": "severed" + }, + { + "title": "cross origin iframe, cross origin popup", + "iframeOrigin": CROSS_ORIGIN, + "popupOrigin": CROSS_ORIGIN, + "opener": "severed" + } +].forEach(variant => { + subsetTest( + iframe_test, + `COOP: same-origin-allow-popups to popup COOP: same-origin-allow-popups via an iframe, with ${variant.title}`, + variant.iframeOrigin, + variant.popupOrigin, + { coop: 'same-origin-allow-popups' }, + variant.opener); +}); +</script> +</body> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/iframe-popup-same-origin-allow-popups-to-same-origin-allow-popups.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/iframe-popup-same-origin-allow-popups-to-same-origin-allow-popups.https.html.headers new file mode 100644 index 0000000000..d83ed86fb9 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/iframe-popup-same-origin-allow-popups-to-same-origin-allow-popups.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: same-origin-allow-popups diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/iframe-popup-same-origin-allow-popups-to-same-origin.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/iframe-popup-same-origin-allow-popups-to-same-origin.https.html new file mode 100644 index 0000000000..34699c8d08 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/iframe-popup-same-origin-allow-popups-to-same-origin.https.html @@ -0,0 +1,86 @@ +<!doctype html> +<meta charset=utf-8> +<meta name=timeout content=long> +<meta name="variant" content="?1-2"> +<meta name="variant" content="?3-4"> +<meta name="variant" content="?5-6"> +<meta name="variant" content="?7-8"> +<meta name="variant" content="?9-last"> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src=/common/dispatcher/dispatcher.js></script> +<script src=/common/get-host-info.sub.js></script> +<script src=/common/subset-tests.js></script> +<script src=/common/utils.js></script> +<script src="resources/common.js"></script> +<script src="resources/iframe-test.js"></script> + +<body> +<script> +[ + { + "title": "same origin iframe, same origin popup", + "iframeOrigin": SAME_ORIGIN, + "popupOrigin": SAME_ORIGIN, + "opener": "severed" + }, + { + "title": "same site iframe, same origin popup", + "iframeOrigin": SAME_SITE, + "popupOrigin": SAME_ORIGIN, + "opener": "severed" + }, + { + "title": "cross origin iframe, same origin popup", + "iframeOrigin": CROSS_ORIGIN, + "popupOrigin": SAME_ORIGIN, + "opener": "severed" + }, + { + "title": "same origin iframe, same site popup", + "iframeOrigin": SAME_ORIGIN, + "popupOrigin": SAME_SITE, + "opener": "severed" + }, + { + "title": "same site iframe, same site popup", + "iframeOrigin": SAME_SITE, + "popupOrigin": SAME_SITE, + "opener": "severed" + }, + { + "title": "cross origin iframe, same site popup", + "iframeOrigin": CROSS_ORIGIN, + "popupOrigin": SAME_SITE, + "opener": "severed" + }, + { + "title": "same origin iframe, cross origin popup", + "iframeOrigin": SAME_ORIGIN, + "popupOrigin": CROSS_ORIGIN, + "opener": "severed" + }, + { + "title": "same site iframe, cross origin popup", + "iframeOrigin": SAME_SITE, + "popupOrigin": CROSS_ORIGIN, + "opener": "severed" + }, + { + "title": "cross origin iframe, cross origin popup", + "iframeOrigin": CROSS_ORIGIN, + "popupOrigin": CROSS_ORIGIN, + "opener": "severed" + } +].forEach(variant => { + subsetTest( + iframe_test, + `COOP: same-origin-allow-popups to popup COOP: same-origin via an iframe, with ${variant.title}`, + variant.iframeOrigin, + variant.popupOrigin, + { coop: 'same-origin' }, + variant.opener); +}); +</script> +</body> + diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/iframe-popup-same-origin-allow-popups-to-same-origin.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/iframe-popup-same-origin-allow-popups-to-same-origin.https.html.headers new file mode 100644 index 0000000000..d83ed86fb9 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/iframe-popup-same-origin-allow-popups-to-same-origin.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: same-origin-allow-popups diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/iframe-popup-same-origin-allow-popups-to-unsafe-none.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/iframe-popup-same-origin-allow-popups-to-unsafe-none.https.html new file mode 100644 index 0000000000..29fb5cfa2d --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/iframe-popup-same-origin-allow-popups-to-unsafe-none.https.html @@ -0,0 +1,85 @@ +<!doctype html> +<meta charset=utf-8> +<meta name=timeout content=long> +<meta name="variant" content="?1-2"> +<meta name="variant" content="?3-4"> +<meta name="variant" content="?5-6"> +<meta name="variant" content="?7-8"> +<meta name="variant" content="?9-last"> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src=/common/dispatcher/dispatcher.js></script> +<script src=/common/get-host-info.sub.js></script> +<script src=/common/subset-tests.js></script> +<script src=/common/utils.js></script> +<script src="resources/common.js"></script> +<script src="resources/iframe-test.js"></script> + +<body> +<script> +[ + { + "title": "same origin iframe, same origin popup", + "iframeOrigin": SAME_ORIGIN, + "popupOrigin": SAME_ORIGIN, + "opener": "preserved" + }, + { + "title": "same site iframe, same origin popup", + "iframeOrigin": SAME_SITE, + "popupOrigin": SAME_ORIGIN, + "opener": "preserved" + }, + { + "title": "cross origin iframe, same origin popup", + "iframeOrigin": CROSS_ORIGIN, + "popupOrigin": SAME_ORIGIN, + "opener": "preserved" + }, + { + "title": "same origin iframe, same site popup", + "iframeOrigin": SAME_ORIGIN, + "popupOrigin": SAME_SITE, + "opener": "preserved" + }, + { + "title": "same site iframe, same site popup", + "iframeOrigin": SAME_SITE, + "popupOrigin": SAME_SITE, + "opener": "preserved" + }, + { + "title": "cross origin iframe, same site popup", + "iframeOrigin": CROSS_ORIGIN, + "popupOrigin": SAME_SITE, + "opener": "preserved" + }, + { + "title": "same origin iframe, cross origin popup", + "iframeOrigin": SAME_ORIGIN, + "popupOrigin": CROSS_ORIGIN, + "opener": "preserved" + }, + { + "title": "same site iframe, cross origin popup", + "iframeOrigin": SAME_SITE, + "popupOrigin": CROSS_ORIGIN, + "opener": "preserved" + }, + { + "title": "cross origin iframe, cross origin popup", + "iframeOrigin": CROSS_ORIGIN, + "popupOrigin": CROSS_ORIGIN, + "opener": "preserved" + } +].forEach(variant => { + subsetTest( + iframe_test, + `COOP: same-origin-allow-popups to popup COOP: unsafe-none via an iframe, with ${variant.title}`, + variant.iframeOrigin, + variant.popupOrigin, + { coop: 'unsafe-none' }, + variant.opener); +}); +</script> +</body> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/iframe-popup-same-origin-allow-popups-to-unsafe-none.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/iframe-popup-same-origin-allow-popups-to-unsafe-none.https.html.headers new file mode 100644 index 0000000000..d83ed86fb9 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/iframe-popup-same-origin-allow-popups-to-unsafe-none.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: same-origin-allow-popups diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/iframe-popup-same-origin-to-same-origin.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/iframe-popup-same-origin-to-same-origin.https.html new file mode 100644 index 0000000000..7d31256584 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/iframe-popup-same-origin-to-same-origin.https.html @@ -0,0 +1,88 @@ +<!doctype html> +<meta charset=utf-8> +<meta name=timeout content=long> +<meta name="variant" content="?1-2"> +<meta name="variant" content="?3-4"> +<meta name="variant" content="?5-6"> +<meta name="variant" content="?7-8"> +<meta name="variant" content="?9-last"> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src=/common/dispatcher/dispatcher.js></script> +<script src=/common/get-host-info.sub.js></script> +<script src=/common/subset-tests.js></script> +<script src=/common/utils.js></script> +<script src="resources/common.js"></script> +<script src="resources/iframe-test.js"></script> + +<body> +<script> + +// This document has COOP "same-origin". The popup has COOP "same-origin". Therefore there should +// only be an opener and name if the frameOrigin and popupOrigin are same-origin with this document. +[ + { + "title": "same origin iframe, same origin popup", + "iframeOrigin": SAME_ORIGIN, + "popupOrigin": SAME_ORIGIN, + "opener": "preserved" + }, + { + "title": "same site iframe, same origin popup", + "iframeOrigin": SAME_SITE, + "popupOrigin": SAME_ORIGIN, + "opener": "noopener" + }, + { + "title": "cross origin iframe, same origin popup", + "iframeOrigin": CROSS_ORIGIN, + "popupOrigin": SAME_ORIGIN, + "opener": "noopener" + }, + { + "title": "same origin iframe, same site popup", + "iframeOrigin": SAME_ORIGIN, + "popupOrigin": SAME_SITE, + "opener": "severed" + }, + { + "title": "same site iframe, same site popup", + "iframeOrigin": SAME_SITE, + "popupOrigin": SAME_SITE, + "opener": "noopener" + }, + { + "title": "cross origin iframe, same site popup", + "iframeOrigin": CROSS_ORIGIN, + "popupOrigin": SAME_SITE, + "opener": "noopener" + }, + { + "title": "same origin iframe, cross origin popup", + "iframeOrigin": SAME_ORIGIN, + "popupOrigin": CROSS_ORIGIN, + "opener": "severed" + }, + { + "title": "same site iframe, cross origin popup", + "iframeOrigin": SAME_SITE, + "popupOrigin": CROSS_ORIGIN, + "opener": "noopener" + }, + { + "title": "cross origin iframe, cross origin popup", + "iframeOrigin": CROSS_ORIGIN, + "popupOrigin": CROSS_ORIGIN, + "opener": "noopener" + } +].forEach(variant => { + subsetTest( + iframe_test, + `COOP: same-origin to popup COOP: same-origin via an iframe, with ${variant.title}`, + variant.iframeOrigin, + variant.popupOrigin, + { coop: 'same-origin' }, + variant.opener); +}); +</script> +</body> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/iframe-popup-same-origin-to-same-origin.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/iframe-popup-same-origin-to-same-origin.https.html.headers new file mode 100644 index 0000000000..46ad58d83b --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/iframe-popup-same-origin-to-same-origin.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: same-origin diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/iframe-popup-same-origin-to-unsafe-none.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/iframe-popup-same-origin-to-unsafe-none.https.html new file mode 100644 index 0000000000..847f75665b --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/iframe-popup-same-origin-to-unsafe-none.https.html @@ -0,0 +1,87 @@ +<!doctype html> +<meta charset=utf-8> +<meta name=timeout content=long> +<meta name="variant" content="?1-2"> +<meta name="variant" content="?3-4"> +<meta name="variant" content="?5-6"> +<meta name="variant" content="?7-8"> +<meta name="variant" content="?9-last"> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src=/common/dispatcher/dispatcher.js></script> +<script src=/common/get-host-info.sub.js></script> +<script src=/common/subset-tests.js></script> +<script src=/common/utils.js></script> +<script src="resources/common.js"></script> +<script src="resources/iframe-test.js"></script> + +<body> +<script> +// This document has COOP: same-origin. The popup has no COOP. Therefore there +// should be no opener or name. +[ + { + "title": "same origin iframe, same origin popup", + "iframeOrigin": SAME_ORIGIN, + "popupOrigin": SAME_ORIGIN, + "opener": "severed" + }, + { + "title": "same site iframe, same origin popup", + "iframeOrigin": SAME_SITE, + "popupOrigin": SAME_ORIGIN, + "opener": "noopener" + }, + { + "title": "cross origin iframe, same origin popup", + "iframeOrigin": CROSS_ORIGIN, + "popupOrigin": SAME_ORIGIN, + "opener": "noopener" + }, + { + "title": "same origin iframe, same site popup", + "iframeOrigin": SAME_ORIGIN, + "popupOrigin": SAME_SITE, + "opener": "severed" + }, + { + "title": "same site iframe, same site popup", + "iframeOrigin": SAME_SITE, + "popupOrigin": SAME_SITE, + "opener": "noopener" + }, + { + "title": "cross origin iframe, same site popup", + "iframeOrigin": CROSS_ORIGIN, + "popupOrigin": SAME_SITE, + "opener": "noopener" + }, + { + "title": "same origin iframe, cross origin popup", + "iframeOrigin": SAME_ORIGIN, + "popupOrigin": CROSS_ORIGIN, + "opener": "severed" + }, + { + "title": "same site iframe, cross origin popup", + "iframeOrigin": SAME_SITE, + "popupOrigin": CROSS_ORIGIN, + "opener": "noopener" + }, + { + "title": "cross origin iframe, cross origin popup", + "iframeOrigin": CROSS_ORIGIN, + "popupOrigin": CROSS_ORIGIN, + "opener": "noopener" + } +].forEach(variant => { + subsetTest( + iframe_test, + `COOP: same-origin to popup COOP: unsafe-none via an iframe, with ${variant.title}`, + variant.iframeOrigin, + variant.popupOrigin, + { coop: 'unsafe-none' }, + variant.opener); +}); +</script> +</body> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/iframe-popup-same-origin-to-unsafe-none.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/iframe-popup-same-origin-to-unsafe-none.https.html.headers new file mode 100644 index 0000000000..46ad58d83b --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/iframe-popup-same-origin-to-unsafe-none.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: same-origin diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/iframe-popup-unsafe-none-to-same-origin.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/iframe-popup-unsafe-none-to-same-origin.https.html new file mode 100644 index 0000000000..8158b9f4d5 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/iframe-popup-unsafe-none-to-same-origin.https.html @@ -0,0 +1,87 @@ +<!doctype html> +<meta charset=utf-8> +<meta name=timeout content=long> +<meta name="variant" content="?1-2"> +<meta name="variant" content="?3-4"> +<meta name="variant" content="?5-6"> +<meta name="variant" content="?7-8"> +<meta name="variant" content="?9-last"> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src=/common/dispatcher/dispatcher.js></script> +<script src=/common/get-host-info.sub.js></script> +<script src=/common/subset-tests.js></script> +<script src=/common/utils.js></script> +<script src="resources/common.js"></script> +<script src="resources/iframe-test.js"></script> + +<body> +<script> +// This document has COOP: unsafe-none. The popup has COOP: same-origin. +// Therefore there should be no opener or name. +[ + { + "title": "same origin iframe, same origin popup", + "iframeOrigin": SAME_ORIGIN, + "popupOrigin": SAME_ORIGIN, + "opener": "severed" + }, + { + "title": "same site iframe, same origin popup", + "iframeOrigin": SAME_SITE, + "popupOrigin": SAME_ORIGIN, + "opener": "severed" + }, + { + "title": "cross origin iframe, same origin popup", + "iframeOrigin": CROSS_ORIGIN, + "popupOrigin": SAME_ORIGIN, + "opener": "severed" + }, + { + "title": "same origin iframe, same site popup", + "iframeOrigin": SAME_ORIGIN, + "popupOrigin": SAME_SITE, + "opener": "severed" + }, + { + "title": "same site iframe, same site popup", + "iframeOrigin": SAME_SITE, + "popupOrigin": SAME_SITE, + "opener": "severed" + }, + { + "title": "cross origin iframe, same site popup", + "iframeOrigin": CROSS_ORIGIN, + "popupOrigin": SAME_SITE, + "opener": "severed" + }, + { + "title": "same origin iframe, cross origin popup", + "iframeOrigin": SAME_ORIGIN, + "popupOrigin": CROSS_ORIGIN, + "opener": "severed" + }, + { + "title": "same site iframe, cross origin popup", + "iframeOrigin": SAME_SITE, + "popupOrigin": CROSS_ORIGIN, + "opener": "severed" + }, + { + "title": "cross origin iframe, cross origin popup", + "iframeOrigin": CROSS_ORIGIN, + "popupOrigin": CROSS_ORIGIN, + "opener": "severed" + } +].forEach(variant => { + subsetTest( + iframe_test, + `COOP: unsafe-none to popup COOP: same-origin via an iframe, with ${variant.title}`, + variant.iframeOrigin, + variant.popupOrigin, + { coop: 'same-origin' }, + variant.opener); +}); +</script> +</body> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/iframe-popup-unsafe-none-to-same-origin.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/iframe-popup-unsafe-none-to-same-origin.https.html.headers new file mode 100644 index 0000000000..073ce7adfb --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/iframe-popup-unsafe-none-to-same-origin.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: unsafe-none diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/iframe-popup-unsafe-none-to-unsafe-none.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/iframe-popup-unsafe-none-to-unsafe-none.https.html new file mode 100644 index 0000000000..74ceeb290d --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/iframe-popup-unsafe-none-to-unsafe-none.https.html @@ -0,0 +1,85 @@ +<!doctype html> +<meta charset=utf-8> +<meta name=timeout content=long> +<meta name="variant" content="?1-2"> +<meta name="variant" content="?3-4"> +<meta name="variant" content="?5-6"> +<meta name="variant" content="?7-8"> +<meta name="variant" content="?9-last"> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src=/common/dispatcher/dispatcher.js></script> +<script src=/common/get-host-info.sub.js></script> +<script src=/common/subset-tests.js></script> +<script src=/common/utils.js></script> +<script src="resources/common.js"></script> +<script src="resources/iframe-test.js"></script> + +<body> +<script> +[ + { + "title": "same origin iframe, same origin popup", + "iframeOrigin": SAME_ORIGIN, + "popupOrigin": SAME_ORIGIN, + "opener": "preserved" + }, + { + "title": "same site iframe, same origin popup", + "iframeOrigin": SAME_SITE, + "popupOrigin": SAME_ORIGIN, + "opener": "preserved" + }, + { + "title": "cross origin iframe, same origin popup", + "iframeOrigin": CROSS_ORIGIN, + "popupOrigin": SAME_ORIGIN, + "opener": "preserved" + }, + { + "title": "same origin iframe, same site popup", + "iframeOrigin": SAME_ORIGIN, + "popupOrigin": SAME_SITE, + "opener": "preserved" + }, + { + "title": "same site iframe, same site popup", + "iframeOrigin": SAME_SITE, + "popupOrigin": SAME_SITE, + "opener": "preserved" + }, + { + "title": "cross origin iframe, same site popup", + "iframeOrigin": CROSS_ORIGIN, + "popupOrigin": SAME_SITE, + "opener": "preserved" + }, + { + "title": "same origin iframe, cross origin popup", + "iframeOrigin": SAME_ORIGIN, + "popupOrigin": CROSS_ORIGIN, + "opener": "preserved" + }, + { + "title": "same site iframe, cross origin popup", + "iframeOrigin": SAME_SITE, + "popupOrigin": CROSS_ORIGIN, + "opener": "preserved" + }, + { + "title": "cross origin iframe, cross origin popup", + "iframeOrigin": CROSS_ORIGIN, + "popupOrigin": CROSS_ORIGIN, + "opener": "preserved" + } +].forEach(variant => { + subsetTest( + iframe_test, + `COOP: unsafe-none to popup COOP: unsafe-none via an iframe, with ${variant.title}`, + variant.iframeOrigin, + variant.popupOrigin, + { coop: 'unsafe-none' }, + variant.opener); +}); +</script> +</body> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/iframe-popup-unsafe-none-to-unsafe-none.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/iframe-popup-unsafe-none-to-unsafe-none.https.html.headers new file mode 100644 index 0000000000..073ce7adfb --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/iframe-popup-unsafe-none-to-unsafe-none.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: unsafe-none diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/javascript-url.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/javascript-url.https.html new file mode 100644 index 0000000000..8ebb3ccd4a --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/javascript-url.https.html @@ -0,0 +1,199 @@ +<!DOCTYPE html> +<title>Cross-Origin-Opener-Policy and a "javascript:" URL popup</title> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<meta name="variant" content="?1-2"> +<meta name="variant" content="?3-4"> +<meta name="variant" content="?5-6"> +<meta name="variant" content="?7-8"> +<meta name="variant" content="?9-10"> +<meta name="variant" content="?11-12"> +<meta name="variant" content="?13-14"> +<meta name="variant" content="?15-16"> +<meta name="variant" content="?17-last"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/subset-tests.js"></script> +<script src="/common/utils.js"></script> +<script src="resources/common.js"></script> + +<p>According to HTML's navigate algorithm, requests to <code>javascript:</code> +URLs should inherit the cross-origin opener policy of the active document. To +observe this, each subtest uses the following procedure.</p> + +<ol> + <li>create popup with a given COOP (the <code>parentCOOP</code>)</li> + <li>navigate the popup to a <code>javascript:</code> URL (the new document is + expected to inherit the <code>parentCOOP</code>)</li> + <li>from the popup, create a second popup window with a given COOP (the + <code>childCOOP</code>)</li> +</ol> + +<p>Both popup windows inspect state and report back to the test.</p> + +<pre> + .---- test ----. + | open(https:) | + | parentCOOP | .----- subject -------. + | '---------> | --------. | + | | | v | + | | | assign(javascript:) | + | | | (COOP under test) | + | | | | | + | | | open(https:) | + | | | childCOOP | .- child -. + | | | '--------------> | | + | | '---------------------' '---------' + | | | | + | validate | <--status---+---------------------' + '--------------' +</pre> + +<script> +'use strict'; + +function getExecutorPath(uuid, origin, coopHeader) { + const executorPath = '/common/dispatcher/executor.html?'; + const coopHeaderPipe = + `|header(Cross-Origin-Opener-Policy,${encodeURIComponent(coopHeader)})`; + return origin + executorPath + `uuid=${uuid}` + '&pipe=' + coopHeaderPipe; +} + +function assert_isolated(results) { + assert_equals(results.childName, '', 'child name'); + assert_false(results.childOpener, 'child opener'); + // The test subject's reference to the "child" window must report "closed" + // when COOP enforces isolation because the document initially created during + // the window open steps must be discarded when a new document object is + // created at the end of the navigation. + assert_true(results.childClosed, 'child closed'); +} + +function assert_not_isolated(results, expectedName) { + assert_equals(results.childName, expectedName, 'child name'); + assert_true(results.childOpener, 'child opener'); + assert_false(results.childClosed, 'child closed'); +} + +async function javascript_url_test(parentCOOP, childCOOP, origin, resultsVerification) { + promise_test(async t => { + const parentToken = token(); + const childToken = token(); + const responseToken = token(); + + const parentURL = getExecutorPath( + parentToken, + SAME_ORIGIN.origin, + parentCOOP); + const childURL = getExecutorPath( + childToken, + origin.origin, + childCOOP); + + // Open a first popup, referred to as the parent popup, and wait for it to + // load. + window.open(parentURL); + send(parentToken, `send('${responseToken}', 'Done loading');`); + assert_equals(await receive(responseToken), 'Done loading'); + + // Make sure the parent popup is removed once the test has run, keeping a + // clean state. + add_completion_callback(() => { + send(parentToken, 'close'); + }); + + // Navigate the popup to the javascript URL. It should inherit the current + // document's COOP. Because we're navigating to a page that is not an + // executor, we lose access to easy messaging, making things a bit more + // complicated. We use a predetermined scenario of communication that + // enables us to retrieve whether the child popup appears closed from the + // parent popup. + // + // Notes: + // - Splitting the script tag prevents HTML parsing to kick in. + // - The innermost double quotes need a triple backslash, because it goes + // through two rounds of consuming escape characters (\\\" -> \" -> "). + // - The javascript URL does not accept \n characters so we need to use + // a new template literal for each line. + send(parentToken, + `location.assign("javascript:'` + + // Include dispatcher.js to have access to send() and receive(). + `<script src=\\\"/common/dispatcher/dispatcher.js\\\"></scr` + `ipt>` + + `<script> (async () => {` + + + // Open the child popup and keep a handle to it. + `const w = open(\\\"${childURL}\\\", \\\"${childToken}\\\");` + + + // We wait for the main frame to query the w.closed property. + `await receive(\\\"${parentToken}\\\");` + + `send(\\\"${responseToken}\\\", w.closed);` + + + // Finally we wait for the cleanup indicating that this popup can be + // closed. + `await receive(\\\"${parentToken}\\\");` + + `close();` + + `})()</scr` + `ipt>'");` + ); + + // Make sure the javascript navigation ran, and the child popup was created. + send(childToken, `send('${responseToken}', 'Done loading');`); + assert_equals(await receive(responseToken), 'Done loading'); + + // Make sure the child popup is removed once the test has run, keeping a + // clean state. + add_completion_callback(() => { + send(childToken, `close()`); + }); + + // Give some time for things to settle across processes etc. before + // proceeding with verifications. + await new Promise(resolve => { t.step_timeout(resolve, 500); }); + + // Gather information about the child popup and verify that they match what + // we expect. + const results = {}; + send(parentToken, 'query'); + results.childClosed = await receive(responseToken) === 'true'; + + send(childToken, `send('${responseToken}', opener != null);`); + results.childOpener = await receive(responseToken) === 'true'; + + send(childToken, `send('${responseToken}', name);`); + results.childName = await receive(responseToken); + + resultsVerification(results, childToken); + }, `navigation: ${origin.name}; ` + `parentCOOP: ${parentCOOP}; ` + + `childCOOP: ${childCOOP}`); +} + +const tests = [ + ['unsafe-none', 'unsafe-none', SAME_ORIGIN, assert_not_isolated], + ['unsafe-none', 'unsafe-none', SAME_SITE, assert_not_isolated], + ['unsafe-none', 'same-origin-allow-popups', SAME_ORIGIN, assert_isolated], + ['unsafe-none', 'same-origin-allow-popups', SAME_SITE, assert_isolated], + ['unsafe-none', 'same-origin', SAME_ORIGIN, assert_isolated], + ['unsafe-none', 'same-origin', SAME_SITE, assert_isolated], + ['same-origin-allow-popups', 'unsafe-none', SAME_ORIGIN, assert_not_isolated], + ['same-origin-allow-popups', 'unsafe-none', SAME_SITE, assert_not_isolated], + ['same-origin-allow-popups', 'same-origin-allow-popups', SAME_ORIGIN, assert_not_isolated], + ['same-origin-allow-popups', 'same-origin-allow-popups', SAME_SITE, assert_isolated], + ['same-origin-allow-popups', 'same-origin', SAME_ORIGIN, assert_isolated], + ['same-origin-allow-popups', 'same-origin', SAME_SITE, assert_isolated], + ['same-origin', 'unsafe-none', SAME_ORIGIN, assert_isolated], + ['same-origin', 'unsafe-none', SAME_SITE, assert_isolated], + ['same-origin', 'same-origin-allow-popups', SAME_ORIGIN, assert_isolated], + ['same-origin', 'same-origin-allow-popups', SAME_SITE, assert_isolated], + ['same-origin', 'same-origin', SAME_ORIGIN, assert_not_isolated], + ['same-origin', 'same-origin', SAME_SITE, assert_isolated], +].forEach(([parentCOOP, childCOOP, origin, expectation]) => { + subsetTest( + javascript_url_test, + parentCOOP, + childCOOP, + origin, + expectation); +}); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/navigate-to-aboutblank.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/navigate-to-aboutblank.https.html new file mode 100644 index 0000000000..b2145cfa56 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/navigate-to-aboutblank.https.html @@ -0,0 +1,193 @@ +<title> + This tests the inheritance of COOP for navigations to about:blank. +</title> +<meta name=timeout content=long> +<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> +<script src="/common/dispatcher/dispatcher.js"></script> + +<p>Non-initial empty documents (about:blank) should inherit their + cross-origin-opener-policy from the navigation's initiator top level document, + if the initiator and its top level document are same-origin, or default + (unsafe-none) otherwise. +</p> + +<ol> + <li>Create the opener popup with a given COOP <code>openerCOOP</code>.</li> + <li>Add iframe to the opener popup that is either same-origin or + cross-origin. + </li> + <li>Opener's iframe opens a new window, to a network document with <code>openeeCOOP</code>.</li> + <li>Opener's iframe navigates the openee popup to about:blank.</li> +</ol> + +<script> +const executor_path = "/common/dispatcher/executor.html?pipe="; +const same_origin = get_host_info().HTTPS_ORIGIN; +const cross_origin = get_host_info().HTTPS_REMOTE_ORIGIN; +const coop_same_origin_header = + '|header(Cross-Origin-Opener-Policy,same-origin)'; +const coep_require_corp_header = + '|header(Cross-Origin-Embedder-Policy,require-corp)'; +const coop_same_origin_plus_coep_header = + coop_same_origin_header + coep_require_corp_header; +const coop_same_origin_allow_popups_header = + '|header(Cross-Origin-Opener-Policy,same-origin-allow-popups)'; +const coop_unsafe_none_header = + '|header(Cross-Origin-Opener-Policy,unsafe-none)'; + +function navigateToAboutBlankTest( + opener_COOP_header, + iframe_origin, + openee_COOP_header, + openee_origin, + iframe_header, + expect_openee_closed +){ + return promise_test(async t => { + const this_window_token = token(); + const opener_token = token(); + const openee_token = token(); + const iframe_token = token(); + + const opener_url = same_origin + executor_path + opener_COOP_header + + `&uuid=${opener_token}`; + const openee_url = openee_origin + executor_path + openee_COOP_header + + `&uuid=${openee_token}`; + const iframe_url = iframe_origin + executor_path + iframe_header + `&uuid=${iframe_token}`; + + t.add_cleanup(() => { + send(openee_token, "window.close()"); + send(opener_token, "window.close()"); + }); + + // 1. Create the opener window. + let opener_window_proxy = window.open(opener_url, opener_token); + + // 2. Create the iframe. + send(opener_token, ` + iframe = document.createElement('iframe'); + iframe.src = "${iframe_url}"; + document.body.appendChild(iframe); + `); + + // 3. The iframe opens its openee window. + send(iframe_token, ` + window.openee = window.open( + '${openee_url.replace(/,/g, '\\,')}', + "${openee_token}" + ); + `); + + // 4. Ensure the popup is fully loaded. + send(openee_token, `send("${this_window_token}", "Ack");`); + assert_equals(await receive(this_window_token), "Ack"); + + // 5. The iframe navigates openee to about:blank. + send(iframe_token, ` + window.openee_blank = window.open('about:blank', "${openee_token}"); + (async function() { + const timeout = 2000; + const retry_delay = 100; + for(let i = 0; i * retry_delay < timeout; ++i) { + // A try-catch block is used, because of same-origin policy, + // preventing access to the document before committing about:blank. + try { + if (window.openee_blank.closed || + window.openee_blank.document.location.href == "about:blank") { + send("${this_window_token}", "about:blank loaded"); + return; + } + } catch(e) {} + await new Promise(resolve => setTimeout(resolve, retry_delay)); + } + send("${this_window_token}", "about:blank not loaded"); + })() + `); + assert_equals(await receive(this_window_token), "about:blank loaded"); + + // 6. Retrieve and check the results. + send(iframe_token, ` + send("${this_window_token}", window.openee.closed); + `); + assert_equals(await receive(this_window_token), `${expect_openee_closed}`); + }, `Navigate to about:blank from iframe with opener.top \ +COOP: ${opener_COOP_header}, iframe origin: ${iframe_origin}, \ +openee COOP: ${openee_COOP_header}, openee origin: ${openee_origin}.`); +}; + +// iframe same-origin with its top-level embedder: +// initial empty document and about:blank navigations initiated from the +// same-origin iframe will inherit the COOP from the iframe's top-level embedder. + +// Since all navigations of openee are within same-origin pages with the +// same COOP value, there are no browsing context group switches. +navigateToAboutBlankTest( + coop_same_origin_header, + same_origin, + coop_same_origin_header, + same_origin, + "", + false +); + +// Since all navigations of openee are within same-origin pages with the +// same COOP value, there are no browsing context group switches. +// Test with both COOP and COEP. +navigateToAboutBlankTest( + coop_same_origin_plus_coep_header, + same_origin, + coop_same_origin_plus_coep_header, + same_origin, + coep_require_corp_header, + false +); + +// Since all navigations of openee are within same-origin pages with the +// same COOP value, there are no browsing context group switches. +navigateToAboutBlankTest( + coop_same_origin_allow_popups_header, + same_origin, + coop_same_origin_allow_popups_header, + same_origin, + "", + false +); + +// The first openee navigation, from initial empty document to +// cross-origin will not switch the browsing context group, thanks to the +// same-origin-allow-popups behavior. +// The second openee navigation, to about:blank, will inherit from the +// iniatiator's, the iframe, top. Navigating from a COOP: unsafe-none page to +// a COOP: same-origin-allow-popups page causes a browsing context group +// switch. +navigateToAboutBlankTest( + coop_same_origin_allow_popups_header, + same_origin, + coop_unsafe_none_header, + cross_origin, + "", + true +); + +// iframe cross-origin with its top-level embedder: +// initial empty document and about:blank navigations initiated from the +// cross-origin iframe will default COOP to unsafe-none. + +// The navigation from the initial empty document and the cross_origin url +// does not cause a browsing context group switch +// (both have COOP: unsafe-none). +// The navigation from the cross-origin url to about:blank does not cause a +// browsing context group swich, about:blank defaulted its COOP value to +// unsafe-none. +navigateToAboutBlankTest( + coop_same_origin_allow_popups_header, + cross_origin, + coop_unsafe_none_header, + cross_origin, + "", + false +); +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/navigate-top-to-aboutblank.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/navigate-top-to-aboutblank.https.html new file mode 100644 index 0000000000..fe605baf45 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/navigate-top-to-aboutblank.https.html @@ -0,0 +1,171 @@ +<title> + This tests the inheritance of COOP for navigations of the top document to about:blank. +</title> +<meta name=timeout content=long> +<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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/resources/common.js"></script> + + +<p>Non-initial empty documents (about:blank) should inherit their + cross-origin-opener-policy from the navigation's initiator top level document, + if the initiator and its top level document are same-origin, or default (to + unsafe-none) otherwise. +</p> + +<ol> + <li>Create the opener popup with a given COOP <code>openerCOOP</code>.</li> + <li>Add iframe to the opener popup that is either same-origin or + cross-origin. + </li> + <li>Opener opens a new window, to a network document with the same origin and + COOP value as opener.</li> + <li>Opener's iframe navigates its parent frame (opener) to about:blank.</li> + <li>Verify the openee still has access to its opener.</li> +</ol> + +<script> +const executor_path = "/common/dispatcher/executor.html?pipe="; +const same_origin = get_host_info().HTTPS_ORIGIN; +const cross_origin = get_host_info().HTTPS_REMOTE_ORIGIN; +const coop_same_origin_header = + '|header(Cross-Origin-Opener-Policy,same-origin)'; +const coop_same_origin_allow_popups_header = + '|header(Cross-Origin-Opener-Policy,same-origin-allow-popups)'; +const coop_unsafe_none_header = + '|header(Cross-Origin-Opener-Policy,unsafe-none)'; + +function navigateToAboutBlankTest( + COOP_header, + iframe_origin, + expect_opener_closed +){ + return promise_test(async t => { + const this_window_token = token(); + const opener_token = token(); + const openee_token = token(); + const iframe_token = token(); + + const opener_url = same_origin + executor_path + COOP_header + + `&uuid=${opener_token}`; + const openee_url = same_origin + executor_path + COOP_header + + `&uuid=${openee_token}`; + const iframe_url = iframe_origin + executor_path + `&uuid=${iframe_token}`; + + t.add_cleanup(() => { + send(opener_token, "window.close()"); + send(openee_token, "window.close()"); + }); + + // 1. Create the opener window. + let opener_window_proxy = window.open(opener_url, opener_token); + + // 2. Create the iframe. + send(opener_token, ` + iframe = document.createElement('iframe'); + iframe.src = "${iframe_url}"; + document.body.appendChild(iframe); + `); + + // 3. The opener opens openee window. + send(opener_token, ` + window.openee = window.open( + '${openee_url.replace(/,/g, '\\,')}' + ); + `); + + // 4. Ensure the popup is fully loaded. + send(openee_token, `send("${this_window_token}", "Ack");`); + assert_equals(await receive(this_window_token), "Ack"); + + // 5. The iframe navigates its top-level document to about:blank. It needs + // to receive a user action as it may be cross-origin and it navigates top + // to a cross-origin document. + // https://github.com/WICG/interventions/issues/16 + send(iframe_token, addScriptAndTriggerOnload( + "/resources/testdriver.js", + `${addScriptAndTriggerOnload("/resources/testdriver-vendor.js", + ` + test_driver.bless('navigate top to about:blank', () => { + open("about:blank", "_top"); + }); + `)} + `)); + + // 6. Ensure opener is fully loaded and then retrieve the results. + send(openee_token, ` + (async function() { + const timeout = 2000; + const retry_delay = 100; + for(let i = 0; i * retry_delay < timeout; ++i) { + // A try-catch block is used, because of same-origin policy, + // which may prevent the access to the opener if its origin changed, + // after a navigation to about:blank from the cross origin iframe. + try { + if ( + window.opener === null || + window.opener.closed || + window.opener.document.location.href == "about:blank") { + send("${this_window_token}", "about:blank loaded"); + return; + } + } catch(e) { + // The exception is thrown when about:blank is loaded and is + // cross-origin with openee. + send("${this_window_token}", "about:blank loaded"); + return; + } + await new Promise(resolve => setTimeout(resolve, retry_delay)); + } + send("${this_window_token}", "about:blank NOT loaded"); + })() + `); + assert_equals(await receive(this_window_token), "about:blank loaded"); + + // 7. Retrieve and check the results. + send(openee_token, ` + send( + "${this_window_token}", + window.opener === null || window.opener.closed); + `); + + assert_equals(await receive(this_window_token), `${expect_opener_closed}`); + }, `Navigate top to about:blank from iframe with \ +opener COOP: ${COOP_header}, iframe origin: ${iframe_origin}`); +}; + +// iframe same-origin with its top-level embedder: +// initial empty document and about:blank navigations initiated from the +// same-origin iframe will inherit COOP from the iframe's top-level embedder. + +// Opener's navigation to about:blank stays in the same browsing context group. +navigateToAboutBlankTest( + coop_same_origin_header, + same_origin, + false +); + +// iframe cross-origin with its top-level embedder: +// initial empty document and about:blank navigations initiated from the +// cross-origin iframe will default COOP to unsafe-none. + +// Opener's navigation to about:blank doesn't inherit COOP, leading to a +// browsing context group switch. +navigateToAboutBlankTest( + coop_same_origin_header, + cross_origin, + true +); + +// Same origin allow popups allows the navigation of top to the cross-origin +// about:blank (origin inherited from the iframe) page, which does not have COOP +// (initiator is a cross origin iframe). +navigateToAboutBlankTest( + coop_same_origin_allow_popups_header, + cross_origin, + false +); +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/no-https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/no-https.html new file mode 100644 index 0000000000..db15d5c676 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/no-https.html @@ -0,0 +1,21 @@ +<!doctype html> +<meta name=timeout content=long> +<title>Cross-Origin-Opener-Policy requires secure contexts</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script> +async_test(t => { + const popup = window.open("resources/call-functionCalledByOpenee.html"); + t.add_cleanup(() => { + popup.close(); + }); + window.functionCalledByOpenee = t.step_func_done(() => { + assert_false(popup.closed); + }); + assert_equals(window, popup.opener); +}, "Cross-Origin-Opener-Policy only works over secure contexts"); + +test(() => { + assert_false(window.crossOriginIsolated); +}, "Bonus: window.crossOriginIsolated"); +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/no-https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/no-https.html.headers new file mode 100644 index 0000000000..46ad58d83b --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/no-https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: same-origin diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/popup-coop-by-sw.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-coop-by-sw.https.html new file mode 100644 index 0000000000..69c2db1ad9 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-coop-by-sw.https.html @@ -0,0 +1,136 @@ +<meta name="timeout" content="long"> +<meta name="variant" content="?1-4"> +<meta name="variant" content="?5-last"> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/subset-tests.js"></script> +<script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script> +<script src="/common/utils.js"></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script> + +const executor_path = '/common/dispatcher/executor.html?pipe='; +const executor_service_worker_path = '/common/dispatcher/executor-service-worker.js?pipe='; + +const coop_header = `|header(Cross-Origin-Opener-Policy,same-origin)`; +const coep_header = `|header(Cross-Origin-Embedder-Policy,require-corp)`; + +const https_origin = get_host_info().HTTPS_ORIGIN; + +const swap_browsing_context_group = true; +const keep_browsing_context_group = false; + +const opener_basic = ""; +const opener_coi = coop_header + coep_header; + +const sw_basic = ""; +const sw_coi = coop_header + coep_header; + +const openee_basic = { + 'content-type': 'text/html', +}; +const openee_coi = { + 'content-type': 'text/html', + 'cross-origin-embedder-policy': 'require-corp', + 'cross-origin-opener-policy': 'same-origin', +}; + +// A document opens a popup. The popup's document is served from a synthetic +// response by a ServiceWorker. Check how cross-origin isolation works in this +// case. +const popupCoopBySwTest = ( + description, + // Test parameters: + opener_headers, + openee_headers, + sw_headers, + // Test expectations: + expected_browing_context_group +) => { + subsetTest(promise_test, async test => { + const driver_token = token(); + + // 1. Create the opener. + const opener_token = token(); + const opener_url = https_origin + executor_path + opener_headers + + `&uuid=${opener_token}`; + const opener_window = window.open(opener_url); + test.add_cleanup(() => opener_window.close()); + + // 2. Define the openee's URL as being served by the service worker. + const openee_url = https_origin + "/common/dispatcher/proxied?" + token(); + + // 3. Register, install and activate a ServiceWorker serving the openee_url. + const sw_token = token(); + const sw_url = https_origin + executor_service_worker_path + sw_headers + + `&uuid=${sw_token}`; + const sw_scope = openee_url; // One-time scope, because of the token. + + const sw_registration = + await service_worker_unregister_and_register(test, sw_url, sw_scope); + test.add_cleanup(() => sw_registration.unregister()); + await wait_for_state(test, sw_registration.installing, 'activated'); + + send(sw_token, ` + fetchHandler = event => { + if (!event.request.url.includes("proxied")) + return; + + const response = new Response(\` + <script src="/common/dispatcher/dispatcher.js"></scr\`+\`ipt> + <script> + send("${driver_token}", opener ? "opener is set" + : "opener is null"); + </scr\` + \`ipt> + \`, { + status: 200, + headers: ${JSON.stringify(openee_headers)}, + }); + event.respondWith(response); + } + + await clients.claim(); + + send("${driver_token}", serviceWorker.state); + `) + assert_equals(await receive(driver_token), "activated"); + + // 4. The opener opens a popup. Its document is a synthetic response served + // from the Service Worker. + send(opener_token, ` + window.open("${openee_url}"); + `); + + assert_equals(await receive(driver_token), + (expected_browing_context_group == swap_browsing_context_group) + ? "opener is null" + : "opener is set"); + }, description); +}; + +popupCoopBySwTest("opener:basic, openee:basic, sw:basic", + opener_basic, openee_basic, sw_basic, + keep_browsing_context_group); +popupCoopBySwTest("opener:basic, openee:basic, sw:coi", + opener_basic, openee_basic, sw_coi, + keep_browsing_context_group); +popupCoopBySwTest("opener:basic, openee:coi, sw:basic", + opener_basic, openee_coi, sw_basic, + swap_browsing_context_group); +popupCoopBySwTest("opener:basic, openee:coi, sw:coi", + opener_basic, openee_coi, sw_coi, + swap_browsing_context_group); +popupCoopBySwTest("opener:coi, openee:basic, sw:basic", + opener_coi, openee_basic, sw_basic, + swap_browsing_context_group); +popupCoopBySwTest("opener:coi, openee:basic, sw:coi", + opener_coi, openee_basic, sw_coi, + swap_browsing_context_group); +popupCoopBySwTest("opener:coi, openee:coi, sw:basic", + opener_coi, openee_coi, sw_basic, + keep_browsing_context_group); +popupCoopBySwTest("opener:coi, openee:coi, sw:coi", + opener_coi, openee_coi, sw_coi, + keep_browsing_context_group); +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/popup-meta-http-equiv.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-meta-http-equiv.https.html new file mode 100644 index 0000000000..157f7aef46 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-meta-http-equiv.https.html @@ -0,0 +1,24 @@ +<!doctype html> +<meta http-equiv="Cross-Origin-Opener-Policy" content="same-origin"><!-- should not be supported --> +<meta charset=utf-8> +<meta name=timeout content=long> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/utils.js"></script> +<script src="resources/common.js"></script> +<script src="resources/popup-test.js"></script> +<script> + +[ + { + "title": "popup without coop", + "coop": "", + "same_origin_opener": "preserved", + } +].forEach(variant => { + popup_test(`Same-origin ${variant.title}`, SAME_ORIGIN, variant.coop, variant.same_origin_opener); +}); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/popup-redirect-cache.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-redirect-cache.https.html new file mode 100644 index 0000000000..6568ac3fdb --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-redirect-cache.https.html @@ -0,0 +1,90 @@ +<!doctype html> +<meta charset=utf-8> +<meta name="timeout" content="long"> +<meta name="variant" content="?0-1"> +<meta name="variant" content="?2-3"> +<meta name="variant" content="?4-5"> +<meta name="variant" content="?6-7"> +<meta name="variant" content="?8-last"> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/subset-tests.js"></script> +<script src="/common/utils.js"></script> +<script src="resources/common.js"></script> + +<div id=log></div> +<script> + +function url_test_cache(t, url, responseToken, iframeToken, hasOpener) { + return new Promise(async (resolve, reject) => { + try { + await dispatcher_url_test(t, url, responseToken, iframeToken, hasOpener, undefined /* OpenerDomAccess */, resolve); + } catch(e) { + reject(e); + } + }).then(() => { + return new Promise(async (resolve, reject) => { + try { + // Test the same url for cache. + // Note that at this point the popup from the first + // `dispatcher_url_test()` call hasn't been closed yet, but once this + // test has finished both will be cleaned up. + await dispatcher_url_test(t, url, responseToken, iframeToken, hasOpener, undefined /* OpenerDomAccess */, resolve); + } catch(e) { + reject(e); + } + }); + }); +} + +// Redirect from hostA to hostB with same coop and coep. +// Cache the hostA page if redirectCache is true. +// Cache the hostB page if destCache is true. +function coop_redirect_cache_test(t, hostA, hostB, coop, coep, redirectCache, destCache, hasOpener) { + let redirectUrl = `${hostA.origin}/html/cross-origin-opener-policy/resources/coop-coep.py`; + let redirectCacheString = redirectCache ? "&cache=1" : ""; + let destCacheString = destCache ? "&cache=1" : ""; + let responseToken = token(); + let iframeToken = token(); + let destUrl = `${hostB.origin}/html/cross-origin-opener-policy/resources/coop-coep.py?coop=${coop}&coep=${coep}${destCacheString}&responseToken=${responseToken}&iframeToken=${iframeToken}`; + let url = `${redirectUrl}?coop=${coop}&coep=${coep}${redirectCacheString}&redirect=${encodeURIComponent(destUrl)}`; + + return url_test_cache(t, url, responseToken, iframeToken, hasOpener); +} + +function run_redirect_cache_tests(documentCOOPValueTitle, testArray) { + testArray.forEach((test, i) => { + // Only run specified variants + if (!shouldRunSubTest(i)) { + return; + } + + promise_test(t => { + return coop_redirect_cache_test(t, test[0], test[1], "same-origin", "require-corp", test[2], test[3], test[4]); + }, `${documentCOOPValueTitle} document opening popup redirect from ${test[0].origin} to ${test[1].origin} with redirectCache ${test[2]} and destCache ${test[3]}`); + }); +} + +const tests = [ + // popup Origin, final Origin, isCacheRedirect, isCacheDestination, hasOpener + // Origin A->A->B + [SAME_ORIGIN, CROSS_ORIGIN, true, false, false], + [SAME_ORIGIN, CROSS_ORIGIN, false, true, false], + [SAME_ORIGIN, CROSS_ORIGIN, true, true, false], + + // Origin A->B->B + [CROSS_ORIGIN, SAME_ORIGIN, true, false, false], + [CROSS_ORIGIN, SAME_ORIGIN, false, true, false], + [CROSS_ORIGIN, SAME_ORIGIN, true, true, false], + + // Origin A->B->C + [SAME_SITE, CROSS_ORIGIN, true, false, false], + [SAME_SITE, CROSS_ORIGIN, false, true, false], + [SAME_SITE, CROSS_ORIGIN, true, true, false], +]; + +run_redirect_cache_tests("same-origin", tests); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/popup-redirect-cache.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-redirect-cache.https.html.headers new file mode 100644 index 0000000000..46ad58d83b --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-redirect-cache.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: same-origin diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/popup-redirect-same-origin-allow-popups.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-redirect-same-origin-allow-popups.https.html new file mode 100644 index 0000000000..73119a76f8 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-redirect-same-origin-allow-popups.https.html @@ -0,0 +1,96 @@ +<title> + Tests the interaction of COOP same-origin-allow-popups with redirects in a + newly opened popup. +</title> +<meta charset=utf-8> +<meta name=timeout content=long> +<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> +<script src="/common/dispatcher/dispatcher.js"></script> + +<div id=log></div> +<script> + +const executor_path = "/common/dispatcher/executor.html?pipe="; +const same_origin = { + host: get_host_info().HTTPS_ORIGIN, + name: "Same origin" +}; +const cross_origin = { + host: get_host_info().HTTPS_REMOTE_ORIGIN, + name: "Cross origin" +}; +const coep_header = '|header(Cross-Origin-Embedder-Policy,unsafe-none)'; + +// Tests the interaction of COOP same-origin-allow-popups with redirects in a +// newly created popup. +// 1- Creates a page with origin SAME_ORIGIN and COOP same-origin-allow-popups. +// 2- This page opens a popup. +// 3- The popup navigates and gets a redirect response with COOP unsafe none +// and origin either SAME_ORIGIN or CROSS_ORIGIN +// 4- The popup follows the redirect and ends up on a final page with COOP +// same-origin-allow-popups and origin SAME_ORIGIN +// 5- The popup and its opener should no longer be in the same browsing context +// group (ie the popup doesn't have an opener and the window that opened the +// popup sees it as closed). +function redirect_test(popup_redirect_origin) { + promise_test(async t => { + // Identifies the test window. + const this_window_token = token(); + + // Identifies the first window that will open the popup. It has COOP + // same-origin-allow-popups. + const opener_token= token(); + const same_origin_allow_popups_header = + `|header(Cross-Origin-Opener-Policy,same-origin-allow-popups)`; + const opener_url = same_origin.host + executor_path + + same_origin_allow_popups_header + `&uuid=${opener_token}`; + + // Identifies the popup. It will initial try to navigate to + // popup_redirect_origin, which has COOP unsafe-none. The navigation is + // then redirected to a final response of SAME_ORIGIN and COOP + // same-origin-allow-popups. + const popup_token = token(); + const popup_final_url = same_origin.host + executor_path + + same_origin_allow_popups_header + `&uuid=${popup_token}`; + const redirect_header = 'status(302)' + + `|header(Location,${encodeURIComponent( + popup_final_url + .replace(/,/g, "\\,") + .replace(/\\\\,/g, "\\\\\\,") + .replace(/\(/g, "%28") + .replace(/\)/g, "%29"))})`; + const popup_initial_url = popup_redirect_origin.host + executor_path + + redirect_header + `&uuid=${popup_token}`; + + // 1. Create the initial window. + let opener_window_proxy = window.open(opener_url); + t.add_cleanup(() => send(opener_token, "window.close()")); + + // 2. The initial window opens a popup. + send(opener_token, ` + popup = window.open("${popup_initial_url}"); + `); + t.add_cleanup(() => send(popup_token, "window.close()")); + + // 3. Check the opener status on the popup. + send(popup_token, ` + send("${this_window_token}", window.opener !== null); + `); + assert_equals(await receive(this_window_token), "false", "opener"); + + // 4. Check the status of the popup from the initial window. + send(opener_token, ` + send("${this_window_token}", popup.closed); + `); + assert_equals(await receive(this_window_token), "true", "popup.closed"); + + }, `${popup_redirect_origin.name} popup redirects to same-origin with same-origin-allow-popups`); +} + +redirect_test(same_origin); +redirect_test(cross_origin); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/popup-same-origin-allow-popups-with-cross-origin.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-same-origin-allow-popups-with-cross-origin.https.html new file mode 100644 index 0000000000..d025faeb67 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-same-origin-allow-popups-with-cross-origin.https.html @@ -0,0 +1,58 @@ +<!doctype html> +<meta charset=utf-8> +<meta name=timeout content=long> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/utils.js"></script> +<script src="resources/common.js"></script> +<script src="resources/popup-test.js"></script> +<script> + +[ + { + "title": "popup with empty coop", + "coop": "", + "opener": "preserved" + }, + { + "title": "popup with coop unsafe-none", + "coop": "unsafe-none", + "opener": "preserved" + }, + { + "title": "popup with jibberish coop", + "coop": "jibberish", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop", + "coop": "same-site", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop 2", + "coop": "same-site unsafe-allow-outgoing", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop 3", + "coop": "same-origin unsafe-allow-outgoing", + "opener": "preserved" + }, + { + "title": "popup with coop same-origin", + "coop": "same-origin", + "opener": "severed" + }, + { + "title": "popup with coop same-origin-allow-popups", + "coop": "same-origin-allow-popups", + "opener": "severed" + } +].forEach(variant => { + popup_test(`Cross-origin ${variant.title}`, CROSS_ORIGIN, { coop : variant.coop }, variant.opener); +}); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/popup-same-origin-allow-popups-with-cross-origin.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-same-origin-allow-popups-with-cross-origin.https.html.headers new file mode 100644 index 0000000000..d83ed86fb9 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-same-origin-allow-popups-with-cross-origin.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: same-origin-allow-popups diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/popup-same-origin-allow-popups-with-same-origin.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-same-origin-allow-popups-with-same-origin.https.html new file mode 100644 index 0000000000..438e424284 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-same-origin-allow-popups-with-same-origin.https.html @@ -0,0 +1,58 @@ +<!doctype html> +<meta charset=utf-8> +<meta name=timeout content=long> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/utils.js"></script> +<script src="resources/common.js"></script> +<script src="resources/popup-test.js"></script> +<script> + +[ + { + "title": "popup with empty coop", + "coop": "", + "opener": "preserved" + }, + { + "title": "popup with coop unsafe-none", + "coop": "unsafe-none", + "opener": "preserved" + }, + { + "title": "popup with jibberish coop", + "coop": "jibberish", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop", + "coop": "same-site", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop 2", + "coop": "same-site unsafe-allow-outgoing", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop 3", + "coop": "same-origin unsafe-allow-outgoing", + "opener": "preserved" + }, + { + "title": "popup with coop same-origin", + "coop": "same-origin", + "opener": "severed" + }, + { + "title": "popup with coop same-origin-allow-popups", + "coop": "same-origin-allow-popups", + "opener": "preserved" + } +].forEach(variant => { + popup_test(`Same-origin ${variant.title}`, SAME_ORIGIN, { coop : variant.coop }, variant.opener); +}); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/popup-same-origin-allow-popups-with-same-origin.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-same-origin-allow-popups-with-same-origin.https.html.headers new file mode 100644 index 0000000000..d83ed86fb9 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-same-origin-allow-popups-with-same-origin.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: same-origin-allow-popups diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/popup-same-origin-allow-popups-with-same-site.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-same-origin-allow-popups-with-same-site.https.html new file mode 100644 index 0000000000..d1b6b60d7c --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-same-origin-allow-popups-with-same-site.https.html @@ -0,0 +1,58 @@ +<!doctype html> +<meta charset=utf-8> +<meta name=timeout content=long> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/utils.js"></script> +<script src="resources/common.js"></script> +<script src="resources/popup-test.js"></script> +<script> + +[ + { + "title": "popup with empty coop", + "coop": "", + "opener": "preserved" + }, + { + "title": "popup with coop unsafe-none", + "coop": "unsafe-none", + "opener": "preserved" + }, + { + "title": "popup with jibberish coop", + "coop": "jibberish", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop", + "coop": "same-site", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop 2", + "coop": "same-site unsafe-allow-outgoing", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop 3", + "coop": "same-origin unsafe-allow-outgoing", + "opener": "preserved" + }, + { + "title": "popup with coop same-origin", + "coop": "same-origin", + "opener": "severed" + }, + { + "title": "popup with coop same-origin-allow-popups", + "coop": "same-origin-allow-popups", + "opener": "severed" + } +].forEach(variant => { + popup_test(`Same-site ${variant.title}`, SAME_SITE, { coop: variant.coop }, variant.opener); +}); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/popup-same-origin-allow-popups-with-same-site.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-same-origin-allow-popups-with-same-site.https.html.headers new file mode 100644 index 0000000000..d83ed86fb9 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-same-origin-allow-popups-with-same-site.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: same-origin-allow-popups diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/popup-same-origin-non-initial-about-blank.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-same-origin-non-initial-about-blank.https.html new file mode 100644 index 0000000000..2e58ea4553 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-same-origin-non-initial-about-blank.https.html @@ -0,0 +1,17 @@ +<!doctype html> +<title>Cross-Origin-Opener-Policy: about:blank</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script> +async_test(t => { + const popup = window.open("resources/coop-coep.py?coop=same-origin&coep=&navigate=about:blank"); + t.add_cleanup(() => popup.close()); + assert_equals(window, popup.opener); + + popup.onload = t.step_func(() => { + assert_true(popup.location.href.endsWith("&navigate=about:blank")); + // Use wait_for_callback as about:blank cannot message back. + t.step_wait_func_done(() => popup.location.href === "about:blank"); + }); +}, "Navigating a popup to about:blank"); +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/popup-same-origin-non-initial-about-blank.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-same-origin-non-initial-about-blank.https.html.headers new file mode 100644 index 0000000000..46ad58d83b --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-same-origin-non-initial-about-blank.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: same-origin diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/popup-same-origin-with-cross-origin.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-same-origin-with-cross-origin.https.html new file mode 100644 index 0000000000..bd1e6848c4 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-same-origin-with-cross-origin.https.html @@ -0,0 +1,58 @@ +<!doctype html> +<meta charset=utf-8> +<meta name=timeout content=long> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/utils.js"></script> +<script src="resources/common.js"></script> +<script src="resources/popup-test.js"></script> +<script> + +[ + { + "title": "popup with empty coop", + "coop": "", + "opener": "severed" + }, + { + "title": "popup with coop unsafe-none", + "coop": "unsafe-none", + "opener": "severed" + }, + { + "title": "popup with jibberish coop", + "coop": "jibberish", + "opener": "severed" + }, + { + "title": "popup with obsolete coop", + "coop": "same-site", + "opener": "severed" + }, + { + "title": "popup with obsolete coop 2", + "coop": "same-site unsafe-allow-outgoing", + "opener": "severed" + }, + { + "title": "popup with obsolete coop 3", + "coop": "same-origin unsafe-allow-outgoing", + "opener": "severed" + }, + { + "title": "popup with coop same-origin", + "coop": "same-origin", + "opener": "severed" + }, + { + "title": "popup with coop same-origin-allow-popups", + "coop": "same-origin-allow-popups", + "opener": "severed" + } +].forEach(variant => { + popup_test(`Cross-origin ${variant.title}`, CROSS_ORIGIN, { coop: variant.coop }, variant.opener); +}); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/popup-same-origin-with-cross-origin.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-same-origin-with-cross-origin.https.html.headers new file mode 100644 index 0000000000..46ad58d83b --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-same-origin-with-cross-origin.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: same-origin diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/popup-same-origin-with-same-origin.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-same-origin-with-same-origin.https.html new file mode 100644 index 0000000000..caf4b173c2 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-same-origin-with-same-origin.https.html @@ -0,0 +1,58 @@ +<!doctype html> +<meta charset=utf-8> +<meta name=timeout content=long> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/utils.js"></script> +<script src="resources/common.js"></script> +<script src="resources/popup-test.js"></script> +<script> + +[ + { + "title": "popup with empty coop", + "coop": "", + "opener": "severed" + }, + { + "title": "popup with coop unsafe-none", + "coop": "unsafe-none", + "opener": "severed" + }, + { + "title": "popup with jibberish coop", + "coop": "jibberish", + "opener": "severed" + }, + { + "title": "popup with obsolete coop", + "coop": "same-site", + "opener": "severed" + }, + { + "title": "popup with obsolete coop 2", + "coop": "same-site unsafe-allow-outgoing", + "opener": "severed" + }, + { + "title": "popup with obsolete coop 3", + "coop": "same-origin unsafe-allow-outgoing", + "opener": "severed" + }, + { + "title": "popup with coop same-origin", + "coop": "same-origin", + "opener": "preserved" + }, + { + "title": "popup with coop same-origin-allow-popups", + "coop": "same-origin-allow-popups", + "opener": "severed" + } +].forEach(variant => { + popup_test(`Same-origin ${variant.title}`, SAME_ORIGIN, { coop: variant.coop }, variant.opener); +}); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/popup-same-origin-with-same-origin.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-same-origin-with-same-origin.https.html.headers new file mode 100644 index 0000000000..46ad58d83b --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-same-origin-with-same-origin.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: same-origin diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/popup-same-origin-with-same-site.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-same-origin-with-same-site.https.html new file mode 100644 index 0000000000..93ba9c9888 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-same-origin-with-same-site.https.html @@ -0,0 +1,58 @@ +<!doctype html> +<meta charset=utf-8> +<meta name=timeout content=long> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/utils.js"></script> +<script src="resources/common.js"></script> +<script src="resources/popup-test.js"></script> +<script> + +[ + { + "title": "popup with empty coop", + "coop": "", + "opener": "severed" + }, + { + "title": "popup with coop unsafe-none", + "coop": "unsafe-none", + "opener": "severed" + }, + { + "title": "popup with jibberish coop", + "coop": "jibberish", + "opener": "severed" + }, + { + "title": "popup with obsolete coop", + "coop": "same-site", + "opener": "severed" + }, + { + "title": "popup with obsolete coop 2", + "coop": "same-site unsafe-allow-outgoing", + "opener": "severed" + }, + { + "title": "popup with obsolete coop 3", + "coop": "same-origin unsafe-allow-outgoing", + "opener": "severed" + }, + { + "title": "popup with coop same-origin", + "coop": "same-origin", + "opener": "severed" + }, + { + "title": "popup with coop same-origin-allow-popups", + "coop": "same-origin-allow-popups", + "opener": "severed" + } +].forEach(variant => { + popup_test(`Same-site ${variant.title}`, SAME_SITE, { coop: variant.coop }, variant.opener); +}); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/popup-same-origin-with-same-site.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-same-origin-with-same-site.https.html.headers new file mode 100644 index 0000000000..46ad58d83b --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-same-origin-with-same-site.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: same-origin diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/popup-unsafe-none-with-cross-origin.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-unsafe-none-with-cross-origin.https.html new file mode 100644 index 0000000000..31ac569491 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-unsafe-none-with-cross-origin.https.html @@ -0,0 +1,58 @@ +<!doctype html> +<meta charset=utf-8> +<meta name=timeout content=long> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/utils.js"></script> +<script src="resources/common.js"></script> +<script src="resources/popup-test.js"></script> +<script> + +[ + { + "title": "popup with empty coop", + "coop": "", + "opener": "preserved" + }, + { + "title": "popup with coop unsafe-none", + "coop": "unsafe-none", + "opener": "preserved" + }, + { + "title": "popup with jibberish coop", + "coop": "jibberish", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop", + "coop": "same-site", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop 2", + "coop": "same-site unsafe-allow-outgoing", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop 3", + "coop": "same-origin unsafe-allow-outgoing", + "opener": "preserved" + }, + { + "title": "popup with coop same-origin", + "coop": "same-origin", + "opener": "severed" + }, + { + "title": "popup with coop same-origin-allow-popups", + "coop": "same-origin-allow-popups", + "opener": "severed" + } +].forEach(variant => { + popup_test(`Cross-origin ${variant.title}`, CROSS_ORIGIN, { coop: variant.coop }, variant.opener); +}); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/popup-unsafe-none-with-cross-origin.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-unsafe-none-with-cross-origin.https.html.headers new file mode 100644 index 0000000000..073ce7adfb --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-unsafe-none-with-cross-origin.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: unsafe-none diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/popup-unsafe-none-with-same-origin.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-unsafe-none-with-same-origin.https.html new file mode 100644 index 0000000000..18f87048c3 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-unsafe-none-with-same-origin.https.html @@ -0,0 +1,58 @@ +<!doctype html> +<meta charset=utf-8> +<meta name=timeout content=long> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/utils.js"></script> +<script src="resources/common.js"></script> +<script src="resources/popup-test.js"></script> +<script> + +[ + { + "title": "popup with empty coop", + "coop": "", + "opener": "preserved" + }, + { + "title": "popup with coop unsafe-none", + "coop": "unsafe-none", + "opener": "preserved" + }, + { + "title": "popup with jibberish coop", + "coop": "jibberish", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop", + "coop": "same-site", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop 2", + "coop": "same-site unsafe-allow-outgoing", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop 3", + "coop": "same-origin unsafe-allow-outgoing", + "opener": "preserved" + }, + { + "title": "popup with coop same-origin", + "coop": "same-origin", + "opener": "severed" + }, + { + "title": "popup with coop same-origin-allow-popups", + "coop": "same-origin-allow-popups", + "opener": "severed" + } +].forEach(variant => { + popup_test(`Same-origin ${variant.title}`, SAME_ORIGIN, { coop: variant.coop }, variant.opener); +}); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/popup-unsafe-none-with-same-origin.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-unsafe-none-with-same-origin.https.html.headers new file mode 100644 index 0000000000..073ce7adfb --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-unsafe-none-with-same-origin.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: unsafe-none diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/popup-unsafe-none-with-same-site.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-unsafe-none-with-same-site.https.html new file mode 100644 index 0000000000..d1b6b60d7c --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-unsafe-none-with-same-site.https.html @@ -0,0 +1,58 @@ +<!doctype html> +<meta charset=utf-8> +<meta name=timeout content=long> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/utils.js"></script> +<script src="resources/common.js"></script> +<script src="resources/popup-test.js"></script> +<script> + +[ + { + "title": "popup with empty coop", + "coop": "", + "opener": "preserved" + }, + { + "title": "popup with coop unsafe-none", + "coop": "unsafe-none", + "opener": "preserved" + }, + { + "title": "popup with jibberish coop", + "coop": "jibberish", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop", + "coop": "same-site", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop 2", + "coop": "same-site unsafe-allow-outgoing", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop 3", + "coop": "same-origin unsafe-allow-outgoing", + "opener": "preserved" + }, + { + "title": "popup with coop same-origin", + "coop": "same-origin", + "opener": "severed" + }, + { + "title": "popup with coop same-origin-allow-popups", + "coop": "same-origin-allow-popups", + "opener": "severed" + } +].forEach(variant => { + popup_test(`Same-site ${variant.title}`, SAME_SITE, { coop: variant.coop }, variant.opener); +}); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/popup-unsafe-none-with-same-site.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-unsafe-none-with-same-site.https.html.headers new file mode 100644 index 0000000000..073ce7adfb --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-unsafe-none-with-same-site.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: unsafe-none diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/popup-unspecified-with-cross-origin.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-unspecified-with-cross-origin.https.html new file mode 100644 index 0000000000..31ac569491 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-unspecified-with-cross-origin.https.html @@ -0,0 +1,58 @@ +<!doctype html> +<meta charset=utf-8> +<meta name=timeout content=long> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/utils.js"></script> +<script src="resources/common.js"></script> +<script src="resources/popup-test.js"></script> +<script> + +[ + { + "title": "popup with empty coop", + "coop": "", + "opener": "preserved" + }, + { + "title": "popup with coop unsafe-none", + "coop": "unsafe-none", + "opener": "preserved" + }, + { + "title": "popup with jibberish coop", + "coop": "jibberish", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop", + "coop": "same-site", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop 2", + "coop": "same-site unsafe-allow-outgoing", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop 3", + "coop": "same-origin unsafe-allow-outgoing", + "opener": "preserved" + }, + { + "title": "popup with coop same-origin", + "coop": "same-origin", + "opener": "severed" + }, + { + "title": "popup with coop same-origin-allow-popups", + "coop": "same-origin-allow-popups", + "opener": "severed" + } +].forEach(variant => { + popup_test(`Cross-origin ${variant.title}`, CROSS_ORIGIN, { coop: variant.coop }, variant.opener); +}); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/popup-unspecified-with-same-origin.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-unspecified-with-same-origin.https.html new file mode 100644 index 0000000000..18f87048c3 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-unspecified-with-same-origin.https.html @@ -0,0 +1,58 @@ +<!doctype html> +<meta charset=utf-8> +<meta name=timeout content=long> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/utils.js"></script> +<script src="resources/common.js"></script> +<script src="resources/popup-test.js"></script> +<script> + +[ + { + "title": "popup with empty coop", + "coop": "", + "opener": "preserved" + }, + { + "title": "popup with coop unsafe-none", + "coop": "unsafe-none", + "opener": "preserved" + }, + { + "title": "popup with jibberish coop", + "coop": "jibberish", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop", + "coop": "same-site", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop 2", + "coop": "same-site unsafe-allow-outgoing", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop 3", + "coop": "same-origin unsafe-allow-outgoing", + "opener": "preserved" + }, + { + "title": "popup with coop same-origin", + "coop": "same-origin", + "opener": "severed" + }, + { + "title": "popup with coop same-origin-allow-popups", + "coop": "same-origin-allow-popups", + "opener": "severed" + } +].forEach(variant => { + popup_test(`Same-origin ${variant.title}`, SAME_ORIGIN, { coop: variant.coop }, variant.opener); +}); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/popup-unspecified-with-same-site.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-unspecified-with-same-site.https.html new file mode 100644 index 0000000000..d1b6b60d7c --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-unspecified-with-same-site.https.html @@ -0,0 +1,58 @@ +<!doctype html> +<meta charset=utf-8> +<meta name=timeout content=long> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/utils.js"></script> +<script src="resources/common.js"></script> +<script src="resources/popup-test.js"></script> +<script> + +[ + { + "title": "popup with empty coop", + "coop": "", + "opener": "preserved" + }, + { + "title": "popup with coop unsafe-none", + "coop": "unsafe-none", + "opener": "preserved" + }, + { + "title": "popup with jibberish coop", + "coop": "jibberish", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop", + "coop": "same-site", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop 2", + "coop": "same-site unsafe-allow-outgoing", + "opener": "preserved" + }, + { + "title": "popup with obsolete coop 3", + "coop": "same-origin unsafe-allow-outgoing", + "opener": "preserved" + }, + { + "title": "popup with coop same-origin", + "coop": "same-origin", + "opener": "severed" + }, + { + "title": "popup with coop same-origin-allow-popups", + "coop": "same-origin-allow-popups", + "opener": "severed" + } +].forEach(variant => { + popup_test(`Same-site ${variant.title}`, SAME_SITE, { coop: variant.coop }, variant.opener); +}); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/popup-with-structured-header.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-with-structured-header.https.html new file mode 100644 index 0000000000..e337e69cc0 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-with-structured-header.https.html @@ -0,0 +1,33 @@ +<!doctype html> +<meta charset=utf-8> +<meta name=timeout content=long> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/utils.js"></script> +<script src="resources/common.js"></script> +<script src="resources/popup-test.js"></script> +<script> + +[ + { + "title": "popup with structured coop unsafe-none", + "coop": "unsafe-none; report-to=endpoint", + "opener": "severed", + }, + { + "title": "popup with structured coop same-origin", + "coop": "same-origin; report-to=endpoint", + "opener": "preserved", + }, + { + "title": "popup with structured coop same-origin-allow-popups", + "coop": "same-origin-allow-popups; report-to=endpoint", + "opener": "severed", + } +].forEach(variant => { + popup_test(`Same-origin ${variant.title}`, SAME_ORIGIN, { coop: variant.coop }, variant.opener); +}); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/popup-with-structured-header.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-with-structured-header.https.html.headers new file mode 100644 index 0000000000..46ad58d83b --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/popup-with-structured-header.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: same-origin diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/META.yml b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/META.yml new file mode 100644 index 0000000000..0db28208a6 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/META.yml @@ -0,0 +1,6 @@ +suggested_reviewers: + - ArthurSonzogni + - ParisMeuleman + - camillelamy + - hemeryar + - mikewest diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-openee_coop-ro.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-openee_coop-ro.https.html new file mode 100644 index 0000000000..a7e83cc0d9 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-openee_coop-ro.https.html @@ -0,0 +1,82 @@ +<title> + COOP reports are to the opener when the opener used COOP-RO+COEP and then it + tries to access a same-origin openee. +</title> +<meta name=timeout content=long> +<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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/resources/common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/try-access.js"></script> +<script> + +const directory = "/html/cross-origin-opener-policy"; +const redirect_path = directory + "/resources/redirect.py?"; +const same_origin = get_host_info().HTTPS_ORIGIN; + +let runTest = (openee_redirect, name) => promise_test(async t => { + // The test window. + const this_window_token = token(); + + // The "opener" window. This has COOP and a reporter. + const opener_report_token= token(); + const opener_token = token(); + const opener_reportTo = reportToHeaders(opener_report_token); + const opener_url = same_origin + executor_path + opener_reportTo.header + + opener_reportTo.coopReportOnlySameOriginHeader + coep_header + + `&uuid=${opener_token}`; + + // The "openee" window. This is same origin with the "opener". + const openee_report_token = token(); + const openee_token = token(); + const openee_url = same_origin + executor_path + `&uuid=${openee_token}`; + const openee_redirect_url = same_origin + redirect_path + openee_url + const openee_requested_url = openee_redirect ? openee_redirect_url + : openee_url; + + // 1. Create the opener window. + let opener_window_proxy = window.open(opener_url); + t.add_cleanup(() => send(opener_token, "window.close()")); + + // 2. The opener opens it openee. + send(opener_token, ` + openee = window.open("${openee_requested_url}"); + send("${this_window_token}", "ACK 1"); + `); + assert_equals("ACK 1", await receive(this_window_token)); + t.add_cleanup(() => send(openee_token, "window.close()")); + + // 3. Ensure the openee's document to be loaded. + send(openee_token, ` + send("${this_window_token}", "ACK 2"); + `); + assert_equals("ACK 2", await receive(this_window_token)); + + // 4. The opener tries to access its openee. + send(opener_token, addScriptAndTriggerOnload( + directory + "/reporting/resources/try-access.js", + "tryAccess(openee);") + ); + // 5. Check a report sent to the opener. + let report = + await receiveReport(opener_report_token, "access-from-coop-page-to-openee") + assert_equals(report.type, "coop"); + assert_equals(report.url, opener_url.replace(/"/g, '%22')); + assert_equals(report.body.disposition, "reporting"); + assert_equals(report.body.effectivePolicy, "same-origin-plus-coep"); + assert_equals(report.body.property, "blur"); + assert_source_location_found(report); + assert_equals(report.body.openerURL, undefined); + assert_equals(report.body.openeeURL, openee_url); + assert_equals(report.body.otherDocumentURL, undefined); + assert_equals(report.body.referrer, undefined); + assert_equals(report.body.initialPopupURL, openee_requested_url); +}, name); + +runTest(false, "access-from-coop-page-to-openee, same-origin"); +runTest(true , "access-from-coop-page-to-openee, same-origin + redirect"); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-openee_coop-ro_cross-origin.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-openee_coop-ro_cross-origin.https.html new file mode 100644 index 0000000000..fe72a2299f --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-openee_coop-ro_cross-origin.https.html @@ -0,0 +1,85 @@ +<title> + COOP reports are to the opener when the opener used COOP-RO+COEP and then it + tries to access a cross-origin openee. +</title> +<meta name=timeout content=long> +<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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/resources/common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/try-access.js"></script> +<script> + +const directory = "/html/cross-origin-opener-policy"; +const redirect_path = directory + "/resources/redirect.py?"; +const same_origin = get_host_info().HTTPS_ORIGIN; +const cross_origin = get_host_info().HTTPS_REMOTE_ORIGIN; + +let runTest = (openee_redirect, name) => promise_test(async t => { + // The test window. + const this_window_token = token(); + + // The "opener" window. This has COOP and a reporter. + const opener_report_token= token(); + const opener_token = token(); + const opener_reportTo = reportToHeaders(opener_report_token); + const opener_url = same_origin + executor_path + opener_reportTo.header + + opener_reportTo.coopReportOnlySameOriginHeader + coep_header + + `&uuid=${opener_token}`; + + // The "openee" window. This is cross origin with the "opener". + const openee_report_token= token(); + const openee_token = token(); + const openee_url = cross_origin + executor_path + `&uuid=${openee_token}`; + const openee_redirect_url = same_origin + redirect_path + openee_url + const openee_requested_url = openee_redirect ? openee_redirect_url + : openee_url; + + // 1. Create the opener window. + let opener_window_proxy = window.open(opener_url); + t.add_cleanup(() => send(opener_token, "window.close()")); + + // 2. The opener opens it openee. + send(opener_token, ` + openee = window.open("${openee_requested_url}"); + send("${this_window_token}", "ACK 1"); + `); + assert_equals("ACK 1", await receive(this_window_token)); + t.add_cleanup(() => send(openee_token, "window.close()")); + + // 3. Ensure the openee's document to be loaded. + send(openee_token, ` + send("${this_window_token}", "ACK 2"); + `); + assert_equals("ACK 2", await receive(this_window_token)); + + // 4. The opener tries to access its openee. + send(opener_token, addScriptAndTriggerOnload( + directory + "/reporting/resources/try-access.js", + "tryAccess(openee);") + ); + + + // 5. Check a report sent to the opener. + let report = + await receiveReport(opener_report_token, "access-from-coop-page-to-openee") + assert_equals(report.type, "coop"); + assert_equals(report.url, opener_url.replace(/"/g, '%22')); + assert_equals(report.body.disposition, "reporting"); + assert_equals(report.body.effectivePolicy, "same-origin-plus-coep"); + assert_equals(report.body.property, "blur"); + assert_source_location_found(report); + assert_equals(report.body.openerURL, undefined); + assert_equals(report.body.openeeURL, ""); + assert_equals(report.body.otherDocumentURL, undefined); + assert_equals(report.body.referrer, undefined); + assert_equals(report.body.initialPopupURL, openee_requested_url); +}, name); + +runTest(false, "access-from-coop-page-to-openee, cross-origin"); +runTest(true , "access-from-coop-page-to-openee, cross-origin + redirect"); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-opener_coop-ro.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-opener_coop-ro.https.html new file mode 100644 index 0000000000..005339a06e --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-opener_coop-ro.https.html @@ -0,0 +1,63 @@ +<title> + COOP reports are sent when the openee used COOP-RO+COEP and then tries to + access its same-origin opener. +</title> +<meta name=timeout content=long> +<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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/resources/common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/try-access.js"></script> +<script> + +const directory = "/html/cross-origin-opener-policy"; +const redirect_path = directory + "/resources/redirect.py?"; +const same_origin = get_host_info().HTTPS_ORIGIN; + +let runTest = (openee_redirect, name) => promise_test(async t => { + const report_token = token(); + const openee_token = token(); + + const opener_url = location.href; + + const reportTo = reportToHeaders(report_token); + const openee_url = same_origin + executor_path + + reportTo.header + reportTo.coopReportOnlySameOriginHeader + coep_header + + `&uuid=${openee_token}`; + const openee_redirect_url = same_origin + redirect_path + openee_url + const openee_requested_url = openee_redirect ? openee_redirect_url + : openee_url; + + const openee = window.open(openee_requested_url); + t.add_cleanup(() => send(openee_token, "window.close()")) + + // 1. Try to access the opener. A report is sent, because of COOP-RO+COEP. + + send(openee_token, addScriptAndTriggerOnload( + directory + "/reporting/resources/try-access.js", + "tryAccess(opener);") + ); + + // 2. Check a report is sent to the openee. + let report = + await receiveReport(report_token, "access-from-coop-page-to-opener") + assert_equals(report.type, "coop"); + assert_equals(report.url, openee_url.replace(/"/g, '%22')); + assert_equals(report.body.disposition, "reporting"); + assert_equals(report.body.effectivePolicy, "same-origin-plus-coep"); + assert_equals(report.body.property, "blur"); + assert_source_location_found(report); + assert_equals(report.body.openerURL, opener_url); + assert_equals(report.body.openeeURL, undefined); + assert_equals(report.body.otherDocumentURL, undefined); + assert_equals(report.body.referrer, opener_url); + assert_equals(report.body.initialPopupURL, undefined); +}, name); + +runTest(false, "access-from-coop-page-to-opener, same-origin"); +runTest(true , "access-from-coop-page-to-opener, same-origin + redirect"); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-opener_coop-ro_cross-origin.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-opener_coop-ro_cross-origin.https.html new file mode 100644 index 0000000000..eedfaa557f --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-opener_coop-ro_cross-origin.https.html @@ -0,0 +1,63 @@ +<title> + COOP reports are sent when the openee used COOP-RO+COEP and then tries to + access its cross-origin opener. +</title> +<meta name=timeout content=long> +<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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/resources/common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/try-access.js"></script> +<script> + +const directory = "/html/cross-origin-opener-policy"; +const redirect_path = directory + "/resources/redirect.py?"; +const same_origin = get_host_info().HTTPS_ORIGIN; +const cross_origin = get_host_info().HTTPS_REMOTE_ORIGIN; + +let runTest = (openee_redirect, name) => promise_test(async t => { + const report_token = token(); + const openee_token = token(); + + const opener_origin = location.origin + '/'; + + const reportTo = reportToHeaders(report_token); + const openee_url = cross_origin + executor_path + + reportTo.header + reportTo.coopReportOnlySameOriginHeader + coep_header + + `&uuid=${openee_token}`; + const openee_redirect_url = same_origin + redirect_path + openee_url + const openee_requested_url = openee_redirect ? openee_redirect_url + : openee_url; + + const openee = window.open(openee_requested_url); + t.add_cleanup(() => send(openee_token, "window.close()")) + + // 1. Try to access the opener. A report is sent, because of COOP-RO+COEP. + send(openee_token, addScriptAndTriggerOnload( + directory + "/reporting/resources/try-access.js", + "tryAccess(opener);") + ); + + // 2. Check a report is sent to the openee. + let report = + await receiveReport(report_token, "access-from-coop-page-to-opener") + assert_equals(report.type, "coop"); + assert_equals(report.url, openee_url.replace(/"/g, '%22')); + assert_equals(report.body.disposition, "reporting"); + assert_equals(report.body.effectivePolicy, "same-origin-plus-coep"); + assert_equals(report.body.property, "blur"); + assert_source_location_found(report); + assert_equals(report.body.openerURL, ""); + assert_equals(report.body.openeeURL, undefined); + assert_equals(report.body.otherDocumentURL, undefined); + assert_equals(report.body.referrer, opener_origin); + assert_equals(report.body.initialPopupURL, undefined); +}, name); + +runTest(false, "access-from-coop-page-to-opener, cross-origin"); +runTest(true , "access-from-coop-page-to-opener, cross-origin + redirect"); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-other_coop-ro.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-other_coop-ro.https.html new file mode 100644 index 0000000000..90df0e4e99 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-other_coop-ro.https.html @@ -0,0 +1,92 @@ +<title> + One window accesses a second one. They are aren't related by an opener/openee + relationship. The first window has set + Cross-Origin-Opener-Policy-Report-Only:same-origin, so it receives a + "access-from-coop-page-to-other" report. +</title> +<meta name=timeout content=long> +<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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/resources/common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/try-access.js"></script> +<script> + +const directory = "/html/cross-origin-opener-policy"; +const same_origin = get_host_info().HTTPS_ORIGIN; + +let escapeComma = url => url.replace(/,/g, '\\,'); + +promise_test(async t => { + const report_token= token(); + const report_to = reportToHeaders(report_token); + + // The test window. + const this_window_token = token(); + + // The "opener" window. With COOP:same-origin + reporter. + const opener_token = token(); + const opener_url = same_origin + executor_path + report_to.header + + report_to.coopReportOnlySameOriginHeader + coep_header + + `&uuid=${opener_token}`; + + // The "openee" window. With COOP:same-origin + reporter. + const openee_token = token(); + const openee_url = same_origin + executor_path + report_to.header + + report_to.coopReportOnlySameOriginHeader + coep_header + + `&uuid=${openee_token}`; + + // The "other" window. + const other_token = token(); + const other_url = same_origin + executor_path + report_to.header + + `&uuid=${other_token}`; + + t.add_cleanup(() => { + send(opener_token, "window.close()") + send(openee_token, "window.close()") + send(other_token, "window.close()") + }) + + // 1. Create the "opener" window. + let opener_window_proxy = window.open(opener_url); + + // 2. Create the "openee" window. + send(opener_token, ` + window.openee = window.open('${escapeComma(openee_url)}'); + `); + + // 3. Create the "other" window. + send(openee_token, ` + window.other = window.open('${escapeComma(other_url)}'); + `); + + // 4. Wait for "other" to load its document. + send(other_token, `send('${this_window_token}', "Loaded");`); + assert_equals(await receive(this_window_token), "Loaded"); + + // 5. "opener" accesses "other" window, through "openee". + send(opener_token, addScriptAndTriggerOnload( + directory + "/reporting/resources/try-access.js", + "tryAccess(openee.other);") + ); + + // 6. Check a report is sent to the openee. + let report = + await receiveReport(report_token, "access-from-coop-page-to-other") + assert_equals(report.type, "coop"); + assert_equals(report.url, opener_url.replace(/"/g, '%22')); + assert_equals(report.body.disposition, "reporting"); + assert_equals(report.body.effectivePolicy, "same-origin-plus-coep"); + assert_equals(report.body.property, "blur"); + assert_source_location_found(report); + assert_equals(report.body.openerURL, undefined); + assert_equals(report.body.openeeURL, undefined); + assert_equals(report.body.otherDocumentURL, other_url.replace(/"/g, '%22')); + assert_equals(report.body.referrer, undefined); + assert_equals(report.body.initialPopupURL, undefined); +}, "access-from-coop-page-to-other (COOP-RO)"); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-other_coop-ro_cross-origin.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-other_coop-ro_cross-origin.https.html new file mode 100644 index 0000000000..f0d60c2531 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-other_coop-ro_cross-origin.https.html @@ -0,0 +1,93 @@ +<title> + One window accesses a second one. They are aren't related by an opener/openee + relationship. The first window has set + Cross-Origin-Opener-Policy-Report-Only:same-origin, so it receives a + "access-from-coop-page-to-other" report. +</title> +<meta name=timeout content=long> +<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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/resources/common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/try-access.js"></script> +<script> + +const directory = "/html/cross-origin-opener-policy"; +const same_origin= get_host_info().HTTPS_ORIGIN; +const cross_origin= get_host_info().HTTPS_REMOTE_ORIGIN; + +let escapeComma = url => url.replace(/,/g, '\\,'); + +promise_test(async t => { + const report_token= token(); + const report_to = reportToHeaders(report_token); + + // The test window. + const this_window_token = token(); + + // The "opener" window. With COOP:same-origin + reporter. + const opener_token = token(); + const opener_url = same_origin + executor_path + report_to.header + + report_to.coopReportOnlySameOriginHeader + coep_header + + `&uuid=${opener_token}`; + + // The "openee" window. With COOP:same-origin + reporter. + const openee_token = token(); + const openee_url = same_origin + executor_path + report_to.header + + report_to.coopReportOnlySameOriginHeader + coep_header + + `&uuid=${openee_token}`; + + // The "other" window. + const other_token = token(); + const other_url = cross_origin + executor_path + report_to.header + + `&uuid=${other_token}`; + + t.add_cleanup(() => { + send(opener_token, "window.close()") + send(openee_token, "window.close()") + send(other_token, "window.close()") + }) + + // 1. Create the "opener" window. + let opener_window_proxy = window.open(opener_url); + + // 2. Create the "openee" window. + send(opener_token, ` + window.openee = window.open('${escapeComma(openee_url)}'); + `); + + // 3. Create the "other" window. + send(openee_token, ` + window.other = window.open('${escapeComma(other_url)}'); + `); + + // 4. Wait for "other" to load its document. + send(other_token, `send('${this_window_token}', "Loaded");`); + assert_equals(await receive(this_window_token), "Loaded"); + + // 5. "opener" accesses "other" window, through "openee". + + send(opener_token, addScriptAndTriggerOnload( + directory + "/reporting/resources/try-access.js", + "tryAccess(openee.other);") + ); + + // 6. Check a report is sent to the openee. + let report = + await receiveReport(report_token, "access-from-coop-page-to-other") + assert_equals(report.type, "coop"); + assert_equals(report.url, opener_url.replace(/"/g, '%22')); + assert_equals(report.body.disposition, "reporting"); + assert_equals(report.body.effectivePolicy, "same-origin-plus-coep"); + assert_equals(report.body.property, "blur"); + assert_source_location_found(report); + assert_equals(report.body.openerURL, undefined); + assert_equals(report.body.openeeURL, undefined); + assert_equals(report.body.otherDocumentURL, ""); + assert_equals(report.body.referrer, undefined); +}, "access-from-coop-page-to-other (COOP-RO)"); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-openee_coop-ro.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-openee_coop-ro.https.html new file mode 100644 index 0000000000..9f0a8821a4 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-openee_coop-ro.https.html @@ -0,0 +1,77 @@ +<title> + COOP reports are to the opener when the opener used COOP-RO+COEP and then its + same-origin openee tries to access it. +</title> +<meta name=timeout content=long> +<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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/resources/common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/try-access.js"></script> +<script> + +const directory = "/html/cross-origin-opener-policy"; +const redirect_path = directory + "/resources/redirect.py?"; +const same_origin = get_host_info().HTTPS_ORIGIN; + +let runTest = (openee_redirect, name) => promise_test(async t => { + // The test window. + const this_window_token = token(); + + // The "opener" window. This has COOP and a reporter. + const opener_report_token= token(); + const opener_token = token(); + const opener_reportTo = reportToHeaders(opener_report_token); + const opener_url = same_origin + executor_path + opener_reportTo.header + + opener_reportTo.coopReportOnlySameOriginHeader + coep_header + + `&uuid=${opener_token}`; + + // The "openee" window. This is same origin with the "opener". + const openee_report_token= token(); + const openee_token = token(); + const openee_url = same_origin + executor_path + `&uuid=${openee_token}`; + const openee_redirect_url = same_origin + redirect_path + openee_url + const openee_requested_url = openee_redirect ? openee_redirect_url + : openee_url; + + // 1. Create the opener window. + let opener_window_proxy = window.open(opener_url); + t.add_cleanup(() => send(opener_token, "window.close()")); + + // 2. The opener opens its openee. + send(opener_token, ` + openee = window.open("${openee_requested_url}"); + send("${this_window_token}", "ACK 1"); + `); + assert_equals("ACK 1", await receive(this_window_token)); + t.add_cleanup(() => send(openee_token, "window.close()")); + + // 3. The openee tries to access its opener. + send(openee_token, addScriptAndTriggerOnload( + directory + "/reporting/resources/try-access.js", + "tryAccess(opener);") + ); + + // 4. Check a report sent to the opener. + let report = + await receiveReport(opener_report_token, "access-to-coop-page-from-openee") + assert_equals(report.type, "coop"); + assert_equals(report.url, opener_url.replace(/"/g, '%22')); + assert_equals(report.body.disposition, "reporting"); + assert_equals(report.body.effectivePolicy, "same-origin-plus-coep"); + assert_equals(report.body.property, "blur"); + assert_source_location_missing(report); + assert_equals(report.body.openerURL, undefined); + assert_equals(report.body.openeeURL, openee_url); + assert_equals(report.body.otherDocumentURL, undefined); + assert_equals(report.body.referrer, undefined); + assert_equals(report.body.initialPopupURL, openee_requested_url); +}, name); + +runTest(false, "access-to-coop-page-from-openee, same-origin"); +runTest(true , "access-to-coop-page-from-openee, same-origin + redirect"); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-openee_coop-ro_cross-origin.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-openee_coop-ro_cross-origin.https.html new file mode 100644 index 0000000000..d9577836d9 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-openee_coop-ro_cross-origin.https.html @@ -0,0 +1,79 @@ +<title> + COOP reports are to the opener when the opener used COOP-RO+COEP and then its + cross-origin openee tries to access it. +</title> +<meta name=timeout content=long> +<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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/resources/common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/try-access.js"></script> +<script> + +const directory = "/html/cross-origin-opener-policy"; +const redirect_path = directory + "/resources/redirect.py?"; +const same_origin = get_host_info().HTTPS_REMOTE_ORIGIN; +const cross_origin= get_host_info().HTTPS_ORIGIN; + +let runTest = (openee_redirect, name) => promise_test(async t => { + // The test window. + const this_window_token = token(); + + // The "opener" window. This has COOP and a reporter. + const opener_report_token= token(); + const opener_token = token(); + const opener_reportTo = reportToHeaders(opener_report_token); + const opener_url = same_origin + executor_path + opener_reportTo.header + + opener_reportTo.coopReportOnlySameOriginHeader + coep_header + + `&uuid=${opener_token}`; + + // The "openee" window. This is cross origin with the "opener". + const openee_report_token= token(); + const openee_token = token(); + const openee_url = cross_origin + executor_path + `&uuid=${openee_token}`; + const openee_redirect_url = same_origin + redirect_path + openee_url + const openee_requested_url = openee_redirect ? openee_redirect_url + : openee_url; + + // 1. Create the opener window. + let opener_window_proxy = window.open(opener_url); + t.add_cleanup(() => send(opener_token, "window.close()")); + + // 2. The opener opens its openee. + send(opener_token, ` + openee = window.open("${openee_requested_url}"); + send("${this_window_token}", "ACK 1"); + `); + assert_equals("ACK 1", await receive(this_window_token)); + t.add_cleanup(() => send(openee_token, "window.close()")); + + // 3. The openee tries to access its opener. + send(openee_token, addScriptAndTriggerOnload( + directory + "/reporting/resources/try-access.js", + "tryAccess(opener);") + ); + + // 4. Check a report sent to the opener. + let report = + await receiveReport(opener_report_token, "access-to-coop-page-from-openee") + assert_equals(report.type, "coop"); + assert_equals(report.url, opener_url.replace(/"/g, '%22')); + assert_equals(report.body.disposition, "reporting"); + assert_equals(report.body.effectivePolicy, "same-origin-plus-coep"); + assert_equals(report.body.property, "blur"); + assert_source_location_missing(report); + assert_equals(report.body.openerURL, undefined); + assert_equals(report.body.openeeURL, ""); + assert_equals(report.body.otherDocumentURL, undefined); + assert_equals(report.body.referrer, undefined); + assert_equals(report.body.referrer, undefined); + assert_equals(report.body.initialPopupURL, openee_requested_url); +}, name); + +runTest(false, "access-to-coop-page-from-openee, cross-origin"); +runTest(true , "access-to-coop-page-from-openee, cross-origin + redirect)"); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-opener_coop-ro.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-opener_coop-ro.https.html new file mode 100644 index 0000000000..8a643d762c --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-opener_coop-ro.https.html @@ -0,0 +1,67 @@ +<title> + COOP reports are sent when the openee used COOP-RO+COEP and then its + same-origin opener tries to access it. +</title> +<meta name=timeout content=long> +<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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/try-access.js"></script> +<script> + +const directory = "/html/cross-origin-opener-policy"; +const redirect_path = directory + "/resources/redirect.py?"; +const same_origin = get_host_info().HTTPS_ORIGIN; + +let runTest = (openee_redirect, name) => promise_test(async t => { + const report_token = token(); + const openee_token = token(); + const opener_token = token(); // The current test window. + + const opener_url = location.href; + + const reportTo = reportToHeaders(report_token); + const openee_url = same_origin + executor_path + reportTo.header + + reportTo.coopReportOnlySameOriginHeader + coep_header + + `&uuid=${openee_token}`; + const openee_redirect_url = same_origin + redirect_path + openee_url + const openee_requested_url = openee_redirect ? openee_redirect_url + : openee_url; + + + const openee = window.open(openee_requested_url); + t.add_cleanup(() => send(openee_token, "window.close()")) + + // 1. Make sure the new document to be loaded. + send(openee_token, ` + send("${opener_token}", "Ready"); + `); + let reply = await receive(opener_token); + assert_equals(reply, "Ready"); + + // 2. Try to access the openee. A report is sent, because of COOP-RO+COEP. + tryAccess(openee); + + // 3. Check a report is sent to the openee. + let report = + await receiveReport(report_token, "access-to-coop-page-from-opener") + assert_equals(report.type, "coop"); + assert_equals(report.url, openee_url.replace(/"/g, '%22')); + assert_equals(report.body.disposition, "reporting"); + assert_equals(report.body.effectivePolicy, "same-origin-plus-coep"); + assert_equals(report.body.property, "blur"); + assert_source_location_missing(report); + assert_equals(report.body.openerURL, opener_url); + assert_equals(report.body.openeeURL, undefined); + assert_equals(report.body.otherDocumentURL, undefined); + assert_equals(report.body.referrer, opener_url); + assert_equals(report.body.initialPopupURL, undefined); +}, name); + +runTest(false, "access-to-coop-page-from-opener, same-origin"); +runTest(true , "access-to-coop-page-from-opener, same-origin + redirect"); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-opener_coop-ro_cross-origin.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-opener_coop-ro_cross-origin.https.html new file mode 100644 index 0000000000..7e1ae870a7 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-opener_coop-ro_cross-origin.https.html @@ -0,0 +1,68 @@ +<title> + COOP reports are sent when the openee used COOP-RO+COEP and then its + cross-origin opener tries to access it. +</title> +<meta name=timeout content=long> +<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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/try-access.js"></script> +<script> + +const directory = "/html/cross-origin-opener-policy"; +const redirect_path = directory + "/resources/redirect.py?"; +const same_origin = get_host_info().HTTPS_ORIGIN; +const cross_origin = get_host_info().HTTPS_REMOTE_ORIGIN; + +let runTest = (openee_redirect, name) => promise_test(async t => { + const report_token = token(); + const openee_token = token(); + const opener_token = token(); // The current test window. + + const opener_origin = location.origin + '/'; + + const reportTo = reportToHeaders(report_token); + const openee_url = cross_origin + executor_path + + reportTo.header + reportTo.coopReportOnlySameOriginHeader + coep_header + + `&uuid=${openee_token}`; + const openee_redirect_url = same_origin + redirect_path + openee_url + const openee_requested_url = openee_redirect ? openee_redirect_url + : openee_url; + + + const openee = window.open(openee_requested_url); + t.add_cleanup(() => send(openee_token, "window.close()")) + + // 1. Make sure the new document to be loaded. + send(openee_token, ` + send("${opener_token}", "Ready"); + `); + let reply = await receive(opener_token); + assert_equals(reply, "Ready"); + + // 2. Try to access the openee. A report is sent, because of COOP-RO+COEP. + tryAccess(openee); + + // 3. Check a report is sent to the openee. + let report = + await receiveReport(report_token, "access-to-coop-page-from-opener") + assert_equals(report.type, "coop"); + assert_equals(report.url, openee_url.replace(/"/g, '%22')); + assert_equals(report.body.disposition, "reporting"); + assert_equals(report.body.effectivePolicy, "same-origin-plus-coep"); + assert_equals(report.body.property, "blur"); + assert_source_location_missing(report); + assert_equals(report.body.openerURL, ""); + assert_equals(report.body.openeeURL, undefined); + assert_equals(report.body.otherDocumentURL, undefined); + assert_equals(report.body.referrer, opener_origin); + assert_equals(report.body.initialPopupURL, undefined); +}, name); + +runTest(false, "access-to-coop-page-from-opener, cross-origin"); +runTest(true , "access-to-coop-page-from-opener, cross-origin + redirect"); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-other_coop-ro.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-other_coop-ro.https.html new file mode 100644 index 0000000000..b73bab8610 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-other_coop-ro.https.html @@ -0,0 +1,82 @@ +<title> + One window accesses a second one. They are aren't related by an opener/openee + relationship. The second window has set + Cross-Origin-Opener-Policy-Report-Only:same-origin, so it receives a + "access-to-coop-page-from-other" report. +</title> +<meta name=timeout content=long> +<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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/resources/common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/try-access.js"></script> +<script> + +const directory = "/html/cross-origin-opener-policy"; +const same_origin = get_host_info().HTTPS_ORIGIN; + +promise_test(async t => { + // The test window. + const this_window_token = token(); + + // The "opener" window. + const opener_token = token(); + const opener_url = same_origin + executor_path + `&uuid=${opener_token}`; + + // The "openee" window. With COOP:same-origin + reporter. + const openee_report_token= token(); + const openee_token = token(); + const openee_reportTo = reportToHeaders(openee_report_token); + const openee_url = same_origin + executor_path + openee_reportTo.header + + openee_reportTo.coopReportOnlySameOriginHeader + coep_header + + `&uuid=${openee_token}`; + + // The "other" window. + const other_token = token(); + const other_url = same_origin + executor_path + `&uuid=${other_token}`; + + t.add_cleanup(() => { + send(opener_token, "window.close()") + send(openee_token, "window.close()") + send(other_token, "window.close()") + }) + + // 1. Create the opener window. + let opener_window_proxy = window.open(opener_url); + + // 2. The opener opens its openee and the other window. + send(opener_token, ` + window.openee = window.open('${openee_url.replace(/,/g, '\\,')}'); + window.other = window.open('${other_url}'); + `); + + // 3. Make sure the openee is loaded. + send(openee_token, `send("${this_window_token}", "Loaded");`); + assert_equals(await receive(this_window_token), "Loaded"); + + // 4. The "other" window attempts to access the openee though the opener. + send(other_token, addScriptAndTriggerOnload( + directory + "/reporting/resources/try-access.js", + "tryAccess(opener.openee);") + ); + + // 4. Check a report sent to the openee. + let report = + await receiveReport(openee_report_token, "access-to-coop-page-from-other") + assert_equals(report.type, "coop"); + assert_equals(report.url, openee_url.replace(/"/g, '%22')); + assert_equals(report.body.disposition, "reporting"); + assert_equals(report.body.effectivePolicy, "same-origin-plus-coep"); + assert_equals(report.body.property, "blur"); + assert_source_location_missing(report); + assert_equals(report.body.openerURL, undefined); + assert_equals(report.body.openeeURL, undefined); + assert_equals(report.body.otherDocumentURL, other_url); + assert_equals(report.body.referrer, undefined); + assert_equals(report.body.initialPopupURL, undefined); +}, "access-to-coop-page-from-other (COOP-RO)"); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-other_coop-ro_cross-origin.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-other_coop-ro_cross-origin.https.html new file mode 100644 index 0000000000..c86daa3dca --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-other_coop-ro_cross-origin.https.html @@ -0,0 +1,83 @@ +<title> + One window accesses a second one. They are aren't related by an opener/openee + relationship. The second window has set + Cross-Origin-Opener-Policy-Report-Only:same-origin, so it receives a + "access-to-coop-page-from-other" report. +</title> +<meta name=timeout content=long> +<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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/resources/common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/try-access.js"></script> +<script> + +const directory = "/html/cross-origin-opener-policy"; +const same_origin = get_host_info().HTTPS_ORIGIN; +const cross_origin = get_host_info().HTTPS_REMOTE_ORIGIN; + +promise_test(async t => { + // The test window. + const this_window_token = token(); + + // The "opener" window. + const opener_token = token(); + const opener_url = same_origin + executor_path + `&uuid=${opener_token}`; + + // The "openee" window. With COOP:same-origin + reporter. + const openee_report_token= token(); + const openee_token = token(); + const openee_reportTo = reportToHeaders(openee_report_token); + const openee_url = cross_origin + executor_path + openee_reportTo.header + + openee_reportTo.coopReportOnlySameOriginHeader + coep_header + + `&uuid=${openee_token}`; + + // The "other" window. + const other_token = token(); + const other_url = same_origin + executor_path + `&uuid=${other_token}`; + + t.add_cleanup(() => { + send(opener_token, "window.close()") + send(openee_token, "window.close()") + send(other_token, "window.close()") + }) + + // 1. Create the opener window. + let opener_window_proxy = window.open(opener_url); + + // 2. The opener opens its openee and the other window. + send(opener_token, ` + window.openee = window.open('${openee_url.replace(/,/g, '\\,')}'); + window.other = window.open('${other_url}'); + `); + + // 3. Make sure the openee is loaded. + send(openee_token, `send("${this_window_token}", "Loaded");`); + assert_equals(await receive(this_window_token), "Loaded"); + + // 4. The "other" window attempts to access the openee though the opener. + send(other_token, addScriptAndTriggerOnload( + directory + "/reporting/resources/try-access.js", + "tryAccess(opener.openee);") + ); + + // 4. Check a report sent to the openee. + let report = + await receiveReport(openee_report_token, "access-to-coop-page-from-other") + assert_equals(report.type, "coop"); + assert_equals(report.url, openee_url.replace(/"/g, '%22')); + assert_equals(report.body.disposition, "reporting"); + assert_equals(report.body.effectivePolicy, "same-origin-plus-coep"); + assert_equals(report.body.property, "blur"); + assert_source_location_missing(report); + assert_equals(report.body.openerURL, undefined); + assert_equals(report.body.openeeURL, undefined); + assert_equals(report.body.otherDocumentURL, ""); + assert_equals(report.body.referrer, undefined); + assert_equals(report.body.initialPopupURL, undefined); +}, "access-to-coop-page-from-other (COOP-RO)"); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-blur.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-blur.https.html new file mode 100644 index 0000000000..849bf6579a --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-blur.https.html @@ -0,0 +1,13 @@ +<title> Check openee.blur() access is checked</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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/test-access-property.js"></script> +<script> + +testAccessProperty("blur", w => w.blur()); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-close.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-close.https.html new file mode 100644 index 0000000000..7696600488 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-close.https.html @@ -0,0 +1,13 @@ +<title> Check openee.close() access is checked</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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/test-access-property.js"></script> +<script> + +testAccessProperty("close", w => w.close()); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-closed.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-closed.https.html new file mode 100644 index 0000000000..c678d18a80 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-closed.https.html @@ -0,0 +1,13 @@ +<title> Check openee.closed access is checked</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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/test-access-property.js"></script> +<script> + +testAccessProperty("closed", w => w.closed); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-focus.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-focus.https.html new file mode 100644 index 0000000000..363c0d294f --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-focus.https.html @@ -0,0 +1,13 @@ +<title> Check openee.focus() access is checked</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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/test-access-property.js"></script> +<script> + +testAccessProperty("focus", w => w.focus()); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-frames.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-frames.https.html new file mode 100644 index 0000000000..fc1925045f --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-frames.https.html @@ -0,0 +1,13 @@ +<title> Check openee.frames access is checked</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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/test-access-property.js"></script> +<script> + +testAccessProperty("frames", w => w.frames); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-indexed-getter.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-indexed-getter.https.html new file mode 100644 index 0000000000..b6c5f5acb1 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-indexed-getter.https.html @@ -0,0 +1,66 @@ +<title> Check reports are sent for the indexed getter</title> +<meta name=timeout content=long> +<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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script> + +const directory = "/html/cross-origin-opener-policy"; +const executor_path = "/common/dispatcher/executor.html?pipe="; +const coep_header = '|header(Cross-Origin-Embedder-Policy,require-corp)'; + +let origin = [ + ["cross-origin" , get_host_info().HTTPS_REMOTE_ORIGIN ] , + ["same-site" , get_host_info().HTTPS_ORIGIN ] , +]; + +let testCase = [ +//[operation , expectReport ] , + [w => w[0] , true ], // Existing iframe. + [w => w[1] , false ], // Out of bounds (positive). + [w => w[-1] , false ], // Out of bounds (negative). +]; + +origin.forEach(([origin_name, origin]) => { + testCase.forEach(([op, expectReport]) => { + promise_test(async t => { + const opener_token = token(); + const openee_token = token(); + + const openee_url = origin+ executor_path + `&uuid=${openee_token}`; + const openee = window.open(openee_url); + t.add_cleanup(() => send(openee_token, "window.close()")) + + // 1. Create an iframe in the openee. + send(openee_token, ` + let iframe = document.createElement("iframe"); + document.body.appendChild(iframe); + + send("${opener_token}", "openee loaded"); + `); + let reply = await receive(opener_token); + assert_equals(reply, "openee loaded"); + + // 2. Try to access the openee. + let observer = new ReportingObserver(()=>{}); + observer.observe(); + try {op(openee)} catch(e) {} + let reports = observer.takeRecords(); + observer.disconnect(); + + // 3. Check the received reports. + if (expectReport) { + assert_equals(reports.length, 1); + assert_equals(reports[0].type, "coop-access-violation"); + assert_equals(reports[0].body.property, "indexed"); + } else { + assert_equals(reports.length, 0); + } + + }, `${origin_name} > ${op}`); +}); +}); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-indexed-getter.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-indexed-getter.https.html.headers new file mode 100644 index 0000000000..64f4d5fedf --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-indexed-getter.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy-Report-Only: same-origin; report-to="none" diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-length.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-length.https.html new file mode 100644 index 0000000000..a9f3614cb5 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-length.https.html @@ -0,0 +1,13 @@ +<title> Check openee.length access is checked</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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/test-access-property.js"></script> +<script> + +testAccessProperty("length", w => w.length); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-location-get.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-location-get.https.html new file mode 100644 index 0000000000..442817748d --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-location-get.https.html @@ -0,0 +1,13 @@ +<title> Check openee.location access is checked</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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/test-access-property.js"></script> +<script> + +testAccessProperty("location", w => w.location); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-location-set.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-location-set.https.html new file mode 100644 index 0000000000..e42f084821 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-location-set.https.html @@ -0,0 +1,13 @@ +<title> Check openee.location access is checked</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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/test-access-property.js"></script> +<script> + +testAccessProperty("location", w => w.location = "#"); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-named-getter.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-named-getter.https.html new file mode 100644 index 0000000000..27be9a48d1 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-named-getter.https.html @@ -0,0 +1,71 @@ +<title> Check reports are sent for the indexed getter</title> +<meta name=timeout content=long> +<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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script> + +const executor_path = "/common/dispatcher/executor.html?pipe="; +let crossOrigin = ["cross-origin" , get_host_info().HTTPS_REMOTE_ORIGIN ]; +let sameOrigin = ["same-site" , get_host_info().HTTPS_ORIGIN ]; + +let testCase = [ +//[ operation , origin , expectReport ], + [ w => w["iframeName"] , sameOrigin , true ], + [ w => w["iframeName"] , crossOrigin , true ], + [ w => w["divID"] , sameOrigin , true ], + [ w => w["divID"] , crossOrigin , false ], + [ w => w["existingGlobal"] , sameOrigin , false ], + [ w => w["existingGlobal"] , crossOrigin , false ], + [ w => w["missingGlobal"] , sameOrigin , false ], + [ w => w["missingGlobal"] , crossOrigin , false ], +]; + +testCase.forEach(([op, [origin_name, origin], expectReport]) => { + promise_test(async t => { + const opener_token = token(); + const openee_token = token(); + + const openee_url = origin + executor_path + `&uuid=${openee_token}`; + const openee = window.open(openee_url); + t.add_cleanup(() => send(openee_token, "window.close()")) + + // 1. Make sure the new document to be loaded. Populate the document. + send(openee_token, ` + let iframe = document.createElement("iframe"); + iframe.name = "iframeName"; + document.body.appendChild(iframe); + + let div = document.createElement("div"); + div.id = "divID"; + document.body.appendChild(div); + + window.existingGlobal = "test"; + + send("${opener_token}", "Ready"); + `); + let reply = await receive(opener_token); + assert_equals(reply, "Ready"); + + // 2. Try to access the openee. + let observer = new ReportingObserver(()=>{}); + observer.observe(); + try {op(openee)} catch(e) {} + let reports = observer.takeRecords(); + observer.disconnect(); + + // 3. Check the received reports. + if (expectReport) { + assert_equals(reports.length, 1); + assert_equals(reports[0].type, "coop-access-violation"); + assert_equals(reports[0].body.property, "named"); + } else { + assert_equals(reports.length, 0); + } + + }, `${origin_name} > ${op}`); +}); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-named-getter.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-named-getter.https.html.headers new file mode 100644 index 0000000000..64f4d5fedf --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-named-getter.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy-Report-Only: same-origin; report-to="none" diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-opener-get.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-opener-get.https.html new file mode 100644 index 0000000000..b99dfdc562 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-opener-get.https.html @@ -0,0 +1,13 @@ +<title> Check openee.opener access is checked</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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/test-access-property.js"></script> +<script> + +testAccessProperty("opener", w => w.opener); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-opener-set.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-opener-set.https.html new file mode 100644 index 0000000000..10c251140b --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-opener-set.https.html @@ -0,0 +1,13 @@ +<title> Check openee.opener access is checked</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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/test-access-property.js"></script> +<script> + +testAccessProperty("opener", w => w.opener = "", /* expectReport = */false); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-postmessage-1.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-postmessage-1.https.html new file mode 100644 index 0000000000..a9168fdaa5 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-postmessage-1.https.html @@ -0,0 +1,13 @@ +<title> Check openee.postMessage(arg1, arg2) access is checked</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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/test-access-property.js"></script> +<script> + +testAccessProperty("postMessage", w => w.postMessage("", "")); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-postmessage-2.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-postmessage-2.https.html new file mode 100644 index 0000000000..4341f245d5 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-postmessage-2.https.html @@ -0,0 +1,13 @@ +<title> Check openee.postMessage(arg1) access is checked</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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/test-access-property.js"></script> +<script> + +testAccessProperty("postMessage", w => w.postMessage("")); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-self.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-self.https.html new file mode 100644 index 0000000000..7a7d5a3fec --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-self.https.html @@ -0,0 +1,13 @@ +<title> Check openee.self access is checked</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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/test-access-property.js"></script> +<script> + +testAccessProperty("self", w => w.self); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-top.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-top.https.html new file mode 100644 index 0000000000..1b75ecc105 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-top.https.html @@ -0,0 +1,13 @@ +<title> Check openee.top access is checked</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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/test-access-property.js"></script> +<script> + +testAccessProperty("top", w => w.top); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-window.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-window.https.html new file mode 100644 index 0000000000..07278b4a11 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/property-window.https.html @@ -0,0 +1,13 @@ +<title> Check openee.window access is checked</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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/test-access-property.js"></script> +<script> + +testAccessProperty("window", w => w.window); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/report-to-both_coop-ro.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/report-to-both_coop-ro.https.html new file mode 100644 index 0000000000..46cdc6eb27 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/report-to-both_coop-ro.https.html @@ -0,0 +1,124 @@ +<title> + Both the openee and the opener have a COOP reporter. The report are sent to + both side. +</title> +<meta name=timeout content=long> +<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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/resources/common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/try-access.js"></script> +<script> + +const directory = "/html/cross-origin-opener-policy"; +const origin_opener = get_host_info().HTTPS_ORIGIN; +const origin_openee = get_host_info().HTTPS_REMOTE_ORIGIN; + +let escapeComma = url => url.replace(/,/g, '\\,'); + +let genericSetup = async function(test) { + // The test window. + const this_window_token = token(); + + // The "opener" window. This has COOP and a reporter. + const opener_report_token= token(); + const opener_token = token(); + const opener_reportTo = reportToHeaders(opener_report_token); + const opener_url = origin_opener+ executor_path + opener_reportTo.header + + opener_reportTo.coopReportOnlySameOriginHeader + coep_header + + `&uuid=${opener_token}`; + + // The "openee" window. This has COOP and a reporter. + const openee_report_token= token(); + const openee_token = token(); + const openee_reportTo = reportToHeaders(openee_report_token); + const openee_url = origin_openee + executor_path + openee_reportTo.header + + openee_reportTo.coopReportOnlySameOriginHeader + coep_header + + `&uuid=${openee_token}`; + + // Cleanup at the end of the test. + test.add_cleanup(() => { + send(openee_token, 'window.close()'); + send(opener_token, 'window.close()'); + }); + + // 1. Spawn the opener and the openee windows. + window.open(opener_url); + send(opener_token, ` + openee = window.open('${escapeComma(openee_url)}'); + `); + + // 2. Wait for both to be loaded. + send(openee_token, `send('${this_window_token}', 'ACK');`); + assert_equals(await receive(this_window_token), 'ACK'); + + return [ + this_window_token, + opener_token, opener_report_token, opener_url, + openee_token, openee_report_token, openee_url, + ]; +} + +let assert_generic_coop_report = function(report) { + assert_equals(report.type, "coop"); + assert_equals(report.body.disposition, "reporting"); + assert_equals(report.body.effectivePolicy, "same-origin-plus-coep"); + assert_equals(report.body.property, "blur"); +} + +promise_test(async test => { + let [ + this_window_token, + opener_token, opener_report_token, opener_url, + openee_token, openee_report_token, openee_url, + ] = await genericSetup(test); + + send(opener_token, addScriptAndTriggerOnload( + directory + "/reporting/resources/try-access.js", + "tryAccess(openee);") + ); + + let report_opener = + await receiveReport(opener_report_token, "access-from-coop-page-to-openee") + let report_openee = + await receiveReport(openee_report_token, "access-to-coop-page-from-opener") + + assert_generic_coop_report(report_openee); + assert_generic_coop_report(report_opener); + + assert_equals(report_opener.url, opener_url.replace(/"/g, '%22')); + assert_equals(report_openee.url, openee_url.replace(/"/g, '%22')); + assert_source_location_found(report_opener); + assert_source_location_missing(report_openee); +}, "Access from opener") + +promise_test(async test => { + let [ + this_window_token, + opener_token, opener_report_token, opener_url, + openee_token, openee_report_token, openee_url, + ] = await genericSetup(test); + + send(openee_token, addScriptAndTriggerOnload( + directory + "/reporting/resources/try-access.js", + "tryAccess(opener);") + ); + + let report_opener = + await receiveReport(opener_report_token, "access-to-coop-page-from-openee") + let report_openee = + await receiveReport(openee_report_token, "access-from-coop-page-to-opener") + + assert_generic_coop_report(report_openee); + assert_generic_coop_report(report_opener); + + assert_equals(report_opener.url, opener_url.replace(/"/g, '%22')); + assert_equals(report_openee.url, openee_url.replace(/"/g, '%22')); + assert_source_location_missing(report_opener); + assert_source_location_found(report_openee); +}, "Access from openee") + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/reporting-observer.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/reporting-observer.html new file mode 100644 index 0000000000..375c627d27 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/access-reporting/reporting-observer.html @@ -0,0 +1,275 @@ +<!doctype html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title> + Check the ReportingObserver(s) are notified about the coop-access-violation + events. +</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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/resources/common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/try-access.js"></script> +<script> + +const directory = "/html/cross-origin-opener-policy"; +const same_origin = get_host_info().HTTPS_ORIGIN; +const cross_site = get_host_info().HTTPS_NOTSAMESITE_ORIGIN; +const corp_header = '|header(Cross-Origin-Resource-Policy,cross-origin)'; + +promise_test(async t => { + // This test window. + const this_window_token = token(); + + // The "opener" window, using COOP-Report-Only and a reporter. + const opener_token = token(); + const opener_reportTo = reportToHeaders(token()); + const opener_url = same_origin + executor_path + opener_reportTo.header + + opener_reportTo.coopReportOnlySameOriginHeader + coep_header + + `&uuid=${opener_token}`; + + // The "openee" window, NOT using COOP. + const openee_token = token(); + const openee_url = same_origin + executor_path + `&uuid=${openee_token}`; + + // 1. Create the opener window. + window.open(opener_url); + t.add_cleanup(() => send(opener_token, "window.close();")); + + // 2. The opener opens its openee. + send(opener_token, `openee = window.open('${openee_url}');`); + t.add_cleanup(() => send(openee_token, `window.close();`)); + + // 3. Wait for the openee to load its document. + send(openee_token, `send("${this_window_token}", "Ready");`); + assert_equals(await receive(this_window_token), "Ready"); + + // 4. The opener tries to access its openee. All reports for blocked access + // from the COOP page should notify the ReportingObservers. + send(opener_token, addScriptAndTriggerOnload( + directory + "/reporting/resources/try-access.js", ` + let observer = new ReportingObserver(()=>{}); + observer.observe(); + tryAccess(openee); + let reports = observer.takeRecords(); + send("${this_window_token}", JSON.stringify(reports)); + observer.disconnect(); + `)); + + let report_access_from = JSON.parse(await receive(this_window_token)); + assert_equals(report_access_from.length, 1, "No report received."); + assert_equals(report_access_from[0].type, "coop-access-violation"); + assert_equals(report_access_from[0].url, opener_url.replace(/"/g, '%22')); + assert_source_location_found(report_access_from[0]) + assert_equals(report_access_from[0].body.type, + "access-from-coop-page-to-openee"); + assert_equals(report_access_from[0].body.openeeURL, openee_url); + assert_equals(report_access_from[0].body.openerURL, undefined); + assert_equals(report_access_from[0].body.otherDocumentURL, undefined); + + // 5. The openee tries to access its opener. No reports for blocked access + // to the COOP page should be dispatched. + send(openee_token, addScriptAndTriggerOnload( + directory + "/reporting/resources/try-access.js", ` + let observer = new ReportingObserver(()=>{}); + observer.observe(); + tryAccess(opener); + let reports = observer.takeRecords(); + send("${this_window_token}", JSON.stringify(reports)); + observer.disconnect(); + `)); + let report_access_to = JSON.parse(await receive(this_window_token)); + assert_equals(report_access_to.length, 0, "Unexpected report received."); +}, "Opener COOP"); + +promise_test(async t => { + // This test window. + const this_window_token = token(); + + // The "opener" window, NOT using COOP. + const opener_token = token(); + const opener_url = same_origin + executor_path + `&uuid=${opener_token}`; + + // The "openee" window, using COOP-Report-Only and a reporter. + const openee_token = token(); + const openee_reportTo = reportToHeaders(token()); + const openee_url = same_origin + executor_path + openee_reportTo.header + + openee_reportTo.coopReportOnlySameOriginHeader + coep_header + + `&uuid=${openee_token}`; + + // 1. Create the opener window. + window.open(opener_url); + t.add_cleanup(() => send(opener_token, "window.close();")); + + // 2. The opener opens its openee. + send(opener_token, + `openee = window.open('${openee_url.replace(/,/g, '\\,')}');`); + t.add_cleanup(() => send(openee_token, `window.close();`)); + + // 3. The openee tries to access its opener. All reports for blocked access + // from the COOP page should notify the ReportingObservers. + send(openee_token, addScriptAndTriggerOnload( + directory + "/reporting/resources/try-access.js", ` + let observer = new ReportingObserver(()=>{}); + observer.observe(); + tryAccess(opener); + let reports = observer.takeRecords(); + send("${this_window_token}", JSON.stringify(reports)); + observer.disconnect(); + `)); + let report_access_from = JSON.parse(await receive(this_window_token)); + assert_equals(report_access_from.length, 1, "No report received."); + assert_equals(report_access_from[0].type, "coop-access-violation"); + assert_equals(report_access_from[0].url, openee_url.replace(/"/g, '%22')); + assert_true(report_access_from[0].body.sourceFile.includes("try-access.js")); + assert_source_location_found(report_access_from[0]) + assert_equals(report_access_from[0].body.type, + "access-from-coop-page-to-opener"); + assert_equals(report_access_from[0].body.openeeURL, undefined); + assert_equals(report_access_from[0].body.openerURL, opener_url); + assert_equals(report_access_from[0].body.otherDocumentURL, undefined); + + // 4. The opener tries to access its openee. No reports for blocked access + // to the COOP page should be dispatched. + send(opener_token, addScriptAndTriggerOnload( + directory + "/reporting/resources/try-access.js", ` + let observer = new ReportingObserver(()=>{}); + observer.observe(); + tryAccess(openee); + let reports = observer.takeRecords(); + send("${this_window_token}", JSON.stringify(reports)); + observer.disconnect(); + `)); + let report_access_to = JSON.parse(await receive(this_window_token)); + assert_equals(report_access_to.length, 0, "Unexpected report received."); +}, "Openee COOP"); + +promise_test(async t => { + // This test window. + const this_window_token = token(); + + // The "opener" window, using COOP-Report-Only and a reporter. + const opener_token = token(); + const opener_reportTo = reportToHeaders(token()); + const opener_url = same_origin + executor_path + opener_reportTo.header + + opener_reportTo.coopReportOnlySameOriginHeader + coep_header + + `&uuid=${opener_token}`; + + // The "opener's iframe", same-origin with its parent. + const opener_iframe_token = token(); + const opener_iframe_url = same_origin + executor_path + coep_header + + `&uuid=${opener_iframe_token}`; + + // The "openee" window, NOT using COOP. + const openee_token = token(); + const openee_url = same_origin + executor_path + coep_header + + `&uuid=${openee_token}`; + + // 1. Create the opener window. + window.open(opener_url); + t.add_cleanup(() => send(opener_token, "window.close();")); + + // 2. The opener opens an iframe, and install a ReportingObserver to catch + // future accesses. + send(opener_token, ` + iframe = document.createElement("iframe"); + iframe.src = "${opener_iframe_url}"; + document.body.appendChild(iframe); + + let observer = new ReportingObserver(reports => { + send("${this_window_token}", JSON.stringify(reports)); + observer.disconnect(); + }); + observer.observe(); + `); + + // 3. The iframe opens the openee. + send(opener_iframe_token, `openee = window.open('${openee_url}');`); + t.add_cleanup(() => send(openee_token, `window.close();`)); + + // 4. Wait for the openee to load its document. + send(openee_token, `send("${this_window_token}", "Ready");`); + assert_equals(await receive(this_window_token), "Ready"); + + // 4. The opener's iframe tries to access the openee. This is an + // "access-from-coop-page" from a same-origin iframe, so the + // ReportingObserver(s) are notified. + send(opener_iframe_token, addScriptAndTriggerOnload( + directory + "/reporting/resources/try-access.js", `tryAccess(openee);`)); + + let reports = await receive(this_window_token); + reports = JSON.parse(reports); + assert_equals(reports.length, 1, "No report received."); + assert_equals(reports[0].type, "coop-access-violation"); + assert_equals(reports[0].url, opener_url.replace(/"/g, '%22')); + assert_true(reports[0].body.sourceFile.includes("try-access.js")); + assert_source_location_found(reports[0]); + assert_equals(reports[0].body.type, + "access-from-coop-page-to-openee"); + assert_equals(reports[0].body.openeeURL, openee_url); + assert_equals(reports[0].body.openerURL, undefined); + assert_equals(reports[0].body.otherDocumentURL, undefined); +}, "Access from same-origin iframe") + +promise_test(async t => { + // This test window. + const this_window_token = token(); + + // The "opener" window, using COOP-Report-Only and a reporter. + const opener_token = token(); + const opener_reportTo = reportToHeaders(token()); + const opener_url = same_origin + executor_path + opener_reportTo.header + + opener_reportTo.coopReportOnlySameOriginHeader + coep_header + + `&uuid=${opener_token}`; + + // The "opener's iframe", same-origin with its parent. + const opener_iframe_token = token(); + const opener_iframe_url = cross_site + executor_path + coep_header + + corp_header + + `&uuid=${opener_iframe_token}`; + + // The "openee" window, NOT using COOP. + const openee_token = token(); + const openee_url = same_origin + executor_path + coep_header + + `&uuid=${openee_token}`; + + // 1. Create the opener window. + window.open(opener_url); + t.add_cleanup(() => send(opener_token, "window.close();")); + + // 2. The opener opens an iframe, and install a ReportingObserver to catch + // future accesses. + send(opener_token, ` + iframe = document.createElement("iframe"); + iframe.src = "${opener_iframe_url}"; + document.body.appendChild(iframe); + + let observer = new ReportingObserver(reports => { + send("${this_window_token}", JSON.stringify(reports)); + observer.disconnect(); + }); + observer.observe(); + `); + + // 3. The iframe opens the openee. + send(opener_iframe_token, `openee = window.open('${openee_url}');`); + t.add_cleanup(() => send(openee_token, `window.close();`)); + + // 4. Wait for the openee to load its document. + send(openee_token, `send("${this_window_token}", "Ready");`); + assert_equals(await receive(this_window_token), "Ready"); + + // 5. The opener's iframe tries to access the openee. This is an + // "access-from-coop-page" from a cross-site iframe. The ReportingObservers + // from the main document aren't notified. + send(opener_iframe_token, addScriptAndTriggerOnload( + directory + "/reporting/resources/try-access.js", `tryAccess(openee);`)); + + let reports = await receive(this_window_token, 2000); + assert_equals(reports, "timeout", "Unexpected report received."); +}, "Access from cross-site iframe") + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/document-reporting/report-only-four-reports.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/document-reporting/report-only-four-reports.https.html new file mode 100644 index 0000000000..7bfdab1330 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/document-reporting/report-only-four-reports.https.html @@ -0,0 +1,86 @@ + +<meta name=timeout content=long> +<title>A test with both COOP and COOP report only setup using Reporting-Endpoints 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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/resources/common.js"></script> +<script + src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js?pipe=sub&report_id=2aee31d2-cd11-43bd-b34d-5f081ca3b2b4&report_only_id=d18f1779-e2ab-4a7a-8b1c-44e3a6f440f5"></script> + +<script> +let tests = [ + // popup origin, popup COOP, popup COEP, popup COOP report-only, popup COEP report-only, expected reports + + // Open a cross-origin popup with both normal and report-only COOP. Four + // reports are sent. + [ + CROSS_ORIGIN, + `same-origin-allow-popups; report-to="${popupReportEndpoint.name}"`, + "require-corp", + `same-origin; report-to="${popupReportOnlyEndpoint.name}"`, + "require-corp", + [ + { + "endpoint": reportEndpoint, + "report": { + "body": { + "disposition": "enforce", + "effectivePolicy": "same-origin-allow-popups", + "nextResponseURL": /uuid=EXECUTOR_UUID$/, // next document URL + "type": "navigation-from-response" + }, + "url": `${location.href}`, + "type": "coop" + } + }, + { + "endpoint": reportOnlyEndpoint, + "report": { + "body": { + "disposition": "reporting", + "effectivePolicy": "same-origin-plus-coep", + "nextResponseURL": /uuid=EXECUTOR_UUID$/, // next document URL + "type": "navigation-from-response" + }, + "url": `${location.href}`, + "type": "coop" + } + }, + { + "endpoint": popupReportEndpoint, + "report": { + "body": { + "disposition": "enforce", + "effectivePolicy": "same-origin-allow-popups", + "previousResponseURL": "", + "referrer": `${location.origin}/`, // referrer + "type": "navigation-to-response" + }, + "url": /uuid=EXECUTOR_UUID$/, + "type": "coop" + } + }, + { + "endpoint": popupReportOnlyEndpoint, + "report": { + "body": { + "disposition": "reporting", + "effectivePolicy": "same-origin-plus-coep", + "previousResponseURL": "", + "referrer": `${location.origin}/`, // referrer + "type": "navigation-to-response" + }, + "url": /uuid=EXECUTOR_UUID$/, + "type": "coop" + } + } + ] + ] +]; + +runNavigationDocumentReportingTests(document.title, tests); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/document-reporting/report-only-four-reports.https.html.sub.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/document-reporting/report-only-four-reports.https.html.sub.headers new file mode 100644 index 0000000000..de48445f38 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/document-reporting/report-only-four-reports.https.html.sub.headers @@ -0,0 +1,6 @@ +Cross-Origin-Opener-Policy: same-origin-allow-popups; report-to="coop-report-endpoint" +Cross-Origin-Opener-Policy-Report-Only: same-origin; report-to="coop-report-only-endpoint" +Cross-Origin-Embedder-Policy: require-corp +Cross-Origin-Embedder-Policy-Report-Only: require-corp +Referrer-Policy: origin +Reporting-Endpoints: coop-report-endpoint="https://{{host}}:{{ports[https][0]}}/reporting/resources/report.py?reportID=2aee31d2-cd11-43bd-b34d-5f081ca3b2b4", coop-report-only-endpoint="https://{{host}}:{{ports[https][0]}}/reporting/resources/report.py?reportID=d18f1779-e2ab-4a7a-8b1c-44e3a6f440f5" diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/document-reporting/report-to-both_coop-ro.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/document-reporting/report-to-both_coop-ro.https.html new file mode 100644 index 0000000000..409628c15c --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/document-reporting/report-to-both_coop-ro.https.html @@ -0,0 +1,124 @@ +<title> + Both the openee and the opener have a COOP reporter. The report are sent to + both side. +</title> +<meta name=timeout content=long> +<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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/resources/common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/try-access.js"></script> +<script> + +const directory = "/html/cross-origin-opener-policy"; +const origin_opener = get_host_info().HTTPS_ORIGIN; +const origin_openee = get_host_info().HTTPS_REMOTE_ORIGIN; + +let escapeComma = url => url.replace(/,/g, '\\,'); + +let genericSetup = async function(test) { + // The test window. + const this_window_token = token(); + + // The "opener" window. This has COOP and a reporter. + const opener_token = token(); + const opener_report_token = reportToken(); + const opener_reporting = reportingEndpointsHeaders(opener_report_token); + const opener_url = origin_opener+ executor_path + opener_reporting.header + + opener_reporting.coopReportOnlySameOriginHeader + coep_header + + `&uuid=${opener_token}`; + + // The "openee" window. This has COOP and a reporter. + const openee_token = token(); + const openee_report_token = reportToken(); + const openee_reporting = reportingEndpointsHeaders(openee_report_token); + const openee_url = origin_openee + executor_path + openee_reporting.header + + openee_reporting.coopReportOnlySameOriginHeader + coep_header + + `&uuid=${openee_token}`; + + // Cleanup at the end of the test. + test.add_cleanup(() => { + send(openee_token, 'window.close()'); + send(opener_token, 'window.close()'); + }); + + // 1. Spawn the opener and the openee windows. + window.open(opener_url); + send(opener_token, ` + openee = window.open('${escapeComma(openee_url)}'); + `); + + // 2. Wait for both to be loaded. + send(openee_token, `send('${this_window_token}', 'ACK');`); + assert_equals(await receive(this_window_token), 'ACK'); + + return [ + this_window_token, + opener_token, opener_report_token, opener_url, + openee_token, openee_report_token, openee_url, + ]; +} + +let assert_generic_coop_report = function(report) { + assert_equals(report.type, "coop"); + assert_equals(report.body.disposition, "reporting"); + assert_equals(report.body.effectivePolicy, "same-origin-plus-coep"); + assert_equals(report.body.property, "blur"); +} + +promise_test(async test => { + let [ + this_window_token, + opener_token, opener_report_token, opener_url, + openee_token, openee_report_token, openee_url, + ] = await genericSetup(test); + + send(opener_token, addScriptAndTriggerOnload( + directory + "/reporting/resources/try-access.js", + "tryAccess(openee);") + ); + + let report_opener = + await receiveReport(opener_report_token, "access-from-coop-page-to-openee") + let report_openee = + await receiveReport(openee_report_token, "access-to-coop-page-from-opener") + + assert_generic_coop_report(report_openee); + assert_generic_coop_report(report_opener); + + assert_equals(report_opener.url, opener_url.replace(/"/g, '%22')); + assert_equals(report_openee.url, openee_url.replace(/"/g, '%22')); + assert_source_location_found(report_opener); + assert_source_location_missing(report_openee); +}, "Access from opener") + +promise_test(async test => { + let [ + this_window_token, + opener_token, opener_report_token, opener_url, + openee_token, openee_report_token, openee_url, + ] = await genericSetup(test); + + send(openee_token, addScriptAndTriggerOnload( + directory + "/reporting/resources/try-access.js", + "tryAccess(opener);") + ); + + let report_opener = + await receiveReport(opener_report_token, "access-to-coop-page-from-openee") + let report_openee = + await receiveReport(openee_report_token, "access-from-coop-page-to-opener") + + assert_generic_coop_report(report_openee); + assert_generic_coop_report(report_opener); + + assert_equals(report_opener.url, opener_url.replace(/"/g, '%22')); + assert_equals(report_openee.url, openee_url.replace(/"/g, '%22')); + assert_source_location_missing(report_opener); + assert_source_location_found(report_openee); +}, "Access from openee") + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/document-reporting/reporting-redirect-with-same-origin-allow-popups.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/document-reporting/reporting-redirect-with-same-origin-allow-popups.https.html new file mode 100644 index 0000000000..b2ff818d56 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/document-reporting/reporting-redirect-with-same-origin-allow-popups.https.html @@ -0,0 +1,111 @@ +<title> + Tests the redirect interaction with COOP same-origin-allow-popups. +</title> +<meta name=timeout content=long> +<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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/resources/common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js"></script> +<script> + +const same_origin = { + host: get_host_info().HTTPS_ORIGIN, + name: "Same origin" +}; +const cross_origin = { + host: get_host_info().HTTPS_REMOTE_ORIGIN, + name: "Cross origin" +}; + +// Tests the redirect interaction with COOP same-origin-allow-popups and +// reporting: +// 1 - open the opener document on origin same_origin wit COOP +// same-origin-allow-popups. +// 2 - opener opens popup with document on origin popup_origin, no COOP and a +// redirect header (HTTP 302, location). +// 3 - redirection to a document with origin same_origin and COOP +// same-origin-allow-popups. +// +// The navigation (2) to the first document of the popup stays in the same +// browsing context group due to the same-origin-allow-popups COOP of the +// opener. +// The redirect (3) to the final document does since it compares the +// popup_origin/unsafe-none document with the +// same-origin/same-origin-allow-popups document. +// +// A opens B, B redirects to C. +// +// Document Origin COOP +// -------- ------------ ------------------------ +// A same-origin same-origin-allow-popups +// B popup-origin unsafe-none +// C same-origin same-origin-allow-popups +function redirect_test(popup_origin) { + promise_test(async t => { + // The test window. + const this_window_token = token(); + + // The "opener" window. This has COOP same-origin-allow-popups and a + // reporter. + const opener_token = token(); + const opener_report_token = reportToken(); + const opener_reporting = reportingEndpointsHeaders(opener_report_token); + const opener_url = same_origin.host + executor_path + + opener_reporting.header + opener_reporting.coopSameOriginAllowPopupsHeader + + `&uuid=${opener_token}`; + + // The "openee" window. + // The initial document does not have COOP and is on popup_origin, it + // redirects to a same-origin (with the opener) document with COOP + // same-origin-allow-popups. + const openee_token = token(); + const openee_redirect_url = same_origin.host + executor_path + + opener_reporting.header + opener_reporting.coopSameOriginAllowPopupsHeader + + `&uuid=${openee_token}`; + const redirect_header = 'status(302)' + + `|header(Location,${encodeURIComponent( + openee_redirect_url + .replace(/,/g, "\\,") + .replace(/\\\\,/g, "\\\\\\,") + .replace(/\(/g, "%28") + .replace(/\)/g, "%29"))})`; + const openee_url = popup_origin.host + executor_path + redirect_header + + `&uuid=${openee_token}`; + // 1. Create the opener window. + let opener_window_proxy = window.open(opener_url); + t.add_cleanup(() => send(opener_token, "window.close()")); + + // 2. The opener opens its openee. + send(opener_token, ` + openee = window.open("${openee_url}"); + `); + t.add_cleanup(() => send(openee_token, "window.close()")); + + // 3. Check the opener status on the openee. + send(openee_token, ` + send("${this_window_token}", opener !== null); + `); + assert_equals(await receive(this_window_token), "false", "opener"); + + // 4. Check the openee status on the opener. + send(opener_token, ` + send("${this_window_token}", openee.closed); + `); + assert_equals(await receive(this_window_token), "true", "openee.closed"); + + // 5. Check a report sent to the openee. + let report = await receiveReport( + opener_report_token, + "navigation-to-response"); + assert_equals(report.type, "coop"); + assert_equals(report.body.disposition, "enforce"); + assert_equals(report.body.effectivePolicy, "same-origin-allow-popups"); + }, `${popup_origin.name} openee redirected to same-origin with same-origin-allow-popups`); +} + +redirect_test(same_origin); +redirect_test(cross_origin); +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/document-reporting/reporting-redirect-with-unsafe-none.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/document-reporting/reporting-redirect-with-unsafe-none.https.html new file mode 100644 index 0000000000..bd89856305 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/document-reporting/reporting-redirect-with-unsafe-none.https.html @@ -0,0 +1,130 @@ +<title> + Tests the redirect interaction with COOP unsafe-none. +</title> +<meta name=timeout content=long> +<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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/resources/common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js"></script> +<script> + +const same_origin = { + host: get_host_info().HTTPS_ORIGIN, + name: "Same origin" +}; +const cross_origin = { + host: get_host_info().HTTPS_REMOTE_ORIGIN, + name: "Cross origin" +}; + +// Repeated call receive() to fetch all reports received within 1 second. +async function fetchReportsByID(uuid){ + let timeStart = new Date().getTime(); + const reports = []; + while(new Date().getTime() - timeStart < 1000) { + // Promise.race is used to timeout since receive() has no timeout mechanism. + reports.push(...await Promise.race([ + receive(uuid).then(JSON.parse), + new Promise(resolve => step_timeout(resolve, 1000, [])) + ])); + } + return reports; +} + +function fetchReportByType(reports, type){ + return reports.filter((report)=> (report.body.type === type)); +} + + // Tests the redirect interaction with COOP unsafe-none and reporting: + // 1 - open the opener document on origin same_origin with COOP + // unsafe-none. + // 2 - opener opens popup with document on origin popup_origin, with COOP + // same-origin, Reporting-Endpoints header and a redirect header + // (HTTP 302, location). + // 3 - redirection to a document with origin same-origin and COOP + // unsafe-none. + // + // Navigation 2) should generate a report sent to B's reporter(navigation-to). + // Navigation 3) should generate a report sent to B's reporter(navigation-from). + // + // A opens B, B redirects to C. + // + // Document Origin COOP + // -------- ------------ ------------------------ + // A same-origin unsafe-none + // B popup-origin same-origin + // C same-origin unsafe-none +function redirect_test(popup_origin) { + promise_test(async t => { + // The test window. + const this_window_token = token(); + + // The "opener" window. This has COOP unsafe-none and no reporter. + const opener_token = token(); + const opener_url = same_origin.host + executor_path + + `&uuid=${opener_token}`; + + // The "openee" window. + // The initial document have COOP, reporter and is on popup_origin, it + // redirects to a same-origin (with the opener) document with no COOP. + const openee_token = token(); + const openee_report_token = reportToken(); + const openee_reporting = reportingEndpointsHeaders(openee_report_token); + const openee_redirect_url = same_origin.host + executor_path + + `&uuid=${openee_token}`; + const redirect_header = '|status(302)' + + `|header(Location,${encodeURIComponent( + openee_redirect_url)})`; + const openee_url = (popup_origin.host + executor_path + + openee_reporting.header + openee_reporting.coopSameOriginHeader + + redirect_header + `&uuid=${openee_token}`) + .replace(/,/g, "\\,") + .replace(/\\\\,/g, "\\\\\\,") + .replace(/\(/g, "%28") + .replace(/\)/g, "%29"); + // 1. Create the opener window. + let opener_window_proxy = window.open(opener_url); + t.add_cleanup(() => send(opener_token, "window.close()")); + + // 2. The opener opens its openee. + send(opener_token, ` + openee = window.open(\`${openee_url}\`); + `); + t.add_cleanup(() => send(openee_token, "window.close()")); + + // 3. Check the opener status on the openee. + send(openee_token, ` + send("${this_window_token}", opener !== null); + `); + assert_equals(await receive(this_window_token), "false", "opener"); + + // 4. Check the openee status on the opener. + send(opener_token, ` + send("${this_window_token}", openee.closed); + `); + assert_equals(await receive(this_window_token), "true", "openee.closed"); + + // 5. Check a report sent to B's reporting endpoint when A opens B. + const reports = await fetchReportsByID(openee_report_token); + const navigationToReport = fetchReportByType( + reports, "navigation-to-response"); + assert_equals(navigationToReport.length, 1); + assert_equals(navigationToReport[0].type, "coop"); + assert_equals(navigationToReport[0].body.disposition, "enforce"); + assert_equals(navigationToReport[0].body.effectivePolicy, "same-origin"); + // 6. Check a report sent to B's reporting endpoint when B redirects to C. + const navigationFromReport = fetchReportByType( + reports, "navigation-from-response"); + assert_equals(navigationFromReport.length, 1); + assert_equals(navigationFromReport[0].type, "coop"); + assert_equals(navigationFromReport[0].body.disposition, "enforce"); + assert_equals(navigationFromReport[0].body.effectivePolicy, "same-origin"); + }, `${popup_origin.name} openee redirected to same-origin with unsafe-none`); +} + +redirect_test(same_origin); +redirect_test(cross_origin); +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-four-reports.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-four-reports.https.html new file mode 100644 index 0000000000..ca1471ccc0 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-four-reports.https.html @@ -0,0 +1,86 @@ +<meta name=timeout content=long> +<title>A test with both COOP and COOP report only setup</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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/resources/common.js"></script> +<script + src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js?pipe=sub&report_id=47b45e17-51c5-4691-bdd5-8f343bbfcf42&report_only_id=3eb3ad1d-872e-4ea8-8b40-0e98783a0683"></script> + +<script> + +let tests = [ + // popup origin, popup COOP, popup COEP, popup COOP report-only, popup COEP report-only, expected reports + + // Open a cross-origin popup with both normal and report-only COOP. Four + // reports are sent. + [ + CROSS_ORIGIN, + `same-origin-allow-popups; report-to="${popupReportEndpoint.name}"`, + "require-corp", + `same-origin; report-to="${popupReportOnlyEndpoint.name}"`, + "require-corp", + [ + { + "endpoint": reportEndpoint, + "report": { + "body": { + "disposition": "enforce", + "effectivePolicy": "same-origin-allow-popups", + "nextResponseURL": /uuid=EXECUTOR_UUID$/, // next document URL + "type": "navigation-from-response" + }, + "url": `${location.href}`, + "type": "coop" + } + }, + { + "endpoint": reportOnlyEndpoint, + "report": { + "body": { + "disposition": "reporting", + "effectivePolicy": "same-origin-plus-coep", + "nextResponseURL": /uuid=EXECUTOR_UUID$/, // next document URL + "type": "navigation-from-response" + }, + "url": `${location.href}`, + "type": "coop" + } + }, + { + "endpoint": popupReportEndpoint, + "report": { + "body": { + "disposition": "enforce", + "effectivePolicy": "same-origin-allow-popups", + "previousResponseURL": "", + "referrer": `${location.origin}/`, // referrer + "type": "navigation-to-response" + }, + "url": /uuid=EXECUTOR_UUID$/, + "type": "coop" + } + }, + { + "endpoint": popupReportOnlyEndpoint, + "report": { + "body": { + "disposition": "reporting", + "effectivePolicy": "same-origin-plus-coep", + "previousResponseURL": "", + "referrer": `${location.origin}/`, // referrer + "type": "navigation-to-response" + }, + "url": /uuid=EXECUTOR_UUID$/, + "type": "coop" + } + } + ] + ] +]; + +runNavigationReportingTests(document.title, tests); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-four-reports.https.html.sub.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-four-reports.https.html.sub.headers new file mode 100644 index 0000000000..50c3045bb6 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-four-reports.https.html.sub.headers @@ -0,0 +1,6 @@ +Cross-Origin-Opener-Policy: same-origin-allow-popups; report-to="coop-report-endpoint" +Cross-Origin-Opener-Policy-Report-Only: same-origin; report-to="coop-report-only-endpoint" +Cross-Origin-Embedder-Policy: require-corp +Cross-Origin-Embedder-Policy-Report-Only: require-corp +Referrer-Policy: origin +Reporting-Endpoints: coop-report-endpoint="https://{{host}}:{{ports[https][0]}}/reporting/resources/report.py?reportID=47b45e17-51c5-4691-bdd5-8f343bbfcf42", coop-report-only-endpoint="https://{{host}}:{{ports[https][0]}}/reporting/resources/report.py?reportID=3eb3ad1d-872e-4ea8-8b40-0e98783a0683"
\ No newline at end of file diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-from-unsafe-none.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-from-unsafe-none.https.html new file mode 100644 index 0000000000..cca2e7e1ae --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-from-unsafe-none.https.html @@ -0,0 +1,71 @@ + +<meta name=timeout content=long> +<title>Report only tests for an opener without any COOP/COOP report only set</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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/resources/common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js"></script> + +<script> + +let tests = [ + // popup origin, popup COOP, popup COEP, popup COOP report-only, popup COEP report-only, expected reports + + // Open a same-origin popup with a same-origin COOP report-only value, which + // would cause a browsing context group swap, hence a report is sent. + [ + SAME_ORIGIN, + "", + "", + `same-origin; report-to="${popupReportOnlyEndpoint.name}"`, + "", + [ + { + "endpoint": popupReportOnlyEndpoint, + "report": { + "body": { + "disposition": "reporting", + "effectivePolicy": "same-origin", + "previousResponseURL": `${location.href}`, // previous documnent url + "referrer": `${location.origin}/`, // referrer (origin, as dictated by the referrer policy) + "type": "navigation-to-response" + }, + "url": /uuid=EXECUTOR_UUID$/, + "type": "coop" + } + } + ] + ], + // Open a cross-origin popup with a same-origin COOP report-only value, which + // would cause a browsing context group swap, hence a report is sent. + [ + CROSS_ORIGIN, + "", + "", + `same-origin; report-to="${popupReportOnlyEndpoint.name}"`, + "", + [ + { + "endpoint": popupReportOnlyEndpoint, + "report": { + "body": { + "disposition": "reporting", + "effectivePolicy": "same-origin", + "previousResponseURL": "", + "referrer": `${location.origin}/`, // referrer (origin, as dictated by the referrer policy) + "type": "navigation-to-response" + }, + "url": /uuid=EXECUTOR_UUID$/, + "type": "coop" + } + } + ] + ], +]; + +runNavigationReportingTests(document.title, tests); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-from-unsafe-none.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-from-unsafe-none.https.html.headers new file mode 100644 index 0000000000..5b29739bbd --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-from-unsafe-none.https.html.headers @@ -0,0 +1 @@ +Referrer-Policy: origin diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-same-origin-report-to.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-same-origin-report-to.https.html new file mode 100644 index 0000000000..52b1f2a09f --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-same-origin-report-to.https.html @@ -0,0 +1,96 @@ +<meta name=timeout content=long> +<title>reporting same origin with report-to</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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/resources/common.js"></script> +<script + src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js?pipe=sub&report_id=380ca360-d1ae-4329-b1dd-69cea49cd705&report_only_id=cf9ac91d-6c5d-4489-a420-10be9402ef84"></script> + +<script> + +let tests = [ + // popup origin, popup COOP, popup COEP, popup COOP report-only, popup COEP report-only, expected reports + + // Open a cross-origin popup without any COOP setup, the current document + // (opener) report-only would cause a browsing context group swap, hence a + // report is sent to the corresponding endpoint. + [ + CROSS_ORIGIN, + "", + "", + "", + "", + [ + { + "endpoint": reportOnlyEndpoint, + "report": { + "body": { + "disposition": "reporting", + "effectivePolicy": "same-origin", + "nextResponseURL": /uuid=EXECUTOR_UUID$/, // next document URL + "type": "navigation-from-response" + }, + "url": `${location.href}`, + "type": "coop" + } + }, + ] + ], + // Open a cross-origin popup with a same-origin COOP report-only value, which + // would cause a browsing context group swap, hence a report is sent to both + // endpoints. + [ + CROSS_ORIGIN, + "", + "", + `same-origin; report-to="${popupReportOnlyEndpoint.name}"`, + "", + [ + { + "endpoint": reportOnlyEndpoint, + "report": { + "body": { + "disposition": "reporting", + "effectivePolicy": "same-origin", + "nextResponseURL": /uuid=EXECUTOR_UUID$/, // next document URL + "type": "navigation-from-response" + }, + "url": `${location.href}`, + "type": "coop" + } + }, + { + "endpoint": popupReportOnlyEndpoint, + "report": { + "body": { + "disposition": "reporting", + "effectivePolicy": "same-origin", + "previousResponseURL": "", + "referrer": `${location.origin}/`, // referrer + "type": "navigation-to-response" + }, + "url": /uuid=EXECUTOR_UUID$/, + "type": "coop" + } + } + ] + ], + // Open a same-origin popup with a same-origin COOP report-only value, the two + // COOP-report-only values match, hence no virtual browsing context group swap + // happens and no report is sent. + [ + SAME_ORIGIN, + "", + "", + `same-origin; report-to="${popupReportOnlyEndpoint.name}"`, + "", + [] + ], +]; + +runNavigationReportingTests(document.title, tests); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-same-origin-report-to.https.html.sub.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-same-origin-report-to.https.html.sub.headers new file mode 100644 index 0000000000..04bc49906b --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-same-origin-report-to.https.html.sub.headers @@ -0,0 +1,3 @@ +Cross-Origin-Opener-Policy-Report-Only: same-origin; report-to="coop-report-only-endpoint" +Referrer-Policy: origin +Reporting-Endpoints: coop-report-endpoint="https://{{host}}:{{ports[https][0]}}/reporting/resources/report.py?reportID=380ca360-d1ae-4329-b1dd-69cea49cd705", coop-report-only-endpoint="https://{{host}}:{{ports[https][0]}}/reporting/resources/report.py?reportID=cf9ac91d-6c5d-4489-a420-10be9402ef84" diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-same-origin-with-coep-report-only.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-same-origin-with-coep-report-only.https.html new file mode 100644 index 0000000000..148c700ee5 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-same-origin-with-coep-report-only.https.html @@ -0,0 +1,32 @@ + +<meta name=timeout content=long> +<title>reporting same origin with report-to</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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/resources/common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js"></script> + +<script> + +let tests = [ + // popup origin, popup COOP, popup COEP, popup COOP report-only, popup COEP report-only, expected reports + + // Open a cross-origin popup with COOP report-only with coep, which mismatches + // with the current document (opener) COOP (unsafe-none) and COOP report-only + // (same-origin) values. + [ + SAME_ORIGIN, + "", + "require-corp", + `same-origin; report-to="${popupReportOnlyEndpoint.name}"`, + "", + [] + ], +]; + +runNavigationReportingTests(document.title, tests); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-same-origin-with-coep-report-only.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-same-origin-with-coep-report-only.https.html.headers new file mode 100644 index 0000000000..58ab03394a --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-same-origin-with-coep-report-only.https.html.headers @@ -0,0 +1,3 @@ +Cross-Origin-Opener-Policy-Report-Only: same-origin +Cross-Origin-Embedder-Policy-Report-Only: require-corp +Referrer-Policy: origin diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-same-origin-with-coep.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-same-origin-with-coep.https.html new file mode 100644 index 0000000000..148c700ee5 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-same-origin-with-coep.https.html @@ -0,0 +1,32 @@ + +<meta name=timeout content=long> +<title>reporting same origin with report-to</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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/resources/common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js"></script> + +<script> + +let tests = [ + // popup origin, popup COOP, popup COEP, popup COOP report-only, popup COEP report-only, expected reports + + // Open a cross-origin popup with COOP report-only with coep, which mismatches + // with the current document (opener) COOP (unsafe-none) and COOP report-only + // (same-origin) values. + [ + SAME_ORIGIN, + "", + "require-corp", + `same-origin; report-to="${popupReportOnlyEndpoint.name}"`, + "", + [] + ], +]; + +runNavigationReportingTests(document.title, tests); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-same-origin-with-coep.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-same-origin-with-coep.https.html.headers new file mode 100644 index 0000000000..2ba7ffb592 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-same-origin-with-coep.https.html.headers @@ -0,0 +1,3 @@ +Cross-Origin-Opener-Policy-Report-Only: same-origin +Cross-Origin-Embedder-Policy: require-corp +Referrer-Policy: origin diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-same-origin.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-same-origin.https.html new file mode 100644 index 0000000000..8a63682c69 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-same-origin.https.html @@ -0,0 +1,73 @@ + +<meta name=timeout content=long> +<title>reporting same origin with report-to</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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/resources/common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js"></script> + +<script> + +let tests = [ + // popup origin, popup COOP, popup COEP, popup COOP report-only, popup COEP report-only, expected reports + + // Open a cross-origin popup with COOP report-only with coep, which mismatches + // with the current document (opener) COOP (unsafe-none) and COOP report-only + // (same-origin) values. + [ + SAME_ORIGIN, + "", + "require-corp", + `same-origin; report-to="${popupReportOnlyEndpoint.name}"`, + "", + [ + { + "endpoint": popupReportOnlyEndpoint, + "report": { + "body": { + "disposition": "reporting", + "effectivePolicy": "same-origin-plus-coep", + "previousResponseURL": `${location.href}`, + "referrer": `${location.origin}/`, + "type": "navigation-to-response" + }, + "url": /uuid=EXECUTOR_UUID$/, + "type": "coop" + } + } + ] + ], + // Open a cross-origin popup with COOP report-only with coep report-only, + // which mismatches with the current document (opener) COOP (unsafe-none) and + // COOP report-only (same-origin) values. + [ + SAME_ORIGIN, + "", + "", + `same-origin; report-to="${popupReportOnlyEndpoint.name}"`, + "require-corp", + [ + { + "endpoint": popupReportOnlyEndpoint, + "report": { + "body": { + "disposition": "reporting", + "effectivePolicy": "same-origin-plus-coep", + "previousResponseURL": `${location.href}`, + "referrer": `${location.origin}/`, + "type": "navigation-to-response" + }, + "url": /uuid=EXECUTOR_UUID$/, + "type": "coop" + } + } + ] + ], +]; + +runNavigationReportingTests(document.title, tests); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-same-origin.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-same-origin.https.html.headers new file mode 100644 index 0000000000..9a8445a43e --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-same-origin.https.html.headers @@ -0,0 +1,2 @@ +Cross-Origin-Opener-Policy-Report-Only: same-origin +Referrer-Policy: origin diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-coop-navigated-opener.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-coop-navigated-opener.https.html new file mode 100644 index 0000000000..893dfa20b8 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-coop-navigated-opener.https.html @@ -0,0 +1,67 @@ +<title> + Reports a browsing context group switch when an opener with COOP navigates. +</title> +<meta name=timeout content=long> +<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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js"></script> +<script> + +const directory = "/html/cross-origin-opener-policy"; +const same_origin = get_host_info().HTTPS_ORIGIN; + +let escapeComma = url => url.replace(/,/g, '\\,'); + +promise_test(async t => { + // The test window. + const this_window_token = token(); + + // The "opener" window. + const opener_token = token(); + const opener_url = same_origin + executor_path + `&uuid=${opener_token}`; + + // The "openee" window. + const openee_token = token(); + const openee_url = same_origin + executor_path + `&uuid=${openee_token}`; + + // The "final" url the opener will navigate to. It has COOP and a reporter. + const final_report_token = reportToken(); + const final_token = token(); + const final_reportTo = reportingEndpointsHeaders(final_report_token); + const final_url = same_origin + executor_path + final_reportTo.header + + final_reportTo.coopSameOriginHeader +`&uuid=${final_token}`; + + // 1. Create the opener window and ensure it doesn't have an opener. + let opener_window_proxy = window.open(opener_url, '_blank', 'noopener'); + t.add_cleanup(() => send(opener_token, "window.close()")); + + // 2. The opener opens a window. + send(opener_token, ` + openee = window.open('${escapeComma(openee_url)}'); + `); + + // 3. Ensure the openee loads. + send(openee_token, ` + send("${this_window_token}", "ACK"); + `); + assert_equals("ACK", await receive(this_window_token)); + + // 4. The opener navigates. + send(opener_token, ` + location.replace('${escapeComma(final_url)}'); + `); + + // 5. Check a report was sent to the opener. + let report = + await receiveReport(final_report_token, "navigation-to-response") + assert_equals(report.type, "coop"); + assert_equals(report.url, final_url.replace(/"/g, '%22')); + assert_equals(report.body.disposition, "enforce"); + assert_equals(report.body.effectivePolicy, "same-origin"); + assert_equals(report.body.previousResponseURL, opener_url.replace(/"/g, '%22')); +}, "navigation-report-from-opener-navigation"); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-coop-navigated-popup.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-coop-navigated-popup.https.html new file mode 100644 index 0000000000..b625b285cf --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-coop-navigated-popup.https.html @@ -0,0 +1,85 @@ +<title>Cross-Origin-Opener-Policy: a navigated popup with reporting</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 --> +<script src="/common/dispatcher/dispatcher.js"></script> +<script + src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js?pipe=sub&report_id=df3cde15-b00b-4a59-b6e2-498b67a6146e&report_only_id=ebf3a415-7a74-42e1-92d1-e600b1bbe22e"></script> + +<script> + +// This test does the following: +// 1 - This document has COOP: same-origin-allow-popups; report-to="coop-report-endpoint" +// 2 - Open a popup on a same-origin page without COOP, with the coop-popup-report-endpoint +// 3 - Navigate the popup to a same-origin page with COOP, with the coop-redirect-report-endpoint +// it verifies that the reports are properly send for the browsing context switch +// during the navigation in the popup (step 3). The current document (the opener) +// endpoint should not receive any report as no switch ocurred on 2. +promise_test( async t => { + const callbackToken = token(); + const noCoopToken = token(); + const coopToken= token(); + await reportingTest(async resolve => { + const noCOOPUrl = executor_path + + convertToWPTHeaderPipe(getReportingEndpointsHeader(location.origin)) + + `|header(Cross-Origin-Opener-Policy,${encodeURIComponent(`unsafe-none; report-to="${popupReportEndpoint.name}"`)})` + + `&uuid=${noCoopToken}`; + const coopUrl = executor_path + + convertToWPTHeaderPipe(getReportingEndpointsHeader(location.origin)) + + `|header(Cross-Origin-Opener-Policy,${encodeURIComponent(`same-origin; report-to="${redirectReportEndpoint.name}"`)})` + + `&uuid=${coopToken}`; + + // 1. Open a popup without COOP and with reporting. COOP does not trigger + // a browsing context group switch because the current document is + // same-origin-allow-popups + const popup = window.open(noCOOPUrl); + t.add_cleanup(() => send(noCoopToken, "window.close()")); + + // 2. Navigate the popup to a COOP document, which switches the browsing + // context group. + send(noCoopToken, `window.location = "${coopUrl}";`); + t.add_cleanup(() => send(coopToken, "window.close()")); + + // 3. Make sure the new document is loaded. + send(coopToken, ` + send("${callbackToken}", "Ready"); + `); + let reply = await receive(callbackToken); + resolve(); + }, + "", // executor token for the report replacements, unused in this test + [ + // Reports expected for the navigation from "noCOOP" to "coop" + { + "endpoint": popupReportEndpoint, + "report": { + "body": { + "disposition": "enforce", + "effectivePolicy": "unsafe-none", + "nextResponseURL": RegExp(`uuid=${coopToken}$`), + "type": "navigation-from-response" + }, + "url": RegExp(`uuid=${noCoopToken}$`), + "type": "coop" + } + }, + { + "endpoint": redirectReportEndpoint, + "report": { + "body": { + "disposition": "enforce", + "effectivePolicy": "same-origin", + "previousResponseURL": RegExp(`uuid=${noCoopToken}$`), + "referrer": RegExp(`uuid=${noCoopToken}$`), + "type": "navigation-to-response" + }, + "url": RegExp(`uuid=${coopToken}$`), + "type": "coop" + } + }, + ]); +}, "Open a popup to a document without COOP, then navigate it to a document with"); + +verifyRemainingReports(); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-coop-navigated-popup.https.html.sub.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-coop-navigated-popup.https.html.sub.headers new file mode 100644 index 0000000000..a6a27c2d3e --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-coop-navigated-popup.https.html.sub.headers @@ -0,0 +1,2 @@ +Cross-Origin-Opener-Policy: same-origin-allow-popups; report-to="coop-report-endpoint" +Reporting-Endpoints: coop-report-endpoint="https://{{host}}:{{ports[https][0]}}/reporting/resources/report.py?reportID=df3cde15-b00b-4a59-b6e2-498b67a6146e", coop-report-only-endpoint="https://{{host}}:{{ports[https][0]}}/reporting/resources/report.py?reportID=ebf3a415-7a74-42e1-92d1-e600b1bbe22e" diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-allow-popups-report-to.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-allow-popups-report-to.https.html new file mode 100644 index 0000000000..d674e2e449 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-allow-popups-report-to.https.html @@ -0,0 +1,126 @@ +<meta name=timeout content=long> +<title>reporting same origin with report-to</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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/resources/common.js"></script> +<script +src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js?pipe=sub&report_id=6a739c25-0ec5-4832-b4a3-847281006857&report_only_id=f91209ee-b3a3-474b-b337-d663533745fb"></script> + +<script> + +let tests = [ + // popup origin, popup COOP, popup COEP, popup COOP report only, popup COEP report only, expected reports + + // Open a same-origin popup with a same-origin COOP and no COEP. Produces two + // reports (one from and one to). Both pages being same origin, the + // next/pervious document urls are available. + [ + SAME_ORIGIN, + `same-origin; report-to="${popupReportEndpoint.name}"`, + "", + "", + "", + [ + { + "endpoint": reportEndpoint, + "report": { + "body": { + "disposition": "enforce", + "effectivePolicy": "same-origin-allow-popups", + "nextResponseURL": /uuid=EXECUTOR_UUID$/, // next document URL + "type": "navigation-from-response" + }, + "url": `${location.href}`, + "type": "coop" + } + }, + { + "endpoint": popupReportEndpoint, + "report": { + "body": { + "disposition": "enforce", + "effectivePolicy": "same-origin", + "previousResponseURL": `${location.href}`, // previous documnent url + "referrer": `${location.origin}/`, // referrer (origin, as dictated by the referrer policy) + "type": "navigation-to-response" + }, + "url": /uuid=EXECUTOR_UUID$/, + "type": "coop" + } + } + ] + ], + // Open a cross-origin popup with a same-origin-allow-popup COOP and noCOEP. + // Produces two reports (one from and one to). Both pages being cross origin, + // the next/pervious document urls are not available and the initial document + // url/referrer are used instead. + [ + CROSS_ORIGIN, + `same-origin-allow-popups; report-to="${popupReportEndpoint.name}"`, + "require-corp", + "", + "", + [ + { + "endpoint": reportEndpoint, + "report": { + "body": { + "disposition": "enforce", + "effectivePolicy": "same-origin-allow-popups", + "nextResponseURL": /uuid=EXECUTOR_UUID$/, // next document URL + "type": "navigation-from-response" + }, + "url": `${location.href}`, + "type": "coop" + } + }, + { + "endpoint": popupReportEndpoint, + "report": { + "body": { + "disposition": "enforce", + "effectivePolicy": "same-origin-allow-popups", + "previousResponseURL": ``, + "referrer": `${location.origin}/`, // referrer (origin, as dictated by the referrer policy) + "type": "navigation-to-response" + }, + "url": /uuid=EXECUTOR_UUID$/, + "type": "coop" + } + } + ] + ], + // Open a cross-origin popup with a same-origin COOP and COEP, and no reporting. + // Produces one navigation-from-report for this document (the opener). The + // pages being cross origin, the next/pervious document urls are not available + // and the initial document url/referrer are used instead. + [ + CROSS_ORIGIN, + `same-origin`, + "require-corp", + "", + "", + [ + { + "endpoint": reportEndpoint, + "report": { + "body": { + "disposition": "enforce", + "effectivePolicy": "same-origin-allow-popups", + "nextResponseURL": /uuid=EXECUTOR_UUID$/, // initial navigation URL + "type": "navigation-from-response" + }, + "url": `${location.href}`, + "type": "coop" + } + } + ] + ], +]; + +runNavigationReportingTests(document.title, tests); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-allow-popups-report-to.https.html.sub.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-allow-popups-report-to.https.html.sub.headers new file mode 100644 index 0000000000..3e213a95a3 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-allow-popups-report-to.https.html.sub.headers @@ -0,0 +1,3 @@ +Reporting-Endpoints: coop-report-endpoint="https://{{host}}:{{ports[https][0]}}/reporting/resources/report.py?reportID=6a739c25-0ec5-4832-b4a3-847281006857", coop-report-only-endpoint="https://{{host}}:{{ports[https][0]}}/reporting/resources/report.py?reportID=f91209ee-b3a3-474b-b337-d663533745fb" +Cross-Origin-Opener-Policy: same-origin-allow-popups; report-to="coop-report-endpoint" +Referrer-Policy: origin diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-coep-report-to.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-coep-report-to.https.html new file mode 100644 index 0000000000..88b180702f --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-coep-report-to.https.html @@ -0,0 +1,173 @@ +<meta name=timeout content=long> +<title>reporting same origin with report-to</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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/resources/common.js"></script> +<script + src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js?pipe=sub&report_id=edbbace3-40ca-4640-8d50-dc6e52acc1da&report_only_id=f65cf51a-ca6f-4028-a2c3-0c06183faa13"></script> +<script> + +let tests = [ + // popup origin, popup COOP, popup COEP, popup COOP report only, popup COEP report only, expected reports + + // Open and navigate a popup to a same-origin page with the same COOP-COEP + // settings: no browsing context group switch hence no report expected. + [ + SAME_ORIGIN, + `same-origin; report-to="${popupReportEndpoint.name}"`, + "require-corp", + "", + "", + [] + ], + // Open a same-origin popup with a same-origin COOP but no COEP. Produces two + // reports (one from and one to). The from report has an effectivePolicy of + // same-origin-plus-coep, both pages being same origin, the entire + // next/pervious document urls are available. + [ + SAME_ORIGIN, + `same-origin; report-to="${popupReportEndpoint.name}"`, + "", + "", + "", + [ + { + "endpoint": reportEndpoint, + "report": { + "body": { + "disposition": "enforce", + "effectivePolicy": "same-origin-plus-coep", + "nextResponseURL": /uuid=EXECUTOR_UUID$/, // next destination url + "type": "navigation-from-response" + }, + "url": `${location.href}`, + "type": "coop" + } + }, + { + "endpoint": popupReportEndpoint, + "report": { + "body": { + "disposition": "enforce", + "effectivePolicy": "same-origin", + "previousResponseURL": `${location.href}`, // previous document url + "referrer": `${location.origin}/`, // referrer (origin, as dictated by the referrer policy) + "type": "navigation-to-response" + }, + "url": /uuid=EXECUTOR_UUID$/, + "type": "coop" + } + } + ] + ], + // Open a cross-origin popup with a same-origin COOP and COEP. Produces two + // reports (one from and one to). The from report has an effectivePolicy of + // same-origin-plus-coep, both pages being cross origin, the next/pervious + // document urls are not available and the initial document url/referrer are + // used instead. + [ + CROSS_ORIGIN, + `same-origin; report-to="${popupReportEndpoint.name}"`, + "require-corp", + "", + "", + [ + { + "endpoint": reportEndpoint, + "report": { + "body": { + "disposition": "enforce", + "effectivePolicy": "same-origin-plus-coep", + "nextResponseURL": /uuid=EXECUTOR_UUID$/, // initial navigation url + "type": "navigation-from-response" + }, + "url": `${location.href}`, + "type": "coop" + } + }, + { + "endpoint": popupReportEndpoint, + "report": { + "body": { + "disposition": "enforce", + "effectivePolicy": "same-origin-plus-coep", + "previousResponseURL": ``, + "referrer": `${location.origin}/`, // referrer (origin, as dictated by the referrer policy) + "type": "navigation-to-response" + }, + "url": /uuid=EXECUTOR_UUID$/, + "type": "coop" + } + } + ] + ], + // Open a same-origin popup with a same-origin COOP report only. One report + // is sent to this page's endpoint, but none to the report-only endpoint. + [ + SAME_ORIGIN, + "", + "", + `same-origin; report-to="${popupReportOnlyEndpoint.name}"`, + "require-corp", + [ + { + "endpoint": reportEndpoint, + "report": { + "body": { + "disposition": "enforce", + "effectivePolicy": "same-origin-plus-coep", + "nextResponseURL": /uuid=EXECUTOR_UUID$/, // initial navigation url + "type": "navigation-from-response" + }, + "url": `${location.href}`, + "type": "coop" + } + } + ] + ], + // Open a cross-origin popup with a same-origin COOP report only. A report is + // sent to both this page's endpoint and the popup's. + [ + CROSS_ORIGIN, + "", + "", + `same-origin; report-to="${popupReportOnlyEndpoint.name}"`, + "require-corp", + [ + { + "endpoint": reportEndpoint, + "report": { + "body": { + "disposition": "enforce", + "effectivePolicy": "same-origin-plus-coep", + "nextResponseURL": /uuid=EXECUTOR_UUID$/, // initial navigation url + "type": "navigation-from-response" + }, + "url": `${location.href}`, + "type": "coop" + } + }, + { + "endpoint": popupReportOnlyEndpoint, + "report": { + "body": { + "disposition": "reporting", + "effectivePolicy": "same-origin-plus-coep", + "previousResponseURL": ``, + "referrer": `${location.origin}/`, // referrer (origin, as dictated by the referrer policy) + "type": "navigation-to-response" + }, + "url": /uuid=EXECUTOR_UUID$/, + "type": "coop" + } + } + ] + ], +]; + +runNavigationReportingTests(document.title, tests); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-coep-report-to.https.html.sub.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-coep-report-to.https.html.sub.headers new file mode 100644 index 0000000000..0f78bdb2d0 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-coep-report-to.https.html.sub.headers @@ -0,0 +1,4 @@ +Reporting-Endpoints: coop-report-endpoint="https://{{host}}:{{ports[https][0]}}/reporting/resources/report.py?reportID=edbbace3-40ca-4640-8d50-dc6e52acc1da", coop-report-only-endpoint="https://{{host}}:{{ports[https][0]}}/reporting/resources/report.py?reportID=f65cf51a-ca6f-4028-a2c3-0c06183faa13" +Cross-Origin-Opener-Policy: same-origin; report-to="coop-report-endpoint" +Cross-Origin-Embedder-Policy: require-corp +Referrer-Policy: origin diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-report-to.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-report-to.https.html new file mode 100644 index 0000000000..47bb67cc4b --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-report-to.https.html @@ -0,0 +1,216 @@ +<meta name=timeout content=long> +<title>reporting same origin with report-to</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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/resources/common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js?pipe=sub&report_id=6aad9729-8642-4894-91d9-a4d44707cd4a&report_only_id=69eb1838-6a03-4cda-97b0-c126ffcb9e8a"></script> + +<script> + +let tests = [ + // popup origin, popup COOP, popup COEP, popup COOP report only, popup COEP report only, expected reports + + // Open a popup on a same-origin page, with a compatible COOP. + // This is a sanity check that no report are produced. + [ + SAME_ORIGIN, + `same-origin; report-to="${popupReportEndpoint.name}"`, + "", + "", + "", + [] + ], + // Open a cross-origin popup with a same-origin COOP. Produces two + // reports (one from and one to). The from report has an effectivePolicy of + // same-origin (corresponding to the current document), both pages being + // cross origin, the next/pervious document urls are not available and the + // initial document url/referrer are used instead. + [ + CROSS_ORIGIN, + `same-origin; report-to="${popupReportEndpoint.name}"`, + "", + "", + "", + [ + { + "endpoint": reportEndpoint, + "report": { + "body": { + "disposition": "enforce", + "effectivePolicy": "same-origin", + "nextResponseURL": /uuid=EXECUTOR_UUID$/, + "type": "navigation-from-response" + }, + "url": `${location.href}`, + "type": "coop" + } + }, + { + "endpoint": popupReportEndpoint, + "report": { + "body": { + "disposition": "enforce", + "effectivePolicy": "same-origin", + "previousResponseURL": "", + "referrer": '', // referrer (empty due to the Referrer Policy) + "type": "navigation-to-response" + }, + "url": /uuid=EXECUTOR_UUID$/, + "type": "coop" + } + } + ] + ], + // Open a same-origin popup with a unsafe-none COOP and no COEP. COOP switches + // the browsing context group and hence produces two reports (one from and one + // to). This test verifies that unsafe-none properly sends report. + [ + SAME_ORIGIN, + `unsafe-none; report-to="${popupReportEndpoint.name}"`, + "", + "", + "", + [ + { + "endpoint": reportEndpoint, + "report": { + "body": { + "disposition": "enforce", + "effectivePolicy": "same-origin", + "nextResponseURL": /uuid=EXECUTOR_UUID$/, + "type": "navigation-from-response" + }, + "url": `${location.href}`, + "type": "coop" + } + }, + { + "endpoint": popupReportEndpoint, + "report": { + "body": { + "disposition": "enforce", + "effectivePolicy": "unsafe-none", + "previousResponseURL": `${location.href}`, + "referrer": '', // referrer (empty due to the Referrer Policy) + "type": "navigation-to-response" + }, + "url": /uuid=EXECUTOR_UUID$/, + "type": "coop" + } + } + ] + ], + // Open a same-origin popup with a same-origin COOP and COEP. The difference + // of COEP values leads to the browsing context group switch and produces two + // reports. This verifies that the navigation-to-document report has an + // effectivePolicy of same-origin-plus-coep. + [ + SAME_ORIGIN, + `same-origin; report-to="${popupReportEndpoint.name}"`, + "require-corp", + "", + "", + [ + { + "endpoint": reportEndpoint, + "report": { + "body": { + "disposition": "enforce", + "effectivePolicy": "same-origin", + "nextResponseURL": /uuid=EXECUTOR_UUID$/, + "type": "navigation-from-response" + }, + "url": `${location.href}`, + "type": "coop" + } + }, + { + "endpoint": popupReportEndpoint, + "report": { + "body": { + "disposition": "enforce", + "effectivePolicy": "same-origin-plus-coep", + "previousResponseURL": `${location.href}`, + "referrer": '', // referrer (empty due to the Referrer Policy) + "type": "navigation-to-response" + }, + "url": /uuid=EXECUTOR_UUID$/, + "type": "coop" + } + } + ] + ], + // Open a cross-origin popup with no COOP (but reporting) and no COEP. + // Produces two reports. The pages being cross origin, the next/pervious + // document urls are not available and the initial document url/referrer are + // used instead. + [ + CROSS_ORIGIN, + `unsafe-none; report-to="${popupReportEndpoint.name}"`, + "", + "", + "", + [ + { + "endpoint": reportEndpoint, + "report": { + "body": { + "disposition": "enforce", + "effectivePolicy": "same-origin", + "nextResponseURL": /uuid=EXECUTOR_UUID$/, + "type": "navigation-from-response" + }, + "url": `${location.href}`, + "type": "coop" + } + }, + { + "endpoint": popupReportEndpoint, + "report": { + "body": { + "disposition": "enforce", + "effectivePolicy": "unsafe-none", + "previousResponseURL": "", + "referrer": '', // referrer (empty due to the Referrer Policy) + "type": "navigation-to-response" + }, + "url": /uuid=EXECUTOR_UUID$/, + "type": "coop" + } + } + ] + ], + // Open a same-origin popup with no COOP (without reporting) and no COEP. + // Produces one report to this page (opener) endpoint. + // This verifies that the navigated-to-document's COOP report values do not + // impact the navigated-from-document's COOP. + [ + SAME_ORIGIN, + "unsafe-none", + "", + "", + "", + [ + { + "endpoint": reportEndpoint, + "report": { + "body": { + "disposition": "enforce", + "effectivePolicy": "same-origin", + "nextResponseURL": /uuid=EXECUTOR_UUID$/, + "type": "navigation-from-response" + }, + "url": `${location.href}`, + "type": "coop" + } + } + ] + ] +]; + +runNavigationReportingTests(document.title, tests); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-report-to.https.html.sub.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-report-to.https.html.sub.headers new file mode 100644 index 0000000000..79c851a86c --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-report-to.https.html.sub.headers @@ -0,0 +1,3 @@ +Reporting-Endpoints: coop-report-endpoint="https://{{host}}:{{ports[https][0]}}/reporting/resources/report.py?reportID=6aad9729-8642-4894-91d9-a4d44707cd4a", coop-report-only-endpoint="https://{{host}}:{{ports[https][0]}}/reporting/resources/report.py?reportID=69eb1838-6a03-4cda-97b0-c126ffcb9e8a" +Cross-Origin-Opener-Policy: same-origin; report-to="coop-report-endpoint" +Referrer-Policy: no-referrer diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin.https.html new file mode 100644 index 0000000000..3a8f343f37 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin.https.html @@ -0,0 +1,110 @@ +<meta name=timeout content=long> +<title>reporting same origin</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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/resources/common.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js"></script> + +<script> + +let tests = [ + // popup origin, popup COOP, popup COEP, popup COOP report only, popup COEP report only, expected reports + + // Open a cross-origin popup with a same-origin COOP and no COEP. COOP + // switches the browsing context group and hence produces one report. + // This test verifies that the navigated to document properly sends a + // navigation-to report. The navigationURI is the referrer. + [ + CROSS_ORIGIN, + `same-origin; report-to="${popupReportEndpoint.name}"`, + "", + "", + "", + [ + { + "endpoint": popupReportEndpoint, + "report": { + "body": { + "disposition": "enforce", + "effectivePolicy": "same-origin", + "previousResponseURL": "", + "referrer": `${location.origin}/`, // referrer + "type": "navigation-to-response" + }, + "url": /uuid=EXECUTOR_UUID$/, + "type": "coop" + } + } + ] + ], + // Open a same-origin popup with a unsafe-none COOP and no COEP. COOP switches + // the browsing context group and hence produces one report. + // This test verifies that having different policies on same origin documents + // still properly produces report to the navigated-to-document. + [ + SAME_ORIGIN, + `unsafe-none; report-to="${popupReportEndpoint.name}"`, + "", + "", + "", + [ + { + "endpoint": popupReportEndpoint, + "report": { + "body": { + "disposition": "enforce", + "effectivePolicy": "unsafe-none", + "previousResponseURL": `${location.href}`, + "referrer": `${location.href}`, // referrer + "type": "navigation-to-response" + }, + "url": /uuid=EXECUTOR_UUID$/, + "type": "coop" + } + } + ] + ], + // Open a cross-origin popup with a unsafe-none COOP (with reporting) and no + // COEP. COOP switches the browsing context group and hence produces one + // reports to the unsafe-none document. This test verifies that unsafe-none + // properly sends report in that configuration. + [ + CROSS_ORIGIN, + `unsafe-none; report-to="${popupReportEndpoint.name}"`, + "", + "", + "", + [ + { + "endpoint": popupReportEndpoint, + "report": { + "body": { + "disposition": "enforce", + "previousResponseURL": "", + "referrer": `${location.origin}/`, // referrer + "type": "navigation-to-response" + }, + "url": /uuid=EXECUTOR_UUID$/, + "type": "coop" + } + } + ] + ], + // Open a same-origin popup with a same-origin COOP Report only value, the + // report only matches the previous document COOP value, no report is sent. + [ + SAME_ORIGIN, + "", + "", + `same-origin; report-to="${popupReportOnlyEndpoint.name}"`, + "", + [] + ], +]; + +runNavigationReportingTests(document.title, tests); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin.https.html.headers new file mode 100644 index 0000000000..46ad58d83b --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: same-origin diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-unsafe-none-report-to.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-unsafe-none-report-to.https.html new file mode 100644 index 0000000000..2563dbb01f --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-unsafe-none-report-to.https.html @@ -0,0 +1,126 @@ +<meta name=timeout content=long> +<title>reporting same origin with report-to</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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/resources/common.js"></script> +<script + src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js?pipe=sub&report_id=1f79b0d5-c2a2-4e0b-8e8c-651af2321964&report_only_id=c50700c8-db1e-4224-b06f-4c6a95a5f4be"></script> + +<script> + +let tests = [ + // popup origin, popup COOP, popup COEP, popup COOP report only, popup COEP report only, expected reports + + // Open a same-origin popup with a same-origin COOP with reporting and no COEP. + // COOP switches the browsing context group and hence produces two reports + // (one from and one to). This test verifies that unsafe-none (from the opener) + // properly sends a report. + [ + SAME_ORIGIN, + `same-origin; report-to="${popupReportEndpoint.name}"`, + "", + "", + "", + [ + { + "endpoint": reportEndpoint, + "report": { + "body": { + "disposition": "enforce", + "effectivePolicy": "unsafe-none", + "nextResponseURL": /uuid=EXECUTOR_UUID$/, // next document URL + "type": "navigation-from-response" + }, + "url": `${location.href}`, + "type": "coop" + } + }, + { + "endpoint": popupReportEndpoint, + "report": { + "body": { + "disposition": "enforce", + "effectivePolicy": "same-origin", + "previousResponseURL": `${location.href}`, // previous document url + "referrer": `${location.href}`, // referrer + "type": "navigation-to-response" + }, + "url": /uuid=EXECUTOR_UUID$/, + "type": "coop" + } + } + ] + ], + // Open a same-origin popup with a same-origin COOP (no reporting)and no COEP. + // COOP switches the browsing context group and hence produces one report for + // the navigated from document (this page, the opener). This test differs with + // the previous one as it assert that the navigated to document's COOP reporting + // values do not interfere. + [ + SAME_ORIGIN, + `same-origin`, + "", + "", + "", + [ + { + "endpoint": reportEndpoint, + "report": { + "body": { + "disposition": "enforce", + "effectivePolicy": "unsafe-none", + "nextResponseURL": /uuid=EXECUTOR_UUID$/, // next document URL + "type": "navigation-from-response" + }, + "url": `${location.href}`, + "type": "coop" + } + } + ] + ], + // Open a cross-origin popup with a same-origin COOP and no COEP. COOP switches + // the browsing context group and hence produces two reports. + [ + CROSS_ORIGIN, + `same-origin; report-to="${popupReportEndpoint.name}"`, + "", + "", + "", + [ + { + "endpoint": reportEndpoint, + "report": { + "body": { + "disposition": "enforce", + "effectivePolicy": "unsafe-none", + "nextResponseURL": /uuid=EXECUTOR_UUID$/, // next document URL + "type": "navigation-from-response" + }, + "url": `${location.href}`, + "type": "coop" + } + }, + { + "endpoint": popupReportEndpoint, + "report": { + "body": { + "disposition": "enforce", + "effectivePolicy": "same-origin", + "previousResponseURL": ``, + "referrer": `${location.origin}/`, // referrer + "type": "navigation-to-response" + }, + "url": /uuid=EXECUTOR_UUID$/, + "type": "coop" + } + } + ] + ] +]; + +runNavigationReportingTests(document.title, tests); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-unsafe-none-report-to.https.html.sub.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-unsafe-none-report-to.https.html.sub.headers new file mode 100644 index 0000000000..f1f18d6708 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-unsafe-none-report-to.https.html.sub.headers @@ -0,0 +1,2 @@ +Reporting-Endpoints: coop-report-endpoint="https://{{host}}:{{ports[https][0]}}/reporting/resources/report.py?reportID=1f79b0d5-c2a2-4e0b-8e8c-651af2321964", coop-report-only-endpoint="https://{{host}}:{{ports[https][0]}}/reporting/resources/report.py?reportID=c50700c8-db1e-4224-b06f-4c6a95a5f4be" +Cross-Origin-Opener-Policy: unsafe-none; report-to="coop-report-endpoint" diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-redirect-with-same-origin-allow-popups.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-redirect-with-same-origin-allow-popups.https.html new file mode 100644 index 0000000000..cd2f6b67b3 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-redirect-with-same-origin-allow-popups.https.html @@ -0,0 +1,111 @@ +<title> + Tests the redirect interaction with COOP same-origin-allow-popups. +</title> +<meta name=timeout content=long> +<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> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/cross-origin-opener-policy/reporting/resources/reporting-common.js"></script> +<script> + +const directory = "/html/cross-origin-opener-policy"; +const same_origin = { + host: get_host_info().HTTPS_ORIGIN, + name: "Same origin" +}; +const cross_origin = { + host: get_host_info().HTTPS_REMOTE_ORIGIN, + name: "Cross origin" +}; + +// Tests the redirect interaction with COOP same-origin-allow-popups and +// reporting: +// 1 - open the opener document on origin same_origin with COOP +// same-origin-allow-popups. +// 2 - opener opens popup with document on origin popup_origin, no COOP and a +// redirect header (HTTP 302, location). +// 3 - redirection to a document with origin same_origin and COOP +// same-origin-allow-popups. +// +// The navigation (2) to the first document of the popup stays in the same +// browsing context group due to the same-origin-allow-popups COOP of the +// opener. +// The redirect (3) to the final document does since it compares the +// popup_origin/unsafe-none document with the +// same-origin/same-origin-allow-popups document. +// +// A opens B, B redirects to C. +// +// Document Origin COOP +// -------- ------------ ------------------------ +// A same-origin same-origin-allow-popups +// B popup-origin unsafe-none +// C same-origin same-origin-allow-popups +function redirect_test( popup_origin ) { + promise_test(async t => { + // The test window. + const this_window_token = token(); + + // The "opener" window. This has COOP same-origin-allow-popups and a + // reporter. + const opener_report_token = reportToken(); + const opener_token = token(); + const opener_reportTo = reportingEndpointsHeaders(opener_report_token); + const opener_url = same_origin.host + executor_path + + opener_reportTo.header + opener_reportTo.coopSameOriginAllowPopupsHeader + + `&uuid=${opener_token}`; + + // The "openee" window. + // The initial document does not have COOP and is on popup_origin, it + // redirects to a same-origin (with the opener) document with COOP + // same-origin-allow-popups. + const openee_token = token(); + const openee_redirect_url = same_origin.host + executor_path + + opener_reportTo.header + opener_reportTo.coopSameOriginAllowPopupsHeader + + `&uuid=${openee_token}`; + const redirect_header = 'status(302)' + + `|header(Location,${encodeURIComponent( + openee_redirect_url + .replace(/,/g, "\\,") + .replace(/\\\\,/g, "\\\\\\,") + .replace(/\(/g, "%28") + .replace(/\)/g, "%29"))})`; + const openee_url = popup_origin.host + executor_path + redirect_header + + `&uuid=${openee_token}`; + // 1. Create the opener window. + let opener_window_proxy = window.open(opener_url); + t.add_cleanup(() => send(opener_token, "window.close()")); + + // 2. The opener opens its openee. + send(opener_token, ` + openee = window.open("${openee_url}"); + `); + t.add_cleanup(() => send(openee_token, "window.close()")); + + // 3. Check the opener status on the openee. + send(openee_token, ` + send("${this_window_token}", opener !== null); + `); + assert_equals(await receive(this_window_token), "false", "opener"); + + // 4. Check the openee status on the opener. + send(opener_token, ` + send("${this_window_token}", openee.closed); + `); + assert_equals(await receive(this_window_token), "true", "openee.closed"); + + // 5. Check a report sent to the openee. + let report = await receiveReport( + opener_report_token, + "navigation-to-response"); + assert_equals(report.type, "coop"); + assert_equals(report.body.disposition, "enforce"); + assert_equals(report.body.effectivePolicy, "same-origin-allow-popups"); + }, `${popup_origin.name} openee redirected to same-origin with same-origin-allow-popups`); +} + +redirect_test(same_origin); +redirect_test(cross_origin); +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/resources/reporting-common.js b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/resources/reporting-common.js new file mode 100644 index 0000000000..19f6410cbf --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/resources/reporting-common.js @@ -0,0 +1,405 @@ +const executor_path = "/common/dispatcher/executor.html?pipe="; +const coep_header = '|header(Cross-Origin-Embedder-Policy,require-corp)'; + +// Report endpoint keys must start with a lower case alphabet character. +// https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-header-structure-15#section-4.2.3.3 +const reportToken = () => { + return token().replace(/./, 'a'); +} + +const isWPTSubEnabled = "{{GET[pipe]}}".includes("sub"); + +const getReportEndpointURL = (reportID) => + `/reporting/resources/report.py?reportID=${reportID}`; + +const reportEndpoint = { + name: "coop-report-endpoint", + reportID: isWPTSubEnabled ? "{{GET[report_id]}}" : token(), + reports: [] +}; +const reportOnlyEndpoint = { + name: "coop-report-only-endpoint", + reportID: isWPTSubEnabled ? "{{GET[report_only_id]}}" : token(), + reports: [] +}; +const popupReportEndpoint = { + name: "coop-popup-report-endpoint", + reportID: token(), + reports: [] +}; +const popupReportOnlyEndpoint = { + name: "coop-popup-report-only-endpoint", + reportID: token(), + reports: [] +}; +const redirectReportEndpoint = { + name: "coop-redirect-report-endpoint", + reportID: token(), + reports: [] +}; +const redirectReportOnlyEndpoint = { + name: "coop-redirect-report-only-endpoint", + reportID: token(), + reports: [] +}; + +const reportEndpoints = [ + reportEndpoint, + reportOnlyEndpoint, + popupReportEndpoint, + popupReportOnlyEndpoint, + redirectReportEndpoint, + redirectReportOnlyEndpoint +]; + +// Allows RegExps to be pretty printed when printing unmatched expected reports. +Object.defineProperty(RegExp.prototype, "toJSON", { + value: RegExp.prototype.toString +}); + +function wait(ms) { + return new Promise(resolve => step_timeout(resolve, ms)); +} + +// Check whether a |report| is a "opener breakage" COOP report. +function isCoopOpenerBreakageReport(report) { + if (report.type != "coop") + return false; + + if (report.body.type != "navigation-from-response" && + report.body.type != "navigation-to-response") { + return false; + } + + return true; +} + +async function clearReportsOnServer(host) { + const res = await fetch( + '/reporting/resources/report.py', { + method: "POST", + body: JSON.stringify({ + op: "DELETE", + reportIDs: reportEndpoints.map(endpoint => endpoint.reportID) + }) + }); + assert_equals(res.status, 200, "reports cleared"); +} + +async function pollReports(endpoint) { + const res = await fetch(getReportEndpointURL(endpoint.reportID), + { cache: 'no-store' }); + if (res.status !== 200) { + return; + } + for (const report of await res.json()) { + if (isCoopOpenerBreakageReport(report)) + endpoint.reports.push(report); + } +} + +// Recursively check that all members of expectedReport are present or matched +// in report. +// Report may have members not explicitly expected by expectedReport. +function isObjectAsExpected(report, expectedReport) { + if (( report === undefined || report === null + || expectedReport === undefined || expectedReport === null ) + && report !== expectedReport ) { + return false; + } + if (expectedReport instanceof RegExp && typeof report === "string") { + return expectedReport.test(report); + } + // Perform this check now, as RegExp and strings above have different typeof. + if (typeof report !== typeof expectedReport) + return false; + if (typeof expectedReport === 'object') { + return Object.keys(expectedReport).every(key => { + return isObjectAsExpected(report[key], expectedReport[key]); + }); + } + return report == expectedReport; +} + +async function checkForExpectedReport(expectedReport) { + return new Promise( async (resolve, reject) => { + const polls = 20; + const waitTime = 200; + for (var i=0; i < polls; ++i) { + pollReports(expectedReport.endpoint); + for (var j=0; j<expectedReport.endpoint.reports.length; ++j){ + if (isObjectAsExpected(expectedReport.endpoint.reports[j], + expectedReport.report)){ + expectedReport.endpoint.reports.splice(j,1); + resolve(); + return; + } + }; + await wait(waitTime); + } + reject( + replaceTokensInReceivedReport( + "No report matched the expected report for endpoint: " + + expectedReport.endpoint.name + + ", expected report: " + JSON.stringify(expectedReport.report) + + ", within available reports: " + + JSON.stringify(expectedReport.endpoint.reports) + )); + }); +} + +function replaceFromRegexOrString(str, match, value) { + if (str instanceof RegExp) { + return RegExp(str.source.replace(match, value)); + } + return str.replace(match, value); +} + +// Replace generated values in regexes and strings of an expected report: +// EXECUTOR_UUID: the uuid generated with token(). +function replaceValuesInExpectedReport(expectedReport, executorUuid) { + if (expectedReport.report.body !== undefined) { + if (expectedReport.report.body.nextResponseURL !== undefined) { + expectedReport.report.body.nextResponseURL = replaceFromRegexOrString( + expectedReport.report.body.nextResponseURL, "EXECUTOR_UUID", + executorUuid); + } + if (expectedReport.report.body.previousResponseURL !== undefined) { + expectedReport.report.body.previousResponseURL = replaceFromRegexOrString( + expectedReport.report.body.previousResponseURL, "EXECUTOR_UUID", + executorUuid); + } + if (expectedReport.report.body.referrer !== undefined) { + expectedReport.report.body.referrer = replaceFromRegexOrString( + expectedReport.report.body.referrer, "EXECUTOR_UUID", + executorUuid); + } + } + if (expectedReport.report.url !== undefined) { + expectedReport.report.url = replaceFromRegexOrString( + expectedReport.report.url, "EXECUTOR_UUID", executorUuid); + } + return expectedReport; +} + +function replaceTokensInReceivedReport(str) { + return str.replace(/.{8}-.{4}-.{4}-.{4}-.{12}/g, `(uuid)`); +} + +// Run a test then check that all expected reports are present. +async function reportingTest(testFunction, executorToken, expectedReports) { + await new Promise(testFunction); + expectedReports = Array.from( + expectedReports, + report => replaceValuesInExpectedReport(report, executorToken) ); + await Promise.all(Array.from(expectedReports, checkForExpectedReport)); +} + +function convertToWPTHeaderPipe([name, value]) { + return `header(${name}, ${encodeURIComponent(value)})`; +} + +function getReportToHeader(host) { + return [ + "Report-To", + reportEndpoints.map( + reportEndpoint => { + const reportToJSON = { + 'group': `${reportEndpoint.name}`, + 'max_age': 3600, + 'endpoints': [{ + 'url': `${host}${getReportEndpointURL(reportEndpoint.reportID)}` + }] + }; + // Escape comma as required by wpt pipes. + return JSON.stringify(reportToJSON) + .replace(/,/g, '\\,') + .replace(/\(/g, '\\\(') + .replace(/\)/g, '\\\)='); + } + ).join("\\, ")]; +} + +function getReportingEndpointsHeader(host) { + return [ + "Reporting-Endpoints", + reportEndpoints.map(reportEndpoint => { + return `${reportEndpoint.name}="${host}${getReportEndpointURL(reportEndpoint.reportID)}"`; + }).join("\\, ")]; +} + +// Return Report and Report-Only policy headers. +function getPolicyHeaders(coop, coep, coopRo, coepRo) { + return [ + [`Cross-Origin-Opener-Policy`, coop], + [`Cross-Origin-Embedder-Policy`, coep], + [`Cross-Origin-Opener-Policy-Report-Only`, coopRo], + [`Cross-Origin-Embedder-Policy-Report-Only`, coepRo]]; +} + +function navigationReportingTest(testName, host, coop, coep, coopRo, coepRo, + expectedReports) { + const executorToken = token(); + const callbackToken = token(); + promise_test(async t => { + await reportingTest(async resolve => { + const openee_headers = [ + getReportingEndpointsHeader(host.origin), + ...getPolicyHeaders(coop, coep, coopRo, coepRo) + ].map(convertToWPTHeaderPipe); + const openee_url = host.origin + executor_path + + openee_headers.join('|') + `&uuid=${executorToken}`; + const openee = window.open(openee_url); + const uuid = token(); + t.add_cleanup(() => send(uuid, "window.close()")); + + // 1. Make sure the new document is loaded. + send(executorToken, ` + send("${callbackToken}", "Ready"); + `); + let reply = await receive(callbackToken); + assert_equals(reply, "Ready"); + resolve(); + }, executorToken, expectedReports); + }, `coop reporting test ${testName} to ${host.name} with ${coop}, ${coep}, ${coopRo}, ${coepRo}`); +} + +function navigationDocumentReportingTest(testName, host, coop, coep, coopRo, + coepRo, expectedReports) { + const executorToken = token(); + const callbackToken = token(); + promise_test(async t => { + const openee_headers = [ + getReportingEndpointsHeader(host.origin), + ...getPolicyHeaders(coop, coep, coopRo, coepRo) + ].map(convertToWPTHeaderPipe); + const openee_url = host.origin + executor_path + + openee_headers.join('|') + `&uuid=${executorToken}`; + window.open(openee_url); + t.add_cleanup(() => send(executorToken, "window.close()")); + // Have openee window send a message through dispatcher, once we receive + // the Ready message from dispatcher it means the openee is fully loaded. + send(executorToken, ` + send("${callbackToken}", "Ready"); + `); + let reply = await receive(callbackToken); + assert_equals(reply, "Ready"); + + await wait(1000); + + expectedReports = expectedReports.map( + (report) => replaceValuesInExpectedReport(report, executorToken)); + return Promise.all(expectedReports.map( + async ({ endpoint, report: expectedReport }) => { + await pollReports(endpoint); + for (let report of endpoint.reports) { + assert_true(isObjectAsExpected(report, expectedReport), + `report received for endpoint: ${endpoint.name} ${JSON.stringify(report)} should match ${JSON.stringify(expectedReport)}`); + } + assert_equals(endpoint.reports.length, 1, `has exactly one report for ${endpoint.name}`) + })); + }, `coop document reporting test ${testName} to ${host.name} with ${coop}, ${coep}, ${coopRo}, ${coepRo}`); +} + +// Run an array of reporting tests then verify there's no reports that were not +// expected. +// Tests' elements contain: host, coop, coep, coop-report-only, +// coep-report-only, expectedReports. +// See isObjectAsExpected for explanations regarding the matching behavior. +async function runNavigationReportingTests(testName, tests) { + await clearReportsOnServer(); + tests.forEach(test => { + navigationReportingTest(testName, ...test); + }); + verifyRemainingReports(); +} + +// Run an array of reporting tests using Reporting-Endpoints header then +// verify there's no reports that were not expected. +// Tests' elements contain: host, coop, coep, coop-report-only, +// coep-report-only, expectedReports. +// See isObjectAsExpected for explanations regarding the matching behavior. +function runNavigationDocumentReportingTests(testName, tests) { + clearReportsOnServer(); + tests.forEach(test => { + navigationDocumentReportingTest(testName, ...test); + }); +} + +function verifyRemainingReports() { + promise_test(t => { + return Promise.all(reportEndpoints.map(async (endpoint) => { + await pollReports(endpoint); + assert_equals(endpoint.reports.length, 0, `${endpoint.name} should be empty`); + })); + }, "verify remaining reports"); +} + +const receiveReport = async function(uuid, type) { + while(true) { + let reports = await Promise.race([ + receive(uuid), + new Promise(resolve => { + step_timeout(resolve, 1000, "timeout"); + }) + ]); + if (reports == "timeout") + return "timeout"; + reports = JSON.parse(reports); + for(report of reports) { + if (report?.body?.type == type) + return report; + } + } +} + +// Build a set of 'Cross-Origin-Opener-Policy' and +// 'Cross-Origin-Opener-Policy-Report-Only' headers. +const coopHeaders = function (uuid) { + return { + coopSameOriginHeader: `|header(Cross-Origin-Opener-Policy,same-origin%3Breport-to="${uuid}")`, + coopSameOriginAllowPopupsHeader: `|header(Cross-Origin-Opener-Policy,same-origin-allow-popups%3Breport-to="${uuid}")`, + coopReportOnlySameOriginHeader: `|header(Cross-Origin-Opener-Policy-Report-Only,same-origin%3Breport-to="${uuid}")`, + coopReportOnlySameOriginAllowPopupsHeader: `|header(Cross-Origin-Opener-Policy-Report-Only,same-origin-allow-popups%3Breport-to="${uuid}")` + }; +} + +// Build a set of headers to tests the reporting API. This defines a set of +// matching 'Report-To', 'Cross-Origin-Opener-Policy' and +// 'Cross-Origin-Opener-Policy-Report-Only' headers. +const reportToHeaders = function(uuid) { + const report_endpoint_url = dispatcher_path + `?uuid=${uuid}`; + let reportToJSON = { + 'group': `${uuid}`, + 'max_age': 3600, + 'endpoints': [ + {'url': report_endpoint_url.toString()}, + ] + }; + reportToJSON = JSON.stringify(reportToJSON) + .replace(/,/g, '\\,') + .replace(/\(/g, '\\\(') + .replace(/\)/g, '\\\)='); + + return { + header: `|header(report-to,${reportToJSON})`, + ...coopHeaders(uuid) + }; +}; + +// Build a set of headers to tests the reporting API. This defines a set of +// matching 'Reporting-Endpoints', 'Cross-Origin-Opener-Policy' and +// 'Cross-Origin-Opener-Policy-Report-Only' headers. +const reportingEndpointsHeaders = function (uuid) { + // Report endpoint keys must start with a lower case alphabet: + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-header-structure-15#section-4.2.3.3 + assert_true(uuid.match(/^[a-z].*/) != null, 'Use reportToken() instead.'); + + const report_endpoint_url = dispatcher_path + `?uuid=${uuid}`; + const reporting_endpoints_header = `${uuid}="${report_endpoint_url}"`; + + return { + header: `|header(Reporting-Endpoints,${reporting_endpoints_header})`, + ...coopHeaders(uuid) + }; +}; diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/resources/test-access-property.js b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/resources/test-access-property.js new file mode 100644 index 0000000000..fe01e9128c --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/resources/test-access-property.js @@ -0,0 +1,57 @@ +const same_origin = get_host_info().HTTPS_ORIGIN; +const cross_origin = get_host_info().HTTPS_REMOTE_ORIGIN; + +const origin = [ + ["same-origin" , same_origin ], + ["cross-origin", cross_origin], +]; +let escapeComma = url => url.replace(/,/g, '\\,'); + +let testAccessProperty = (property, op, expectReport = true) => { + origin.forEach(([origin_name, origin]) => { + promise_test(async t => { + const this_window_token = token(); + + // The opener window: + const opener_token = token(); + const opener_url = get_host_info().HTTP_ORIGIN + executor_path + + `&uuid=${opener_token}`; + + // The openee window: + const openee_token = token(); + const openee_report_token = token(); + const openee_report_to = reportToHeaders(openee_report_token); + const openee_url = origin + executor_path + openee_report_to.header + + openee_report_to.coopReportOnlySameOriginHeader + coep_header + + `&uuid=${openee_token}`; + + t.add_cleanup(() => { + send(opener_token, "window.close()") + send(openee_token, "window.close()") + }); + + // Open the two windows. Wait for them to be loaded. + window.open(opener_url); + send(opener_token, ` + window.openee = window.open('${escapeComma(openee_url)}'); + `); + send(openee_token, `send("${this_window_token}", "Ready");`); + assert_equals(await receive(this_window_token), "Ready"); + + // 2. Try to access the openee. + send(opener_token, `(${op})(openee);`); + + // 3. Fetch reports sent to the openee. + let report = await receiveReport(openee_report_token, + "access-to-coop-page-from-opener"); + if (expectReport) { + assert_equals(report.body.property, property); + } else { + // "timeout" should be returned if no such reports are received. + assert_equals(report, "timeout"); + } + + + }, `${origin_name} > ${op}`); + }) +}; diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/resources/try-access.js b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/resources/try-access.js new file mode 100644 index 0000000000..a06cb07904 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/reporting/resources/try-access.js @@ -0,0 +1,20 @@ +// A function trying to access to |w| through a "CrossOrigin" attribute (blur). +// This function is kept in its own file to ensure the source location of the +// call stays constant. +function tryAccess(w) { + try { + w.blur(); + } catch(e) {} +} + +function assert_source_location_found(report) { + assert_true(report.body.sourceFile.includes("try-access.js")); + assert_equals(report.body.lineNumber, 6); + assert_equals(report.body.columnNumber, 7); +} + +function assert_source_location_missing(report) { + assert_equals(report.body.sourceFile, undefined); + assert_equals(report.body.lineNumber, undefined); + assert_equals(report.body.columnNumber, undefined); +} diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/resource-popup.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/resource-popup.https.html new file mode 100644 index 0000000000..481cceb72f --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/resource-popup.https.html @@ -0,0 +1,91 @@ +<!DOCTYPE html> +<html lang="en"> +<meta charset="utf-8"> +<title>Cross-Origin-Opener-Policy forces browsing context switch in various popup document types</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/utils.js"></script> + +<p>These tests create a "parent" popup window which is an HTML document with a +specific Cross-Origin-Opener-Policy. The parent creates a "child" popup window +which is a non-HTML document with a Cross-Origin-Opener-Policy of its own. The +parent waits for the child's location to change from "<code>about:blank</code>" +and then inspects its <code>name</code> and <code>closed</code> properties +which it reports back to the test context.</p> + +<p>The HTTP `Refresh` header is used to ensure the child eventually closes +itself (since proper observance of COOP will prevent the parent from closing +the child in some cases).</p> + +<script> +'use strict'; + +const coop_resource_test = ({parentCoop, resourceCoop, resource, resourceName, validate}) => { + async_test((t) => { + const bc = new BroadcastChannel(token()); + bc.onmessage = t.step_func_done(({data}) => validate(data)); + const childLocation = resource + + `?pipe=header(Refresh,2;url=/html/cross-origin-opener-policy/resources/resource-cleanup.html?channel=${bc.name})` + + (resourceCoop ? `|header(Cross-Origin-Opener-Policy,${resourceCoop})` : ''); + const parentLocation = 'resources/resource-popup.html' + + `?channel_name=${bc.name}` + + `&resource=${encodeURIComponent(childLocation)}` + + `&resource_name=${resourceName}` + + (parentCoop ? `&pipe=header(Cross-Origin-Opener-Policy,${parentCoop})` : ''); + + open(parentLocation); + + t.add_cleanup(() => { + // Close the "parent" popup and the "child" popup if it has already + // redirected to the HTML document. + bc.postMessage(null); + // Prepare to close the "child" popup in the case that it has not yet + // redirected to the the HTML document. + bc.onmessage = () => bc.postMessage(null); + }); + }, `${resource} - parent COOP: "${parentCoop}"; child COOP: "${resourceCoop}"`); +}; + +const resources = [ + '/common/dummy.xml', + '/images/red.png', + '/common/text-plain.txt', + '/media/2x2-green.mp4', +]; + +for (const resource of resources) { + coop_resource_test({ + parentCoop: '', + resourceCoop: 'same-origin', + resource, + resourceName: 'foobar', + validate(data) { + assert_equals(data.name, null); + assert_equals(data.closed, true); + } + }); + + coop_resource_test({ + parentCoop: 'same-origin', + resourceCoop: '', + resource, + resourceName: 'foobar', + validate(data) { + assert_equals(data.name, null); + assert_equals(data.closed, true); + } + }); + + coop_resource_test({ + parentCoop: 'same-origin', + resourceCoop: 'same-origin', + resource, + resourceName: 'foobar', + validate(data) { + assert_equals(data.name, 'foobar'); + assert_equals(data.closed, false); + } + }); +} +</script> +</html> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/resources/call-functionCalledByOpenee.html b/testing/web-platform/tests/html/cross-origin-opener-policy/resources/call-functionCalledByOpenee.html new file mode 100644 index 0000000000..d0ff0b723e --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/resources/call-functionCalledByOpenee.html @@ -0,0 +1,5 @@ +<!doctype html> +<meta charset=utf-8> +<script> +window.opener.functionCalledByOpenee(); +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/resources/common.js b/testing/web-platform/tests/html/cross-origin-opener-policy/resources/common.js new file mode 100644 index 0000000000..a005cb8a20 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/resources/common.js @@ -0,0 +1,86 @@ +// To use the functions below, be sure to include the following files in your +// test: +// - "/common/get-host-info.sub.js" to get the different origin values. + +const SAME_ORIGIN = {origin: get_host_info().HTTPS_ORIGIN, name: "SAME_ORIGIN"}; +const SAME_SITE = {origin: get_host_info().HTTPS_REMOTE_ORIGIN, name: "SAME_SITE"}; +const CROSS_ORIGIN = {origin: get_host_info().HTTPS_NOTSAMESITE_ORIGIN, name: "CROSS_ORIGIN"} + +function addScriptAndTriggerOnload(src, onload){ + return `script = document.createElement("script"); + script.src= "${src}" ; + script.onload = () => { + ${onload} + }; + document.head.append(script);` +} + +function verify_window(callback, w, hasOpener) { + // If there's no opener, the w must be closed: + assert_equals(w.closed, !hasOpener, 'w.closed'); + // Opener's access on w.length is possible only if hasOpener: + assert_equals(w.length, hasOpener? 1: 0, 'w.length'); + callback(); +} + +function validate_results(callback, test, w, channelName, hasOpener, openerDOMAccess, payload) { + assert_equals(payload.name, hasOpener ? channelName : "", 'name'); + assert_equals(payload.opener, hasOpener, 'opener'); + // TODO(zcorpan): add openerDOMAccess expectations to all tests + if (openerDOMAccess !== undefined) { + assert_equals(payload.openerDOMAccess, openerDOMAccess, 'openerDOMAccess'); + } + + // The window proxy in Chromium might still reflect the previous frame, + // until its unloaded. This delays the verification of w here. + if( !w.closed && w.length == 0) { + test.step_timeout( () => { + verify_window(callback, w, hasOpener); + }, 500); + } else { + verify_window(callback, w, hasOpener); + } +} + +// Note: This function is deprecated and should not be used by new tests. +// Instead, use `dispatcher_url_test()`. +function url_test(t, url, channelName, hasOpener, openerDOMAccess, callback) { + if (callback === undefined) { + callback = () => { t.done(); }; + } + const bc = new BroadcastChannel(channelName); + bc.onmessage = t.step_func(event => { + const payload = event.data; + validate_results(callback, t, w, channelName, hasOpener, openerDOMAccess, payload); + }); + + const w = window.open(url, channelName); + + // Close the popup once the test is complete. + // The browsing context might be closed hence use the broadcast channel + // to trigger the closure. + t.add_cleanup(() => { + bc.postMessage("close"); + }); +} + +// Similar to `url_test()` above except that this uses a dispatcher instead of +// BroadcastChannel (useful in cases where the context we are testing in is a +// third-party iframe that doesn't share a partition with the top-level +// site). +async function dispatcher_url_test(t, url, responseToken, iframeToken, hasOpener, openerDOMAccess, callback) { + + const w = window.open(url, responseToken); + + // Close the popup once the test is complete. + // The browsing context might be closed hence we'll have the iframe trigger + // the closure by sending it a 'close' message. + t.add_cleanup(async () => { + await send(iframeToken, "close"); + }); + + var payload = await receive(responseToken); + payload = JSON.parse(payload); + validate_results(callback, t, w, responseToken, hasOpener, openerDOMAccess, payload); +} + diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/resources/coop-coep.py b/testing/web-platform/tests/html/cross-origin-opener-policy/resources/coop-coep.py new file mode 100644 index 0000000000..d8e3bf0d42 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/resources/coop-coep.py @@ -0,0 +1,84 @@ +import json + +def main(request, response): + requestData = request.GET + if request.method == u"POST": + requestData = request.POST + + coop = requestData.first(b"coop") + coopReportOnly = requestData.first(b"coop-report-only", None) + coep = requestData.first(b"coep") + coepReportOnly = requestData.first(b"coep-report-only", None) + redirect = requestData.first(b"redirect", None) + if coop != b"": + response.headers.set(b"Cross-Origin-Opener-Policy", coop) + if coopReportOnly is not None: + response.headers.set(b"Cross-Origin-Opener-Policy-Report-Only", coopReportOnly) + if coep != b"": + response.headers.set(b"Cross-Origin-Embedder-Policy", coep) + if coepReportOnly is not None: + response.headers.set(b"Cross-Origin-Embedder-Policy-Report-Only", coepReportOnly) + if b'cache' in requestData: + response.headers.set(b'Cache-Control', b'max-age=3600') + host = request.url_parts[1] + + if redirect != None: + response.status = 302 + response.headers.set(b"Location", redirect) + return + + # Collect relevant params to be visible to response JS + params = {} + for key in (b"navHistory", b"avoidBackAndForth", b"navigate", b"channel", b"responseToken", b"iframeToken"): + value = requestData.first(key, None) + params[key.decode()] = value and value.decode() + + response.content = b""" +<!doctype html> +<meta charset=utf-8> +<script src="/common/get-host-info.sub.js"></script> +<script src="/html/cross-origin-opener-policy/resources/fully-loaded.js"></script> +<body> +<script> + const params = %s; + const navHistory = params.navHistory; + const avoidBackAndForth = params.avoidBackAndForth; + const navigate = params.navigate; + if (navHistory !== null) { + fullyLoaded().then(() => { + history.go(Number(navHistory)); + }); + } else if (navigate !== null && (history.length === 1 || !avoidBackAndForth)) { + fullyLoaded().then(() => { + self.location = navigate; + }); + } else { + let openerDOMAccessAllowed = false; + try { + openerDOMAccessAllowed = !!self.opener.document.URL; + } catch(ex) { + } + // Handle the response from the frame, closing the popup once the + // test completes. + addEventListener("message", event => { + if (event.data == "close") { + close(); + } + }); + iframe = document.createElement("iframe"); + iframe.onload = () => { + const payload = { name: self.name, opener: !!self.opener, openerDOMAccess: openerDOMAccessAllowed }; + iframe.contentWindow.postMessage(payload, "*"); + }; + const channelName = params.channel; + const responseToken = params.responseToken; + const iframeToken = params.iframeToken; + iframe.src = `${get_host_info().HTTPS_ORIGIN}/html/cross-origin-opener-policy/resources/postback.html` + + `?channel=${encodeURIComponent(channelName)}` + + `&responseToken=${responseToken}` + + `&iframeToken=${iframeToken}`; + document.body.appendChild(iframe); + } +</script> +</body> +""" % json.dumps(params).encode("utf-8") diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/resources/coop-same-origin-repeated.asis b/testing/web-platform/tests/html/cross-origin-opener-policy/resources/coop-same-origin-repeated.asis new file mode 100644 index 0000000000..082478e159 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/resources/coop-same-origin-repeated.asis @@ -0,0 +1,24 @@ +HTTP/1.1 200 OK +Cross-Origin-Opener-Policy: same-origin +Cross-Origin-Opener-Policy: same-origin +Server: BaseHTTP/0.3 Python/2.7.15+ +Date: Wed, 18 Dec 2019 00:47:08 GMT + +<!doctype html> +<meta charset=utf-8> +<script src="/common/get-host-info.sub.js"></script> +<iframe></iframe> +<script> + const navigate = new URL(location).searchParams.get("navigate"); + if (navigate !== null) { + self.location = navigate; + } else { + const iframe = document.querySelector("iframe"); + iframe.onload = () => { + const payload = { name: self.name, opener: !!self.opener }; + iframe.contentWindow.postMessage(payload, "*"); + }; + const channelName = new URL(location).searchParams.get("channel"); + iframe.src = `${get_host_info().HTTPS_ORIGIN}/html/cross-origin-opener-policy/resources/postback.html?channel=${channelName}`; + } +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/resources/csp-sandbox.py b/testing/web-platform/tests/html/cross-origin-opener-policy/resources/csp-sandbox.py new file mode 100644 index 0000000000..6cf21aeccf --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/resources/csp-sandbox.py @@ -0,0 +1,29 @@ +def main(request, response): + coop = request.GET.first(b"coop") + coep = request.GET.first(b"coep") + sandbox = request.GET.first(b"sandbox") + if coop != "": + response.headers.set(b"Cross-Origin-Opener-Policy", coop) + if coep != "": + response.headers.set(b"Cross-Origin-Embedder-Policy", coep) + response.headers.set(b"Content-Security-Policy", b"sandbox " + sandbox + b";") + + # Open a popup to coop-coep.py with the same parameters (except sandbox) + response.content = b""" +<!doctype html> +<meta charset=utf-8> +<script src="/common/get-host-info.sub.js"></script> +<script src="/html/cross-origin-opener-policy/resources/fully-loaded.js"></script> +<script> + const params = new URL(location).searchParams; + params.delete("sandbox"); + const navigate = params.get("navigate"); + if (navigate) { + fullyLoaded().then(() => { + self.location = navigate; + }); + } else { + window.open(`/html/cross-origin-opener-policy/resources/coop-coep.py?${params}`); + } +</script> +""" diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/resources/fully-loaded.js b/testing/web-platform/tests/html/cross-origin-opener-policy/resources/fully-loaded.js new file mode 100644 index 0000000000..d40e00af43 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/resources/fully-loaded.js @@ -0,0 +1,10 @@ +// Return a promise, which resolves when new navigations aren't considered +// client-side redirects anymore. +// +// Note: A long `setTimeout` is used, because client-side redirect is an +// heuristic and isn't clearly specified. +function fullyLoaded() { + return new Promise((resolve, reject) => { + addEventListener('load', () => setTimeout(resolve, 2000)) + }); +} diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/resources/iframe-test.js b/testing/web-platform/tests/html/cross-origin-opener-policy/resources/iframe-test.js new file mode 100644 index 0000000000..a18688caf7 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/resources/iframe-test.js @@ -0,0 +1,234 @@ +// To use the functions below, be sure to include the following files in your +// test: +// - "/common/get-host-info.sub.js" to get the different origin values. +// - "common.js" to have the origins easily available. +// - "/common/dispatcher/dispatcher.js" for cross-origin messaging. +// - "/common/utils.js" for token(). + +function getBaseExecutorPath(origin) { + return origin + '/common/dispatcher/executor.html'; +} + +function getHeadersPipe(headers) { + const coop_header = headers.coop ? + `|header(Cross-Origin-Opener-Policy,${encodeURIComponent(headers.coop)})` : ''; + const coep_header = headers.coep ? + `|header(Cross-Origin-Embedder-Policy,${encodeURIComponent(headers.coep)})` : ''; + return coop_header + coep_header; +} + +function getExecutorPath(uuid, origin, headers) { + return getBaseExecutorPath(origin) + + `?uuid=${uuid}` + + `&pipe=${getHeadersPipe(headers)}`; +} + +function evaluate(target_token, script) { + const reply_token = token(); + send(target_token, `send('${reply_token}', ${script});`); + return receive(reply_token); +} + +// Return true if an opened iframe can access |property| on a stored +// window.popup object without throwing an error. +function iframeCanAccessProperty(iframe_token, property) { + const reply_token = token(); + send(iframe_token, + `try { + const unused = window.popup['${property}']; + send('${reply_token}', 'true') + } catch (errors) { + send('${reply_token}', 'false') + }`); + return receive(reply_token); +} + +// Returns the script necessary to open a popup, given the method in +// `popup_via`. Supported methods are 'window_open' that leverages +// window.open(), 'anchor' that creates an <a> HTML element and clicks on it, +// and 'form' that creates a form and submits it. +function popupOpeningScript(popup_via, popup_url, popup_origin, headers, + popup_token) { + if (popup_via === 'window_open') + return `window.popup = window.open('${popup_url}', '${popup_token}');`; + + if (popup_via === 'anchor') { + return ` + const anchor = document.createElement('a'); + anchor.href = '${popup_url}'; + anchor.rel = "opener"; + anchor.target = '${popup_token}'; + anchor.innerText = "anchor"; + document.body.appendChild(anchor); + anchor.click(); + `; + } + + if (popup_via === "form") { + return ` + const form = document.createElement("form"); + form.action = '${getBaseExecutorPath(popup_origin.origin)}'; + form.target = '${popup_token}'; + form.method = 'GET'; + const add_param = (name, value) => { + const input = document.createElement("input"); + input.name = name; + input.value = value; + form.appendChild(input); + }; + add_param("uuid", "${popup_token}"); + add_param("pipe", "${getHeadersPipe(headers)}"); + document.body.appendChild(form); + form.submit(); + `; + } + + assert_not_reached('Unrecognized popup opening method.'); +} + + +// Verifies that a popup with origin `popup_origin` and headers `headers` has +// the expected `opener_state` after being opened from an iframe with origin +// `iframe_origin`. +function iframe_test(description, iframe_origin, popup_origin, headers, + expected_opener_state) { + for (const popup_via of ['window_open', 'anchor','form']) { + promise_test(async t => { + const iframe_token = token(); + const popup_token = token(); + const reply_token = token(); + + const frame = document.createElement("iframe"); + const iframe_url = getExecutorPath( + iframe_token, + iframe_origin.origin, + {}); + + frame.src = iframe_url; + document.body.append(frame); + + send(iframe_token, `send('${reply_token}', 'Iframe loaded');`); + assert_equals(await receive(reply_token), 'Iframe loaded'); + + const popup_url = getExecutorPath( + popup_token, + popup_origin.origin, + headers); + + // We open popup and then ping it, it will respond after loading. + send(iframe_token, popupOpeningScript(popup_via, popup_url, popup_origin, + headers, popup_token)); + send(popup_token, `send('${reply_token}', 'Popup loaded');`); + assert_equals(await receive(reply_token), 'Popup loaded'); + + // Make sure the popup and the iframe are removed once the test has run, + // keeping a clean state. + add_completion_callback(() => { + frame.remove(); + send(popup_token, `close()`); + }); + + // Give some time for things to settle across processes etc. before + // proceeding with verifications. + await new Promise(resolve => { t.step_timeout(resolve, 500); }); + + // Verify that the opener is in the state we expect it to be in. + switch (expected_opener_state) { + case 'preserved': { + assert_equals( + await evaluate(popup_token, 'opener != null'), "true", + 'Popup has an opener?'); + assert_equals( + await evaluate(popup_token, `name === '${popup_token}'`), "true", + 'Popup has a name?'); + + // When the popup was created using window.open, we've kept a handle + // and we can do extra verifications. + if (popup_via === 'window_open') { + assert_equals( + await evaluate(iframe_token, 'popup != null'), "true", + 'Popup handle is non-null in iframe?'); + assert_equals( + await evaluate(iframe_token, 'popup.closed'), "false", + 'Popup appears closed from iframe?'); + assert_equals( + await iframeCanAccessProperty(iframe_token, "document"), + popup_origin === iframe_origin ? "true" : "false", + 'Iframe has dom access to the popup?'); + assert_equals( + await iframeCanAccessProperty(iframe_token, "frames"), "true", + 'Iframe has cross origin access to the popup?'); + } + break; + } + case 'restricted': { + assert_equals( + await evaluate(popup_token, 'opener != null'), "true", + 'Popup has an opener?'); + assert_equals( + await evaluate(popup_token, `name === '${popup_token}'`), "true", + 'Popup has a name?'); + + // When the popup was created using window.open, we've kept a handle + // and we can do extra verifications. + if (popup_via === 'window_open') { + assert_equals( + await evaluate(iframe_token, 'popup != null'), "true", + 'Popup handle is non-null in iframe?'); + assert_equals( + await evaluate(iframe_token, 'popup.closed'), "false", + 'Popup appears closed from iframe?'); + assert_equals( + await iframeCanAccessProperty(iframe_token, "document"), "false", + 'Iframe has dom access to the popup?'); + assert_equals( + await iframeCanAccessProperty(iframe_token, "frames"), "false", + 'Iframe has cross origin access to the popup?'); + assert_equals( + await iframeCanAccessProperty(iframe_token, "closed"), "true", + 'Iframe has limited cross origin access to the popup?'); + } + break; + } + case 'severed': { + assert_equals(await evaluate(popup_token, 'opener != null'), "false", + 'Popup has an opener?'); + assert_equals( + await evaluate(popup_token, `name === '${popup_token}'`), "false", + 'Popup has a name?'); + + // When the popup was created using window.open, we've kept a handle + // and we can do extra verifications. + if (popup_via === 'window_open') { + assert_equals( + await evaluate(iframe_token, 'popup != null'), "true", + 'Popup handle is non-null in iframe?'); + assert_equals( + await evaluate(iframe_token, 'popup.closed'), "true", + 'Popup appears closed from iframe?'); + } + break; + } + case 'noopener': { + assert_equals(await evaluate(popup_token, 'opener != null'), "false", + 'Popup has an opener?'); + assert_equals( + await evaluate(popup_token, `name === '${popup_token}'`), "false", + 'Popup has a name?'); + + // When the popup was created using window.open, we've kept a handle + // and we can do extra verifications. + if (popup_via === 'window_open') { + assert_equals( + await evaluate(iframe_token, 'popup == null'), "true", + 'Popup handle is null in iframe?'); + } + break; + } + default: + assert_not_reached('Unrecognized opener state: ' + + expected_opener_state); + } + }, `${description} with ${popup_via}`); + } +} diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/resources/popup-test.js b/testing/web-platform/tests/html/cross-origin-opener-policy/resources/popup-test.js new file mode 100644 index 0000000000..c2717bb135 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/resources/popup-test.js @@ -0,0 +1,99 @@ +// To use the functions below, be sure to include the following files in your +// test: +// - "/common/get-host-info.sub.js" to get the different origin values. +// - "common.js" to have the origins easily available. +// - "/common/dispatcher/dispatcher.js" for cross-origin messaging. +// - "/common/utils.js" for token(). + +function getExecutorPath(uuid, origin, headers) { + const executor_path = '/common/dispatcher/executor.html?'; + const coop_header = headers.coop ? + `|header(Cross-Origin-Opener-Policy,${encodeURIComponent(headers.coop)})` : ''; + const coep_header = headers.coep ? + `|header(Cross-Origin-Embedder-Policy,${encodeURIComponent(headers.coep)})` : ''; + return origin + + executor_path + + `uuid=${uuid}` + + '&pipe=' + coop_header + coep_header; +} + +function getPopupHasOpener(popup_token) { + const reply_token = token(); + send(popup_token, `send('${reply_token}', window.opener != null);`); + return receive(reply_token); +} + +// Return true if |object|.|property| can be called without throwing an error. +function canAccessProperty(object, property) { + try { + const unused = object[property]; + return true; + } catch (errors) { + return false; + } +} + +// Verifies that a popup with origin `origin` and headers `headers` has +// the expected `opener_state` after being opened. +async function popup_test(description, origin, headers, expected_opener_state) { + promise_test(async t => { + const popup_token = token(); + const reply_token = token(); + + const popup_url = getExecutorPath( + popup_token, + origin.origin, + headers); + + // We open popup and then ping it, it will respond after loading. + const popup = window.open(popup_url); + send(popup_token, `send('${reply_token}', 'Popup loaded');`); + assert_equals(await receive(reply_token), 'Popup loaded'); + + // Make sure the popup will be closed once the test has run, keeping a clean + // state. + t.add_cleanup(() => { + send(popup_token, `close()`); + }); + + // Give some time for things to settle across processes etc. before + // proceeding with verifications. + await new Promise(resolve => { t.step_timeout(resolve, 500); }); + + // Verify that the opener is in the state we expect it to be in. + switch (expected_opener_state) { + case 'preserved': { + assert_false(popup.closed, 'Popup is closed from opener?'); + assert_true(await getPopupHasOpener(popup_token) === "true", + 'Popup has nulled opener?'); + assert_equals(canAccessProperty(popup, "document"), + origin === SAME_ORIGIN, + 'Main page has dom access to the popup?'); + assert_true(canAccessProperty(popup, "frames"), + 'Main page has cross origin access to the popup?'); + break; + } + case 'restricted': { + assert_false(popup.closed, 'Popup is closed from opener?'); + assert_true(await getPopupHasOpener(popup_token) === "true", + 'Popup has nulled opener?'); + assert_false(canAccessProperty(popup, "document"), + 'Main page has dom access to the popup?'); + assert_false(canAccessProperty(popup, "frames"), + 'Main page has cross origin access to the popup?'); + assert_true(canAccessProperty(popup, "closed"), + 'Main page has limited cross origin access to the popup?'); + break; + } + case 'severed': { + assert_true(popup.closed, 'Popup is closed from opener?'); + assert_false(await getPopupHasOpener(popup_token) === "true", + 'Popup has nulled opener?'); + break; + } + default: + assert_unreached(true, "Unrecognized opener relationship: " + expected_opener_state); + } + }, description); +} + diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/resources/postback.html b/testing/web-platform/tests/html/cross-origin-opener-policy/resources/postback.html new file mode 100644 index 0000000000..35b3be5c93 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/resources/postback.html @@ -0,0 +1,45 @@ +<!doctype html> +<meta charset=utf-8> +<script src="/common/dispatcher/dispatcher.js"></script> +<script> +const params = new URL(location).searchParams; +const channelName = params.get("channel"); +const responseToken = params.get("responseToken"); +const iframeToken = params.get("iframeToken"); + +// If the channel parameter is set, use the BroadcastChannel-based communication +// method. Otherwise, use the dispatcher (useful in cases where this is embedded +// in a third-party iframe that doesn't share a partition with the top-level +// site). +if (channelName != "null") { + const bc = new BroadcastChannel(channelName); + // Handle the close message from the test-cleanup, forwarding it to the + // top level document, as this iframe and the opening document might not + // be able to close the popup. + bc.onmessage = event => { + if (event.data == "close") { + top.postMessage("close", "*"); + } + }; + + window.addEventListener("message", event => { + bc.postMessage(event.data); + }); + +} else { + window.addEventListener("message", event => { + send(responseToken, JSON.stringify(event.data)); + }); + + async function waitToClose() { + response = await receive(iframeToken); + // Handle the close message from the test-cleanup, forwarding it to the + // top level document, as this iframe and the opening document might not + // be able to close the popup. + if (response == "close") { + top.postMessage("close", "*"); + } + } + waitToClose(); +} +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/resources/postback.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/resources/postback.html.headers new file mode 100644 index 0000000000..4e798cd9f5 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/resources/postback.html.headers @@ -0,0 +1,2 @@ +Cross-Origin-Embedder-Policy: require-corp +Cross-Origin-Resource-Policy: cross-origin diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/resources/redirect.py b/testing/web-platform/tests/html/cross-origin-opener-policy/resources/redirect.py new file mode 100644 index 0000000000..88dbd60fae --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/resources/redirect.py @@ -0,0 +1,5 @@ +from wptserve.utils import isomorphic_encode + +def main(request, response): + response.status = 302 + response.headers.set(b"Location", isomorphic_encode(request.url[request.url.find(u'?')+1:])) diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/resources/resource-cleanup.html b/testing/web-platform/tests/html/cross-origin-opener-policy/resources/resource-cleanup.html new file mode 100644 index 0000000000..3ae5587c7d --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/resources/resource-cleanup.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html lang="en"> +<meta charset="utf-8"> +<title>Redirect destination for non-HTML documents to close themselves</title> +<script> +'use strict'; +const channel = new URL(location).searchParams.get('channel'); +const bc = new BroadcastChannel(channel); +bc.onmessage = () => close(); +bc.postMessage({name: 'FAIL', closed: 'FAIL' }); +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/resources/resource-popup.html b/testing/web-platform/tests/html/cross-origin-opener-policy/resources/resource-popup.html new file mode 100644 index 0000000000..2957e35f59 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/resources/resource-popup.html @@ -0,0 +1,21 @@ +<!DOCTYPE html> +<html lang="en"> +<meta charset="utf-8"> +<title></title> +<script> +'use strict'; +const params = new URL(location).searchParams; +const bc = new BroadcastChannel(params.get('channel_name')); +const win = open(params.get('resource'), params.get('resource_name')); + +bc.onmessage = () => { + win.close(); + close(); +}; +const id = setInterval(() => { + if (win.closed || win.location.href !== 'about:blank') { + clearInterval(id); + bc.postMessage({name: win.name || null, closed: win.closed}); + } +}, 100); +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/resources/universal-worker.js b/testing/web-platform/tests/html/cross-origin-opener-policy/resources/universal-worker.js new file mode 100644 index 0000000000..2441679372 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/resources/universal-worker.js @@ -0,0 +1,2 @@ +onmessage = message => eval(message.data); +onfetch = event => fetchHandler(event); diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/README.md b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/README.md new file mode 100644 index 0000000000..b3c24c3f82 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/README.md @@ -0,0 +1,9 @@ +Because this test suite is run as a virtual suite and it's quite deep in the +folders, we have to use abbreviations for the test names to not run over 200 +characters, which is problematic on Windows. + +* unspecified -> "u" +* unsafe-none -> "un" +* same-origin -> "so" +* same-origin-allow-popups -> "soap" +* restrict-properties -> omitted diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/coop-rp-in-navigation-chain.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/coop-rp-in-navigation-chain.https.html new file mode 100644 index 0000000000..e5c8775174 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/coop-rp-in-navigation-chain.https.html @@ -0,0 +1,65 @@ +<!doctype html> +<meta charset=utf-8> +<meta name=timeout content=long> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/utils.js"></script> +<script src="../../resources/common.js"></script> +<script src="../../resources/popup-test.js"></script> +<script> + +promise_test(async t => { + const popup_token = token(); + const second_popup_token = token(); + const reply_token = token(); + + const unsafe_none_url = getExecutorPath( + popup_token, + SAME_ORIGIN.origin, + { coop: "unsafe-none"}); + + const restrict_properties_url = getExecutorPath( + second_popup_token, + SAME_ORIGIN.origin, + { coop: "restrict-properties"}); + + // We open popup and then ping it, it will respond after loading. + const popup = window.open(unsafe_none_url); + send(popup_token, `send('${reply_token}', 'Popup loaded');`); + assert_equals(await receive(reply_token), 'Popup loaded'); + + // Make sure the popup will be closed once the test has run, keeping a clean + // state. + t.add_cleanup(() => { + send(popup_token, `close()`); + }); + + // Now navigate this popup to a restrict-properties page. + send(popup_token, `document.location = '${restrict_properties_url}'`); + send(second_popup_token, `send('${reply_token}', 'Popup loaded');`); + assert_equals(await receive(reply_token), 'Popup loaded'); + + // Navigate again to the original page. + send(second_popup_token, `document.location = '${unsafe_none_url}'`); + send(popup_token, `send('${reply_token}', 'Popup loaded');`); + assert_equals(await receive(reply_token), 'Popup loaded'); + + // Give some time for things to settle across processes etc. before + // proceeding with verifications. + await new Promise(resolve => { t.step_timeout(resolve, 500); }); + + // Verify that we have full access to the popup. + assert_false(popup.closed, 'Popup is closed from opener?'); + assert_true(await getPopupHasOpener(popup_token) === "true", + 'Popup has nulled opener?'); + assert_true(canAccessProperty(popup, "document"), + 'Main page has dom access to the popup?'); + assert_true(canAccessProperty(popup, "frames"), + 'Main page has cross origin access to the popup?'); + +}, "COOP: restrict-properties has no impact in a navigation chain between " + + "multiple unsafe-none pages."); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/coop-rp-in-navigation-chain.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/coop-rp-in-navigation-chain.https.html.headers new file mode 100644 index 0000000000..073ce7adfb --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/coop-rp-in-navigation-chain.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: unsafe-none diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup-to-so.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup-to-so.https.html new file mode 100644 index 0000000000..740ff2595a --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup-to-so.https.html @@ -0,0 +1,90 @@ +<!doctype html> +<meta charset=utf-8> +<meta name=timeout content=long> +<meta name="variant" content="?1-2"> +<meta name="variant" content="?3-4"> +<meta name="variant" content="?5-6"> +<meta name="variant" content="?7-8"> +<meta name="variant" content="?9-last"> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src=/common/dispatcher/dispatcher.js></script> +<script src=/common/get-host-info.sub.js></script> +<script src=/common/subset-tests.js></script> +<script src=/common/utils.js></script> +<script src="../../resources/common.js"></script> +<script src="../../resources/iframe-test.js"></script> + +<body> +<script> + +// This document has COOP: restrict-properties. The popup has COOP: same-origin. +// Opening from an iframe should not be different from opening from the main +// frame and the opener should be severed. +[ + { + "title": "same origin iframe, same origin popup", + "iframeOrigin": SAME_ORIGIN, + "popupOrigin": SAME_ORIGIN, + "opener": "severed" + }, + { + "title": "same site iframe, same origin popup", + "iframeOrigin": SAME_SITE, + "popupOrigin": SAME_ORIGIN, + "opener": "severed" + }, + { + "title": "cross origin iframe, same origin popup", + "iframeOrigin": CROSS_ORIGIN, + "popupOrigin": SAME_ORIGIN, + "opener": "severed" + }, + { + "title": "same origin iframe, same site popup", + "iframeOrigin": SAME_ORIGIN, + "popupOrigin": SAME_SITE, + "opener": "severed" + }, + { + "title": "same site iframe, same site popup", + "iframeOrigin": SAME_SITE, + "popupOrigin": SAME_SITE, + "opener": "severed" + }, + { + "title": "cross origin iframe, same site popup", + "iframeOrigin": CROSS_ORIGIN, + "popupOrigin": SAME_SITE, + "opener": "severed" + }, + { + "title": "same origin iframe, cross origin popup", + "iframeOrigin": SAME_ORIGIN, + "popupOrigin": CROSS_ORIGIN, + "opener": "severed" + }, + { + "title": "same site iframe, cross origin popup", + "iframeOrigin": SAME_SITE, + "popupOrigin": CROSS_ORIGIN, + "opener": "severed" + }, + { + "title": "cross origin iframe, cross origin popup", + "iframeOrigin": CROSS_ORIGIN, + "popupOrigin": CROSS_ORIGIN, + "opener": "severed" + } +].forEach(variant => { + subsetTest( + iframe_test, + `COOP: restrict-properties to popup COOP: same-origin via an iframe, ` + + `with ${variant.title}`, + variant.iframeOrigin, + variant.popupOrigin, + { coop: 'same-origin' }, + variant.opener); +}); +</script> +</body> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup-to-so.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup-to-so.https.html.headers new file mode 100644 index 0000000000..d5c99062d2 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup-to-so.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: restrict-properties diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup-to-soap.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup-to-soap.https.html new file mode 100644 index 0000000000..f3af3ca7db --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup-to-soap.https.html @@ -0,0 +1,91 @@ +<!doctype html> +<meta charset=utf-8> +<meta name=timeout content=long> +<meta name="variant" content="?1-2"> +<meta name="variant" content="?3-4"> +<meta name="variant" content="?5-6"> +<meta name="variant" content="?7-8"> +<meta name="variant" content="?9-last"> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src=/common/dispatcher/dispatcher.js></script> +<script src=/common/get-host-info.sub.js></script> +<script src=/common/subset-tests.js></script> +<script src=/common/utils.js></script> +<script src="../../resources/common.js"></script> +<script src="../../resources/iframe-test.js"></script> + +<body> +<script> + + +// This document has COOP: restrict-properties. The popup has COOP: +// same-origin-allow-popups. Opening from an iframe should not be different from +// opening from the main frame and the opener should be severed. +[ + { + "title": "same origin iframe, same origin popup", + "iframeOrigin": SAME_ORIGIN, + "popupOrigin": SAME_ORIGIN, + "opener": "severed" + }, + { + "title": "same site iframe, same origin popup", + "iframeOrigin": SAME_SITE, + "popupOrigin": SAME_ORIGIN, + "opener": "severed" + }, + { + "title": "cross origin iframe, same origin popup", + "iframeOrigin": CROSS_ORIGIN, + "popupOrigin": SAME_ORIGIN, + "opener": "severed" + }, + { + "title": "same origin iframe, same site popup", + "iframeOrigin": SAME_ORIGIN, + "popupOrigin": SAME_SITE, + "opener": "severed" + }, + { + "title": "same site iframe, same site popup", + "iframeOrigin": SAME_SITE, + "popupOrigin": SAME_SITE, + "opener": "severed" + }, + { + "title": "cross origin iframe, same site popup", + "iframeOrigin": CROSS_ORIGIN, + "popupOrigin": SAME_SITE, + "opener": "severed" + }, + { + "title": "same origin iframe, cross origin popup", + "iframeOrigin": SAME_ORIGIN, + "popupOrigin": CROSS_ORIGIN, + "opener": "severed" + }, + { + "title": "same site iframe, cross origin popup", + "iframeOrigin": SAME_SITE, + "popupOrigin": CROSS_ORIGIN, + "opener": "severed" + }, + { + "title": "cross origin iframe, cross origin popup", + "iframeOrigin": CROSS_ORIGIN, + "popupOrigin": CROSS_ORIGIN, + "opener": "severed" + } +].forEach(variant => { + subsetTest( + iframe_test, + `COOP: restrict-properties to popup COOP: same-origin-allow-popups ` + + `via an iframe, with ${variant.title}`, + variant.iframeOrigin, + variant.popupOrigin, + { coop: 'same-origin-allow-popups' }, + variant.opener); +}); +</script> +</body> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup-to-soap.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup-to-soap.https.html.headers new file mode 100644 index 0000000000..d5c99062d2 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup-to-soap.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: restrict-properties diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup-to-un.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup-to-un.https.html new file mode 100644 index 0000000000..560dfd9051 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup-to-un.https.html @@ -0,0 +1,90 @@ +<!doctype html> +<meta charset=utf-8> +<meta name=timeout content=long> +<meta name="variant" content="?1-2"> +<meta name="variant" content="?3-4"> +<meta name="variant" content="?5-6"> +<meta name="variant" content="?7-8"> +<meta name="variant" content="?9-last"> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src=/common/dispatcher/dispatcher.js></script> +<script src=/common/get-host-info.sub.js></script> +<script src=/common/subset-tests.js></script> +<script src=/common/utils.js></script> +<script src="../../resources/common.js"></script> +<script src="../../resources/iframe-test.js"></script> + +<body> +<script> + +// This document has COOP: restrict-properties. The popup has COOP: unsafe-none. +// Opening from an iframe should not be different from opening from the main +// frame and the opener should be severed. +[ + { + "title": "same origin iframe, same origin popup", + "iframeOrigin": SAME_ORIGIN, + "popupOrigin": SAME_ORIGIN, + "opener": "restricted" + }, + { + "title": "same site iframe, same origin popup", + "iframeOrigin": SAME_SITE, + "popupOrigin": SAME_ORIGIN, + "opener": "restricted" + }, + { + "title": "cross origin iframe, same origin popup", + "iframeOrigin": CROSS_ORIGIN, + "popupOrigin": SAME_ORIGIN, + "opener": "restricted" + }, + { + "title": "same origin iframe, same site popup", + "iframeOrigin": SAME_ORIGIN, + "popupOrigin": SAME_SITE, + "opener": "restricted" + }, + { + "title": "same site iframe, same site popup", + "iframeOrigin": SAME_SITE, + "popupOrigin": SAME_SITE, + "opener": "restricted" + }, + { + "title": "cross origin iframe, same site popup", + "iframeOrigin": CROSS_ORIGIN, + "popupOrigin": SAME_SITE, + "opener": "restricted" + }, + { + "title": "same origin iframe, cross origin popup", + "iframeOrigin": SAME_ORIGIN, + "popupOrigin": CROSS_ORIGIN, + "opener": "restricted" + }, + { + "title": "same site iframe, cross origin popup", + "iframeOrigin": SAME_SITE, + "popupOrigin": CROSS_ORIGIN, + "opener": "restricted" + }, + { + "title": "cross origin iframe, cross origin popup", + "iframeOrigin": CROSS_ORIGIN, + "popupOrigin": CROSS_ORIGIN, + "opener": "restricted" + } +].forEach(variant => { + subsetTest( + iframe_test, + `COOP: restrict-properties to popup COOP: unsafe-none via an iframe, ` + + `with ${variant.title}`, + variant.iframeOrigin, + variant.popupOrigin, + { coop: 'unsafe-none' }, + variant.opener); +}); +</script> +</body> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup-to-un.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup-to-un.https.html.headers new file mode 100644 index 0000000000..d5c99062d2 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup-to-un.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: restrict-properties diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup.https.html new file mode 100644 index 0000000000..2c6f0b6282 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup.https.html @@ -0,0 +1,90 @@ +<!doctype html> +<meta charset=utf-8> +<meta name=timeout content=long> +<meta name="variant" content="?1-2"> +<meta name="variant" content="?3-4"> +<meta name="variant" content="?5-6"> +<meta name="variant" content="?7-8"> +<meta name="variant" content="?9-last"> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src=/common/dispatcher/dispatcher.js></script> +<script src=/common/get-host-info.sub.js></script> +<script src=/common/subset-tests.js></script> +<script src=/common/utils.js></script> +<script src="../../resources/common.js"></script> +<script src="../../resources/iframe-test.js"></script> + +<body> +<script> + +// This document has COOP: restrict-properties. The popup has COOP: +// restrict-properties. Opening from an iframe should not be different from +// opening from the main frame and the opener should be severed. +[ + { + "title": "same origin iframe, same origin popup", + "iframeOrigin": SAME_ORIGIN, + "popupOrigin": SAME_ORIGIN, + "opener": "restricted" + }, + { + "title": "same site iframe, same origin popup", + "iframeOrigin": SAME_SITE, + "popupOrigin": SAME_ORIGIN, + "opener": "restricted" + }, + { + "title": "cross origin iframe, same origin popup", + "iframeOrigin": CROSS_ORIGIN, + "popupOrigin": SAME_ORIGIN, + "opener": "restricted" + }, + { + "title": "same origin iframe, same site popup", + "iframeOrigin": SAME_ORIGIN, + "popupOrigin": SAME_SITE, + "opener": "restricted" + }, + { + "title": "same site iframe, same site popup", + "iframeOrigin": SAME_SITE, + "popupOrigin": SAME_SITE, + "opener": "restricted" + }, + { + "title": "cross origin iframe, same site popup", + "iframeOrigin": CROSS_ORIGIN, + "popupOrigin": SAME_SITE, + "opener": "restricted" + }, + { + "title": "same origin iframe, cross origin popup", + "iframeOrigin": SAME_ORIGIN, + "popupOrigin": CROSS_ORIGIN, + "opener": "restricted" + }, + { + "title": "same site iframe, cross origin popup", + "iframeOrigin": SAME_SITE, + "popupOrigin": CROSS_ORIGIN, + "opener": "restricted" + }, + { + "title": "cross origin iframe, cross origin popup", + "iframeOrigin": CROSS_ORIGIN, + "popupOrigin": CROSS_ORIGIN, + "opener": "restricted" + } +].forEach(variant => { + subsetTest( + iframe_test, + `COOP: restrict-properties to popup COOP: restrict-properties via an ` + + `iframe, with ${variant.title}`, + variant.iframeOrigin, + variant.popupOrigin, + { coop: 'restrict-properties' }, + variant.opener); +}); +</script> +</body> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup.https.html.headers new file mode 100644 index 0000000000..d5c99062d2 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: restrict-properties diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/named_targeting.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/named_targeting.https.html new file mode 100644 index 0000000000..00eb6506e9 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/named_targeting.https.html @@ -0,0 +1,40 @@ +<!doctype html> +<meta charset=utf-8> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/utils.js"></script> +<script src="../../resources/common.js"></script> + +<script> + +async function createCoopRestrictPropertiesPopup(name) { + const popupToken = token(); + const url = SAME_ORIGIN.origin + '/common/dispatcher/executor.html' + + `?uuid=${popupToken}` + + '&pipe=|header(Cross-Origin-Opener-Policy, restrict-properties)'; + const popup = window.open(url, name); + add_completion_callback(() => popup.close()); + + // Wait for the popup to be loaded. + const replyToken = token(); + send(popupToken, `send('${replyToken}', 'Done loading')`); + assert_equals(await receive(replyToken), 'Done loading'); + + return popup; +} + +promise_test(async t => { + // Open two COOP: restrict-properties popups with the same name. + const name = token(); + const popup1 = await createCoopRestrictPropertiesPopup(name); + const popup2 = await createCoopRestrictPropertiesPopup(name); + + // Check that named targeting did not cross isolation boundaries. Two popups + // should have been created. + assert_not_equals(popup1, popup2, + 'Named targeting resolved across isolation boundaries'); +}, 'Verify that named targeting does not work across isolation boundaries.'); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/named_targeting.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/named_targeting.https.html.headers new file mode 100644 index 0000000000..d5c99062d2 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/named_targeting.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: restrict-properties diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/popup-so.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/popup-so.https.html new file mode 100644 index 0000000000..e5313a6e22 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/popup-so.https.html @@ -0,0 +1,37 @@ +<!doctype html> +<meta charset=utf-8> +<meta name=timeout content=long> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/utils.js"></script> +<script src="../../resources/common.js"></script> +<script src="../../resources/popup-test.js"></script> +<script> + +[ + { + "title": "popup with coop restrict-properties", + "coop": "restrict-properties", + "opener": "severed", + "origin": SAME_ORIGIN + }, + { + "title": "popup with coop restrict-properties", + "coop": "restrict-properties", + "opener": "severed", + "origin": SAME_SITE + }, + { + "title": "popup with coop restrict-properties", + "coop": "restrict-properties", + "opener": "severed", + "origin": CROSS_ORIGIN + } +].forEach(variant => { + popup_test(`${variant.origin.name} ${variant.title}`, variant.origin, + { coop: variant.coop }, variant.opener); +}); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/popup-so.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/popup-so.https.html.headers new file mode 100644 index 0000000000..46ad58d83b --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/popup-so.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: same-origin diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/popup-soap.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/popup-soap.https.html new file mode 100644 index 0000000000..595a10a84b --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/popup-soap.https.html @@ -0,0 +1,37 @@ +<!doctype html> +<meta charset=utf-8> +<meta name=timeout content=long> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/utils.js"></script> +<script src="../../resources/common.js"></script> +<script src="../../resources/popup-test.js"></script> +<script> + +[ + { + "title": "popup with coop restrict-properties", + "coop": "restrict-properties", + "opener": "restricted", + "origin": SAME_ORIGIN + }, + { + "title": "popup with coop restrict-properties", + "coop": "restrict-properties", + "opener": "restricted", + "origin": SAME_SITE + }, + { + "title": "popup with coop restrict-properties", + "coop": "restrict-properties", + "opener": "restricted", + "origin": CROSS_ORIGIN + } +].forEach(variant => { + popup_test(`${variant.origin.name} ${variant.title}`, variant.origin, + { coop: variant.coop }, variant.opener); +}); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/popup-soap.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/popup-soap.https.html.headers new file mode 100644 index 0000000000..d83ed86fb9 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/popup-soap.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: same-origin-allow-popups diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/popup-u.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/popup-u.https.html new file mode 100644 index 0000000000..595a10a84b --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/popup-u.https.html @@ -0,0 +1,37 @@ +<!doctype html> +<meta charset=utf-8> +<meta name=timeout content=long> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/utils.js"></script> +<script src="../../resources/common.js"></script> +<script src="../../resources/popup-test.js"></script> +<script> + +[ + { + "title": "popup with coop restrict-properties", + "coop": "restrict-properties", + "opener": "restricted", + "origin": SAME_ORIGIN + }, + { + "title": "popup with coop restrict-properties", + "coop": "restrict-properties", + "opener": "restricted", + "origin": SAME_SITE + }, + { + "title": "popup with coop restrict-properties", + "coop": "restrict-properties", + "opener": "restricted", + "origin": CROSS_ORIGIN + } +].forEach(variant => { + popup_test(`${variant.origin.name} ${variant.title}`, variant.origin, + { coop: variant.coop }, variant.opener); +}); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/popup-un.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/popup-un.https.html new file mode 100644 index 0000000000..595a10a84b --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/popup-un.https.html @@ -0,0 +1,37 @@ +<!doctype html> +<meta charset=utf-8> +<meta name=timeout content=long> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/utils.js"></script> +<script src="../../resources/common.js"></script> +<script src="../../resources/popup-test.js"></script> +<script> + +[ + { + "title": "popup with coop restrict-properties", + "coop": "restrict-properties", + "opener": "restricted", + "origin": SAME_ORIGIN + }, + { + "title": "popup with coop restrict-properties", + "coop": "restrict-properties", + "opener": "restricted", + "origin": SAME_SITE + }, + { + "title": "popup with coop restrict-properties", + "coop": "restrict-properties", + "opener": "restricted", + "origin": CROSS_ORIGIN + } +].forEach(variant => { + popup_test(`${variant.origin.name} ${variant.title}`, variant.origin, + { coop: variant.coop }, variant.opener); +}); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/popup-un.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/popup-un.https.html.headers new file mode 100644 index 0000000000..073ce7adfb --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/popup-un.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: unsafe-none diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/popup-with-cross-origin.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/popup-with-cross-origin.https.html new file mode 100644 index 0000000000..a84d52584e --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/popup-with-cross-origin.https.html @@ -0,0 +1,44 @@ +<!doctype html> +<meta charset=utf-8> +<meta name=timeout content=long> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/utils.js"></script> +<script src="../../resources/common.js"></script> +<script src="../../resources/popup-test.js"></script> +<script> + +[ + { + "title": "popup with empty coop", + "coop": "", + "opener": "restricted" + }, + { + "title": "popup with coop unsafe-none", + "coop": "unsafe-none", + "opener": "restricted" + }, + { + "title": "popup with coop same-origin", + "coop": "same-origin", + "opener": "severed" + }, + { + "title": "popup with coop same-origin-allow-popups", + "coop": "same-origin-allow-popups", + "opener": "severed" + }, + { + "title": "popup with coop restrict-properties", + "coop": "restrict-properties", + "opener": "restricted" + } +].forEach(variant => { + popup_test(`Cross-origin ${variant.title}`, CROSS_ORIGIN, + { coop: variant.coop }, variant.opener); +}); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/popup-with-cross-origin.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/popup-with-cross-origin.https.html.headers new file mode 100644 index 0000000000..d5c99062d2 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/popup-with-cross-origin.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: restrict-properties diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/popup-with-same-origin.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/popup-with-same-origin.https.html new file mode 100644 index 0000000000..491cbc3b9d --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/popup-with-same-origin.https.html @@ -0,0 +1,44 @@ +<!doctype html> +<meta charset=utf-8> +<meta name=timeout content=long> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/utils.js"></script> +<script src="../../resources/common.js"></script> +<script src="../../resources/popup-test.js"></script> +<script> + +[ + { + "title": "popup with empty coop", + "coop": "", + "opener": "restricted" + }, + { + "title": "popup with coop unsafe-none", + "coop": "unsafe-none", + "opener": "restricted" + }, + { + "title": "popup with coop same-origin", + "coop": "same-origin", + "opener": "severed" + }, + { + "title": "popup with coop same-origin-allow-popups", + "coop": "same-origin-allow-popups", + "opener": "severed" + }, + { + "title": "popup with coop restrict-properties", + "coop": "restrict-properties", + "opener": "restricted" + } +].forEach(variant => { + popup_test(`Same-origin ${variant.title}`, SAME_ORIGIN, + { coop: variant.coop }, variant.opener); +}); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/popup-with-same-origin.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/popup-with-same-origin.https.html.headers new file mode 100644 index 0000000000..d5c99062d2 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/popup-with-same-origin.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: restrict-properties diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/popup-with-same-site.https.html b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/popup-with-same-site.https.html new file mode 100644 index 0000000000..7d115ac7e6 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/popup-with-same-site.https.html @@ -0,0 +1,44 @@ +<!doctype html> +<meta charset=utf-8> +<meta name=timeout content=long> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/utils.js"></script> +<script src="../../resources/common.js"></script> +<script src="../../resources/popup-test.js"></script> +<script> + +[ + { + "title": "popup with empty coop", + "coop": "", + "opener": "restricted" + }, + { + "title": "popup with coop unsafe-none", + "coop": "unsafe-none", + "opener": "restricted" + }, + { + "title": "popup with coop same-origin", + "coop": "same-origin", + "opener": "severed" + }, + { + "title": "popup with coop same-origin-allow-popups", + "coop": "same-origin-allow-popups", + "opener": "severed" + }, + { + "title": "popup with coop restrict-properties", + "coop": "restrict-properties", + "opener": "restricted" + } +].forEach(variant => { + popup_test(`Same-site ${variant.title}`, SAME_SITE, + { coop: variant.coop }, variant.opener); +}); + +</script> diff --git a/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/popup-with-same-site.https.html.headers b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/popup-with-same-site.https.html.headers new file mode 100644 index 0000000000..d5c99062d2 --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-opener-policy/tentative/restrict-properties/popup-with-same-site.https.html.headers @@ -0,0 +1 @@ +Cross-Origin-Opener-Policy: restrict-properties |