Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test has a WPT meta file that expects 3 subtest issues.
- This WPT test may be referenced by the following Test IDs:
- /connection-allowlist/tentative/shared-worker.sub.window.html - WPT Dashboard Interop Dashboard
// META: script=/common/get-host-info.sub.js
//
// The following tests assume the policy `Connection-Allowlist: (response-origin)` has been set.
const port = get_host_info().HTTP_PORT_ELIDED;
const SUCCESS = true;
const FAILURE = false;
// The worker content will attempt to fetch a URL and post the result back.
const worker_content = `
importScripts("${get_host_info().HTTP_ORIGIN}/connection-allowlist/tentative/resources/shared-worker-onconnect.js");
`;
const dataUrl = "data:text/javascript," + encodeURIComponent(worker_content);
function worker_fetch_test(origin, expectation, description) {
promise_test(async t => {
const worker = new SharedWorker(dataUrl);
const fetch_url = `${origin}/common/blank-with-cors.html`;
worker.port.postMessage(fetch_url);
const msgEvent = await new Promise((resolve, reject) => {
worker.port.onmessage = resolve;
worker.onerror = (e) => reject(new Error("Worker Error"));
});
if (expectation === SUCCESS) {
assert_true(msgEvent.data.success, `Fetch to ${origin} should succeed.`);
} else {
assert_false(msgEvent.data.success, `Fetch to ${origin} should be blocked.`);
}
}, description);
}
// 1. Same-origin fetch from the worker should succeed as it is allowlisted via (response-origin).
worker_fetch_test(
"http://{{hosts[][]}}" + port,
SUCCESS,
"Same-origin fetch from a shared worker (data: URL) succeeds."
);
// 2. Cross-origin fetch from the worker should be blocked as it is not allowlisted.
worker_fetch_test(
"http://{{hosts[alt][]}}" + port,
FAILURE,
"Cross-origin fetch from a shared worker (data: URL) should be blocked by inherited policy."
);
function worker_script_fetch_test(origin, expectation, description) {
promise_test(async t => {
const script_url = `${origin}/connection-allowlist/tentative/resources/shared-worker-fetch-script.js`;
let worker;
try {
worker = new SharedWorker(script_url);
} catch (e) {
assert_equals(expectation, FAILURE, "SharedWorker constructor threw unexpectedly");
return;
}
const promise = new Promise((resolve, reject) => {
worker.port.onmessage = () => resolve(SUCCESS);
worker.onerror = (e) => {
e.preventDefault();
reject(new Error("Worker Load Error"));
};
// Send a message to the worker. If it loaded successfully, it will
// respond and onmessage will fire. If it failed to load, onerror
// should fire.
worker.port.postMessage(`${get_host_info().HTTP_ORIGIN}/common/blank-with-cors.html`);
});
if (expectation === SUCCESS) {
const result = await promise;
assert_equals(result, expectation, description);
} else {
await promise_rejects_js(t, Error, promise, description);
}
}, description);
}
// 3. Same-origin main script fetch should succeed.
worker_script_fetch_test(
get_host_info().HTTP_ORIGIN,
SUCCESS,
"Same-origin shared worker main script fetch succeeds."
);
// 4. Cross-origin main script fetch should be blocked by the creator's policy.
worker_script_fetch_test(
get_host_info().HTTP_REMOTE_ORIGIN,
FAILURE,
"Cross-origin shared worker main script fetch should be blocked by creator policy."
);
// 5. Worker script with empty connection allowlist should not be able to fetch anything.
promise_test(async t => {
const script_url = "resources/shared-worker-fetch-script-empty.js";
const worker = new SharedWorker(script_url);
const fetch_url = `${get_host_info().HTTP_ORIGIN}/common/blank-with-cors.html`;
worker.port.postMessage(fetch_url);
const msgEvent = await new Promise((resolve, reject) => {
worker.port.onmessage = resolve;
worker.onerror = (e) => reject(new Error("Worker Error"));
});
assert_false(msgEvent.data.success, "Fetch from worker with empty allowlist should be blocked.");
}, "Shared worker with empty connection allowlist cannot perform any fetches.");
// 6. Same-origin fetch from a shared worker (blob: URL) should succeed.
promise_test(async t => {
const blob = new Blob([worker_content], {type: 'text/javascript'});
const blobUrl = URL.createObjectURL(blob);
t.add_cleanup(() => URL.revokeObjectURL(blobUrl));
const worker = new SharedWorker(blobUrl);
const fetch_url = `${get_host_info().HTTP_ORIGIN}/common/blank-with-cors.html`;
worker.port.postMessage(fetch_url);
const msgEvent = await new Promise((resolve, reject) => {
worker.port.onmessage = resolve;
worker.onerror = (e) => reject(new Error("Worker Error"));
});
assert_true(msgEvent.data.success, "Same-origin fetch from a shared worker (blob: URL) should succeed.");
}, "Same-origin fetch from a shared worker (blob: URL) succeeds.");
// 7. Shared worker (blob: URL) inherits creator's connection allowlist policy.
promise_test(async t => {
const blob = new Blob([worker_content], {type: 'text/javascript'});
const blobUrl = URL.createObjectURL(blob);
t.add_cleanup(() => URL.revokeObjectURL(blobUrl));
const worker = new SharedWorker(blobUrl);
const cross_origin = "http://{{hosts[alt][]}}" + port;
const fetch_url = `${cross_origin}/common/blank-with-cors.html`;
worker.port.postMessage(fetch_url);
const msgEvent = await new Promise((resolve, reject) => {
worker.port.onmessage = resolve;
worker.onerror = (e) => reject(new Error("Worker Error"));
});
assert_false(msgEvent.data.success, "Cross-origin fetch from a shared worker (blob: URL) should be blocked by inherited policy.");
}, "Shared worker (blob: URL) inherits creator's connection allowlist policy.");