Bug 1686668 [wpt PR 27185] - Update wpt metadata, a=testonly
[gecko.git] / dom / base / BodyStream.h
blob33b1166006d869d701d80783c850476eec805108
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/. */
7 #ifndef mozilla_dom_BodyStream_h
8 #define mozilla_dom_BodyStream_h
10 #include "jsapi.h"
11 #include "js/Stream.h"
12 #include "nsIAsyncInputStream.h"
13 #include "nsCycleCollectionParticipant.h"
14 #include "nsIObserver.h"
15 #include "nsISupportsImpl.h"
16 #include "nsNetCID.h"
17 #include "nsWeakReference.h"
18 #include "mozilla/Mutex.h"
20 class nsIGlobalObject;
22 class nsIInputStream;
24 namespace mozilla {
25 class ErrorResult;
27 namespace dom {
29 class BodyStream;
30 class WeakWorkerRef;
32 class BodyStreamHolder : public nsISupports {
33 friend class BodyStream;
35 public:
36 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
37 NS_DECL_CYCLE_COLLECTION_CLASS(BodyStreamHolder)
39 BodyStreamHolder();
41 virtual void NullifyStream() = 0;
43 virtual void MarkAsRead() = 0;
45 virtual void SetReadableStreamBody(JSObject* aBody) = 0;
47 virtual JSObject* GetReadableStreamBody() = 0;
49 protected:
50 virtual ~BodyStreamHolder() = default;
52 private:
53 void StoreBodyStream(BodyStream* aBodyStream);
54 void ForgetBodyStream();
56 // Raw pointer because BodyStream keeps BodyStreamHolder alive and it
57 // nullifies this stream before being released.
58 BodyStream* mBodyStream;
60 #ifdef DEBUG
61 bool mStreamCreated = false;
62 #endif
65 class BodyStream final : public nsIInputStreamCallback,
66 public nsIObserver,
67 public nsSupportsWeakReference,
68 private JS::ReadableStreamUnderlyingSource {
69 friend class BodyStreamHolder;
71 public:
72 NS_DECL_THREADSAFE_ISUPPORTS
73 NS_DECL_NSIINPUTSTREAMCALLBACK
74 NS_DECL_NSIOBSERVER
76 // This method creates a JS ReadableStream object and it assigns it to the
77 // aStreamHolder calling SetReadableStreamBody().
78 static void Create(JSContext* aCx, BodyStreamHolder* aStreamHolder,
79 nsIGlobalObject* aGlobal, nsIInputStream* aInputStream,
80 ErrorResult& aRv);
82 void Close();
84 static nsresult RetrieveInputStream(
85 JS::ReadableStreamUnderlyingSource* aUnderlyingReadableStreamSource,
86 nsIInputStream** aInputStream);
88 private:
89 BodyStream(nsIGlobalObject* aGlobal, BodyStreamHolder* aStreamHolder,
90 nsIInputStream* aInputStream);
91 ~BodyStream();
93 #ifdef DEBUG
94 void AssertIsOnOwningThread();
95 #else
96 void AssertIsOnOwningThread() {}
97 #endif
99 void requestData(JSContext* aCx, JS::HandleObject aStream,
100 size_t aDesiredSize) override;
102 void writeIntoReadRequestBuffer(JSContext* aCx, JS::HandleObject aStream,
103 void* aBuffer, size_t aLength,
104 size_t* aBytesWritten) override;
106 JS::Value cancel(JSContext* aCx, JS::HandleObject aStream,
107 JS::HandleValue aReason) override;
109 void onClosed(JSContext* aCx, JS::HandleObject aStream) override;
111 void onErrored(JSContext* aCx, JS::HandleObject aStream,
112 JS::HandleValue aReason) override;
114 void finalize() override;
116 void ErrorPropagation(JSContext* aCx, const MutexAutoLock& aProofOfLock,
117 JS::HandleObject aStream, nsresult aRv);
119 void CloseAndReleaseObjects(JSContext* aCx, const MutexAutoLock& aProofOfLock,
120 JS::HandleObject aSteam);
122 class WorkerShutdown;
124 void ReleaseObjects(const MutexAutoLock& aProofOfLock);
126 void ReleaseObjects();
128 // Common methods
130 enum State {
131 // This is the beginning state before any reading operation.
132 eInitializing,
134 // RequestDataCallback has not been called yet. We haven't started to read
135 // data from the stream yet.
136 eWaiting,
138 // We are reading data in a separate I/O thread.
139 eReading,
141 // We are ready to write something in the JS Buffer.
142 eWriting,
144 // After a writing, we want to check if the stream is closed. After the
145 // check, we go back to eWaiting. If a reading request happens in the
146 // meantime, we move to eReading state.
147 eChecking,
149 // Operation completed.
150 eClosed,
153 // We need a mutex because JS engine can release BodyStream on a non-owning
154 // thread. We must be sure that the releasing of resources doesn't trigger
155 // race conditions.
156 Mutex mMutex;
158 // Protected by mutex.
159 State mState;
161 nsCOMPtr<nsIGlobalObject> mGlobal;
162 RefPtr<BodyStreamHolder> mStreamHolder;
163 nsCOMPtr<nsIEventTarget> mOwningEventTarget;
165 // This is the original inputStream received during the CTOR. It will be
166 // converted into an nsIAsyncInputStream and stored into mInputStream at the
167 // first use.
168 nsCOMPtr<nsIInputStream> mOriginalInputStream;
169 nsCOMPtr<nsIAsyncInputStream> mInputStream;
171 RefPtr<WeakWorkerRef> mWorkerRef;
174 } // namespace dom
175 } // namespace mozilla
177 #endif // mozilla_dom_BodyStream_h