[Service Workers] Implement "Soft Update" algorithm
[WebKit-https.git] / Source / WebCore / workers / service / server / SWServer.h
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 "RegistrationStore.h"
33 #include "SWServerWorker.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/CrossThreadQueue.h>
41 #include <wtf/CrossThreadTask.h>
42 #include <wtf/HashMap.h>
43 #include <wtf/HashSet.h>
44 #include <wtf/ObjectIdentifier.h>
45 #include <wtf/RunLoop.h>
46 #include <wtf/ThreadSafeRefCounted.h>
47 #include <wtf/Threading.h>
48 #include <wtf/UniqueRef.h>
49 #include <wtf/WeakPtr.h>
50
51 namespace WebCore {
52
53 class SWOriginStore;
54 class SWServerJobQueue;
55 class SWServerRegistration;
56 class SWServerToContextConnection;
57 enum class ServiceWorkerRegistrationState;
58 enum class ServiceWorkerState;
59 struct ExceptionData;
60 struct ServiceWorkerClientQueryOptions;
61 struct ServiceWorkerContextData;
62 struct ServiceWorkerFetchResult;
63 struct ServiceWorkerRegistrationData;
64 class Timer;
65
66 class SWServer {
67     WTF_MAKE_FAST_ALLOCATED;
68 public:
69     class Connection {
70         WTF_MAKE_FAST_ALLOCATED;
71         friend class SWServer;
72     public:
73         WEBCORE_EXPORT virtual ~Connection();
74
75         using Identifier = SWServerConnectionIdentifier;
76         Identifier identifier() const { return m_identifier; }
77
78         auto& weakPtrFactory() { return m_weakFactory; }
79
80         WEBCORE_EXPORT void didResolveRegistrationPromise(const ServiceWorkerRegistrationKey&);
81         SWServerRegistration* doRegistrationMatching(const SecurityOriginData& topOrigin, const URL& clientURL) { return m_server.doRegistrationMatching(topOrigin, clientURL); }
82         void resolveRegistrationReadyRequests(SWServerRegistration&);
83
84         // Messages to the client WebProcess
85         virtual void updateRegistrationStateInClient(ServiceWorkerRegistrationIdentifier, ServiceWorkerRegistrationState, const std::optional<ServiceWorkerData>&) = 0;
86         virtual void updateWorkerStateInClient(ServiceWorkerIdentifier, ServiceWorkerState) = 0;
87         virtual void fireUpdateFoundEvent(ServiceWorkerRegistrationIdentifier) = 0;
88         virtual void setRegistrationLastUpdateTime(ServiceWorkerRegistrationIdentifier, WallTime) = 0;
89         virtual void setRegistrationUpdateViaCache(ServiceWorkerRegistrationIdentifier, ServiceWorkerUpdateViaCache) = 0;
90         virtual void notifyClientsOfControllerChange(const HashSet<DocumentIdentifier>& contextIdentifiers, const ServiceWorkerData& newController) = 0;
91         virtual void registrationReady(uint64_t registrationReadyRequestIdentifier, ServiceWorkerRegistrationData&&) = 0;
92
93     protected:
94         WEBCORE_EXPORT explicit Connection(SWServer&);
95         SWServer& server() { return m_server; }
96
97         WEBCORE_EXPORT void scheduleJobInServer(const ServiceWorkerJobData&);
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(const ServiceWorkerJobDataIdentifier&, const ExceptionData&) = 0;
107         virtual void resolveRegistrationJobInClient(const ServiceWorkerJobDataIdentifier&, const ServiceWorkerRegistrationData&, ShouldNotifyWhenResolved) = 0;
108         virtual void resolveUnregistrationJobInClient(const ServiceWorkerJobDataIdentifier&, const ServiceWorkerRegistrationKey&, bool registrationResult) = 0;
109         virtual void startScriptFetchInClient(const ServiceWorkerJobDataIdentifier&, 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         WeakPtrFactory<Connection> m_weakFactory;
120         Vector<RegistrationReadyRequest> m_registrationReadyRequests;
121     };
122
123     WEBCORE_EXPORT SWServer(UniqueRef<SWOriginStore>&&, String&& registrationDatabaseDirectory, PAL::SessionID);
124     WEBCORE_EXPORT ~SWServer();
125
126     WEBCORE_EXPORT void clearAll(WTF::CompletionHandler<void()>&&);
127     WEBCORE_EXPORT void clear(const SecurityOrigin&, WTF::CompletionHandler<void()>&&);
128
129     SWServerRegistration* getRegistration(const ServiceWorkerRegistrationKey&);
130     void addRegistration(std::unique_ptr<SWServerRegistration>&&);
131     void removeRegistration(const ServiceWorkerRegistrationKey&);
132     WEBCORE_EXPORT Vector<ServiceWorkerRegistrationData> getRegistrations(const SecurityOriginData& topOrigin, const URL& clientURL);
133
134     void scheduleJob(const ServiceWorkerJobData&);
135     void rejectJob(const ServiceWorkerJobData&, const ExceptionData&);
136     void resolveRegistrationJob(const ServiceWorkerJobData&, const ServiceWorkerRegistrationData&, ShouldNotifyWhenResolved);
137     void resolveUnregistrationJob(const ServiceWorkerJobData&, const ServiceWorkerRegistrationKey&, bool unregistrationResult);
138     void startScriptFetch(const ServiceWorkerJobData&, FetchOptions::Cache);
139
140     void postTask(CrossThreadTask&&);
141     void postTaskReply(CrossThreadTask&&);
142
143     void updateWorker(Connection&, const ServiceWorkerJobDataIdentifier&, SWServerRegistration&, const URL&, const String& script, WorkerType);
144     void terminateWorker(SWServerWorker&);
145     void syncTerminateWorker(SWServerWorker&);
146     void fireInstallEvent(SWServerWorker&);
147     void fireActivateEvent(SWServerWorker&);
148
149     WEBCORE_EXPORT SWServerWorker* workerByID(ServiceWorkerIdentifier) const;
150     WEBCORE_EXPORT std::optional<ServiceWorkerClientData> serviceWorkerClientByID(const ServiceWorkerClientIdentifier&) const;
151
152     WEBCORE_EXPORT void markAllWorkersAsTerminated();
153     
154     Connection* getConnection(SWServerConnectionIdentifier identifier) { return m_connections.get(identifier); }
155     SWOriginStore& originStore() { return m_originStore; }
156
157     void scriptContextFailedToStart(const std::optional<ServiceWorkerJobDataIdentifier>&, SWServerWorker&, const String& message);
158     void scriptContextStarted(const std::optional<ServiceWorkerJobDataIdentifier>&, SWServerWorker&);
159     void didFinishInstall(const std::optional<ServiceWorkerJobDataIdentifier>&, SWServerWorker&, bool wasSuccessful);
160     void didFinishActivation(SWServerWorker&);
161     void workerContextTerminated(SWServerWorker&);
162     void matchAll(SWServerWorker&, const ServiceWorkerClientQueryOptions&, ServiceWorkerClientsMatchAllCallback&&);
163     void claim(SWServerWorker&);
164
165     WEBCORE_EXPORT void serverToContextConnectionCreated();
166     
167     WEBCORE_EXPORT static HashSet<SWServer*>& allServers();
168
169     WEBCORE_EXPORT void registerServiceWorkerClient(ClientOrigin&&, ServiceWorkerClientData&&, const std::optional<ServiceWorkerIdentifier>& controllingServiceWorkerIdentifier);
170     WEBCORE_EXPORT void unregisterServiceWorkerClient(const ClientOrigin&, ServiceWorkerClientIdentifier);
171
172     using RunServiceWorkerCallback = WTF::Function<void(bool, SWServerToContextConnection&)>;
173     WEBCORE_EXPORT void runServiceWorkerIfNecessary(ServiceWorkerIdentifier, RunServiceWorkerCallback&&);
174
175     void setClientActiveWorker(ServiceWorkerClientIdentifier, ServiceWorkerIdentifier);
176     void resolveRegistrationReadyRequests(SWServerRegistration&);
177
178     void addRegistrationFromStore(ServiceWorkerContextData&&);
179     void registrationStoreImportComplete();
180     void registrationStoreDatabaseFailedToOpen();
181
182     WEBCORE_EXPORT void getOriginsWithRegistrations(WTF::Function<void(const HashSet<SecurityOriginData>&)>);
183
184 private:
185     void registerConnection(Connection&);
186     void unregisterConnection(Connection&);
187
188     void taskThreadEntryPoint();
189     void handleTaskRepliesOnMainThread();
190
191     void scriptFetchFinished(Connection&, const ServiceWorkerFetchResult&);
192
193     void didResolveRegistrationPromise(Connection&, const ServiceWorkerRegistrationKey&);
194
195     void addClientServiceWorkerRegistration(Connection&, ServiceWorkerRegistrationIdentifier);
196     void removeClientServiceWorkerRegistration(Connection&, ServiceWorkerRegistrationIdentifier);
197
198     WEBCORE_EXPORT SWServerRegistration* doRegistrationMatching(const SecurityOriginData& topOrigin, const URL& clientURL);
199     bool runServiceWorker(ServiceWorkerIdentifier);
200
201     void tryInstallContextData(ServiceWorkerContextData&&);
202     void installContextData(const ServiceWorkerContextData&);
203
204     SWServerRegistration* registrationFromServiceWorkerIdentifier(ServiceWorkerIdentifier);
205     void forEachClientForOrigin(const ClientOrigin&, const WTF::Function<void(ServiceWorkerClientData&)>&);
206
207     void performGetOriginsWithRegistrationsCallbacks();
208
209     enum TerminationMode {
210         Synchronous,
211         Asynchronous,
212     };
213     void terminateWorkerInternal(SWServerWorker&, TerminationMode);
214
215     HashMap<SWServerConnectionIdentifier, Connection*> m_connections;
216     HashMap<ServiceWorkerRegistrationKey, std::unique_ptr<SWServerRegistration>> m_registrations;
217     HashMap<ServiceWorkerRegistrationIdentifier, SWServerRegistration*> m_registrationsByID;
218     HashMap<ServiceWorkerRegistrationKey, std::unique_ptr<SWServerJobQueue>> m_jobQueues;
219
220     HashMap<ServiceWorkerIdentifier, Ref<SWServerWorker>> m_runningOrTerminatingWorkers;
221
222     struct Clients {
223         Vector<ServiceWorkerClientIdentifier> identifiers;
224         std::unique_ptr<Timer> terminateServiceWorkersTimer;
225     };
226     HashMap<ClientOrigin, Clients> m_clientIdentifiersPerOrigin;
227     HashMap<ServiceWorkerClientIdentifier, ServiceWorkerClientData> m_clientsById;
228     HashMap<ServiceWorkerClientIdentifier, ServiceWorkerIdentifier> m_clientToControllingWorker;
229
230     RefPtr<Thread> m_taskThread;
231     Lock m_taskThreadLock;
232
233     CrossThreadQueue<CrossThreadTask> m_taskQueue;
234     CrossThreadQueue<CrossThreadTask> m_taskReplyQueue;
235
236     Lock m_mainThreadReplyLock;
237     bool m_mainThreadReplyScheduled { false };
238     UniqueRef<SWOriginStore> m_originStore;
239     RegistrationStore m_registrationStore;
240     Deque<ServiceWorkerContextData> m_pendingContextDatas;
241     HashMap<ServiceWorkerIdentifier, Vector<RunServiceWorkerCallback>> m_serviceWorkerRunRequests;
242     PAL::SessionID m_sessionID;
243     bool m_importCompleted { false };
244     Vector<WTF::Function<void(const HashSet<SecurityOriginData>&)>> m_getOriginsWithRegistrationsCallbacks;
245 };
246
247 } // namespace WebCore
248
249 #endif // ENABLE(SERVICE_WORKER)