Coverage Report

Created: 2018-09-25 14:53

/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