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 "ActiveDOMObject.h"
31#include "DOMPromiseProxy.h"
32#include "EventTarget.h"
33#include "SWClientConnection.h"
34#include "SWServer.h"
35#include "ServiceWorkerJobClient.h"
36#include "ServiceWorkerRegistration.h"
37#include "ServiceWorkerRegistrationOptions.h"
38#include "WorkerType.h"
39#include <pal/SessionID.h>
40#include <wtf/Threading.h>
41
42namespace WebCore {
43
44class DeferredPromise;
45class NavigatorBase;
46class ServiceWorker;
47
48enum class ServiceWorkerUpdateViaCache : uint8_t;
49enum class WorkerType;
50
51class ServiceWorkerContainer final : public EventTargetWithInlineData, public ActiveDOMObject, public ServiceWorkerJobClient {
52 WTF_MAKE_NONCOPYABLE(ServiceWorkerContainer);
53 WTF_MAKE_ISO_ALLOCATED(ServiceWorkerContainer);
54public:
55 ServiceWorkerContainer(ScriptExecutionContext*, NavigatorBase&);
56 ~ServiceWorkerContainer();
57
58 ServiceWorker* controller() const;
59
60 using ReadyPromise = DOMPromiseProxy<IDLInterface<ServiceWorkerRegistration>>;
61 ReadyPromise& ready();
62
63 using RegistrationOptions = ServiceWorkerRegistrationOptions;
64 void addRegistration(const String& scriptURL, const RegistrationOptions&, Ref<DeferredPromise>&&);
65 void removeRegistration(const URL& scopeURL, Ref<DeferredPromise>&&);
66 void updateRegistration(const URL& scopeURL, const URL& scriptURL, WorkerType, RefPtr<DeferredPromise>&&);
67
68 void getRegistration(const String& clientURL, Ref<DeferredPromise>&&);
69 void updateRegistrationState(ServiceWorkerRegistrationIdentifier, ServiceWorkerRegistrationState, const Optional<ServiceWorkerData>&);
70 void fireUpdateFoundEvent(ServiceWorkerRegistrationIdentifier);
71 void fireControllerChangeEvent();
72
73 void postMessage(MessageWithMessagePorts&&, ServiceWorkerData&& sourceData, String&& sourceOrigin);
74
75 void getRegistrations(Ref<DeferredPromise>&&);
76
77 ServiceWorkerRegistration* registration(ServiceWorkerRegistrationIdentifier identifier) const { return m_registrations.get(identifier); }
78
79 void addRegistration(ServiceWorkerRegistration&);
80 void removeRegistration(ServiceWorkerRegistration&);
81
82 ServiceWorkerJob* job(ServiceWorkerJobIdentifier);
83
84 void startMessages();
85
86 bool isStopped() const { return m_isStopped; };
87
88 bool isAlwaysOnLoggingAllowed() const;
89
90private:
91 void scheduleJob(std::unique_ptr<ServiceWorkerJob>&&);
92
93 void jobFailedWithException(ServiceWorkerJob&, const Exception&) final;
94 void jobResolvedWithRegistration(ServiceWorkerJob&, ServiceWorkerRegistrationData&&, ShouldNotifyWhenResolved) final;
95 void jobResolvedWithUnregistrationResult(ServiceWorkerJob&, bool unregistrationResult) final;
96 void startScriptFetchForJob(ServiceWorkerJob&, FetchOptions::Cache) final;
97 void jobFinishedLoadingScript(ServiceWorkerJob&, const String& script, const ContentSecurityPolicyResponseHeaders&, const String& referrerPolicy) final;
98 void jobFailedLoadingScript(ServiceWorkerJob&, const ResourceError&, Exception&&) final;
99
100 void notifyFailedFetchingScript(ServiceWorkerJob&, const ResourceError&);
101 void destroyJob(ServiceWorkerJob&);
102
103 void didFinishGetRegistrationRequest(uint64_t requestIdentifier, Optional<ServiceWorkerRegistrationData>&&);
104 void didFinishGetRegistrationsRequest(uint64_t requestIdentifier, Vector<ServiceWorkerRegistrationData>&&);
105
106 SWServerConnectionIdentifier connectionIdentifier() final;
107 DocumentOrWorkerIdentifier contextIdentifier() final;
108
109 SWClientConnection& ensureSWClientConnection();
110
111 const char* activeDOMObjectName() const final;
112 bool canSuspendForDocumentSuspension() const final;
113 ScriptExecutionContext* scriptExecutionContext() const final { return ActiveDOMObject::scriptExecutionContext(); }
114 EventTargetInterface eventTargetInterface() const final { return ServiceWorkerContainerEventTargetInterfaceType; }
115 void refEventTarget() final;
116 void derefEventTarget() final;
117 void stop() final;
118
119 void notifyRegistrationIsSettled(const ServiceWorkerRegistrationKey&);
120
121 std::unique_ptr<ReadyPromise> m_readyPromise;
122
123 NavigatorBase& m_navigator;
124
125 RefPtr<SWClientConnection> m_swConnection;
126
127 struct OngoingJob {
128 std::unique_ptr<ServiceWorkerJob> job;
129 RefPtr<PendingActivity<ServiceWorkerContainer>> pendingActivity;
130 };
131 HashMap<ServiceWorkerJobIdentifier, OngoingJob> m_jobMap;
132
133 bool m_isStopped { false };
134 HashMap<ServiceWorkerRegistrationIdentifier, ServiceWorkerRegistration*> m_registrations;
135
136#ifndef NDEBUG
137 Ref<Thread> m_creationThread { Thread::current() };
138#endif
139
140 struct PendingPromise {
141 PendingPromise(Ref<DeferredPromise>&& promise, Ref<PendingActivity<ServiceWorkerContainer>>&& pendingActivity)
142 : promise(WTFMove(promise))
143 , pendingActivity(WTFMove(pendingActivity))
144 { }
145
146 Ref<DeferredPromise> promise;
147 Ref<PendingActivity<ServiceWorkerContainer>> pendingActivity;
148 };
149
150 uint64_t m_lastPendingPromiseIdentifier { 0 };
151 HashMap<uint64_t, std::unique_ptr<PendingPromise>> m_pendingPromises;
152
153 uint64_t m_lastOngoingSettledRegistrationIdentifier { 0 };
154 HashMap<uint64_t, ServiceWorkerRegistrationKey> m_ongoingSettledRegistrations;
155
156};
157
158} // namespace WebCore
159
160#endif // ENABLE(SERVICE_WORKER)
161