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/CacheOpParent.h"
8 :
9 : #include "mozilla/Unused.h"
10 : #include "mozilla/dom/cache/AutoUtils.h"
11 : #include "mozilla/dom/cache/ReadStream.h"
12 : #include "mozilla/dom/cache/SavedTypes.h"
13 : #include "mozilla/ipc/FileDescriptorSetParent.h"
14 : #include "mozilla/ipc/InputStreamUtils.h"
15 :
16 : namespace mozilla {
17 : namespace dom {
18 : namespace cache {
19 :
20 : using mozilla::ipc::FileDescriptorSetParent;
21 : using mozilla::ipc::PBackgroundParent;
22 :
23 0 : CacheOpParent::CacheOpParent(PBackgroundParent* aIpcManager, CacheId aCacheId,
24 0 : const CacheOpArgs& aOpArgs)
25 : : mIpcManager(aIpcManager)
26 : , mCacheId(aCacheId)
27 : , mNamespace(INVALID_NAMESPACE)
28 0 : , mOpArgs(aOpArgs)
29 : {
30 0 : MOZ_DIAGNOSTIC_ASSERT(mIpcManager);
31 0 : }
32 :
33 0 : CacheOpParent::CacheOpParent(PBackgroundParent* aIpcManager,
34 0 : Namespace aNamespace, const CacheOpArgs& aOpArgs)
35 : : mIpcManager(aIpcManager)
36 : , mCacheId(INVALID_CACHE_ID)
37 : , mNamespace(aNamespace)
38 0 : , mOpArgs(aOpArgs)
39 : {
40 0 : MOZ_DIAGNOSTIC_ASSERT(mIpcManager);
41 0 : }
42 :
43 0 : CacheOpParent::~CacheOpParent()
44 : {
45 0 : NS_ASSERT_OWNINGTHREAD(CacheOpParent);
46 0 : }
47 :
48 : void
49 0 : CacheOpParent::Execute(ManagerId* aManagerId)
50 : {
51 0 : NS_ASSERT_OWNINGTHREAD(CacheOpParent);
52 0 : MOZ_DIAGNOSTIC_ASSERT(!mManager);
53 0 : MOZ_DIAGNOSTIC_ASSERT(!mVerifier);
54 :
55 0 : RefPtr<cache::Manager> manager;
56 0 : nsresult rv = cache::Manager::GetOrCreate(aManagerId, getter_AddRefs(manager));
57 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
58 0 : ErrorResult result(rv);
59 0 : Unused << Send__delete__(this, result, void_t());
60 0 : result.SuppressException();
61 0 : return;
62 : }
63 :
64 0 : Execute(manager);
65 : }
66 :
67 : void
68 0 : CacheOpParent::Execute(cache::Manager* aManager)
69 : {
70 0 : NS_ASSERT_OWNINGTHREAD(CacheOpParent);
71 0 : MOZ_DIAGNOSTIC_ASSERT(!mManager);
72 0 : MOZ_DIAGNOSTIC_ASSERT(!mVerifier);
73 :
74 0 : mManager = aManager;
75 :
76 : // Handle put op
77 0 : if (mOpArgs.type() == CacheOpArgs::TCachePutAllArgs) {
78 0 : MOZ_DIAGNOSTIC_ASSERT(mCacheId != INVALID_CACHE_ID);
79 :
80 0 : const CachePutAllArgs& args = mOpArgs.get_CachePutAllArgs();
81 0 : const nsTArray<CacheRequestResponse>& list = args.requestResponseList();
82 :
83 0 : AutoTArray<nsCOMPtr<nsIInputStream>, 256> requestStreamList;
84 0 : AutoTArray<nsCOMPtr<nsIInputStream>, 256> responseStreamList;
85 :
86 0 : for (uint32_t i = 0; i < list.Length(); ++i) {
87 : requestStreamList.AppendElement(
88 0 : DeserializeCacheStream(list[i].request().body()));
89 : responseStreamList.AppendElement(
90 0 : DeserializeCacheStream(list[i].response().body()));
91 : }
92 :
93 0 : mManager->ExecutePutAll(this, mCacheId, args.requestResponseList(),
94 0 : requestStreamList, responseStreamList);
95 0 : return;
96 : }
97 :
98 : // Handle all other cache ops
99 0 : if (mCacheId != INVALID_CACHE_ID) {
100 0 : MOZ_DIAGNOSTIC_ASSERT(mNamespace == INVALID_NAMESPACE);
101 0 : mManager->ExecuteCacheOp(this, mCacheId, mOpArgs);
102 0 : return;
103 : }
104 :
105 : // Handle all storage ops
106 0 : MOZ_DIAGNOSTIC_ASSERT(mNamespace != INVALID_NAMESPACE);
107 0 : mManager->ExecuteStorageOp(this, mNamespace, mOpArgs);
108 : }
109 :
110 : void
111 0 : CacheOpParent::WaitForVerification(PrincipalVerifier* aVerifier)
112 : {
113 0 : NS_ASSERT_OWNINGTHREAD(CacheOpParent);
114 0 : MOZ_DIAGNOSTIC_ASSERT(!mManager);
115 0 : MOZ_DIAGNOSTIC_ASSERT(!mVerifier);
116 :
117 0 : mVerifier = aVerifier;
118 0 : mVerifier->AddListener(this);
119 0 : }
120 :
121 : void
122 0 : CacheOpParent::ActorDestroy(ActorDestroyReason aReason)
123 : {
124 0 : NS_ASSERT_OWNINGTHREAD(CacheOpParent);
125 :
126 0 : if (mVerifier) {
127 0 : mVerifier->RemoveListener(this);
128 0 : mVerifier = nullptr;
129 : }
130 :
131 0 : if (mManager) {
132 0 : mManager->RemoveListener(this);
133 0 : mManager = nullptr;
134 : }
135 :
136 0 : mIpcManager = nullptr;
137 0 : }
138 :
139 : void
140 0 : CacheOpParent::OnPrincipalVerified(nsresult aRv, ManagerId* aManagerId)
141 : {
142 0 : NS_ASSERT_OWNINGTHREAD(CacheOpParent);
143 :
144 0 : mVerifier->RemoveListener(this);
145 0 : mVerifier = nullptr;
146 :
147 0 : if (NS_WARN_IF(NS_FAILED(aRv))) {
148 0 : ErrorResult result(aRv);
149 0 : Unused << Send__delete__(this, result, void_t());
150 0 : result.SuppressException();
151 0 : return;
152 : }
153 :
154 0 : Execute(aManagerId);
155 : }
156 :
157 : void
158 0 : CacheOpParent::OnOpComplete(ErrorResult&& aRv, const CacheOpResult& aResult,
159 : CacheId aOpenedCacheId,
160 : const nsTArray<SavedResponse>& aSavedResponseList,
161 : const nsTArray<SavedRequest>& aSavedRequestList,
162 : StreamList* aStreamList)
163 : {
164 0 : NS_ASSERT_OWNINGTHREAD(CacheOpParent);
165 0 : MOZ_DIAGNOSTIC_ASSERT(mIpcManager);
166 0 : MOZ_DIAGNOSTIC_ASSERT(mManager);
167 :
168 : // Never send an op-specific result if we have an error. Instead, send
169 : // void_t() to ensure that we don't leak actors on the child side.
170 0 : if (NS_WARN_IF(aRv.Failed())) {
171 0 : Unused << Send__delete__(this, aRv, void_t());
172 0 : aRv.SuppressException(); // We serialiazed it, as best we could.
173 0 : return;
174 : }
175 :
176 0 : uint32_t entryCount = std::max(1lu, static_cast<unsigned long>(
177 0 : std::max(aSavedResponseList.Length(),
178 0 : aSavedRequestList.Length())));
179 :
180 : // The result must contain the appropriate type at this point. It may
181 : // or may not contain the additional result data yet. For types that
182 : // do not need special processing, it should already be set. If the
183 : // result requires actor-specific operations, then we do that below.
184 : // If the type and data types don't match, then we will trigger an
185 : // assertion in AutoParentOpResult::Add().
186 0 : AutoParentOpResult result(mIpcManager, aResult, entryCount);
187 :
188 0 : if (aOpenedCacheId != INVALID_CACHE_ID) {
189 0 : result.Add(aOpenedCacheId, mManager);
190 : }
191 :
192 0 : for (uint32_t i = 0; i < aSavedResponseList.Length(); ++i) {
193 0 : result.Add(aSavedResponseList[i], aStreamList);
194 : }
195 :
196 0 : for (uint32_t i = 0; i < aSavedRequestList.Length(); ++i) {
197 0 : result.Add(aSavedRequestList[i], aStreamList);
198 : }
199 :
200 0 : Unused << Send__delete__(this, aRv, result.SendAsOpResult());
201 : }
202 :
203 : already_AddRefed<nsIInputStream>
204 0 : CacheOpParent::DeserializeCacheStream(const CacheReadStreamOrVoid& aStreamOrVoid)
205 : {
206 0 : if (aStreamOrVoid.type() == CacheReadStreamOrVoid::Tvoid_t) {
207 0 : return nullptr;
208 : }
209 :
210 0 : nsCOMPtr<nsIInputStream> stream;
211 0 : const CacheReadStream& readStream = aStreamOrVoid.get_CacheReadStream();
212 :
213 : // Option 1: One of our own ReadStreams was passed back to us with a stream
214 : // control actor.
215 0 : stream = ReadStream::Create(readStream);
216 0 : if (stream) {
217 0 : return stream.forget();
218 : }
219 :
220 : // Option 2: A stream was serialized using normal methods or passed
221 : // as a PChildToParentStream actor. Use the standard method for
222 : // extracting the resulting stream.
223 0 : return DeserializeIPCStream(readStream.stream());
224 : }
225 :
226 : } // namespace cache
227 : } // namespace dom
228 : } // namespace mozilla
|