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/. */
7 #include "mozilla/dom/cache/CacheOpChild.h"
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/CacheWorkerRef.h"
17 namespace mozilla::dom
{
18 // XXX Move this to ToJSValue.h
20 [[nodiscard
]] bool ToJSValue(JSContext
* aCx
, const SafeRefPtr
<T
>& aArgument
,
21 JS::MutableHandle
<JS::Value
> aValue
) {
22 return ToJSValue(aCx
, *aArgument
.unsafeGetRawPtr(), aValue
);
27 using mozilla::ipc::PBackgroundChild
;
31 void AddWorkerRefToStreamChild(const CacheReadStream
& aReadStream
,
32 const SafeRefPtr
<CacheWorkerRef
>& aWorkerRef
) {
33 MOZ_ASSERT_IF(!NS_IsMainThread(), aWorkerRef
);
34 CacheStreamControlChild
* cacheControl
=
35 static_cast<CacheStreamControlChild
*>(aReadStream
.control().AsChild());
37 cacheControl
->SetWorkerRef(aWorkerRef
.clonePtr());
41 void AddWorkerRefToStreamChild(const CacheResponse
& aResponse
,
42 const SafeRefPtr
<CacheWorkerRef
>& aWorkerRef
) {
43 MOZ_ASSERT_IF(!NS_IsMainThread(), aWorkerRef
);
45 if (aResponse
.body().isNothing()) {
49 AddWorkerRefToStreamChild(aResponse
.body().ref(), aWorkerRef
);
52 void AddWorkerRefToStreamChild(const CacheRequest
& aRequest
,
53 const SafeRefPtr
<CacheWorkerRef
>& aWorkerRef
) {
54 MOZ_ASSERT_IF(!NS_IsMainThread(), aWorkerRef
);
56 if (aRequest
.body().isNothing()) {
60 AddWorkerRefToStreamChild(aRequest
.body().ref(), aWorkerRef
);
65 CacheOpChild::CacheOpChild(SafeRefPtr
<CacheWorkerRef
> aWorkerRef
,
66 nsIGlobalObject
* aGlobal
, nsISupports
* aParent
,
67 Promise
* aPromise
, ActorChild
* aParentActor
)
71 mParentActor(aParentActor
) {
72 MOZ_DIAGNOSTIC_ASSERT(mGlobal
);
73 MOZ_DIAGNOSTIC_ASSERT(mParent
);
74 MOZ_DIAGNOSTIC_ASSERT(mPromise
);
76 MOZ_ASSERT_IF(!NS_IsMainThread(), aWorkerRef
);
78 SetWorkerRef(CacheWorkerRef::PreferBehavior(
79 std::move(aWorkerRef
), CacheWorkerRef::eStrongWorkerRef
));
82 CacheOpChild::~CacheOpChild() {
83 NS_ASSERT_OWNINGTHREAD(CacheOpChild
);
84 MOZ_DIAGNOSTIC_ASSERT(!mPromise
);
87 void CacheOpChild::ActorDestroy(ActorDestroyReason aReason
) {
88 NS_ASSERT_OWNINGTHREAD(CacheOpChild
);
90 // If the actor was terminated for some unknown reason, then indicate the
93 mPromise
->MaybeReject(NS_ERROR_FAILURE
);
96 mParentActor
->NoteDeletedActor();
100 mozilla::ipc::IPCResult
CacheOpChild::Recv__delete__(
101 ErrorResult
&& aRv
, const CacheOpResult
& aResult
) {
102 NS_ASSERT_OWNINGTHREAD(CacheOpChild
);
104 if (NS_WARN_IF(aRv
.Failed())) {
105 MOZ_DIAGNOSTIC_ASSERT(aResult
.type() == CacheOpResult::Tvoid_t
);
106 mPromise
->MaybeReject(std::move(aRv
));
111 switch (aResult
.type()) {
112 case CacheOpResult::TCacheMatchResult
: {
113 HandleResponse(aResult
.get_CacheMatchResult().maybeResponse());
116 case CacheOpResult::TCacheMatchAllResult
: {
117 HandleResponseList(aResult
.get_CacheMatchAllResult().responseList());
120 case CacheOpResult::TCachePutAllResult
: {
121 mPromise
->MaybeResolveWithUndefined();
124 case CacheOpResult::TCacheDeleteResult
: {
125 mPromise
->MaybeResolve(aResult
.get_CacheDeleteResult().success());
128 case CacheOpResult::TCacheKeysResult
: {
129 HandleRequestList(aResult
.get_CacheKeysResult().requestList());
132 case CacheOpResult::TStorageMatchResult
: {
133 HandleResponse(aResult
.get_StorageMatchResult().maybeResponse());
136 case CacheOpResult::TStorageHasResult
: {
137 mPromise
->MaybeResolve(aResult
.get_StorageHasResult().success());
140 case CacheOpResult::TStorageOpenResult
: {
141 auto result
= aResult
.get_StorageOpenResult();
142 auto actor
= static_cast<CacheChild
*>(result
.actor().AsChild());
144 // If we have a success status then we should have an actor. Gracefully
145 // reject instead of crashing, though, if we get a nullptr here.
146 MOZ_DIAGNOSTIC_ASSERT(actor
);
148 mPromise
->MaybeRejectWithTypeError(
149 "CacheStorage.open() failed to access the storage system.");
153 actor
->SetWorkerRef(CacheWorkerRef::PreferBehavior(
154 GetWorkerRefPtr().clonePtr(), CacheWorkerRef::eIPCWorkerRef
));
155 RefPtr
<Cache
> cache
= new Cache(mGlobal
, actor
, result
.ns());
156 mPromise
->MaybeResolve(cache
);
159 case CacheOpResult::TStorageDeleteResult
: {
160 mPromise
->MaybeResolve(aResult
.get_StorageDeleteResult().success());
163 case CacheOpResult::TStorageKeysResult
: {
164 mPromise
->MaybeResolve(aResult
.get_StorageKeysResult().keyList());
168 MOZ_CRASH("Unknown Cache op result type!");
176 void CacheOpChild::StartDestroy() {
177 NS_ASSERT_OWNINGTHREAD(CacheOpChild
);
179 // Do not cancel on-going operations when WorkerRef calls this. Instead,
180 // keep the Worker alive until we are done.
183 nsIGlobalObject
* CacheOpChild::GetGlobalObject() const { return mGlobal
; }
186 void CacheOpChild::AssertOwningThread() const {
187 NS_ASSERT_OWNINGTHREAD(CacheOpChild
);
191 PBackgroundChild
* CacheOpChild::GetIPCManager() {
192 MOZ_CRASH("CacheOpChild does not implement TypeUtils::GetIPCManager()");
195 void CacheOpChild::HandleResponse(const Maybe
<CacheResponse
>& aMaybeResponse
) {
196 if (aMaybeResponse
.isNothing()) {
197 mPromise
->MaybeResolveWithUndefined();
201 const CacheResponse
& cacheResponse
= aMaybeResponse
.ref();
203 AddWorkerRefToStreamChild(cacheResponse
, GetWorkerRefPtr());
204 RefPtr
<Response
> response
= ToResponse(cacheResponse
);
206 mPromise
->MaybeResolve(response
);
209 void CacheOpChild::HandleResponseList(
210 const nsTArray
<CacheResponse
>& aResponseList
) {
211 AutoTArray
<RefPtr
<Response
>, 256> responses
;
212 responses
.SetCapacity(aResponseList
.Length());
214 for (uint32_t i
= 0; i
< aResponseList
.Length(); ++i
) {
215 AddWorkerRefToStreamChild(aResponseList
[i
], GetWorkerRefPtr());
216 responses
.AppendElement(ToResponse(aResponseList
[i
]));
219 mPromise
->MaybeResolve(responses
);
222 void CacheOpChild::HandleRequestList(
223 const nsTArray
<CacheRequest
>& aRequestList
) {
224 AutoTArray
<SafeRefPtr
<Request
>, 256> requests
;
225 requests
.SetCapacity(aRequestList
.Length());
227 for (uint32_t i
= 0; i
< aRequestList
.Length(); ++i
) {
228 AddWorkerRefToStreamChild(aRequestList
[i
], GetWorkerRefPtr());
229 requests
.AppendElement(ToRequest(aRequestList
[i
]));
232 mPromise
->MaybeResolve(requests
);
236 } // namespace mozilla::dom