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#pragma once
27
28#if ENABLE(SERVICE_WORKER)
29
30#include "ClientOrigin.h"
31#include "DocumentIdentifier.h"
32#include "SWServerWorker.h"
33#include "SecurityOriginData.h"
34#include "ServiceWorkerClientData.h"
35#include "ServiceWorkerIdentifier.h"
36#include "ServiceWorkerJob.h"
37#include "ServiceWorkerRegistrationData.h"
38#include "ServiceWorkerRegistrationKey.h"
39#include "ServiceWorkerTypes.h"
40#include <wtf/HashMap.h>
41#include <wtf/HashSet.h>
42#include <wtf/ObjectIdentifier.h>
43#include <wtf/RunLoop.h>
44#include <wtf/ThreadSafeRefCounted.h>
45#include <wtf/Threading.h>
46#include <wtf/UniqueRef.h>
47#include <wtf/WeakPtr.h>
48
49namespace WebCore {
50
51class RegistrationStore;
52class SWOriginStore;
53class SWServerJobQueue;
54class SWServerRegistration;
55class SWServerToContextConnection;
56enum class ServiceWorkerRegistrationState : uint8_t;
57enum class ServiceWorkerState : uint8_t;
58struct ExceptionData;
59struct ServiceWorkerClientQueryOptions;
60struct ServiceWorkerContextData;
61struct ServiceWorkerFetchResult;
62struct ServiceWorkerRegistrationData;
63class Timer;
64
65class SWServer {
66 WTF_MAKE_FAST_ALLOCATED;
67public:
68 class Connection : public CanMakeWeakPtr<Connection> {
69 WTF_MAKE_FAST_ALLOCATED;
70 friend class SWServer;
71 public:
72 virtual ~Connection() = default;
73
74 using Identifier = SWServerConnectionIdentifier;
75 Identifier identifier() const { return m_identifier; }
76
77 WEBCORE_EXPORT void didResolveRegistrationPromise(const ServiceWorkerRegistrationKey&);
78 SWServerRegistration* doRegistrationMatching(const SecurityOriginData& topOrigin, const URL& clientURL) { return m_server.doRegistrationMatching(topOrigin, clientURL); }
79 void resolveRegistrationReadyRequests(SWServerRegistration&);
80
81 // Messages to the client WebProcess
82 virtual void updateRegistrationStateInClient(ServiceWorkerRegistrationIdentifier, ServiceWorkerRegistrationState, const Optional<ServiceWorkerData>&) = 0;
83 virtual void updateWorkerStateInClient(ServiceWorkerIdentifier, ServiceWorkerState) = 0;
84 virtual void fireUpdateFoundEvent(ServiceWorkerRegistrationIdentifier) = 0;
85 virtual void setRegistrationLastUpdateTime(ServiceWorkerRegistrationIdentifier, WallTime) = 0;
86 virtual void setRegistrationUpdateViaCache(ServiceWorkerRegistrationIdentifier, ServiceWorkerUpdateViaCache) = 0;
87 virtual void notifyClientsOfControllerChange(const HashSet<DocumentIdentifier>& contextIdentifiers, const ServiceWorkerData& newController) = 0;
88 virtual void registrationReady(uint64_t registrationReadyRequestIdentifier, ServiceWorkerRegistrationData&&) = 0;
89
90 virtual void serverToContextConnectionCreated(SWServerToContextConnection&) = 0;
91
92 SWServer& server() { return m_server; }
93 const SWServer& server() const { return m_server; }
94
95 protected:
96 WEBCORE_EXPORT explicit Connection(SWServer&);
97
98 WEBCORE_EXPORT void finishFetchingScriptInServer(const ServiceWorkerFetchResult&);
99 WEBCORE_EXPORT void addServiceWorkerRegistrationInServer(ServiceWorkerRegistrationIdentifier);
100 WEBCORE_EXPORT void removeServiceWorkerRegistrationInServer(ServiceWorkerRegistrationIdentifier);
101 WEBCORE_EXPORT void syncTerminateWorker(ServiceWorkerIdentifier);
102 WEBCORE_EXPORT void whenRegistrationReady(uint64_t registrationReadyRequestIdentifier, const SecurityOriginData& topOrigin, const URL& clientURL);
103
104 private:
105 // Messages to the client WebProcess
106 virtual void rejectJobInClient(ServiceWorkerJobIdentifier, const ExceptionData&) = 0;
107 virtual void resolveRegistrationJobInClient(ServiceWorkerJobIdentifier, const ServiceWorkerRegistrationData&, ShouldNotifyWhenResolved) = 0;
108 virtual void resolveUnregistrationJobInClient(ServiceWorkerJobIdentifier, const ServiceWorkerRegistrationKey&, bool registrationResult) = 0;
109 virtual void startScriptFetchInClient(ServiceWorkerJobIdentifier, const ServiceWorkerRegistrationKey&, FetchOptions::Cache) = 0;
110
111 struct RegistrationReadyRequest {
112 SecurityOriginData topOrigin;
113 URL clientURL;
114 uint64_t identifier;
115 };
116
117 SWServer& m_server;
118 Identifier m_identifier;
119 Vector<RegistrationReadyRequest> m_registrationReadyRequests;
120 };
121
122 WEBCORE_EXPORT SWServer(UniqueRef<SWOriginStore>&&, String&& registrationDatabaseDirectory, PAL::SessionID);
123 WEBCORE_EXPORT ~SWServer();
124
125 WEBCORE_EXPORT void clearAll(WTF::CompletionHandler<void()>&&);
126 WEBCORE_EXPORT void clear(const SecurityOriginData&, WTF::CompletionHandler<void()>&&);
127
128 WEBCORE_EXPORT void startSuspension(CompletionHandler<void()>&&);
129 WEBCORE_EXPORT void endSuspension();
130
131 SWServerRegistration* getRegistration(const ServiceWorkerRegistrationKey&);
132 void addRegistration(std::unique_ptr<SWServerRegistration>&&);
133 void removeRegistration(const ServiceWorkerRegistrationKey&);
134 WEBCORE_EXPORT Vector<ServiceWorkerRegistrationData> getRegistrations(const SecurityOriginData& topOrigin, const URL& clientURL);
135
136 WEBCORE_EXPORT void scheduleJob(ServiceWorkerJobData&&);
137 void rejectJob(const ServiceWorkerJobData&, const ExceptionData&);
138 void resolveRegistrationJob(const ServiceWorkerJobData&, const ServiceWorkerRegistrationData&, ShouldNotifyWhenResolved);
139 void resolveUnregistrationJob(const ServiceWorkerJobData&, const ServiceWorkerRegistrationKey&, bool unregistrationResult);
140 void startScriptFetch(const ServiceWorkerJobData&, FetchOptions::Cache);
141
142 void updateWorker(Connection&, const ServiceWorkerJobDataIdentifier&, SWServerRegistration&, const URL&, const String& script, const ContentSecurityPolicyResponseHeaders&, const String& referrerPolicy, WorkerType, HashMap<URL, ServiceWorkerContextData::ImportedScript>&&);
143 void terminateWorker(SWServerWorker&);
144 void syncTerminateWorker(SWServerWorker&);
145 void fireInstallEvent(SWServerWorker&);
146 void fireActivateEvent(SWServerWorker&);
147
148 WEBCORE_EXPORT SWServerWorker* workerByID(ServiceWorkerIdentifier) const;
149 Optional<ServiceWorkerClientData> serviceWorkerClientWithOriginByID(const ClientOrigin&, const ServiceWorkerClientIdentifier&) const;
150 String serviceWorkerClientUserAgent(const ClientOrigin&) const;
151 WEBCORE_EXPORT SWServerWorker* activeWorkerFromRegistrationID(ServiceWorkerRegistrationIdentifier);
152
153 WEBCORE_EXPORT void markAllWorkersForRegistrableDomainAsTerminated(const RegistrableDomain&);
154
155 WEBCORE_EXPORT void addConnection(std::unique_ptr<Connection>&&);
156 WEBCORE_EXPORT void removeConnection(SWServerConnectionIdentifier);
157 Connection* connection(SWServerConnectionIdentifier identifier) const { return m_connections.get(identifier); }
158
159 const HashMap<SWServerConnectionIdentifier, std::unique_ptr<Connection>>& connections() const { return m_connections; }
160
161 SWOriginStore& originStore() { return m_originStore; }
162
163 void scriptContextFailedToStart(const Optional<ServiceWorkerJobDataIdentifier>&, SWServerWorker&, const String& message);
164 void scriptContextStarted(const Optional<ServiceWorkerJobDataIdentifier>&, SWServerWorker&);
165 void didFinishInstall(const Optional<ServiceWorkerJobDataIdentifier>&, SWServerWorker&, bool wasSuccessful);
166 void didFinishActivation(SWServerWorker&);
167 void workerContextTerminated(SWServerWorker&);
168 void matchAll(SWServerWorker&, const ServiceWorkerClientQueryOptions&, ServiceWorkerClientsMatchAllCallback&&);
169 void claim(SWServerWorker&);
170
171 WEBCORE_EXPORT void serverToContextConnectionCreated(SWServerToContextConnection&);
172
173 WEBCORE_EXPORT static HashSet<SWServer*>& allServers();
174
175 WEBCORE_EXPORT void registerServiceWorkerClient(ClientOrigin&&, ServiceWorkerClientData&&, const Optional<ServiceWorkerRegistrationIdentifier>&, String&& userAgent);
176 WEBCORE_EXPORT void unregisterServiceWorkerClient(const ClientOrigin&, ServiceWorkerClientIdentifier);
177
178 using RunServiceWorkerCallback = WTF::Function<void(SWServerToContextConnection*)>;
179 WEBCORE_EXPORT void runServiceWorkerIfNecessary(ServiceWorkerIdentifier, RunServiceWorkerCallback&&);
180
181 void resolveRegistrationReadyRequests(SWServerRegistration&);
182
183 void addRegistrationFromStore(ServiceWorkerContextData&&);
184 void registrationStoreImportComplete();
185 void registrationStoreDatabaseFailedToOpen();
186
187 WEBCORE_EXPORT void getOriginsWithRegistrations(Function<void(const HashSet<SecurityOriginData>&)>&&);
188
189 PAL::SessionID sessionID() const { return m_sessionID; }
190 WEBCORE_EXPORT bool needsServerToContextConnectionForRegistrableDomain(const RegistrableDomain&) const;
191
192 void disableServiceWorkerProcessTerminationDelay() { m_shouldDisableServiceWorkerProcessTerminationDelay = true; }
193
194private:
195 void scriptFetchFinished(Connection&, const ServiceWorkerFetchResult&);
196
197 void didResolveRegistrationPromise(Connection&, const ServiceWorkerRegistrationKey&);
198
199 void addClientServiceWorkerRegistration(Connection&, ServiceWorkerRegistrationIdentifier);
200 void removeClientServiceWorkerRegistration(Connection&, ServiceWorkerRegistrationIdentifier);
201
202 void terminatePreinstallationWorker(SWServerWorker&);
203
204 WEBCORE_EXPORT SWServerRegistration* doRegistrationMatching(const SecurityOriginData& topOrigin, const URL& clientURL);
205 bool runServiceWorker(ServiceWorkerIdentifier);
206
207 void tryInstallContextData(ServiceWorkerContextData&&);
208 void installContextData(const ServiceWorkerContextData&);
209
210 SWServerRegistration* registrationFromServiceWorkerIdentifier(ServiceWorkerIdentifier);
211 void forEachClientForOrigin(const ClientOrigin&, const WTF::Function<void(ServiceWorkerClientData&)>&);
212
213 void performGetOriginsWithRegistrationsCallbacks();
214
215 enum TerminationMode {
216 Synchronous,
217 Asynchronous,
218 };
219 void terminateWorkerInternal(SWServerWorker&, TerminationMode);
220
221 HashMap<SWServerConnectionIdentifier, std::unique_ptr<Connection>> m_connections;
222 HashMap<ServiceWorkerRegistrationKey, std::unique_ptr<SWServerRegistration>> m_registrations;
223 HashMap<ServiceWorkerRegistrationIdentifier, SWServerRegistration*> m_registrationsByID;
224 HashMap<ServiceWorkerRegistrationKey, std::unique_ptr<SWServerJobQueue>> m_jobQueues;
225
226 HashMap<ServiceWorkerIdentifier, Ref<SWServerWorker>> m_runningOrTerminatingWorkers;
227
228 HashMap<RegistrableDomain, HashSet<ServiceWorkerClientIdentifier>> m_clientsByRegistrableDomain;
229 struct Clients {
230 Vector<ServiceWorkerClientIdentifier> identifiers;
231 std::unique_ptr<Timer> terminateServiceWorkersTimer;
232 String userAgent;
233 };
234 HashMap<ClientOrigin, Clients> m_clientIdentifiersPerOrigin;
235 HashMap<ServiceWorkerClientIdentifier, ServiceWorkerClientData> m_clientsById;
236 HashMap<ServiceWorkerClientIdentifier, ServiceWorkerRegistrationIdentifier> m_clientToControllingRegistration;
237
238 UniqueRef<SWOriginStore> m_originStore;
239 std::unique_ptr<RegistrationStore> m_registrationStore;
240 HashMap<RegistrableDomain, Vector<ServiceWorkerContextData>> m_pendingContextDatas;
241 HashMap<RegistrableDomain, HashMap<ServiceWorkerIdentifier, Vector<RunServiceWorkerCallback>>> m_serviceWorkerRunRequests;
242 PAL::SessionID m_sessionID;
243 bool m_importCompleted { false };
244 bool m_shouldDisableServiceWorkerProcessTerminationDelay { false };
245 Vector<CompletionHandler<void()>> m_clearCompletionCallbacks;
246 Vector<Function<void(const HashSet<SecurityOriginData>&)>> m_getOriginsWithRegistrationsCallbacks;
247};
248
249} // namespace WebCore
250
251#endif // ENABLE(SERVICE_WORKER)
252