Skip to content
Permalink
Browse files
[Safari 16 regression] service worker download does not work in case …
…of preloads

https://bugs.webkit.org/show_bug.cgi?id=247885
rdar://problem/102312723

Reviewed by Alex Christensen and Geoffrey Garen.

When a fetch is converted to download and is served from a service worker that uses a preload, we should use that preload.

* LayoutTests/http/wpt/service-workers/fetch-service-worker-preload-use-download.https-expected.txt: Added.
* LayoutTests/http/wpt/service-workers/fetch-service-worker-preload-use-download.https.html: Added.
* LayoutTests/http/wpt/service-workers/fetch-service-worker-preload-use-download-and-clone.https-expected.txt: Added.
* LayoutTests/http/wpt/service-workers/fetch-service-worker-preload-use-download-and-clone.https.html: Added.
* LayoutTests/http/wpt/service-workers/fetch-service-worker-preload-worker.js:
(event.event.request.url.includes): Deleted.
* LayoutTests/platform/glib/TestExpectations:
* LayoutTests/platform/ios-wk2/http/wpt/service-workers/fetch-service-worker-preload-use-download-and-clone.https-expected.txt: Added.
* LayoutTests/platform/ios-wk2/http/wpt/service-workers/fetch-service-worker-preload-use-download.https-expected.txt: Added.
* Source/WebKit/NetworkProcess/ServiceWorker/ServiceWorkerFetchTask.cpp:
(WebKit::ServiceWorkerFetchTask::convertToDownload):

Canonical link: https://commits.webkit.org/256731@main
  • Loading branch information
youennf committed Nov 16, 2022
1 parent 8f48b85 commit daf8b0ba46a83dd93ba488b73557960e01e02c7a
Show file tree
Hide file tree
Showing 9 changed files with 173 additions and 2 deletions.
@@ -0,0 +1,5 @@
Download started.
Downloading URL with suggested filename "fetch-service-worker-preload-script.py.vcf"
Download size: 7.
Download completed.

@@ -0,0 +1,63 @@
<!doctype html>
<html>
<head>
<script src="/common/utils.js"></script>
<script src="resources/routines.js"></script>
</head>
<body>
<script>
if (window.testRunner) {
testRunner.dumpAsText();
testRunner.setShouldLogDownloadCallbacks(true);
testRunner.setShouldLogDownloadSize(true);
testRunner.waitUntilDownloadFinished();
testRunner.setShouldDownloadUndisplayableMIMETypes(true);
}

var activeWorker;
var uuid = token();
var url = "/WebKit/service-workers/resources/fetch-service-worker-preload-script.py?download=yes&token=" + uuid;
var frame;
const channel = new MessageChannel();

function waitUntilActivating()
{
return new Promise(resolve => {
channel.port2.onmessage = (event) => {
if (event.data === "activating")
resolve();
};
});
}

function triggerActivation()
{
activeWorker.postMessage("activate");
}

async function doTest() {
if (window.testRunner) {
testRunner.setUseSeparateServiceWorkerProcess(true);
await fetch("").then(() => { }, () => { });
}

const registration = await navigator.serviceWorker.register("/WebKit/service-workers/fetch-service-worker-preload-worker.js", { scope : url });
if (!registration.installing) {
registration.unregister();
registration = await navigator.serviceWorker.register("/WebKit/service-workers/fetch-service-worker-preload-worker.js", { scope : url });
}

activeWorker = registration.installing;
activeWorker.postMessage({ port: channel.port1 }, [channel.port1]);

await waitUntilActivating();
triggerActivation();
await registration.navigationPreload.enable();

// Download size should be size of "use-preload".
const promise = withIframe(url + "&promise=getCloneResponseFromNavigationPreload");
}
doTest();
</script>
</body>
</html>
@@ -0,0 +1,5 @@
Download started.
Downloading URL with suggested filename "fetch-service-worker-preload-script.py.vcf"
Download size: 7.
Download completed.

@@ -0,0 +1,63 @@
<!doctype html>
<html>
<head>
<script src="/common/utils.js"></script>
<script src="resources/routines.js"></script>
</head>
<body>
<script>
if (window.testRunner) {
testRunner.dumpAsText();
testRunner.setShouldLogDownloadCallbacks(true);
testRunner.setShouldLogDownloadSize(true);
testRunner.waitUntilDownloadFinished();
testRunner.setShouldDownloadUndisplayableMIMETypes(true);
}

var activeWorker;
var uuid = token();
var url = "/WebKit/service-workers/resources/fetch-service-worker-preload-script.py?download=yes&token=" + uuid;
var frame;
const channel = new MessageChannel();

function waitUntilActivating()
{
return new Promise(resolve => {
channel.port2.onmessage = (event) => {
if (event.data === "activating")
resolve();
};
});
}

function triggerActivation()
{
activeWorker.postMessage("activate");
}

async function doTest() {
if (window.testRunner) {
testRunner.setUseSeparateServiceWorkerProcess(true);
await fetch("").then(() => { }, () => { });
}

const registration = await navigator.serviceWorker.register("/WebKit/service-workers/fetch-service-worker-preload-worker.js", { scope : url });
if (!registration.installing) {
registration.unregister();
registration = await navigator.serviceWorker.register("/WebKit/service-workers/fetch-service-worker-preload-worker.js", { scope : url });
}

activeWorker = registration.installing;
activeWorker.postMessage({ port: channel.port1 }, [channel.port1]);

await waitUntilActivating();
triggerActivation();
await registration.navigationPreload.enable();

// Download size should be size of "use-preload".
const promise = withIframe(url + "&promise=getResponseFromNavigationPreload");
}
doTest();
</script>
</body>
</html>
@@ -22,13 +22,35 @@ onactivate = (event) => {
self.port.postMessage("activating");
}

self.addEventListener('fetch', (event) => {
self.addEventListener('fetch', async (event) => {
if (event.request.url.includes("no-fetch-event-handling"))
return;

if (event.request.url.includes("useNavigationPreloadPromise") && event.preloadResponse) {
event.respondWith(event.preloadResponse);
return;
}

if (event.request.url.includes("getResponseFromNavigationPreload") && event.preloadResponse) {
event.respondWith((async () => {
const response = await event.preloadResponse;
if (response)
return response;
return fetch(event.request);
})());
return;
}


if (event.request.url.includes("getCloneResponseFromNavigationPreload") && event.preloadResponse) {
event.respondWith((async () => {
const response = await event.preloadResponse;
if (response)
return response.clone();
return fetch(event.request);
})());
return;
}

event.respondWith(fetch(event.request));
});
@@ -1183,6 +1183,9 @@ webkit.org/b/177940 workers/wasm-hashset.html [ Skip ]
webkit.org/b/201981 http/wpt/service-workers/server-trust-evaluation.https.html [ Failure ]
webkit.org/b/201981 imported/w3c/web-platform-tests/service-workers/service-worker/fetch-canvas-tainting-image-cache.https.html [ Failure Pass ]

http/wpt/service-workers/fetch-service-worker-preload-use-download-and-clone.https.html [ Failure ]
http/wpt/service-workers/fetch-service-worker-preload-use-download.https.html [ Failure ]

webkit.org/b/238738 http/wpt/service-workers/navigate-iframes-window-client.https.html [ Failure ]
webkit.org/b/238738238738 imported/w3c/web-platform-tests/service-workers/service-worker/windowclient-navigate.https.html [ Failure ]

@@ -0,0 +1,5 @@
Download started.
Downloading URL with suggested filename "fetch-service-worker-preload-script.py"
Download size: 7.
Download completed.

@@ -0,0 +1,5 @@
Download started.
Downloading URL with suggested filename "fetch-service-worker-preload-script.py"
Download size: 7.
Download completed.

@@ -483,7 +483,7 @@ NetworkSession* ServiceWorkerFetchTask::session()

bool ServiceWorkerFetchTask::convertToDownload(DownloadManager& manager, DownloadID downloadID, const ResourceRequest& request, const ResourceResponse& response)
{
if (m_preloader && !m_preloader->isServiceWorkerNavigationPreloadEnabled())
if (m_preloader)
return m_preloader->convertToDownload(manager, downloadID, request, response);

auto* session = this->session();

0 comments on commit daf8b0b

Please sign in to comment.