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