SharedWorker: Add shared-worker-import-referrer.html WPT
This CL adds shared-worker-import-referrer.html for web-platform-test.
Bug: 824646
Change-Id: I3031e34f1181303f7a0455974b3c614340d939f8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2037275
Commit-Queue: Eriko Kurimoto <elkurin@google.com>
Reviewed-by: Hiroki Nakagawa <nhiroki@chromium.org>
Cr-Commit-Position: refs/heads/master@{#738474}
diff --git a/workers/modules/dedicated-worker-import-referrer.html b/workers/modules/dedicated-worker-import-referrer.html
index e13c0e2..32d3b3f 100644
--- a/workers/modules/dedicated-worker-import-referrer.html
+++ b/workers/modules/dedicated-worker-import-referrer.html
@@ -124,21 +124,21 @@
// using [Window]'s URL as the referrer.
import_referrer_test(
- { scriptURL: 'referrer-checker.py',
+ { scriptURL: 'postmessage-referrer-checker.py',
windowReferrerPolicy: 'no-referrer',
fetchType: 'top-level' },
'Same-origin top-level module script loading with "no-referrer" referrer ' +
'policy');
import_referrer_test(
- { scriptURL: 'referrer-checker.py',
+ { scriptURL: 'postmessage-referrer-checker.py',
windowReferrerPolicy: 'origin',
fetchType: 'top-level' },
'Same-origin top-level module script loading with "origin" referrer ' +
'policy');
import_referrer_test(
- { scriptURL: 'referrer-checker.py',
+ { scriptURL: 'postmessage-referrer-checker.py',
windowReferrerPolicy: 'same-origin',
fetchType: 'top-level' },
'Same-origin top-level module script loading with "same-origin" referrer ' +
diff --git a/workers/modules/resources/dynamic-import-remote-origin-referrer-checker-worker.sub.js b/workers/modules/resources/dynamic-import-remote-origin-referrer-checker-worker.sub.js
index e8f7b0a..3f281fa 100644
--- a/workers/modules/resources/dynamic-import-remote-origin-referrer-checker-worker.sub.js
+++ b/workers/modules/resources/dynamic-import-remote-origin-referrer-checker-worker.sub.js
@@ -1,3 +1,16 @@
// Import a remote origin script.
-import('https://{{domains[www1]}}:{{ports[https][0]}}/workers/modules/resources/referrer-checker.py')
- .catch(error => postMessage(`Import failed: ${error}`));
+const import_url = 'https://{{domains[www1]}}:{{ports[https][0]}}/workers/modules/resources/export-referrer-checker.py';
+if ('DedicatedWorkerGlobalScope' in self &&
+ self instanceof DedicatedWorkerGlobalScope) {
+ import(import_url)
+ .then(module => postMessage(module.referrer))
+ .catch(error => postMessage(`Import failed: ${error}`));
+} else if (
+ 'SharedWorkerGlobalScope' in self &&
+ self instanceof SharedWorkerGlobalScope) {
+ onconnect = e => {
+ import(import_url)
+ .then(module => e.ports[0].postMessage(module.referrer))
+ .catch(error => e.ports[0].postMessage(`Import failed: ${error}`));
+ };
+}
diff --git a/workers/modules/resources/dynamic-import-same-origin-referrer-checker-worker.js b/workers/modules/resources/dynamic-import-same-origin-referrer-checker-worker.js
index a1c4eea..56f8a6f 100644
--- a/workers/modules/resources/dynamic-import-same-origin-referrer-checker-worker.js
+++ b/workers/modules/resources/dynamic-import-same-origin-referrer-checker-worker.js
@@ -1,2 +1,15 @@
-import('./referrer-checker.py')
- .catch(error => postMessage(`Import failed: ${error}`));
+const import_url = './export-referrer-checker.py';
+if ('DedicatedWorkerGlobalScope' in self &&
+ self instanceof DedicatedWorkerGlobalScope) {
+ import(import_url)
+ .then(module => postMessage(module.referrer))
+ .catch(error => postMessage(`Import failed: ${error}`));
+} else if (
+ 'SharedWorkerGlobalScope' in self &&
+ self instanceof SharedWorkerGlobalScope) {
+ onconnect = e => {
+ import(import_url)
+ .then(module => e.ports[0].postMessage(module.referrer))
+ .catch(error => e.ports[0].postMessage(`Import failed: ${error}`));
+ };
+}
diff --git a/workers/modules/resources/referrer-checker.py b/workers/modules/resources/export-referrer-checker.py
similarity index 84%
rename from workers/modules/resources/referrer-checker.py
rename to workers/modules/resources/export-referrer-checker.py
index 83a9003..2928d28 100644
--- a/workers/modules/resources/referrer-checker.py
+++ b/workers/modules/resources/export-referrer-checker.py
@@ -6,4 +6,4 @@
("Access-Control-Allow-Origin", "*")]
return (200, response_headers,
- "postMessage('"+referrer+"')")
+ "export const referrer = '"+referrer+"';")
diff --git a/workers/modules/resources/new-shared-worker-window.html b/workers/modules/resources/new-shared-worker-window.html
new file mode 100644
index 0000000..a7fee4d
--- /dev/null
+++ b/workers/modules/resources/new-shared-worker-window.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<title>SharedWorker: new SharedWorker()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+let worker;
+
+// Create a new shared worker for a given script url.
+window.onmessage = e => {
+ worker = new SharedWorker(e.data, { type: 'module' });
+ worker.port.onmessage = msg => window.opener.postMessage(msg.data, '*');
+ worker.onerror = err => {
+ window.opener.postMessage(['ERROR'], '*');
+ err.preventDefault();
+ };
+}
+window.opener.postMessage('LOADED', '*');
+</script>
diff --git a/workers/modules/resources/postmessage-referrer-checker.py b/workers/modules/resources/postmessage-referrer-checker.py
new file mode 100644
index 0000000..f926834
--- /dev/null
+++ b/workers/modules/resources/postmessage-referrer-checker.py
@@ -0,0 +1,16 @@
+# Returns a worker script that posts the request's referrer header.
+def main(request, response):
+ referrer = request.headers.get("referer", "")
+
+ response_headers = [("Content-Type", "text/javascript"),
+ ("Access-Control-Allow-Origin", "*")]
+
+ return (200, response_headers,
+ "if ('DedicatedWorkerGlobalScope' in self &&" +
+ " self instanceof DedicatedWorkerGlobalScope) {" +
+ " postMessage('"+referrer+"');" +
+ "} else if (" +
+ " 'SharedWorkerGlobalScope' in self &&" +
+ " self instanceof SharedWorkerGlobalScope) {" +
+ " onconnect = e => e.ports[0].postMessage('"+referrer+"');" +
+ "}")
diff --git a/workers/modules/resources/static-import-remote-origin-referrer-checker-worker.sub.js b/workers/modules/resources/static-import-remote-origin-referrer-checker-worker.sub.js
index 1722fc9..45fc549 100644
--- a/workers/modules/resources/static-import-remote-origin-referrer-checker-worker.sub.js
+++ b/workers/modules/resources/static-import-remote-origin-referrer-checker-worker.sub.js
@@ -1,2 +1,12 @@
// Import a remote origin script.
-import 'https://{{domains[www1]}}:{{ports[https][0]}}/workers/modules/resources/referrer-checker.py';
+import * as module from 'https://{{domains[www1]}}:{{ports[https][0]}}/workers/modules/resources/export-referrer-checker.py';
+if ('DedicatedWorkerGlobalScope' in self &&
+ self instanceof DedicatedWorkerGlobalScope) {
+ postMessage(module.referrer);
+} else if (
+ 'SharedWorkerGlobalScope' in self &&
+ self instanceof SharedWorkerGlobalScope) {
+ onconnect = e => {
+ e.ports[0].postMessage(module.referrer);
+ };
+}
diff --git a/workers/modules/resources/static-import-same-origin-referrer-checker-worker.js b/workers/modules/resources/static-import-same-origin-referrer-checker-worker.js
index 7d564f9..ffcab9e 100644
--- a/workers/modules/resources/static-import-same-origin-referrer-checker-worker.js
+++ b/workers/modules/resources/static-import-same-origin-referrer-checker-worker.js
@@ -1 +1,11 @@
-import './referrer-checker.py';
+import * as module from './export-referrer-checker.py';
+if ('DedicatedWorkerGlobalScope' in self &&
+ self instanceof DedicatedWorkerGlobalScope) {
+ postMessage(module.referrer);
+} else if (
+ 'SharedWorkerGlobalScope' in self &&
+ self instanceof SharedWorkerGlobalScope) {
+ onconnect = e => {
+ e.ports[0].postMessage(module.referrer);
+ };
+}
diff --git a/workers/modules/shared-worker-import-referrer.html b/workers/modules/shared-worker-import-referrer.html
new file mode 100644
index 0000000..abd4b41
--- /dev/null
+++ b/workers/modules/shared-worker-import-referrer.html
@@ -0,0 +1,245 @@
+<!DOCTYPE html>
+<title>SharedWorker: Referrer</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+
+async function openWindow(url) {
+ const win = window.open(url, '_blank');
+ add_result_callback(() => win.close());
+ const msg_event = await new Promise(resolve => window.onmessage = resolve);
+ assert_equals(msg_event.data, 'LOADED');
+ return win;
+}
+
+// Removes URL parameters from the given URL string and returns it.
+function removeParams(url_string) {
+ if (!url_string)
+ return url_string;
+ let url = new URL(url_string);
+ for (var key of url.searchParams.keys())
+ url.searchParams.delete(key);
+ return url.href;
+}
+
+// Generates a referrer given a fetchType, referrer policy, and a request URL
+// (used to determine whether request is remote-origin or not). This function
+// is used to generate expected referrers.
+function generateExpectedReferrer(referrerURL, referrerPolicy, requestURL) {
+ let generatedReferrer = "";
+ if (referrerPolicy === 'no-referrer')
+ generatedReferrer = "";
+ else if (referrerPolicy === 'origin')
+ generatedReferrer = new URL('resources/' + referrerURL, location.href).origin + '/';
+ else if (referrerPolicy === 'same-origin')
+ generatedReferrer = requestURL.includes('remote') ? "" : new URL('resources/' + referrerURL, location.href).href;
+ else
+ generatedReferrer = new URL('resources/' + referrerURL, location.href).href;
+
+ return generatedReferrer;
+}
+
+// Runs a referrer policy test with the given settings. This opens a new window
+// that starts a shared worker.
+//
+// |settings| has options as follows:
+//
+// settings = {
+// scriptURL: 'resources/referrer-checker.sub.js',
+// windowReferrerPolicy: 'no-referrer',
+// workerReferrerPolicy: 'same-origin',
+// fetchType: 'top-level' or 'descendant-static' or 'descendant-dynamic'
+// };
+//
+// - |scriptURL| is used for starting a new worker.
+// - |windowReferrerPolicy| is to set the ReferrerPolicy HTTP header of the
+// window. This policy should be applied to top-level worker module script
+// loading and static imports.
+// - |workerReferrerPolicy| is to set the ReferrerPolicy HTTP header of the
+// worker. This policy should be applied to dynamic imports.
+// - |fetchType| indicates a script whose referrer will be tested.
+function import_referrer_test(settings, description) {
+ promise_test(async () => {
+ let windowURL = 'resources/new-shared-worker-window.html';
+ if (settings.windowReferrerPolicy) {
+ windowURL +=
+ `?pipe=header(Referrer-Policy, ${settings.windowReferrerPolicy})`;
+ }
+
+ let scriptURL = settings.scriptURL;
+ if (settings.workerReferrerPolicy) {
+ // 'sub' is necessary even if the |scriptURL| contains the '.sub'
+ // extension because the extension doesn't work with the 'pipe' parameter.
+ // See an issue on the WPT's repository:
+ // https://github.com/web-platform-tests/wpt/issues/9345
+ scriptURL +=
+ `?pipe=sub|header(Referrer-Policy, ${settings.workerReferrerPolicy})`;
+ }
+
+ const win = await openWindow(windowURL);
+ win.postMessage(scriptURL, '*');
+ const msgEvent = await new Promise(resolve => window.onmessage = resolve);
+
+ // Generate the expected referrer, given:
+ // - The fetchType of the test
+ // - Referrer URL to be used
+ // - Relevant referrer policy
+ // - Request URL
+ let expectedReferrer;
+ if (settings.fetchType === 'top-level') {
+ // Top-level worker requests have their outgoing referrers set given their
+ // containing window's URL and referrer policy.
+ expectedReferrer = generateExpectedReferrer('new-shared-worker-window.html', settings.windowReferrerPolicy, settings.scriptURL);
+ } else if (settings.fetchType === 'descendant-static') {
+ // Static descendant script requests from a worker have their outgoing
+ // referrer set given their containing script's URL and containing
+ // window's referrer policy.
+
+ // In the below cases, the referrer URL and the request URLs are the same
+ // because the initial request (for the top-level worker script) should
+ // act as the referrer for future descendant requests.
+ expectedReferrer = generateExpectedReferrer(settings.scriptURL, settings.windowReferrerPolicy, settings.scriptURL);
+ } else if (settings.fetchType === 'descendant-dynamic') {
+ // Dynamic descendant script requests from a worker have their outgoing
+ // referrer set given their containing script's URL and referrer policy.
+ expectedReferrer = generateExpectedReferrer(settings.scriptURL, settings.workerReferrerPolicy, settings.scriptURL);
+ }
+
+ // Delete query parameters from the actual referrer to make it easy to match
+ // it with the expected referrer.
+ const actualReferrer = removeParams(msgEvent.data);
+
+ assert_equals(actualReferrer, expectedReferrer);
+ }, description);
+}
+
+// Tests for top-level worker module script loading.
+//
+// Top-level worker module scripts should inherit the containing window's
+// referrer policy when using the containing window's URL as the referrer.
+//
+// [Current document]
+// --(open)--> [Window] whose referrer policy is |windowReferrerPolicy|.
+// --(new SharedWorker)--> [SharedWorker] should respect [windowReferrerPolicy|
+// when using [Window]'s URL as the referrer.
+
+import_referrer_test(
+ { scriptURL: 'postmessage-referrer-checker.py',
+ windowReferrerPolicy: 'no-referrer',
+ fetchType: 'top-level' },
+ 'Same-origin top-level module script loading with "no-referrer" referrer ' +
+ 'policy');
+
+import_referrer_test(
+ { scriptURL: 'postmessage-referrer-checker.py',
+ windowReferrerPolicy: 'origin',
+ fetchType: 'top-level' },
+ 'Same-origin top-level module script loading with "origin" referrer ' +
+ 'policy');
+
+import_referrer_test(
+ { scriptURL: 'postmessage-referrer-checker.py',
+ windowReferrerPolicy: 'same-origin',
+ fetchType: 'top-level' },
+ 'Same-origin top-level module script loading with "same-origin" referrer ' +
+ 'policy');
+
+// Tests for static imports.
+//
+// Static imports should inherit the containing window's referrer policy when
+// using the containing module script's URL as the referrer.
+// Note: This is subject to change in the future; see
+// https://github.com/w3c/webappsec-referrer-policy/issues/111.
+//
+// [Current document]
+// --(open)--> [Window] whose referrer policy is |windowReferrerPolicy|.
+// --(new SharedWorker)--> [SharedWorker]
+// --(static import)--> [Script] should respect |windowReferrerPolicy| when
+// using [SharedWorker]'s URL as the referrer.
+
+import_referrer_test(
+ { scriptURL: 'static-import-same-origin-referrer-checker-worker.js',
+ windowReferrerPolicy: 'no-referrer',
+ fetchType: 'descendant-static' },
+ 'Same-origin static import with "no-referrer" referrer policy.');
+
+import_referrer_test(
+ { scriptURL: 'static-import-same-origin-referrer-checker-worker.js',
+ windowReferrerPolicy: 'origin',
+ fetchType: 'descendant-static' },
+ 'Same-origin static import with "origin" referrer policy.');
+
+import_referrer_test(
+ { scriptURL: 'static-import-same-origin-referrer-checker-worker.js',
+ windowReferrerPolicy: 'same-origin',
+ fetchType: 'descendant-static' },
+ 'Same-origin static import with "same-origin" referrer policy.');
+
+import_referrer_test(
+ { scriptURL: 'static-import-remote-origin-referrer-checker-worker.sub.js',
+ windowReferrerPolicy: 'no-referrer',
+ fetchType: 'descendant-static' },
+ 'Cross-origin static import with "no-referrer" referrer policy.');
+
+import_referrer_test(
+ { scriptURL: 'static-import-remote-origin-referrer-checker-worker.sub.js',
+ windowReferrerPolicy: 'origin',
+ fetchType: 'descendant-static' },
+ 'Cross-origin static import with "origin" referrer policy.');
+
+import_referrer_test(
+ { scriptURL: 'static-import-remote-origin-referrer-checker-worker.sub.js',
+ windowReferrerPolicy: 'same-origin',
+ fetchType: 'descendant-static' },
+ 'Cross-origin static import with "same-origin" referrer policy.');
+
+// Tests for dynamic imports.
+//
+// Dynamic imports should inherit the containing script's referrer policy if
+// set, and use the default referrer policy otherwise, when using the
+// containing script's URL as the referrer.
+//
+// [Current document]
+// --(open)--> [Window]
+// --(new SharedWorker)--> [SharedWorker] whose referrer policy is
+// |workerReferrerPolicy|.
+// --(dynamic import)--> [Script] should respect |workerReferrerPolicy| when
+// using [SharedWorker]'s URL as the referrer.
+
+import_referrer_test(
+ { scriptURL: 'dynamic-import-same-origin-referrer-checker-worker.js',
+ workerReferrerPolicy: 'no-referrer',
+ fetchType: 'descendant-dynamic' },
+ 'Same-origin dynamic import with "no-referrer" referrer policy.');
+
+import_referrer_test(
+ { scriptURL: 'dynamic-import-same-origin-referrer-checker-worker.js',
+ workerReferrerPolicy: 'origin',
+ fetchType: 'descendant-dynamic' },
+ 'Same-origin dynamic import with "origin" referrer policy.');
+
+import_referrer_test(
+ { scriptURL: 'dynamic-import-same-origin-referrer-checker-worker.js',
+ workerReferrerPolicy: 'same-origin',
+ fetchType: 'descendant-dynamic' },
+ 'Same-origin dynamic import with "same-origin" referrer policy.');
+
+import_referrer_test(
+ { scriptURL: 'dynamic-import-remote-origin-referrer-checker-worker.sub.js',
+ workerReferrerPolicy: 'no-referrer',
+ fetchType: 'descendant-dynamic' },
+ 'Cross-origin dynamic import with "no-referrer" referrer policy.');
+
+import_referrer_test(
+ { scriptURL: 'dynamic-import-remote-origin-referrer-checker-worker.sub.js',
+ workerReferrerPolicy: 'origin',
+ fetchType: 'descendant-dynamic' },
+ 'Cross-origin dynamic import with "origin" referrer policy.');
+
+import_referrer_test(
+ { scriptURL: 'dynamic-import-remote-origin-referrer-checker-worker.sub.js',
+ workerReferrerPolicy: 'same-origin',
+ fetchType: 'descendant-dynamic' },
+ 'Cross-origin dynamic import with "same-origin" referrer policy.');
+
+</script>