Bug 1700051: part 26) Correct typo in comment of `mozInlineSpellWordUtil::BuildSoftTe...
[gecko.git] / dom / fetch / Fetch.h
blob1689848be704b1ccad120c46b1116a4cbf13ed5e
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_Fetch_h
8 #define mozilla_dom_Fetch_h
10 #include "nsCOMPtr.h"
11 #include "nsError.h"
12 #include "nsProxyRelease.h"
13 #include "nsString.h"
15 #include "mozilla/DebugOnly.h"
16 #include "mozilla/dom/AbortSignal.h"
17 #include "mozilla/dom/BodyConsumer.h"
18 #include "mozilla/dom/BodyStream.h"
19 #include "mozilla/dom/Promise.h"
20 #include "mozilla/dom/FetchStreamReader.h"
21 #include "mozilla/dom/RequestBinding.h"
23 class nsIGlobalObject;
24 class nsIEventTarget;
26 namespace mozilla {
27 class ErrorResult;
29 namespace dom {
31 class BlobOrArrayBufferViewOrArrayBufferOrFormDataOrURLSearchParamsOrUSVString;
32 class
33 BlobOrArrayBufferViewOrArrayBufferOrFormDataOrURLSearchParamsOrReadableStreamOrUSVString;
34 class BlobImpl;
35 class InternalRequest;
36 class
37 OwningBlobOrArrayBufferViewOrArrayBufferOrFormDataOrURLSearchParamsOrUSVString;
38 struct ReadableStream;
39 class RequestOrUSVString;
40 class WorkerPrivate;
42 enum class CallerType : uint32_t;
44 already_AddRefed<Promise> FetchRequest(nsIGlobalObject* aGlobal,
45 const RequestOrUSVString& aInput,
46 const RequestInit& aInit,
47 CallerType aCallerType,
48 ErrorResult& aRv);
50 nsresult UpdateRequestReferrer(nsIGlobalObject* aGlobal,
51 InternalRequest* aRequest);
53 namespace fetch {
54 typedef BlobOrArrayBufferViewOrArrayBufferOrFormDataOrURLSearchParamsOrUSVString
55 BodyInit;
56 typedef BlobOrArrayBufferViewOrArrayBufferOrFormDataOrURLSearchParamsOrReadableStreamOrUSVString
57 ResponseBodyInit;
58 typedef OwningBlobOrArrayBufferViewOrArrayBufferOrFormDataOrURLSearchParamsOrUSVString
59 OwningBodyInit;
60 }; // namespace fetch
63 * Creates an nsIInputStream based on the fetch specifications 'extract a byte
64 * stream algorithm' - http://fetch.spec.whatwg.org/#concept-bodyinit-extract.
65 * Stores content type in out param aContentType.
67 nsresult ExtractByteStreamFromBody(const fetch::OwningBodyInit& aBodyInit,
68 nsIInputStream** aStream,
69 nsCString& aContentType,
70 uint64_t& aContentLength);
73 * Non-owning version.
75 nsresult ExtractByteStreamFromBody(const fetch::BodyInit& aBodyInit,
76 nsIInputStream** aStream,
77 nsCString& aContentType,
78 uint64_t& aContentLength);
81 * Non-owning version. This method should go away when BodyInit will contain
82 * ReadableStream.
84 nsresult ExtractByteStreamFromBody(const fetch::ResponseBodyInit& aBodyInit,
85 nsIInputStream** aStream,
86 nsCString& aContentType,
87 uint64_t& aContentLength);
90 * FetchBody's body consumption uses nsIInputStreamPump to read from the
91 * underlying stream to a block of memory, which is then adopted by
92 * ContinueConsumeBody() and converted to the right type based on the JS
93 * function called.
95 * Use of the nsIInputStreamPump complicates things on the worker thread.
96 * The solution used here is similar to WebSockets.
97 * The difference is that we are only interested in completion and not data
98 * events, and nsIInputStreamPump can only deliver completion on the main
99 * thread.
101 * Before starting the pump on the main thread, we addref the FetchBody to keep
102 * it alive. Then we add a feature, to track the status of the worker.
104 * ContinueConsumeBody() is the function that cleans things up in both success
105 * and error conditions and so all callers call it with the appropriate status.
107 * Once the read is initiated on the main thread there are two possibilities.
109 * 1) Pump finishes before worker has finished Running.
110 * In this case we adopt the data and dispatch a runnable to the worker,
111 * which derefs FetchBody and removes the feature and resolves the Promise.
113 * 2) Pump still working while worker has stopped Running.
114 * The feature is Notify()ed and ContinueConsumeBody() is called with
115 * NS_BINDING_ABORTED. We first Cancel() the pump using a sync runnable to
116 * ensure that mFetchBody remains alive (since mConsumeBodyPump is strongly
117 * held by it) until pump->Cancel() is called. OnStreamComplete() will not
118 * do anything if the error code is NS_BINDING_ABORTED, so we don't have to
119 * worry about keeping anything alive.
121 * The pump is always released on the main thread.
123 template <class Derived>
124 class FetchBody : public BodyStreamHolder, public AbortFollower {
125 public:
126 using BodyStreamHolder::QueryInterface;
128 NS_INLINE_DECL_REFCOUNTING_INHERITED(FetchBody, BodyStreamHolder)
130 bool GetBodyUsed(ErrorResult& aRv) const;
132 // For use in assertions. On success, returns true if the body is used, false
133 // if not. On error, this sweeps the error under the rug and returns true.
134 bool CheckBodyUsed() const;
136 already_AddRefed<Promise> ArrayBuffer(JSContext* aCx, ErrorResult& aRv) {
137 return ConsumeBody(aCx, BodyConsumer::CONSUME_ARRAYBUFFER, aRv);
140 already_AddRefed<Promise> Blob(JSContext* aCx, ErrorResult& aRv) {
141 return ConsumeBody(aCx, BodyConsumer::CONSUME_BLOB, aRv);
144 already_AddRefed<Promise> FormData(JSContext* aCx, ErrorResult& aRv) {
145 return ConsumeBody(aCx, BodyConsumer::CONSUME_FORMDATA, aRv);
148 already_AddRefed<Promise> Json(JSContext* aCx, ErrorResult& aRv) {
149 return ConsumeBody(aCx, BodyConsumer::CONSUME_JSON, aRv);
152 already_AddRefed<Promise> Text(JSContext* aCx, ErrorResult& aRv) {
153 return ConsumeBody(aCx, BodyConsumer::CONSUME_TEXT, aRv);
156 void GetBody(JSContext* aCx, JS::MutableHandle<JSObject*> aBodyOut,
157 ErrorResult& aRv);
159 void GetMimeType(nsACString& aMimeType);
161 const nsACString& BodyBlobURISpec() const;
163 const nsAString& BodyLocalPath() const;
165 // If the body contains a ReadableStream body object, this method produces a
166 // tee() of it.
167 void MaybeTeeReadableStreamBody(JSContext* aCx,
168 JS::MutableHandle<JSObject*> aBodyOut,
169 FetchStreamReader** aStreamReader,
170 nsIInputStream** aInputStream,
171 ErrorResult& aRv);
173 // Utility public methods accessed by various runnables.
175 // This method _must_ be called in order to set the body as used. If the body
176 // is a ReadableStream, this method will start reading the stream.
177 // More in details, this method does:
178 // 1) It uses an internal flag to track if the body is used. This is tracked
179 // separately from the ReadableStream disturbed state due to purely native
180 // streams.
181 // 2) If there is a ReadableStream reflector for the native stream it is
182 // Locked.
183 // 3) If there is a JS ReadableStream then we begin pumping it into the native
184 // body stream. This effectively locks and disturbs the stream.
186 // Note that JSContext is used only if there is a ReadableStream (this can
187 // happen because the body is a ReadableStream or because attribute body has
188 // already been used by content). If something goes wrong using
189 // ReadableStream, errors will be reported via ErrorResult and not as JS
190 // exceptions in JSContext. This is done in order to have a centralized error
191 // reporting way.
193 // Exceptions generated when reading from the ReadableStream are directly sent
194 // to the Console.
195 void SetBodyUsed(JSContext* aCx, ErrorResult& aRv);
197 // BodyStreamHolder
198 void NullifyStream() override {
199 mReadableStreamBody = nullptr;
200 mReadableStreamReader = nullptr;
201 mFetchStreamReader = nullptr;
204 void SetReadableStreamBody(JSObject* aBody) override {
205 mReadableStreamBody = aBody;
208 JSObject* GetReadableStreamBody() override { return mReadableStreamBody; }
210 void MarkAsRead() override { mBodyUsed = true; }
212 virtual AbortSignalImpl* GetSignalImpl() const = 0;
214 // AbortFollower
215 void RunAbortAlgorithm() override;
217 already_AddRefed<Promise> ConsumeBody(JSContext* aCx,
218 BodyConsumer::ConsumeType aType,
219 ErrorResult& aRv);
221 protected:
222 nsCOMPtr<nsIGlobalObject> mOwner;
224 // Always set whenever the FetchBody is created on the worker thread.
225 WorkerPrivate* mWorkerPrivate;
227 // This is the ReadableStream exposed to content. It's underlying source is a
228 // BodyStream object.
229 JS::Heap<JSObject*> mReadableStreamBody;
231 // This is the Reader used to retrieve data from the body.
232 JS::Heap<JSObject*> mReadableStreamReader;
233 RefPtr<FetchStreamReader> mFetchStreamReader;
235 explicit FetchBody(nsIGlobalObject* aOwner);
237 virtual ~FetchBody();
239 void SetReadableStreamBody(JSContext* aCx, JSObject* aBody);
241 private:
242 Derived* DerivedClass() const {
243 return static_cast<Derived*>(const_cast<FetchBody*>(this));
246 void LockStream(JSContext* aCx, JS::HandleObject aStream, ErrorResult& aRv);
248 bool IsOnTargetThread() { return NS_IsMainThread() == !mWorkerPrivate; }
250 void AssertIsOnTargetThread() { MOZ_ASSERT(IsOnTargetThread()); }
252 // Only ever set once, always on target thread.
253 bool mBodyUsed;
255 // The main-thread event target for runnable dispatching.
256 nsCOMPtr<nsIEventTarget> mMainThreadEventTarget;
259 } // namespace dom
260 } // namespace mozilla
262 #endif // mozilla_dom_Fetch_h