Add release logging to help debug issues related to service workers
[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 #define SWSERVERCONNECTION_RELEASE_LOG_IF_ALLOWED(fmt, ...) RELEASE_LOG_IF(m_sessionID.isAlwaysOnLoggingAllowed(), ServiceWorker, "%p - WebSWServerConnection::" fmt, this, ##__VA_ARGS__)
60 #define SWSERVERCONNECTION_RELEASE_LOG_ERROR_IF_ALLOWED(fmt, ...) RELEASE_LOG_ERROR_IF(m_sessionID.isAlwaysOnLoggingAllowed(), ServiceWorker, "%p - WebSWServerConnection::" fmt, this, ##__VA_ARGS__)
61
62 WebSWServerConnection::WebSWServerConnection(SWServer& server, IPC::Connection& connection, SessionID sessionID)
63     : SWServer::Connection(server)
64     , m_sessionID(sessionID)
65     , m_contentConnection(connection)
66 {
67     StorageProcess::singleton().registerSWServerConnection(*this);
68 }
69
70 WebSWServerConnection::~WebSWServerConnection()
71 {
72     StorageProcess::singleton().unregisterSWServerConnection(*this);
73     for (auto keyValue : m_clientOrigins)
74         server().unregisterServiceWorkerClient(keyValue.value, keyValue.key);
75 }
76
77 void WebSWServerConnection::disconnectedFromWebProcess()
78 {
79     notImplemented();
80 }
81
82 void WebSWServerConnection::rejectJobInClient(ServiceWorkerJobIdentifier jobIdentifier, const ExceptionData& exceptionData)
83 {
84     send(Messages::WebSWClientConnection::JobRejectedInServer(jobIdentifier, exceptionData));
85 }
86
87 void WebSWServerConnection::resolveRegistrationJobInClient(ServiceWorkerJobIdentifier jobIdentifier, const ServiceWorkerRegistrationData& registrationData, ShouldNotifyWhenResolved shouldNotifyWhenResolved)
88 {
89     send(Messages::WebSWClientConnection::RegistrationJobResolvedInServer(jobIdentifier, registrationData, shouldNotifyWhenResolved));
90 }
91
92 void WebSWServerConnection::resolveUnregistrationJobInClient(ServiceWorkerJobIdentifier jobIdentifier, const ServiceWorkerRegistrationKey& registrationKey, bool unregistrationResult)
93 {
94     send(Messages::WebSWClientConnection::UnregistrationJobResolvedInServer(jobIdentifier, unregistrationResult));
95 }
96
97 void WebSWServerConnection::startScriptFetchInClient(ServiceWorkerJobIdentifier jobIdentifier, const ServiceWorkerRegistrationKey& registrationKey, FetchOptions::Cache cachePolicy)
98 {
99     send(Messages::WebSWClientConnection::StartScriptFetchForServer(jobIdentifier, registrationKey, cachePolicy));
100 }
101
102 void WebSWServerConnection::updateRegistrationStateInClient(ServiceWorkerRegistrationIdentifier identifier, ServiceWorkerRegistrationState state, const std::optional<ServiceWorkerData>& serviceWorkerData)
103 {
104     send(Messages::WebSWClientConnection::UpdateRegistrationState(identifier, state, serviceWorkerData));
105 }
106
107 void WebSWServerConnection::fireUpdateFoundEvent(ServiceWorkerRegistrationIdentifier identifier)
108 {
109     send(Messages::WebSWClientConnection::FireUpdateFoundEvent(identifier));
110 }
111
112 void WebSWServerConnection::setRegistrationLastUpdateTime(ServiceWorkerRegistrationIdentifier identifier, WallTime lastUpdateTime)
113 {
114     send(Messages::WebSWClientConnection::SetRegistrationLastUpdateTime(identifier, lastUpdateTime));
115 }
116
117 void WebSWServerConnection::setRegistrationUpdateViaCache(ServiceWorkerRegistrationIdentifier identifier, ServiceWorkerUpdateViaCache updateViaCache)
118 {
119     send(Messages::WebSWClientConnection::SetRegistrationUpdateViaCache(identifier, updateViaCache));
120 }
121
122 void WebSWServerConnection::notifyClientsOfControllerChange(const HashSet<DocumentIdentifier>& contextIdentifiers, const ServiceWorkerData& newController)
123 {
124     send(Messages::WebSWClientConnection::NotifyClientsOfControllerChange(contextIdentifiers, newController));
125 }
126
127 void WebSWServerConnection::updateWorkerStateInClient(ServiceWorkerIdentifier worker, ServiceWorkerState state)
128 {
129     send(Messages::WebSWClientConnection::UpdateWorkerState(worker, state));
130 }
131
132 void WebSWServerConnection::startFetch(uint64_t fetchIdentifier, ServiceWorkerRegistrationIdentifier serviceWorkerRegistrationIdentifier, ResourceRequest&& request, FetchOptions&& options, IPC::FormDataReference&& formData, String&& referrer)
133 {
134     auto* worker = server().activeWorkerFromRegistrationID(serviceWorkerRegistrationIdentifier);
135     if (!worker) {
136         SWSERVERCONNECTION_RELEASE_LOG_ERROR_IF_ALLOWED("startFetch: fetchIdentifier: %llu -> DidNotHandle because no active worker", fetchIdentifier);
137         m_contentConnection->send(Messages::ServiceWorkerClientFetch::DidNotHandle { }, fetchIdentifier);
138         return;
139     }
140     auto serviceWorkerIdentifier = worker->identifier();
141
142     auto runServerWorkerAndStartFetch = [weakThis = makeWeakPtr(this), this, fetchIdentifier, serviceWorkerIdentifier, request = WTFMove(request), options = WTFMove(options), formData = WTFMove(formData), referrer = WTFMove(referrer)](bool success) mutable {
143         if (!weakThis)
144             return;
145
146         if (!success) {
147             SWSERVERCONNECTION_RELEASE_LOG_ERROR_IF_ALLOWED("startFetch: fetchIdentifier: %llu -> DidNotHandle because worker did not become activated", fetchIdentifier);
148             m_contentConnection->send(Messages::ServiceWorkerClientFetch::DidNotHandle { }, fetchIdentifier);
149             return;
150         }
151
152         server().runServiceWorkerIfNecessary(serviceWorkerIdentifier, [weakThis = WTFMove(weakThis), this, fetchIdentifier, serviceWorkerIdentifier, request = WTFMove(request), options = WTFMove(options), formData = WTFMove(formData), referrer = WTFMove(referrer)](bool success, auto& contextConnection) {
153             if (!weakThis)
154                 return;
155
156             if (success) {
157                 SWSERVERCONNECTION_RELEASE_LOG_IF_ALLOWED("startFetch: Starting fetch %llu via service worker %llu", fetchIdentifier, serviceWorkerIdentifier.toUInt64());
158                 sendToContextProcess(contextConnection, Messages::WebSWContextManagerConnection::StartFetch { identifier(), fetchIdentifier, serviceWorkerIdentifier, request, options, formData, referrer });
159             } else {
160                 SWSERVERCONNECTION_RELEASE_LOG_ERROR_IF_ALLOWED("startFetch: fetchIdentifier: %llu -> DidNotHandle because failed to run service worker", fetchIdentifier);
161                 m_contentConnection->send(Messages::ServiceWorkerClientFetch::DidNotHandle { }, fetchIdentifier);
162             }
163         });
164     };
165
166     if (worker->state() == ServiceWorkerState::Activating) {
167         worker->whenActivated(WTFMove(runServerWorkerAndStartFetch));
168         return;
169     }
170     ASSERT(worker->state() == ServiceWorkerState::Activated);
171     runServerWorkerAndStartFetch(true);
172 }
173
174 void WebSWServerConnection::postMessageToServiceWorker(ServiceWorkerIdentifier destinationIdentifier, IPC::DataReference&& message, const ServiceWorkerOrClientIdentifier& sourceIdentifier)
175 {
176     std::optional<ServiceWorkerOrClientData> sourceData;
177     WTF::switchOn(sourceIdentifier, [&](ServiceWorkerIdentifier identifier) {
178         if (auto* sourceWorker = server().workerByID(identifier))
179             sourceData = ServiceWorkerOrClientData { sourceWorker->data() };
180     }, [&](ServiceWorkerClientIdentifier identifier) {
181         if (auto clientData = server().serviceWorkerClientByID(identifier))
182             sourceData = ServiceWorkerOrClientData { *clientData };
183     });
184
185     if (!sourceData)
186         return;
187
188     // It's possible this specific worker cannot be re-run (e.g. its registration has been removed)
189     server().runServiceWorkerIfNecessary(destinationIdentifier, [destinationIdentifier, message = message.vector(), sourceData = WTFMove(*sourceData)](bool success, auto& contextConnection) mutable {
190         if (success)
191             sendToContextProcess(contextConnection, Messages::WebSWContextManagerConnection::PostMessageToServiceWorker { destinationIdentifier, message, WTFMove(sourceData) });
192     });
193 }
194
195 void WebSWServerConnection::didReceiveFetchResponse(uint64_t fetchIdentifier, const ResourceResponse& response)
196 {
197     m_contentConnection->send(Messages::ServiceWorkerClientFetch::DidReceiveResponse { response }, fetchIdentifier);
198 }
199
200 void WebSWServerConnection::didReceiveFetchData(uint64_t fetchIdentifier, const IPC::DataReference& data, int64_t encodedDataLength)
201 {
202     m_contentConnection->send(Messages::ServiceWorkerClientFetch::DidReceiveData { data, encodedDataLength }, fetchIdentifier);
203 }
204
205 void WebSWServerConnection::didReceiveFetchFormData(uint64_t fetchIdentifier, const IPC::FormDataReference& formData)
206 {
207     m_contentConnection->send(Messages::ServiceWorkerClientFetch::DidReceiveFormData { formData }, fetchIdentifier);
208 }
209
210 void WebSWServerConnection::didFinishFetch(uint64_t fetchIdentifier)
211 {
212     SWSERVERCONNECTION_RELEASE_LOG_IF_ALLOWED("didFinishFetch: fetchIdentifier: %llu", fetchIdentifier);
213     m_contentConnection->send(Messages::ServiceWorkerClientFetch::DidFinish { }, fetchIdentifier);
214 }
215
216 void WebSWServerConnection::didFailFetch(uint64_t fetchIdentifier)
217 {
218     SWSERVERCONNECTION_RELEASE_LOG_ERROR_IF_ALLOWED("didFailFetch: fetchIdentifier: %llu", fetchIdentifier);
219     m_contentConnection->send(Messages::ServiceWorkerClientFetch::DidFail { }, fetchIdentifier);
220 }
221
222 void WebSWServerConnection::didNotHandleFetch(uint64_t fetchIdentifier)
223 {
224     SWSERVERCONNECTION_RELEASE_LOG_IF_ALLOWED("didNotHandleFetch: fetchIdentifier: %llu", fetchIdentifier);
225     m_contentConnection->send(Messages::ServiceWorkerClientFetch::DidNotHandle { }, fetchIdentifier);
226 }
227
228 void WebSWServerConnection::postMessageToServiceWorkerClient(DocumentIdentifier destinationContextIdentifier, const IPC::DataReference& message, ServiceWorkerIdentifier sourceIdentifier, const String& sourceOrigin)
229 {
230     auto* sourceServiceWorker = server().workerByID(sourceIdentifier);
231     if (!sourceServiceWorker)
232         return;
233
234     send(Messages::WebSWClientConnection::PostMessageToServiceWorkerClient { destinationContextIdentifier, message, sourceServiceWorker->data(), sourceOrigin });
235 }
236
237 void WebSWServerConnection::matchRegistration(uint64_t registrationMatchRequestIdentifier, const SecurityOriginData& topOrigin, const URL& clientURL)
238 {
239     if (auto* registration = doRegistrationMatching(topOrigin, clientURL)) {
240         send(Messages::WebSWClientConnection::DidMatchRegistration { registrationMatchRequestIdentifier, registration->data() });
241         return;
242     }
243     send(Messages::WebSWClientConnection::DidMatchRegistration { registrationMatchRequestIdentifier, std::nullopt });
244 }
245
246 void WebSWServerConnection::registrationReady(uint64_t registrationReadyRequestIdentifier, ServiceWorkerRegistrationData&& registrationData)
247 {
248     send(Messages::WebSWClientConnection::RegistrationReady { registrationReadyRequestIdentifier, WTFMove(registrationData) });
249 }
250
251 void WebSWServerConnection::getRegistrations(uint64_t registrationMatchRequestIdentifier, const SecurityOriginData& topOrigin, const URL& clientURL)
252 {
253     auto registrations = server().getRegistrations(topOrigin, clientURL);
254     send(Messages::WebSWClientConnection::DidGetRegistrations { registrationMatchRequestIdentifier, registrations });
255 }
256
257 void WebSWServerConnection::registerServiceWorkerClient(SecurityOriginData&& topOrigin, ServiceWorkerClientData&& data, const std::optional<ServiceWorkerIdentifier>& controllingServiceWorkerIdentifier)
258 {
259     auto clientOrigin = ClientOrigin { WTFMove(topOrigin), SecurityOriginData::fromSecurityOrigin(SecurityOrigin::create(data.url)) };
260     m_clientOrigins.add(data.identifier, clientOrigin);
261     server().registerServiceWorkerClient(WTFMove(clientOrigin), WTFMove(data), controllingServiceWorkerIdentifier);
262 }
263
264 void WebSWServerConnection::unregisterServiceWorkerClient(const ServiceWorkerClientIdentifier& clientIdentifier)
265 {
266     auto iterator = m_clientOrigins.find(clientIdentifier);
267     if (iterator == m_clientOrigins.end())
268         return;
269
270     server().unregisterServiceWorkerClient(iterator->value, clientIdentifier);
271     m_clientOrigins.remove(iterator);
272 }
273
274 template<typename U> void WebSWServerConnection::sendToContextProcess(U&& message)
275 {
276     if (auto* connection = StorageProcess::singleton().globalServerToContextConnection())
277         connection->send(WTFMove(message));
278 }
279
280 template<typename U> void WebSWServerConnection::sendToContextProcess(WebCore::SWServerToContextConnection& connection, U&& message)
281 {
282     static_cast<WebSWServerToContextConnection&>(connection).send(WTFMove(message));
283 }
284
285 } // namespace WebKit
286
287 #endif // ENABLE(SERVICE_WORKER)