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 */,