summaryrefslogtreecommitdiffstats
path: root/dom/fetch/FetchConsumer.h
blob: 77af09d9b5b527cc551a87646a526ec1fb093e69 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef mozilla_dom_FetchConsumer_h
#define mozilla_dom_FetchConsumer_h

#include "Fetch.h"
#include "nsIInputStream.h"
#include "nsIObserver.h"
#include "nsWeakReference.h"
#include "mozilla/dom/AbortSignal.h"
#include "mozilla/dom/MutableBlobStorage.h"

class nsIThread;
class nsIInputStreamPump;

namespace mozilla {
namespace dom {

class Promise;

namespace workers {
class WorkerPrivate;
class WorkerHolder;
}

template <class Derived> class FetchBody;

// FetchBody is not thread-safe but we need to move it around threads.
// In order to keep it alive all the time, we use a WorkerHolder, if created on
// workers, plus a this consumer.
template <class Derived>
class FetchBodyConsumer final : public nsIObserver
                              , public nsSupportsWeakReference
                              , public AbortSignal::Follower
{
public:
  NS_DECL_THREADSAFE_ISUPPORTS
  NS_DECL_NSIOBSERVER

  static already_AddRefed<Promise>
  Create(nsIGlobalObject* aGlobal,
         FetchBody<Derived>* aBody,
         AbortSignal* aSignal,
         FetchConsumeType aType,
         ErrorResult& aRv);

  void
  ReleaseObject();

  void
  BeginConsumeBodyMainThread();

  void
  ContinueConsumeBody(nsresult aStatus, uint32_t aLength, uint8_t* aResult);

  void
  ContinueConsumeBlobBody(BlobImpl* aBlobImpl);

  void
  ShutDownMainThreadConsuming();

  workers::WorkerPrivate*
  GetWorkerPrivate() const
  {
    return mWorkerPrivate;
  }

  void
  NullifyConsumeBodyPump()
  {
    mShuttingDown = true;
    mConsumeBodyPump = nullptr;
  }

  // Override AbortSignal::Follower::Aborted
  void Aborted() override;

private:
  FetchBodyConsumer(nsIGlobalObject* aGlobalObject,
                    workers::WorkerPrivate* aWorkerPrivate,
                    FetchBody<Derived>* aBody,
                    nsIInputStream* aBodyStream,
                    Promise* aPromise,
                    FetchConsumeType aType);

  ~FetchBodyConsumer();

  void
  AssertIsOnTargetThread() const;

  bool
  RegisterWorkerHolder();

  nsCOMPtr<nsIThread> mTargetThread;

#ifdef DEBUG
  // This is used only to check if the body has been correctly consumed.
  RefPtr<FetchBody<Derived>> mBody;
#endif

  nsCOMPtr<nsIInputStream> mBodyStream;
  MutableBlobStorage::MutableBlobStorageType mBlobStorageType;
  nsCString mBodyMimeType;

  // Set when consuming the body is attempted on a worker.
  // Unset when consumption is done/aborted.
  // This WorkerHolder keeps alive the consumer via a cycle.
  UniquePtr<workers::WorkerHolder> mWorkerHolder;

  nsCOMPtr<nsIGlobalObject> mGlobal;

  // Always set whenever the FetchBodyConsumer is created on the worker thread.
  workers::WorkerPrivate* mWorkerPrivate;

  // Touched on the main-thread only.
  nsCOMPtr<nsIInputStreamPump> mConsumeBodyPump;

  // Only ever set once, always on target thread.
  FetchConsumeType mConsumeType;
  RefPtr<Promise> mConsumePromise;

  // touched only on the target thread.
  bool mBodyConsumed;

  // touched only on the main-thread.
  bool mShuttingDown;
};

} // namespace dom
} // namespace mozilla

#endif // mozilla_dom_FetchConsumer_h