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/referrer-policy/generic | |
parent | Initial commit. (diff) | |
download | firefox-upstream.tar.xz firefox-upstream.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/referrer-policy/generic')
51 files changed, 1834 insertions, 0 deletions
diff --git a/testing/web-platform/tests/referrer-policy/generic/first-meta-changed-after-second-added.http.html b/testing/web-platform/tests/referrer-policy/generic/first-meta-changed-after-second-added.http.html new file mode 100644 index 0000000000..2ee5ade8c0 --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/first-meta-changed-after-second-added.http.html @@ -0,0 +1,36 @@ +<!DOCTYPE html> +<head> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + + <meta name="referrer" content="no-referrer" id="referrermeta"> +</head> +<body> + <script> + async function fetchAndGetReferrer() { + let response = await fetch('/common/security-features/subresource/xhr.py'); + let data = await response.json(); + return data.headers.referer; + } + + promise_test(async t => { + assert_equals(await fetchAndGetReferrer(), undefined, + 'referrer should not be set'); + + // Add second meta _before_ first meta. + const first_meta = document.getElementById('referrermeta'); + const second_meta = document.createElement('meta'); + second_meta.name = 'referrer'; + second_meta.content = 'strict-origin'; + document.head.appendChild(second_meta); + assert_equals(await fetchAndGetReferrer(), window.location.origin + '/', + 'referrer should be origin only'); + + // Update content attribute of first meta. + first_meta.content = 'unsafe-url'; + assert_equals(await fetchAndGetReferrer(), window.location.href, + 'referrer should be full url'); + }, 'document referrer policy is the value of the most recently modified <meta name="referrer"'); + + </script> +</body> diff --git a/testing/web-platform/tests/referrer-policy/generic/iframe-src-change.html b/testing/web-platform/tests/referrer-policy/generic/iframe-src-change.html new file mode 100644 index 0000000000..15202a76a1 --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/iframe-src-change.html @@ -0,0 +1,37 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<body> +<script> +function nextMessage() { + return new Promise((resolve, reject) => { + window.addEventListener('message', e => resolve(e.data), {once: true}); + }); +} + +promise_test(async () => { + let iframe = document.createElement('iframe'); + iframe.setAttribute('src', '/common/security-features/subresource/document.py?first') + iframe.setAttribute('referrerpolicy', 'no-referrer'); + document.body.appendChild(iframe); + + try { + { + let {referrer: documentReferrer, headers: {referer: httpReferrer}} = await nextMessage(); + assert_equals(httpReferrer, undefined, 'expected no HTTP Referer header on initial load'); + assert_equals(documentReferrer, undefined, 'expected no document.referrer on initial load'); + } + + iframe.setAttribute('src', '/common/security-features/subresource/document.py?second'); + + { + let {referrer: documentReferrer, headers: {referer: httpReferrer}} = await nextMessage(); + assert_equals(httpReferrer, undefined, 'expected no HTTP Referer header on src change'); + assert_equals(documentReferrer, undefined, 'expected no document.referrer on src change'); + } + } finally { + iframe.remove(); + } +}, "Checks that referrerpolicy is respected when an iframe's src changes."); +</script> +</body> diff --git a/testing/web-platform/tests/referrer-policy/generic/iframe-upgrade-request-to-cross-origin.sub.html b/testing/web-platform/tests/referrer-policy/generic/iframe-upgrade-request-to-cross-origin.sub.html new file mode 100644 index 0000000000..4040072ab9 --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/iframe-upgrade-request-to-cross-origin.sub.html @@ -0,0 +1,26 @@ +<!DOCTYPE html> +<link rel="author" title="Dominic Farolino" href="dom@chromium.org"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<!-- We need to set the CSP via the <meta> tag. If we were to use the HTTP + header, we'd have to specify the absolute HTTPS URL of the test harness and + reporter, but then this file is not recognized as a test harness test, and + will not run --> +<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests"> +<body> +<iframe id="iframe"></iframe> +<script> +async_test(t => { + const iframe = document.querySelector('iframe'); + iframe.src = + 'http://{{domains[www]}}:{{ports[https][0]}}/referrer-policy/generic/resources/referrer.py'; + + addEventListener('message', t.step_func_done(msg => { + const referrer = msg.data; + assert_equals(referrer, new URL(location.href).origin + '/', + "The referrer header sent for the iframe request should be redacted"); + })); +}, "If an insecure iframe request is upgraded to https to be cross-origin, " + + "referrer policies that consider same-origin-ness should be applied correctly"); +</script> +</body> diff --git a/testing/web-platform/tests/referrer-policy/generic/iframe-upgrade-request-to-cross-origin.sub.html.headers b/testing/web-platform/tests/referrer-policy/generic/iframe-upgrade-request-to-cross-origin.sub.html.headers new file mode 100644 index 0000000000..ad768e6329 --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/iframe-upgrade-request-to-cross-origin.sub.html.headers @@ -0,0 +1 @@ +Referrer-Policy: origin-when-cross-origin diff --git a/testing/web-platform/tests/referrer-policy/generic/iframe-upgrade-request-to-same-origin.sub.https.html b/testing/web-platform/tests/referrer-policy/generic/iframe-upgrade-request-to-same-origin.sub.https.html new file mode 100644 index 0000000000..f9163bec54 --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/iframe-upgrade-request-to-same-origin.sub.https.html @@ -0,0 +1,21 @@ +<!DOCTYPE html> +<link rel="author" title="Dominic Farolino" href="dom@chromium.org"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<body> +<iframe id="iframe"></iframe> +<script> +async_test(t => { + const iframe = document.querySelector('iframe'); + const insecure_origin = new URL(location.href).origin.replace("https", "http"); + iframe.src = insecure_origin + '/referrer-policy/generic/resources/referrer.py'; + + addEventListener('message', t.step_func_done(msg => { + const referrer = msg.data; + assert_equals(referrer, location.href, + "The referrer header sent for the iframe request should not be redacted"); + })); +}, "If an insecure iframe request is upgraded to https to be same-origin, " + + "referrer policies that consider same-origin-ness should be applied correctly"); +</script> +</body> diff --git a/testing/web-platform/tests/referrer-policy/generic/iframe-upgrade-request-to-same-origin.sub.https.html.headers b/testing/web-platform/tests/referrer-policy/generic/iframe-upgrade-request-to-same-origin.sub.https.html.headers new file mode 100644 index 0000000000..fd9ee0f032 --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/iframe-upgrade-request-to-same-origin.sub.https.html.headers @@ -0,0 +1,2 @@ +Content-Security-Policy: upgrade-insecure-requests +Referrer-Policy: origin-when-cross-origin diff --git a/testing/web-platform/tests/referrer-policy/generic/inheritance/iframe-inheritance-about-blank.html b/testing/web-platform/tests/referrer-policy/generic/inheritance/iframe-inheritance-about-blank.html new file mode 100644 index 0000000000..fc7d39a4cf --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/inheritance/iframe-inheritance-about-blank.html @@ -0,0 +1,107 @@ +<!doctype html> +<meta charset="utf-8"> +<title>Referrer Policy: iframe src="about:blank"</title> +<link rel="author" title="Hiroshige Hayashizaki" href="mailto:hiroshige@chromium.org"> +<link rel="author" title="Dom Farolino" href="mailto:dom@chromium.org"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<meta name="referrer" content="origin"> +<body> +<script> +const testFetchClientReferrer = + async_test("The fetch() API in an about:blank iframe with the 'client' " + + "referrer is fetched with no 'Referer' header"); +const testFetchURLReferrer = + async_test("The fetch() API in an about:blank iframe with a custom URL " + + "referrer is fetched with a 'Referer` header that uses the " + + "outer document's URL along with its referrer policy"); +const testDocumentReferrer = + async_test("The value of document.referrer in an about:blank iframe is the " + + "outer document's full URL, regardless of referrer policy"); +const testSubresource = + async_test("A subresource fetched from an about:blank iframe is fetched " + + "with no 'Referer' header"); + +window.addEventListener("message", msg => { + const test_name = msg.data.test; + const referrer = msg.data.referrer; + if (test_name === "testFetchClientReferrer") { + testFetchClientReferrer.step_func_done(() => { + // Because the URL of the Document of <iframe src="about:blank"> is + // "about:blank", the stripped URL is no referrer: + // https://w3c.github.io/webappsec-referrer-policy/#strip-url. + assert_equals(referrer, undefined); + })(); + } else if (test_name === "testFetchURLReferrer") { + // <iframe src="about:blank"> inherits its parent's referrer policy. + // Note: Setting an explicit URL as referrer succeeds + // because the same-origin check at + // https://fetch.spec.whatwg.org/#dom-request + // is done against <iframe>'s origin, which inherits the parent + // Document's origin == location.orgin. Furthermore, since the iframe + // inherits its parent's referrer policy, the URL should be restricted to + // its origin. + testFetchURLReferrer.step_func_done(() => { + assert_equals(referrer, location.origin + '/'); + })(); + } else if (test_name === "testDocumentReferrer") { + // The referrer of the initial document in an about:blank iframe is set to + // its creating document's URL, unredacted by a referrer policy, as per step + // 13 of: + // https://html.spec.whatwg.org/multipage/browsers.html#creating-a-new-browsing-context. + testDocumentReferrer.step_func_done(() => { + assert_equals(referrer, location.href); + })(); + } else if (test_name === "testSubresource") { + // Because the URL of the Document of <iframe src="about:blank"> is + // "about:blank", the stripped URL is no referrer: + // https://w3c.github.io/webappsec-referrer-policy/#strip-url. + testSubresource.step_func_done(() => { + assert_equals(referrer, ""); + })(); + } +}); + +const iframe = document.createElement("iframe"); + +iframe.addEventListener("load", function() { + const iframe_script = iframe.contentDocument.createElement('script'); + iframe_script.textContent = ` + // Test fetch() API with default "client" referrer. + fetch("${location.origin}/common/security-features/subresource/xhr.py?name=testFetchClientReferrer") + .then(r => r.json()) + .then(j => { + top.postMessage({test: "testFetchClientReferrer", referrer: j.headers.referer}, "*") + }).catch(e => { + top.postMessage({test: "testFetchClientReferrer", referrer: "FAILURE"}, "*"); + }); + + // Test fetch() API with custom URL referrer. + fetch("${location.origin}/common/security-features/subresource/xhr.py?name=URL", + {referrer: "${location.href}/custom"}) + .then(r => r.json()) + .then(j => { + top.postMessage({test: "testFetchURLReferrer", referrer: j.headers.referer}, "*") + }).catch(e => { + top.postMessage({test: "testFetchURLReferrer", referrer: "FAILURE"}, "*"); + }); + + // Test document.referrer. + top.postMessage({test: "testDocumentReferrer", referrer: document.referrer}, "*"); + + // Test a subresource being fetched by the iframe. + const subresource_script = document.createElement('script'); + subresource_script.src = "${location.origin}/common/security-features/subresource/referrer.py"; + subresource_script.onload = e => { + top.postMessage({test: "testSubresource", referrer: window.referrer}, "*"); + } + subresource_script.onerror = function(e) { + top.postMessage({test: "testSubresource", referrer: "FAILURE"}, "*"); + }; + document.head.appendChild(subresource_script); + `; + iframe.contentDocument.body.appendChild(iframe_script); +}); + +document.body.appendChild(iframe); +</script> diff --git a/testing/web-platform/tests/referrer-policy/generic/inheritance/iframe-inheritance-data.html b/testing/web-platform/tests/referrer-policy/generic/inheritance/iframe-inheritance-data.html new file mode 100644 index 0000000000..1d39781e30 --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/inheritance/iframe-inheritance-data.html @@ -0,0 +1,27 @@ +<html> + <head> + <title>Referrer Policy: iframes with data url uses no referrer</title> + <link rel="help" href="https://www.w3.org/TR/referrer-policy/#referrer-policy-delivery-nested"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="/common/get-host-info.sub.js"></script> + <script src="resources/make-html-script.js"></script> + <meta name="referrer" content="origin"> + </head> + <body onload="runTest()"> + <h1>Referrer Policy: iframes with data url uses no referrer</h1> + <script> + let test = async_test("iframes with data url uses no referrer"); + window.addEventListener("message", test.step_func_done(msg => { + assert_equals(msg.data.referrer, undefined); + })); + + function runTest() { + let iframe = document.createElement("iframe"); + iframe.src = `data:text/html,${createScriptString(get_host_info().REMOTE_ORIGIN)}`; + document.body.appendChild(iframe); + } + </script> + <div id="log"></div> + </body> +</html> diff --git a/testing/web-platform/tests/referrer-policy/generic/inheritance/iframe-inheritance-document-write.html b/testing/web-platform/tests/referrer-policy/generic/inheritance/iframe-inheritance-document-write.html new file mode 100644 index 0000000000..c88586aaf6 --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/inheritance/iframe-inheritance-document-write.html @@ -0,0 +1,34 @@ +<!doctype html> +<title>Referrer Policy: iframes with document.write()</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="resources/make-html-script.js"></script> +<meta name="referrer" content="origin"> +<div id="log"></div> +<script> + let reportedReferrer = () => { + return new Promise(resolve => { + window.addEventListener("message", msg => resolve(msg.data.referrer)); + }); + }; + + const iframe = document.createElement("iframe"); + promise_test(async t => { + let referrer_of_srcdoc_iframe = reportedReferrer(); + const script_to_fetch_cross_origin_resource = + createScriptString(get_host_info().REMOTE_ORIGIN, location.origin + "/custom"); + iframe.srcdoc = `<head><meta name="referrer" content="unsafe-url"></head>` + + script_to_fetch_cross_origin_resource; + document.body.appendChild(iframe); + assert_equals(await referrer_of_srcdoc_iframe, self.origin + "/custom", + "Srcdoc iframe setting referrer policy via meta header should use that referrer policy."); + + let referrer_after_document_open = reportedReferrer(); + iframe.contentDocument.open(); + iframe.contentDocument.write(script_to_fetch_cross_origin_resource); + iframe.contentDocument.close(); + assert_equals(await referrer_after_document_open, self.origin + "/custom", + "Referrer policy should not change after document.open()."); + }, "document.open() should not change the referrer policy of the opened document."); +</script> diff --git a/testing/web-platform/tests/referrer-policy/generic/inheritance/iframe-inheritance-history-about-blank.html b/testing/web-platform/tests/referrer-policy/generic/inheritance/iframe-inheritance-history-about-blank.html new file mode 100644 index 0000000000..8d68ffb5ff --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/inheritance/iframe-inheritance-history-about-blank.html @@ -0,0 +1,80 @@ +<!doctype html> +<title>Referrer Policy: navigating back to an about:blank iframe reuses the original referrer policy</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<meta name="referrer" content="no-referrer"> +<div id="log"></div> +<script> + let checkReferrer = document => { + let script = document.createElement('script'); + script.innerText = ` + fetch("${origin}/common/security-features/subresource/xhr.py", + {referrer: "${location.origin}/custom"}) + .then(r => r.json()) + .then(j => { + top.postMessage({referrer: j.headers.referer}, "*") + }).catch(e => { + top.postMessage({referrer: "FAILURE"}, "*"); + }); + ` + + let referrer = new Promise(resolve => { + window.addEventListener("message", function listener(msg) { + window.removeEventListener("message", listener, false); + resolve(msg.data.referrer); + }); + }); + + document.body.appendChild(script); + + return referrer; + }; + + let iframeLoaded = iframe => { + return new Promise(resolve => { + iframe.onload = resolve; + }); + }; + + promise_test(async t => { + // 1. Create an iframe and navigate it to about:blank. + // (We cannot just create an empty iframe since the initial empty + // document will get its history entry replaced, so we cannot + // navigate back to it.) + const iframe = document.createElement("iframe"); + iframe.name = 'test_frame'; + iframe.src = "/referrer-policy"; + document.body.appendChild(iframe); + await iframeLoaded(iframe); + + window.open('about:blank', 'test_frame'); + await iframeLoaded(iframe); + let referrer_1 = await checkReferrer(iframe.contentDocument); + assert_equals(referrer_1, undefined, + "First navigation uses correct policy."); + + // 2. Change the referrer policy of the iframe. + let meta = iframe.contentDocument.createElement('meta'); + meta.name = 'referrer'; + meta.content = "unsafe-url"; + iframe.contentDocument.head.appendChild(meta); + + let referrer_2 = await checkReferrer(iframe.contentDocument); + assert_equals(referrer_2, location.origin + '/custom', + "Referrer policy correctly changed."); + + // 3. Navigate the iframe elsewhere. + window.open('/referrer-policy', 'test_frame'); + await iframeLoaded(iframe); + + // 4. Navigate the iframe back. + iframe.contentWindow.history.back(); + await iframeLoaded(iframe); + + let referrer_3 = await checkReferrer(iframe.contentDocument); + assert_equals(referrer_3, undefined, + "History navigation reuses original policy."); + document.body.removeChild(iframe); + }, "History navigation reuses original policy."); + +</script> diff --git a/testing/web-platform/tests/referrer-policy/generic/inheritance/iframe-inheritance-history-about-srcdoc.html b/testing/web-platform/tests/referrer-policy/generic/inheritance/iframe-inheritance-history-about-srcdoc.html new file mode 100644 index 0000000000..91ac5fc139 --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/inheritance/iframe-inheritance-history-about-srcdoc.html @@ -0,0 +1,73 @@ +<!doctype html> +<title>Referrer Policy: navigating back to an about:srcdoc iframe reuses the original referrer policy</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="resources/make-html-script.js"></script> +<meta name="referrer" content="no-referrer"> +<div id="log"></div> +<script> + let reportedReferrer = () => { + return new Promise(resolve => { + window.addEventListener("message", function listener(msg) { + window.removeEventListener("message", listener, false); + resolve(msg.data.referrer); + }); + }); + }; + + let iframeLoaded = iframe => { + return new Promise(resolve => { + iframe.onload = resolve; + }); + }; + + promise_test(async t => { + // 1. Create an about:srcdoc iframe. + const iframe = document.createElement("iframe"); + iframe.name = 'test_frame'; + let iframe_load_1 = iframeLoaded(iframe); + let referrer_1 = reportedReferrer(); + iframe.srcdoc = createScriptString(get_host_info().REMOTE_ORIGIN, + location.origin + "/custom"); + document.body.appendChild(iframe); + await iframe_load_1; + let referrer_1_result = await referrer_1; + + // 2. Change the referrer policy of the main document. + document.getElementsByTagName('meta')[0].content = "unsafe-url"; + + // 3. Navigate the iframe elsewhere. + let iframe_load_2 = iframeLoaded(iframe); + window.open('/referrer-policy', 'test_frame'); + await iframe_load_2; + + // 4. Navigate the iframe back. + let iframe_load_3 = iframeLoaded(iframe); + let referrer_2 = reportedReferrer(); + iframe.contentWindow.history.back(); + await iframe_load_3; + + // Despite the main document has changed its referrer policy in (2), the + // reported referrer for the history navigation to about:srcdoc in (4) must + // match with the one originally reported in (1). + assert_equals(referrer_1_result, undefined, + "First navigation uses correct policy."); + assert_equals(await referrer_2, undefined, + "History navigation reuses original policy."); + }, "History navigation reuses original policy."); + + promise_test(async t => { + // If we initiate a new about:srcdoc navigation, the new referrer policy + // should apply. + const new_iframe = document.createElement("iframe"); + let new_iframe_load = iframeLoaded(new_iframe); + let new_iframe_referrer = reportedReferrer(); + new_iframe.srcdoc = createScriptString(get_host_info().REMOTE_ORIGIN, + location.origin + "/custom"); + document.body.appendChild(new_iframe); + await new_iframe_load; + + assert_equals(await new_iframe_referrer, self.origin + '/custom'); + }, "New srcdoc iframe uses new policy."); +</script> diff --git a/testing/web-platform/tests/referrer-policy/generic/inheritance/iframe-inheritance-javascript-child.html b/testing/web-platform/tests/referrer-policy/generic/inheritance/iframe-inheritance-javascript-child.html new file mode 100644 index 0000000000..491f104de4 --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/inheritance/iframe-inheritance-javascript-child.html @@ -0,0 +1,77 @@ +<!doctype html> +<title>Referrer Policy: iframes with javascript url reuse referrer policy</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="resources/make-html-script.js"></script> +<meta name="referrer" content="unsafe-url"> +<div id="log"></div> +<script> +[ + { + srcDocPolicy: ``, + expected: location.origin + "/custom" + }, + { + srcDocPolicy: `<meta name="referrer" content="no-referrer">`, + expected: undefined + } +].forEach(({ srcDocPolicy, expected }) => { + promise_test(t => { + return new Promise(resolve => { + window.addEventListener("message", t.step_func(msg => { + assert_equals(msg.data.referrer, expected); + resolve(); + }), { once:true }); + + const iframe = document.createElement("iframe"); + t.add_cleanup(() => iframe.remove()); + iframe.srcdoc = `${srcDocPolicy}<body><h1>Outer iframe</h1></body>`; + iframe.onload = t.step_func(() => { + iframe.onload = null; + const iframeChild = iframe.contentDocument.createElement("iframe"); + // We add a custom referrer to the fetch request. Otherwise, + // since the frame's URL is "about:blank", the Referer header will + // always be empty: + // https://w3c.github.io/webappsec-referrer-policy/#strip-url. + iframeChild.src = `javascript:'${createScriptString(get_host_info().REMOTE_ORIGIN, location.origin+"/custom")}'`; + iframe.contentDocument.body.appendChild(iframeChild); + }); + document.body.appendChild(iframe); + }); + }); +}); + +[ + { + srcDocPolicy: ``, + expected: location.href // Executing javascript does not change the document url. + // Since the algorithm for computing the referrer in a srcdoc + // iframe defers recursively to the parent, the expected + // referrer should be the full url of the main document. + }, + { + srcDocPolicy: `<meta name="referrer" content="no-referrer">`, + expected: undefined + } +].forEach(({ srcDocPolicy, expected }) => { + promise_test(t => { + return new Promise(resolve => { + window.addEventListener("message", t.step_func(msg => { + assert_equals(msg.data.referrer, expected); + resolve(); + }), { once:true }); + + const iframe = document.createElement("iframe"); + t.add_cleanup(() => iframe.remove()); + iframe.srcdoc = `${srcDocPolicy}<body><h1>Outer iframe</h1></body>`; + iframe.onload = t.step_func(() => { + iframe.onload = null; + iframe.contentWindow.location = `javascript:'${createScriptString(get_host_info().REMOTE_ORIGIN)}'`; + }); + document.body.appendChild(iframe); + }); + }); +}); + +</script> diff --git a/testing/web-platform/tests/referrer-policy/generic/inheritance/iframe-inheritance-javascript.html b/testing/web-platform/tests/referrer-policy/generic/inheritance/iframe-inheritance-javascript.html new file mode 100644 index 0000000000..cf1f099c63 --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/inheritance/iframe-inheritance-javascript.html @@ -0,0 +1,45 @@ +<!doctype html> +<title>Referrer Policy: iframes with javascript url reuse referrer policy</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="resources/make-html-script.js"></script> +<meta name="referrer" content="unsafe-url"> +<div id="log"></div> +<script> + +[ + { + fetchReferrer: "", + // Because the URL of the Document of <iframe src="javascript:..."> is + // "about:blank", the stripped URL is no referrer: + // https://w3c.github.io/webappsec-referrer-policy/#strip-url. + expected: undefined + }, + { + fetchReferrer: location.origin+"/custom", + // <iframe src="javascript:..."> inherits its parent's referrer policy. + // Note: Setting an explicit URL as referrer succeeds + // because the same-origin check at + // https://fetch.spec.whatwg.org/#dom-request + // is done against <iframe>'s origin, which inherits the parent + // Document's origin == location.orgin. Furthermore, since the iframe + // inherits its parent's referrer policy, the URL should be restricted to + // its origin. + expected: self.origin + "/custom" + } +].forEach(({ fetchReferrer, expected }) => { + promise_test(t => { + return new Promise(resolve => { + window.addEventListener("message", t.step_func(msg => { + assert_equals(msg.data.referrer, expected); + resolve(); + }), { once: true }); + const iframe = document.createElement("iframe"); + iframe.src = `javascript:'${createScriptString(get_host_info().REMOTE_ORIGIN, fetchReferrer)}'`; + document.body.appendChild(iframe); + }); + }); +}); + +</script> diff --git a/testing/web-platform/tests/referrer-policy/generic/inheritance/iframe-inheritance-srcdoc-child.html b/testing/web-platform/tests/referrer-policy/generic/inheritance/iframe-inheritance-srcdoc-child.html new file mode 100644 index 0000000000..cd4b4ae724 --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/inheritance/iframe-inheritance-srcdoc-child.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html> + <head> + <title>Referrer Policy: iframes srdoc child correctly inherit the ancestor's referrer policy</title> + <link rel="help" href="https://www.w3.org/TR/referrer-policy/#referrer-policy-delivery-nested"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="/common/get-host-info.sub.js"></script> + <script src="resources/make-html-script.js"></script> + <meta name="referrer" content="origin"> + </head> + <body onload="runTest()"> + <h1>Referrer Policy: iframes srcdoc child correctly inherit the ancestor's referrer policy</h1> + <script> + var test = async_test("iframes srcdoc child correctly inherit the ancestor's referrer policy"); + window.addEventListener("message", test.step_func_done(msg => { + assert_equals(msg.data.referrer, self.origin + "/"); + })); + + function runTest() { + var iframe = document.createElement("iframe"); + iframe.srcdoc = `<body><h1>Outer iframe</h1></body>`; + iframe.onload = test.step_func(() => { + iframe.onload = null; + var iframeChild = iframe.contentDocument.createElement("iframe"); + iframeChild.srcdoc = createScriptString(get_host_info().REMOTE_ORIGIN); + iframe.contentDocument.body.appendChild(iframeChild); + }); + document.body.appendChild(iframe); + } + </script> + <div id="log"></div> + </body> +</html> diff --git a/testing/web-platform/tests/referrer-policy/generic/inheritance/iframe-inheritance-srcdoc.html b/testing/web-platform/tests/referrer-policy/generic/inheritance/iframe-inheritance-srcdoc.html new file mode 100644 index 0000000000..6904374b63 --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/inheritance/iframe-inheritance-srcdoc.html @@ -0,0 +1,45 @@ +<!DOCTYPE html> +<html> + <head> + <title>Referrer Policy: iframes srdoc correctly inherit the ancestor's referrer policy</title> + <link rel="help" href="https://www.w3.org/TR/referrer-policy/#referrer-policy-delivery-nested"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="/common/get-host-info.sub.js"></script> + <script src="resources/make-html-script.js"></script> + <meta name="referrer" content="origin"> + </head> + <body> + <h1>Referrer Policy: iframes srcdoc correctly inherit the ancestor's referrer policy</h1> + <script> + let reportedReferrer = () => { + return new Promise(resolve => { + window.addEventListener("message", msg => resolve(msg.data.referrer)); + }); + }; + + const iframe = document.createElement("iframe"); + + promise_test(async t => { + let referrer = reportedReferrer(); + iframe.srcdoc = createScriptString(get_host_info().REMOTE_ORIGIN, + location.origin + "/custom"); + document.body.appendChild(iframe); + assert_equals(await referrer, self.origin + "/", + "Referrer policy should be inherited from parent."); + + let meta = document.createElement('meta'); + meta.name = "referrer"; + meta.content = "unsafe-url"; + document.head.appendChild(meta); + iframe.contentWindow.postMessage('checkReferrer'); + assert_equals( + await reportedReferrer(), self.origin + "/", + "Changing parent's referrer policy has no effect on the child."); + + }, "Srcdoc iframe inherits referrer policy from parent on creation."); + + </script> + <div id="log"></div> + </body> +</html> diff --git a/testing/web-platform/tests/referrer-policy/generic/inheritance/popup-inheritance-about-blank.html b/testing/web-platform/tests/referrer-policy/generic/inheritance/popup-inheritance-about-blank.html new file mode 100644 index 0000000000..c8e9a9c012 --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/inheritance/popup-inheritance-about-blank.html @@ -0,0 +1,105 @@ +<!doctype html> +<meta charset="utf-8"> +<title>Referrer Policy: popup src="about:blank"</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<meta name="referrer" content="origin"> +<body> +<script> +const testFetchClientReferrer = + async_test("The fetch() API in an about:blank popup with the 'client' " + + "referrer is fetched with no 'Referer' header"); +const testFetchURLReferrer = + async_test("The fetch() API in an about:blank popup with a custom URL " + + "referrer is fetched with a 'Referer` header that uses the " + + "outer document's URL along with its referrer policy"); +const testDocumentReferrer = + async_test("The value of document.referrer in an about:blank popup is the " + + "outer document's full URL, regardless of referrer policy"); +const testSubresource = + async_test("A subresource fetched from an about:blank popup is fetched " + + "with no 'Referer' header"); + +window.addEventListener("message", msg => { + const test_name = msg.data.test; + const referrer = msg.data.referrer; + if (test_name === "testFetchClientReferrer") { + // Because the URL of the document of the popup opened through + // `window.open()` is "about:blank", the stripped URL is no referrer: + // https://w3c.github.io/webappsec-referrer-policy/#strip-url. + testFetchClientReferrer.step_func_done(() => { + assert_equals(referrer, undefined); + })(); + } else if (test_name === "testFetchURLReferrer") { + // The "about:blank" popup inherits its opener's referrer policy. + // Note: Setting an explicit URL as referrer is allowed per spec because the + // same-origin check at https://fetch.spec.whatwg.org/#dom-request is done + // against the popup's origin, which inherits the opener document's origin. + testFetchURLReferrer.step_func_done(() => { + assert_equals(referrer, location.origin + '/'); + })(); + } else if (test_name === "testDocumentReferrer") { + // The referrer of the initial document in an about:blank popup is set to + // its creating document's URL, unredacted by a referrer policy, as per step + // 17 of: + // https://html.spec.whatwg.org/multipage/browsers.html#creating-a-new-browsing-context. + testDocumentReferrer.step_func_done(() => { + assert_equals(referrer, location.href); + })(); + } else if (test_name === "testSubresource") { + // Because the URL of the document of the popup is "about:blank", the + // stripped URL is no referrer: + // https://w3c.github.io/webappsec-referrer-policy/#strip-url. + // + // Note: this test is essentially the same as "testFetchClientReferrer" (the + // only difference is that the fetch is not initiated by javascript). + // Compared to the other test, we expect the empty string here instead of + // `undefined` just because of a testing quirk. + testSubresource.step_func_done(() => { + assert_equals(referrer, ""); + })(); + } +}); + +const popup = window.open(); +const script = popup.document.createElement('script'); + +script.textContent = ` + // Test fetch() API with default "client" referrer. + fetch("${location.origin}/common/security-features/subresource/xhr.py?name=testFetchClientReferrer") + .then(r => r.json()) + .then(j => { + opener.postMessage({test: "testFetchClientReferrer", referrer: j.headers.referer}, "*") + }).catch(e => { + opener.postMessage({test: "testFetchClientReferrer", referrer: "FAILURE"}, "*"); + }); + + // Test fetch() API with custom URL referrer. + fetch("${location.origin}/common/security-features/subresource/xhr.py?name=URL", + {referrer: "${location.href}/custom"}) + .then(r => r.json()) + .then(j => { + opener.postMessage({test: "testFetchURLReferrer", referrer: j.headers.referer}, "*") + }).catch(e => { + opener.postMessage({test: "testFetchURLReferrer", referrer: "FAILURE"}, "*"); + }); + + // Test document.referrer. + opener.postMessage({test: "testDocumentReferrer", referrer: document.referrer}, "*"); + + // Test a subresource being fetched by the popup. + // This is practicallty the same as the first test: the only difference is + // that here the fetch is not triggered by a javascript fetch function but by + // a script element with a src tag embedded in the html source. + const subresource_script = document.createElement('script'); + subresource_script.src = "${location.origin}/common/security-features/subresource/referrer.py"; + subresource_script.onload = e => { + opener.postMessage({test: "testSubresource", referrer: window.referrer}, "*"); + } + subresource_script.onerror = function(e) { + opener.postMessage({test: "testSubresource", referrer: "FAILURE"}, "*"); + }; + document.head.appendChild(subresource_script); +`; +popup.document.body.appendChild(script); +</script> diff --git a/testing/web-platform/tests/referrer-policy/generic/inheritance/popup-inheritance-form-submission.html b/testing/web-platform/tests/referrer-policy/generic/inheritance/popup-inheritance-form-submission.html new file mode 100644 index 0000000000..2c03792a07 --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/inheritance/popup-inheritance-form-submission.html @@ -0,0 +1,30 @@ +<!doctype html> +<meta charset="utf-8"> +<title>Referrer Policy: popup src="about:blank"</title> +<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1370425"> +<link rel="help" href="https://html.spec.whatwg.org/#creating-a-new-browsing-context"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<body> + +<iframe src="resources/submit-form-and-remove-frame.html"></iframe> +<script> +async_test(t => { + // Called by the child frame once it has submitted its form that creates a new + // `about:blank` window in our browsing context group (therefore, the window + // is reachable by us). + window.removeIframe = t.step_func(() => { + const iframe = document.querySelector('iframe'); + const expected_referrer = iframe.contentWindow.location.href; + iframe.remove(); + + // The child frame is removed, but its form submission navigation is still + // queued on the opened window's global. Wait until it is run and then + // evaluate script. + t.step_timeout(t.step_func_done(() => { + const window_opened_from_form = window.open("", "does-not-exist"); + assert_equals(document.referrer, expected_referrer); + })); + }); +}, "A new frame's document.referrer is correct even if its initiator frame is gone"); +</script> diff --git a/testing/web-platform/tests/referrer-policy/generic/inheritance/resources/make-html-script.js b/testing/web-platform/tests/referrer-policy/generic/inheritance/resources/make-html-script.js new file mode 100644 index 0000000000..6c2c145c4e --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/inheritance/resources/make-html-script.js @@ -0,0 +1,19 @@ +function createScriptString(origin, referrer) { + let request_init = referrer ? `{referrer: "${referrer}"}` : ""; + return `<script> + function checkReferrer() { + fetch("${origin}/common/security-features/subresource/xhr.py", + ${request_init}) + .then(r => r.json()) + .then(j => { + top.postMessage({referrer: j.headers.referer}, "*") + }).catch(e => { + top.postMessage({referrer: "FAILURE"}, "*"); + }); + } + checkReferrer(); + window.addEventListener("message", msg => { + if (msg.data === "checkReferrer") checkReferrer(); + }); + <\/script>`; +} diff --git a/testing/web-platform/tests/referrer-policy/generic/inheritance/resources/submit-form-and-remove-frame.html b/testing/web-platform/tests/referrer-policy/generic/inheritance/resources/submit-form-and-remove-frame.html new file mode 100644 index 0000000000..bf5ede96d9 --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/inheritance/resources/submit-form-and-remove-frame.html @@ -0,0 +1,10 @@ +<!doctype html> +<meta name='referrer' content='no-referrer'> +<body onload='start()'> +<script> + function start() { + myform.submit(); + parent.removeIframe(); + } +</script> +<form id='myform' action='about:blank' target='does-not-exist'> diff --git a/testing/web-platform/tests/referrer-policy/generic/inheritance/workers.html b/testing/web-platform/tests/referrer-policy/generic/inheritance/workers.html new file mode 100644 index 0000000000..0bd75a1d15 --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/inheritance/workers.html @@ -0,0 +1,47 @@ +<html> + <head> + <title>Referrer Policy: local scheme workers inherit from creator</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="/common/get-host-info.sub.js"></script> + <meta name="referrer" content="no-referrer"> + </head> + <script> + let cross_origin = get_host_info().REMOTE_ORIGIN; + + let generateFetchString = postmessage => ` + fetch("${cross_origin}/common/security-features/subresource/xhr.py", + {referrer: "${location.href}/custom"}) + .then(r => r.json()) + .then(j => ${postmessage}({referrer: j.headers.referer})) + .catch(e => ${postmessage}({referrer: "FAILURE"}));` + + async_test(t => { + let blob = new Blob([generateFetchString("postMessage")], + {type : 'application/javascript'}); + let blob_url = URL.createObjectURL(blob); + let worker = new Worker(blob_url); + worker.onmessage = t.step_func_done(msg => { + assert_equals(msg.data.referrer, undefined); + }); + }, "Dedicated worker with local scheme inherits referrer policy " + + "from the creating document."); + + async_test(t => { + let script = ` + onconnect = e => { + let port = e.ports[0]; + port.start(); + ${generateFetchString("port.postMessage")} + };` + let blob = new Blob([script], {type : 'application/javascript'}); + let blob_url = URL.createObjectURL(blob); + let shared_worker = new SharedWorker(blob_url); + shared_worker.port.start(); + shared_worker.port.onmessage = t.step_func_done(msg => { + assert_equals(msg.data.referrer, undefined); + }); + }, "Shared worker with local scheme inherits referrer policy " + + "from the creating document."); + </script> +</html> diff --git a/testing/web-platform/tests/referrer-policy/generic/link-rel-prefetch.html b/testing/web-platform/tests/referrer-policy/generic/link-rel-prefetch.html new file mode 100644 index 0000000000..72e831c921 --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/link-rel-prefetch.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<html> + <head> + <title>Referrer policies for resources loaded via link rel prefetch</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <!-- Common global functions for referrer-policy tests. --> + <script src="/common/security-features/resources/common.sub.js"></script> + <meta name="referrer" content="origin"> + <link rel="prefetch" href="/common/security-features/subresource/image.py"> + </head> + <body> + <p>Check that resources loaded via link rel prefetch use the referrer + and referrer policy from the document.</p> + + <script> + var img_url = "/common/security-features/subresource/image.py"; + promise_test((t) => timeoutPromise(t, 1000) + .then(() => requestViaImage(img_url, null)) + .then(message => { + assert_equals(message.headers.referer, document.location.origin + "/"); + }), + "Prefetched image."); + </script> + + <div id="log"></div> + </body> +</html> diff --git a/testing/web-platform/tests/referrer-policy/generic/meta-referrer-outofhead-fetch.http.html b/testing/web-platform/tests/referrer-policy/generic/meta-referrer-outofhead-fetch.http.html new file mode 100644 index 0000000000..1b7a7bada5 --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/meta-referrer-outofhead-fetch.http.html @@ -0,0 +1,21 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <meta name="referrer" content="no-referrer"> + <script> + promise_test((t) => + fetch("/common/security-features/subresource/xhr.py") + .then(res => res.json()) + .then(data => { + assert_equals(data.headers.referer, undefined); + }), + "Referer header was not send"); + </script> + <div id="log"></div> + </body> +</html> diff --git a/testing/web-platform/tests/referrer-policy/generic/meta-referrer-removed-1.http.html b/testing/web-platform/tests/referrer-policy/generic/meta-referrer-removed-1.http.html new file mode 100644 index 0000000000..7027788504 --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/meta-referrer-removed-1.http.html @@ -0,0 +1,25 @@ +<!DOCTYPE html> +<head> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + + <meta name="referrer" content="no-referrer" id="referrermeta"> +</head> +<body> + <script> + async function fetchAndGetReferrer() { + let response = await fetch('/common/security-features/subresource/xhr.py'); + let data = await response.json(); + return data.headers.referer; + } + + promise_test(async t => { + assert_equals(await fetchAndGetReferrer(), undefined, + 'referrer should not be set'); + + document.getElementById('referrermeta').remove(); + assert_equals(await fetchAndGetReferrer(), undefined, + 'referrer should not be set'); + }, 'removing <meta name="referrer"> should not change referrer policy'); + </script> +</body> diff --git a/testing/web-platform/tests/referrer-policy/generic/meta-referrer-removed-2.http.html b/testing/web-platform/tests/referrer-policy/generic/meta-referrer-removed-2.http.html new file mode 100644 index 0000000000..42f73e8781 --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/meta-referrer-removed-2.http.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<head> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + + <meta name="referrer" content="no-referrer" id="referrermeta"> +</head> +<body> + <script> + async function fetchAndGetReferrer() { + let response = await fetch('/common/security-features/subresource/xhr.py'); + let data = await response.json(); + return data.headers.referer; + } + + promise_test(async t => { + assert_equals(await fetchAndGetReferrer(), undefined, + 'referrer should not be set'); + + // Add second meta tag. + const second_meta = document.createElement('meta'); + second_meta.name = 'referrer'; + second_meta.content = 'strict-origin'; + document.head.appendChild(second_meta); + // Second meta should override the first. + assert_equals(await fetchAndGetReferrer(), location.origin + '/', + 'referrer should be origin only'); + + second_meta.remove(); + assert_equals(await fetchAndGetReferrer(), window.location.origin + '/', + 'referrer should be origin only'); + }, 'referrer policy does not change when second <meta name="referrer"> is removed'); + </script> +</body> diff --git a/testing/web-platform/tests/referrer-policy/generic/meta-tag-in-svg-image.html b/testing/web-platform/tests/referrer-policy/generic/meta-tag-in-svg-image.html new file mode 100644 index 0000000000..5bdc2c1abf --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/meta-tag-in-svg-image.html @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<html> + <head> + <title>Referrer Policy: Meta tag in svg image loaded via img should not change referrer policy</title> + <meta name="referrer" content="origin"/> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <!-- Common global functions for referrer-policy tests. --> + <script src="/common/security-features/resources/common.sub.js"></script> + </head> + <body> + <script> + async_test(function(t) { + var img = document.createElement("img"); + img.onload = function() { + var urlPath = '/common/security-features/subresource/image.py?cache_destroyer=' + (new Date()).getTime(); + return requestViaImage(urlPath, null, 'always') + .then(t.step_func(function(message) { + assert_equals(message.referrer, self.origin + '/'); + })) + .finally(function() { t.done(); }); + }; + img.onerror = t.step_func_done(function() { + assert_unreached("img should load"); + }); + img.src = "./resources/img-with-referrer-policy.svg"; + document.body.appendChild(img); + }, "Meta tag in SVG image loaded via img should be ignored"); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/referrer-policy/generic/multiple-headers-and-values.html b/testing/web-platform/tests/referrer-policy/generic/multiple-headers-and-values.html new file mode 100644 index 0000000000..e6b7b07d51 --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/multiple-headers-and-values.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<html> + <head> + <title>Referrer Policy: multiple Referrer-Policy header and header values are allowed</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + + <script src="/common/security-features/resources/common.sub.js"></script> + </head> + <body> + <h1>Referrer Policy: multiple Referrer-Policy header and header values are allowed</h1> + <p></p> + + <pre id="received_message">Running...</pre> + + <script> + promise_test(() => { + var urlPath = '/common/security-features/subresource/image.py?cache_destroyer=' + (new Date()).getTime(); + var url = location.protocol + "//www1." + location.hostname + ":" + location.port + + urlPath; + return requestViaImage(url, null, 'no-referrer') + .then(function(message) { + assert_equals(message.referrer, document.location.origin + "/"); + }); + }, "Image uses the last recognized Referrer-Policy header value"); + </script> + + <div id="log"></div> + </body> +</html> diff --git a/testing/web-platform/tests/referrer-policy/generic/multiple-headers-and-values.html.headers b/testing/web-platform/tests/referrer-policy/generic/multiple-headers-and-values.html.headers new file mode 100644 index 0000000000..d1acc2f1d3 --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/multiple-headers-and-values.html.headers @@ -0,0 +1,2 @@ +Referrer-Policy: no-referrer +Referrer-Policy: no-referrer,origin diff --git a/testing/web-platform/tests/referrer-policy/generic/multiple-headers-combined.html b/testing/web-platform/tests/referrer-policy/generic/multiple-headers-combined.html new file mode 100644 index 0000000000..b5c27515df --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/multiple-headers-combined.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<html> + <head> + <title>Referrer Policy: multiple Referrer-Policy header values are allowed</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + + <script src="/common/security-features/resources/common.sub.js"></script> + </head> + <body> + <h1>Referrer Policy: multiple Referrer-Policy header values are allowed</h1> + <p></p> + + <pre id="received_message">Running...</pre> + + <script> + promise_test(() => { + var urlPath = '/common/security-features/subresource/image.py?cache_destroyer=' + (new Date()).getTime(); + var url = location.protocol + "//www1." + location.hostname + ":" + location.port + + urlPath; + return requestViaImage(url, null, 'no-referrer') + .then(function(message) { + assert_equals(message.referrer, document.location.origin + "/"); + }); + }, "Image uses the last recognized Referrer-Policy header value"); + </script> + + <div id="log"></div> + </body> +</html> diff --git a/testing/web-platform/tests/referrer-policy/generic/multiple-headers-combined.html.headers b/testing/web-platform/tests/referrer-policy/generic/multiple-headers-combined.html.headers new file mode 100644 index 0000000000..fc30a2a186 --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/multiple-headers-combined.html.headers @@ -0,0 +1 @@ +Referrer-Policy: no-referrer, origin diff --git a/testing/web-platform/tests/referrer-policy/generic/multiple-headers-one-invalid.html b/testing/web-platform/tests/referrer-policy/generic/multiple-headers-one-invalid.html new file mode 100644 index 0000000000..eca734601a --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/multiple-headers-one-invalid.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html> + <head> + <title>Referrer Policy: multiple Referrer-Policy headers with one invalid</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + + <script src="/common/security-features/resources/common.sub.js"></script> + </head> + <body> + <h1>Referrer Policy: multiple Referrer-Policy headers with one invalid</h1> + <p></p> + + <pre id="received_message">Running...</pre> + + <script> + promise_test(() => { + var urlPath = '/common/security-features/subresource/image.py?cache_destroyer=' + (new Date()).getTime(); + // The default referrer policy is strict-origin-when-cross-origin. + // This document's headers contain the 'origin' and 'no-referrer' tokens, + // and we're making a same-origin image load, so, if the image request, + // uses the default policy (which is what this test's verifying), we + // should see the full initiating URL in the referrer, rather than just + // the origin or an empty string. + return requestViaImage(urlPath, null, 'no-referrer') + .then(function(message) { + assert_equals(message.referrer, document.location.href); + }); + }, "Referrer policy header parsing fails if one header is invalid"); + </script> + + <div id="log"></div> + </body> +</html> diff --git a/testing/web-platform/tests/referrer-policy/generic/multiple-headers-one-invalid.html.headers b/testing/web-platform/tests/referrer-policy/generic/multiple-headers-one-invalid.html.headers new file mode 100644 index 0000000000..0752193804 --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/multiple-headers-one-invalid.html.headers @@ -0,0 +1,2 @@ +Referrer-Policy: origin +Referrer-Policy: origin no-referrer diff --git a/testing/web-platform/tests/referrer-policy/generic/multiple-headers-one-unknown-token.html b/testing/web-platform/tests/referrer-policy/generic/multiple-headers-one-unknown-token.html new file mode 100644 index 0000000000..f07500e546 --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/multiple-headers-one-unknown-token.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<html> + <head> + <title>Referrer Policy: multiple Referrer-Policy headers with one invalid</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + + <script src="/common/security-features/resources/common.sub.js"></script> + </head> + <body> + <h1>Referrer Policy: multiple Referrer-Policy headers with one invalid</h1> + <p></p> + + <pre id="received_message">Running...</pre> + + <script> + promise_test(() => { + var urlPath = '/common/security-features/subresource/image.py?cache_destroyer=' + (new Date()).getTime(); + var url = location.protocol + "//www1." + location.hostname + ":" + location.port + + urlPath; + return requestViaImage(url, null, 'no-referrer') + .then(function(message) { + assert_equals(message.referrer, document.location.origin + "/"); + }); + }, "Image uses last recognized referrer policy token from Referrer-Policy headers"); + </script> + + <div id="log"></div> + </body> +</html> diff --git a/testing/web-platform/tests/referrer-policy/generic/multiple-headers-one-unknown-token.html.headers b/testing/web-platform/tests/referrer-policy/generic/multiple-headers-one-unknown-token.html.headers new file mode 100644 index 0000000000..46feffd705 --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/multiple-headers-one-unknown-token.html.headers @@ -0,0 +1,2 @@ +Referrer-Policy: no-referrer +Referrer-Policy: origin,not-a-valid-token diff --git a/testing/web-platform/tests/referrer-policy/generic/multiple-headers.html b/testing/web-platform/tests/referrer-policy/generic/multiple-headers.html new file mode 100644 index 0000000000..d6c3a90ccb --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/multiple-headers.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<html> + <head> + <title>Referrer Policy: multiple Referrer-Policy headers are allowed</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + + <script src="/common/security-features/resources/common.sub.js"></script> + </head> + <body> + <h1>Referrer Policy: multiple Referrer-Policy headers are allowed</h1> + <p></p> + + <pre id="received_message">Running...</pre> + + <script> + promise_test(() => { + var urlPath = '/common/security-features/subresource/image.py?cache_destroyer=' + (new Date()).getTime(); + var url = location.protocol + "//www1." + location.hostname + ":" + location.port + + urlPath; + return requestViaImage(url, null, 'no-referrer') + .then(function(message) { + assert_equals(message.referrer, document.location.origin + "/"); + }); + }, "Image uses the last recognized Referrer-Policy header"); + </script> + + <div id="log"></div> + </body> +</html> diff --git a/testing/web-platform/tests/referrer-policy/generic/multiple-headers.html.headers b/testing/web-platform/tests/referrer-policy/generic/multiple-headers.html.headers new file mode 100644 index 0000000000..dd1dd853f2 --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/multiple-headers.html.headers @@ -0,0 +1,2 @@ +Referrer-Policy: no-referrer +Referrer-Policy: origin diff --git a/testing/web-platform/tests/referrer-policy/generic/resources/img-with-referrer-policy.svg b/testing/web-platform/tests/referrer-policy/generic/resources/img-with-referrer-policy.svg new file mode 100644 index 0000000000..d54232d7bb --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/resources/img-with-referrer-policy.svg @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg width="100%" height="100%" version="1.1" +xmlns="http://www.w3.org/2000/svg"> + <meta xmlns="http://www.w3.org/1999/xhtml" name="referrer" content="unsafe-url"/> + <circle cx="10" cy="10" r="10" stroke="black" stroke-width="1" fill="red" /> +</svg>
\ No newline at end of file diff --git a/testing/web-platform/tests/referrer-policy/generic/resources/referrer.py b/testing/web-platform/tests/referrer-policy/generic/resources/referrer.py new file mode 100644 index 0000000000..2d15dc09c4 --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/resources/referrer.py @@ -0,0 +1,10 @@ +def main(request, response): + response_headers = [(b"Access-Control-Allow-Origin", b"*")] + body = b""" + <p id=referrer>%s</p> + <script> + const referrer_text = referrer.textContent; + window.parent.postMessage(referrer_text, "*"); + </script> + """ % request.headers.get(b"referer", b"") + return (200, response_headers, body) diff --git a/testing/web-platform/tests/referrer-policy/generic/sandboxed-iframe-with-opaque-origin.html b/testing/web-platform/tests/referrer-policy/generic/sandboxed-iframe-with-opaque-origin.html new file mode 100644 index 0000000000..fd1857e0dd --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/sandboxed-iframe-with-opaque-origin.html @@ -0,0 +1,93 @@ +<!DOCTYPE html> +<html> +<head> + <title>Referrer Policy: Sandboxed iframes with opaque origins don't send referrers</title> + <link rel="author" title="Jochen Eisinger" href="mailto:jochen@chromium.org"> + <link rel="author" title="Arthur Sonzogni" href="mailto:arthursonzogni@chromium.org"> + <link rel="help" href="https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <!-- Common global functions for referrer-policy tests. --> + <script src="/common/security-features/resources/common.sub.js"></script> + <script src="/common/get-host-info.sub.js"></script> +</head> +<body> +<h1> + Referrer Policy: A document with an opaque origin doesn't send referrers +</h1> +<script> + +let futureMessage = function() { + return new Promise(resolve => { + window.addEventListener("message", event => resolve(event.data)); + }); +} + +function testSandboxedIframeSubresource(description, + sandboxAttributes, + expectedReferrer) { + promise_test(async test => { + let resource_url = get_host_info().HTTP_NOTSAMESITE_ORIGIN + + "/common/security-features/subresource/xhr.py"; + const iframe = document.createElement("iframe"); + iframe.sandbox = sandboxAttributes; + iframe.srcdoc = ` + <meta name="referrer" content="always"> + <script src="/common/security-features/resources/common.sub.js"> + </scr`+`ipt> + <script> + requestViaFetch("${resource_url}").then((msg) => { + parent.postMessage(msg.referrer, '*'); + }).catch((e) => { + parent.postMessage("FAILURE", '*'); + }); + </scr`+`ipt> + `; + + const future_message = futureMessage(); + document.body.appendChild(iframe); + assert_equals(await future_message, expectedReferrer); + + }, description); +} + +function testSandboxedIframeMainResource(description, + sandboxAttributes, + expectedReferrer) { + promise_test(async test => { + let document_url = get_host_info().HTTP_NOTSAMESITE_ORIGIN + + "/referrer-policy/generic/resources/referrer.py"; + const iframe = document.createElement("iframe"); + iframe.sandbox = sandboxAttributes; + iframe.srcdoc = ` + <meta name="referrer" content="always"> + <script> + onload = () => { + location.href = "${document_url}"; + } + </scr`+`ipt> + `; + + const future_message = futureMessage(); + document.body.appendChild(iframe); + assert_equals(await future_message, expectedReferrer); + + }, description); +} + +testSandboxedIframeSubresource( + "Sandboxed iframe with opaque origin doesn't send referrers to subresources", + "allow-scripts", undefined); +testSandboxedIframeSubresource( + "Sandboxed iframe with tuple origin sends referrers to subresources", + "allow-same-origin allow-scripts", document.location.href); +testSandboxedIframeMainResource( + "Sandboxed iframe with opaque origin doesn't send referrers on navigation", + "allow-scripts", ""); +testSandboxedIframeMainResource( + "Sandboxed iframe with tuple origin sends referrers on navigation", + "allow-same-origin allow-scripts", document.location.href); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/referrer-policy/generic/sanity-checker.js b/testing/web-platform/tests/referrer-policy/generic/sanity-checker.js new file mode 100644 index 0000000000..e296ce93b9 --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/sanity-checker.js @@ -0,0 +1,46 @@ +// The SanityChecker is used in debug mode to identify problems with the +// structure of the testsuite. In release mode it is mocked out to do nothing. + +function SanityChecker() {} + +SanityChecker.prototype.checkScenario = function(scenario) { + // Check if scenario is valid. + // TODO(kristijanburnik): Move to a sanity-checks.js for debug mode only. + test(function() { + + // We extend the exsiting test_expansion_schema not to kill performance by + // copying. + var expectedFields = SPEC_JSON["test_expansion_schema"]; + expectedFields["referrer_policy"] = SPEC_JSON["referrer_policy_schema"]; + + for (var field in expectedFields) { + assert_own_property(scenario, field, + "The scenario contains field " + field) + assert_in_array(scenario[field], expectedFields[field], + "Scenario's " + field + " is one of: " + + expectedFields[field].join(", ")) + "." + } + + // Check if the protocol is matched. + assert_equals(scenario["source_protocol"] + ":", location.protocol, + "Protocol of the test page should match the scenario.") + + }, "[ReferrerPolicyTestCase] The test scenario is valid."); +} + +SanityChecker.prototype.checkSubresourceResult = function(scenario, + subresourceUrl, + result) { + assert_equals(Object.keys(result).length, 3); + assert_own_property(result, "location"); + assert_own_property(result, "referrer"); + assert_own_property(result, "headers"); + + // Skip location check for scripts. + if (scenario.subresource == "script-tag") + return; + + // Sanity check: location of sub-resource matches reported location. + assert_equals(result.location, subresourceUrl, + "Subresource reported location."); +}; diff --git a/testing/web-platform/tests/referrer-policy/generic/second-meta-referrer-added-before-first.http.html b/testing/web-platform/tests/referrer-policy/generic/second-meta-referrer-added-before-first.http.html new file mode 100644 index 0000000000..38fab901fb --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/second-meta-referrer-added-before-first.http.html @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<head> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + + <meta name="referrer" content="no-referrer" id="referrermeta"> +</head> +<body> + <script> + async function fetchAndGetReferrer() { + let response = await fetch('/common/security-features/subresource/xhr.py'); + let data = await response.json(); + return data.headers.referer; + } + + promise_test(async t => { + assert_equals(await fetchAndGetReferrer(), undefined, + 'referrer should not be set'); + + // Add second meta _before_ first meta. + const first_meta = document.getElementById('referrermeta'); + const second_meta = document.createElement('meta'); + second_meta.name = 'referrer'; + second_meta.content = 'strict-origin'; + document.head.insertBefore(second_meta, first_meta); + assert_equals(await fetchAndGetReferrer(), window.location.origin + '/', + 'referrer should the origin only'); + }, 'document referrer policy is the value of the most recently added <meta name="referrer">'); + + </script> +</body> diff --git a/testing/web-platform/tests/referrer-policy/generic/subresource-test/area-navigate.html b/testing/web-platform/tests/referrer-policy/generic/subresource-test/area-navigate.html new file mode 100644 index 0000000000..2a4f29654d --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/subresource-test/area-navigate.html @@ -0,0 +1,39 @@ +<!DOCTYPE html> +<!-- TODO(kristijanburnik): Remove subres. duplication. Reuse a template. --> +<html> + <head> + <title>Area Link messaging - cross-origin Area Link navigation</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <!-- Common global functions for referrer-policy tests. --> + <script src="/common/security-features/resources/common.sub.js"></script> + </head> + <body> + <h1>Area Link messaging - cross-origin Area Link navigation</h1> + <p>If you can read JSON encoded HTTP request headers of the Area link below, + the messaging works as expected.</p> + + <pre id="received_message">Running...</pre> + + <script> + promise_test(function() { + var urlPath = '/common/security-features/subresource/document.py'; + var url = location.protocol + "//www1." + location.hostname + ":" + location.port + + urlPath; + return requestViaArea(url) + .then(function(message) { + var pre = document.getElementById('received_message') + var headers = message.headers; + pre.innerHTML = ""; + pre.innerHTML += url + ":\n\n"; + pre.innerHTML += JSON.stringify(headers, null, 2) + "\n\n" + assert_own_property(headers, "host") + assert_own_property(headers, "connection") + }); + }, + "Area is responding with HTTP headers"); + </script> + + <div id="log"></div> + </body> +</html> diff --git a/testing/web-platform/tests/referrer-policy/generic/subresource-test/attr-referrer-invalid-value.html b/testing/web-platform/tests/referrer-policy/generic/subresource-test/attr-referrer-invalid-value.html new file mode 100644 index 0000000000..bfdf1166ce --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/subresource-test/attr-referrer-invalid-value.html @@ -0,0 +1,25 @@ +<!DOCTYPE html> +<html> + <head> + <title>Invalid referrerPolicy attribute value</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <h1>Invalid referrerPolicy attribute value</h1> + <pre>Running...</pre> + + <script> + test(function () { + var elements = ["iframe", "img", "a", "area", "link", "script"]; + for (var i = 0; i < elements.length; i++) { + var elem = document.createElement(elements[i]); + elem.referrerPolicy = "unsafe-url"; + assert_equals(elem.referrerPolicy, "unsafe-url"); + elem.referrerPolicy = "not-valid-value"; + assert_equals(elem.referrerPolicy, ""); + } + }, "Invalid referrerpolicy values not reflected"); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/referrer-policy/generic/subresource-test/fetch-messaging.html b/testing/web-platform/tests/referrer-policy/generic/subresource-test/fetch-messaging.html new file mode 100644 index 0000000000..2678af822e --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/subresource-test/fetch-messaging.html @@ -0,0 +1,42 @@ +<!DOCTYPE html> +<!-- TODO(kristijanburnik): Remove subres. duplication. Reuse a template. --> +<html> + <head> + <title>Fetch messaging - same-origin Fetch request</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <!-- Common global functions for referrer-policy tests. --> + <script src="/common/security-features/resources/common.sub.js"></script> + </head> + <body> + <h1>Fetch messaging - same-origin Fetch request</h1> + <p>If you can read JSON encoded HTTP request headers of the Fetch below, + the messaging works as expected.</p> + + <pre id="received_message">Running...</pre> + + <script> + test(function() { + assert_true(!!window.fetch, "Fetch is not supported by this browser."); + }, "Fetch is supported by the browser."); + + promise_test(function() { + var urlPath = '/common/security-features/subresource/xhr.py'; + var url = location.protocol + "//" + location.hostname + ":" + + location.port + urlPath; + return requestViaFetch(url) + .then(function(message) { + var pre = document.getElementById('received_message') + var headers = message.headers; + pre.innerHTML = ""; + pre.innerHTML += url + ":\n\n"; + pre.innerHTML += JSON.stringify(headers, null, 2) + "\n\n"; + assert_own_property(headers, "host") + assert_own_property(headers, "connection") + }); + }, "Fetch is responding with HTTP headers"); + </script> + + <div id="log"></div> + </body> +</html> diff --git a/testing/web-platform/tests/referrer-policy/generic/subresource-test/iframe-messaging.html b/testing/web-platform/tests/referrer-policy/generic/subresource-test/iframe-messaging.html new file mode 100644 index 0000000000..b8bdb0e5e0 --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/subresource-test/iframe-messaging.html @@ -0,0 +1,38 @@ +<!DOCTYPE html> +<!-- TODO(kristijanburnik): Remove subres. duplication. Reuse a template. --> +<html> + <head> + <title>Iframe messaging - cross-origin iframe request</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <!-- Common global functions for referrer-policy tests. --> + <script src="/common/security-features/resources/common.sub.js"></script> + </head> + <body> + <h1>Iframe messaging - cross-origin iframe request</h1> + <p>If you can read JSON encoded HTTP request headers of the iframe below, + the messaging works as expected.</p> + + <pre id="received_message">Running...</pre> + + <script> + promise_test(function() { + var urlPath = '/common/security-features/subresource/document.py'; + var url = location.protocol + "//www1." + location.hostname + ":" + location.port + + urlPath; + return requestViaIframe(url) + .then(function(message) { + var pre = document.getElementById('received_message') + var headers = message.headers; + pre.innerHTML = ""; + pre.innerHTML += url + ":\n\n"; + pre.innerHTML += JSON.stringify(headers, null, 2) + "\n\n" + assert_own_property(headers, "host") + assert_own_property(headers, "connection") + }); + }, "Iframe is responding with HTTP headers"); + </script> + + <div id="log"></div> + </body> +</html> diff --git a/testing/web-platform/tests/referrer-policy/generic/subresource-test/image-decoding.html b/testing/web-platform/tests/referrer-policy/generic/subresource-test/image-decoding.html new file mode 100644 index 0000000000..76ce0e263a --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/subresource-test/image-decoding.html @@ -0,0 +1,38 @@ +<!DOCTYPE html> +<!-- TODO(kristijanburnik): Remove subres. duplication. Reuse a template. --> +<html> + <head> + <title>Image decoding - cross-origin image request</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <!-- Common global functions for referrer-policy tests. --> + <script src="/common/security-features/resources/common.sub.js"></script> + </head> + <body> + <h1>Image decoding - cross-origin image request</h1> + <p>If you can read JSON encoded HTTP headers of the image below, + the decoding works as expected.</p> + + <pre id="received_message">Running...</pre> + + <script> + promise_test(function() { + var urlPath = '/common/security-features/subresource/image.py'; + var url = location.protocol + "//www1." + location.hostname + ":" + location.port + + urlPath + "?cache_destroyer=" + (new Date()).getTime(); + return requestViaImage(url, undefined, "always") + .then(function(message) { + var pre = document.getElementById('received_message') + var headers = message.headers; + pre.innerHTML = ""; + pre.innerHTML += url + ":\n\n"; + pre.innerHTML += JSON.stringify(headers, null, 2) + "\n\n" + assert_own_property(headers, "host") + assert_own_property(headers, "connection") + }); + }, "Image is encoding headers as JSON."); + </script> + + <div id="log"></div> + </body> +</html> diff --git a/testing/web-platform/tests/referrer-policy/generic/subresource-test/link-navigate.html b/testing/web-platform/tests/referrer-policy/generic/subresource-test/link-navigate.html new file mode 100644 index 0000000000..21783d3e31 --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/subresource-test/link-navigate.html @@ -0,0 +1,38 @@ +<!DOCTYPE html> +<!-- TODO(kristijanburnik): Remove subres. duplication. Reuse a template. --> +<html> + <head> + <title>Link messaging - cross-origin Link navigation</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <!-- Common global functions for referrer-policy tests. --> + <script src="/common/security-features/resources/common.sub.js"></script> + </head> + <body> + <h1>Link messaging - cross-origin Link navigation</h1> + <p>If you can read JSON encoded HTTP request headers of the Link below, + the messaging works as expected.</p> + + <pre id="received_message">Running...</pre> + + <script> + promise_test(function() { + var urlPath = '/common/security-features/subresource/document.py'; + var url = location.protocol + "//www1." + location.hostname + ":" + location.port + + urlPath; + return requestViaAnchor(url) + .then(function(message) { + var pre = document.getElementById('received_message') + var headers = message.headers; + pre.innerHTML = ""; + pre.innerHTML += url + ":\n\n"; + pre.innerHTML += JSON.stringify(headers, null, 2) + "\n\n" + assert_own_property(headers, "host") + assert_own_property(headers, "connection") + }); + }, "Link is responding with HTTP headers"); + </script> + + <div id="log"></div> + </body> +</html> diff --git a/testing/web-platform/tests/referrer-policy/generic/subresource-test/script-messaging.html b/testing/web-platform/tests/referrer-policy/generic/subresource-test/script-messaging.html new file mode 100644 index 0000000000..1bc0ba13ef --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/subresource-test/script-messaging.html @@ -0,0 +1,38 @@ +<!DOCTYPE html> +<!-- TODO(kristijanburnik): Remove subres. duplication. Reuse a template. --> +<html> + <head> + <title>Script messaging - cross-origin Script request</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <!-- Common global functions for referrer-policy tests. --> + <script src="/common/security-features/resources/common.sub.js"></script> + </head> + <body> + <h1>Script messaging - cross-origin Script request</h1> + <p>If you can read JSON encoded HTTP request headers of the Script below, + the messaging works as expected.</p> + + <pre id="received_message">Running...</pre> + + <script> + promise_test(function() { + var urlPath = '/common/security-features/subresource/script.py'; + var url = location.protocol + "//www1." + location.hostname + ":" + location.port + + urlPath; + return requestViaScript(url) + .then(function(message) { + var pre = document.getElementById('received_message') + var headers = message.headers; + pre.innerHTML = ""; + pre.innerHTML += url + ":\n\n"; + pre.innerHTML += JSON.stringify(headers, null, 2) + "\n\n" + assert_own_property(headers, "host") + assert_own_property(headers, "connection") + }); + }, "Script is responding with HTTP headers"); + </script> + + <div id="log"></div> + </body> +</html> diff --git a/testing/web-platform/tests/referrer-policy/generic/subresource-test/worker-messaging.html b/testing/web-platform/tests/referrer-policy/generic/subresource-test/worker-messaging.html new file mode 100644 index 0000000000..c2db8fe845 --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/subresource-test/worker-messaging.html @@ -0,0 +1,38 @@ +<!DOCTYPE html> +<!-- TODO(kristijanburnik): Remove subres. duplication. Reuse a template. --> +<html> + <head> + <title>Worker messaging - same-origin Worker request</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <!-- Common global functions for referrer-policy tests. --> + <script src="/common/security-features/resources/common.sub.js"></script> + </head> + <body> + <h1>Worker messaging - same-origin Worker request</h1> + <p>If you can read JSON encoded HTTP request headers of the Worker below, + the messaging works as expected.</p> + + <pre id="received_message">Running...</pre> + + <script> + promise_test(function() { + var urlPath = '/common/security-features/subresource/worker.py'; + var url = location.protocol + "//" + location.hostname + ":" + + location.port + urlPath; + return requestViaDedicatedWorker(url, {}) + .then(function(message) { + var pre = document.getElementById('received_message') + var headers = message.headers; + pre.innerHTML = ""; + pre.innerHTML += url + ":\n\n"; + pre.innerHTML += JSON.stringify(headers, null, 2) + "\n\n" + assert_own_property(headers, "host") + assert_own_property(headers, "connection") + }); + }, "Worker is responding with HTTP headers"); + </script> + + <div id="log"></div> + </body> +</html> diff --git a/testing/web-platform/tests/referrer-policy/generic/subresource-test/xhr-messaging.html b/testing/web-platform/tests/referrer-policy/generic/subresource-test/xhr-messaging.html new file mode 100644 index 0000000000..c1f89919ca --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/subresource-test/xhr-messaging.html @@ -0,0 +1,38 @@ +<!DOCTYPE html> +<!-- TODO(kristijanburnik): Remove subres. duplication. Reuse a template. --> +<html> + <head> + <title>XHR messaging - cross-origin XHR request</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <!-- Common global functions for referrer-policy tests. --> + <script src="/common/security-features/resources/common.sub.js"></script> + </head> + <body> + <h1>XHR messaging - cross-origin XHR request</h1> + <p>If you can read JSON encoded HTTP request headers of the XHR below, + the messaging works as expected.</p> + + <pre id="received_message">Running...</pre> + + <script> + promise_test(function() { + var urlPath = '/common/security-features/subresource/xhr.py'; + var url = location.protocol + "//www1." + location.hostname + ":" + location.port + + urlPath; + return requestViaXhr(url) + .then(function(message) { + var pre = document.getElementById('received_message') + var headers = message.headers; + pre.innerHTML = ""; + pre.innerHTML += url + ":\n\n"; + pre.innerHTML += JSON.stringify(headers, null, 2) + "\n\n" + assert_own_property(headers, "host") + assert_own_property(headers, "connection") + }); + }, "XHR is responding with HTTP headers"); + </script> + + <div id="log"></div> + </body> +</html> diff --git a/testing/web-platform/tests/referrer-policy/generic/test-case.sub.js b/testing/web-platform/tests/referrer-policy/generic/test-case.sub.js new file mode 100644 index 0000000000..717cd1a5e7 --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/test-case.sub.js @@ -0,0 +1,127 @@ +// https://w3c.github.io/webappsec-referrer-policy/#strip-url +function stripUrlForUseAsReferrer(url, originOnly) { + // Step 2. If url’s scheme is a local scheme, then return no referrer. + const parsedUrl = new URL(url); + + if (["about:", "blob:", "data:"].includes(parsedUrl.protocol)) + return undefined; + + // Step 3. Set url’s username to the empty string. + parsedUrl.username = ''; + + // Step 4. Set url’s password to null. + parsedUrl.password = ''; + + // Step 5. Set url’s fragment to null. + parsedUrl.hash = ''; + + // Step 6. If the origin-only flag is true, then: + if (originOnly) { + // Step 6.1. Set url’s path to null. + parsedUrl.pathname = ''; + // Step 6.2. Set url’s query to null. + parsedUrl.search = ''; + } + return parsedUrl.href; +} + +function invokeScenario(scenario) { + const urls = getRequestURLs( + scenario.subresource, + scenario.origin, + scenario.redirection); + /** @type {Subresource} */ + const subresource = { + subresourceType: scenario.subresource, + url: urls.testUrl, + policyDeliveries: scenario.subresource_policy_deliveries, + }; + + return invokeRequest(subresource, scenario.source_context_list); +} + +const referrerUrlResolver = { + // The spec allows UAs to "enforce arbitrary policy considerations in the + // interests of minimizing data leakage"; to start to vaguely approximate + // this, we allow stronger policies to be used instead of what's specificed. + "omitted": function(sourceUrl) { + return [undefined]; + }, + "origin": function(sourceUrl) { + return [stripUrlForUseAsReferrer(sourceUrl, true), + undefined]; + }, + "stripped-referrer": function(sourceUrl) { + return [stripUrlForUseAsReferrer(sourceUrl, false), + stripUrlForUseAsReferrer(sourceUrl, true), + undefined]; + } +}; + +function checkResult(scenario, expectation, result) { +// https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer + let referrerSource = result.sourceContextUrl; + const sentFromSrcdoc = scenario.source_context_list.length > 0 && + scenario.source_context_list[scenario.source_context_list.length - 1] + .sourceContextType === 'srcdoc'; + if (sentFromSrcdoc) { + // Step 3. While document is an iframe srcdoc document, let document be + // document's browsing context's browsing context container's node + // document. [spec text] + + // Workaround for srcdoc cases. Currently we only test <iframe srcdoc> + // inside the top-level Document, so |document| in the spec here is + // the top-level Document. + // This doesn't work if e.g. we test <iframe srcdoc> inside another + // external <iframe>. + referrerSource = location.toString(); + } + const possibleReferrerUrls = + referrerUrlResolver[expectation](referrerSource); + + // Check the reported URL. + assert_in_array(result.referrer, + possibleReferrerUrls, + "document.referrer"); + assert_in_array(result.headers.referer, + possibleReferrerUrls, + "HTTP Referer header"); +} + +function runLengthTest(scenario, urlLength, expectation, testDescription) { + // `Referer` headers with length over 4k are culled down to an origin, so, + // let's test around that boundary for tests that would otherwise return + // the complete URL. + history.pushState(null, null, "/"); + history.replaceState(null, null, + "A".repeat(urlLength - location.href.length)); + + promise_test(t => { + assert_equals(scenario.expectation, "stripped-referrer"); + // Only on top-level Window, due to navigations using `history`. + assert_equals(scenario.source_context_list.length, 0); + + return invokeScenario(scenario) + .then(result => checkResult(scenario, expectation, result)); + }, testDescription); +} + +function TestCase(scenarios, sanityChecker) { + function runTest(scenario) { + // This check is A NOOP in release. + sanityChecker.checkScenario(scenario); + + promise_test(_ => { + return invokeScenario(scenario) + .then(result => checkResult(scenario, scenario.expectation, result)); + }, scenario.test_description); + } + + function runTests() { + for (const scenario of scenarios) { + runTest(scenario); + } + } + + return {start: runTests}; +} diff --git a/testing/web-platform/tests/referrer-policy/generic/unsupported-csp-referrer-directive.html b/testing/web-platform/tests/referrer-policy/generic/unsupported-csp-referrer-directive.html new file mode 100644 index 0000000000..27a3a99113 --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/generic/unsupported-csp-referrer-directive.html @@ -0,0 +1,29 @@ +<!DOCTYPE html> +<html> + <head> + <title>Referrer Policy: CSP 'referrer' directive should not be supported</title> + <meta http-equiv="Content-Security-Policy" content="referrer no-referrer"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <!-- Common global functions for referrer-policy tests. --> + <script src="/common/security-features/resources/common.sub.js"></script> + </head> + <body> + <h1>Referrer Policy: CSP 'referrer' directive should not be supported</h1> + <p>CSP used to have a 'referrer' directive to set a Referrer Policy. This directive has been removed and should not be supported.</p> + + <pre id="received_message">Running...</pre> + + <script> + promise_test(function() { + var urlPath = '/common/security-features/subresource/image.py?cache_destroyer=' + (new Date()).getTime(); + return requestViaImage(urlPath, null, 'always') + .then(function(message) { + assert_equals(message.referrer, document.location.href); + }); + }, "Image has a referrer despite CSP 'referrer' directive"); + </script> + + <div id="log"></div> + </body> +</html> |