5a1e9132352c5385d54bcec7fdee74f17a8ff13e
[WebKit-https.git] / Source / WebKit / StorageProcess / ServiceWorker / WebSWServerConnection.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 "WebSWServerConnection.h"
28
29 #if ENABLE(SERVICE_WORKER)
30
31 #include "DataReference.h"
32 #include "Logging.h"
33 #include "ServiceWorkerClientFetchMessages.h"
34 #include "StorageProcess.h"
35 #include "StorageToWebProcessConnectionMessages.h"
36 #include "WebCoreArgumentCoders.h"
37 #include "WebProcess.h"
38 #include "WebProcessMessages.h"
39 #include "WebSWClientConnectionMessages.h"
40 #include "WebSWContextManagerConnectionMessages.h"
41 #include "WebSWServerConnectionMessages.h"
42 #include "WebSWServerToContextConnection.h"
43 #include "WebToStorageProcessConnection.h"
44 #include <WebCore/ExceptionData.h>
45 #include <WebCore/NotImplemented.h>
46 #include <WebCore/SWServerRegistration.h>
47 #include <WebCore/SecurityOrigin.h>
48 #include <WebCore/ServiceWorkerClientData.h>
49 #include <WebCore/ServiceWorkerClientIdentifier.h>
50 #include <WebCore/ServiceWorkerContextData.h>
51 #include <WebCore/ServiceWorkerJobData.h>
52 #include <wtf/MainThread.h>
53
54 using namespace PAL;
55 using namespace WebCore;
56
57 namespace WebKit {
58
59 WebSWServerConnection::WebSWServerConnection(SWServer& server, IPC::Connection& connection, SessionID sessionID)
60     : SWServer::Connection(server)
61     , m_sessionID(sessionID)
62     , m_contentConnection(connection)
63 {
64     StorageProcess::singleton().registerSWServerConnection(*this);
65 }
66
67 WebSWServerConnection::~WebSWServerConnection()
68 {
69     StorageProcess::singleton().unregisterSWServerConnection(*this);
70     for (auto keyValue : m_clientOrigins)
71         server().unregisterServiceWorkerClient(keyValue.value, ServiceWorkerClientIdentifier { identifier(), keyValue.key });
72 }
73
74 void WebSWServerConnection::disconnectedFromWebProcess()
75 {
76     notImplemented();
77 }
78
79 void WebSWServerConnection::rejectJobInClient(const ServiceWorkerJobDataIdentifier& jobDataIdentifier, const ExceptionData& exceptionData)
80 {
81     send(Messages::WebSWClientConnection::JobRejectedInServer(jobDataIdentifier, exceptionData));
82 }
83
84 void WebSWServerConnection::resolveRegistrationJobInClient(const ServiceWorkerJobDataIdentifier& jobDataIdentifier, const ServiceWorkerRegistrationData& registrationData, ShouldNotifyWhenResolved shouldNotifyWhenResolved)
85 {
86     send(Messages::WebSWClientConnection::RegistrationJobResolvedInServer(jobDataIdentifier, registrationData, shouldNotifyWhenResolved));
87 }
88
89 void WebSWServerConnection::resolveUnregistrationJobInClient(const ServiceWorkerJobDataIdentifier& jobDataIdentifier, const ServiceWorkerRegistrationKey& registrationKey, bool unregistrationResult)
90 {
91     send(Messages::WebSWClientConnection::UnregistrationJobResolvedInServer(jobDataIdentifier, unregistrationResult));
92 }
93
94 void WebSWServerConnection::startScriptFetchInClient(const ServiceWorkerJobDataIdentifier& jobDataIdentifier)
95 {
96     send(Messages::WebSWClientConnection::StartScriptFetchForServer(jobDataIdentifier));
97 }
98
99 void WebSWServerConnection::updateRegistrationStateInClient(ServiceWorkerRegistrationIdentifier identifier, ServiceWorkerRegistrationState state, const std::optional<ServiceWorkerData>& serviceWorkerData)
100 {
101     send(Messages::WebSWClientConnection::UpdateRegistrationState(identifier, state, serviceWorkerData));
102 }
103
104 void WebSWServerConnection::fireUpdateFoundEvent(ServiceWorkerRegistrationIdentifier identifier)
105 {
106     send(Messages::WebSWClientConnection::FireUpdateFoundEvent(identifier));
107 }
108
109 void WebSWServerConnection::notifyClientsOfControllerChange(const HashSet<DocumentIdentifier>& contextIdentifiers, const ServiceWorkerData& newController)
110 {
111     send(Messages::WebSWClientConnection::NotifyClientsOfControllerChange(contextIdentifiers, newController));
112 }
113
114 void WebSWServerConnection::updateWorkerStateInClient(ServiceWorkerIdentifier worker, ServiceWorkerState state)
115 {
116     send(Messages::WebSWClientConnection::UpdateWorkerState(worker, state));
117 }
118
119 void WebSWServerConnection::startFetch(uint64_t fetchIdentifier, std::optional<ServiceWorkerIdentifier> serviceWorkerIdentifier, ResourceRequest&& request, FetchOptions&& options, IPC::FormDataReference&& formData)
120 {
121     // It's possible this specific worker cannot be re-run (e.g. its registration has been removed)
122     if (serviceWorkerIdentifier) {
123         server().runServiceWorkerIfNecessary(*serviceWorkerIdentifier, [contentConnection = m_contentConnection.copyRef(), connectionIdentifier = identifier(), fetchIdentifier, serviceWorkerIdentifier = *serviceWorkerIdentifier, request = WTFMove(request), options = WTFMove(options), formData = WTFMove(formData)](bool success, auto& contextConnection) {
124             if (success)
125                 sendToContextProcess(contextConnection, Messages::WebSWContextManagerConnection::StartFetch { connectionIdentifier, fetchIdentifier, serviceWorkerIdentifier, request, options, formData });
126             else
127                 contentConnection->send(Messages::ServiceWorkerClientFetch::DidNotHandle { }, fetchIdentifier);
128         });
129         return;
130     }
131
132     // FIXME: If we don't have a ServiceWorkerIdentifier here then we need to create and run the appropriate Service Worker,
133     // but it's unclear that we have enough information here to do that.
134
135     sendToContextProcess(Messages::WebSWContextManagerConnection::StartFetch { identifier(), fetchIdentifier, serviceWorkerIdentifier, request, options, formData });
136 }
137
138 void WebSWServerConnection::postMessageToServiceWorkerFromClient(ServiceWorkerIdentifier destinationIdentifier, IPC::DataReference&& message, ServiceWorkerClientIdentifier sourceIdentifier, ServiceWorkerClientData&& sourceData)
139 {
140     // It's possible this specific worker cannot be re-run (e.g. its registration has been removed)
141     server().runServiceWorkerIfNecessary(destinationIdentifier, [destinationIdentifier, message = WTFMove(message), sourceIdentifier, sourceData = WTFMove(sourceData)](bool success, auto& contextConnection) mutable {
142         if (success)
143             sendToContextProcess(contextConnection, Messages::WebSWContextManagerConnection::PostMessageToServiceWorkerFromClient { destinationIdentifier, message, sourceIdentifier, WTFMove(sourceData) });
144     });
145 }
146
147 void WebSWServerConnection::postMessageToServiceWorkerFromServiceWorker(ServiceWorkerIdentifier destinationIdentifier, IPC::DataReference&& message, ServiceWorkerIdentifier sourceIdentifier)
148 {
149     auto* sourceWorker = server().workerByID(sourceIdentifier);
150     if (!sourceWorker)
151         return;
152
153     // It's possible this specific worker cannot be re-run (e.g. its registration has been removed)
154     server().runServiceWorkerIfNecessary(destinationIdentifier, [destinationIdentifier, message = WTFMove(message), sourceIdentifier, sourceData = sourceWorker->data()](bool success, auto& contextConnection) mutable {
155         if (!success)
156             return;
157
158         sendToContextProcess(contextConnection, Messages::WebSWContextManagerConnection::PostMessageToServiceWorkerFromServiceWorker { destinationIdentifier, message, WTFMove(sourceData) });
159     });
160 }
161
162 void WebSWServerConnection::didReceiveFetchResponse(uint64_t fetchIdentifier, const ResourceResponse& response)
163 {
164     m_contentConnection->send(Messages::ServiceWorkerClientFetch::DidReceiveResponse { response }, fetchIdentifier);
165 }
166
167 void WebSWServerConnection::didReceiveFetchData(uint64_t fetchIdentifier, const IPC::DataReference& data, int64_t encodedDataLength)
168 {
169     m_contentConnection->send(Messages::ServiceWorkerClientFetch::DidReceiveData { data, encodedDataLength }, fetchIdentifier);
170 }
171
172 void WebSWServerConnection::didReceiveFetchFormData(uint64_t fetchIdentifier, const IPC::FormDataReference& formData)
173 {
174     m_contentConnection->send(Messages::ServiceWorkerClientFetch::DidReceiveFormData { formData }, fetchIdentifier);
175 }
176
177 void WebSWServerConnection::didFinishFetch(uint64_t fetchIdentifier)
178 {
179     m_contentConnection->send(Messages::ServiceWorkerClientFetch::DidFinish { }, fetchIdentifier);
180 }
181
182 void WebSWServerConnection::didFailFetch(uint64_t fetchIdentifier)
183 {
184     m_contentConnection->send(Messages::ServiceWorkerClientFetch::DidFail { }, fetchIdentifier);
185 }
186
187 void WebSWServerConnection::didNotHandleFetch(uint64_t fetchIdentifier)
188 {
189     m_contentConnection->send(Messages::ServiceWorkerClientFetch::DidNotHandle { }, fetchIdentifier);
190 }
191
192 void WebSWServerConnection::postMessageToServiceWorkerClient(DocumentIdentifier destinationContextIdentifier, const IPC::DataReference& message, ServiceWorkerIdentifier sourceIdentifier, const String& sourceOrigin)
193 {
194     auto* sourceServiceWorker = server().workerByID(sourceIdentifier);
195     if (!sourceServiceWorker)
196         return;
197
198     send(Messages::WebSWClientConnection::PostMessageToServiceWorkerClient { destinationContextIdentifier, message, sourceServiceWorker->data(), sourceOrigin });
199 }
200
201 void WebSWServerConnection::matchRegistration(uint64_t registrationMatchRequestIdentifier, const SecurityOriginData& topOrigin, const URL& clientURL)
202 {
203     if (auto* registration = doRegistrationMatching(topOrigin, clientURL)) {
204         send(Messages::WebSWClientConnection::DidMatchRegistration { registrationMatchRequestIdentifier, registration->data() });
205         return;
206     }
207     send(Messages::WebSWClientConnection::DidMatchRegistration { registrationMatchRequestIdentifier, std::nullopt });
208 }
209
210 void WebSWServerConnection::registrationReady(uint64_t registrationReadyRequestIdentifier, ServiceWorkerRegistrationData&& registrationData)
211 {
212     send(Messages::WebSWClientConnection::RegistrationReady { registrationReadyRequestIdentifier, WTFMove(registrationData) });
213 }
214
215 void WebSWServerConnection::getRegistrations(uint64_t registrationMatchRequestIdentifier, const SecurityOriginData& topOrigin, const URL& clientURL)
216 {
217     auto registrations = server().getRegistrations(topOrigin, clientURL);
218     send(Messages::WebSWClientConnection::DidGetRegistrations { registrationMatchRequestIdentifier, registrations });
219 }
220
221 void WebSWServerConnection::registerServiceWorkerClient(SecurityOriginData&& topOrigin, DocumentIdentifier contextIdentifier, ServiceWorkerClientData&& data, const std::optional<ServiceWorkerIdentifier>& controllingServiceWorkerIdentifier)
222 {
223     auto clientOrigin = ClientOrigin { WTFMove(topOrigin), SecurityOriginData::fromSecurityOrigin(SecurityOrigin::create(data.url)) };
224     m_clientOrigins.add(contextIdentifier, clientOrigin);
225     server().registerServiceWorkerClient(WTFMove(clientOrigin), ServiceWorkerClientIdentifier { this->identifier(), contextIdentifier } , WTFMove(data), controllingServiceWorkerIdentifier);
226 }
227
228 void WebSWServerConnection::unregisterServiceWorkerClient(DocumentIdentifier contextIdentifier)
229 {
230     auto iterator = m_clientOrigins.find(contextIdentifier);
231     if (iterator == m_clientOrigins.end())
232         return;
233
234     server().unregisterServiceWorkerClient(iterator->value, ServiceWorkerClientIdentifier { this->identifier(), contextIdentifier });
235     m_clientOrigins.remove(iterator);
236 }
237
238 template<typename U> void WebSWServerConnection::sendToContextProcess(U&& message)
239 {
240     if (auto* connection = StorageProcess::singleton().globalServerToContextConnection())
241         connection->send(WTFMove(message));
242 }
243
244 template<typename U> void WebSWServerConnection::sendToContextProcess(WebCore::SWServerToContextConnection& connection, U&& message)
245 {
246     static_cast<WebSWServerToContextConnection&>(connection).send(WTFMove(message));
247 }
248
249 } // namespace WebKit
250
251 #endif // ENABLE(SERVICE_WORKER)