Title: [286288] trunk
Revision
286288
Author
[email protected]
Date
2021-11-30 02:48:04 -0800 (Tue, 30 Nov 2021)

Log Message

Preload navigation request if the service worker is not immediately ready to handle the navigation request fetch event
https://bugs.webkit.org/show_bug.cgi?id=233471

Reviewed by Chris Dumez.

Source/WebCore:

Add a helper routine.

* loader/FetchOptions.h:

Source/WebKit:

Launching a service worker might take time due to parsing and running the service worker script.
This might delay navigation loads, especially if the service worker is pass through on these loads.
To optimize this code path, we preload the navigation request in case service worker is not running or not yet activated.
We then wait for the service worker to handle the fetch event, which will tell us to either go to the network, in which
case we use the preload, or will provide its own response in which case we use it and cancel the preload.

Test: http/wpt/service-workers/service-worker-preload-when-not-activated.https.html

* NetworkProcess/ServiceWorker/ServiceWorkerFetchTask.cpp:
* NetworkProcess/ServiceWorker/ServiceWorkerFetchTask.h:
* NetworkProcess/ServiceWorker/ServiceWorkerNavigationPreloader.cpp: Added.
* NetworkProcess/ServiceWorker/ServiceWorkerNavigationPreloader.h: Added.
* NetworkProcess/ServiceWorker/WebSWServerConnection.cpp:
* NetworkProcess/ServiceWorker/WebSWServerConnection.h:
* NetworkProcess/webrtc/NetworkMDNSRegister.h:
* Sources.txt:
* WebKit.xcodeproj/project.pbxproj:

LayoutTests:

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

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (286287 => 286288)


--- trunk/LayoutTests/ChangeLog	2021-11-30 09:19:15 UTC (rev 286287)
+++ trunk/LayoutTests/ChangeLog	2021-11-30 10:48:04 UTC (rev 286288)
@@ -1,3 +1,15 @@
+2021-11-30  Youenn Fablet  <[email protected]>
+
+        Preload navigation request if the service worker is not immediately ready to handle the navigation request fetch event
+        https://bugs.webkit.org/show_bug.cgi?id=233471
+
+        Reviewed by Chris Dumez.
+
+        * http/wpt/service-workers/resources/service-worker-preload-when-not-activated-script.py: Added.
+        * http/wpt/service-workers/service-worker-preload-when-not-activated-worker.js: Added.
+        * http/wpt/service-workers/service-worker-preload-when-not-activated.https-expected.txt: Added.
+        * http/wpt/service-workers/service-worker-preload-when-not-activated.https.html: Added.
+
 2021-11-29  Wenson Hsieh  <[email protected]>
 
         [Webpage translation] Avoid translating text inside image overlays

Added: trunk/LayoutTests/http/wpt/service-workers/resources/service-worker-preload-when-not-activated-script.py (0 => 286288)


--- trunk/LayoutTests/http/wpt/service-workers/resources/service-worker-preload-when-not-activated-script.py	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/service-workers/resources/service-worker-preload-when-not-activated-script.py	2021-11-30 10:48:04 UTC (rev 286288)
@@ -0,0 +1,24 @@
+import os
+import hashlib
+import json
+
+
+def main(request, response):
+    token = request.GET[b'token']
+    testId = hashlib.md5(token).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']
+
+    value = request.server.stash.take(testId)
+    if not value:
+        response.headers.set(b"Cache-Control", b"no-cache")
+        response.headers.set(b"Content-Type", b"text/ascii")
+        return "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()

Added: trunk/LayoutTests/http/wpt/service-workers/service-worker-preload-when-not-activated-worker.js (0 => 286288)


--- trunk/LayoutTests/http/wpt/service-workers/service-worker-preload-when-not-activated-worker.js	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/service-workers/service-worker-preload-when-not-activated-worker.js	2021-11-30 10:48:04 UTC (rev 286288)
@@ -0,0 +1,28 @@
+_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', () => {
+    if (self.port)
+        self.port.postMessage("fetching");
+});

Added: trunk/LayoutTests/http/wpt/service-workers/service-worker-preload-when-not-activated.https-expected.txt (0 => 286288)


--- trunk/LayoutTests/http/wpt/service-workers/service-worker-preload-when-not-activated.https-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/service-workers/service-worker-preload-when-not-activated.https-expected.txt	2021-11-30 10:48:04 UTC (rev 286288)
@@ -0,0 +1,5 @@
+
+
+PASS Setup activating worker
+PASS Service worker load uses preload if available and fetch event was not handled
+

Added: trunk/LayoutTests/http/wpt/service-workers/service-worker-preload-when-not-activated.https.html (0 => 286288)


--- trunk/LayoutTests/http/wpt/service-workers/service-worker-preload-when-not-activated.https.html	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/service-workers/service-worker-preload-when-not-activated.https.html	2021-11-30 10:48:04 UTC (rev 286288)
@@ -0,0 +1,72 @@
+<!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/service-worker-preload-when-not-activated-worker.js", { scope : url });
+    if (!registration.installing) {
+        registration.unregister();
+        registration = await navigator.serviceWorker.register("/WebKit/service-workers/service-worker-preload-when-not-activated-worker.js", { scope : url });
+    }
+
+    activeWorker = registration.installing;
+    activeWorker.postMessage({ port: channel.port1 }, [channel.port1]);
+
+    return waitUntilActivating();
+}, "Setup activating worker");
+
+promise_test(async (test) => {
+    // Set value to 'before-navigation'
+    await fetch(url + "&value=before-navigation", { method: 'POST' });
+
+    // Start loading iframe, with activating worker, so only preload will start.
+    const iframePromise = withIframe(url);
+
+    // Wait a little bit to do a fetch. This fetch should happen after the preload and should receive a 'nothing' body.
+    await new Promise(resolve => setTimeout(resolve, 100));
+    const fetchPromise = fetch(url);
+
+    // Trigger activation to start the fetch event handler, which will do nothing so we will use the preload.
+    triggerActivation();
+
+    const response = await fetchPromise;
+    assert_equals(await response.text(), "nothing");
+
+    const frame = await iframePromise;
+    assert_equals(frame.contentWindow.value, "before-navigation");
+}, "Service worker load uses preload if available and fetch event was not handled");
+</script>
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (286287 => 286288)


--- trunk/Source/WebCore/ChangeLog	2021-11-30 09:19:15 UTC (rev 286287)
+++ trunk/Source/WebCore/ChangeLog	2021-11-30 10:48:04 UTC (rev 286288)
@@ -1,3 +1,14 @@
+2021-11-30  Youenn Fablet  <[email protected]>
+
+        Preload navigation request if the service worker is not immediately ready to handle the navigation request fetch event
+        https://bugs.webkit.org/show_bug.cgi?id=233471
+
+        Reviewed by Chris Dumez.
+
+        Add a helper routine.
+
+        * loader/FetchOptions.h:
+
 2021-11-30  Said Abou-Hallawa  <[email protected]>
 
         [GPU Process] Calculate the result image rectangle of the FilterEffect in filter coordinates

Modified: trunk/Source/WebCore/loader/FetchOptions.h (286287 => 286288)


--- trunk/Source/WebCore/loader/FetchOptions.h	2021-11-30 09:19:15 UTC (rev 286287)
+++ trunk/Source/WebCore/loader/FetchOptions.h	2021-11-30 10:48:04 UTC (rev 286288)
@@ -81,6 +81,15 @@
         || destination == FetchOptions::Destination::Embed;
 }
 
+// https://fetch.spec.whatwg.org/#navigation-request
+inline bool isNavigationRequest(FetchOptions::Destination destination)
+{
+    return destination == FetchOptions::Destination::Document
+        || destination == FetchOptions::Destination::Iframe
+        || destination == FetchOptions::Destination::Object
+        || destination == FetchOptions::Destination::Embed;
+}
+
 // https://fetch.spec.whatwg.org/#non-subresource-request
 inline bool isNonSubresourceRequest(FetchOptions::Destination destination)
 {

Modified: trunk/Source/WebKit/ChangeLog (286287 => 286288)


--- trunk/Source/WebKit/ChangeLog	2021-11-30 09:19:15 UTC (rev 286287)
+++ trunk/Source/WebKit/ChangeLog	2021-11-30 10:48:04 UTC (rev 286288)
@@ -1,5 +1,30 @@
 2021-11-30  Youenn Fablet  <[email protected]>
 
+        Preload navigation request if the service worker is not immediately ready to handle the navigation request fetch event
+        https://bugs.webkit.org/show_bug.cgi?id=233471
+
+        Reviewed by Chris Dumez.
+
+        Launching a service worker might take time due to parsing and running the service worker script.
+        This might delay navigation loads, especially if the service worker is pass through on these loads.
+        To optimize this code path, we preload the navigation request in case service worker is not running or not yet activated.
+        We then wait for the service worker to handle the fetch event, which will tell us to either go to the network, in which
+        case we use the preload, or will provide its own response in which case we use it and cancel the preload.
+
+        Test: http/wpt/service-workers/service-worker-preload-when-not-activated.https.html
+
+        * NetworkProcess/ServiceWorker/ServiceWorkerFetchTask.cpp:
+        * NetworkProcess/ServiceWorker/ServiceWorkerFetchTask.h:
+        * NetworkProcess/ServiceWorker/ServiceWorkerNavigationPreloader.cpp: Added.
+        * NetworkProcess/ServiceWorker/ServiceWorkerNavigationPreloader.h: Added.
+        * NetworkProcess/ServiceWorker/WebSWServerConnection.cpp:
+        * NetworkProcess/ServiceWorker/WebSWServerConnection.h:
+        * NetworkProcess/webrtc/NetworkMDNSRegister.h:
+        * Sources.txt:
+        * WebKit.xcodeproj/project.pbxproj:
+
+2021-11-30  Youenn Fablet  <[email protected]>
+
         Remove unnecessary service worker page settings handling
         https://bugs.webkit.org/show_bug.cgi?id=233468
 

Modified: trunk/Source/WebKit/NetworkProcess/ServiceWorker/ServiceWorkerFetchTask.cpp (286287 => 286288)


--- trunk/Source/WebKit/NetworkProcess/ServiceWorker/ServiceWorkerFetchTask.cpp	2021-11-30 09:19:15 UTC (rev 286287)
+++ trunk/Source/WebKit/NetworkProcess/ServiceWorker/ServiceWorkerFetchTask.cpp	2021-11-30 10:48:04 UTC (rev 286288)
@@ -33,6 +33,7 @@
 #include "Logging.h"
 #include "NetworkProcess.h"
 #include "NetworkResourceLoader.h"
+#include "ServiceWorkerNavigationPreloader.h"
 #include "SharedBufferDataReference.h"
 #include "WebCoreArgumentCoders.h"
 #include "WebResourceLoaderMessages.h"
@@ -49,7 +50,7 @@
 
 using namespace WebCore;
 
-ServiceWorkerFetchTask::ServiceWorkerFetchTask(WebSWServerConnection& swServerConnection, NetworkResourceLoader& loader, ResourceRequest&& request, SWServerConnectionIdentifier serverConnectionIdentifier, ServiceWorkerIdentifier serviceWorkerIdentifier, ServiceWorkerRegistrationIdentifier serviceWorkerRegistrationIdentifier, bool shouldSoftUpdate)
+ServiceWorkerFetchTask::ServiceWorkerFetchTask(WebSWServerConnection& swServerConnection, NetworkResourceLoader& loader, ResourceRequest&& request, SWServerConnectionIdentifier serverConnectionIdentifier, ServiceWorkerIdentifier serviceWorkerIdentifier, SWServerRegistration& registration, NetworkSession* session, bool isWorkerReady)
     : m_swServerConnection(swServerConnection)
     , m_loader(loader)
     , m_fetchIdentifier(WebCore::FetchIdentifier::generate())
@@ -57,11 +58,19 @@
     , m_serviceWorkerIdentifier(serviceWorkerIdentifier)
     , m_currentRequest(WTFMove(request))
     , m_timeoutTimer(*this, &ServiceWorkerFetchTask::timeoutTimerFired)
-    , m_serviceWorkerRegistrationIdentifier(serviceWorkerRegistrationIdentifier)
-    , m_shouldSoftUpdate(shouldSoftUpdate)
+    , m_serviceWorkerRegistrationIdentifier(registration.identifier())
+    , m_shouldSoftUpdate(registration.shouldSoftUpdate(loader.parameters().options))
 {
-    SWFETCH_RELEASE_LOG("ServiceWorkerFetchTask: (serverConnectionIdentifier=%" PRIu64 ", serviceWorkerRegistrationIdentifier=%" PRIu64 ", serviceWorkerIdentifier=%" PRIu64 ")", m_serverConnectionIdentifier.toUInt64(), m_serviceWorkerRegistrationIdentifier.toUInt64(), m_serviceWorkerIdentifier.toUInt64());
+    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());
+
+    // FIXME: Consider extending this based on navigation preload manager.
+    bool shouldDoNavigationPreload = session && isNavigationRequest(loader.parameters().options.destination) && loader.originalRequest().httpMethod() == "GET";
+    if (shouldDoNavigationPreload && !isWorkerReady) {
+        NetworkLoadParameters parameters = loader.parameters();
+        parameters.request = m_currentRequest;
+        m_preloader = makeUnique<ServiceWorkerNavigationPreloader>(*session, WTFMove(parameters));
+    }
 }
 
 ServiceWorkerFetchTask::~ServiceWorkerFetchTask()
@@ -69,6 +78,8 @@
     SWFETCH_RELEASE_LOG("~ServiceWorkerFetchTask:");
     if (m_serviceWorkerConnection)
         m_serviceWorkerConnection->unregisterFetch(*this);
+
+    cancelPreloadIfNecessary();
 }
 
 template<typename Message> bool ServiceWorkerFetchTask::sendToServiceWorker(Message&& message)
@@ -119,28 +130,43 @@
     ASSERT_UNUSED(isSent, isSent);
 }
 
-void ServiceWorkerFetchTask::didReceiveRedirectResponse(ResourceResponse&& response)
+void ServiceWorkerFetchTask::didReceiveRedirectResponse(WebCore::ResourceResponse&& response)
 {
+    cancelPreloadIfNecessary();
+
+    processRedirectResponse(WTFMove(response), ShouldSetSource::Yes);
+}
+
+void ServiceWorkerFetchTask::processRedirectResponse(ResourceResponse&& response, ShouldSetSource shouldSetSource)
+{
     if (m_isDone)
         return;
 
-    SWFETCH_RELEASE_LOG("didReceiveRedirectResponse:");
+    SWFETCH_RELEASE_LOG("processRedirectResponse:");
     m_wasHandled = true;
     m_timeoutTimer.stop();
     softUpdateIfNeeded();
 
-    response.setSource(ResourceResponse::Source::ServiceWorker);
+    if (shouldSetSource == ShouldSetSource::Yes)
+        response.setSource(ResourceResponse::Source::ServiceWorker);
     auto newRequest = m_currentRequest.redirectedRequest(response, m_loader.parameters().shouldClearReferrerOnHTTPSToHTTPRedirect);
 
     sendToClient(Messages::WebResourceLoader::WillSendRequest { newRequest, IPC::FormDataReference { newRequest.httpBody() }, response });
 }
 
-void ServiceWorkerFetchTask::didReceiveResponse(ResourceResponse&& response, bool needsContinueDidReceiveResponseMessage)
+void ServiceWorkerFetchTask::didReceiveResponse(WebCore::ResourceResponse&& response, bool needsContinueDidReceiveResponseMessage)
 {
+    cancelPreloadIfNecessary();
+
+    processResponse(WTFMove(response), needsContinueDidReceiveResponseMessage, ShouldSetSource::Yes);
+}
+
+void ServiceWorkerFetchTask::processResponse(ResourceResponse&& response, bool needsContinueDidReceiveResponseMessage, ShouldSetSource shouldSetSource)
+{
     if (m_isDone)
         return;
 
-    SWFETCH_RELEASE_LOG("didReceiveResponse: (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()));
+    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();
     softUpdateIfNeeded();
@@ -165,7 +191,8 @@
         return;
     }
 
-    response.setSource(ResourceResponse::Source::ServiceWorker);
+    if (shouldSetSource == ShouldSetSource::Yes)
+        response.setSource(ResourceResponse::Source::ServiceWorker);
     m_loader.sendDidReceiveResponsePotentiallyInNewBrowsingContextGroup(response, needsContinueDidReceiveResponseMessage);
     if (needsContinueDidReceiveResponseMessage)
         m_loader.setResponse(WTFMove(response));
@@ -191,12 +218,17 @@
 
 void ServiceWorkerFetchTask::didFinish()
 {
+    didFinishWithMetrics({ });
+}
+
+void ServiceWorkerFetchTask::didFinishWithMetrics(const NetworkLoadMetrics& networkLoadMetrics)
+{
     ASSERT(!m_timeoutTimer.isActive());
-    SWFETCH_RELEASE_LOG("didFinish:");
+    SWFETCH_RELEASE_LOG("didFinishWithMetrics:");
 
     m_isDone = true;
     m_timeoutTimer.stop();
-    sendToClient(Messages::WebResourceLoader::DidFinishResourceLoad { { } });
+    sendToClient(Messages::WebResourceLoader::DidFinishResourceLoad { networkLoadMetrics });
 }
 
 void ServiceWorkerFetchTask::didFail(const ResourceError& error)
@@ -206,6 +238,8 @@
         m_timeoutTimer.stop();
         softUpdateIfNeeded();
     }
+    cancelPreloadIfNecessary();
+
     SWFETCH_RELEASE_LOG_ERROR("didFail: (error.domain=%" PUBLIC_LOG_STRING ", error.code=%d)", error.domain().utf8().data(), error.errorCode());
     m_loader.didFailLoading(error);
 }
@@ -216,10 +250,15 @@
         return;
 
     SWFETCH_RELEASE_LOG("didNotHandle:");
-    m_isDone = true;
     m_timeoutTimer.stop();
     softUpdateIfNeeded();
 
+    if (m_preloader) {
+        loadResponseFromPreloader();
+        return;
+    }
+
+    m_isDone = true;
     m_loader.serviceWorkerDidNotHandle(this);
 }
 
@@ -242,6 +281,10 @@
 void ServiceWorkerFetchTask::continueDidReceiveFetchResponse()
 {
     SWFETCH_RELEASE_LOG("continueDidReceiveFetchResponse:");
+    if (m_isLoadingFromPreloader) {
+        loadBodyFromPreloader();
+        return;
+    }
     sendToServiceWorker(Messages::WebSWContextManagerConnection::ContinueDidReceiveFetchResponse { m_serverConnectionIdentifier, m_serviceWorkerIdentifier, m_fetchIdentifier });
 }
 
@@ -280,6 +323,61 @@
         registration->scheduleSoftUpdate(m_loader.isAppInitiated() ? WebCore::IsAppInitiated::Yes : WebCore::IsAppInitiated::No);
 }
 
+void ServiceWorkerFetchTask::loadResponseFromPreloader()
+{
+    SWFETCH_RELEASE_LOG("loadResponseFromPreloader");
+
+    ASSERT(!m_isLoadingFromPreloader);
+    m_isLoadingFromPreloader = true;
+
+    m_preloader->waitForResponse([weakThis = WeakPtr { *this }, this] {
+        if (!weakThis)
+            return;
+
+        if (!m_preloader->error().isNull()) {
+            didFail(m_preloader->error());
+            return;
+        }
+
+        auto response = m_preloader->response();
+        if (response.isRedirection() && response.httpHeaderFields().contains(HTTPHeaderName::Location)) {
+            processRedirectResponse(WTFMove(response), ShouldSetSource::No);
+            return;
+        }
+
+        bool needsContinueDidReceiveResponseMessage = true;
+        processResponse(WTFMove(response), needsContinueDidReceiveResponseMessage, ShouldSetSource::No);
+    });
+}
+
+void ServiceWorkerFetchTask::loadBodyFromPreloader()
+{
+    SWFETCH_RELEASE_LOG("loadBodyFromPreloader");
+
+    ASSERT(m_isLoadingFromPreloader);
+    m_preloader->waitForBody([weakThis = WeakPtr { *this }, this](auto&& chunk, int length) {
+        if (!weakThis)
+            return;
+        if (!m_preloader->error().isNull()) {
+            didFail(m_preloader->error());
+            return;
+        }
+        if (!chunk) {
+            didFinishWithMetrics(m_preloader->networkLoadMetrics());
+            return;
+        }
+        didReceiveData(IPC::DataReference { chunk->data(), chunk->size() }, length);
+    });
+}
+
+void ServiceWorkerFetchTask::cancelPreloadIfNecessary()
+{
+    if (!m_preloader)
+        return;
+    m_preloader->cancel();
+    m_preloader = nullptr;
+}
+
 } // namespace WebKit
 
 #undef SWFETCH_RELEASE_LOG

Modified: trunk/Source/WebKit/NetworkProcess/ServiceWorker/ServiceWorkerFetchTask.h (286287 => 286288)


--- trunk/Source/WebKit/NetworkProcess/ServiceWorker/ServiceWorkerFetchTask.h	2021-11-30 09:19:15 UTC (rev 286287)
+++ trunk/Source/WebKit/NetworkProcess/ServiceWorker/ServiceWorkerFetchTask.h	2021-11-30 10:48:04 UTC (rev 286288)
@@ -40,6 +40,7 @@
 class ResourceError;
 class ResourceRequest;
 class ResourceResponse;
+class SWServerRegistration;
 }
 
 namespace IPC {
@@ -48,9 +49,14 @@
 class FormDataReference;
 }
 
+namespace WebCore {
+class NetworkLoadMetrics;
+}
+
 namespace WebKit {
-
 class NetworkResourceLoader;
+class NetworkSession;
+class ServiceWorkerNavigationPreloader;
 class WebSWServerConnection;
 class WebSWServerToContextConnection;
 
@@ -57,7 +63,7 @@
 class ServiceWorkerFetchTask : public CanMakeWeakPtr<ServiceWorkerFetchTask> {
     WTF_MAKE_FAST_ALLOCATED;
 public:
-    ServiceWorkerFetchTask(WebSWServerConnection&, NetworkResourceLoader&, WebCore::ResourceRequest&&, WebCore::SWServerConnectionIdentifier, WebCore::ServiceWorkerIdentifier, WebCore::ServiceWorkerRegistrationIdentifier, bool shouldSoftUpdate);
+    ServiceWorkerFetchTask(WebSWServerConnection&, NetworkResourceLoader&, WebCore::ResourceRequest&&, WebCore::SWServerConnectionIdentifier, WebCore::ServiceWorkerIdentifier, WebCore::SWServerRegistration&, NetworkSession*, bool isWorkerReady);
     ~ServiceWorkerFetchTask();
 
     void start(WebSWServerToContextConnection&);
@@ -76,18 +82,26 @@
     void contextClosed();
 
 private:
+    enum class ShouldSetSource : bool { No, Yes };
     void didReceiveRedirectResponse(WebCore::ResourceResponse&&);
     void didReceiveResponse(WebCore::ResourceResponse&&, bool needsContinueDidReceiveResponseMessage);
     void didReceiveData(const IPC::DataReference&, int64_t encodedDataLength);
     void didReceiveFormData(const IPC::FormDataReference&);
     void didFinish();
+    void didFinishWithMetrics(const WebCore::NetworkLoadMetrics&);
     void didFail(const WebCore::ResourceError&);
     void didNotHandle();
 
+    void processRedirectResponse(WebCore::ResourceResponse&&, ShouldSetSource);
+    void processResponse(WebCore::ResourceResponse&&, bool needsContinueDidReceiveResponseMessage, ShouldSetSource);
+
     void startFetch();
 
     void timeoutTimerFired();
     void softUpdateIfNeeded();
+    void loadResponseFromPreloader();
+    void loadBodyFromPreloader();
+    void cancelPreloadIfNecessary();
 
     template<typename Message> bool sendToServiceWorker(Message&&);
     template<typename Message> bool sendToClient(Message&&);
@@ -100,10 +114,12 @@
     WebCore::ServiceWorkerIdentifier m_serviceWorkerIdentifier;
     WebCore::ResourceRequest m_currentRequest;
     WebCore::Timer m_timeoutTimer;
+    WebCore::ServiceWorkerRegistrationIdentifier m_serviceWorkerRegistrationIdentifier;
+    std::unique_ptr<ServiceWorkerNavigationPreloader> m_preloader;
     bool m_wasHandled { false };
     bool m_isDone { false };
-    WebCore::ServiceWorkerRegistrationIdentifier m_serviceWorkerRegistrationIdentifier;
     bool m_shouldSoftUpdate { false };
+    bool m_isLoadingFromPreloader { false };
 };
 
 }

Added: trunk/Source/WebKit/NetworkProcess/ServiceWorker/ServiceWorkerNavigationPreloader.cpp (0 => 286288)


--- trunk/Source/WebKit/NetworkProcess/ServiceWorker/ServiceWorkerNavigationPreloader.cpp	                        (rev 0)
+++ trunk/Source/WebKit/NetworkProcess/ServiceWorker/ServiceWorkerNavigationPreloader.cpp	2021-11-30 10:48:04 UTC (rev 286288)
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ServiceWorkerNavigationPreloader.h"
+
+#if ENABLE(SERVICE_WORKER)
+
+#include "Logging.h"
+#include "NetworkCache.h"
+#include "NetworkLoad.h"
+#include "NetworkSession.h"
+
+namespace WebKit {
+
+using namespace WebCore;
+
+ServiceWorkerNavigationPreloader::ServiceWorkerNavigationPreloader(NetworkSession& session, NetworkLoadParameters&& parameters)
+    : m_session(session)
+{
+    RELEASE_LOG(ServiceWorker, "ServiceWorkerNavigationPreloader::ServiceWorkerNavigationPreloader %p", this);
+    if (session.cache()) {
+        NetworkCache::GlobalFrameID globalID { parameters.webPageProxyID, parameters.webPageID, parameters.webFrameID };
+        session.cache()->retrieve(parameters.request, globalID, parameters.isNavigatingToAppBoundDomain, [this, weakThis = WeakPtr { *this }, parameters = WTFMove(parameters)](auto&& entry, auto&&) mutable {
+            if (!weakThis || m_isCancelled)
+                return;
+            if (!m_session) {
+                didFailLoading(ResourceError { ResourceError::Type::Cancellation });
+                return;
+            }
+            if (entry && !entry->needsValidation()) {
+                loadWithCacheEntry(*entry);
+                return;
+            }
+
+            parameters.request.setCachePolicy(ResourceRequestCachePolicy::RefreshAnyCacheData);
+            if (entry) {
+                m_cacheEntry = WTFMove(entry);
+
+                auto eTag = m_cacheEntry->response().httpHeaderField(HTTPHeaderName::ETag);
+                if (!eTag.isEmpty())
+                    parameters.request.setHTTPHeaderField(HTTPHeaderName::IfNoneMatch, eTag);
+
+                auto lastModified = m_cacheEntry->response().httpHeaderField(HTTPHeaderName::LastModified);
+                if (!lastModified.isEmpty())
+                    parameters.request.setHTTPHeaderField(HTTPHeaderName::IfModifiedSince, lastModified);
+            }
+            loadFromNetwork(*m_session, WTFMove(parameters));
+        });
+        return;
+    }
+    loadFromNetwork(session, WTFMove(parameters));
+}
+
+ServiceWorkerNavigationPreloader::~ServiceWorkerNavigationPreloader()
+{
+}
+
+void ServiceWorkerNavigationPreloader::cancel()
+{
+    m_isCancelled = true;
+    if (m_responseCompletionHandler)
+        m_responseCompletionHandler(PolicyAction::Ignore);
+    if (m_networkLoad)
+        m_networkLoad->cancel();
+}
+
+void ServiceWorkerNavigationPreloader::loadWithCacheEntry(NetworkCache::Entry& entry)
+{
+    didReceiveResponse(ResourceResponse { entry.response() }, [body = RefPtr { entry.buffer() }, weakThis = WeakPtr { *this }](auto) mutable {
+        if (!weakThis)
+            return;
+
+        if (body) {
+            auto size = body->size();
+            weakThis->didReceiveBuffer(body.releaseNonNull(), size);
+        }
+
+        if (!weakThis)
+            return;
+
+        NetworkLoadMetrics networkLoadMetrics;
+        networkLoadMetrics.markComplete();
+        networkLoadMetrics.responseBodyBytesReceived = 0;
+        networkLoadMetrics.responseBodyDecodedSize = 0;
+        weakThis->didFinishLoading(networkLoadMetrics);
+    });
+    didComplete();
+}
+
+void ServiceWorkerNavigationPreloader::loadFromNetwork(NetworkSession& session, NetworkLoadParameters&& parameters)
+{
+    RELEASE_LOG(ServiceWorker, "ServiceWorkerNavigationPreloader::loadFromNetwork %p", this);
+
+    m_networkLoad = makeUnique<NetworkLoad>(*this, nullptr, WTFMove(parameters), session);
+    m_networkLoad->start();
+}
+
+void ServiceWorkerNavigationPreloader::willSendRedirectedRequest(ResourceRequest&&, ResourceRequest&&, ResourceResponse&& response)
+{
+    didReceiveResponse(WTFMove(response), [](auto) { });
+    didComplete();
+}
+
+void ServiceWorkerNavigationPreloader::didReceiveResponse(ResourceResponse&& response, ResponseCompletionHandler&& completionHandler)
+{
+    RELEASE_LOG(ServiceWorker, "ServiceWorkerNavigationPreloader::didReceiveResponse %p", this);
+
+    if (response.httpStatusCode() == 304 && m_cacheEntry) {
+        auto cacheEntry = WTFMove(m_cacheEntry);
+        loadWithCacheEntry(*cacheEntry);
+        completionHandler(PolicyAction::Ignore);
+        return;
+    }
+
+    m_response = WTFMove(response);
+    m_responseCompletionHandler = WTFMove(completionHandler);
+
+    if (auto callback = std::exchange(m_responseCallback, { }))
+        callback();
+}
+
+void ServiceWorkerNavigationPreloader::didReceiveBuffer(Ref<SharedBuffer>&& buffer, int reportedEncodedDataLength)
+{
+    if (m_bodyCallback)
+        m_bodyCallback(WTFMove(buffer), reportedEncodedDataLength);
+}
+
+void ServiceWorkerNavigationPreloader::didFinishLoading(const NetworkLoadMetrics& networkLoadMetrics)
+{
+    RELEASE_LOG(ServiceWorker, "ServiceWorkerNavigationPreloader::didFinishLoading %p", this);
+
+    m_networkLoadMetrics = networkLoadMetrics;
+    didComplete();
+}
+
+void ServiceWorkerNavigationPreloader::didFailLoading(const ResourceError& error)
+{
+    RELEASE_LOG(ServiceWorker, "ServiceWorkerNavigationPreloader::didFailLoading %p", this);
+
+    m_error = error;
+    didComplete();
+}
+
+void ServiceWorkerNavigationPreloader::didComplete()
+{
+    m_networkLoad = nullptr;
+
+    if (auto callback = std::exchange(m_responseCallback, { }))
+        callback();
+
+    if (m_bodyCallback)
+        m_bodyCallback({ }, 0);
+}
+
+void ServiceWorkerNavigationPreloader::waitForResponse(ResponseCallback&& callback)
+{
+    if (!m_error.isNull()) {
+        callback();
+        return;
+    }
+
+    if (m_responseCompletionHandler) {
+        callback();
+        return;
+    }
+
+    m_responseCallback = WTFMove(callback);
+}
+
+void ServiceWorkerNavigationPreloader::waitForBody(BodyCallback&& callback)
+{
+    if (!m_error.isNull()) {
+        callback({ }, 0);
+        return;
+    }
+
+    ASSERT(!m_response.isNull());
+    ASSERT(m_responseCompletionHandler || !m_networkLoad);
+    if (!m_networkLoad) {
+        callback({ }, 0);
+        return;
+    }
+    if (m_responseCompletionHandler)
+        m_responseCompletionHandler(PolicyAction::Use);
+    m_bodyCallback = WTFMove(callback);
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(SERVICE_WORKER)

Added: trunk/Source/WebKit/NetworkProcess/ServiceWorker/ServiceWorkerNavigationPreloader.h (0 => 286288)


--- trunk/Source/WebKit/NetworkProcess/ServiceWorker/ServiceWorkerNavigationPreloader.h	                        (rev 0)
+++ trunk/Source/WebKit/NetworkProcess/ServiceWorker/ServiceWorkerNavigationPreloader.h	2021-11-30 10:48:04 UTC (rev 286288)
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(SERVICE_WORKER)
+
+#include "NetworkCacheEntry.h"
+#include "NetworkLoadClient.h"
+#include <wtf/WeakPtr.h>
+
+namespace WebCore {
+class NetworkLoadMetrics;
+}
+
+namespace WebKit {
+
+class NetworkLoad;
+class NetworkLoadParameters;
+class NetworkSession;
+
+class ServiceWorkerNavigationPreloader final : public NetworkLoadClient, public CanMakeWeakPtr<ServiceWorkerNavigationPreloader> {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    ServiceWorkerNavigationPreloader(NetworkSession&, NetworkLoadParameters&&);
+    ~ServiceWorkerNavigationPreloader();
+
+    void cancel();
+
+    using ResponseCallback = Function<void()>;
+    void waitForResponse(ResponseCallback&&);
+    using BodyCallback = Function<void(RefPtr<WebCore::SharedBuffer>&&, int reportedEncodedDataLength)>;
+    void waitForBody(BodyCallback&&);
+
+    const WebCore::ResourceError& error() const { return m_error; }
+    const WebCore::ResourceResponse& response() const { return m_response; }
+    const WebCore::NetworkLoadMetrics& networkLoadMetrics() const { return m_networkLoadMetrics; }
+
+private:
+    // NetworkLoadClient.
+    void didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent) final { }
+    bool isSynchronous() const final { return false; }
+    bool isAllowedToAskUserForCredentials() const final { return false; }
+    void willSendRedirectedRequest(WebCore::ResourceRequest&&, WebCore::ResourceRequest&& redirectRequest, WebCore::ResourceResponse&& redirectResponse) final;
+    void didReceiveResponse(WebCore::ResourceResponse&&, ResponseCompletionHandler&&) final;
+    void didReceiveBuffer(Ref<WebCore::SharedBuffer>&&, int reportedEncodedDataLength) final;
+    void didFinishLoading(const WebCore::NetworkLoadMetrics&) final;
+    void didFailLoading(const WebCore::ResourceError&) final;
+
+    void loadWithCacheEntry(NetworkCache::Entry&);
+    void loadFromNetwork(NetworkSession&, NetworkLoadParameters&&);
+    void didComplete();
+
+    std::unique_ptr<NetworkLoad> m_networkLoad;
+    WeakPtr<NetworkSession> m_session;
+    bool m_isCancelled { false };
+
+    std::unique_ptr<NetworkCache::Entry> m_cacheEntry;
+    WebCore::NetworkLoadMetrics m_networkLoadMetrics;
+    WebCore::ResourceResponse m_response;
+    ResponseCompletionHandler m_responseCompletionHandler;
+    WebCore::ResourceError m_error;
+
+    ResponseCallback m_responseCallback;
+    BodyCallback m_bodyCallback;
+};
+
+} // namespace WebKit
+
+#endif // ENABLE(SERVICE_WORKER)
+

Modified: trunk/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerConnection.cpp (286287 => 286288)


--- trunk/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerConnection.cpp	2021-11-30 09:19:15 UTC (rev 286287)
+++ trunk/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerConnection.cpp	2021-11-30 10:48:04 UTC (rev 286288)
@@ -184,9 +184,8 @@
     }
 
     auto* registration = server().getRegistration(*serviceWorkerRegistrationIdentifier);
-    bool shouldSoftUpdate = registration && registration->shouldSoftUpdate(loader.parameters().options);
     if (worker->shouldSkipFetchEvent()) {
-        if (shouldSoftUpdate)
+        if (registration && registration->shouldSoftUpdate(loader.parameters().options))
             registration->scheduleSoftUpdate(loader.isAppInitiated() ? WebCore::IsAppInitiated::Yes : WebCore::IsAppInitiated::No);
 
         return nullptr;
@@ -197,7 +196,8 @@
         return nullptr;
     }
 
-    auto task = makeUnique<ServiceWorkerFetchTask>(*this, loader, ResourceRequest { request }, identifier(), worker->identifier(), *serviceWorkerRegistrationIdentifier, shouldSoftUpdate);
+    bool isWorkerReady = worker->isRunning() && worker->state() == ServiceWorkerState::Activated;
+    auto task = makeUnique<ServiceWorkerFetchTask>(*this, loader, ResourceRequest { request }, identifier(), worker->identifier(), *registration, session(), isWorkerReady);
     startFetch(*task, *worker);
     return task;
 }
@@ -503,7 +503,12 @@
 {
     return server().sessionID();
 }
-    
+
+NetworkSession* WebSWServerConnection::session()
+{
+    return m_networkProcess->networkSession(sessionID());
+}
+
 template<typename U> void WebSWServerConnection::sendToContextProcess(WebCore::SWServerToContextConnection& connection, U&& message)
 {
     static_cast<WebSWServerToContextConnection&>(connection).send(WTFMove(message));

Modified: trunk/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerConnection.h (286287 => 286288)


--- trunk/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerConnection.h	2021-11-30 09:19:15 UTC (rev 286287)
+++ trunk/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerConnection.h	2021-11-30 10:48:04 UTC (rev 286288)
@@ -75,7 +75,8 @@
     IPC::Connection& ipcConnection() const { return m_contentConnection.get(); }
 
     void didReceiveMessage(IPC::Connection&, IPC::Decoder&) final;
-    
+
+    NetworkSession* session();
     PAL::SessionID sessionID() const;
 
     std::unique_ptr<ServiceWorkerFetchTask> createFetchTask(NetworkResourceLoader&, const WebCore::ResourceRequest&);

Modified: trunk/Source/WebKit/NetworkProcess/webrtc/NetworkMDNSRegister.h (286287 => 286288)


--- trunk/Source/WebKit/NetworkProcess/webrtc/NetworkMDNSRegister.h	2021-11-30 09:19:15 UTC (rev 286287)
+++ trunk/Source/WebKit/NetworkProcess/webrtc/NetworkMDNSRegister.h	2021-11-30 10:48:04 UTC (rev 286288)
@@ -29,6 +29,7 @@
 
 #include "MDNSRegisterIdentifier.h"
 #include "RTCNetwork.h"
+#include <WebCore/ProcessQualified.h>
 #include <WebCore/ScriptExecutionContextIdentifier.h>
 #include <wtf/Expected.h>
 #include <wtf/Forward.h>

Modified: trunk/Source/WebKit/Sources.txt (286287 => 286288)


--- trunk/Source/WebKit/Sources.txt	2021-11-30 09:19:15 UTC (rev 286287)
+++ trunk/Source/WebKit/Sources.txt	2021-11-30 10:48:04 UTC (rev 286288)
@@ -134,6 +134,7 @@
 NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementManagerProxy.cpp
 
 NetworkProcess/ServiceWorker/ServiceWorkerFetchTask.cpp @no-unify
+NetworkProcess/ServiceWorker/ServiceWorkerNavigationPreloader.cpp
 NetworkProcess/ServiceWorker/ServiceWorkerSoftUpdateLoader.cpp
 NetworkProcess/ServiceWorker/WebSWOriginStore.cpp @no-unify
 NetworkProcess/ServiceWorker/WebSWServerConnection.cpp @no-unify

Modified: trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj (286287 => 286288)


--- trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj	2021-11-30 09:19:15 UTC (rev 286287)
+++ trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj	2021-11-30 10:48:04 UTC (rev 286288)
@@ -4112,6 +4112,8 @@
 		41E242DF26E0C904009A8C64 /* NetworkRTCUtilitiesCocoa.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = NetworkRTCUtilitiesCocoa.mm; sourceTree = "<group>"; };
 		41E67A8C25D2CFD0007B0A4C /* RemoteRealtimeAudioSource.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RemoteRealtimeAudioSource.h; sourceTree = "<group>"; };
 		41E67A8D25D2CFD0007B0A4C /* RemoteRealtimeAudioSource.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = RemoteRealtimeAudioSource.cpp; sourceTree = "<group>"; };
+		41EB4D3A274CE04500A9272B /* ServiceWorkerNavigationPreloader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ServiceWorkerNavigationPreloader.h; sourceTree = "<group>"; };
+		41EB4D3B274CE04500A9272B /* ServiceWorkerNavigationPreloader.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ServiceWorkerNavigationPreloader.cpp; sourceTree = "<group>"; };
 		41F060DD1654317500F3281C /* WebSocketChannelMessageReceiver.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = WebSocketChannelMessageReceiver.cpp; path = DerivedSources/WebKit2/WebSocketChannelMessageReceiver.cpp; sourceTree = BUILT_PRODUCTS_DIR; };
 		41F9FD1823ED8A810099B579 /* LibWebRTCResolverIdentifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LibWebRTCResolverIdentifier.h; path = Network/webrtc/LibWebRTCResolverIdentifier.h; sourceTree = "<group>"; };
 		41FABD281F4DDFDC006A6C97 /* CacheStorageEngineCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CacheStorageEngineCache.h; sourceTree = "<group>"; };
@@ -10283,6 +10285,8 @@
 				41518536222704F6005430C6 /* ServiceWorkerFetchTask.cpp */,
 				41518535222704F5005430C6 /* ServiceWorkerFetchTask.h */,
 				4151853822270F53005430C6 /* ServiceWorkerFetchTask.messages.in */,
+				41EB4D3B274CE04500A9272B /* ServiceWorkerNavigationPreloader.cpp */,
+				41EB4D3A274CE04500A9272B /* ServiceWorkerNavigationPreloader.h */,
 				41D5C6D9238EB20E00B9B3CB /* ServiceWorkerSoftUpdateLoader.cpp */,
 				41D5C6D8238EB20D00B9B3CB /* ServiceWorkerSoftUpdateLoader.h */,
 				93BA04DF2151ADF4007F455F /* WebSWOriginStore.cpp */,
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to