Coverage Report

Created: 2018-09-25 14:53

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