Implement "UpdateWorkerState" and use it
[WebKit-https.git] / Source / WebKit / WebProcess / Storage / WebSWContextManagerConnection.cpp
1 /*
2  * Copyright (C) 2017 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "WebSWContextManagerConnection.h"
28
29 #if ENABLE(SERVICE_WORKER)
30
31 #include "DataReference.h"
32 #include "Logging.h"
33 #include "StorageProcessMessages.h"
34 #include "WebCacheStorageProvider.h"
35 #include "WebCoreArgumentCoders.h"
36 #include "WebDocumentLoader.h"
37 #include "WebPreferencesKeys.h"
38 #include "WebPreferencesStore.h"
39 #include "WebProcess.h"
40 #include "WebServiceWorkerFetchTaskClient.h"
41 #include "WebSocketProvider.h"
42 #include <WebCore/EditorClient.h>
43 #include <WebCore/EmptyClients.h>
44 #include <WebCore/EmptyFrameLoaderClient.h>
45 #include <WebCore/LibWebRTCProvider.h>
46 #include <WebCore/PageConfiguration.h>
47 #include <WebCore/RuntimeEnabledFeatures.h>
48 #include <WebCore/SerializedScriptValue.h>
49 #include <pal/SessionID.h>
50
51 #if USE(QUICK_LOOK)
52 #include <WebCore/PreviewLoaderClient.h>
53 #endif
54
55 using namespace PAL;
56 using namespace WebCore;
57
58 namespace WebKit {
59
60 class ServiceWorkerFrameLoaderClient final : public EmptyFrameLoaderClient {
61 public:
62     ServiceWorkerFrameLoaderClient(PAL::SessionID sessionID, uint64_t pageID, uint64_t frameID)
63         : m_sessionID(sessionID)
64         , m_pageID(pageID)
65         , m_frameID(frameID)
66     {
67     }
68
69 private:
70     Ref<DocumentLoader> createDocumentLoader(const ResourceRequest& request, const SubstituteData& substituteData) final
71     {
72         return WebDocumentLoader::create(request, substituteData);
73     }
74
75     PAL::SessionID sessionID() const final { return m_sessionID; }
76     uint64_t pageID() const final { return m_pageID; }
77     uint64_t frameID() const final { return m_frameID; }
78
79     PAL::SessionID m_sessionID;
80     uint64_t m_pageID { 0 };
81     uint64_t m_frameID { 0 };
82 };
83
84 WebSWContextManagerConnection::WebSWContextManagerConnection(Ref<IPC::Connection>&& connection, uint64_t pageID, const WebPreferencesStore& store)
85     : m_connectionToStorageProcess(WTFMove(connection))
86     , m_pageID(pageID)
87 {
88     updatePreferences(store);
89 }
90
91 void WebSWContextManagerConnection::updatePreferences(const WebPreferencesStore& store)
92 {
93     RuntimeEnabledFeatures::sharedFeatures().setServiceWorkerEnabled(true);
94     RuntimeEnabledFeatures::sharedFeatures().setCacheAPIEnabled(store.getBoolValueForKey(WebPreferencesKey::cacheAPIEnabledKey()));
95     RuntimeEnabledFeatures::sharedFeatures().setFetchAPIEnabled(store.getBoolValueForKey(WebPreferencesKey::fetchAPIEnabledKey()));
96 }
97
98 void WebSWContextManagerConnection::installServiceWorker(uint64_t serverConnectionIdentifier, const ServiceWorkerContextData& data)
99 {
100     // FIXME: Provide a sensical session ID.
101     auto sessionID = PAL::SessionID::defaultSessionID();
102
103     PageConfiguration pageConfiguration {
104         createEmptyEditorClient(),
105         WebSocketProvider::create(),
106         WebCore::LibWebRTCProvider::create(),
107         WebProcess::singleton().cacheStorageProvider()
108     };
109     fillWithEmptyClients(pageConfiguration);
110
111     // FIXME: This method should be moved directly to WebCore::SWContextManager::Connection
112     // If it weren't for ServiceWorkerFrameLoaderClient's dependence on WebDocumentLoader, this could already happen.
113     auto frameLoaderClient = std::make_unique<ServiceWorkerFrameLoaderClient>(sessionID, m_pageID, ++m_previousServiceWorkerID);
114     pageConfiguration.loaderClientForMainFrame = frameLoaderClient.release();
115
116     auto serviceWorkerThreadProxy = ServiceWorkerThreadProxy::create(WTFMove(pageConfiguration), serverConnectionIdentifier, data, sessionID, WebProcess::singleton().cacheStorageProvider());
117     SWContextManager::singleton().registerServiceWorkerThreadForInstall(WTFMove(serviceWorkerThreadProxy));
118
119     LOG(ServiceWorker, "Context process PID: %i created worker thread\n", getpid());
120 }
121
122 void WebSWContextManagerConnection::serviceWorkerStartedWithMessage(ServiceWorkerIdentifier serviceWorkerIdentifier, const String& exceptionMessage)
123 {
124     auto* threadProxy = SWContextManager::singleton().serviceWorkerThreadProxy(serviceWorkerIdentifier);
125     ASSERT(threadProxy);
126     
127     auto& data = threadProxy->thread().contextData();
128     
129     if (exceptionMessage.isEmpty())
130         m_connectionToStorageProcess->send(Messages::StorageProcess::ServiceWorkerContextStarted(threadProxy->thread().serverConnectionIdentifier(), data.registrationKey, serviceWorkerIdentifier), 0);
131     else
132         m_connectionToStorageProcess->send(Messages::StorageProcess::ServiceWorkerContextFailedToStart(threadProxy->thread().serverConnectionIdentifier(), data.registrationKey, serviceWorkerIdentifier, exceptionMessage), 0);
133 }
134
135 void WebSWContextManagerConnection::startFetch(uint64_t serverConnectionIdentifier, uint64_t fetchIdentifier, std::optional<ServiceWorkerIdentifier> serviceWorkerIdentifier, ResourceRequest&& request, FetchOptions&& options)
136 {
137     auto* serviceWorkerThreadProxy = serviceWorkerIdentifier ? SWContextManager::singleton().serviceWorkerThreadProxy(*serviceWorkerIdentifier) : nullptr;
138     if (!serviceWorkerThreadProxy) {
139         m_connectionToStorageProcess->send(Messages::StorageProcess::DidNotHandleFetch(serverConnectionIdentifier, fetchIdentifier), 0);
140         return;
141     }
142
143     auto client = WebServiceWorkerFetchTaskClient::create(m_connectionToStorageProcess.copyRef(), serverConnectionIdentifier, fetchIdentifier);
144     serviceWorkerThreadProxy->thread().postFetchTask(WTFMove(client), WTFMove(request), WTFMove(options));
145 }
146
147 void WebSWContextManagerConnection::postMessageToServiceWorkerGlobalScope(ServiceWorkerIdentifier destinationIdentifier, const IPC::DataReference& message, const ServiceWorkerClientIdentifier& sourceIdentifier, const String& sourceOrigin)
148 {
149     SWContextManager::singleton().postMessageToServiceWorkerGlobalScope(destinationIdentifier, SerializedScriptValue::adopt(message.vector()), sourceIdentifier, sourceOrigin);
150 }
151
152 void WebSWContextManagerConnection::fireInstallEvent(uint64_t serverConnectionIdentifier, ServiceWorkerIdentifier identifier)
153 {
154     UNUSED_PARAM(serverConnectionIdentifier);
155     SWContextManager::singleton().fireInstallEvent(identifier);
156 }
157
158 void WebSWContextManagerConnection::postMessageToServiceWorkerClient(const ServiceWorkerClientIdentifier& destinationIdentifier, Ref<SerializedScriptValue>&& message, ServiceWorkerIdentifier sourceIdentifier, const String& sourceOrigin)
159 {
160     m_connectionToStorageProcess->send(Messages::StorageProcess::PostMessageToServiceWorkerClient(destinationIdentifier, IPC::DataReference { message->data() }, sourceIdentifier, sourceOrigin), 0);
161 }
162
163 void WebSWContextManagerConnection::didFinishInstall(ServiceWorkerIdentifier serviceWorkerIdentifier, bool wasSuccessful)
164 {
165     auto* threadProxy = SWContextManager::singleton().serviceWorkerThreadProxy(serviceWorkerIdentifier);
166     ASSERT(threadProxy);
167
168     auto& data = threadProxy->thread().contextData();
169     m_connectionToStorageProcess->send(Messages::StorageProcess::DidFinishServiceWorkerInstall(threadProxy->thread().serverConnectionIdentifier(), data.registrationKey, serviceWorkerIdentifier, wasSuccessful), 0);
170 }
171
172 } // namespace WebCore
173
174 #endif // ENABLE(SERVICE_WORKER)