Title: [286361] trunk
Revision
286361
Author
[email protected]
Date
2021-12-01 05:36:58 -0800 (Wed, 01 Dec 2021)

Log Message

Reuse navigation preload if service worker is fetching the corresponding navigation request
https://bugs.webkit.org/show_bug.cgi?id=233490

Reviewed by Chris Dumez.

Source/WebCore:

Store the fetch identifier in FetchRequest as this might be used as the navigation preload identifier.
We set it when creating a FetchRequest for firing a fetch event.
This identifier is kept in case of request cloning or when creating a request as part of calling fetch.
It is used to set the navigationPreloadIdentifier in ResourceLoaderOptions that is piped to WebLoaderStrategy.

Test: http/wpt/service-workers/fetch-service-worker-preload.https.html

* Modules/fetch/FetchLoader.cpp:
* Modules/fetch/FetchRequest.cpp:
* Modules/fetch/FetchRequest.h:
* loader/ResourceLoaderOptions.h:
* loader/ThreadableLoader.cpp:
* workers/service/context/ServiceWorkerFetch.cpp:
* workers/service/context/ServiceWorkerFetch.h:
* workers/service/context/ServiceWorkerThread.cpp:
* workers/service/context/ServiceWorkerThread.h:
* workers/service/context/ServiceWorkerThreadProxy.cpp:

Source/WebKit:

Store navigation preloader in NetworkSession, keyed by the corresponding fetch identifier.
When a navigation request is coming from fetch with the corresponding navigation preload identifier
we look at ongoing preloads and use it if available to answer the fetch.
To do so, we create a new ServiceWorkerFetchTask that will take the preloader of the initial ServiceWorkerFetchTask.

* NetworkProcess/NetworkResourceLoadParameters.cpp:
* NetworkProcess/NetworkResourceLoadParameters.h:
* NetworkProcess/NetworkSession.cpp:
* NetworkProcess/NetworkSession.h:
* NetworkProcess/ServiceWorker/ServiceWorkerFetchTask.cpp:
* NetworkProcess/ServiceWorker/ServiceWorkerFetchTask.h:
* NetworkProcess/ServiceWorker/WebSWServerConnection.cpp:
* WebProcess/Network/WebLoaderStrategy.cpp:

LayoutTests:

* http/wpt/service-workers/fetch-service-worker-preload-worker.js: Added.
* http/wpt/service-workers/fetch-service-worker-preload.https-expected.txt: Added.
* http/wpt/service-workers/fetch-service-worker-preload.https.html: Added.
* http/wpt/service-workers/resources/fetch-service-worker-preload-script.py: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (286360 => 286361)


--- trunk/LayoutTests/ChangeLog	2021-12-01 12:45:42 UTC (rev 286360)
+++ trunk/LayoutTests/ChangeLog	2021-12-01 13:36:58 UTC (rev 286361)
@@ -1,3 +1,15 @@
+2021-12-01  Youenn Fablet  <[email protected]>
+
+        Reuse navigation preload if service worker is fetching the corresponding navigation request
+        https://bugs.webkit.org/show_bug.cgi?id=233490
+
+        Reviewed by Chris Dumez.
+
+        * http/wpt/service-workers/fetch-service-worker-preload-worker.js: Added.
+        * http/wpt/service-workers/fetch-service-worker-preload.https-expected.txt: Added.
+        * http/wpt/service-workers/fetch-service-worker-preload.https.html: Added.
+        * http/wpt/service-workers/resources/fetch-service-worker-preload-script.py: Added.
+
 2021-11-30  Robert Jenner  <[email protected]>
 
         REBASELINE [ Monterey ]fast/css/continuationCrash.html (layout-test) is a constant text failure

Added: trunk/LayoutTests/http/wpt/service-workers/fetch-service-worker-preload-worker.js (0 => 286361)


--- trunk/LayoutTests/http/wpt/service-workers/fetch-service-worker-preload-worker.js	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/service-workers/fetch-service-worker-preload-worker.js	2021-12-01 13:36:58 UTC (rev 286361)
@@ -0,0 +1,27 @@
+_oninstall_ = (event) => {
+    if (self.port)
+        return;
+    event.waitUntil(new Promise(resolve => self.installingPromiseResolve = resolve));
+}
+
+_onmessage_ = (event) => {
+    if (event.data.port)
+        self.port = event.data.port;
+    if (self.installingPromiseResolve) {
+        self.installingPromiseResolve();
+        self.installingPromiseResolve = null;
+    }
+    if (self.activatingPromiseResolve) {
+        self.activatingPromiseResolve();
+        self.activatingPromiseResolve = null;
+    }
+};
+
+_onactivate_ = (event) => {
+    event.waitUntil(new Promise(resolve => self.activatingPromiseResolve = resolve));
+    self.port.postMessage("activating");
+}
+
+self.addEventListener('fetch', (event) => {
+    event.respondWith(fetch(event.request));
+});

Added: trunk/LayoutTests/http/wpt/service-workers/fetch-service-worker-preload.https-expected.txt (0 => 286361)


--- trunk/LayoutTests/http/wpt/service-workers/fetch-service-worker-preload.https-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/service-workers/fetch-service-worker-preload.https-expected.txt	2021-12-01 13:36:58 UTC (rev 286361)
@@ -0,0 +1,5 @@
+
+
+PASS Setup activating worker
+PASS Service worker load uses preload through calling fetch on the fetch event request
+

Added: trunk/LayoutTests/http/wpt/service-workers/fetch-service-worker-preload.https.html (0 => 286361)


--- trunk/LayoutTests/http/wpt/service-workers/fetch-service-worker-preload.https.html	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/service-workers/fetch-service-worker-preload.https.html	2021-12-01 13:36:58 UTC (rev 286361)
@@ -0,0 +1,67 @@
+<!doctype html>
+<html>
+<head>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+</head>
+<body>
+<script>
+var activeWorker;
+var uuid = token();
+var url = "" + 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");
+}
+
+promise_test(async (test) => {
+    if (window.testRunner) {
+        testRunner.setUseSeparateServiceWorkerProcess(true);
+        await fetch("").then(() => { }, () => { });
+    }
+
+    let 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]);
+
+    return waitUntilActivating();
+}, "Setup activating worker");
+
+promise_test(async (test) => {
+    fetch(url + "&value=use-preload", { method: 'POST' });
+
+    // Load iframe, with activating worker, so only preload will start.
+    const promise = withIframe(url);
+
+    triggerActivation();
+
+    const frame = await promise;
+    assert_equals(frame.contentWindow.value, "use-preload");
+
+    // We should have only one GET fetch to url: the service worker preload
+    const response = await fetch(url + "&count=True");
+    assert_equals(await response.text(), "1");
+}, "Service worker load uses preload through calling fetch on the fetch event request");
+</script>
+</body>
+</html>

Added: trunk/LayoutTests/http/wpt/service-workers/resources/fetch-service-worker-preload-script.py (0 => 286361)


--- trunk/LayoutTests/http/wpt/service-workers/resources/fetch-service-worker-preload-script.py	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/service-workers/resources/fetch-service-worker-preload-script.py	2021-12-01 13:36:58 UTC (rev 286361)
@@ -0,0 +1,35 @@
+import os
+import hashlib
+import json
+
+
+def main(request, response):
+    token = request.GET[b'token']
+    testId = hashlib.md5(token).hexdigest()
+    countId = hashlib.md5(token + b'-count').hexdigest()
+
+    if request.method == "POST":
+        request.server.stash.take(testId)
+        request.server.stash.put(testId, request.GET[b'value'])
+        response.headers.set(b"Content-Type", b"text/ascii")
+        return b"updated to " + request.GET[b'value']
+
+    if request.GET.first(b"count", False):
+        count = request.server.stash.take(countId)
+        if not count:
+            count = 0
+        response.headers.set(b"Content-Type", b"text/ascii")
+        return str(count)
+
+    count = request.server.stash.take(countId)
+    if not count:
+        count = 0
+    count = count + 1
+    request.server.stash.put(countId, count)
+
+    value = request.server.stash.take(testId)
+    if not value:
+        value = b"nothing"
+    response.headers.set(b"Cache-Control", b"no-cache")
+    response.headers.set(b"Content-Type", b"text/html")
+    return "<html><body><script>window.value = '%s';</script></body></html>" % value.decode()

Modified: trunk/Source/WebCore/ChangeLog (286360 => 286361)


--- trunk/Source/WebCore/ChangeLog	2021-12-01 12:45:42 UTC (rev 286360)
+++ trunk/Source/WebCore/ChangeLog	2021-12-01 13:36:58 UTC (rev 286361)
@@ -1,3 +1,28 @@
+2021-12-01  Youenn Fablet  <[email protected]>
+
+        Reuse navigation preload if service worker is fetching the corresponding navigation request
+        https://bugs.webkit.org/show_bug.cgi?id=233490
+
+        Reviewed by Chris Dumez.
+
+        Store the fetch identifier in FetchRequest as this might be used as the navigation preload identifier.
+        We set it when creating a FetchRequest for firing a fetch event.
+        This identifier is kept in case of request cloning or when creating a request as part of calling fetch.
+        It is used to set the navigationPreloadIdentifier in ResourceLoaderOptions that is piped to WebLoaderStrategy.
+
+        Test: http/wpt/service-workers/fetch-service-worker-preload.https.html
+
+        * Modules/fetch/FetchLoader.cpp:
+        * Modules/fetch/FetchRequest.cpp:
+        * Modules/fetch/FetchRequest.h:
+        * loader/ResourceLoaderOptions.h:
+        * loader/ThreadableLoader.cpp:
+        * workers/service/context/ServiceWorkerFetch.cpp:
+        * workers/service/context/ServiceWorkerFetch.h:
+        * workers/service/context/ServiceWorkerThread.cpp:
+        * workers/service/context/ServiceWorkerThread.h:
+        * workers/service/context/ServiceWorkerThreadProxy.cpp:
+
 2021-12-01  Enrique Ocaña González  <[email protected]>
 
         [MSE][WPE] Parameterize maximum buffer size using the MSE_MAX_BUFFER_SIZE env var

Modified: trunk/Source/WebCore/Modules/fetch/FetchLoader.cpp (286360 => 286361)


--- trunk/Source/WebCore/Modules/fetch/FetchLoader.cpp	2021-12-01 12:45:42 UTC (rev 286360)
+++ trunk/Source/WebCore/Modules/fetch/FetchLoader.cpp	2021-12-01 13:36:58 UTC (rev 286361)
@@ -94,6 +94,7 @@
     options.sendLoadCallbacks = SendCallbackPolicy::SendCallbacks;
     options.dataBufferingPolicy = DataBufferingPolicy::DoNotBufferData;
     options.sameOriginDataURLFlag = SameOriginDataURLFlag::Set;
+    options.navigationPreloadIdentifier = request.navigationPreloadIdentifier();
 
     ResourceRequest fetchRequest = request.resourceRequest();
 

Modified: trunk/Source/WebCore/Modules/fetch/FetchRequest.cpp (286360 => 286361)


--- trunk/Source/WebCore/Modules/fetch/FetchRequest.cpp	2021-12-01 12:45:42 UTC (rev 286360)
+++ trunk/Source/WebCore/Modules/fetch/FetchRequest.cpp	2021-12-01 13:36:58 UTC (rev 286361)
@@ -170,7 +170,6 @@
     m_options.credentials = Credentials::SameOrigin;
     m_referrer = "client"_s;
     m_request.setURL(requestURL);
-    m_request.setRequester(ResourceRequest::Requester::Fetch);
     m_request.setInitiatorIdentifier(scriptExecutionContext()->resourceRequestIdentifier());
 
     auto optionsResult = initializeOptions(init);
@@ -205,6 +204,8 @@
 ExceptionOr<void> FetchRequest::initializeWith(FetchRequest& input, Init&& init)
 {
     m_request = input.m_request;
+    m_navigationPreloadIdentifier = input.navigationPreloadIdentifier();
+
     m_options = input.m_options;
     m_referrer = input.m_referrer;
 
@@ -322,8 +323,9 @@
     if (isDisturbedOrLocked())
         return Exception { TypeError, "Body is disturbed or locked"_s };
 
-    auto clone = adoptRef(*new FetchRequest(context, std::nullopt, FetchHeaders::create(m_headers.get()), ResourceRequest { m_request }, FetchOptions { m_options}, String { m_referrer }));
+    auto clone = adoptRef(*new FetchRequest(context, std::nullopt, FetchHeaders::create(m_headers.get()), ResourceRequest { m_request }, FetchOptions { m_options }, String { m_referrer }));
     clone->cloneBody(*this);
+    clone->setNavigationPreloadIdentifier(m_navigationPreloadIdentifier);
     clone->m_signal->signalFollow(m_signal);
     return clone;
 }

Modified: trunk/Source/WebCore/Modules/fetch/FetchRequest.h (286360 => 286361)


--- trunk/Source/WebCore/Modules/fetch/FetchRequest.h	2021-12-01 12:45:42 UTC (rev 286360)
+++ trunk/Source/WebCore/Modules/fetch/FetchRequest.h	2021-12-01 13:36:58 UTC (rev 286361)
@@ -31,6 +31,7 @@
 #include "AbortSignal.h"
 #include "ExceptionOr.h"
 #include "FetchBodyOwner.h"
+#include "FetchIdentifier.h"
 #include "FetchOptions.h"
 #include "FetchRequestInit.h"
 #include "ResourceRequest.h"
@@ -80,6 +81,8 @@
     const URL& url() const { return m_request.url(); }
 
     ResourceRequest resourceRequest() const;
+    FetchIdentifier navigationPreloadIdentifier() const { return m_navigationPreloadIdentifier; }
+    void setNavigationPreloadIdentifier(FetchIdentifier identifier) { m_navigationPreloadIdentifier = identifier; }
 
 private:
     FetchRequest(ScriptExecutionContext&, std::optional<FetchBody>&&, Ref<FetchHeaders>&&, ResourceRequest&&, FetchOptions&&, String&& referrer);
@@ -97,6 +100,7 @@
     String m_referrer;
     mutable String m_requestURL;
     Ref<AbortSignal> m_signal;
+    FetchIdentifier m_navigationPreloadIdentifier;
 };
 
 inline FetchRequest::FetchRequest(ScriptExecutionContext& context, std::optional<FetchBody>&& body, Ref<FetchHeaders>&& headers, ResourceRequest&& request, FetchOptions&& options, String&& referrer)
@@ -106,6 +110,7 @@
     , m_referrer(WTFMove(referrer))
     , m_signal(AbortSignal::create(context))
 {
+    m_request.setRequester(ResourceRequest::Requester::Fetch);
     updateContentType();
 }
 

Modified: trunk/Source/WebCore/loader/ResourceLoaderOptions.h (286360 => 286361)


--- trunk/Source/WebCore/loader/ResourceLoaderOptions.h	2021-12-01 12:45:42 UTC (rev 286360)
+++ trunk/Source/WebCore/loader/ResourceLoaderOptions.h	2021-12-01 13:36:58 UTC (rev 286361)
@@ -33,6 +33,7 @@
 #include "ContentSecurityPolicyResponseHeaders.h"
 #include "CrossOriginAccessControl.h"
 #include "CrossOriginEmbedderPolicy.h"
+#include "FetchIdentifier.h"
 #include "FetchOptions.h"
 #include "HTTPHeaderNames.h"
 #include "ServiceWorkerTypes.h"
@@ -204,6 +205,7 @@
     std::optional<CrossOriginEmbedderPolicy> crossOriginEmbedderPolicy;
     OptionSet<HTTPHeadersToKeepFromCleaning> httpHeadersToKeep;
     uint8_t maxRedirectCount { 20 };
+    FetchIdentifier navigationPreloadIdentifier;
 
     SendCallbackPolicy sendLoadCallbacks : bitWidthOfSendCallbackPolicy;
     ContentSniffingPolicy sniffContent : bitWidthOfContentSniffingPolicy;

Modified: trunk/Source/WebCore/loader/ThreadableLoader.cpp (286360 => 286361)


--- trunk/Source/WebCore/loader/ThreadableLoader.cpp	2021-12-01 12:45:42 UTC (rev 286360)
+++ trunk/Source/WebCore/loader/ThreadableLoader.cpp	2021-12-01 13:36:58 UTC (rev 286361)
@@ -91,6 +91,7 @@
     copy.clientCredentialPolicy = this->clientCredentialPolicy;
     copy.maxRedirectCount = this->maxRedirectCount;
     copy.preflightPolicy = this->preflightPolicy;
+    copy.navigationPreloadIdentifier = this->navigationPreloadIdentifier;
 
     // ThreadableLoaderOptions
     copy.contentSecurityPolicyEnforcement = this->contentSecurityPolicyEnforcement;

Modified: trunk/Source/WebCore/workers/service/context/ServiceWorkerFetch.cpp (286360 => 286361)


--- trunk/Source/WebCore/workers/service/context/ServiceWorkerFetch.cpp	2021-12-01 12:45:42 UTC (rev 286360)
+++ trunk/Source/WebCore/workers/service/context/ServiceWorkerFetch.cpp	2021-12-01 13:36:58 UTC (rev 286361)
@@ -139,7 +139,7 @@
     });
 }
 
-void dispatchFetchEvent(Ref<Client>&& client, ServiceWorkerGlobalScope& globalScope, std::optional<ScriptExecutionContextIdentifier> clientId, ResourceRequest&& request, String&& referrer, FetchOptions&& options)
+void dispatchFetchEvent(Ref<Client>&& client, ServiceWorkerGlobalScope& globalScope, std::optional<ScriptExecutionContextIdentifier> clientId, ResourceRequest&& request, String&& referrer, FetchOptions&& options, FetchIdentifier fetchIdentifier)
 {
     auto requestHeaders = FetchHeaders::create(FetchHeaders::Guard::Immutable, HTTPHeaderMap { request.httpHeaderFields() });
 
@@ -167,6 +167,7 @@
 
     URL requestURL = request.url();
     auto fetchRequest = FetchRequest::create(globalScope, WTFMove(body), WTFMove(requestHeaders),  WTFMove(request), WTFMove(options), WTFMove(referrer));
+    fetchRequest->setNavigationPreloadIdentifier(fetchIdentifier);
 
     FetchEvent::Init init;
     init.request = WTFMove(fetchRequest);

Modified: trunk/Source/WebCore/workers/service/context/ServiceWorkerFetch.h (286360 => 286361)


--- trunk/Source/WebCore/workers/service/context/ServiceWorkerFetch.h	2021-12-01 12:45:42 UTC (rev 286360)
+++ trunk/Source/WebCore/workers/service/context/ServiceWorkerFetch.h	2021-12-01 13:36:58 UTC (rev 286361)
@@ -59,7 +59,7 @@
     virtual void continueDidReceiveResponse() = 0;
 };
 
-void dispatchFetchEvent(Ref<Client>&&, ServiceWorkerGlobalScope&, std::optional<ScriptExecutionContextIdentifier>, ResourceRequest&&, String&& referrer, FetchOptions&&);
+void dispatchFetchEvent(Ref<Client>&&, ServiceWorkerGlobalScope&, std::optional<ScriptExecutionContextIdentifier>, ResourceRequest&&, String&& referrer, FetchOptions&&, FetchIdentifier);
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/workers/service/context/ServiceWorkerThread.cpp (286360 => 286361)


--- trunk/Source/WebCore/workers/service/context/ServiceWorkerThread.cpp	2021-12-01 12:45:42 UTC (rev 286360)
+++ trunk/Source/WebCore/workers/service/context/ServiceWorkerThread.cpp	2021-12-01 13:36:58 UTC (rev 286361)
@@ -124,11 +124,11 @@
     WorkerThread::runEventLoop();
 }
 
-void ServiceWorkerThread::queueTaskToFireFetchEvent(Ref<ServiceWorkerFetch::Client>&& client, std::optional<ScriptExecutionContextIdentifier>&& clientId, ResourceRequest&& request, String&& referrer, FetchOptions&& options)
+void ServiceWorkerThread::queueTaskToFireFetchEvent(Ref<ServiceWorkerFetch::Client>&& client, std::optional<ScriptExecutionContextIdentifier>&& clientId, ResourceRequest&& request, String&& referrer, FetchOptions&& options, FetchIdentifier fetchIdentifier)
 {
     Ref serviceWorkerGlobalScope = downcast<ServiceWorkerGlobalScope>(*globalScope());
-    serviceWorkerGlobalScope->eventLoop().queueTask(TaskSource::DOMManipulation, [serviceWorkerGlobalScope, client = WTFMove(client), clientId, request = WTFMove(request), referrer = WTFMove(referrer), options = WTFMove(options)]() mutable {
-        ServiceWorkerFetch::dispatchFetchEvent(WTFMove(client), serviceWorkerGlobalScope, clientId, WTFMove(request), WTFMove(referrer), WTFMove(options));
+    serviceWorkerGlobalScope->eventLoop().queueTask(TaskSource::DOMManipulation, [serviceWorkerGlobalScope, client = WTFMove(client), clientId, request = WTFMove(request), referrer = WTFMove(referrer), options = WTFMove(options), fetchIdentifier]() mutable {
+        ServiceWorkerFetch::dispatchFetchEvent(WTFMove(client), serviceWorkerGlobalScope, clientId, WTFMove(request), WTFMove(referrer), WTFMove(options), fetchIdentifier);
     });
 }
 

Modified: trunk/Source/WebCore/workers/service/context/ServiceWorkerThread.h (286360 => 286361)


--- trunk/Source/WebCore/workers/service/context/ServiceWorkerThread.h	2021-12-01 12:45:42 UTC (rev 286360)
+++ trunk/Source/WebCore/workers/service/context/ServiceWorkerThread.h	2021-12-01 13:36:58 UTC (rev 286361)
@@ -64,7 +64,7 @@
     void willPostTaskToFireMessageEvent();
     void willPostTaskToFirePushSubscriptionChangeEvent();
 
-    void queueTaskToFireFetchEvent(Ref<ServiceWorkerFetch::Client>&&, std::optional<ScriptExecutionContextIdentifier>&&, ResourceRequest&&, String&& referrer, FetchOptions&&);
+    void queueTaskToFireFetchEvent(Ref<ServiceWorkerFetch::Client>&&, std::optional<ScriptExecutionContextIdentifier>&&, ResourceRequest&&, String&& referrer, FetchOptions&&, FetchIdentifier);
     void queueTaskToPostMessage(MessageWithMessagePorts&&, ServiceWorkerOrClientData&& sourceData);
     void queueTaskToFireInstallEvent();
     void queueTaskToFireActivateEvent();

Modified: trunk/Source/WebCore/workers/service/context/ServiceWorkerThreadProxy.cpp (286360 => 286361)


--- trunk/Source/WebCore/workers/service/context/ServiceWorkerThreadProxy.cpp	2021-12-01 12:45:42 UTC (rev 286360)
+++ trunk/Source/WebCore/workers/service/context/ServiceWorkerThreadProxy.cpp	2021-12-01 13:36:58 UTC (rev 286361)
@@ -221,8 +221,8 @@
 
     ASSERT(!m_ongoingFetchTasks.contains(key));
     m_ongoingFetchTasks.add(key, client.copyRef());
-    postTaskForModeToWorkerOrWorkletGlobalScope([this, protectedThis = Ref { *this }, client = WTFMove(client), clientId, request = request.isolatedCopy(), referrer = referrer.isolatedCopy(), options = options.isolatedCopy()](auto&) mutable {
-        thread().queueTaskToFireFetchEvent(WTFMove(client), WTFMove(clientId), WTFMove(request), WTFMove(referrer), WTFMove(options));
+    postTaskForModeToWorkerOrWorkletGlobalScope([this, protectedThis = Ref { *this }, client = WTFMove(client), clientId, request = request.isolatedCopy(), referrer = referrer.isolatedCopy(), options = options.isolatedCopy(), fetchIdentifier](auto&) mutable {
+        thread().queueTaskToFireFetchEvent(WTFMove(client), WTFMove(clientId), WTFMove(request), WTFMove(referrer), WTFMove(options), fetchIdentifier);
     }, WorkerRunLoop::defaultMode());
 }
 

Modified: trunk/Source/WebKit/ChangeLog (286360 => 286361)


--- trunk/Source/WebKit/ChangeLog	2021-12-01 12:45:42 UTC (rev 286360)
+++ trunk/Source/WebKit/ChangeLog	2021-12-01 13:36:58 UTC (rev 286361)
@@ -1,5 +1,26 @@
 2021-12-01  Youenn Fablet  <[email protected]>
 
+        Reuse navigation preload if service worker is fetching the corresponding navigation request
+        https://bugs.webkit.org/show_bug.cgi?id=233490
+
+        Reviewed by Chris Dumez.
+
+        Store navigation preloader in NetworkSession, keyed by the corresponding fetch identifier.
+        When a navigation request is coming from fetch with the corresponding navigation preload identifier
+        we look at ongoing preloads and use it if available to answer the fetch.
+        To do so, we create a new ServiceWorkerFetchTask that will take the preloader of the initial ServiceWorkerFetchTask.
+
+        * NetworkProcess/NetworkResourceLoadParameters.cpp:
+        * NetworkProcess/NetworkResourceLoadParameters.h:
+        * NetworkProcess/NetworkSession.cpp:
+        * NetworkProcess/NetworkSession.h:
+        * NetworkProcess/ServiceWorker/ServiceWorkerFetchTask.cpp:
+        * NetworkProcess/ServiceWorker/ServiceWorkerFetchTask.h:
+        * NetworkProcess/ServiceWorker/WebSWServerConnection.cpp:
+        * WebProcess/Network/WebLoaderStrategy.cpp:
+
+2021-12-01  Youenn Fablet  <[email protected]>
+
         WebSWServerConnection::createFetchTask does not need to query twice for a registration
         https://bugs.webkit.org/show_bug.cgi?id=233467
 

Modified: trunk/Source/WebKit/NetworkProcess/NetworkResourceLoadParameters.cpp (286360 => 286361)


--- trunk/Source/WebKit/NetworkProcess/NetworkResourceLoadParameters.cpp	2021-12-01 12:45:42 UTC (rev 286360)
+++ trunk/Source/WebKit/NetworkProcess/NetworkResourceLoadParameters.cpp	2021-12-01 13:36:58 UTC (rev 286361)
@@ -128,6 +128,7 @@
     encoder << serviceWorkersMode;
     encoder << serviceWorkerRegistrationIdentifier;
     encoder << httpHeadersToKeep;
+    encoder << navigationPreloadIdentifier;
 #endif
 
 #if ENABLE(CONTENT_EXTENSIONS)
@@ -362,6 +363,12 @@
     if (!httpHeadersToKeep)
         return std::nullopt;
     result.httpHeadersToKeep = WTFMove(*httpHeadersToKeep);
+
+    std::optional<std::optional<FetchIdentifier>> navigationPreloadIdentifier;
+    decoder >> navigationPreloadIdentifier;
+    if (!navigationPreloadIdentifier)
+        return std::nullopt;
+    result.navigationPreloadIdentifier = *navigationPreloadIdentifier;
 #endif
 
 #if ENABLE(CONTENT_EXTENSIONS)

Modified: trunk/Source/WebKit/NetworkProcess/NetworkResourceLoadParameters.h (286360 => 286361)


--- trunk/Source/WebKit/NetworkProcess/NetworkResourceLoadParameters.h	2021-12-01 12:45:42 UTC (rev 286360)
+++ trunk/Source/WebKit/NetworkProcess/NetworkResourceLoadParameters.h	2021-12-01 13:36:58 UTC (rev 286361)
@@ -77,11 +77,12 @@
     WebCore::CrossOriginOpenerPolicy sourceCrossOriginOpenerPolicy;
     uint64_t navigationID { 0 };
     std::optional<WebCore::NavigationRequester> navigationRequester;
-    
+
 #if ENABLE(SERVICE_WORKER)
     WebCore::ServiceWorkersMode serviceWorkersMode { WebCore::ServiceWorkersMode::None };
     std::optional<WebCore::ServiceWorkerRegistrationIdentifier> serviceWorkerRegistrationIdentifier;
     OptionSet<WebCore::HTTPHeadersToKeepFromCleaning> httpHeadersToKeep;
+    std::optional<WebCore::FetchIdentifier> navigationPreloadIdentifier;
 #endif
 
 #if ENABLE(CONTENT_EXTENSIONS)

Modified: trunk/Source/WebKit/NetworkProcess/NetworkSession.cpp (286360 => 286361)


--- trunk/Source/WebKit/NetworkProcess/NetworkSession.cpp	2021-12-01 12:45:42 UTC (rev 286360)
+++ trunk/Source/WebKit/NetworkProcess/NetworkSession.cpp	2021-12-01 13:36:58 UTC (rev 286361)
@@ -39,6 +39,7 @@
 #include "PrivateClickMeasurementClientImpl.h"
 #include "PrivateClickMeasurementManager.h"
 #include "PrivateClickMeasurementManagerProxy.h"
+#include "ServiceWorkerFetchTask.h"
 #include "WebPageProxy.h"
 #include "WebPageProxyMessages.h"
 #include "WebProcessProxy.h"
@@ -546,4 +547,21 @@
     return m_attributedBundleIdentifierFromPageIdentifiers.get(identifier);
 }
 
+#if ENABLE(SERVICE_WORKER)
+void NetworkSession::addNavigationPreloaderTask(ServiceWorkerFetchTask& task)
+{
+    m_navigationPreloaders.add(task.fetchIdentifier(), task);
+}
+
+void NetworkSession::removeNavigationPreloaderTask(ServiceWorkerFetchTask& task)
+{
+    m_navigationPreloaders.remove(task.fetchIdentifier());
+}
+
+ServiceWorkerFetchTask* NetworkSession::navigationPreloaderTaskFromFetchIdentifier(FetchIdentifier identifier)
+{
+    return m_navigationPreloaders.get(identifier).get();
+}
+#endif
+
 } // namespace WebKit

Modified: trunk/Source/WebKit/NetworkProcess/NetworkSession.h (286360 => 286361)


--- trunk/Source/WebKit/NetworkProcess/NetworkSession.h	2021-12-01 12:45:42 UTC (rev 286360)
+++ trunk/Source/WebKit/NetworkProcess/NetworkSession.h	2021-12-01 13:36:58 UTC (rev 286361)
@@ -36,6 +36,7 @@
 #include "WebPageProxyIdentifier.h"
 #include "WebResourceLoadStatisticsStore.h"
 #include <WebCore/BlobRegistryImpl.h>
+#include <WebCore/FetchIdentifier.h>
 #include <WebCore/NetworkStorageSession.h>
 #include <WebCore/PrivateClickMeasurement.h>
 #include <WebCore/RegistrableDomain.h>
@@ -65,6 +66,7 @@
 class NetworkResourceLoader;
 class NetworkBroadcastChannelRegistry;
 class NetworkSocketChannel;
+class ServiceWorkerFetchTask;
 class WebPageNetworkParameters;
 class WebResourceLoadStatisticsStore;
 class WebSocketTask;
@@ -175,6 +177,9 @@
 #if ENABLE(SERVICE_WORKER)
     void addSoftUpdateLoader(std::unique_ptr<ServiceWorkerSoftUpdateLoader>&& loader) { m_softUpdateLoaders.add(WTFMove(loader)); }
     void removeSoftUpdateLoader(ServiceWorkerSoftUpdateLoader* loader) { m_softUpdateLoaders.remove(loader); }
+    void addNavigationPreloaderTask(ServiceWorkerFetchTask&);
+    ServiceWorkerFetchTask* navigationPreloaderTaskFromFetchIdentifier(WebCore::FetchIdentifier);
+    void removeNavigationPreloaderTask(ServiceWorkerFetchTask&);
 #endif
 
     NetworkLoadScheduler& networkLoadScheduler();
@@ -258,8 +263,9 @@
 
 #if ENABLE(SERVICE_WORKER)
     HashSet<std::unique_ptr<ServiceWorkerSoftUpdateLoader>> m_softUpdateLoaders;
+    HashMap<WebCore::FetchIdentifier, WeakPtr<ServiceWorkerFetchTask>> m_navigationPreloaders;
 #endif
-    
+
 #if PLATFORM(COCOA)
     AppPrivacyReportTestingData m_appPrivacyReportTestingData;
 #endif

Modified: trunk/Source/WebKit/NetworkProcess/ServiceWorker/ServiceWorkerFetchTask.cpp (286360 => 286361)


--- trunk/Source/WebKit/NetworkProcess/ServiceWorker/ServiceWorkerFetchTask.cpp	2021-12-01 12:45:42 UTC (rev 286360)
+++ trunk/Source/WebKit/NetworkProcess/ServiceWorker/ServiceWorkerFetchTask.cpp	2021-12-01 13:36:58 UTC (rev 286361)
@@ -33,6 +33,7 @@
 #include "Logging.h"
 #include "NetworkProcess.h"
 #include "NetworkResourceLoader.h"
+#include "NetworkSession.h"
 #include "ServiceWorkerNavigationPreloader.h"
 #include "SharedBufferDataReference.h"
 #include "WebCoreArgumentCoders.h"
@@ -50,6 +51,28 @@
 
 using namespace WebCore;
 
+std::unique_ptr<ServiceWorkerFetchTask> ServiceWorkerFetchTask::fromNavigationPreloader(WebSWServerConnection& swServerConnection, NetworkResourceLoader& loader, const WebCore::ResourceRequest& request, NetworkSession* session)
+{
+    if (!loader.parameters().navigationPreloadIdentifier)
+        return nullptr;
+
+    auto task = session ? session->navigationPreloaderTaskFromFetchIdentifier(*loader.parameters().navigationPreloadIdentifier) : nullptr;
+    if (!task || !task->m_preloader || task->m_isLoadingFromPreloader)
+        return nullptr;
+
+    auto preload = std::exchange(task->m_preloader, { });
+    return makeUnique<ServiceWorkerFetchTask>(swServerConnection, loader, WTFMove(preload));
+}
+
+ServiceWorkerFetchTask::ServiceWorkerFetchTask(WebSWServerConnection& swServerConnection, NetworkResourceLoader& loader, std::unique_ptr<ServiceWorkerNavigationPreloader>&& preloader)
+    : m_swServerConnection(swServerConnection)
+    , m_loader(loader)
+    , m_fetchIdentifier(WebCore::FetchIdentifier::generate())
+    , m_preloader(WTFMove(preloader))
+{
+    loadResponseFromPreloader();
+}
+
 ServiceWorkerFetchTask::ServiceWorkerFetchTask(WebSWServerConnection& swServerConnection, NetworkResourceLoader& loader, ResourceRequest&& request, SWServerConnectionIdentifier serverConnectionIdentifier, ServiceWorkerIdentifier serviceWorkerIdentifier, SWServerRegistration& registration, NetworkSession* session, bool isWorkerReady)
     : m_swServerConnection(swServerConnection)
     , m_loader(loader)
@@ -57,13 +80,14 @@
     , m_serverConnectionIdentifier(serverConnectionIdentifier)
     , m_serviceWorkerIdentifier(serviceWorkerIdentifier)
     , m_currentRequest(WTFMove(request))
-    , m_timeoutTimer(*this, &ServiceWorkerFetchTask::timeoutTimerFired)
+    , m_timeoutTimer(makeUnique<Timer>(*this, &ServiceWorkerFetchTask::timeoutTimerFired))
     , m_serviceWorkerRegistrationIdentifier(registration.identifier())
     , m_shouldSoftUpdate(registration.shouldSoftUpdate(loader.parameters().options))
 {
     SWFETCH_RELEASE_LOG("ServiceWorkerFetchTask: (serverConnectionIdentifier=%" PRIu64 ", serviceWorkerRegistrationIdentifier=%" PRIu64 ", serviceWorkerIdentifier=%" PRIu64 ", %d)", m_serverConnectionIdentifier.toUInt64(), m_serviceWorkerRegistrationIdentifier.toUInt64(), m_serviceWorkerIdentifier.toUInt64(), isWorkerReady);
-    m_timeoutTimer.startOneShot(loader.connectionToWebProcess().networkProcess().serviceWorkerFetchTimeout());
 
+    m_timeoutTimer->startOneShot(loader.connectionToWebProcess().networkProcess().serviceWorkerFetchTimeout());
+
     // FIXME: Consider extending this based on navigation preload manager.
     bool shouldDoNavigationPreload = session && isNavigationRequest(loader.parameters().options.destination) && loader.originalRequest().httpMethod() == "GET";
     if (shouldDoNavigationPreload && !isWorkerReady) {
@@ -70,6 +94,7 @@
         NetworkLoadParameters parameters = loader.parameters();
         parameters.request = m_currentRequest;
         m_preloader = makeUnique<ServiceWorkerNavigationPreloader>(*session, WTFMove(parameters));
+        session->addNavigationPreloaderTask(*this);
     }
 }
 
@@ -144,7 +169,8 @@
 
     SWFETCH_RELEASE_LOG("processRedirectResponse:");
     m_wasHandled = true;
-    m_timeoutTimer.stop();
+    if (m_timeoutTimer)
+        m_timeoutTimer->stop();
     softUpdateIfNeeded();
 
     if (shouldSetSource == ShouldSetSource::Yes)
@@ -168,7 +194,8 @@
 
     SWFETCH_RELEASE_LOG("processResponse: (httpStatusCode=%d, MIMEType=%" PUBLIC_LOG_STRING ", expectedContentLength=%" PRId64 ", needsContinueDidReceiveResponseMessage=%d, source=%u)", response.httpStatusCode(), response.mimeType().utf8().data(), response.expectedContentLength(), needsContinueDidReceiveResponseMessage, static_cast<unsigned>(response.source()));
     m_wasHandled = true;
-    m_timeoutTimer.stop();
+    if (m_timeoutTimer)
+        m_timeoutTimer->stop();
     softUpdateIfNeeded();
 
     if (m_loader.parameters().options.mode == FetchOptions::Mode::Navigate) {
@@ -203,7 +230,7 @@
     if (m_isDone)
         return;
 
-    ASSERT(!m_timeoutTimer.isActive());
+    ASSERT(!m_timeoutTimer || !m_timeoutTimer->isActive());
     sendToClient(Messages::WebResourceLoader::DidReceiveData { data, encodedDataLength });
 }
 
@@ -212,7 +239,7 @@
     if (m_isDone)
         return;
 
-    ASSERT(!m_timeoutTimer.isActive());
+    ASSERT(!m_timeoutTimer || !m_timeoutTimer->isActive());
     // FIXME: Allow WebResourceLoader to receive form data.
 }
 
@@ -223,11 +250,12 @@
 
 void ServiceWorkerFetchTask::didFinishWithMetrics(const NetworkLoadMetrics& networkLoadMetrics)
 {
-    ASSERT(!m_timeoutTimer.isActive());
+    ASSERT(!m_timeoutTimer || !m_timeoutTimer->isActive());
     SWFETCH_RELEASE_LOG("didFinishWithMetrics:");
 
     m_isDone = true;
-    m_timeoutTimer.stop();
+    if (m_timeoutTimer)
+        m_timeoutTimer->stop();
     sendToClient(Messages::WebResourceLoader::DidFinishResourceLoad { networkLoadMetrics });
 }
 
@@ -234,8 +262,8 @@
 void ServiceWorkerFetchTask::didFail(const ResourceError& error)
 {
     m_isDone = true;
-    if (m_timeoutTimer.isActive()) {
-        m_timeoutTimer.stop();
+    if (m_timeoutTimer && m_timeoutTimer->isActive()) {
+        m_timeoutTimer->stop();
         softUpdateIfNeeded();
     }
     cancelPreloadIfNecessary();
@@ -250,7 +278,8 @@
         return;
 
     SWFETCH_RELEASE_LOG("didNotHandle:");
-    m_timeoutTimer.stop();
+    if (m_timeoutTimer)
+        m_timeoutTimer->stop();
     softUpdateIfNeeded();
 
     if (m_preloader) {
@@ -295,7 +324,8 @@
         m_loader.serviceWorkerDidNotHandle(this);
         return;
     }
-    m_timeoutTimer.startOneShot(m_loader.connectionToWebProcess().networkProcess().serviceWorkerFetchTimeout());
+    if (m_timeoutTimer)
+        m_timeoutTimer->startOneShot(m_loader.connectionToWebProcess().networkProcess().serviceWorkerFetchTimeout());
     m_currentRequest = WTFMove(request);
     startFetch();
 }
@@ -374,10 +404,19 @@
 {
     if (!m_preloader)
         return;
+
+    if (auto* session = this->session())
+        session->removeNavigationPreloaderTask(*this);
+
     m_preloader->cancel();
     m_preloader = nullptr;
 }
 
+NetworkSession* ServiceWorkerFetchTask::session()
+{
+    return m_swServerConnection ? m_swServerConnection->session() : nullptr;
+}
+
 } // namespace WebKit
 
 #undef SWFETCH_RELEASE_LOG

Modified: trunk/Source/WebKit/NetworkProcess/ServiceWorker/ServiceWorkerFetchTask.h (286360 => 286361)


--- trunk/Source/WebKit/NetworkProcess/ServiceWorker/ServiceWorkerFetchTask.h	2021-12-01 12:45:42 UTC (rev 286360)
+++ trunk/Source/WebKit/NetworkProcess/ServiceWorker/ServiceWorkerFetchTask.h	2021-12-01 13:36:58 UTC (rev 286361)
@@ -63,7 +63,11 @@
 class ServiceWorkerFetchTask : public CanMakeWeakPtr<ServiceWorkerFetchTask> {
     WTF_MAKE_FAST_ALLOCATED;
 public:
+    static std::unique_ptr<ServiceWorkerFetchTask> fromNavigationPreloader(WebSWServerConnection&, NetworkResourceLoader&, const WebCore::ResourceRequest&, NetworkSession*);
+
     ServiceWorkerFetchTask(WebSWServerConnection&, NetworkResourceLoader&, WebCore::ResourceRequest&&, WebCore::SWServerConnectionIdentifier, WebCore::ServiceWorkerIdentifier, WebCore::SWServerRegistration&, NetworkSession*, bool isWorkerReady);
+    ServiceWorkerFetchTask(WebSWServerConnection&, NetworkResourceLoader&, std::unique_ptr<ServiceWorkerNavigationPreloader>&&);
+
     ~ServiceWorkerFetchTask();
 
     void start(WebSWServerToContextConnection&);
@@ -102,6 +106,7 @@
     void loadResponseFromPreloader();
     void loadBodyFromPreloader();
     void cancelPreloadIfNecessary();
+    NetworkSession* session();
 
     template<typename Message> bool sendToServiceWorker(Message&&);
     template<typename Message> bool sendToClient(Message&&);
@@ -113,7 +118,7 @@
     WebCore::SWServerConnectionIdentifier m_serverConnectionIdentifier;
     WebCore::ServiceWorkerIdentifier m_serviceWorkerIdentifier;
     WebCore::ResourceRequest m_currentRequest;
-    WebCore::Timer m_timeoutTimer;
+    std::unique_ptr<WebCore::Timer> m_timeoutTimer;
     WebCore::ServiceWorkerRegistrationIdentifier m_serviceWorkerRegistrationIdentifier;
     std::unique_ptr<ServiceWorkerNavigationPreloader> m_preloader;
     bool m_wasHandled { false };

Modified: trunk/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerConnection.cpp (286360 => 286361)


--- trunk/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerConnection.cpp	2021-12-01 12:45:42 UTC (rev 286360)
+++ trunk/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerConnection.cpp	2021-12-01 13:36:58 UTC (rev 286361)
@@ -152,8 +152,13 @@
 
 std::unique_ptr<ServiceWorkerFetchTask> WebSWServerConnection::createFetchTask(NetworkResourceLoader& loader, const ResourceRequest& request)
 {
-    if (loader.parameters().serviceWorkersMode == ServiceWorkersMode::None)
+    if (loader.parameters().serviceWorkersMode == ServiceWorkersMode::None) {
+        if (loader.parameters().request.requester() == ResourceRequest::Requester::Fetch && isNavigationRequest(loader.parameters().options.destination)) {
+            if (auto task = ServiceWorkerFetchTask::fromNavigationPreloader(*this, loader, request, session()))
+                return task;
+        }
         return nullptr;
+    }
 
     if (!server().canHandleScheme(loader.originalRequest().url().protocol()))
         return nullptr;

Modified: trunk/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp (286360 => 286361)


--- trunk/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp	2021-12-01 12:45:42 UTC (rev 286360)
+++ trunk/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp	2021-12-01 13:36:58 UTC (rev 286361)
@@ -333,6 +333,8 @@
     loadParameters.serviceWorkersMode = resourceLoader.options().loadedFromOpaqueSource == LoadedFromOpaqueSource::No ? resourceLoader.options().serviceWorkersMode : ServiceWorkersMode::None;
     loadParameters.serviceWorkerRegistrationIdentifier = resourceLoader.options().serviceWorkerRegistrationIdentifier;
     loadParameters.httpHeadersToKeep = resourceLoader.options().httpHeadersToKeep;
+    if (resourceLoader.options().navigationPreloadIdentifier)
+        loadParameters.navigationPreloadIdentifier = resourceLoader.options().navigationPreloadIdentifier;
 #endif
 
     auto* document = frame ? frame->document() : nullptr;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to