Source code
Revision control
Copy as Markdown
Other Tools
Test Info:
- This WPT test may be referenced by the following Test IDs:
- /speculation-rules/prefetch/tentative/service-worker/basic.sub.https.html?origin=cross-site&sw=fetch-handler - WPT Dashboard Interop Dashboard
- /speculation-rules/prefetch/tentative/service-worker/basic.sub.https.html?origin=cross-site&sw=fetch-handler-to-fallback - WPT Dashboard Interop Dashboard
- /speculation-rules/prefetch/tentative/service-worker/basic.sub.https.html?origin=cross-site&sw=no-controller - WPT Dashboard Interop Dashboard
- /speculation-rules/prefetch/tentative/service-worker/basic.sub.https.html?origin=cross-site&sw=no-fetch-handler - WPT Dashboard Interop Dashboard
- /speculation-rules/prefetch/tentative/service-worker/basic.sub.https.html?origin=same-site&sw=fetch-handler - WPT Dashboard Interop Dashboard
- /speculation-rules/prefetch/tentative/service-worker/basic.sub.https.html?origin=same-site&sw=fetch-handler-modify-referrer - WPT Dashboard Interop Dashboard
- /speculation-rules/prefetch/tentative/service-worker/basic.sub.https.html?origin=same-site&sw=fetch-handler-modify-url - WPT Dashboard Interop Dashboard
- /speculation-rules/prefetch/tentative/service-worker/basic.sub.https.html?origin=same-site&sw=fetch-handler-to-fallback - WPT Dashboard Interop Dashboard
- /speculation-rules/prefetch/tentative/service-worker/basic.sub.https.html?origin=same-site&sw=no-controller - WPT Dashboard Interop Dashboard
- /speculation-rules/prefetch/tentative/service-worker/basic.sub.https.html?origin=same-site&sw=no-fetch-handler - WPT Dashboard Interop Dashboard
<!DOCTYPE html>
<meta name="timeout" content="long">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/utils.js"></script>
<script src="/common/dispatcher/dispatcher.js"></script>
<script src="../../../resources/utils.js"></script>
<script src="../../resources/utils.sub.js"></script>
<script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script>
<meta name="variant" content="?origin=same-site&sw=fetch-handler">
<meta name="variant" content="?origin=same-site&sw=fetch-handler-to-fallback">
<meta name="variant" content="?origin=same-site&sw=fetch-handler-modify-url">
<meta name="variant" content="?origin=same-site&sw=fetch-handler-modify-referrer">
<meta name="variant" content="?origin=same-site&sw=no-fetch-handler">
<meta name="variant" content="?origin=same-site&sw=no-controller">
<meta name="variant" content="?origin=cross-site&sw=fetch-handler">
<meta name="variant" content="?origin=cross-site&sw=fetch-handler-to-fallback">
<meta name="variant" content="?origin=cross-site&sw=no-fetch-handler">
<meta name="variant" content="?origin=cross-site&sw=no-controller">
<script>
setup(() => assertSpeculationRulesIsSupported());
// "same-origin", and add same-site cross-origin tests.
const originOption = new URL(location.href).searchParams.get('origin');
const swOption = new URL(location.href).searchParams.get('sw');
promise_test(async t => {
const hostname = originOption === 'cross-site' ? '{{hosts[alt][www]}}'
: undefined;
const win = await spawnWindow(t, { protocol: 'https', hostname: hostname });
const nextUrl = win.getExecutorURL({ executor: 'counting-executor.py', protocol: 'https', page: 2 });
const swUrl = new URL('../../resources/basic-service-worker.js?sw=' + swOption, location.href).href;
// Register a SW not controlling any pages below, just to confirm such
// unrelated SWs in the same-origin doesn't affect the behavior.
const reg_unrelated = await service_worker_unregister_and_register(
t, swUrl, nextUrl + '&unrelated');
await wait_for_state(t, reg_unrelated.installing, 'activated');
// Register a SW for `nextUrl`.
let sw;
if (swOption !== 'no-controller') {
const reg = await service_worker_unregister_and_register(
t, swUrl, nextUrl);
await wait_for_state(t, reg.installing, 'activated');
sw = reg.installing;
}
// Start speculation rules prefetch and navigate to the URL.
await win.forceSinglePrefetch(nextUrl);
await win.navigate(nextUrl);
const requestCount = await (await fetch(nextUrl + '&check')).json();
const headers = await win.execute_script(() => {
return requestHeaders;
}, []);
const controllerUrl = await win.execute_script(() => {
return navigator.serviceWorker.controller?.scriptURL;
}, []);
if (swOption === 'no-controller') {
assert_equals(controllerUrl, undefined);
} else {
// The navigated page should be controlled by the ServiceWorker,
// regardless of whether prefetch is performed/used.
assert_equals(controllerUrl, swUrl);
}
// Current Chromium's expected behavior:
// prefetch works when
// - there are no controlling service worker, or
// - same-site prefetches with controlling service worker.
if (swOption === 'no-controller' ||
(originOption === 'same-site' &&
(swOption === 'fetch-handler' ||
swOption === 'fetch-handler-to-fallback' ||
swOption === 'no-fetch-handler'))) {
assert_prefetched(headers, "Prefetched result should be served.");
assert_equals(requestCount.prefetch, 1,
'a prefetch request should be sent to the server.');
assert_equals(requestCount.nonPrefetch, 0,
'non-prefetch requests should not be sent to the server.');
assert_prefetched(headers, "Prefetched result should be served.");
} else if (originOption === 'same-site' &&
(swOption === 'fetch-handler-modify-url' ||
swOption === 'fetch-handler-modify-referrer')) {
// When the ServiceWorker modifies the prefetch request
// (`fetch-handler-modify-*` cases below), still prefetch can work and be
// served, but Sec-Purpose header is dropped
assert_prefetched_without_sec_purpose(headers,
"Prefetched result should be served without Sec-Purpose.");
// `requestCount` checks the Sec-Purpose header so the prefetch request
// without Sec-Prefetch is counted as nonPrefetch here.
assert_equals(requestCount.nonPrefetch, 1,
'a prefetch request without Sec-Purpose should be sent to the server.');
assert_equals(requestCount.prefetch, 0,
'Other requests with Sec-Prefetch should not be sent to the server.');
// Check the modified URL/referrer to check if the prefetched and
// ServiceWorker-modified response is actually served.
if (swOption === 'fetch-handler-modify-url') {
assert_equals(
await win.execute_script(() => { return requestUrl; }, []),
nextUrl + '&intercepted=true',
'URL should be modified by ServiceWorker');
}
if (swOption === 'fetch-handler-modify-referrer') {
assert_equals(
headers.referer,
new URL('/intercepted', location.href).href,
'Referrer should be modified by ServiceWorker');
}
} else {
assert_not_prefetched(headers, "Prefetched result should not be served.");
assert_equals(requestCount.nonPrefetch, 1,
'a non-prefetch request should be sent to the server.');
assert_equals(requestCount.prefetch, 0,
'prefetch requests should not be sent to the server.');
}
}, "Prefetch with ServiceWorker (" + swOption + ")");
</script>