Handle service worker loads through NetworkResourceLoader
https://bugs.webkit.org/show_bug.cgi?id=202309

Reviewed by Alex Christensen.

LayoutTests/imported/w3c:

* web-platform-tests/service-workers/service-worker/fetch-request-xhr.https-expected.txt:

Source/WebCore:

Allow to serialize HTTP header names as enumeration.
Updated SWServer ability to handle schemes by adding built-in support for HTTP and HTTPS as done in LegacySchemeRegistry.

Covered by existing tests.

* loader/ResourceLoaderOptions.h:
* platform/network/create-http-header-name-table:
* workers/service/server/SWServer.cpp:
(WebCore::SWServer::canHandleScheme const):
* workers/service/server/SWServer.h:
* workers/service/server/SWServerJobQueue.cpp:
(WebCore::SWServerJobQueue::runRegisterJob):

Source/WebKit:

Remove ServiceWorkerFetchClient.
Instead we use the normal NetworkResourceLoader/WebResourceLoader communication channel.
We pass additional parameters, in particular service worker mode and registration identifier.

Based on that information, network process will decide whether to load from service worker or network.
The first advantage is that in case of service worker not handling the load, going to the network is faster.
This will also allow us to do the registration matching in network process when receiving a navigation request.

ServiceWorkerFetchTask is now beefed up to do the link between service worker and NetworkResourceLoader/WebResourceLoader.
To support the same console logging, we add a new message called DidFailServiceWorkerLoad.

To support API tests, we continue to go to the service worker before trying to go to URL scheme handlers.
This adds some burden as we need to go to network process/service worker process and, in case load is not handled
by service worker, we go back to the web process to do the load through URL scheme handlers.
For that purpose we use ServiceWorkersMode::Only.

* CMakeLists.txt:
* DerivedSources-input.xcfilelist:
* DerivedSources-output.xcfilelist:
* DerivedSources.make:
* NetworkProcess/NetworkConnectionToWebProcess.cpp:
(WebKit::NetworkConnectionToWebProcess::scheduleResourceLoad):
* NetworkProcess/NetworkResourceLoadParameters.cpp:
(WebKit::NetworkResourceLoadParameters::encode const):
(WebKit::NetworkResourceLoadParameters::decode):
* NetworkProcess/NetworkResourceLoadParameters.h:
* NetworkProcess/NetworkResourceLoader.cpp:
(WebKit::NetworkResourceLoader::abort):
(WebKit::NetworkResourceLoader::didFailLoading):
(WebKit::NetworkResourceLoader::continueWillSendRequest):
(WebKit::NetworkResourceLoader::continueDidReceiveResponse):
(WebKit::NetworkResourceLoader::startWithServiceWorker):
(WebKit::NetworkResourceLoader::serviceWorkerDidNotHandle):
* NetworkProcess/NetworkResourceLoader.h:
* NetworkProcess/ServiceWorker/ServiceWorkerFetchTask.cpp:
(WebKit::ServiceWorkerFetchTask::ServiceWorkerFetchTask):
(WebKit::ServiceWorkerFetchTask::~ServiceWorkerFetchTask):
(WebKit::ServiceWorkerFetchTask::sendToServiceWorker):
(WebKit::ServiceWorkerFetchTask::sendToClient):
(WebKit::ServiceWorkerFetchTask::start):
(WebKit::ServiceWorkerFetchTask::startFetch):
(WebKit::ServiceWorkerFetchTask::didReceiveRedirectResponse):
(WebKit::ServiceWorkerFetchTask::didReceiveResponse):
(WebKit::ServiceWorkerFetchTask::didReceiveData):
(WebKit::ServiceWorkerFetchTask::didReceiveFormData):
(WebKit::ServiceWorkerFetchTask::didFinish):
(WebKit::ServiceWorkerFetchTask::didFail):
(WebKit::ServiceWorkerFetchTask::didNotHandle):
(WebKit::ServiceWorkerFetchTask::cancelFromClient):
(WebKit::ServiceWorkerFetchTask::continueDidReceiveFetchResponse):
(WebKit::ServiceWorkerFetchTask::continueFetchTaskWith):
(WebKit::ServiceWorkerFetchTask::timeoutTimerFired):
* NetworkProcess/ServiceWorker/ServiceWorkerFetchTask.h:
(WebKit::ServiceWorkerFetchTask::fetchIdentifier const):
(WebKit::ServiceWorkerFetchTask::serviceWorkerIdentifier const):
* NetworkProcess/ServiceWorker/WebSWServerConnection.cpp:
(WebKit::WebSWServerConnection::cancelFetch):
(WebKit::WebSWServerConnection::createFetchTask):
(WebKit::WebSWServerConnection::startFetch):
* NetworkProcess/ServiceWorker/WebSWServerConnection.h:
* NetworkProcess/ServiceWorker/WebSWServerConnection.messages.in:
* NetworkProcess/ServiceWorker/WebSWServerToContextConnection.cpp:
(WebKit::WebSWServerToContextConnection::startFetch):
(WebKit::WebSWServerToContextConnection::continueDidReceiveFetchResponse):
(WebKit::WebSWServerToContextConnection::didReceiveFetchTaskMessage):
(WebKit::WebSWServerToContextConnection::registerFetch):
(WebKit::WebSWServerToContextConnection::unregisterFetch):
(WebKit::WebSWServerToContextConnection::fetchTaskTimedOut):
* NetworkProcess/ServiceWorker/WebSWServerToContextConnection.h:
(WebKit::WebSWServerToContextConnection::ipcConnection const):
* Sources.txt:
* WebKit.xcodeproj/project.pbxproj:
* WebProcess/Network/NetworkProcessConnection.cpp:
(WebKit::NetworkProcessConnection::didReceiveMessage):
* WebProcess/Network/WebLoaderStrategy.cpp:
(WebKit::WebLoaderStrategy::scheduleLoad):
* WebProcess/Network/WebResourceLoader.cpp:
(WebKit::WebResourceLoader::didFailServiceWorkerLoad):
(WebKit::WebResourceLoader::serviceWorkerDidNotHandle):
* WebProcess/Network/WebResourceLoader.h:
* WebProcess/Network/WebResourceLoader.messages.in:
* WebProcess/Storage/ServiceWorkerClientFetch.cpp: Removed.
* WebProcess/Storage/ServiceWorkerClientFetch.h: Removed.
* WebProcess/Storage/ServiceWorkerClientFetch.messages.in: Removed.
* WebProcess/Storage/WebSWClientConnection.cpp:
* WebProcess/Storage/WebSWClientConnection.h:
* WebProcess/Storage/WebServiceWorkerProvider.cpp:
* WebProcess/Storage/WebServiceWorkerProvider.h:


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@251124 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/imported/w3c/ChangeLog b/LayoutTests/imported/w3c/ChangeLog
index ef1905e..9552aa16 100644
--- a/LayoutTests/imported/w3c/ChangeLog
+++ b/LayoutTests/imported/w3c/ChangeLog
@@ -1,3 +1,12 @@
+2019-10-14  Youenn Fablet  <youenn@apple.com>
+
+        Handle service worker loads through NetworkResourceLoader
+        https://bugs.webkit.org/show_bug.cgi?id=202309
+
+        Reviewed by Alex Christensen.
+
+        * web-platform-tests/service-workers/service-worker/fetch-request-xhr.https-expected.txt:
+
 2019-10-14  Ryosuke Niwa  <rniwa@webkit.org>
 
         Import W3C tests for requestidlecallback
diff --git a/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/fetch-request-xhr.https-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/fetch-request-xhr.https-expected.txt
index 4fb6bb5..85aa00b 100644
--- a/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/fetch-request-xhr.https-expected.txt
+++ b/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/fetch-request-xhr.https-expected.txt
@@ -8,7 +8,7 @@
 PASS FetchEvent#request.body contains XHR request data (blob) 
 PASS FetchEvent#request.method is set to XHR method 
 PASS XHR using OPTIONS method 
-FAIL XHR with form data promise_test: Unhandled rejection with value: object "Error: assert_equals: expected (string) "POST" but got (undefined) undefined"
+PASS XHR with form data 
 PASS XHR with mode/credentials set 
 PASS XHR to data URL 
 PASS restore global state 
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 8a9b206..0b4d5d3 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,23 @@
+2019-10-14  Youenn Fablet  <youenn@apple.com>
+
+        Handle service worker loads through NetworkResourceLoader
+        https://bugs.webkit.org/show_bug.cgi?id=202309
+
+        Reviewed by Alex Christensen.
+
+        Allow to serialize HTTP header names as enumeration.
+        Updated SWServer ability to handle schemes by adding built-in support for HTTP and HTTPS as done in LegacySchemeRegistry.
+
+        Covered by existing tests.
+
+        * loader/ResourceLoaderOptions.h:
+        * platform/network/create-http-header-name-table:
+        * workers/service/server/SWServer.cpp:
+        (WebCore::SWServer::canHandleScheme const):
+        * workers/service/server/SWServer.h:
+        * workers/service/server/SWServerJobQueue.cpp:
+        (WebCore::SWServerJobQueue::runRegisterJob):
+
 2019-10-14  Tim Horton  <timothy_horton@apple.com>
 
         Unify sources for bindings more densely
diff --git a/Source/WebCore/loader/ResourceLoaderOptions.h b/Source/WebCore/loader/ResourceLoaderOptions.h
index 9e3074d..dbea1bf 100644
--- a/Source/WebCore/loader/ResourceLoaderOptions.h
+++ b/Source/WebCore/loader/ResourceLoaderOptions.h
@@ -31,6 +31,7 @@
 #pragma once
 
 #include "ContentSecurityPolicyResponseHeaders.h"
+#include "CrossOriginAccessControl.h"
 #include "FetchOptions.h"
 #include "HTTPHeaderNames.h"
 #include "ServiceWorkerTypes.h"
@@ -151,7 +152,7 @@
 #if ENABLE(SERVICE_WORKER)
     Optional<ServiceWorkerRegistrationIdentifier> serviceWorkerRegistrationIdentifier;
 #endif
-    HashSet<HTTPHeaderName, WTF::IntHash<HTTPHeaderName>, WTF::StrongEnumHashTraits<HTTPHeaderName>> httpHeadersToKeep;
+    HTTPHeaderNameSet httpHeadersToKeep;
     Optional<ContentSecurityPolicyResponseHeaders> cspResponseHeaders;
     unsigned maxRedirectCount { 20 };
 
@@ -175,3 +176,16 @@
 };
 
 } // namespace WebCore
+
+namespace WTF {
+
+template<> struct EnumTraits<WebCore::ServiceWorkersMode> {
+    using values = EnumValues<
+        WebCore::ServiceWorkersMode,
+        WebCore::ServiceWorkersMode::All,
+        WebCore::ServiceWorkersMode::None,
+        WebCore::ServiceWorkersMode::Only
+    >;
+};
+
+} // namespace WTF
diff --git a/Source/WebCore/platform/network/create-http-header-name-table b/Source/WebCore/platform/network/create-http-header-name-table
index 647cdd8..439db68 100755
--- a/Source/WebCore/platform/network/create-http-header-name-table
+++ b/Source/WebCore/platform/network/create-http-header-name-table
@@ -233,6 +233,28 @@
 
 } // namespace WebCore
 
+namespace WTF {
+
+template<> struct EnumTraits<WebCore::HTTPHeaderName> {
+    using values = EnumValues<
+        WebCore::HTTPHeaderName,
+''')
+
+is_first = True
+for http_header_name in http_header_names:
+    if is_first:
+        is_first = False
+    else:
+    	header_file.write(',\n')
+
+    header_file.write('        WebCore::HTTPHeaderName::%s' % http_header_name_to_id[http_header_name])
+
+header_file.write('''
+    >;
+};
+
+} // namespace WTF
+
 #endif // HTTPHeaderNames_h
 ''')
 header_file.close()
diff --git a/Source/WebCore/workers/service/server/SWServer.cpp b/Source/WebCore/workers/service/server/SWServer.cpp
index 9bb66ab..3718860 100644
--- a/Source/WebCore/workers/service/server/SWServer.cpp
+++ b/Source/WebCore/workers/service/server/SWServer.cpp
@@ -974,6 +974,21 @@
     m_createContextConnectionCallback(registrableDomain);
 }
 
+bool SWServer::canHandleScheme(StringView scheme) const
+{
+    if (scheme.isNull())
+        return false;
+
+    if (equalLettersIgnoringASCIICase(scheme.substring(0, 4), "http")) {
+        if (scheme.length() == 4)
+            return true;
+        if (scheme.length() == 5 && isASCIIAlphaCaselessEqual(scheme[4], 's'))
+            return true;
+    }
+
+    return m_registeredSchemes.contains(scheme.toStringWithoutCopying());
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(SERVICE_WORKER)
diff --git a/Source/WebCore/workers/service/server/SWServer.h b/Source/WebCore/workers/service/server/SWServer.h
index 4601317..e3ec1be 100644
--- a/Source/WebCore/workers/service/server/SWServer.h
+++ b/Source/WebCore/workers/service/server/SWServer.h
@@ -164,7 +164,7 @@
     Connection* connection(SWServerConnectionIdentifier identifier) const { return m_connections.get(identifier); }
 
     const HashMap<SWServerConnectionIdentifier, std::unique_ptr<Connection>>& connections() const { return m_connections; }
-    const HashSet<String> registeredSchemes() const { return m_registeredSchemes; }
+    WEBCORE_EXPORT bool canHandleScheme(StringView) const;
 
     SWOriginStore& originStore() { return m_originStore; }
 
diff --git a/Source/WebCore/workers/service/server/SWServerJobQueue.cpp b/Source/WebCore/workers/service/server/SWServerJobQueue.cpp
index 778ae7d..6d7cda0 100644
--- a/Source/WebCore/workers/service/server/SWServerJobQueue.cpp
+++ b/Source/WebCore/workers/service/server/SWServerJobQueue.cpp
@@ -259,7 +259,7 @@
 {
     ASSERT(job.type == ServiceWorkerJobType::Register);
 
-    if (!shouldTreatAsPotentiallyTrustworthy(job.scriptURL) && !m_server.registeredSchemes().contains(job.scriptURL.protocol().toStringWithoutCopying()))
+    if (!shouldTreatAsPotentiallyTrustworthy(job.scriptURL) && !m_server.canHandleScheme(job.scriptURL.protocol()))
         return rejectCurrentJob(ExceptionData { SecurityError, "Script URL is not potentially trustworthy"_s });
 
     // If the origin of job's script url is not job's referrer's origin, then:
diff --git a/Source/WebKit/CMakeLists.txt b/Source/WebKit/CMakeLists.txt
index f7cd18b..1e06e62 100644
--- a/Source/WebKit/CMakeLists.txt
+++ b/Source/WebKit/CMakeLists.txt
@@ -190,7 +190,6 @@
     WebProcess/Plugins/PluginProcessConnectionManager.messages.in
     WebProcess/Plugins/PluginProxy.messages.in
 
-    WebProcess/Storage/ServiceWorkerClientFetch.messages.in
     WebProcess/Storage/WebSWClientConnection.messages.in
     WebProcess/Storage/WebSWContextManagerConnection.messages.in
 
diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog
index 13228d3..937f98a 100644
--- a/Source/WebKit/ChangeLog
+++ b/Source/WebKit/ChangeLog
@@ -1,3 +1,99 @@
+2019-10-14  Youenn Fablet  <youenn@apple.com>
+
+        Handle service worker loads through NetworkResourceLoader
+        https://bugs.webkit.org/show_bug.cgi?id=202309
+
+        Reviewed by Alex Christensen.
+
+        Remove ServiceWorkerFetchClient.
+        Instead we use the normal NetworkResourceLoader/WebResourceLoader communication channel.
+        We pass additional parameters, in particular service worker mode and registration identifier.
+
+        Based on that information, network process will decide whether to load from service worker or network.
+        The first advantage is that in case of service worker not handling the load, going to the network is faster.
+        This will also allow us to do the registration matching in network process when receiving a navigation request.
+
+        ServiceWorkerFetchTask is now beefed up to do the link between service worker and NetworkResourceLoader/WebResourceLoader.
+        To support the same console logging, we add a new message called DidFailServiceWorkerLoad.
+
+        To support API tests, we continue to go to the service worker before trying to go to URL scheme handlers.
+        This adds some burden as we need to go to network process/service worker process and, in case load is not handled
+        by service worker, we go back to the web process to do the load through URL scheme handlers.
+        For that purpose we use ServiceWorkersMode::Only.
+
+        * CMakeLists.txt:
+        * DerivedSources-input.xcfilelist:
+        * DerivedSources-output.xcfilelist:
+        * DerivedSources.make:
+        * NetworkProcess/NetworkConnectionToWebProcess.cpp:
+        (WebKit::NetworkConnectionToWebProcess::scheduleResourceLoad):
+        * NetworkProcess/NetworkResourceLoadParameters.cpp:
+        (WebKit::NetworkResourceLoadParameters::encode const):
+        (WebKit::NetworkResourceLoadParameters::decode):
+        * NetworkProcess/NetworkResourceLoadParameters.h:
+        * NetworkProcess/NetworkResourceLoader.cpp:
+        (WebKit::NetworkResourceLoader::abort):
+        (WebKit::NetworkResourceLoader::didFailLoading):
+        (WebKit::NetworkResourceLoader::continueWillSendRequest):
+        (WebKit::NetworkResourceLoader::continueDidReceiveResponse):
+        (WebKit::NetworkResourceLoader::startWithServiceWorker):
+        (WebKit::NetworkResourceLoader::serviceWorkerDidNotHandle):
+        * NetworkProcess/NetworkResourceLoader.h:
+        * NetworkProcess/ServiceWorker/ServiceWorkerFetchTask.cpp:
+        (WebKit::ServiceWorkerFetchTask::ServiceWorkerFetchTask):
+        (WebKit::ServiceWorkerFetchTask::~ServiceWorkerFetchTask):
+        (WebKit::ServiceWorkerFetchTask::sendToServiceWorker):
+        (WebKit::ServiceWorkerFetchTask::sendToClient):
+        (WebKit::ServiceWorkerFetchTask::start):
+        (WebKit::ServiceWorkerFetchTask::startFetch):
+        (WebKit::ServiceWorkerFetchTask::didReceiveRedirectResponse):
+        (WebKit::ServiceWorkerFetchTask::didReceiveResponse):
+        (WebKit::ServiceWorkerFetchTask::didReceiveData):
+        (WebKit::ServiceWorkerFetchTask::didReceiveFormData):
+        (WebKit::ServiceWorkerFetchTask::didFinish):
+        (WebKit::ServiceWorkerFetchTask::didFail):
+        (WebKit::ServiceWorkerFetchTask::didNotHandle):
+        (WebKit::ServiceWorkerFetchTask::cancelFromClient):
+        (WebKit::ServiceWorkerFetchTask::continueDidReceiveFetchResponse):
+        (WebKit::ServiceWorkerFetchTask::continueFetchTaskWith):
+        (WebKit::ServiceWorkerFetchTask::timeoutTimerFired):
+        * NetworkProcess/ServiceWorker/ServiceWorkerFetchTask.h:
+        (WebKit::ServiceWorkerFetchTask::fetchIdentifier const):
+        (WebKit::ServiceWorkerFetchTask::serviceWorkerIdentifier const):
+        * NetworkProcess/ServiceWorker/WebSWServerConnection.cpp:
+        (WebKit::WebSWServerConnection::cancelFetch):
+        (WebKit::WebSWServerConnection::createFetchTask):
+        (WebKit::WebSWServerConnection::startFetch):
+        * NetworkProcess/ServiceWorker/WebSWServerConnection.h:
+        * NetworkProcess/ServiceWorker/WebSWServerConnection.messages.in:
+        * NetworkProcess/ServiceWorker/WebSWServerToContextConnection.cpp:
+        (WebKit::WebSWServerToContextConnection::startFetch):
+        (WebKit::WebSWServerToContextConnection::continueDidReceiveFetchResponse):
+        (WebKit::WebSWServerToContextConnection::didReceiveFetchTaskMessage):
+        (WebKit::WebSWServerToContextConnection::registerFetch):
+        (WebKit::WebSWServerToContextConnection::unregisterFetch):
+        (WebKit::WebSWServerToContextConnection::fetchTaskTimedOut):
+        * NetworkProcess/ServiceWorker/WebSWServerToContextConnection.h:
+        (WebKit::WebSWServerToContextConnection::ipcConnection const):
+        * Sources.txt:
+        * WebKit.xcodeproj/project.pbxproj:
+        * WebProcess/Network/NetworkProcessConnection.cpp:
+        (WebKit::NetworkProcessConnection::didReceiveMessage):
+        * WebProcess/Network/WebLoaderStrategy.cpp:
+        (WebKit::WebLoaderStrategy::scheduleLoad):
+        * WebProcess/Network/WebResourceLoader.cpp:
+        (WebKit::WebResourceLoader::didFailServiceWorkerLoad):
+        (WebKit::WebResourceLoader::serviceWorkerDidNotHandle):
+        * WebProcess/Network/WebResourceLoader.h:
+        * WebProcess/Network/WebResourceLoader.messages.in:
+        * WebProcess/Storage/ServiceWorkerClientFetch.cpp: Removed.
+        * WebProcess/Storage/ServiceWorkerClientFetch.h: Removed.
+        * WebProcess/Storage/ServiceWorkerClientFetch.messages.in: Removed.
+        * WebProcess/Storage/WebSWClientConnection.cpp:
+        * WebProcess/Storage/WebSWClientConnection.h:
+        * WebProcess/Storage/WebServiceWorkerProvider.cpp:
+        * WebProcess/Storage/WebServiceWorkerProvider.h:
+
 2019-10-14  Carlos Garcia Campos  <cgarcia@igalia.com>
 
         [GTK] White pages in AC mode: Cannot get default EGL display: EGL_BAD_PARAMETER
diff --git a/Source/WebKit/DerivedSources-input.xcfilelist b/Source/WebKit/DerivedSources-input.xcfilelist
index 2e47660..f1adad6 100644
--- a/Source/WebKit/DerivedSources-input.xcfilelist
+++ b/Source/WebKit/DerivedSources-input.xcfilelist
@@ -105,7 +105,6 @@
 $(PROJECT_DIR)/WebProcess/Plugins/PluginProcessConnection.messages.in
 $(PROJECT_DIR)/WebProcess/Plugins/PluginProcessConnectionManager.messages.in
 $(PROJECT_DIR)/WebProcess/Plugins/PluginProxy.messages.in
-$(PROJECT_DIR)/WebProcess/Storage/ServiceWorkerClientFetch.messages.in
 $(PROJECT_DIR)/WebProcess/Storage/WebSWClientConnection.messages.in
 $(PROJECT_DIR)/WebProcess/Storage/WebSWContextManagerConnection.messages.in
 $(PROJECT_DIR)/WebProcess/UserContent/WebUserContentController.messages.in
diff --git a/Source/WebKit/DerivedSources-output.xcfilelist b/Source/WebKit/DerivedSources-output.xcfilelist
index bd9dd7f..1c5d214 100644
--- a/Source/WebKit/DerivedSources-output.xcfilelist
+++ b/Source/WebKit/DerivedSources-output.xcfilelist
@@ -80,8 +80,6 @@
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/RemoteWebInspectorUIMessages.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/SecItemShimProxyMessageReceiver.cpp
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/SecItemShimProxyMessages.h
-$(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/ServiceWorkerClientFetchMessageReceiver.cpp
-$(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/ServiceWorkerClientFetchMessages.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/ServiceWorkerFetchTaskMessageReceiver.cpp
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/ServiceWorkerFetchTaskMessages.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/SmartMagnificationControllerMessageReceiver.cpp
diff --git a/Source/WebKit/DerivedSources.make b/Source/WebKit/DerivedSources.make
index 9de7042..bae7c31 100644
--- a/Source/WebKit/DerivedSources.make
+++ b/Source/WebKit/DerivedSources.make
@@ -132,7 +132,6 @@
     RemoteWebInspectorProxy \
     RemoteWebInspectorUI \
     SecItemShimProxy \
-    ServiceWorkerClientFetch \
     ServiceWorkerFetchTask \
     SmartMagnificationController \
     StorageAreaMap \
diff --git a/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp b/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp
index 247c71a..c8a0766 100644
--- a/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp
+++ b/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp
@@ -405,9 +405,13 @@
     RELEASE_ASSERT(RunLoop::isMain());
     ASSERT(!m_networkResourceLoaders.contains(identifier));
 
-    auto loader = NetworkResourceLoader::create(WTFMove(loadParameters), *this);
-    m_networkResourceLoaders.add(identifier, loader.copyRef());
+    auto& loader = m_networkResourceLoaders.add(identifier, NetworkResourceLoader::create(WTFMove(loadParameters), *this)).iterator->value;
+
+#if ENABLE(SERVICE_WORKER)
+    loader->startWithServiceWorker(m_swConnection.get());
+#else
     loader->start();
+#endif
 }
 
 void NetworkConnectionToWebProcess::performSynchronousLoad(NetworkResourceLoadParameters&& loadParameters, Messages::NetworkConnectionToWebProcess::PerformSynchronousLoad::DelayedReply&& reply)
diff --git a/Source/WebKit/NetworkProcess/NetworkResourceLoadParameters.cpp b/Source/WebKit/NetworkProcess/NetworkResourceLoadParameters.cpp
index e28c7d1..8dbd25e 100644
--- a/Source/WebKit/NetworkProcess/NetworkResourceLoadParameters.cpp
+++ b/Source/WebKit/NetworkProcess/NetworkResourceLoadParameters.cpp
@@ -107,6 +107,12 @@
     encoder << frameAncestorOrigins;
     encoder << isHTTPSUpgradeEnabled;
 
+#if ENABLE(SERVICE_WORKER)
+    encoder << serviceWorkersMode;
+    encoder << serviceWorkerRegistrationIdentifier;
+    encoder << httpHeadersToKeep;
+#endif
+
 #if ENABLE(CONTENT_EXTENSIONS)
     encoder << mainDocumentURL;
     encoder << userContentControllerIdentifier;
@@ -242,7 +248,27 @@
     if (!isHTTPSUpgradeEnabled)
         return WTF::nullopt;
     result.isHTTPSUpgradeEnabled = *isHTTPSUpgradeEnabled;
-    
+
+#if ENABLE(SERVICE_WORKER)
+    Optional<ServiceWorkersMode> serviceWorkersMode;
+    decoder >> serviceWorkersMode;
+    if (!serviceWorkersMode)
+        return WTF::nullopt;
+    result.serviceWorkersMode = *serviceWorkersMode;
+
+    Optional<Optional<ServiceWorkerRegistrationIdentifier>> serviceWorkerRegistrationIdentifier;
+    decoder >> serviceWorkerRegistrationIdentifier;
+    if (!serviceWorkerRegistrationIdentifier)
+        return WTF::nullopt;
+    result.serviceWorkerRegistrationIdentifier = *serviceWorkerRegistrationIdentifier;
+
+    Optional<HTTPHeaderNameSet> httpHeadersToKeep;
+    decoder >> httpHeadersToKeep;
+    if (!httpHeadersToKeep)
+        return WTF::nullopt;
+    result.httpHeadersToKeep = WTFMove(*httpHeadersToKeep);
+#endif
+
 #if ENABLE(CONTENT_EXTENSIONS)
     if (!decoder.decode(result.mainDocumentURL))
         return WTF::nullopt;
diff --git a/Source/WebKit/NetworkProcess/NetworkResourceLoadParameters.h b/Source/WebKit/NetworkProcess/NetworkResourceLoadParameters.h
index 1203470..e87dc7a 100644
--- a/Source/WebKit/NetworkProcess/NetworkResourceLoadParameters.h
+++ b/Source/WebKit/NetworkProcess/NetworkResourceLoadParameters.h
@@ -29,6 +29,7 @@
 #include "SandboxExtension.h"
 #include "UserContentControllerIdentifier.h"
 #include <WebCore/ContentSecurityPolicyResponseHeaders.h>
+#include <WebCore/CrossOriginAccessControl.h>
 #include <WebCore/FetchOptions.h>
 #include <wtf/Seconds.h>
 
@@ -60,6 +61,12 @@
     Vector<RefPtr<WebCore::SecurityOrigin>> frameAncestorOrigins;
     bool isHTTPSUpgradeEnabled { false };
 
+#if ENABLE(SERVICE_WORKER)
+    WebCore::ServiceWorkersMode serviceWorkersMode { WebCore::ServiceWorkersMode::None };
+    Optional<WebCore::ServiceWorkerRegistrationIdentifier> serviceWorkerRegistrationIdentifier;
+    WebCore::HTTPHeaderNameSet httpHeadersToKeep;
+#endif
+
 #if ENABLE(CONTENT_EXTENSIONS)
     URL mainDocumentURL;
     Optional<UserContentControllerIdentifier> userContentControllerIdentifier;
diff --git a/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp b/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp
index fb372d7..8797939 100644
--- a/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp
+++ b/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp
@@ -379,6 +379,11 @@
         return;
     }
 
+#if ENABLE(SERVICE_WORKER)
+    if (auto task = WTFMove(m_serviceWorkerFetchTask))
+        task->cancelFromClient();
+#endif
+
     if (m_networkLoad) {
         if (canUseCache(m_networkLoad->currentRequest())) {
             // We might already have used data from this incomplete load. Ensure older versions don't remain in the cache after cancel.
@@ -612,8 +617,16 @@
     if (isSynchronous()) {
         m_synchronousLoadData->error = error;
         sendReplyToSynchronousRequest(*m_synchronousLoadData, nullptr);
-    } else if (auto* connection = messageSenderConnection())
+    } else if (auto* connection = messageSenderConnection()) {
+#if ENABLE(SERVICE_WORKER)
+        if (m_serviceWorkerFetchTask)
+            connection->send(Messages::WebResourceLoader::DidFailServiceWorkerLoad(error), messageSenderDestinationID());
+        else
+            connection->send(Messages::WebResourceLoader::DidFailResourceLoad(error), messageSenderDestinationID());
+#else
         connection->send(Messages::WebResourceLoader::DidFailResourceLoad(error), messageSenderDestinationID());
+#endif
+    }
 
     cleanup(LoadResult::Failure);
 }
@@ -747,6 +760,10 @@
 
 void NetworkResourceLoader::continueWillSendRequest(ResourceRequest&& newRequest, bool isAllowedToAskUserForCredentials)
 {
+    if (m_serviceWorkerFetchTask) {
+        m_serviceWorkerFetchTask->continueFetchTaskWith(WTFMove(newRequest));
+        return;
+    }
     if (m_shouldRestartLoad) {
         m_shouldRestartLoad = false;
 
@@ -792,6 +809,11 @@
 
 void NetworkResourceLoader::continueDidReceiveResponse()
 {
+    if (m_serviceWorkerFetchTask) {
+        m_serviceWorkerFetchTask->continueDidReceiveFetchResponse();
+        return;
+    }
+
     if (m_cacheEntryWaitingForContinueDidReceiveResponse) {
         sendResultForCacheEntry(WTFMove(m_cacheEntryWaitingForContinueDidReceiveResponse));
         cleanup(LoadResult::Success);
@@ -1196,6 +1218,31 @@
     return request.httpHeaderField(HTTPHeaderName::Purpose) == "prefetch" && !m_parameters.sourceOrigin->canRequest(request.url());
 }
 
+#if ENABLE(SERVICE_WORKER)
+void NetworkResourceLoader::startWithServiceWorker(WebSWServerConnection* swConnection)
+{
+    ASSERT(!m_serviceWorkerFetchTask);
+    m_serviceWorkerFetchTask = swConnection ? swConnection->createFetchTask(*this) : nullptr;
+    if (m_serviceWorkerFetchTask)
+        return;
+
+    serviceWorkerDidNotHandle();
+}
+
+void NetworkResourceLoader::serviceWorkerDidNotHandle()
+{
+    if (m_parameters.serviceWorkersMode == ServiceWorkersMode::Only) {
+        send(Messages::WebResourceLoader::ServiceWorkerDidNotHandle { }, identifier());
+        abort();
+        return;
+    }
+
+    m_serviceWorkerFetchTask = nullptr;
+    start();
+}
+
+#endif
+
 } // namespace WebKit
 
 #undef RELEASE_LOG_IF_ALLOWED
diff --git a/Source/WebKit/NetworkProcess/NetworkResourceLoader.h b/Source/WebKit/NetworkProcess/NetworkResourceLoader.h
index d65072b..71f81bb 100644
--- a/Source/WebKit/NetworkProcess/NetworkResourceLoader.h
+++ b/Source/WebKit/NetworkProcess/NetworkResourceLoader.h
@@ -51,6 +51,8 @@
 class NetworkConnectionToWebProcess;
 class NetworkLoad;
 class NetworkLoadChecker;
+class ServiceWorkerFetchTask;
+class WebSWServerConnection;
 
 namespace NetworkCache {
 class Entry;
@@ -88,7 +90,8 @@
     ResourceLoadIdentifier identifier() const { return m_parameters.identifier; }
     WebCore::FrameIdentifier frameID() const { return m_parameters.webFrameID; }
     WebCore::PageIdentifier pageID() const { return m_parameters.webPageID; }
-    
+    const NetworkResourceLoadParameters& parameters() const { return m_parameters; }
+
     NetworkCache::GlobalFrameID globalFrameID() { return { m_parameters.webPageProxyID, pageID(), frameID() }; }
 
     struct SynchronousLoadData;
@@ -122,6 +125,11 @@
 
     bool isKeptAlive() const { return m_isKeptAlive; }
 
+#if ENABLE(SERVICE_WORKER)
+    void startWithServiceWorker(WebSWServerConnection*);
+    void serviceWorkerDidNotHandle();
+#endif
+
 private:
     NetworkResourceLoader(NetworkResourceLoadParameters&&, NetworkConnectionToWebProcess&, Messages::NetworkConnectionToWebProcess::PerformSynchronousLoad::DelayedReply&&);
 
@@ -220,6 +228,9 @@
     bool m_isKeptAlive { false };
 
     Optional<NetworkActivityTracker> m_networkActivityTracker;
+#if ENABLE(SERVICE_WORKER)
+    std::unique_ptr<ServiceWorkerFetchTask> m_serviceWorkerFetchTask;
+#endif
 };
 
 } // namespace WebKit
diff --git a/Source/WebKit/NetworkProcess/ServiceWorker/ServiceWorkerFetchTask.cpp b/Source/WebKit/NetworkProcess/ServiceWorker/ServiceWorkerFetchTask.cpp
index 834b569..d457e21 100644
--- a/Source/WebKit/NetworkProcess/ServiceWorker/ServiceWorkerFetchTask.cpp
+++ b/Source/WebKit/NetworkProcess/ServiceWorker/ServiceWorkerFetchTask.cpp
@@ -32,10 +32,14 @@
 #include "DataReference.h"
 #include "FormDataReference.h"
 #include "Logging.h"
-#include "ServiceWorkerClientFetchMessages.h"
+#include "NetworkProcess.h"
+#include "NetworkResourceLoader.h"
+#include "SharedBufferDataReference.h"
 #include "WebCoreArgumentCoders.h"
-#include "WebSWServerConnection.h"
+#include "WebResourceLoaderMessages.h"
+#include "WebSWContextManagerConnectionMessages.h"
 #include "WebSWServerToContextConnection.h"
+#include <WebCore/CrossOriginAccessControl.h>
 
 #define RELEASE_LOG_IF_ALLOWED(fmt, ...) RELEASE_LOG_IF(m_sessionID.isAlwaysOnLoggingAllowed(), ServiceWorker, "%p - ServiceWorkerFetchTask::" fmt, this, ##__VA_ARGS__)
 #define RELEASE_LOG_ERROR_IF_ALLOWED(fmt, ...) RELEASE_LOG_ERROR_IF(m_sessionID.isAlwaysOnLoggingAllowed(), ServiceWorker, "%p - ServiceWorkerFetchTask::" fmt, this, ##__VA_ARGS__)
@@ -44,80 +48,135 @@
 
 namespace WebKit {
 
-ServiceWorkerFetchTask::ServiceWorkerFetchTask(PAL::SessionID sessionID, WebSWServerConnection& connection, WebSWServerToContextConnection& contextConnection, FetchIdentifier fetchIdentifier, ServiceWorkerIdentifier serviceWorkerIdentifier, Seconds timeout)
+ServiceWorkerFetchTask::ServiceWorkerFetchTask(PAL::SessionID sessionID, NetworkResourceLoader& loader, SWServerConnectionIdentifier serverConnectionIdentifier, ServiceWorkerIdentifier serviceWorkerIdentifier)
     : m_sessionID(sessionID)
-    , m_connection(makeWeakPtr(connection))
-    , m_contextConnection(contextConnection)
-    , m_identifier { connection.identifier(), fetchIdentifier }
+    , m_loader(loader)
+    , m_fetchIdentifier(WebCore::FetchIdentifier::generate())
+    , m_serverConnectionIdentifier(serverConnectionIdentifier)
     , m_serviceWorkerIdentifier(serviceWorkerIdentifier)
-    , m_timeout(timeout)
     , m_timeoutTimer(*this, &ServiceWorkerFetchTask::timeoutTimerFired)
 {
-    m_timeoutTimer.startOneShot(m_timeout);
+    m_timeoutTimer.startOneShot(loader.connectionToWebProcess().networkProcess().serviceWorkerFetchTimeout());
 }
 
-void ServiceWorkerFetchTask::didReceiveRedirectResponse(const ResourceResponse& response)
+ServiceWorkerFetchTask::~ServiceWorkerFetchTask()
 {
-    RELEASE_LOG_IF_ALLOWED("didReceiveRedirectResponse: %s", m_identifier.fetchIdentifier.loggingString().utf8().data());
-    m_timeoutTimer.stop();
-    m_wasHandled = true;
-    if (m_connection)
-        m_connection->send(Messages::ServiceWorkerClientFetch::DidReceiveRedirectResponse { response }, m_identifier.fetchIdentifier);
+    if (m_serviceWorkerConnection)
+        m_serviceWorkerConnection->unregisterFetch(*this);
 }
 
-void ServiceWorkerFetchTask::didReceiveResponse(const ResourceResponse& response, bool needsContinueDidReceiveResponseMessage)
+template<typename Message> bool ServiceWorkerFetchTask::sendToServiceWorker(Message&& message)
 {
-    RELEASE_LOG_IF_ALLOWED("didReceiveResponse: %s", m_identifier.fetchIdentifier.loggingString().utf8().data());
+    return m_serviceWorkerConnection ? m_serviceWorkerConnection->ipcConnection().send(std::forward<Message>(message), 0) : false;
+}
+
+template<typename Message> bool ServiceWorkerFetchTask::sendToClient(Message&& message)
+{
+    return m_loader.connectionToWebProcess().connection().send(std::forward<Message>(message), m_loader.identifier());
+}
+
+void ServiceWorkerFetchTask::start(WebSWServerToContextConnection& serviceWorkerConnection)
+{
+    m_serviceWorkerConnection = makeWeakPtr(serviceWorkerConnection);
+    serviceWorkerConnection.registerFetch(*this);
+
+    startFetch(ResourceRequest { m_loader.originalRequest() }, serviceWorkerConnection);
+}
+
+void ServiceWorkerFetchTask::startFetch(ResourceRequest&& request, WebSWServerToContextConnection& serviceWorkerConnection)
+{
+    m_currentRequest = WTFMove(request);
+
+    auto& options = m_loader.parameters().options;
+    auto referrer = m_currentRequest.httpReferrer();
+
+    // We are intercepting fetch calls after going through the HTTP layer, which may add some specific headers.
+    cleanHTTPRequestHeadersForAccessControl(m_currentRequest, m_loader.parameters().httpHeadersToKeep);
+
+    bool isSent = sendToServiceWorker(Messages::WebSWContextManagerConnection::StartFetch { m_serverConnectionIdentifier, m_serviceWorkerIdentifier, m_fetchIdentifier, m_currentRequest, options, IPC::FormDataReference { m_currentRequest.httpBody() }, referrer });
+    ASSERT_UNUSED(isSent, isSent);
+}
+
+void ServiceWorkerFetchTask::didReceiveRedirectResponse(ResourceResponse&& response)
+{
+    RELEASE_LOG_IF_ALLOWED("didReceiveRedirectResponse: %s", m_fetchIdentifier.loggingString().utf8().data());
+    m_wasHandled = true;
+
+    response.setSource(ResourceResponse::Source::ServiceWorker);
+    auto newRequest = m_currentRequest.redirectedRequest(response, m_loader.parameters().shouldClearReferrerOnHTTPSToHTTPRedirect);
+
+    sendToClient(Messages::WebResourceLoader::WillSendRequest { newRequest, response });
+}
+
+void ServiceWorkerFetchTask::didReceiveResponse(ResourceResponse&& response, bool needsContinueDidReceiveResponseMessage)
+{
+    RELEASE_LOG_IF_ALLOWED("didReceiveResponse: %s", m_fetchIdentifier.loggingString().utf8().data());
     m_timeoutTimer.stop();
     m_wasHandled = true;
-    if (m_connection)
-        m_connection->send(Messages::ServiceWorkerClientFetch::DidReceiveResponse { response, needsContinueDidReceiveResponseMessage }, m_identifier.fetchIdentifier);
+
+    response.setSource(ResourceResponse::Source::ServiceWorker);
+    sendToClient(Messages::WebResourceLoader::DidReceiveResponse { response, needsContinueDidReceiveResponseMessage });
 }
 
 void ServiceWorkerFetchTask::didReceiveData(const IPC::DataReference& data, int64_t encodedDataLength)
 {
     ASSERT(!m_timeoutTimer.isActive());
-    if (m_connection)
-        m_connection->send(Messages::ServiceWorkerClientFetch::DidReceiveData { data, encodedDataLength }, m_identifier.fetchIdentifier);
+    sendToClient(Messages::WebResourceLoader::DidReceiveData { IPC::SharedBufferDataReference { data.data(), data.size() }, encodedDataLength });
 }
 
 void ServiceWorkerFetchTask::didReceiveFormData(const IPC::FormDataReference& formData)
 {
     ASSERT(!m_timeoutTimer.isActive());
-    if (m_connection)
-        m_connection->send(Messages::ServiceWorkerClientFetch::DidReceiveFormData { formData }, m_identifier.fetchIdentifier);
+    // FIXME: Allow WebResourceLoader to receive form data.
 }
 
 void ServiceWorkerFetchTask::didFinish()
 {
     ASSERT(!m_timeoutTimer.isActive());
-    RELEASE_LOG_IF_ALLOWED("didFinishFetch: fetchIdentifier: %s", m_identifier.fetchIdentifier.loggingString().utf8().data());
+    RELEASE_LOG_IF_ALLOWED("didFinishFetch: fetchIdentifier: %s", m_fetchIdentifier.loggingString().utf8().data());
     m_timeoutTimer.stop();
-    if (m_connection)
-        m_connection->send(Messages::ServiceWorkerClientFetch::DidFinish { }, m_identifier.fetchIdentifier);
+    sendToClient(Messages::WebResourceLoader::DidFinishResourceLoad { { } });
 }
 
 void ServiceWorkerFetchTask::didFail(const ResourceError& error)
 {
-    RELEASE_LOG_ERROR_IF_ALLOWED("didFailFetch: fetchIdentifier: %s", m_identifier.fetchIdentifier.loggingString().utf8().data());
     m_timeoutTimer.stop();
-    if (m_connection)
-        m_connection->send(Messages::ServiceWorkerClientFetch::DidFail { error }, m_identifier.fetchIdentifier);
+    RELEASE_LOG_ERROR_IF_ALLOWED("didFailFetch: fetchIdentifier: %s", m_fetchIdentifier.loggingString().utf8().data());
+    m_loader.didFailLoading(error);
 }
 
 void ServiceWorkerFetchTask::didNotHandle()
 {
-    RELEASE_LOG_IF_ALLOWED("didNotHandleFetch: fetchIdentifier: %s", m_identifier.fetchIdentifier.loggingString().utf8().data());
+    RELEASE_LOG_IF_ALLOWED("didNotHandleFetch: fetchIdentifier: %s", m_fetchIdentifier.loggingString().utf8().data());
     m_timeoutTimer.stop();
-    if (m_connection)
-        m_connection->send(Messages::ServiceWorkerClientFetch::DidNotHandle { }, m_identifier.fetchIdentifier);
+    m_loader.serviceWorkerDidNotHandle();
+}
+
+void ServiceWorkerFetchTask::cancelFromClient()
+{
+    RELEASE_LOG_IF_ALLOWED("cancelFromClient: fetchIdentifier: %s", m_fetchIdentifier.loggingString().utf8().data());
+    sendToServiceWorker(Messages::WebSWContextManagerConnection::CancelFetch { m_serverConnectionIdentifier, m_serviceWorkerIdentifier, m_fetchIdentifier });
+}
+
+void ServiceWorkerFetchTask::continueDidReceiveFetchResponse()
+{
+    sendToServiceWorker(Messages::WebSWContextManagerConnection::ContinueDidReceiveFetchResponse { m_serverConnectionIdentifier, m_serviceWorkerIdentifier, m_fetchIdentifier });
+}
+
+void ServiceWorkerFetchTask::continueFetchTaskWith(ResourceRequest&& request)
+{
+    if (!m_serviceWorkerConnection) {
+        m_loader.serviceWorkerDidNotHandle();
+        return;
+    }
+    startFetch(WTFMove(request), *m_serviceWorkerConnection);
 }
 
 void ServiceWorkerFetchTask::timeoutTimerFired()
 {
-    RELEASE_LOG_IF_ALLOWED("timeoutTimerFired: fetchIdentifier: %s", m_identifier.fetchIdentifier.loggingString().utf8().data());
-    didNotHandle();
-    m_contextConnection.fetchTaskTimedOut(*this);
+    RELEASE_LOG_IF_ALLOWED("timeoutTimerFired: fetchIdentifier: %s", m_fetchIdentifier.loggingString().utf8().data());
+    if (m_serviceWorkerConnection)
+        m_serviceWorkerConnection->fetchTaskTimedOut(serviceWorkerIdentifier());
 }
 
 } // namespace WebKit
diff --git a/Source/WebKit/NetworkProcess/ServiceWorker/ServiceWorkerFetchTask.h b/Source/WebKit/NetworkProcess/ServiceWorker/ServiceWorkerFetchTask.h
index d8b9d6f..bdfd5e6 100644
--- a/Source/WebKit/NetworkProcess/ServiceWorker/ServiceWorkerFetchTask.h
+++ b/Source/WebKit/NetworkProcess/ServiceWorker/ServiceWorkerFetchTask.h
@@ -28,12 +28,15 @@
 #if ENABLE(SERVICE_WORKER)
 
 #include <WebCore/FetchIdentifier.h>
+#include <WebCore/ResourceRequest.h>
 #include <WebCore/ServiceWorkerTypes.h>
 #include <WebCore/Timer.h>
 #include <pal/SessionID.h>
+#include <wtf/WeakPtr.h>
 
 namespace WebCore {
 class ResourceError;
+class ResourceRequest;
 class ResourceResponse;
 }
 
@@ -46,82 +49,59 @@
 
 namespace WebKit {
 
-class WebSWServerConnection;
+class NetworkResourceLoader;
 class WebSWServerToContextConnection;
 
-class ServiceWorkerFetchTask {
+class NetworkResourceLoader;
+class WebSWServerToContextConnection;
+
+class ServiceWorkerFetchTask : public CanMakeWeakPtr<ServiceWorkerFetchTask> {
     WTF_MAKE_FAST_ALLOCATED;
 public:
-    ServiceWorkerFetchTask(PAL::SessionID, WebSWServerConnection&, WebSWServerToContextConnection&, WebCore::FetchIdentifier, WebCore::ServiceWorkerIdentifier, Seconds timeout);
+    ServiceWorkerFetchTask(PAL::SessionID, NetworkResourceLoader&, WebCore::SWServerConnectionIdentifier, WebCore::ServiceWorkerIdentifier);
+    ~ServiceWorkerFetchTask();
 
-    void didNotHandle();
+    void start(WebSWServerToContextConnection&);
+    void cancelFromClient();
     void fail(const WebCore::ResourceError& error) { didFail(error); }
     void didReceiveMessage(IPC::Connection&, IPC::Decoder&);
 
-    struct Identifier {
-        WebCore::SWServerConnectionIdentifier connectionIdentifier;
-        WebCore::FetchIdentifier fetchIdentifier;
-        
-        unsigned hash() const
-        {
-            unsigned hashes[2];
-            hashes[0] = WTF::intHash(connectionIdentifier.toUInt64());
-            hashes[1] = WTF::intHash(fetchIdentifier.toUInt64());
-            return StringHasher::hashMemory(hashes, sizeof(hashes));
-        }
-    };
+    void continueDidReceiveFetchResponse();
+    void continueFetchTaskWith(WebCore::ResourceRequest&&);
 
-    const Identifier& identifier() const { return m_identifier; }
-    const WebCore::ServiceWorkerIdentifier& serviceWorkerIdentifier() const { return m_serviceWorkerIdentifier; }
+    WebCore::FetchIdentifier fetchIdentifier() const { return m_fetchIdentifier; }
+    WebCore::ServiceWorkerIdentifier serviceWorkerIdentifier() const { return m_serviceWorkerIdentifier; }
+
+    void didNotHandle();
+
     bool wasHandled() const { return m_wasHandled; }
 
 private:
-    void didReceiveRedirectResponse(const WebCore::ResourceResponse&);
-    void didReceiveResponse(const WebCore::ResourceResponse&, bool needsContinueDidReceiveResponseMessage);
+    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 didFail(const WebCore::ResourceError&);
+
+    void startFetch(WebCore::ResourceRequest&&, WebSWServerToContextConnection&);
+
     void timeoutTimerFired();
 
+    template<typename Message> bool sendToServiceWorker(Message&&);
+    template<typename Message> bool sendToClient(Message&&);
+
     PAL::SessionID m_sessionID;
-    WeakPtr<WebSWServerConnection> m_connection;
-    WebSWServerToContextConnection& m_contextConnection;
-    Identifier m_identifier;
+    NetworkResourceLoader& m_loader;
+    WeakPtr<WebSWServerToContextConnection> m_serviceWorkerConnection;
+    WebCore::FetchIdentifier m_fetchIdentifier;
+    WebCore::SWServerConnectionIdentifier m_serverConnectionIdentifier;
     WebCore::ServiceWorkerIdentifier m_serviceWorkerIdentifier;
-    Seconds m_timeout;
+    WebCore::ResourceRequest m_currentRequest;
     WebCore::Timer m_timeoutTimer;
     bool m_wasHandled { false };
 };
 
-inline bool operator==(const ServiceWorkerFetchTask::Identifier& a, const ServiceWorkerFetchTask::Identifier& b)
-{
-    return a.connectionIdentifier == b.connectionIdentifier &&  a.fetchIdentifier == b.fetchIdentifier;
-}
-
-} // namespace WebKit
-
-
-namespace WTF {
-
-struct ServiceWorkerFetchTaskIdentifierHash {
-    static unsigned hash(const WebKit::ServiceWorkerFetchTask::Identifier& key) { return key.hash(); }
-    static bool equal(const WebKit::ServiceWorkerFetchTask::Identifier& a, const WebKit::ServiceWorkerFetchTask::Identifier& b) { return a == b; }
-    static const bool safeToCompareToEmptyOrDeleted = true;
-};
-
-template<> struct HashTraits<WebKit::ServiceWorkerFetchTask::Identifier> : GenericHashTraits<WebKit::ServiceWorkerFetchTask::Identifier> {
-    static WebKit::ServiceWorkerFetchTask::Identifier emptyValue() { return { }; }
-    
-    static void constructDeletedValue(WebKit::ServiceWorkerFetchTask::Identifier& slot) { slot.connectionIdentifier = makeObjectIdentifier<WebCore::SWServerConnectionIdentifierType>(std::numeric_limits<uint64_t>::max()); }
-    
-    static bool isDeletedValue(const WebKit::ServiceWorkerFetchTask::Identifier& slot) { return slot.connectionIdentifier.toUInt64() == std::numeric_limits<uint64_t>::max(); }
-};
-
-template<> struct DefaultHash<WebKit::ServiceWorkerFetchTask::Identifier> {
-    using Hash = ServiceWorkerFetchTaskIdentifierHash;
-};
-
 }
 
 #endif // ENABLE(SERVICE_WORKER)
diff --git a/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerConnection.cpp b/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerConnection.cpp
index 79e3265..c6b7258 100644
--- a/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerConnection.cpp
+++ b/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerConnection.cpp
@@ -33,16 +33,18 @@
 #include "Logging.h"
 #include "NetworkConnectionToWebProcessMessages.h"
 #include "NetworkProcess.h"
-#include "ServiceWorkerClientFetchMessages.h"
+#include "NetworkResourceLoader.h"
 #include "WebCoreArgumentCoders.h"
 #include "WebProcess.h"
 #include "WebProcessMessages.h"
+#include "WebResourceLoaderMessages.h"
 #include "WebSWClientConnectionMessages.h"
 #include "WebSWContextManagerConnectionMessages.h"
 #include "WebSWServerConnectionMessages.h"
 #include "WebSWServerToContextConnection.h"
 #include <WebCore/DocumentIdentifier.h>
 #include <WebCore/ExceptionData.h>
+#include <WebCore/LegacySchemeRegistry.h>
 #include <WebCore/NotImplemented.h>
 #include <WebCore/SWServerRegistration.h>
 #include <WebCore/SecurityOrigin.h>
@@ -126,86 +128,89 @@
     send(Messages::WebSWClientConnection::UpdateWorkerState(worker, state));
 }
 
-void WebSWServerConnection::cancelFetch(ServiceWorkerRegistrationIdentifier serviceWorkerRegistrationIdentifier, FetchIdentifier fetchIdentifier)
+std::unique_ptr<ServiceWorkerFetchTask> WebSWServerConnection::createFetchTask(NetworkResourceLoader& loader)
 {
-    SWSERVERCONNECTION_RELEASE_LOG_IF_ALLOWED("cancelFetch: %s", fetchIdentifier.loggingString().utf8().data());
-    auto* worker = server().activeWorkerFromRegistrationID(serviceWorkerRegistrationIdentifier);
-    if (!worker || !worker->isRunning())
-        return;
+    if (!loader.parameters().serviceWorkerRegistrationIdentifier)
+        return nullptr;
 
-    auto serviceWorkerIdentifier = worker->identifier();
-    server().runServiceWorkerIfNecessary(serviceWorkerIdentifier, [weakThis = makeWeakPtr(this), this, serviceWorkerIdentifier, fetchIdentifier](auto* contextConnection) mutable {
-        if (weakThis && contextConnection)
-            static_cast<WebSWServerToContextConnection&>(*contextConnection).cancelFetch(this->identifier(), fetchIdentifier, serviceWorkerIdentifier);
-    });
-}
+    if (loader.parameters().serviceWorkersMode == ServiceWorkersMode::None)
+        return nullptr;
 
-void WebSWServerConnection::continueDidReceiveFetchResponse(ServiceWorkerRegistrationIdentifier serviceWorkerRegistrationIdentifier, FetchIdentifier fetchIdentifier)
-{
-    auto* worker = server().activeWorkerFromRegistrationID(serviceWorkerRegistrationIdentifier);
-    if (!worker || !worker->isRunning())
-        return;
+    if (isPotentialNavigationOrSubresourceRequest(loader.parameters().options.destination))
+        return nullptr;
 
-    auto serviceWorkerIdentifier = worker->identifier();
-    server().runServiceWorkerIfNecessary(serviceWorkerIdentifier, [weakThis = makeWeakPtr(this), this, serviceWorkerIdentifier, fetchIdentifier](auto* contextConnection) mutable {
-        if (weakThis && contextConnection)
-            static_cast<WebSWServerToContextConnection&>(*contextConnection).continueDidReceiveFetchResponse(this->identifier(), fetchIdentifier, serviceWorkerIdentifier);
-    });
-}
+    if (!server().canHandleScheme(loader.originalRequest().url().protocol()))
+        return nullptr;
 
-void WebSWServerConnection::startFetch(ServiceWorkerRegistrationIdentifier serviceWorkerRegistrationIdentifier, FetchIdentifier fetchIdentifier, ResourceRequest&& request, FetchOptions&& options, IPC::FormDataReference&& formData, String&& referrer)
-{
-    auto* worker = server().activeWorkerFromRegistrationID(serviceWorkerRegistrationIdentifier);
+    auto* worker = server().activeWorkerFromRegistrationID(*loader.parameters().serviceWorkerRegistrationIdentifier);
     if (!worker) {
-        SWSERVERCONNECTION_RELEASE_LOG_ERROR_IF_ALLOWED("startFetch: fetchIdentifier: %s -> DidNotHandle because no active worker", fetchIdentifier.loggingString().utf8().data());
-        m_contentConnection->send(Messages::ServiceWorkerClientFetch::DidNotHandle { }, fetchIdentifier);
-        return;
+        SWSERVERCONNECTION_RELEASE_LOG_ERROR_IF_ALLOWED("startFetch: DidNotHandle because no active worker %s", loader.parameters().serviceWorkerRegistrationIdentifier->loggingString().utf8().data());
+        return nullptr;
     }
-    auto serviceWorkerIdentifier = worker->identifier();
-
-    auto runServerWorkerAndStartFetch = [weakThis = makeWeakPtr(this), this, fetchIdentifier, serviceWorkerIdentifier, request = WTFMove(request), options = WTFMove(options), formData = WTFMove(formData), referrer = WTFMove(referrer)](bool success) mutable {
-        if (!weakThis)
-            return;
-
-        if (!success) {
-            SWSERVERCONNECTION_RELEASE_LOG_ERROR_IF_ALLOWED("startFetch: fetchIdentifier: %s DidNotHandle because worker did not become activated", fetchIdentifier.loggingString().utf8().data());
-            m_contentConnection->send(Messages::ServiceWorkerClientFetch::DidNotHandle { }, fetchIdentifier);
-            return;
-        }
-
-        auto* worker = server().workerByID(serviceWorkerIdentifier);
-        if (!worker || worker->hasTimedOutAnyFetchTasks()) {
-            m_contentConnection->send(Messages::ServiceWorkerClientFetch::DidNotHandle { }, fetchIdentifier);
-            return;
-        }
-
-        server().runServiceWorkerIfNecessary(serviceWorkerIdentifier, [weakThis = WTFMove(weakThis), this, fetchIdentifier, serviceWorkerIdentifier, request = WTFMove(request), options = WTFMove(options), formData = WTFMove(formData), referrer = WTFMove(referrer), shouldSkipFetchEvent = worker->shouldSkipFetchEvent()](auto* contextConnection) {
-            if (!weakThis)
-                return;
-
-            if (contextConnection) {
-                SWSERVERCONNECTION_RELEASE_LOG_IF_ALLOWED("startFetch: Starting fetch %s via service worker %s", fetchIdentifier.loggingString().utf8().data(), serviceWorkerIdentifier.loggingString().utf8().data());
-                static_cast<WebSWServerToContextConnection&>(*contextConnection).startFetch(sessionID(), *this, fetchIdentifier, serviceWorkerIdentifier, request, options, formData, referrer);
-            } else {
-                SWSERVERCONNECTION_RELEASE_LOG_ERROR_IF_ALLOWED("startFetch: fetchIdentifier: %s DidNotHandle because failed to run service worker, or service worker has had timed out fetch tasks", fetchIdentifier.loggingString().utf8().data());
-                m_contentConnection->send(Messages::ServiceWorkerClientFetch::DidNotHandle { }, fetchIdentifier);
-            }
-        });
-    };
 
     if (worker->shouldSkipFetchEvent()) {
-        m_contentConnection->send(Messages::ServiceWorkerClientFetch::DidNotHandle { }, fetchIdentifier);
         auto* registration = server().getRegistration(worker->registrationKey());
-        if (registration && registration->shouldSoftUpdate(options))
+        if (registration && registration->shouldSoftUpdate(loader.parameters().options))
             registration->softUpdate();
+        return nullptr;
+    }
+
+    auto task = makeUnique<ServiceWorkerFetchTask>(sessionID(), loader, identifier(), worker->identifier());
+    startFetch(*task, *worker);
+    return task;
+}
+
+void WebSWServerConnection::startFetch(ServiceWorkerFetchTask& task, SWServerWorker& worker)
+{
+    auto runServerWorkerAndStartFetch = [weakThis = makeWeakPtr(this), this, task = makeWeakPtr(task)](bool success) mutable {
+        if (!task)
+            return;
+
+        if (!weakThis) {
+            task->didNotHandle();
+            return;
+        }
+
+        if (!success) {
+            SWSERVERCONNECTION_RELEASE_LOG_ERROR_IF_ALLOWED("startFetch: fetchIdentifier: %s DidNotHandle because worker did not become activated", task->fetchIdentifier().loggingString().utf8().data());
+            task->didNotHandle();
+            return;
+        }
+
+        auto* worker = server().workerByID(task->serviceWorkerIdentifier());
+        if (!worker || worker->hasTimedOutAnyFetchTasks()) {
+            task->didNotHandle();
+            return;
+        }
+
+        if (!worker->contextConnection())
+            server().createContextConnection(worker->registrableDomain());
+
+        server().runServiceWorkerIfNecessary(task->serviceWorkerIdentifier(), [weakThis = WTFMove(weakThis), this, task = WTFMove(task)](auto* contextConnection) mutable {
+            if (!task)
+                return;
+            
+            if (!weakThis) {
+                task->didNotHandle();
+                return;
+            }
+
+            if (!contextConnection) {
+                SWSERVERCONNECTION_RELEASE_LOG_ERROR_IF_ALLOWED("startFetch: fetchIdentifier: %s DidNotHandle because failed to run service worker", task->fetchIdentifier().loggingString().utf8().data());
+                task->didNotHandle();
+                return;
+            }
+            SWSERVERCONNECTION_RELEASE_LOG_IF_ALLOWED("startFetch: Starting fetch %s via service worker %s", task->fetchIdentifier().loggingString().utf8().data(), task->serviceWorkerIdentifier().loggingString().utf8().data());
+            static_cast<WebSWServerToContextConnection&>(*contextConnection).startFetch(*task);
+        });
+    };
+    
+    if (worker.state() == ServiceWorkerState::Activating) {
+        worker.whenActivated(WTFMove(runServerWorkerAndStartFetch));
         return;
     }
 
-    if (worker->state() == ServiceWorkerState::Activating) {
-        worker->whenActivated(WTFMove(runServerWorkerAndStartFetch));
-        return;
-    }
-    ASSERT(worker->state() == ServiceWorkerState::Activated);
+    ASSERT(worker.state() == ServiceWorkerState::Activated);
     runServerWorkerAndStartFetch(true);
 }
 
diff --git a/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerConnection.h b/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerConnection.h
index 7bd2a33..4ed201e 100644
--- a/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerConnection.h
+++ b/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerConnection.h
@@ -52,6 +52,8 @@
 namespace WebKit {
 
 class NetworkProcess;
+class NetworkResourceLoader;
+class ServiceWorkerFetchTask;
 
 class WebSWServerConnection : public WebCore::SWServer::Connection, public IPC::MessageSender, public IPC::MessageReceiver {
 public:
@@ -66,6 +68,8 @@
     
     PAL::SessionID sessionID() const;
 
+    std::unique_ptr<ServiceWorkerFetchTask> createFetchTask(NetworkResourceLoader&);
+
 private:
     // Implement SWServer::Connection (Messages to the client WebProcess)
     void rejectJobInClient(WebCore::ServiceWorkerJobIdentifier, const WebCore::ExceptionData&) final;
@@ -82,9 +86,9 @@
 
     void scheduleJobInServer(WebCore::ServiceWorkerJobData&&);
 
-    void startFetch(WebCore::ServiceWorkerRegistrationIdentifier, WebCore::FetchIdentifier, WebCore::ResourceRequest&&, WebCore::FetchOptions&&, IPC::FormDataReference&&, String&& referrer);
-    void cancelFetch(WebCore::ServiceWorkerRegistrationIdentifier, WebCore::FetchIdentifier);
-    void continueDidReceiveFetchResponse(WebCore::ServiceWorkerRegistrationIdentifier, WebCore::FetchIdentifier);
+    bool handleFetch(NetworkResourceLoader&);
+
+    void startFetch(ServiceWorkerFetchTask&, WebCore::SWServerWorker&);
 
     void matchRegistration(uint64_t registrationMatchRequestIdentifier, const WebCore::SecurityOriginData& topOrigin, const URL& clientURL);
     void getRegistrations(uint64_t registrationMatchRequestIdentifier, const WebCore::SecurityOriginData& topOrigin, const URL& clientURL);
diff --git a/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerConnection.messages.in b/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerConnection.messages.in
index ab2468e..3da64d9 100644
--- a/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerConnection.messages.in
+++ b/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerConnection.messages.in
@@ -29,10 +29,6 @@
     AddServiceWorkerRegistrationInServer(WebCore::ServiceWorkerRegistrationIdentifier identifier)
     RemoveServiceWorkerRegistrationInServer(WebCore::ServiceWorkerRegistrationIdentifier identifier)
 
-    StartFetch(WebCore::ServiceWorkerRegistrationIdentifier serviceWorkerRegistrationIdentifier, WebCore::FetchIdentifier fetchIdentifier, WebCore::ResourceRequest request, struct WebCore::FetchOptions options, IPC::FormDataReference requestBody, String referrer)
-    CancelFetch(WebCore::ServiceWorkerRegistrationIdentifier serviceWorkerRegistrationIdentifier, WebCore::FetchIdentifier fetchIdentifier)
-    ContinueDidReceiveFetchResponse(WebCore::ServiceWorkerRegistrationIdentifier serviceWorkerRegistrationIdentifier, WebCore::FetchIdentifier fetchIdentifier)
-
     PostMessageToServiceWorker(WebCore::ServiceWorkerIdentifier destination, struct WebCore::MessageWithMessagePorts message, WebCore::ServiceWorkerOrClientIdentifier source)
 
     DidResolveRegistrationPromise(WebCore::ServiceWorkerRegistrationKey key)
diff --git a/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerToContextConnection.cpp b/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerToContextConnection.cpp
index 6c14e6d..c850a93 100644
--- a/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerToContextConnection.cpp
+++ b/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerToContextConnection.cpp
@@ -61,9 +61,14 @@
         m_server->removeContextConnection(*this);
 }
 
+IPC::Connection& WebSWServerToContextConnection::ipcConnection() const
+{
+    return m_connection.connection();
+}
+
 IPC::Connection* WebSWServerToContextConnection::messageSenderConnection() const
 {
-    return &m_connection.connection();
+    return &ipcConnection();
 }
 
 uint64_t WebSWServerToContextConnection::messageSenderDestinationID() const
@@ -141,39 +146,9 @@
     send(Messages::WebSWContextManagerConnection::SetThrottleState { isThrottleable });
 }
 
-void WebSWServerToContextConnection::startFetch(PAL::SessionID sessionID, WebSWServerConnection& contentConnection, FetchIdentifier contentFetchIdentifier, ServiceWorkerIdentifier serviceWorkerIdentifier, const ResourceRequest& request, const FetchOptions& options, const IPC::FormDataReference& data, const String& referrer)
+void WebSWServerToContextConnection::startFetch(ServiceWorkerFetchTask& task)
 {
-    auto serverConnectionIdentifier = contentConnection.identifier();
-    auto fetchIdentifier = FetchIdentifier::generate();
-
-    auto result = m_ongoingFetches.add(fetchIdentifier, makeUnique<ServiceWorkerFetchTask>(sessionID, contentConnection, *this, contentFetchIdentifier, serviceWorkerIdentifier, m_connection.networkProcess().serviceWorkerFetchTimeout()));
-
-    ASSERT(!m_ongoingFetchIdentifiers.contains({ serverConnectionIdentifier, contentFetchIdentifier }));
-    m_ongoingFetchIdentifiers.add({ serverConnectionIdentifier, contentFetchIdentifier }, fetchIdentifier);
-
-    if (!send(Messages::WebSWContextManagerConnection::StartFetch { serverConnectionIdentifier, serviceWorkerIdentifier, fetchIdentifier, request, options, data, referrer }))
-        result.iterator->value->didNotHandle();
-}
-
-void WebSWServerToContextConnection::cancelFetch(WebCore::SWServerConnectionIdentifier serverConnectionIdentifier, FetchIdentifier contentFetchIdentifier, ServiceWorkerIdentifier serviceWorkerIdentifier)
-{
-    auto iterator = m_ongoingFetchIdentifiers.find({ serverConnectionIdentifier, contentFetchIdentifier });
-    if (iterator == m_ongoingFetchIdentifiers.end())
-        return;
-
-    send(Messages::WebSWContextManagerConnection::CancelFetch { serverConnectionIdentifier, serviceWorkerIdentifier, iterator->value });
-
-    m_ongoingFetches.remove(iterator->value);
-    m_ongoingFetchIdentifiers.remove(iterator);
-}
-
-void WebSWServerToContextConnection::continueDidReceiveFetchResponse(WebCore::SWServerConnectionIdentifier serverConnectionIdentifier, FetchIdentifier contentFetchIdentifier, ServiceWorkerIdentifier serviceWorkerIdentifier)
-{
-    auto iterator = m_ongoingFetchIdentifiers.find({ serverConnectionIdentifier, contentFetchIdentifier });
-    if (iterator == m_ongoingFetchIdentifiers.end())
-        return;
-    
-    send(Messages::WebSWContextManagerConnection::ContinueDidReceiveFetchResponse { serverConnectionIdentifier, serviceWorkerIdentifier, iterator->value });
+    task.start(*this);
 }
 
 void WebSWServerToContextConnection::didReceiveFetchTaskMessage(IPC::Connection& connection, IPC::Decoder& decoder)
@@ -181,51 +156,41 @@
     auto iterator = m_ongoingFetches.find(makeObjectIdentifier<FetchIdentifierType>(decoder.destinationID()));
     if (iterator == m_ongoingFetches.end())
         return;
-    
-    bool shouldRemove = decoder.messageName() == Messages::ServiceWorkerFetchTask::DidFail::name()
-        || decoder.messageName() == Messages::ServiceWorkerFetchTask::DidNotHandle::name()
-        || decoder.messageName() == Messages::ServiceWorkerFetchTask::DidFinish::name()
-        || decoder.messageName() == Messages::ServiceWorkerFetchTask::DidReceiveRedirectResponse::name();
 
     iterator->value->didReceiveMessage(connection, decoder);
-
-    if (shouldRemove) {
-        ASSERT(m_ongoingFetchIdentifiers.contains(iterator->value->identifier()));
-        m_ongoingFetchIdentifiers.remove(iterator->value->identifier());
-        m_ongoingFetches.remove(iterator);
-    }
 }
 
-void WebSWServerToContextConnection::fetchTaskTimedOut(ServiceWorkerFetchTask& task)
+void WebSWServerToContextConnection::registerFetch(ServiceWorkerFetchTask& task)
 {
-    ASSERT(m_ongoingFetchIdentifiers.contains(task.identifier()));
-    auto takenIdentifier = m_ongoingFetchIdentifiers.take(task.identifier());
+    ASSERT(!m_ongoingFetches.contains(task.fetchIdentifier()));
+    m_ongoingFetches.add(task.fetchIdentifier(), makeWeakPtr(task));
+}
 
-    ASSERT(m_ongoingFetches.contains(takenIdentifier));
-    auto takenTask = m_ongoingFetches.take(takenIdentifier);
-    ASSERT(takenTask);
-    ASSERT(takenTask.get() == &task);
+void WebSWServerToContextConnection::unregisterFetch(ServiceWorkerFetchTask& task)
+{
+    ASSERT(m_ongoingFetches.contains(task.fetchIdentifier()));
+    m_ongoingFetches.remove(task.fetchIdentifier());
+}
 
-    // Gather all other fetches in this service worker
-    Vector<ServiceWorkerFetchTask*> otherFetches;
+void WebSWServerToContextConnection::fetchTaskTimedOut(ServiceWorkerIdentifier serviceWorkerIdentifier)
+{
+    // Gather all fetches in this service worker
+    Vector<ServiceWorkerFetchTask*> fetches;
     for (auto& fetchTask : m_ongoingFetches.values()) {
-        if (fetchTask->serviceWorkerIdentifier() == task.serviceWorkerIdentifier())
-            otherFetches.append(fetchTask.get());
+        if (fetchTask->serviceWorkerIdentifier() == serviceWorkerIdentifier)
+            fetches.append(fetchTask.get());
     }
 
     // Signal load failure for them
-    for (auto* fetchTask : otherFetches) {
+    for (auto* fetchTask : fetches) {
         if (fetchTask->wasHandled())
             fetchTask->fail({ errorDomainWebKitInternal, 0, { }, "Service Worker context closed"_s });
         else
             fetchTask->didNotHandle();
-
-        auto identifier = m_ongoingFetchIdentifiers.take(fetchTask->identifier());
-        m_ongoingFetches.remove(identifier);
     }
 
     if (m_server) {
-        if (auto* worker = m_server->workerByID(task.serviceWorkerIdentifier())) {
+        if (auto* worker = m_server->workerByID(serviceWorkerIdentifier)) {
             worker->setHasTimedOutAnyFetchTasks();
             if (worker->isRunning())
                 m_server->syncTerminateWorker(*worker);
diff --git a/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerToContextConnection.h b/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerToContextConnection.h
index dd9531d..2c00ff7 100644
--- a/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerToContextConnection.h
+++ b/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerToContextConnection.h
@@ -52,24 +52,28 @@
 class NetworkConnectionToWebProcess;
 class WebSWServerConnection;
 
-class WebSWServerToContextConnection : public WebCore::SWServerToContextConnection, public IPC::MessageSender, public IPC::MessageReceiver {
+class WebSWServerToContextConnection: public CanMakeWeakPtr<WebSWServerToContextConnection>, public WebCore::SWServerToContextConnection, public IPC::MessageSender, public IPC::MessageReceiver {
 public:
     WebSWServerToContextConnection(NetworkConnectionToWebProcess&, WebCore::RegistrableDomain&&, WebCore::SWServer&);
     ~WebSWServerToContextConnection();
 
+    IPC::Connection& ipcConnection() const;
+
     // IPC::MessageReceiver
     void didReceiveMessage(IPC::Connection&, IPC::Decoder&) final;
 
-    void startFetch(PAL::SessionID, WebSWServerConnection&, WebCore::FetchIdentifier, WebCore::ServiceWorkerIdentifier, const WebCore::ResourceRequest&, const WebCore::FetchOptions&, const IPC::FormDataReference&, const String&);
+    void startFetch(ServiceWorkerFetchTask&);
     void cancelFetch(WebCore::SWServerConnectionIdentifier, WebCore::FetchIdentifier, WebCore::ServiceWorkerIdentifier);
-    void continueDidReceiveFetchResponse(WebCore::SWServerConnectionIdentifier, WebCore::FetchIdentifier, WebCore::ServiceWorkerIdentifier);
 
     void didReceiveFetchTaskMessage(IPC::Connection&, IPC::Decoder&);
 
     void setThrottleState(bool isThrottleable);
     bool isThrottleable() const { return m_isThrottleable; }
 
-    void fetchTaskTimedOut(ServiceWorkerFetchTask&);
+    void fetchTaskTimedOut(WebCore::ServiceWorkerIdentifier);
+
+    void registerFetch(ServiceWorkerFetchTask&);
+    void unregisterFetch(ServiceWorkerFetchTask&);
 
 private:
     // IPC::MessageSender
@@ -96,9 +100,7 @@
 
     NetworkConnectionToWebProcess& m_connection;
     WeakPtr<WebCore::SWServer> m_server;
-
-    HashMap<ServiceWorkerFetchTask::Identifier, WebCore::FetchIdentifier> m_ongoingFetchIdentifiers;
-    HashMap<WebCore::FetchIdentifier, std::unique_ptr<ServiceWorkerFetchTask>> m_ongoingFetches;
+    HashMap<WebCore::FetchIdentifier, WeakPtr<ServiceWorkerFetchTask>> m_ongoingFetches;
     bool m_isThrottleable { true };
 }; // class WebSWServerToContextConnection
 
diff --git a/Source/WebKit/Sources.txt b/Source/WebKit/Sources.txt
index d7d8991..355197a 100644
--- a/Source/WebKit/Sources.txt
+++ b/Source/WebKit/Sources.txt
@@ -526,7 +526,6 @@
 WebProcess/Plugins/Netscape/NetscapePlugin.cpp @no-unify
 WebProcess/Plugins/Netscape/NetscapePluginStream.cpp @no-unify
 
-WebProcess/Storage/ServiceWorkerClientFetch.cpp
 WebProcess/Storage/WebSWClientConnection.cpp
 WebProcess/Storage/WebSWContextManagerConnection.cpp
 WebProcess/Storage/WebSWOriginTable.cpp
diff --git a/Source/WebKit/WebKit.xcodeproj/project.pbxproj b/Source/WebKit/WebKit.xcodeproj/project.pbxproj
index bf16311..ec0ba4d 100644
--- a/Source/WebKit/WebKit.xcodeproj/project.pbxproj
+++ b/Source/WebKit/WebKit.xcodeproj/project.pbxproj
@@ -1144,7 +1144,6 @@
 		5CE912122293C278005BEC78 /* AuxiliaryProcessMain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5CE9120F2293C25F005BEC78 /* AuxiliaryProcessMain.cpp */; };
 		5CE912132293C279005BEC78 /* AuxiliaryProcessMain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5CE9120F2293C25F005BEC78 /* AuxiliaryProcessMain.cpp */; };
 		5CE912142293C280005BEC78 /* WKMain.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CE9120B2293C1E0005BEC78 /* WKMain.h */; settings = {ATTRIBUTES = (Private, ); }; };
-		617A52D81F43A9DA00DCDC0A /* ServiceWorkerClientFetchMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 617A52D71F43A9B600DCDC0A /* ServiceWorkerClientFetchMessageReceiver.cpp */; };
 		63108F961F96719C00A0DB84 /* _WKApplicationManifest.h in Headers */ = {isa = PBXBuildFile; fileRef = 63108F941F96719C00A0DB84 /* _WKApplicationManifest.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		63108F991F9671F700A0DB84 /* _WKApplicationManifestInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 63108F981F9671F700A0DB84 /* _WKApplicationManifestInternal.h */; };
 		634842511FB26E7100946E3C /* APIApplicationManifest.h in Headers */ = {isa = PBXBuildFile; fileRef = 6348424F1FB26E7100946E3C /* APIApplicationManifest.h */; };
@@ -3132,9 +3131,6 @@
 		413075A61DE85EE70039EC69 /* LibWebRTCSocketFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LibWebRTCSocketFactory.h; path = Network/webrtc/LibWebRTCSocketFactory.h; sourceTree = "<group>"; };
 		413075A71DE85EE70039EC69 /* LibWebRTCProvider.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = LibWebRTCProvider.cpp; path = Network/webrtc/LibWebRTCProvider.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
 		413075A81DE85EE70039EC69 /* LibWebRTCProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = LibWebRTCProvider.h; path = Network/webrtc/LibWebRTCProvider.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
-		4131F3CE1F96A4950059995A /* ServiceWorkerClientFetch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ServiceWorkerClientFetch.h; sourceTree = "<group>"; };
-		4131F3CF1F96A9360059995A /* ServiceWorkerClientFetch.messages.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ServiceWorkerClientFetch.messages.in; sourceTree = "<group>"; };
-		4131F3D01F96BCC80059995A /* ServiceWorkerClientFetch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ServiceWorkerClientFetch.cpp; sourceTree = "<group>"; };
 		4131F3E01F98712C0059995A /* WebServiceWorkerFetchTaskClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebServiceWorkerFetchTaskClient.cpp; sourceTree = "<group>"; };
 		4135FBCF1F4FB7F20074C47B /* CacheStorageEngineCaches.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CacheStorageEngineCaches.cpp; sourceTree = "<group>"; };
 		4135FBD01F4FB7F20074C47B /* CacheStorageEngineCaches.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CacheStorageEngineCaches.h; sourceTree = "<group>"; };
@@ -3714,7 +3710,6 @@
 		5CEABA2B2333251400797797 /* LegacyGlobalSettings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LegacyGlobalSettings.cpp; sourceTree = "<group>"; };
 		5CFECB031E1ED1C800F88504 /* LegacyCustomProtocolManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LegacyCustomProtocolManager.cpp; sourceTree = "<group>"; };
 		5DAD73F1116FF90C00EE5396 /* BaseTarget.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = BaseTarget.xcconfig; sourceTree = "<group>"; };
-		617A52D71F43A9B600DCDC0A /* ServiceWorkerClientFetchMessageReceiver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ServiceWorkerClientFetchMessageReceiver.cpp; path = DerivedSources/WebKit2/ServiceWorkerClientFetchMessageReceiver.cpp; sourceTree = BUILT_PRODUCTS_DIR; };
 		63108F941F96719C00A0DB84 /* _WKApplicationManifest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = _WKApplicationManifest.h; sourceTree = "<group>"; };
 		63108F951F96719C00A0DB84 /* _WKApplicationManifest.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = _WKApplicationManifest.mm; sourceTree = "<group>"; };
 		63108F981F9671F700A0DB84 /* _WKApplicationManifestInternal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = _WKApplicationManifestInternal.h; sourceTree = "<group>"; };
@@ -6847,9 +6842,6 @@
 		5118E9981F295259003EF9F5 /* Storage */ = {
 			isa = PBXGroup;
 			children = (
-				4131F3D01F96BCC80059995A /* ServiceWorkerClientFetch.cpp */,
-				4131F3CE1F96A4950059995A /* ServiceWorkerClientFetch.h */,
-				4131F3CF1F96A9360059995A /* ServiceWorkerClientFetch.messages.in */,
 				4131F3E01F98712C0059995A /* WebServiceWorkerFetchTaskClient.cpp */,
 				419ACF9B1F981D26009F1A83 /* WebServiceWorkerFetchTaskClient.h */,
 				51BEB6291F3A5ACD005029B9 /* WebServiceWorkerProvider.cpp */,
@@ -8885,7 +8877,6 @@
 				1BBBE49E19B66C53006B7D81 /* RemoteWebInspectorUIMessageReceiver.cpp */,
 				E18E6913169B667B009B6670 /* SecItemShimProxyMessageReceiver.cpp */,
 				E18E6914169B667B009B6670 /* SecItemShimProxyMessages.h */,
-				617A52D71F43A9B600DCDC0A /* ServiceWorkerClientFetchMessageReceiver.cpp */,
 				2DE6943B18BD2A68005C15E5 /* SmartMagnificationControllerMessageReceiver.cpp */,
 				2DE6943C18BD2A68005C15E5 /* SmartMagnificationControllerMessages.h */,
 				1A334DEB16DE8F88006A8E38 /* StorageAreaMapMessageReceiver.cpp */,
@@ -11325,7 +11316,6 @@
 				A55BA8261BA25CFD007CD33D /* RemoteWebInspectorProxyMessageReceiver.cpp in Sources */,
 				1BBBE4A019B66C53006B7D81 /* RemoteWebInspectorUIMessageReceiver.cpp in Sources */,
 				E18E6917169B667B009B6670 /* SecItemShimProxyMessageReceiver.cpp in Sources */,
-				617A52D81F43A9DA00DCDC0A /* ServiceWorkerClientFetchMessageReceiver.cpp in Sources */,
 				41DE7C6C22278F1E00532B65 /* ServiceWorkerFetchTask.cpp in Sources */,
 				2D92A787212B6AB100F493FD /* ShareableBitmap.cpp in Sources */,
 				2DE6943D18BD2A68005C15E5 /* SmartMagnificationControllerMessageReceiver.cpp in Sources */,
diff --git a/Source/WebKit/WebProcess/Network/NetworkProcessConnection.cpp b/Source/WebKit/WebProcess/Network/NetworkProcessConnection.cpp
index f0b4fdf..3083357 100644
--- a/Source/WebKit/WebProcess/Network/NetworkProcessConnection.cpp
+++ b/Source/WebKit/WebProcess/Network/NetworkProcessConnection.cpp
@@ -29,7 +29,6 @@
 #include "DataReference.h"
 #include "LibWebRTCNetwork.h"
 #include "NetworkConnectionToWebProcessMessages.h"
-#include "ServiceWorkerClientFetchMessages.h"
 #include "StorageAreaMap.h"
 #include "StorageAreaMapMessages.h"
 #include "WebCacheStorageProvider.h"
@@ -141,10 +140,6 @@
             m_swConnection->didReceiveMessage(connection, decoder);
         return;
     }
-    if (decoder.messageReceiverName() == Messages::ServiceWorkerClientFetch::messageReceiverName()) {
-        WebServiceWorkerProvider::singleton().didReceiveServiceWorkerClientFetchMessage(connection, decoder);
-        return;
-    }
     if (decoder.messageReceiverName() == Messages::WebSWContextManagerConnection::messageReceiverName()) {
         ASSERT(SWContextManager::singleton().connection());
         if (auto* contextManagerConnection = SWContextManager::singleton().connection())
diff --git a/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp b/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp
index afa3c72..a9fc04d 100644
--- a/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp
+++ b/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp
@@ -215,41 +215,20 @@
 #endif
 
 #if ENABLE(SERVICE_WORKER)
-    if (!!resourceLoader.options().serviceWorkerRegistrationIdentifier)
-        RELEASE_LOG_IF_ALLOWED("scheduleLoad: URL will be scheduled through ServiceWorker or Network Process (frame = %p, pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ")", resourceLoader.frame(), trackingParameters.pageID.toUInt64(), trackingParameters.frameID.toUInt64(), identifier);
+    auto url = resourceLoader.request().url();
+    auto* data = url.string().utf8().data();
+    if (data)
+        url.string();
 
-    WebServiceWorkerProvider::singleton().handleFetch(resourceLoader, shouldClearReferrerOnHTTPSToHTTPRedirect, [this, trackingParameters, identifier, shouldClearReferrerOnHTTPSToHTTPRedirect, maximumBufferingTime = maximumBufferingTime(resource), resourceLoader = makeRef(resourceLoader)] (ServiceWorkerClientFetch::Result result) mutable {
-        if (result != ServiceWorkerClientFetch::Result::Unhandled) {
-            LOG(NetworkScheduling, "(WebProcess) WebLoaderStrategy::scheduleLoad, url '%s' will be scheduled through ServiceWorker handle fetch algorithm", resourceLoader->url().string().latin1().data());
-            RELEASE_LOG_IF_ALLOWED("scheduleLoad: URL will be scheduled through ServiceWorker handle fetch algorithm (frame = %p, pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ")", resourceLoader->frame(), trackingParameters.pageID.toUInt64(), trackingParameters.frameID.toUInt64(), identifier);
-            return;
-        }
-        if (resourceLoader->options().serviceWorkersMode == ServiceWorkersMode::Only) {
-            RELEASE_LOG_ERROR_IF_ALLOWED("scheduleLoad: unable to schedule URL through ServiceWorker handle fetch algorithm (frame = %p, pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ")", resourceLoader->frame(), trackingParameters.pageID.toUInt64(), trackingParameters.frameID.toUInt64(), identifier);
-            callOnMainThread([resourceLoader = WTFMove(resourceLoader)] {
-                auto error = internalError(resourceLoader->request().url());
-                error.setType(ResourceError::Type::Cancellation);
-                resourceLoader->didFail(error);
-            });
-            return;
-        }
-
-        if (!WebProcess::singleton().webLoaderStrategy().tryLoadingUsingURLSchemeHandler(resourceLoader)) {
-            RELEASE_LOG_IF_ALLOWED("scheduleLoad: URL will be scheduled with the NetworkProcess (frame = %p, pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ")", resourceLoader->frame(), trackingParameters.pageID.toUInt64(), trackingParameters.frameID.toUInt64(), identifier);
-            WebProcess::singleton().webLoaderStrategy().scheduleLoadFromNetworkProcess(resourceLoader.get(), resourceLoader->request(), trackingParameters, shouldClearReferrerOnHTTPSToHTTPRedirect, maximumBufferingTime);
-            return;
-        }
-
-        RELEASE_LOG_IF_ALLOWED("scheduleLoad: URL not handled by any handlers (frame = %p, pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ")", resourceLoader->frame(), trackingParameters.pageID.toUInt64(), trackingParameters.frameID.toUInt64(), identifier);
-    });
+    if ((resourceLoader.options().serviceWorkerRegistrationIdentifier && resourceLoader.options().serviceWorkersMode != ServiceWorkersMode::None) || !tryLoadingUsingURLSchemeHandler(resourceLoader)) {
 #else
     if (!tryLoadingUsingURLSchemeHandler(resourceLoader)) {
+#endif
         RELEASE_LOG_IF_ALLOWED("scheduleLoad: URL will be scheduled with the NetworkProcess (frame = %p, pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ")", resourceLoader.frame(), trackingParameters.pageID.toUInt64(), trackingParameters.frameID.toUInt64(), identifier);
         scheduleLoadFromNetworkProcess(resourceLoader, resourceLoader.request(), trackingParameters, shouldClearReferrerOnHTTPSToHTTPRedirect, maximumBufferingTime(resource));
         return;
     }
     RELEASE_LOG_IF_ALLOWED("scheduleLoad: URL not handled by any handlers (frame = %p, pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ")", resourceLoader.frame(), trackingParameters.pageID.toUInt64(), trackingParameters.frameID.toUInt64(), identifier);
-#endif
 }
 
 bool WebLoaderStrategy::tryLoadingUsingURLSchemeHandler(ResourceLoader& resourceLoader)
@@ -271,6 +250,10 @@
 
 void WebLoaderStrategy::scheduleLoadFromNetworkProcess(ResourceLoader& resourceLoader, const ResourceRequest& request, const WebResourceLoader::TrackingParameters& trackingParameters, bool shouldClearReferrerOnHTTPSToHTTPRedirect, Seconds maximumBufferingTime)
 {
+    auto* webFrameLoaderClient = toWebFrameLoaderClient(resourceLoader.frameLoader()->client());
+    auto* webFrame = webFrameLoaderClient ? webFrameLoaderClient->webFrame() : nullptr;
+    auto* webPage = webFrame ? webFrame->page() : nullptr;
+
     ResourceLoadIdentifier identifier = resourceLoader.identifier();
     ASSERT(identifier);
 
@@ -302,6 +285,17 @@
     loadParameters.preflightPolicy = resourceLoader.options().preflightPolicy;
     loadParameters.isHTTPSUpgradeEnabled = resourceLoader.frame() ? resourceLoader.frame()->settings().HTTPSUpgradeEnabled() : false;
 
+#if ENABLE(SERVICE_WORKER)
+    // In case of URL scheme handler, we will try to load on service workers and if unhandled, fallback to URL scheme handler.
+    if (resourceLoader.options().serviceWorkersMode == ServiceWorkersMode::All && webPage &&  webPage->urlSchemeHandlerForScheme(resourceLoader.request().url().protocol().toStringWithoutCopying()))
+        loadParameters.serviceWorkersMode = ServiceWorkersMode::Only;
+    else
+        loadParameters.serviceWorkersMode = resourceLoader.options().serviceWorkersMode;
+
+    loadParameters.serviceWorkerRegistrationIdentifier = resourceLoader.options().serviceWorkerRegistrationIdentifier;
+    loadParameters.httpHeadersToKeep = resourceLoader.options().httpHeadersToKeep;
+#endif
+
     auto* document = resourceLoader.frame() ? resourceLoader.frame()->document() : nullptr;
     if (resourceLoader.options().cspResponseHeaders)
         loadParameters.cspResponseHeaders = resourceLoader.options().cspResponseHeaders;
@@ -438,11 +432,6 @@
         return;
     }
 
-#if ENABLE(SERVICE_WORKER)
-    if (WebServiceWorkerProvider::singleton().cancelFetch(makeObjectIdentifier<FetchIdentifierType>(identifier)))
-        return;
-#endif
-
     RefPtr<WebResourceLoader> loader = m_webResourceLoaders.take(identifier);
     // Loader may not be registered if we created it, but haven't scheduled yet (a bundle client can decide to cancel such request via willSendRequest).
     if (!loader)
diff --git a/Source/WebKit/WebProcess/Network/WebResourceLoader.cpp b/Source/WebKit/WebProcess/Network/WebResourceLoader.cpp
index a39241a..5b3ef23 100644
--- a/Source/WebKit/WebProcess/Network/WebResourceLoader.cpp
+++ b/Source/WebKit/WebProcess/Network/WebResourceLoader.cpp
@@ -32,13 +32,20 @@
 #include "NetworkResourceLoaderMessages.h"
 #include "WebCoreArgumentCoders.h"
 #include "WebErrors.h"
+#include "WebFrame.h"
+#include "WebFrameLoaderClient.h"
+#include "WebLoaderStrategy.h"
+#include "WebPage.h"
 #include "WebProcess.h"
+#include "WebURLSchemeHandlerProxy.h"
 #include <WebCore/ApplicationCacheHost.h>
 #include <WebCore/CertificateInfo.h>
 #include <WebCore/DiagnosticLoggingClient.h>
 #include <WebCore/DiagnosticLoggingKeys.h>
 #include <WebCore/DocumentLoader.h>
 #include <WebCore/Frame.h>
+#include <WebCore/FrameLoader.h>
+#include <WebCore/FrameLoaderClient.h>
 #include <WebCore/InspectorInstrumentationWebKit.h>
 #include <WebCore/NetworkLoadMetrics.h>
 #include <WebCore/Page.h>
@@ -218,6 +225,47 @@
     m_coreLoader->didFinishLoading(networkLoadMetrics);
 }
 
+void WebResourceLoader::didFailServiceWorkerLoad(const ResourceError& error)
+{
+    if (auto* document = m_coreLoader->frame() ? m_coreLoader->frame()->document() : nullptr) {
+        if (m_coreLoader->options().destination != FetchOptions::Destination::EmptyString || error.isGeneral())
+            document->addConsoleMessage(MessageSource::JS, MessageLevel::Error, error.localizedDescription());
+        if (m_coreLoader->options().destination != FetchOptions::Destination::EmptyString)
+            document->addConsoleMessage(MessageSource::JS, MessageLevel::Error, makeString("Cannot load ", error.failingURL().string(), "."));
+    }
+
+    didFailResourceLoad(error);
+}
+
+void WebResourceLoader::serviceWorkerDidNotHandle()
+{
+#if ENABLE(SERVICE_WORKER)
+    RELEASE_LOG_IF_ALLOWED("serviceWorkerDidNotHandle: (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ")", m_trackingParameters.pageID.toUInt64(), m_trackingParameters.frameID.toUInt64(), m_trackingParameters.resourceID);
+
+    if (m_coreLoader->options().serviceWorkersMode != ServiceWorkersMode::Only) {
+        auto* webFrameLoaderClient = toWebFrameLoaderClient(m_coreLoader->frameLoader()->client());
+        auto* webFrame = webFrameLoaderClient ? webFrameLoaderClient->webFrame() : nullptr;
+        auto* webPage = webFrame ? webFrame->page() : nullptr;
+
+        if (auto* handler = webPage->urlSchemeHandlerForScheme(m_coreLoader->request().url().protocol().toStringWithoutCopying())) {
+            RELEASE_LOG_IF_ALLOWED("resource loaded by URL scheme handler: (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ")", m_trackingParameters.pageID.toUInt64(), m_trackingParameters.frameID.toUInt64(), m_trackingParameters.resourceID);
+
+            auto loader = m_coreLoader;
+            WebProcess::singleton().webLoaderStrategy().remove(m_coreLoader.get());
+
+            handler->startNewTask(*loader);
+            return;
+        }
+    }
+
+    auto error = internalError(m_coreLoader->request().url());
+    error.setType(ResourceError::Type::Cancellation);
+    m_coreLoader->didFail(error);
+#else
+    ASSERT_NOT_REACHED();
+#endif
+}
+
 void WebResourceLoader::didFailResourceLoad(const ResourceError& error)
 {
     LOG(Network, "(WebProcess) WebResourceLoader::didFailResourceLoad for '%s'", m_coreLoader->url().string().latin1().data());
diff --git a/Source/WebKit/WebProcess/Network/WebResourceLoader.h b/Source/WebKit/WebProcess/Network/WebResourceLoader.h
index 8ea1aed..7c2111d 100644
--- a/Source/WebKit/WebProcess/Network/WebResourceLoader.h
+++ b/Source/WebKit/WebProcess/Network/WebResourceLoader.h
@@ -85,6 +85,8 @@
     void didReceiveData(const IPC::DataReference&, int64_t encodedDataLength);
     void didFinishResourceLoad(const WebCore::NetworkLoadMetrics&);
     void didFailResourceLoad(const WebCore::ResourceError&);
+    void didFailServiceWorkerLoad(const WebCore::ResourceError&);
+    void serviceWorkerDidNotHandle();
     void didBlockAuthenticationChallenge();
 
     void stopLoadingAfterXFrameOptionsOrContentSecurityPolicyDenied(const WebCore::ResourceResponse&);
diff --git a/Source/WebKit/WebProcess/Network/WebResourceLoader.messages.in b/Source/WebKit/WebProcess/Network/WebResourceLoader.messages.in
index 7b93256..8c0f21a 100644
--- a/Source/WebKit/WebProcess/Network/WebResourceLoader.messages.in
+++ b/Source/WebKit/WebProcess/Network/WebResourceLoader.messages.in
@@ -27,6 +27,8 @@
     DidReceiveData(IPC::SharedBufferDataReference data, int64_t encodedDataLength)
     DidFinishResourceLoad(WebCore::NetworkLoadMetrics networkLoadMetrics)
     DidFailResourceLoad(WebCore::ResourceError error)
+    DidFailServiceWorkerLoad(WebCore::ResourceError error)
+    ServiceWorkerDidNotHandle()
     DidBlockAuthenticationChallenge()
 
     StopLoadingAfterXFrameOptionsOrContentSecurityPolicyDenied(WebCore::ResourceResponse response)
diff --git a/Source/WebKit/WebProcess/Storage/ServiceWorkerClientFetch.cpp b/Source/WebKit/WebProcess/Storage/ServiceWorkerClientFetch.cpp
deleted file mode 100644
index 324466a..0000000
--- a/Source/WebKit/WebProcess/Storage/ServiceWorkerClientFetch.cpp
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright (C) 2017 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 "ServiceWorkerClientFetch.h"
-
-#if ENABLE(SERVICE_WORKER)
-
-#include "DataReference.h"
-#include "WebSWClientConnection.h"
-#include "WebServiceWorkerProvider.h"
-#include <WebCore/CrossOriginAccessControl.h>
-#include <WebCore/Document.h>
-#include <WebCore/Frame.h>
-#include <WebCore/NotImplemented.h>
-#include <WebCore/ResourceError.h>
-#include <WebCore/SharedBuffer.h>
-
-namespace WebKit {
-using namespace WebCore;
-
-Ref<ServiceWorkerClientFetch> ServiceWorkerClientFetch::create(WebServiceWorkerProvider& serviceWorkerProvider, Ref<WebCore::ResourceLoader>&& loader, FetchIdentifier identifier, Ref<WebSWClientConnection>&& connection, bool shouldClearReferrerOnHTTPSToHTTPRedirect, Callback&& callback)
-{
-    auto fetch = adoptRef(*new ServiceWorkerClientFetch { serviceWorkerProvider, WTFMove(loader), identifier, WTFMove(connection), shouldClearReferrerOnHTTPSToHTTPRedirect, WTFMove(callback) });
-    fetch->start();
-    return fetch;
-}
-
-ServiceWorkerClientFetch::~ServiceWorkerClientFetch()
-{
-}
-
-ServiceWorkerClientFetch::ServiceWorkerClientFetch(WebServiceWorkerProvider& serviceWorkerProvider, Ref<WebCore::ResourceLoader>&& loader, FetchIdentifier identifier, Ref<WebSWClientConnection>&& connection, bool shouldClearReferrerOnHTTPSToHTTPRedirect, Callback&& callback)
-    : m_serviceWorkerProvider(serviceWorkerProvider)
-    , m_loader(WTFMove(loader))
-    , m_identifier(identifier)
-    , m_connection(WTFMove(connection))
-    , m_callback(WTFMove(callback))
-    , m_shouldClearReferrerOnHTTPSToHTTPRedirect(shouldClearReferrerOnHTTPSToHTTPRedirect)
-{
-}
-
-void ServiceWorkerClientFetch::start()
-{
-    auto request = m_loader->request();
-    auto& options = m_loader->options();
-
-    auto referrer = request.httpReferrer();
-
-    // We are intercepting fetch calls after going through the HTTP layer, which may add some specific headers.
-    cleanHTTPRequestHeadersForAccessControl(request, options.httpHeadersToKeep);
-
-    ASSERT(options.serviceWorkersMode != ServiceWorkersMode::None);
-    m_serviceWorkerRegistrationIdentifier = options.serviceWorkerRegistrationIdentifier.value();
-    m_connection->startFetch(m_identifier, m_serviceWorkerRegistrationIdentifier, request, options, referrer);
-}
-
-void ServiceWorkerClientFetch::didReceiveRedirectResponse(ResourceResponse&& response)
-{
-    callOnMainThread([this, protectedThis = makeRef(*this), response = WTFMove(response)]() mutable {
-        if (!m_loader)
-            return;
-
-        response.setSource(ResourceResponse::Source::ServiceWorker);
-
-        m_loader->willSendRequest(m_loader->request().redirectedRequest(response, m_shouldClearReferrerOnHTTPSToHTTPRedirect), response, [this, protectedThis = protectedThis.copyRef()](ResourceRequest&& request) {
-            if (!m_loader || request.isNull()) {
-                if (auto callback = WTFMove(m_callback))
-                    callback(Result::Succeeded);
-                return;
-            }
-            ASSERT(request == m_loader->request());
-            start();
-        });
-    });
-}
-
-void ServiceWorkerClientFetch::didReceiveResponse(ResourceResponse&& response, bool needsContinueDidReceiveResponseMessage)
-{
-    callOnMainThread([this, protectedThis = makeRef(*this), response = WTFMove(response), needsContinueDidReceiveResponseMessage]() mutable {
-        if (!m_loader)
-            return;
-
-        if (auto callback = WTFMove(m_callback))
-            callback(Result::Succeeded);
-
-        ASSERT(!response.isRedirection() || !response.httpHeaderFields().contains(HTTPHeaderName::Location));
-
-        if (!needsContinueDidReceiveResponseMessage) {
-            m_loader->didReceiveResponse(response, [] { });
-            return;
-        }
-
-        m_loader->didReceiveResponse(response, [this, protectedThis = WTFMove(protectedThis)] {
-            if (!m_loader)
-                return;
-
-            m_connection->continueDidReceiveFetchResponse(m_identifier, m_serviceWorkerRegistrationIdentifier);
-        });
-    });
-}
-
-void ServiceWorkerClientFetch::didReceiveData(const IPC::DataReference& dataReference, int64_t encodedDataLength)
-{
-    auto* data = reinterpret_cast<const char*>(dataReference.data());
-    callOnMainThread([this, protectedThis = makeRef(*this), encodedDataLength, buffer = SharedBuffer::create(data, dataReference.size())]() mutable {
-        if (!m_loader)
-            return;
-
-        m_encodedDataLength += encodedDataLength;
-
-        m_loader->didReceiveBuffer(WTFMove(buffer), m_encodedDataLength, DataPayloadBytes);
-    });
-}
-
-void ServiceWorkerClientFetch::didReceiveFormData(const IPC::FormDataReference&)
-{
-    // FIXME: Implement form data reading.
-}
-
-void ServiceWorkerClientFetch::didFinish()
-{
-    callOnMainThread([this, protectedThis = makeRef(*this)] {
-        if (!m_loader)
-            return;
-
-        ASSERT(!m_callback);
-
-        m_loader->didFinishLoading(NetworkLoadMetrics { });
-        m_serviceWorkerProvider.fetchFinished(m_identifier);
-    });
-}
-
-void ServiceWorkerClientFetch::didFail(ResourceError&& error)
-{
-    callOnMainThread([this, protectedThis = makeRef(*this), error = WTFMove(error)] {
-        if (!m_loader)
-            return;
-
-        auto* document = m_loader->frame() ? m_loader->frame()->document() : nullptr;
-        if (document) {
-            if (m_loader->options().destination != FetchOptions::Destination::EmptyString || error.isGeneral())
-                document->addConsoleMessage(MessageSource::JS, MessageLevel::Error, error.localizedDescription());
-            if (m_loader->options().destination != FetchOptions::Destination::EmptyString)
-                document->addConsoleMessage(MessageSource::JS, MessageLevel::Error, makeString("Cannot load ", error.failingURL().string(), "."));
-        }
-
-        m_loader->didFail(error);
-
-        if (auto callback = WTFMove(m_callback))
-            callback(Result::Succeeded);
-
-        m_serviceWorkerProvider.fetchFinished(m_identifier);
-    });
-}
-
-void ServiceWorkerClientFetch::didNotHandle()
-{
-    callOnMainThread([this, protectedThis = makeRef(*this)] {
-        if (!m_loader)
-            return;
-
-        if (auto callback = WTFMove(m_callback))
-            callback(Result::Unhandled);
-
-        m_serviceWorkerProvider.fetchFinished(m_identifier);
-    });
-}
-
-void ServiceWorkerClientFetch::cancel()
-{
-    if (auto callback = WTFMove(m_callback))
-        callback(Result::Cancelled);
-
-    m_connection->cancelFetch(m_identifier, m_serviceWorkerRegistrationIdentifier);
-    m_loader = nullptr;
-}
-
-} // namespace WebKit
-
-#endif // ENABLE(SERVICE_WORKER)
diff --git a/Source/WebKit/WebProcess/Storage/ServiceWorkerClientFetch.h b/Source/WebKit/WebProcess/Storage/ServiceWorkerClientFetch.h
deleted file mode 100644
index c667ac7..0000000
--- a/Source/WebKit/WebProcess/Storage/ServiceWorkerClientFetch.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2017 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 "DataReference.h"
-#include "FormDataReference.h"
-#include "MessageReceiver.h"
-#include "MessageSender.h"
-#include <WebCore/FetchIdentifier.h>
-#include <WebCore/ResourceError.h>
-#include <WebCore/ResourceLoader.h>
-#include <wtf/CompletionHandler.h>
-
-namespace WebKit {
-
-class WebSWClientConnection;
-class WebServiceWorkerProvider;
-
-class ServiceWorkerClientFetch final : public RefCounted<ServiceWorkerClientFetch>, public IPC::MessageReceiver {
-public:
-    enum class Result { Succeeded, Cancelled, Unhandled };
-    using Callback = WTF::CompletionHandler<void(Result)>;
-
-    static Ref<ServiceWorkerClientFetch> create(WebServiceWorkerProvider&, Ref<WebCore::ResourceLoader>&&, WebCore::FetchIdentifier, Ref<WebSWClientConnection>&&, bool shouldClearReferrerOnHTTPSToHTTPRedirect, Callback&&);
-    ~ServiceWorkerClientFetch();
-
-    void start();
-
-    void didReceiveMessage(IPC::Connection&, IPC::Decoder&) final;
-    void cancel();
-
-    bool isOngoing() const { return !!m_callback; }
-
-private:
-    ServiceWorkerClientFetch(WebServiceWorkerProvider&, Ref<WebCore::ResourceLoader>&&, WebCore::FetchIdentifier, Ref<WebSWClientConnection>&&, bool shouldClearReferrerOnHTTPSToHTTPRedirect, Callback&&);
-
-    Optional<WebCore::ResourceError> validateResponse(const WebCore::ResourceResponse&);
-
-    void didReceiveResponse(WebCore::ResourceResponse&&, bool needsContinueDidReceiveResponseMessage);
-    void didReceiveRedirectResponse(WebCore::ResourceResponse&&);
-    void didReceiveData(const IPC::DataReference&, int64_t encodedDataLength);
-    void didReceiveFormData(const IPC::FormDataReference&);
-    void didFinish();
-    void didFail(WebCore::ResourceError&&);
-    void didNotHandle();
-
-    WebServiceWorkerProvider& m_serviceWorkerProvider;
-    RefPtr<WebCore::ResourceLoader> m_loader;
-    WebCore::FetchIdentifier m_identifier;
-    Ref<WebSWClientConnection> m_connection;
-    Callback m_callback;
-    bool m_shouldClearReferrerOnHTTPSToHTTPRedirect { true };
-    int64_t m_encodedDataLength { 0 };
-    bool m_didFail { false };
-    WebCore::ServiceWorkerRegistrationIdentifier m_serviceWorkerRegistrationIdentifier;
-};
-
-} // namespace WebKit
-
-#endif // ENABLE(SERVICE_WORKER)
diff --git a/Source/WebKit/WebProcess/Storage/ServiceWorkerClientFetch.messages.in b/Source/WebKit/WebProcess/Storage/ServiceWorkerClientFetch.messages.in
deleted file mode 100644
index 3d3bc74..0000000
--- a/Source/WebKit/WebProcess/Storage/ServiceWorkerClientFetch.messages.in
+++ /dev/null
@@ -1,35 +0,0 @@
-# Copyright (C) 2017 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.
-
-#if ENABLE(SERVICE_WORKER)
-
-messages -> ServiceWorkerClientFetch {
-    DidReceiveResponse(WebCore::ResourceResponse response, bool needsContinueDidReceiveResponseMessage)
-    DidReceiveRedirectResponse(WebCore::ResourceResponse response)
-    DidReceiveData(IPC::DataReference data, int64_t encodedDataLength)
-    DidReceiveFormData(IPC::FormDataReference data)
-    DidFinish()
-    DidFail(WebCore::ResourceError error)
-    DidNotHandle()
-}
-
-#endif // ENABLE(SERVICE_WORKER)
diff --git a/Source/WebKit/WebProcess/Storage/WebSWClientConnection.cpp b/Source/WebKit/WebProcess/Storage/WebSWClientConnection.cpp
index 06a4cc7..d0089bf 100644
--- a/Source/WebKit/WebProcess/Storage/WebSWClientConnection.cpp
+++ b/Source/WebKit/WebProcess/Storage/WebSWClientConnection.cpp
@@ -34,7 +34,6 @@
 #include "NetworkConnectionToWebProcessMessages.h"
 #include "NetworkProcessConnection.h"
 #include "NetworkProcessMessages.h"
-#include "ServiceWorkerClientFetch.h"
 #include "WebCoreArgumentCoders.h"
 #include "WebProcess.h"
 #include "WebProcessPoolMessages.h"
@@ -203,21 +202,6 @@
     });
 }
 
-void WebSWClientConnection::startFetch(FetchIdentifier fetchIdentifier, ServiceWorkerRegistrationIdentifier serviceWorkerRegistrationIdentifier, const ResourceRequest& request, const FetchOptions& options, const String& referrer)
-{
-    send(Messages::WebSWServerConnection::StartFetch { serviceWorkerRegistrationIdentifier, fetchIdentifier, request, options, IPC::FormDataReference { request.httpBody() }, referrer });
-}
-
-void WebSWClientConnection::cancelFetch(FetchIdentifier fetchIdentifier, ServiceWorkerRegistrationIdentifier serviceWorkerRegistrationIdentifier)
-{
-    send(Messages::WebSWServerConnection::CancelFetch { serviceWorkerRegistrationIdentifier, fetchIdentifier });
-}
-
-void WebSWClientConnection::continueDidReceiveFetchResponse(FetchIdentifier fetchIdentifier, ServiceWorkerRegistrationIdentifier serviceWorkerRegistrationIdentifier)
-{
-    send(Messages::WebSWServerConnection::ContinueDidReceiveFetchResponse { serviceWorkerRegistrationIdentifier, fetchIdentifier });
-}
-
 void WebSWClientConnection::connectionToServerLost()
 {
     clear();
diff --git a/Source/WebKit/WebProcess/Storage/WebSWClientConnection.h b/Source/WebKit/WebProcess/Storage/WebSWClientConnection.h
index 27fea2c..9e445f5 100644
--- a/Source/WebKit/WebProcess/Storage/WebSWClientConnection.h
+++ b/Source/WebKit/WebProcess/Storage/WebSWClientConnection.h
@@ -30,7 +30,6 @@
 #include "Connection.h"
 #include "MessageReceiver.h"
 #include "MessageSender.h"
-#include "ServiceWorkerClientFetch.h"
 #include "SharedMemory.h"
 #include <WebCore/MessageWithMessagePorts.h>
 #include <WebCore/SWClientConnection.h>
@@ -60,9 +59,6 @@
     void didReceiveMessage(IPC::Connection&, IPC::Decoder&) final;
 
     bool mayHaveServiceWorkerRegisteredForOrigin(const WebCore::SecurityOriginData&) const final;
-    void startFetch(WebCore::FetchIdentifier, WebCore::ServiceWorkerRegistrationIdentifier, const WebCore::ResourceRequest&, const WebCore::FetchOptions&, const String& referrer);
-    void cancelFetch(WebCore::FetchIdentifier, WebCore::ServiceWorkerRegistrationIdentifier);
-    void continueDidReceiveFetchResponse(WebCore::FetchIdentifier, WebCore::ServiceWorkerRegistrationIdentifier);
 
     void connectionToServerLost();
 
diff --git a/Source/WebKit/WebProcess/Storage/WebServiceWorkerProvider.cpp b/Source/WebKit/WebProcess/Storage/WebServiceWorkerProvider.cpp
index 62a39b2..7dcd18e 100644
--- a/Source/WebKit/WebProcess/Storage/WebServiceWorkerProvider.cpp
+++ b/Source/WebKit/WebProcess/Storage/WebServiceWorkerProvider.cpp
@@ -66,48 +66,6 @@
     return networkProcessConnection->existingServiceWorkerConnection();
 }
 
-static inline bool shouldHandleFetch(const ResourceLoaderOptions& options)
-{
-    if (options.serviceWorkersMode == ServiceWorkersMode::None)
-        return false;
-
-    if (isPotentialNavigationOrSubresourceRequest(options.destination))
-        return false;
-
-    return !!options.serviceWorkerRegistrationIdentifier;
-}
-
-void WebServiceWorkerProvider::handleFetch(ResourceLoader& loader, bool shouldClearReferrerOnHTTPSToHTTPRedirect, ServiceWorkerClientFetch::Callback&& callback)
-{
-    if (!LegacySchemeRegistry::canServiceWorkersHandleURLScheme(loader.request().url().protocol().toStringWithoutCopying()) || !shouldHandleFetch(loader.options())) {
-        callback(ServiceWorkerClientFetch::Result::Unhandled);
-        return;
-    }
-
-    auto& connection = WebProcess::singleton().ensureNetworkProcessConnection().serviceWorkerConnection();
-    auto fetchIdentifier = makeObjectIdentifier<FetchIdentifierType>(loader.identifier());
-    m_ongoingFetchTasks.add(fetchIdentifier, ServiceWorkerClientFetch::create(*this, loader, fetchIdentifier, connection, shouldClearReferrerOnHTTPSToHTTPRedirect, WTFMove(callback)));
-}
-
-bool WebServiceWorkerProvider::cancelFetch(FetchIdentifier fetchIdentifier)
-{
-    auto fetch = m_ongoingFetchTasks.take(fetchIdentifier);
-    if (fetch)
-        (*fetch)->cancel();
-    return !!fetch;
-}
-
-void WebServiceWorkerProvider::fetchFinished(FetchIdentifier fetchIdentifier)
-{
-    m_ongoingFetchTasks.take(fetchIdentifier);
-}
-
-void WebServiceWorkerProvider::didReceiveServiceWorkerClientFetchMessage(IPC::Connection& connection, IPC::Decoder& decoder)
-{
-    if (auto fetch = m_ongoingFetchTasks.get(makeObjectIdentifier<FetchIdentifierType>(decoder.destinationID())))
-        fetch->didReceiveMessage(connection, decoder);
-}
-
 } // namespace WebKit
 
 #endif // ENABLE(SERVICE_WORKER)
diff --git a/Source/WebKit/WebProcess/Storage/WebServiceWorkerProvider.h b/Source/WebKit/WebProcess/Storage/WebServiceWorkerProvider.h
index 088aed9..c00c047 100644
--- a/Source/WebKit/WebProcess/Storage/WebServiceWorkerProvider.h
+++ b/Source/WebKit/WebProcess/Storage/WebServiceWorkerProvider.h
@@ -27,7 +27,6 @@
 
 #if ENABLE(SERVICE_WORKER)
 
-#include "ServiceWorkerClientFetch.h"
 #include <WebCore/ServiceWorkerProvider.h>
 #include <wtf/NeverDestroyed.h>
 
@@ -41,11 +40,6 @@
 public:
     static WebServiceWorkerProvider& singleton();
 
-    void handleFetch(WebCore::ResourceLoader&, bool shouldClearReferrerOnHTTPSToHTTPRedirect, ServiceWorkerClientFetch::Callback&&);
-    bool cancelFetch(WebCore::FetchIdentifier);
-    void fetchFinished(WebCore::FetchIdentifier);
-
-    void didReceiveServiceWorkerClientFetchMessage(IPC::Connection&, IPC::Decoder&);
     void didReceiveServiceWorkerClientRegistrationMatch(IPC::Connection&, IPC::Decoder&);
 
 private:
@@ -54,8 +48,6 @@
 
     WebCore::SWClientConnection* existingServiceWorkerConnection() final;
     WebCore::SWClientConnection& serviceWorkerConnection() final;
-
-    HashMap<WebCore::FetchIdentifier, Ref<ServiceWorkerClientFetch>> m_ongoingFetchTasks;
 }; // class WebServiceWorkerProvider
 
 } // namespace WebKit