Line data Source code
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 "mozilla/dom/cache/CacheOpChild.h"
8 :
9 : #include "mozilla/dom/Promise.h"
10 : #include "mozilla/dom/Request.h"
11 : #include "mozilla/dom/Response.h"
12 : #include "mozilla/dom/cache/Cache.h"
13 : #include "mozilla/dom/cache/CacheChild.h"
14 : #include "mozilla/dom/cache/CacheStreamControlChild.h"
15 :
16 : namespace mozilla {
17 : namespace dom {
18 : namespace cache {
19 :
20 : using mozilla::ipc::PBackgroundChild;
21 :
22 : namespace {
23 :
24 : void
25 0 : AddWorkerHolderToStreamChild(const CacheReadStream& aReadStream,
26 : CacheWorkerHolder* aWorkerHolder)
27 : {
28 0 : MOZ_ASSERT_IF(!NS_IsMainThread(), aWorkerHolder);
29 : CacheStreamControlChild* cacheControl =
30 0 : static_cast<CacheStreamControlChild*>(aReadStream.controlChild());
31 0 : if (cacheControl) {
32 0 : cacheControl->SetWorkerHolder(aWorkerHolder);
33 : }
34 0 : }
35 :
36 : void
37 0 : AddWorkerHolderToStreamChild(const CacheResponse& aResponse,
38 : CacheWorkerHolder* aWorkerHolder)
39 : {
40 0 : MOZ_ASSERT_IF(!NS_IsMainThread(), aWorkerHolder);
41 :
42 0 : if (aResponse.body().type() == CacheReadStreamOrVoid::Tvoid_t) {
43 0 : return;
44 : }
45 :
46 0 : AddWorkerHolderToStreamChild(aResponse.body().get_CacheReadStream(),
47 0 : aWorkerHolder);
48 : }
49 :
50 : void
51 0 : AddWorkerHolderToStreamChild(const CacheRequest& aRequest,
52 : CacheWorkerHolder* aWorkerHolder)
53 : {
54 0 : MOZ_ASSERT_IF(!NS_IsMainThread(), aWorkerHolder);
55 :
56 0 : if (aRequest.body().type() == CacheReadStreamOrVoid::Tvoid_t) {
57 0 : return;
58 : }
59 :
60 0 : AddWorkerHolderToStreamChild(aRequest.body().get_CacheReadStream(),
61 0 : aWorkerHolder);
62 : }
63 :
64 : } // namespace
65 :
66 0 : CacheOpChild::CacheOpChild(CacheWorkerHolder* aWorkerHolder,
67 : nsIGlobalObject* aGlobal,
68 0 : nsISupports* aParent, Promise* aPromise)
69 : : mGlobal(aGlobal)
70 : , mParent(aParent)
71 0 : , mPromise(aPromise)
72 : {
73 0 : MOZ_DIAGNOSTIC_ASSERT(mGlobal);
74 0 : MOZ_DIAGNOSTIC_ASSERT(mParent);
75 0 : MOZ_DIAGNOSTIC_ASSERT(mPromise);
76 :
77 0 : MOZ_ASSERT_IF(!NS_IsMainThread(), aWorkerHolder);
78 :
79 : RefPtr<CacheWorkerHolder> workerHolder =
80 0 : CacheWorkerHolder::PreferBehavior(aWorkerHolder,
81 0 : CacheWorkerHolder::PreventIdleShutdownStart);
82 :
83 0 : SetWorkerHolder(workerHolder);
84 0 : }
85 :
86 0 : CacheOpChild::~CacheOpChild()
87 : {
88 0 : NS_ASSERT_OWNINGTHREAD(CacheOpChild);
89 0 : MOZ_DIAGNOSTIC_ASSERT(!mPromise);
90 0 : }
91 :
92 : void
93 0 : CacheOpChild::ActorDestroy(ActorDestroyReason aReason)
94 : {
95 0 : NS_ASSERT_OWNINGTHREAD(CacheOpChild);
96 :
97 : // If the actor was terminated for some unknown reason, then indicate the
98 : // operation is dead.
99 0 : if (mPromise) {
100 0 : mPromise->MaybeReject(NS_ERROR_FAILURE);
101 0 : mPromise = nullptr;
102 : }
103 :
104 0 : RemoveWorkerHolder();
105 0 : }
106 :
107 : mozilla::ipc::IPCResult
108 0 : CacheOpChild::Recv__delete__(const ErrorResult& aRv,
109 : const CacheOpResult& aResult)
110 : {
111 0 : NS_ASSERT_OWNINGTHREAD(CacheOpChild);
112 :
113 0 : if (NS_WARN_IF(aRv.Failed())) {
114 0 : MOZ_DIAGNOSTIC_ASSERT(aResult.type() == CacheOpResult::Tvoid_t);
115 : // TODO: Remove this const_cast (bug 1152078).
116 : // It is safe for now since this ErrorResult is handed off to us by IPDL
117 : // and is thrown into the trash afterwards.
118 0 : mPromise->MaybeReject(const_cast<ErrorResult&>(aRv));
119 0 : mPromise = nullptr;
120 0 : return IPC_OK();
121 : }
122 :
123 0 : switch (aResult.type()) {
124 : case CacheOpResult::TCacheMatchResult:
125 : {
126 0 : HandleResponse(aResult.get_CacheMatchResult().responseOrVoid());
127 0 : break;
128 : }
129 : case CacheOpResult::TCacheMatchAllResult:
130 : {
131 0 : HandleResponseList(aResult.get_CacheMatchAllResult().responseList());
132 0 : break;
133 : }
134 : case CacheOpResult::TCachePutAllResult:
135 : {
136 0 : mPromise->MaybeResolveWithUndefined();
137 0 : break;
138 : }
139 : case CacheOpResult::TCacheDeleteResult:
140 : {
141 0 : mPromise->MaybeResolve(aResult.get_CacheDeleteResult().success());
142 0 : break;
143 : }
144 : case CacheOpResult::TCacheKeysResult:
145 : {
146 0 : HandleRequestList(aResult.get_CacheKeysResult().requestList());
147 0 : break;
148 : }
149 : case CacheOpResult::TStorageMatchResult:
150 : {
151 0 : HandleResponse(aResult.get_StorageMatchResult().responseOrVoid());
152 0 : break;
153 : }
154 : case CacheOpResult::TStorageHasResult:
155 : {
156 0 : mPromise->MaybeResolve(aResult.get_StorageHasResult().success());
157 0 : break;
158 : }
159 : case CacheOpResult::TStorageOpenResult:
160 : {
161 : auto actor = static_cast<CacheChild*>(
162 0 : aResult.get_StorageOpenResult().actorChild());
163 :
164 : // If we have a success status then we should have an actor. Gracefully
165 : // reject instead of crashing, though, if we get a nullptr here.
166 0 : MOZ_DIAGNOSTIC_ASSERT(actor);
167 0 : if (!actor) {
168 0 : ErrorResult status;
169 0 : status.ThrowTypeError<MSG_CACHE_OPEN_FAILED>();
170 0 : mPromise->MaybeReject(status);
171 0 : break;
172 : }
173 :
174 : RefPtr<CacheWorkerHolder> workerHolder =
175 0 : CacheWorkerHolder::PreferBehavior(GetWorkerHolder(),
176 0 : CacheWorkerHolder::AllowIdleShutdownStart);
177 :
178 0 : actor->SetWorkerHolder(workerHolder);
179 0 : RefPtr<Cache> cache = new Cache(mGlobal, actor);
180 0 : mPromise->MaybeResolve(cache);
181 0 : break;
182 : }
183 : case CacheOpResult::TStorageDeleteResult:
184 : {
185 0 : mPromise->MaybeResolve(aResult.get_StorageDeleteResult().success());
186 0 : break;
187 : }
188 : case CacheOpResult::TStorageKeysResult:
189 : {
190 0 : mPromise->MaybeResolve(aResult.get_StorageKeysResult().keyList());
191 0 : break;
192 : }
193 : default:
194 0 : MOZ_CRASH("Unknown Cache op result type!");
195 : }
196 :
197 0 : mPromise = nullptr;
198 :
199 0 : return IPC_OK();
200 : }
201 :
202 : void
203 0 : CacheOpChild::StartDestroy()
204 : {
205 0 : NS_ASSERT_OWNINGTHREAD(CacheOpChild);
206 :
207 : // Do not cancel on-going operations when WorkerHolder calls this. Instead,
208 : // keep the Worker alive until we are done.
209 0 : }
210 :
211 : nsIGlobalObject*
212 0 : CacheOpChild::GetGlobalObject() const
213 : {
214 0 : return mGlobal;
215 : }
216 :
217 : #ifdef DEBUG
218 : void
219 0 : CacheOpChild::AssertOwningThread() const
220 : {
221 0 : NS_ASSERT_OWNINGTHREAD(CacheOpChild);
222 0 : }
223 : #endif
224 :
225 : PBackgroundChild*
226 0 : CacheOpChild::GetIPCManager()
227 : {
228 0 : MOZ_CRASH("CacheOpChild does not implement TypeUtils::GetIPCManager()");
229 : }
230 :
231 : void
232 0 : CacheOpChild::HandleResponse(const CacheResponseOrVoid& aResponseOrVoid)
233 : {
234 0 : if (aResponseOrVoid.type() == CacheResponseOrVoid::Tvoid_t) {
235 0 : mPromise->MaybeResolveWithUndefined();
236 0 : return;
237 : }
238 :
239 0 : const CacheResponse& cacheResponse = aResponseOrVoid.get_CacheResponse();
240 :
241 0 : AddWorkerHolderToStreamChild(cacheResponse, GetWorkerHolder());
242 0 : RefPtr<Response> response = ToResponse(cacheResponse);
243 :
244 0 : mPromise->MaybeResolve(response);
245 : }
246 :
247 : void
248 0 : CacheOpChild::HandleResponseList(const nsTArray<CacheResponse>& aResponseList)
249 : {
250 0 : AutoTArray<RefPtr<Response>, 256> responses;
251 0 : responses.SetCapacity(aResponseList.Length());
252 :
253 0 : for (uint32_t i = 0; i < aResponseList.Length(); ++i) {
254 0 : AddWorkerHolderToStreamChild(aResponseList[i], GetWorkerHolder());
255 0 : responses.AppendElement(ToResponse(aResponseList[i]));
256 : }
257 :
258 0 : mPromise->MaybeResolve(responses);
259 0 : }
260 :
261 : void
262 0 : CacheOpChild::HandleRequestList(const nsTArray<CacheRequest>& aRequestList)
263 : {
264 0 : AutoTArray<RefPtr<Request>, 256> requests;
265 0 : requests.SetCapacity(aRequestList.Length());
266 :
267 0 : for (uint32_t i = 0; i < aRequestList.Length(); ++i) {
268 0 : AddWorkerHolderToStreamChild(aRequestList[i], GetWorkerHolder());
269 0 : requests.AppendElement(ToRequest(aRequestList[i]));
270 : }
271 :
272 0 : mPromise->MaybeResolve(requests);
273 0 : }
274 :
275 : } // namespace cache
276 : } // namespace dom
277 : } // namespace mozilla
|