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
.controlChild());
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
,
68 : mGlobal(aGlobal
), mParent(aParent
), mPromise(aPromise
) {
69 MOZ_DIAGNOSTIC_ASSERT(mGlobal
);
70 MOZ_DIAGNOSTIC_ASSERT(mParent
);
71 MOZ_DIAGNOSTIC_ASSERT(mPromise
);
73 MOZ_ASSERT_IF(!NS_IsMainThread(), aWorkerRef
);
75 SetWorkerRef(CacheWorkerRef::PreferBehavior(
76 std::move(aWorkerRef
), CacheWorkerRef::eStrongWorkerRef
));
79 CacheOpChild::~CacheOpChild() {
80 NS_ASSERT_OWNINGTHREAD(CacheOpChild
);
81 MOZ_DIAGNOSTIC_ASSERT(!mPromise
);
84 void CacheOpChild::ActorDestroy(ActorDestroyReason aReason
) {
85 NS_ASSERT_OWNINGTHREAD(CacheOpChild
);
87 // If the actor was terminated for some unknown reason, then indicate the
90 mPromise
->MaybeReject(NS_ERROR_FAILURE
);
97 mozilla::ipc::IPCResult
CacheOpChild::Recv__delete__(
98 ErrorResult
&& aRv
, const CacheOpResult
& aResult
) {
99 NS_ASSERT_OWNINGTHREAD(CacheOpChild
);
101 if (NS_WARN_IF(aRv
.Failed())) {
102 MOZ_DIAGNOSTIC_ASSERT(aResult
.type() == CacheOpResult::Tvoid_t
);
103 mPromise
->MaybeReject(std::move(aRv
));
108 switch (aResult
.type()) {
109 case CacheOpResult::TCacheMatchResult
: {
110 HandleResponse(aResult
.get_CacheMatchResult().maybeResponse());
113 case CacheOpResult::TCacheMatchAllResult
: {
114 HandleResponseList(aResult
.get_CacheMatchAllResult().responseList());
117 case CacheOpResult::TCachePutAllResult
: {
118 mPromise
->MaybeResolveWithUndefined();
121 case CacheOpResult::TCacheDeleteResult
: {
122 mPromise
->MaybeResolve(aResult
.get_CacheDeleteResult().success());
125 case CacheOpResult::TCacheKeysResult
: {
126 HandleRequestList(aResult
.get_CacheKeysResult().requestList());
129 case CacheOpResult::TStorageMatchResult
: {
130 HandleResponse(aResult
.get_StorageMatchResult().maybeResponse());
133 case CacheOpResult::TStorageHasResult
: {
134 mPromise
->MaybeResolve(aResult
.get_StorageHasResult().success());
137 case CacheOpResult::TStorageOpenResult
: {
138 auto result
= aResult
.get_StorageOpenResult();
139 auto actor
= static_cast<CacheChild
*>(result
.actorChild());
141 // If we have a success status then we should have an actor. Gracefully
142 // reject instead of crashing, though, if we get a nullptr here.
143 MOZ_DIAGNOSTIC_ASSERT(actor
);
145 mPromise
->MaybeRejectWithTypeError(
146 "CacheStorage.open() failed to access the storage system.");
150 actor
->SetWorkerRef(CacheWorkerRef::PreferBehavior(
151 GetWorkerRefPtr().clonePtr(), CacheWorkerRef::eIPCWorkerRef
));
152 RefPtr
<Cache
> cache
= new Cache(mGlobal
, actor
, result
.ns());
153 mPromise
->MaybeResolve(cache
);
156 case CacheOpResult::TStorageDeleteResult
: {
157 mPromise
->MaybeResolve(aResult
.get_StorageDeleteResult().success());
160 case CacheOpResult::TStorageKeysResult
: {
161 mPromise
->MaybeResolve(aResult
.get_StorageKeysResult().keyList());
165 MOZ_CRASH("Unknown Cache op result type!");
173 void CacheOpChild::StartDestroy() {
174 NS_ASSERT_OWNINGTHREAD(CacheOpChild
);
176 // Do not cancel on-going operations when WorkerRef calls this. Instead,
177 // keep the Worker alive until we are done.
180 nsIGlobalObject
* CacheOpChild::GetGlobalObject() const { return mGlobal
; }
183 void CacheOpChild::AssertOwningThread() const {
184 NS_ASSERT_OWNINGTHREAD(CacheOpChild
);
188 PBackgroundChild
* CacheOpChild::GetIPCManager() {
189 MOZ_CRASH("CacheOpChild does not implement TypeUtils::GetIPCManager()");
192 void CacheOpChild::HandleResponse(const Maybe
<CacheResponse
>& aMaybeResponse
) {
193 if (aMaybeResponse
.isNothing()) {
194 mPromise
->MaybeResolveWithUndefined();
198 const CacheResponse
& cacheResponse
= aMaybeResponse
.ref();
200 AddWorkerRefToStreamChild(cacheResponse
, GetWorkerRefPtr());
201 RefPtr
<Response
> response
= ToResponse(cacheResponse
);
203 mPromise
->MaybeResolve(response
);
206 void CacheOpChild::HandleResponseList(
207 const nsTArray
<CacheResponse
>& aResponseList
) {
208 AutoTArray
<RefPtr
<Response
>, 256> responses
;
209 responses
.SetCapacity(aResponseList
.Length());
211 for (uint32_t i
= 0; i
< aResponseList
.Length(); ++i
) {
212 AddWorkerRefToStreamChild(aResponseList
[i
], GetWorkerRefPtr());
213 responses
.AppendElement(ToResponse(aResponseList
[i
]));
216 mPromise
->MaybeResolve(responses
);
219 void CacheOpChild::HandleRequestList(
220 const nsTArray
<CacheRequest
>& aRequestList
) {
221 AutoTArray
<SafeRefPtr
<Request
>, 256> requests
;
222 requests
.SetCapacity(aRequestList
.Length());
224 for (uint32_t i
= 0; i
< aRequestList
.Length(); ++i
) {
225 AddWorkerRefToStreamChild(aRequestList
[i
], GetWorkerRefPtr());
226 requests
.AppendElement(ToRequest(aRequestList
[i
]));
229 mPromise
->MaybeResolve(requests
);
233 } // namespace mozilla::dom