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 DocumentOrWorkerIdentifier contextIdentifier() final;
107
108 SWClientConnection& ensureSWClientConnection();
109
110 const char* activeDOMObjectName() const final;
111 bool canSuspendForDocumentSuspension() const final;
112 ScriptExecutionContext* scriptExecutionContext() const final { return ActiveDOMObject::scriptExecutionContext(); }
113 EventTargetInterface eventTargetInterface() const final { return ServiceWorkerContainerEventTargetInterfaceType; }
114 void refEventTarget() final;
115 void derefEventTarget() final;
116 void stop() final;
117
118 void notifyRegistrationIsSettled(const ServiceWorkerRegistrationKey&);
119
120 std::unique_ptr<ReadyPromise> m_readyPromise;
121
122 NavigatorBase& m_navigator;
123
124 RefPtr<SWClientConnection> m_swConnection;
125
126 struct OngoingJob {
127 std::unique_ptr<ServiceWorkerJob> job;
128 RefPtr<PendingActivity<ServiceWorkerContainer>> pendingActivity;
129 };
130 HashMap<ServiceWorkerJobIdentifier, OngoingJob> m_jobMap;
131
132 bool m_isStopped { false };
133 HashMap<ServiceWorkerRegistrationIdentifier, ServiceWorkerRegistration*> m_registrations;
134
135#ifndef NDEBUG
136 Ref<Thread> m_creationThread { Thread::current() };
137#endif
138
139 struct PendingPromise {
140 PendingPromise(Ref<DeferredPromise>&& promise, Ref<PendingActivity<ServiceWorkerContainer>>&& pendingActivity)
141 : promise(WTFMove(promise))
142 , pendingActivity(WTFMove(pendingActivity))
143 { }
144
145 Ref<DeferredPromise> promise;
146 Ref<PendingActivity<ServiceWorkerContainer>> pendingActivity;
147 };
148
149 uint64_t m_lastPendingPromiseIdentifier { 0 };
150 HashMap<uint64_t, std::unique_ptr<PendingPromise>> m_pendingPromises;
151
152 uint64_t m_lastOngoingSettledRegistrationIdentifier { 0 };
153 HashMap<uint64_t, ServiceWorkerRegistrationKey> m_ongoingSettledRegistrations;
154
155};
156
157} // namespace WebCore
158
159#endif // ENABLE(SERVICE_WORKER)
160