Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/fetch/FetchConsumer.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 "Fetch.h"
8
#include "FetchConsumer.h"
9
10
#include "mozilla/dom/BlobBinding.h"
11
#include "mozilla/dom/File.h"
12
#include "mozilla/dom/FileBinding.h"
13
#include "mozilla/dom/FileCreatorHelper.h"
14
#include "mozilla/dom/PromiseNativeHandler.h"
15
#include "mozilla/dom/WorkerCommon.h"
16
#include "mozilla/dom/WorkerPrivate.h"
17
#include "mozilla/dom/WorkerRef.h"
18
#include "mozilla/dom/WorkerRunnable.h"
19
#include "mozilla/dom/WorkerScope.h"
20
#include "mozilla/ipc/PBackgroundSharedTypes.h"
21
#include "nsIInputStreamPump.h"
22
#include "nsIThreadRetargetableRequest.h"
23
#include "nsProxyRelease.h"
24
25
// Undefine the macro of CreateFile to avoid FileCreatorHelper#CreateFile being
26
// replaced by FileCreatorHelper#CreateFileW.
27
#ifdef CreateFile
28
#undef CreateFile
29
#endif
30
31
namespace mozilla {
32
namespace dom {
33
34
namespace {
35
36
template <class Derived>
37
class BeginConsumeBodyRunnable final : public Runnable
38
{
39
public:
40
  BeginConsumeBodyRunnable(FetchBodyConsumer<Derived>* aConsumer,
41
                           ThreadSafeWorkerRef* aWorkerRef)
42
    : Runnable("BeginConsumeBodyRunnable")
43
    , mFetchBodyConsumer(aConsumer)
44
    , mWorkerRef(aWorkerRef)
45
0
  { }
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::BeginConsumeBodyRunnable<mozilla::dom::Request>::BeginConsumeBodyRunnable(mozilla::dom::FetchBodyConsumer<mozilla::dom::Request>*, mozilla::dom::ThreadSafeWorkerRef*)
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::BeginConsumeBodyRunnable<mozilla::dom::Response>::BeginConsumeBodyRunnable(mozilla::dom::FetchBodyConsumer<mozilla::dom::Response>*, mozilla::dom::ThreadSafeWorkerRef*)
46
47
  NS_IMETHOD
48
  Run() override
49
0
  {
50
0
    mFetchBodyConsumer->BeginConsumeBodyMainThread(mWorkerRef);
51
0
    return NS_OK;
52
0
  }
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::BeginConsumeBodyRunnable<mozilla::dom::Request>::Run()
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::BeginConsumeBodyRunnable<mozilla::dom::Response>::Run()
53
54
private:
55
  RefPtr<FetchBodyConsumer<Derived>> mFetchBodyConsumer;
56
  RefPtr<ThreadSafeWorkerRef> mWorkerRef;
57
};
58
59
/*
60
 * Called on successfully reading the complete stream.
61
 */
62
template <class Derived>
63
class ContinueConsumeBodyRunnable final : public MainThreadWorkerRunnable
64
{
65
  RefPtr<FetchBodyConsumer<Derived>> mFetchBodyConsumer;
66
  nsresult mStatus;
67
  uint32_t mLength;
68
  uint8_t* mResult;
69
70
public:
71
  ContinueConsumeBodyRunnable(FetchBodyConsumer<Derived>* aFetchBodyConsumer,
72
                              WorkerPrivate* aWorkerPrivate,
73
                              nsresult aStatus, uint32_t aLength,
74
                              uint8_t* aResult)
75
    : MainThreadWorkerRunnable(aWorkerPrivate)
76
    , mFetchBodyConsumer(aFetchBodyConsumer)
77
    , mStatus(aStatus)
78
    , mLength(aLength)
79
    , mResult(aResult)
80
0
  {
81
0
    MOZ_ASSERT(NS_IsMainThread());
82
0
  }
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::ContinueConsumeBodyRunnable<mozilla::dom::Request>::ContinueConsumeBodyRunnable(mozilla::dom::FetchBodyConsumer<mozilla::dom::Request>*, mozilla::dom::WorkerPrivate*, nsresult, unsigned int, unsigned char*)
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::ContinueConsumeBodyRunnable<mozilla::dom::Response>::ContinueConsumeBodyRunnable(mozilla::dom::FetchBodyConsumer<mozilla::dom::Response>*, mozilla::dom::WorkerPrivate*, nsresult, unsigned int, unsigned char*)
83
84
  bool
85
  WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
86
0
  {
87
0
    mFetchBodyConsumer->ContinueConsumeBody(mStatus, mLength, mResult);
88
0
    return true;
89
0
  }
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::ContinueConsumeBodyRunnable<mozilla::dom::Request>::WorkerRun(JSContext*, mozilla::dom::WorkerPrivate*)
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::ContinueConsumeBodyRunnable<mozilla::dom::Response>::WorkerRun(JSContext*, mozilla::dom::WorkerPrivate*)
90
};
91
92
// ControlRunnable used to complete the releasing of resources on the worker
93
// thread when already shutting down.
94
template <class Derived>
95
class AbortConsumeBodyControlRunnable final : public MainThreadWorkerControlRunnable
96
{
97
  RefPtr<FetchBodyConsumer<Derived>> mFetchBodyConsumer;
98
99
public:
100
  AbortConsumeBodyControlRunnable(FetchBodyConsumer<Derived>* aFetchBodyConsumer,
101
                                  WorkerPrivate* aWorkerPrivate)
102
    : MainThreadWorkerControlRunnable(aWorkerPrivate)
103
    , mFetchBodyConsumer(aFetchBodyConsumer)
104
0
  {
105
0
    MOZ_ASSERT(NS_IsMainThread());
106
0
  }
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::AbortConsumeBodyControlRunnable<mozilla::dom::Request>::AbortConsumeBodyControlRunnable(mozilla::dom::FetchBodyConsumer<mozilla::dom::Request>*, mozilla::dom::WorkerPrivate*)
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::AbortConsumeBodyControlRunnable<mozilla::dom::Response>::AbortConsumeBodyControlRunnable(mozilla::dom::FetchBodyConsumer<mozilla::dom::Response>*, mozilla::dom::WorkerPrivate*)
107
108
  bool
109
  WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
110
0
  {
111
0
    mFetchBodyConsumer->ContinueConsumeBody(NS_BINDING_ABORTED, 0, nullptr,
112
0
                                            true /* shutting down */);
113
0
    return true;
114
0
  }
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::AbortConsumeBodyControlRunnable<mozilla::dom::Request>::WorkerRun(JSContext*, mozilla::dom::WorkerPrivate*)
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::AbortConsumeBodyControlRunnable<mozilla::dom::Response>::WorkerRun(JSContext*, mozilla::dom::WorkerPrivate*)
115
};
116
117
/*
118
 * In case of failure to create a stream pump or dispatch stream completion to
119
 * worker, ensure we cleanup properly. Thread agnostic.
120
 */
121
template <class Derived>
122
class MOZ_STACK_CLASS AutoFailConsumeBody final
123
{
124
public:
125
  AutoFailConsumeBody(FetchBodyConsumer<Derived>* aBodyConsumer,
126
                      ThreadSafeWorkerRef* aWorkerRef)
127
    : mBodyConsumer(aBodyConsumer)
128
    , mWorkerRef(aWorkerRef)
129
0
  {}
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::AutoFailConsumeBody<mozilla::dom::Request>::AutoFailConsumeBody(mozilla::dom::FetchBodyConsumer<mozilla::dom::Request>*, mozilla::dom::ThreadSafeWorkerRef*)
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::AutoFailConsumeBody<mozilla::dom::Response>::AutoFailConsumeBody(mozilla::dom::FetchBodyConsumer<mozilla::dom::Response>*, mozilla::dom::ThreadSafeWorkerRef*)
130
131
  ~AutoFailConsumeBody()
132
0
  {
133
0
    AssertIsOnMainThread();
134
0
135
0
    if (!mBodyConsumer) {
136
0
      return;
137
0
    }
138
0
139
0
    // Web Worker
140
0
    if (mWorkerRef) {
141
0
      RefPtr<AbortConsumeBodyControlRunnable<Derived>> r =
142
0
        new AbortConsumeBodyControlRunnable<Derived>(mBodyConsumer,
143
0
                                                     mWorkerRef->Private());
144
0
      if (!r->Dispatch()) {
145
0
        MOZ_CRASH("We are going to leak");
146
0
      }
147
0
      return;
148
0
    }
149
0
150
0
    // Main-thread
151
0
    mBodyConsumer->ContinueConsumeBody(NS_ERROR_FAILURE, 0, nullptr);
152
0
  }
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::AutoFailConsumeBody<mozilla::dom::Request>::~AutoFailConsumeBody()
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::AutoFailConsumeBody<mozilla::dom::Response>::~AutoFailConsumeBody()
153
154
  void
155
  DontFail()
156
0
  {
157
0
    mBodyConsumer = nullptr;
158
0
  }
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::AutoFailConsumeBody<mozilla::dom::Request>::DontFail()
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::AutoFailConsumeBody<mozilla::dom::Response>::DontFail()
159
160
private:
161
  RefPtr<FetchBodyConsumer<Derived>> mBodyConsumer;
162
  RefPtr<ThreadSafeWorkerRef> mWorkerRef;
163
};
164
165
/*
166
 * Called on successfully reading the complete stream for Blob.
167
 */
168
template <class Derived>
169
class ContinueConsumeBlobBodyRunnable final : public MainThreadWorkerRunnable
170
{
171
  RefPtr<FetchBodyConsumer<Derived>> mFetchBodyConsumer;
172
  RefPtr<BlobImpl> mBlobImpl;
173
174
public:
175
  ContinueConsumeBlobBodyRunnable(FetchBodyConsumer<Derived>* aFetchBodyConsumer,
176
                                  WorkerPrivate* aWorkerPrivate,
177
                                  BlobImpl* aBlobImpl)
178
    : MainThreadWorkerRunnable(aWorkerPrivate)
179
    , mFetchBodyConsumer(aFetchBodyConsumer)
180
    , mBlobImpl(aBlobImpl)
181
0
  {
182
0
    MOZ_ASSERT(NS_IsMainThread());
183
0
    MOZ_ASSERT(mBlobImpl);
184
0
  }
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::ContinueConsumeBlobBodyRunnable<mozilla::dom::Request>::ContinueConsumeBlobBodyRunnable(mozilla::dom::FetchBodyConsumer<mozilla::dom::Request>*, mozilla::dom::WorkerPrivate*, mozilla::dom::BlobImpl*)
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::ContinueConsumeBlobBodyRunnable<mozilla::dom::Response>::ContinueConsumeBlobBodyRunnable(mozilla::dom::FetchBodyConsumer<mozilla::dom::Response>*, mozilla::dom::WorkerPrivate*, mozilla::dom::BlobImpl*)
185
186
  bool
187
  WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
188
0
  {
189
0
    mFetchBodyConsumer->ContinueConsumeBlobBody(mBlobImpl);
190
0
    return true;
191
0
  }
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::ContinueConsumeBlobBodyRunnable<mozilla::dom::Request>::WorkerRun(JSContext*, mozilla::dom::WorkerPrivate*)
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::ContinueConsumeBlobBodyRunnable<mozilla::dom::Response>::WorkerRun(JSContext*, mozilla::dom::WorkerPrivate*)
192
};
193
194
// ControlRunnable used to complete the releasing of resources on the worker
195
// thread when already shutting down.
196
template <class Derived>
197
class AbortConsumeBlobBodyControlRunnable final
198
  : public MainThreadWorkerControlRunnable
199
{
200
  RefPtr<FetchBodyConsumer<Derived>> mFetchBodyConsumer;
201
202
public:
203
  AbortConsumeBlobBodyControlRunnable(FetchBodyConsumer<Derived>* aFetchBodyConsumer,
204
                                      WorkerPrivate* aWorkerPrivate)
205
    : MainThreadWorkerControlRunnable(aWorkerPrivate)
206
    , mFetchBodyConsumer(aFetchBodyConsumer)
207
0
  {
208
0
    MOZ_ASSERT(NS_IsMainThread());
209
0
  }
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::AbortConsumeBlobBodyControlRunnable<mozilla::dom::Request>::AbortConsumeBlobBodyControlRunnable(mozilla::dom::FetchBodyConsumer<mozilla::dom::Request>*, mozilla::dom::WorkerPrivate*)
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::AbortConsumeBlobBodyControlRunnable<mozilla::dom::Response>::AbortConsumeBlobBodyControlRunnable(mozilla::dom::FetchBodyConsumer<mozilla::dom::Response>*, mozilla::dom::WorkerPrivate*)
210
211
  bool
212
  WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
213
0
  {
214
0
    mFetchBodyConsumer->ContinueConsumeBlobBody(nullptr,
215
0
                                                true /* shutting down */);
216
0
    return true;
217
0
  }
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::AbortConsumeBlobBodyControlRunnable<mozilla::dom::Request>::WorkerRun(JSContext*, mozilla::dom::WorkerPrivate*)
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::AbortConsumeBlobBodyControlRunnable<mozilla::dom::Response>::WorkerRun(JSContext*, mozilla::dom::WorkerPrivate*)
218
};
219
220
template <class Derived>
221
class ConsumeBodyDoneObserver final : public nsIStreamLoaderObserver
222
                                    , public MutableBlobStorageCallback
223
{
224
public:
225
  NS_DECL_THREADSAFE_ISUPPORTS
226
227
  ConsumeBodyDoneObserver(FetchBodyConsumer<Derived>* aFetchBodyConsumer,
228
                          ThreadSafeWorkerRef* aWorkerRef)
229
    : mFetchBodyConsumer(aFetchBodyConsumer)
230
    , mWorkerRef(aWorkerRef)
231
0
  { }
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::ConsumeBodyDoneObserver<mozilla::dom::Request>::ConsumeBodyDoneObserver(mozilla::dom::FetchBodyConsumer<mozilla::dom::Request>*, mozilla::dom::ThreadSafeWorkerRef*)
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::ConsumeBodyDoneObserver<mozilla::dom::Response>::ConsumeBodyDoneObserver(mozilla::dom::FetchBodyConsumer<mozilla::dom::Response>*, mozilla::dom::ThreadSafeWorkerRef*)
232
233
  NS_IMETHOD
234
  OnStreamComplete(nsIStreamLoader* aLoader,
235
                   nsISupports* aCtxt,
236
                   nsresult aStatus,
237
                   uint32_t aResultLength,
238
                   const uint8_t* aResult) override
239
0
  {
240
0
    MOZ_ASSERT(NS_IsMainThread());
241
0
242
0
    // The loading is completed. Let's nullify the pump before continuing the
243
0
    // consuming of the body.
244
0
    mFetchBodyConsumer->NullifyConsumeBodyPump();
245
0
246
0
    uint8_t* nonconstResult = const_cast<uint8_t*>(aResult);
247
0
248
0
    // Main-thread.
249
0
    if (!mWorkerRef) {
250
0
      mFetchBodyConsumer->ContinueConsumeBody(aStatus, aResultLength,
251
0
                                              nonconstResult);
252
0
      // FetchBody is responsible for data.
253
0
      return NS_SUCCESS_ADOPTED_DATA;
254
0
    }
255
0
256
0
    // Web Worker.
257
0
    {
258
0
      RefPtr<ContinueConsumeBodyRunnable<Derived>> r =
259
0
        new ContinueConsumeBodyRunnable<Derived>(mFetchBodyConsumer,
260
0
                                                 mWorkerRef->Private(),
261
0
                                                 aStatus,
262
0
                                                 aResultLength,
263
0
                                                 nonconstResult);
264
0
      if (r->Dispatch()) {
265
0
        // FetchBody is responsible for data.
266
0
        return NS_SUCCESS_ADOPTED_DATA;
267
0
      }
268
0
    }
269
0
270
0
    // The worker is shutting down. Let's use a control runnable to complete the
271
0
    // shutting down procedure.
272
0
273
0
    RefPtr<AbortConsumeBodyControlRunnable<Derived>> r =
274
0
      new AbortConsumeBodyControlRunnable<Derived>(mFetchBodyConsumer,
275
0
                                                   mWorkerRef->Private());
276
0
    if (NS_WARN_IF(!r->Dispatch())) {
277
0
      return NS_ERROR_FAILURE;
278
0
    }
279
0
280
0
    // We haven't taken ownership of the data.
281
0
    return NS_OK;
282
0
  }
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::ConsumeBodyDoneObserver<mozilla::dom::Request>::OnStreamComplete(nsIStreamLoader*, nsISupports*, nsresult, unsigned int, unsigned char const*)
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::ConsumeBodyDoneObserver<mozilla::dom::Response>::OnStreamComplete(nsIStreamLoader*, nsISupports*, nsresult, unsigned int, unsigned char const*)
283
284
  virtual void BlobStoreCompleted(MutableBlobStorage* aBlobStorage,
285
                                  Blob* aBlob,
286
                                  nsresult aRv) override
287
0
  {
288
0
    // On error.
289
0
    if (NS_FAILED(aRv)) {
290
0
      OnStreamComplete(nullptr, nullptr, aRv, 0, nullptr);
291
0
      return;
292
0
    }
293
0
294
0
    // The loading is completed. Let's nullify the pump before continuing the
295
0
    // consuming of the body.
296
0
    mFetchBodyConsumer->NullifyConsumeBodyPump();
297
0
298
0
    mFetchBodyConsumer->OnBlobResult(aBlob, mWorkerRef);
299
0
  }
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::ConsumeBodyDoneObserver<mozilla::dom::Request>::BlobStoreCompleted(mozilla::dom::MutableBlobStorage*, mozilla::dom::Blob*, nsresult)
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::ConsumeBodyDoneObserver<mozilla::dom::Response>::BlobStoreCompleted(mozilla::dom::MutableBlobStorage*, mozilla::dom::Blob*, nsresult)
300
301
private:
302
0
  ~ConsumeBodyDoneObserver() = default;
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::ConsumeBodyDoneObserver<mozilla::dom::Request>::~ConsumeBodyDoneObserver()
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::ConsumeBodyDoneObserver<mozilla::dom::Response>::~ConsumeBodyDoneObserver()
303
304
  RefPtr<FetchBodyConsumer<Derived>> mFetchBodyConsumer;
305
  RefPtr<ThreadSafeWorkerRef> mWorkerRef;
306
};
307
308
template <class Derived>
309
NS_IMPL_ADDREF(ConsumeBodyDoneObserver<Derived>)
310
template <class Derived>
311
NS_IMPL_RELEASE(ConsumeBodyDoneObserver<Derived>)
312
template <class Derived>
313
0
NS_INTERFACE_MAP_BEGIN(ConsumeBodyDoneObserver<Derived>)
314
0
  NS_INTERFACE_MAP_ENTRY(nsIStreamLoaderObserver)
315
0
  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStreamLoaderObserver)
316
0
NS_INTERFACE_MAP_END
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::ConsumeBodyDoneObserver<mozilla::dom::Request>::QueryInterface(nsID const&, void**)
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::ConsumeBodyDoneObserver<mozilla::dom::Response>::QueryInterface(nsID const&, void**)
317
318
} // anonymous
319
320
template <class Derived>
321
/* static */ already_AddRefed<Promise>
322
FetchBodyConsumer<Derived>::Create(nsIGlobalObject* aGlobal,
323
                                   nsIEventTarget* aMainThreadEventTarget,
324
                                   FetchBody<Derived>* aBody,
325
                                   AbortSignalImpl* aSignalImpl,
326
                                   FetchConsumeType aType,
327
                                   ErrorResult& aRv)
328
0
{
329
0
  MOZ_ASSERT(aBody);
330
0
  MOZ_ASSERT(aMainThreadEventTarget);
331
0
332
0
  nsCOMPtr<nsIInputStream> bodyStream;
333
0
  aBody->DerivedClass()->GetBody(getter_AddRefs(bodyStream));
334
0
  if (!bodyStream) {
335
0
    aRv = NS_NewCStringInputStream(getter_AddRefs(bodyStream), EmptyCString());
336
0
    if (NS_WARN_IF(aRv.Failed())) {
337
0
      return nullptr;
338
0
    }
339
0
  }
340
0
341
0
  RefPtr<Promise> promise = Promise::Create(aGlobal, aRv);
342
0
  if (aRv.Failed()) {
343
0
    return nullptr;
344
0
  }
345
0
346
0
  RefPtr<FetchBodyConsumer<Derived>> consumer =
347
0
    new FetchBodyConsumer<Derived>(aMainThreadEventTarget, aGlobal,
348
0
                                   aBody, bodyStream, promise,
349
0
                                   aType);
350
0
351
0
  RefPtr<ThreadSafeWorkerRef> workerRef;
352
0
353
0
  if (!NS_IsMainThread()) {
354
0
    WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
355
0
    MOZ_ASSERT(workerPrivate);
356
0
357
0
    RefPtr<StrongWorkerRef> strongWorkerRef =
358
0
      StrongWorkerRef::Create(workerPrivate, "FetchBodyConsumer",
359
0
                              [consumer]() {
360
0
        consumer->ShutDownMainThreadConsuming();
361
0
      });
Unexecuted instantiation: mozilla::dom::FetchBodyConsumer<mozilla::dom::Request>::Create(nsIGlobalObject*, nsIEventTarget*, mozilla::dom::FetchBody<mozilla::dom::Request>*, mozilla::dom::AbortSignalImpl*, mozilla::dom::FetchConsumeType, mozilla::ErrorResult&)::{lambda()#1}::operator()() const
Unexecuted instantiation: mozilla::dom::FetchBodyConsumer<mozilla::dom::Response>::Create(nsIGlobalObject*, nsIEventTarget*, mozilla::dom::FetchBody<mozilla::dom::Response>*, mozilla::dom::AbortSignalImpl*, mozilla::dom::FetchConsumeType, mozilla::ErrorResult&)::{lambda()#1}::operator()() const
362
0
    if (NS_WARN_IF(!strongWorkerRef)) {
363
0
      aRv.Throw(NS_ERROR_FAILURE);
364
0
      return nullptr;
365
0
    }
366
0
367
0
    workerRef = new ThreadSafeWorkerRef(strongWorkerRef);
368
0
  } else {
369
0
    nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
370
0
    if (NS_WARN_IF(!os)) {
371
0
      aRv.Throw(NS_ERROR_FAILURE);
372
0
      return nullptr;
373
0
    }
374
0
375
0
    aRv = os->AddObserver(consumer, DOM_WINDOW_DESTROYED_TOPIC, true);
376
0
    if (NS_WARN_IF(aRv.Failed())) {
377
0
      return nullptr;
378
0
    }
379
0
380
0
    aRv = os->AddObserver(consumer, DOM_WINDOW_FROZEN_TOPIC, true);
381
0
    if (NS_WARN_IF(aRv.Failed())) {
382
0
      return nullptr;
383
0
    }
384
0
  }
385
0
386
0
  nsCOMPtr<nsIRunnable> r =
387
0
    new BeginConsumeBodyRunnable<Derived>(consumer, workerRef);
388
0
  aRv = aMainThreadEventTarget->Dispatch(r.forget(), NS_DISPATCH_NORMAL);
389
0
  if (NS_WARN_IF(aRv.Failed())) {
390
0
    return nullptr;
391
0
  }
392
0
393
0
  if (aSignalImpl) {
394
0
    consumer->Follow(aSignalImpl);
395
0
  }
396
0
397
0
  return promise.forget();
398
0
}
Unexecuted instantiation: mozilla::dom::FetchBodyConsumer<mozilla::dom::Request>::Create(nsIGlobalObject*, nsIEventTarget*, mozilla::dom::FetchBody<mozilla::dom::Request>*, mozilla::dom::AbortSignalImpl*, mozilla::dom::FetchConsumeType, mozilla::ErrorResult&)
Unexecuted instantiation: mozilla::dom::FetchBodyConsumer<mozilla::dom::Response>::Create(nsIGlobalObject*, nsIEventTarget*, mozilla::dom::FetchBody<mozilla::dom::Response>*, mozilla::dom::AbortSignalImpl*, mozilla::dom::FetchConsumeType, mozilla::ErrorResult&)
399
400
template <class Derived>
401
void
402
FetchBodyConsumer<Derived>::ReleaseObject()
403
0
{
404
0
  AssertIsOnTargetThread();
405
0
406
0
  if (NS_IsMainThread()) {
407
0
    nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
408
0
    if (os) {
409
0
      os->RemoveObserver(this, DOM_WINDOW_DESTROYED_TOPIC);
410
0
      os->RemoveObserver(this, DOM_WINDOW_FROZEN_TOPIC);
411
0
    }
412
0
  }
413
0
414
0
  mGlobal = nullptr;
415
0
416
#ifdef DEBUG
417
  mBody = nullptr;
418
#endif
419
420
0
  Unfollow();
421
0
}
Unexecuted instantiation: mozilla::dom::FetchBodyConsumer<mozilla::dom::Request>::ReleaseObject()
Unexecuted instantiation: mozilla::dom::FetchBodyConsumer<mozilla::dom::Response>::ReleaseObject()
422
423
template <class Derived>
424
FetchBodyConsumer<Derived>::FetchBodyConsumer(nsIEventTarget* aMainThreadEventTarget,
425
                                              nsIGlobalObject* aGlobalObject,
426
                                              FetchBody<Derived>* aBody,
427
                                              nsIInputStream* aBodyStream,
428
                                              Promise* aPromise,
429
                                              FetchConsumeType aType)
430
  : mTargetThread(NS_GetCurrentThread())
431
  , mMainThreadEventTarget(aMainThreadEventTarget)
432
#ifdef DEBUG
433
  , mBody(aBody)
434
#endif
435
  , mBodyStream(aBodyStream)
436
  , mBlobStorageType(MutableBlobStorage::eOnlyInMemory)
437
  , mBodyLocalPath(aBody ? aBody->BodyLocalPath() : VoidString())
438
  , mGlobal(aGlobalObject)
439
  , mConsumeType(aType)
440
  , mConsumePromise(aPromise)
441
  , mBodyConsumed(false)
442
  , mShuttingDown(false)
443
0
{
444
0
  MOZ_ASSERT(aMainThreadEventTarget);
445
0
  MOZ_ASSERT(aBody);
446
0
  MOZ_ASSERT(aBodyStream);
447
0
  MOZ_ASSERT(aPromise);
448
0
449
0
  const mozilla::UniquePtr<mozilla::ipc::PrincipalInfo>& principalInfo =
450
0
    aBody->DerivedClass()->GetPrincipalInfo();
451
0
  // We support temporary file for blobs only if the principal is known and
452
0
  // it's system or content not in private Browsing.
453
0
  if (principalInfo &&
454
0
      (principalInfo->type() == mozilla::ipc::PrincipalInfo::TSystemPrincipalInfo ||
455
0
       (principalInfo->type() == mozilla::ipc::PrincipalInfo::TContentPrincipalInfo &&
456
0
        principalInfo->get_ContentPrincipalInfo().attrs().mPrivateBrowsingId == 0))) {
457
0
    mBlobStorageType = MutableBlobStorage::eCouldBeInTemporaryFile;
458
0
  }
459
0
460
0
  mBodyMimeType = aBody->MimeType();
461
0
}
Unexecuted instantiation: mozilla::dom::FetchBodyConsumer<mozilla::dom::Request>::FetchBodyConsumer(nsIEventTarget*, nsIGlobalObject*, mozilla::dom::FetchBody<mozilla::dom::Request>*, nsIInputStream*, mozilla::dom::Promise*, mozilla::dom::FetchConsumeType)
Unexecuted instantiation: mozilla::dom::FetchBodyConsumer<mozilla::dom::Response>::FetchBodyConsumer(nsIEventTarget*, nsIGlobalObject*, mozilla::dom::FetchBody<mozilla::dom::Response>*, nsIInputStream*, mozilla::dom::Promise*, mozilla::dom::FetchConsumeType)
462
463
template <class Derived>
464
FetchBodyConsumer<Derived>::~FetchBodyConsumer()
465
0
{
466
0
}
Unexecuted instantiation: mozilla::dom::FetchBodyConsumer<mozilla::dom::Request>::~FetchBodyConsumer()
Unexecuted instantiation: mozilla::dom::FetchBodyConsumer<mozilla::dom::Response>::~FetchBodyConsumer()
467
468
template <class Derived>
469
void
470
FetchBodyConsumer<Derived>::AssertIsOnTargetThread() const
471
0
{
472
0
  MOZ_ASSERT(NS_GetCurrentThread() == mTargetThread);
473
0
}
Unexecuted instantiation: mozilla::dom::FetchBodyConsumer<mozilla::dom::Request>::AssertIsOnTargetThread() const
Unexecuted instantiation: mozilla::dom::FetchBodyConsumer<mozilla::dom::Response>::AssertIsOnTargetThread() const
474
475
namespace {
476
477
template <class Derived>
478
class FileCreationHandler final : public PromiseNativeHandler
479
{
480
public:
481
  NS_DECL_THREADSAFE_ISUPPORTS
482
483
  static void
484
  Create(Promise* aPromise, FetchBodyConsumer<Derived>* aConsumer)
485
0
  {
486
0
    AssertIsOnMainThread();
487
0
    MOZ_ASSERT(aPromise);
488
0
489
0
    RefPtr<FileCreationHandler> handler = new FileCreationHandler<Derived>(aConsumer);
490
0
    aPromise->AppendNativeHandler(handler);
491
0
  }
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::FileCreationHandler<mozilla::dom::Request>::Create(mozilla::dom::Promise*, mozilla::dom::FetchBodyConsumer<mozilla::dom::Request>*)
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::FileCreationHandler<mozilla::dom::Response>::Create(mozilla::dom::Promise*, mozilla::dom::FetchBodyConsumer<mozilla::dom::Response>*)
492
493
  void
494
  ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
495
0
  {
496
0
    AssertIsOnMainThread();
497
0
498
0
    if (NS_WARN_IF(!aValue.isObject())) {
499
0
      mConsumer->OnBlobResult(nullptr);
500
0
      return;
501
0
    }
502
0
503
0
    RefPtr<Blob> blob;
504
0
    if (NS_WARN_IF(NS_FAILED(UNWRAP_OBJECT(Blob, &aValue.toObject(), blob)))) {
505
0
      mConsumer->OnBlobResult(nullptr);
506
0
      return;
507
0
    }
508
0
509
0
    mConsumer->OnBlobResult(blob);
510
0
  }
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::FileCreationHandler<mozilla::dom::Request>::ResolvedCallback(JSContext*, JS::Handle<JS::Value>)
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::FileCreationHandler<mozilla::dom::Response>::ResolvedCallback(JSContext*, JS::Handle<JS::Value>)
511
512
  void
513
  RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
514
0
  {
515
0
    AssertIsOnMainThread();
516
0
517
0
    mConsumer->OnBlobResult(nullptr);
518
0
  }
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::FileCreationHandler<mozilla::dom::Request>::RejectedCallback(JSContext*, JS::Handle<JS::Value>)
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::FileCreationHandler<mozilla::dom::Response>::RejectedCallback(JSContext*, JS::Handle<JS::Value>)
519
520
private:
521
  explicit FileCreationHandler<Derived>(FetchBodyConsumer<Derived>* aConsumer)
522
    : mConsumer(aConsumer)
523
0
  {
524
0
    AssertIsOnMainThread();
525
0
    MOZ_ASSERT(aConsumer);
526
0
  }
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::FileCreationHandler<mozilla::dom::Request>::FileCreationHandler(mozilla::dom::FetchBodyConsumer<mozilla::dom::Request>*)
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::FileCreationHandler<mozilla::dom::Response>::FileCreationHandler(mozilla::dom::FetchBodyConsumer<mozilla::dom::Response>*)
527
528
0
  ~FileCreationHandler() = default;
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::FileCreationHandler<mozilla::dom::Request>::~FileCreationHandler()
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::FileCreationHandler<mozilla::dom::Response>::~FileCreationHandler()
529
530
  RefPtr<FetchBodyConsumer<Derived>> mConsumer;
531
};
532
533
template <class Derived>
534
NS_IMPL_ADDREF(FileCreationHandler<Derived>)
535
template <class Derived>
536
NS_IMPL_RELEASE(FileCreationHandler<Derived>)
537
template <class Derived>
538
0
NS_INTERFACE_MAP_BEGIN(FileCreationHandler<Derived>)
539
0
  NS_INTERFACE_MAP_ENTRY(nsISupports)
540
0
NS_INTERFACE_MAP_END
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::FileCreationHandler<mozilla::dom::Request>::QueryInterface(nsID const&, void**)
Unexecuted instantiation: Unified_cpp_dom_fetch0.cpp:mozilla::dom::(anonymous namespace)::FileCreationHandler<mozilla::dom::Response>::QueryInterface(nsID const&, void**)
541
542
} // namespace
543
544
template <class Derived>
545
nsresult
546
FetchBodyConsumer<Derived>::GetBodyLocalFile(nsIFile** aFile) const
547
0
{
548
0
  AssertIsOnMainThread();
549
0
550
0
  if (!mBodyLocalPath.Length()) {
551
0
    return NS_OK;
552
0
  }
553
0
554
0
  nsresult rv;
555
0
  nsCOMPtr<nsIFile> file = do_CreateInstance("@mozilla.org/file/local;1", &rv);
556
0
  if (NS_FAILED(rv)) {
557
0
    return rv;
558
0
  }
559
0
560
0
  rv = file->InitWithPath(mBodyLocalPath);
561
0
  NS_ENSURE_SUCCESS(rv, rv);
562
0
563
0
  bool exists;
564
0
  rv = file->Exists(&exists);
565
0
  NS_ENSURE_SUCCESS(rv, rv);
566
0
  if (!exists) {
567
0
    return NS_ERROR_FILE_NOT_FOUND;
568
0
  }
569
0
570
0
  bool isDir;
571
0
  rv = file->IsDirectory(&isDir);
572
0
  NS_ENSURE_SUCCESS(rv, rv);
573
0
  if (isDir) {
574
0
    return NS_ERROR_FILE_IS_DIRECTORY;
575
0
  }
576
0
577
0
  file.forget(aFile);
578
0
  return NS_OK;
579
0
}
Unexecuted instantiation: mozilla::dom::FetchBodyConsumer<mozilla::dom::Request>::GetBodyLocalFile(nsIFile**) const
Unexecuted instantiation: mozilla::dom::FetchBodyConsumer<mozilla::dom::Response>::GetBodyLocalFile(nsIFile**) const
580
581
/*
582
 * BeginConsumeBodyMainThread() will automatically reject the consume promise
583
 * and clean up on any failures, so there is no need for callers to do so,
584
 * reflected in a lack of error return code.
585
 */
586
template <class Derived>
587
void
588
FetchBodyConsumer<Derived>::BeginConsumeBodyMainThread(ThreadSafeWorkerRef* aWorkerRef)
589
0
{
590
0
  AssertIsOnMainThread();
591
0
592
0
  AutoFailConsumeBody<Derived> autoReject(this, aWorkerRef);
593
0
594
0
  if (mShuttingDown) {
595
0
    // We haven't started yet, but we have been terminated. AutoFailConsumeBody
596
0
    // will dispatch a runnable to release resources.
597
0
    return;
598
0
  }
599
0
600
0
  // If we're trying to consume a blob, and the request was for a local
601
0
  // file, then generate and return a File blob.
602
0
  if (mConsumeType == CONSUME_BLOB) {
603
0
    nsCOMPtr<nsIFile> file;
604
0
    nsresult rv = GetBodyLocalFile(getter_AddRefs(file));
605
0
    if (!NS_WARN_IF(NS_FAILED(rv)) && file) {
606
0
      ChromeFilePropertyBag bag;
607
0
      bag.mType = NS_ConvertUTF8toUTF16(mBodyMimeType);
608
0
609
0
      ErrorResult error;
610
0
      RefPtr<Promise> promise =
611
0
        FileCreatorHelper::CreateFile(mGlobal, file, bag, true, error);
612
0
      if (NS_WARN_IF(error.Failed())) {
613
0
        return;
614
0
      }
615
0
616
0
      FileCreationHandler<Derived>::Create(promise, this);
617
0
      autoReject.DontFail();
618
0
      return;
619
0
    }
620
0
  }
621
0
622
0
  nsCOMPtr<nsIInputStreamPump> pump;
623
0
  nsresult rv = NS_NewInputStreamPump(getter_AddRefs(pump),
624
0
                                      mBodyStream.forget(), 0, 0, false,
625
0
                                      mMainThreadEventTarget);
626
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
627
0
    return;
628
0
  }
629
0
630
0
  RefPtr<ConsumeBodyDoneObserver<Derived>> p =
631
0
   new ConsumeBodyDoneObserver<Derived>(this, aWorkerRef);
632
0
633
0
  nsCOMPtr<nsIStreamListener> listener;
634
0
  if (mConsumeType == CONSUME_BLOB) {
635
0
    listener = new MutableBlobStreamListener(mBlobStorageType, nullptr,
636
0
                                             mBodyMimeType, p,
637
0
                                             mMainThreadEventTarget);
638
0
  } else {
639
0
    nsCOMPtr<nsIStreamLoader> loader;
640
0
    rv = NS_NewStreamLoader(getter_AddRefs(loader), p);
641
0
    if (NS_WARN_IF(NS_FAILED(rv))) {
642
0
      return;
643
0
    }
644
0
645
0
    listener = loader;
646
0
  }
647
0
648
0
  rv = pump->AsyncRead(listener, nullptr);
649
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
650
0
    return;
651
0
  }
652
0
653
0
  // Now that everything succeeded, we can assign the pump to a pointer that
654
0
  // stays alive for the lifetime of the FetchConsumer.
655
0
  mConsumeBodyPump = pump;
656
0
657
0
  // It is ok for retargeting to fail and reads to happen on the main thread.
658
0
  autoReject.DontFail();
659
0
660
0
  // Try to retarget, otherwise fall back to main thread.
661
0
  nsCOMPtr<nsIThreadRetargetableRequest> rr = do_QueryInterface(pump);
662
0
  if (rr) {
663
0
    nsCOMPtr<nsIEventTarget> sts = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
664
0
    rv = rr->RetargetDeliveryTo(sts);
665
0
    if (NS_FAILED(rv)) {
666
0
      NS_WARNING("Retargeting failed");
667
0
    }
668
0
  }
669
0
}
Unexecuted instantiation: mozilla::dom::FetchBodyConsumer<mozilla::dom::Request>::BeginConsumeBodyMainThread(mozilla::dom::ThreadSafeWorkerRef*)
Unexecuted instantiation: mozilla::dom::FetchBodyConsumer<mozilla::dom::Response>::BeginConsumeBodyMainThread(mozilla::dom::ThreadSafeWorkerRef*)
670
671
/*
672
 * OnBlobResult() is called when a blob body is ready to be consumed (when its
673
 * network transfer completes in BeginConsumeBodyRunnable or its local File has
674
 * been wrapped by FileCreationHandler). The blob is sent to the target thread
675
 * and ContinueConsumeBody is called.
676
 */
677
template <class Derived>
678
void
679
FetchBodyConsumer<Derived>::OnBlobResult(Blob* aBlob, ThreadSafeWorkerRef* aWorkerRef)
680
0
{
681
0
  MOZ_ASSERT(aBlob);
682
0
683
0
  // Main-thread.
684
0
  if (!aWorkerRef) {
685
0
    ContinueConsumeBlobBody(aBlob->Impl());
686
0
    return;
687
0
  }
688
0
689
0
  // Web Worker.
690
0
  {
691
0
    RefPtr<ContinueConsumeBlobBodyRunnable<Derived>> r =
692
0
      new ContinueConsumeBlobBodyRunnable<Derived>(this, aWorkerRef->Private(),
693
0
                                                   aBlob->Impl());
694
0
695
0
    if (r->Dispatch()) {
696
0
      return;
697
0
    }
698
0
  }
699
0
700
0
  // The worker is shutting down. Let's use a control runnable to complete the
701
0
  // shutting down procedure.
702
0
703
0
  RefPtr<AbortConsumeBlobBodyControlRunnable<Derived>> r =
704
0
    new AbortConsumeBlobBodyControlRunnable<Derived>(this,
705
0
                                                     aWorkerRef->Private());
706
0
707
0
  Unused << NS_WARN_IF(!r->Dispatch());
708
0
}
Unexecuted instantiation: mozilla::dom::FetchBodyConsumer<mozilla::dom::Request>::OnBlobResult(mozilla::dom::Blob*, mozilla::dom::ThreadSafeWorkerRef*)
Unexecuted instantiation: mozilla::dom::FetchBodyConsumer<mozilla::dom::Response>::OnBlobResult(mozilla::dom::Blob*, mozilla::dom::ThreadSafeWorkerRef*)
709
710
/*
711
 * ContinueConsumeBody() is to be called on the target thread whenever the
712
 * final result of the fetch is known. The fetch promise is resolved or
713
 * rejected based on whether the fetch succeeded, and the body can be
714
 * converted into the expected type of JS object.
715
 */
716
template <class Derived>
717
void
718
FetchBodyConsumer<Derived>::ContinueConsumeBody(nsresult aStatus,
719
                                                uint32_t aResultLength,
720
                                                uint8_t* aResult,
721
                                                bool aShuttingDown)
722
0
{
723
0
  AssertIsOnTargetThread();
724
0
725
0
  // This makes sure that we free the data correctly.
726
0
  auto autoFree = mozilla::MakeScopeExit([&] {
727
0
    free(aResult);
728
0
  });
Unexecuted instantiation: mozilla::dom::FetchBodyConsumer<mozilla::dom::Request>::ContinueConsumeBody(nsresult, unsigned int, unsigned char*, bool)::{lambda()#1}::operator()() const
Unexecuted instantiation: mozilla::dom::FetchBodyConsumer<mozilla::dom::Response>::ContinueConsumeBody(nsresult, unsigned int, unsigned char*, bool)::{lambda()#1}::operator()() const
729
0
730
0
  if (mBodyConsumed) {
731
0
    return;
732
0
  }
733
0
  mBodyConsumed = true;
734
0
735
0
  // Just a precaution to ensure ContinueConsumeBody is not called out of
736
0
  // sync with a body read.
737
0
  MOZ_ASSERT(mBody->BodyUsed());
738
0
739
0
  MOZ_ASSERT(mConsumePromise);
740
0
  RefPtr<Promise> localPromise = mConsumePromise.forget();
741
0
742
0
  RefPtr<FetchBodyConsumer<Derived>> self = this;
743
0
  auto autoReleaseObject = mozilla::MakeScopeExit([self] {
744
0
    self->ReleaseObject();
745
0
  });
Unexecuted instantiation: mozilla::dom::FetchBodyConsumer<mozilla::dom::Request>::ContinueConsumeBody(nsresult, unsigned int, unsigned char*, bool)::{lambda()#2}::operator()() const
Unexecuted instantiation: mozilla::dom::FetchBodyConsumer<mozilla::dom::Response>::ContinueConsumeBody(nsresult, unsigned int, unsigned char*, bool)::{lambda()#2}::operator()() const
746
0
747
0
  if (aShuttingDown) {
748
0
    // If shutting down, we don't want to resolve any promise.
749
0
    return;
750
0
  }
751
0
752
0
  if (NS_WARN_IF(NS_FAILED(aStatus))) {
753
0
    localPromise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
754
0
  }
755
0
756
0
  // Don't warn here since we warned above.
757
0
  if (NS_FAILED(aStatus)) {
758
0
    return;
759
0
  }
760
0
761
0
  // Finish successfully consuming body according to type.
762
0
  MOZ_ASSERT(aResult);
763
0
764
0
  AutoJSAPI jsapi;
765
0
  if (!jsapi.Init(mGlobal)) {
766
0
    localPromise->MaybeReject(NS_ERROR_UNEXPECTED);
767
0
    return;
768
0
  }
769
0
770
0
  JSContext* cx = jsapi.cx();
771
0
  ErrorResult error;
772
0
773
0
  switch (mConsumeType) {
774
0
    case CONSUME_ARRAYBUFFER: {
775
0
      JS::Rooted<JSObject*> arrayBuffer(cx);
776
0
      BodyUtil::ConsumeArrayBuffer(cx, &arrayBuffer, aResultLength, aResult,
777
0
                                   error);
778
0
779
0
      if (!error.Failed()) {
780
0
        JS::Rooted<JS::Value> val(cx);
781
0
        val.setObjectOrNull(arrayBuffer);
782
0
783
0
        localPromise->MaybeResolve(cx, val);
784
0
        // ArrayBuffer takes over ownership.
785
0
        aResult = nullptr;
786
0
      }
787
0
      break;
788
0
    }
789
0
    case CONSUME_BLOB: {
790
0
      MOZ_CRASH("This should not happen.");
791
0
      break;
792
0
    }
793
0
    case CONSUME_FORMDATA: {
794
0
      nsCString data;
795
0
      data.Adopt(reinterpret_cast<char*>(aResult), aResultLength);
796
0
      aResult = nullptr;
797
0
798
0
      RefPtr<dom::FormData> fd =
799
0
        BodyUtil::ConsumeFormData(mGlobal, mBodyMimeType, data, error);
800
0
      if (!error.Failed()) {
801
0
        localPromise->MaybeResolve(fd);
802
0
      }
803
0
      break;
804
0
    }
805
0
    case CONSUME_TEXT:
806
0
      // fall through handles early exit.
807
0
    case CONSUME_JSON: {
808
0
      nsString decoded;
809
0
      if (NS_SUCCEEDED(BodyUtil::ConsumeText(aResultLength, aResult, decoded))) {
810
0
        if (mConsumeType == CONSUME_TEXT) {
811
0
          localPromise->MaybeResolve(decoded);
812
0
        } else {
813
0
          JS::Rooted<JS::Value> json(cx);
814
0
          BodyUtil::ConsumeJson(cx, &json, decoded, error);
815
0
          if (!error.Failed()) {
816
0
            localPromise->MaybeResolve(cx, json);
817
0
          }
818
0
        }
819
0
      };
820
0
      break;
821
0
    }
822
0
    default:
823
0
      MOZ_ASSERT_UNREACHABLE("Unexpected consume body type");
824
0
  }
825
0
826
0
  error.WouldReportJSException();
827
0
  if (error.Failed()) {
828
0
    localPromise->MaybeReject(error);
829
0
  }
830
0
}
Unexecuted instantiation: mozilla::dom::FetchBodyConsumer<mozilla::dom::Request>::ContinueConsumeBody(nsresult, unsigned int, unsigned char*, bool)
Unexecuted instantiation: mozilla::dom::FetchBodyConsumer<mozilla::dom::Response>::ContinueConsumeBody(nsresult, unsigned int, unsigned char*, bool)
831
832
template <class Derived>
833
void
834
FetchBodyConsumer<Derived>::ContinueConsumeBlobBody(BlobImpl* aBlobImpl,
835
                                                    bool aShuttingDown)
836
0
{
837
0
  AssertIsOnTargetThread();
838
0
  MOZ_ASSERT(mConsumeType == CONSUME_BLOB);
839
0
840
0
  if (mBodyConsumed) {
841
0
    return;
842
0
  }
843
0
  mBodyConsumed = true;
844
0
845
0
  // Just a precaution to ensure ContinueConsumeBody is not called out of
846
0
  // sync with a body read.
847
0
  MOZ_ASSERT(mBody->BodyUsed());
848
0
849
0
  MOZ_ASSERT(mConsumePromise);
850
0
  RefPtr<Promise> localPromise = mConsumePromise.forget();
851
0
852
0
  if (!aShuttingDown) {
853
0
    RefPtr<dom::Blob> blob = dom::Blob::Create(mGlobal, aBlobImpl);
854
0
    MOZ_ASSERT(blob);
855
0
856
0
    localPromise->MaybeResolve(blob);
857
0
  }
858
0
859
0
  ReleaseObject();
860
0
}
Unexecuted instantiation: mozilla::dom::FetchBodyConsumer<mozilla::dom::Request>::ContinueConsumeBlobBody(mozilla::dom::BlobImpl*, bool)
Unexecuted instantiation: mozilla::dom::FetchBodyConsumer<mozilla::dom::Response>::ContinueConsumeBlobBody(mozilla::dom::BlobImpl*, bool)
861
862
template <class Derived>
863
void
864
FetchBodyConsumer<Derived>::ShutDownMainThreadConsuming()
865
0
{
866
0
  if (!NS_IsMainThread()) {
867
0
    RefPtr<FetchBodyConsumer<Derived>> self = this;
868
0
869
0
    nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
870
0
      "FetchBodyConsumer::ShutDownMainThreadConsuming",
871
0
      [self] () { self->ShutDownMainThreadConsuming(); });
Unexecuted instantiation: mozilla::dom::FetchBodyConsumer<mozilla::dom::Request>::ShutDownMainThreadConsuming()::{lambda()#1}::operator()() const
Unexecuted instantiation: mozilla::dom::FetchBodyConsumer<mozilla::dom::Response>::ShutDownMainThreadConsuming()::{lambda()#1}::operator()() const
872
0
873
0
    mMainThreadEventTarget->Dispatch(r.forget(), NS_DISPATCH_NORMAL);
874
0
    return;
875
0
  }
876
0
877
0
  // We need this because maybe, mConsumeBodyPump has not been created yet. We
878
0
  // must be sure that we don't try to do it.
879
0
  mShuttingDown = true;
880
0
881
0
  if (mConsumeBodyPump) {
882
0
    mConsumeBodyPump->Cancel(NS_BINDING_ABORTED);
883
0
    mConsumeBodyPump = nullptr;
884
0
  }
885
0
}
Unexecuted instantiation: mozilla::dom::FetchBodyConsumer<mozilla::dom::Request>::ShutDownMainThreadConsuming()
Unexecuted instantiation: mozilla::dom::FetchBodyConsumer<mozilla::dom::Response>::ShutDownMainThreadConsuming()
886
887
template <class Derived>
888
NS_IMETHODIMP
889
FetchBodyConsumer<Derived>::Observe(nsISupports* aSubject,
890
                                    const char* aTopic,
891
                                    const char16_t* aData)
892
0
{
893
0
  AssertIsOnMainThread();
894
0
895
0
  MOZ_ASSERT((strcmp(aTopic, DOM_WINDOW_FROZEN_TOPIC) == 0) ||
896
0
             (strcmp(aTopic, DOM_WINDOW_DESTROYED_TOPIC) == 0));
897
0
898
0
  nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(mGlobal);
899
0
  if (SameCOMIdentity(aSubject, window)) {
900
0
    ContinueConsumeBody(NS_BINDING_ABORTED, 0, nullptr);
901
0
  }
902
0
903
0
  return NS_OK;
904
0
}
Unexecuted instantiation: mozilla::dom::FetchBodyConsumer<mozilla::dom::Request>::Observe(nsISupports*, char const*, char16_t const*)
Unexecuted instantiation: mozilla::dom::FetchBodyConsumer<mozilla::dom::Response>::Observe(nsISupports*, char const*, char16_t const*)
905
906
template <class Derived>
907
void
908
FetchBodyConsumer<Derived>::Abort()
909
0
{
910
0
  AssertIsOnTargetThread();
911
0
  ShutDownMainThreadConsuming();
912
0
  ContinueConsumeBody(NS_ERROR_DOM_ABORT_ERR, 0, nullptr);
913
0
}
Unexecuted instantiation: mozilla::dom::FetchBodyConsumer<mozilla::dom::Request>::Abort()
Unexecuted instantiation: mozilla::dom::FetchBodyConsumer<mozilla::dom::Response>::Abort()
914
915
template <class Derived>
916
NS_IMPL_ADDREF(FetchBodyConsumer<Derived>)
917
918
template <class Derived>
919
NS_IMPL_RELEASE(FetchBodyConsumer<Derived>)
920
921
template <class Derived>
922
NS_IMPL_QUERY_INTERFACE(FetchBodyConsumer<Derived>,
923
                        nsIObserver,
924
                        nsISupportsWeakReference)
925
926
} // namespace dom
927
} // namespace mozilla