Skip to content

Commit

Permalink
[WPT] Add tests for speculation-rules prefetch + ServiceWorker
Browse files Browse the repository at this point in the history
For testing the upcoming ServiceWorker + speculation rules prefetch
as well as regression testing for https://crbug.com/379076354.

Bug: 40947546, 379076354
Change-Id: I3863217f9a3dc2902201d74e354d6b99541ba2b0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6023660
Commit-Queue: Hiroshige Hayashizaki <[email protected]>
Reviewed-by: Kouhei Ueno <[email protected]>
Reviewed-by: Hiroki Nakagawa <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1387011}
  • Loading branch information
hiroshige-g authored and chromium-wpt-export-bot committed Nov 22, 2024
1 parent 9f7aaf0 commit 0dc40f3
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 0 deletions.
11 changes: 11 additions & 0 deletions speculation-rules/prefetch/resources/basic-service-worker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const swOption = new URL(location.href).searchParams.get('sw');

if (swOption !== 'no-fetch-handler') {
self.addEventListener('fetch', event => {
if (swOption === 'fetch-handler') {
event.respondWith(fetch(event.request));
} else {
// Do nothing to fallback to the network.
}
});
}
26 changes: 26 additions & 0 deletions speculation-rules/prefetch/resources/counting-executor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import json
import os.path
from wptserve.pipes import template

def main(request, response):
response.headers.set(b"Content-Type", b"text/html")
response.headers.set(b"Cache-Control", b"no-store")

uuid = request.GET[b"uuid"]
request_count = request.server.stash.take(uuid)
if request_count is None:
request_count = {"prefetch": 0, "nonPrefetch": 0}

if b"check" in request.GET:
response.content = json.dumps(request_count)
return

prefetch = request.headers.get(
"Sec-Purpose", b"").decode("utf-8").startswith("prefetch")

request_count["prefetch" if prefetch else "nonPrefetch"] += 1
request.server.stash.put(uuid, request_count)

response.content = template(
request,
open(os.path.join(os.path.dirname(__file__), "executor.sub.html"), "rb").read())
7 changes: 7 additions & 0 deletions speculation-rules/prefetch/tentative/service-worker/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
This directory contains tests for ServiceWorker + speculation rules prefetch
integration.
The details are still to be spec'ed, and the tests so far reflects the current
expectations of the ongoing Chromium's implementation.

- https://wicg.github.io/nav-speculation/prefetch.html#issue-1ea0021d
- https://crbug.com/40947546
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<!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=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());

const originOption = new URL(location.href).searchParams.get('origin');
const swOption = new URL(location.href).searchParams.get('sw');

promise_test(async t => {
// Current Chromium's expected behavior: prefetch only works when there
// are no controlling service worker.
const expectsPrefetch = swOption === 'no-controller';

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 = '../../resources/basic-service-worker.js?sw=' + swOption;

// 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;
}, []);

if (expectsPrefetch) {
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 {
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>

0 comments on commit 0dc40f3

Please sign in to comment.