1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include "RemoteServiceWorkerContainerImpl.h"
8
9 #include <utility>
10
11 #include "mozilla/ipc/BackgroundChild.h"
12 #include "mozilla/ipc/PBackgroundChild.h"
13 #include "ServiceWorkerContainerChild.h"
14
15 namespace mozilla {
16 namespace dom {
17
18 using mozilla::ipc::BackgroundChild;
19 using mozilla::ipc::PBackgroundChild;
20 using mozilla::ipc::ResponseRejectReason;
21
~RemoteServiceWorkerContainerImpl()22 RemoteServiceWorkerContainerImpl::~RemoteServiceWorkerContainerImpl() {
23 Shutdown();
24 MOZ_DIAGNOSTIC_ASSERT(!mOuter);
25 }
26
Shutdown()27 void RemoteServiceWorkerContainerImpl::Shutdown() {
28 if (mShutdown) {
29 return;
30 }
31 mShutdown = true;
32
33 if (mActor) {
34 mActor->RevokeOwner(this);
35 mActor->MaybeStartTeardown();
36 mActor = nullptr;
37 }
38 }
39
AddContainer(ServiceWorkerContainer * aOuter)40 void RemoteServiceWorkerContainerImpl::AddContainer(
41 ServiceWorkerContainer* aOuter) {
42 MOZ_DIAGNOSTIC_ASSERT(aOuter);
43 MOZ_DIAGNOSTIC_ASSERT(!mOuter);
44 mOuter = aOuter;
45 }
46
RemoveContainer(ServiceWorkerContainer * aOuter)47 void RemoteServiceWorkerContainerImpl::RemoveContainer(
48 ServiceWorkerContainer* aOuter) {
49 MOZ_DIAGNOSTIC_ASSERT(aOuter);
50 MOZ_DIAGNOSTIC_ASSERT(mOuter == aOuter);
51 mOuter = nullptr;
52 }
53
Register(const ClientInfo & aClientInfo,const nsACString & aScopeURL,const nsACString & aScriptURL,ServiceWorkerUpdateViaCache aUpdateViaCache,ServiceWorkerRegistrationCallback && aSuccessCB,ServiceWorkerFailureCallback && aFailureCB) const54 void RemoteServiceWorkerContainerImpl::Register(
55 const ClientInfo& aClientInfo, const nsACString& aScopeURL,
56 const nsACString& aScriptURL, ServiceWorkerUpdateViaCache aUpdateViaCache,
57 ServiceWorkerRegistrationCallback&& aSuccessCB,
58 ServiceWorkerFailureCallback&& aFailureCB) const {
59 if (!mActor) {
60 CopyableErrorResult rv;
61 rv.ThrowInvalidStateError("Can't register service worker");
62 aFailureCB(std::move(rv));
63 return;
64 }
65
66 mActor->SendRegister(
67 aClientInfo.ToIPC(), nsCString(aScopeURL), nsCString(aScriptURL),
68 aUpdateViaCache,
69 [successCB = std::move(aSuccessCB), aFailureCB](
70 const IPCServiceWorkerRegistrationDescriptorOrCopyableErrorResult&
71 aResult) {
72 if (aResult.type() ==
73 IPCServiceWorkerRegistrationDescriptorOrCopyableErrorResult::
74 TCopyableErrorResult) {
75 // application layer error
76 auto& rv = aResult.get_CopyableErrorResult();
77 MOZ_DIAGNOSTIC_ASSERT(rv.Failed());
78 aFailureCB(CopyableErrorResult(rv));
79 return;
80 }
81 // success
82 auto& ipcDesc = aResult.get_IPCServiceWorkerRegistrationDescriptor();
83 successCB(ServiceWorkerRegistrationDescriptor(ipcDesc));
84 },
85 [aFailureCB](ResponseRejectReason&& aReason) {
86 // IPC layer error
87 CopyableErrorResult rv;
88 rv.ThrowInvalidStateError("Failed to register service worker");
89 aFailureCB(std::move(rv));
90 });
91 }
92
GetRegistration(const ClientInfo & aClientInfo,const nsACString & aURL,ServiceWorkerRegistrationCallback && aSuccessCB,ServiceWorkerFailureCallback && aFailureCB) const93 void RemoteServiceWorkerContainerImpl::GetRegistration(
94 const ClientInfo& aClientInfo, const nsACString& aURL,
95 ServiceWorkerRegistrationCallback&& aSuccessCB,
96 ServiceWorkerFailureCallback&& aFailureCB) const {
97 if (!mActor) {
98 aFailureCB(CopyableErrorResult(NS_ERROR_DOM_INVALID_STATE_ERR));
99 return;
100 }
101
102 mActor->SendGetRegistration(
103 aClientInfo.ToIPC(), nsCString(aURL),
104 [successCB = std::move(aSuccessCB), aFailureCB](
105 const IPCServiceWorkerRegistrationDescriptorOrCopyableErrorResult&
106 aResult) {
107 if (aResult.type() ==
108 IPCServiceWorkerRegistrationDescriptorOrCopyableErrorResult::
109 TCopyableErrorResult) {
110 auto& rv = aResult.get_CopyableErrorResult();
111 // If rv is a failure then this is an application layer error. Note,
112 // though, we also reject with NS_OK to indicate that we just didn't
113 // find a registration.
114 aFailureCB(CopyableErrorResult(rv));
115 return;
116 }
117 // success
118 auto& ipcDesc = aResult.get_IPCServiceWorkerRegistrationDescriptor();
119 successCB(ServiceWorkerRegistrationDescriptor(ipcDesc));
120 },
121 [aFailureCB](ResponseRejectReason&& aReason) {
122 // IPC layer error
123 aFailureCB(CopyableErrorResult(NS_ERROR_DOM_INVALID_STATE_ERR));
124 });
125 }
126
GetRegistrations(const ClientInfo & aClientInfo,ServiceWorkerRegistrationListCallback && aSuccessCB,ServiceWorkerFailureCallback && aFailureCB) const127 void RemoteServiceWorkerContainerImpl::GetRegistrations(
128 const ClientInfo& aClientInfo,
129 ServiceWorkerRegistrationListCallback&& aSuccessCB,
130 ServiceWorkerFailureCallback&& aFailureCB) const {
131 if (!mActor) {
132 aFailureCB(CopyableErrorResult(NS_ERROR_DOM_INVALID_STATE_ERR));
133 return;
134 }
135
136 mActor->SendGetRegistrations(
137 aClientInfo.ToIPC(),
138 [successCB = std::move(aSuccessCB), aFailureCB](
139 const IPCServiceWorkerRegistrationDescriptorListOrCopyableErrorResult&
140 aResult) {
141 if (aResult.type() ==
142 IPCServiceWorkerRegistrationDescriptorListOrCopyableErrorResult::
143 TCopyableErrorResult) {
144 // application layer error
145 auto& rv = aResult.get_CopyableErrorResult();
146 MOZ_DIAGNOSTIC_ASSERT(rv.Failed());
147 aFailureCB(CopyableErrorResult(rv));
148 return;
149 }
150 // success
151 auto& ipcList =
152 aResult.get_IPCServiceWorkerRegistrationDescriptorList();
153 nsTArray<ServiceWorkerRegistrationDescriptor> list(
154 ipcList.values().Length());
155 for (auto& ipcDesc : ipcList.values()) {
156 list.AppendElement(ServiceWorkerRegistrationDescriptor(ipcDesc));
157 }
158 successCB(std::move(list));
159 },
160 [aFailureCB](ResponseRejectReason&& aReason) {
161 // IPC layer error
162 aFailureCB(CopyableErrorResult(NS_ERROR_DOM_INVALID_STATE_ERR));
163 });
164 }
165
GetReady(const ClientInfo & aClientInfo,ServiceWorkerRegistrationCallback && aSuccessCB,ServiceWorkerFailureCallback && aFailureCB) const166 void RemoteServiceWorkerContainerImpl::GetReady(
167 const ClientInfo& aClientInfo,
168 ServiceWorkerRegistrationCallback&& aSuccessCB,
169 ServiceWorkerFailureCallback&& aFailureCB) const {
170 if (!mActor) {
171 aFailureCB(CopyableErrorResult(NS_ERROR_DOM_INVALID_STATE_ERR));
172 return;
173 }
174
175 mActor->SendGetReady(
176 aClientInfo.ToIPC(),
177 [successCB = std::move(aSuccessCB), aFailureCB](
178 const IPCServiceWorkerRegistrationDescriptorOrCopyableErrorResult&
179 aResult) {
180 if (aResult.type() ==
181 IPCServiceWorkerRegistrationDescriptorOrCopyableErrorResult::
182 TCopyableErrorResult) {
183 // application layer error
184 auto& rv = aResult.get_CopyableErrorResult();
185 MOZ_DIAGNOSTIC_ASSERT(rv.Failed());
186 aFailureCB(CopyableErrorResult(rv));
187 return;
188 }
189 // success
190 auto& ipcDesc = aResult.get_IPCServiceWorkerRegistrationDescriptor();
191 successCB(ServiceWorkerRegistrationDescriptor(ipcDesc));
192 },
193 [aFailureCB](ResponseRejectReason&& aReason) {
194 // IPC layer error
195 aFailureCB(CopyableErrorResult(NS_ERROR_DOM_INVALID_STATE_ERR));
196 });
197 }
198
RemoteServiceWorkerContainerImpl()199 RemoteServiceWorkerContainerImpl::RemoteServiceWorkerContainerImpl()
200 : mOuter(nullptr), mShutdown(false) {
201 PBackgroundChild* parentActor =
202 BackgroundChild::GetOrCreateForCurrentThread();
203 if (NS_WARN_IF(!parentActor)) {
204 Shutdown();
205 return;
206 }
207
208 RefPtr<ServiceWorkerContainerChild> actor =
209 ServiceWorkerContainerChild::Create();
210 if (NS_WARN_IF(!actor)) {
211 Shutdown();
212 return;
213 }
214
215 PServiceWorkerContainerChild* sentActor =
216 parentActor->SendPServiceWorkerContainerConstructor(actor);
217 if (NS_WARN_IF(!sentActor)) {
218 Shutdown();
219 return;
220 }
221 MOZ_DIAGNOSTIC_ASSERT(sentActor == actor);
222
223 mActor = std::move(actor);
224 mActor->SetOwner(this);
225 }
226
RevokeActor(ServiceWorkerContainerChild * aActor)227 void RemoteServiceWorkerContainerImpl::RevokeActor(
228 ServiceWorkerContainerChild* aActor) {
229 MOZ_DIAGNOSTIC_ASSERT(mActor);
230 MOZ_DIAGNOSTIC_ASSERT(mActor == aActor);
231 mActor->RevokeOwner(this);
232 mActor = nullptr;
233
234 mShutdown = true;
235 }
236
237 } // namespace dom
238 } // namespace mozilla
239