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/. */
11 #include "nsNetUtil.h"
12 #include "nsPIDOMWindow.h"
14 #include "mozilla/ErrorResult.h"
15 #include "mozilla/dom/Headers.h"
16 #include "mozilla/dom/Fetch.h"
17 #include "mozilla/dom/FetchUtil.h"
18 #include "mozilla/dom/Promise.h"
19 #include "mozilla/dom/URL.h"
20 #include "mozilla/dom/WorkerPrivate.h"
21 #include "mozilla/dom/WorkerRunnable.h"
22 #include "mozilla/dom/WindowContext.h"
23 #include "mozilla/ipc/PBackgroundSharedTypes.h"
24 #include "mozilla/Unused.h"
26 #include "mozilla/dom/ReadableStreamDefaultReader.h"
28 namespace mozilla::dom
{
30 NS_IMPL_ADDREF_INHERITED(Request
, FetchBody
<Request
>)
31 NS_IMPL_RELEASE_INHERITED(Request
, FetchBody
<Request
>)
33 // Can't use _INHERITED macro here because FetchBody<Request> is abstract.
34 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(Request
)
36 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(Request
, FetchBody
<Request
>)
37 NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner
)
38 NS_IMPL_CYCLE_COLLECTION_UNLINK(mHeaders
)
39 NS_IMPL_CYCLE_COLLECTION_UNLINK(mSignal
)
40 NS_IMPL_CYCLE_COLLECTION_UNLINK(mFetchStreamReader
)
41 NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
42 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
44 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(Request
, FetchBody
<Request
>)
45 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner
)
46 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mHeaders
)
47 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSignal
)
48 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFetchStreamReader
)
49 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
51 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Request
)
52 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
53 NS_INTERFACE_MAP_END_INHERITING(FetchBody
<Request
>)
55 Request::Request(nsIGlobalObject
* aOwner
, SafeRefPtr
<InternalRequest
> aRequest
,
57 : FetchBody
<Request
>(aOwner
), mRequest(std::move(aRequest
)) {
58 MOZ_ASSERT(mRequest
->Headers()->Guard() == HeadersGuardEnum::Immutable
||
59 mRequest
->Headers()->Guard() == HeadersGuardEnum::Request
||
60 mRequest
->Headers()->Guard() == HeadersGuardEnum::Request_no_cors
);
62 // If we don't have a signal as argument, we will create it when required by
63 // content, otherwise the Request's signal must follow what has been passed.
64 JS::Rooted
<JS::Value
> reason(RootingCx(), aSignal
->RawReason());
65 mSignal
= new AbortSignal(aOwner
, aSignal
->Aborted(), reason
);
66 if (!mSignal
->Aborted()) {
67 mSignal
->Follow(aSignal
);
72 Request::~Request() = default;
74 SafeRefPtr
<InternalRequest
> Request::GetInternalRequest() {
75 return mRequest
.clonePtr();
79 already_AddRefed
<nsIURI
> ParseURLFromDocument(Document
* aDocument
,
80 const nsAString
& aInput
,
82 MOZ_ASSERT(aDocument
);
83 MOZ_ASSERT(NS_IsMainThread());
85 // Don't use NS_ConvertUTF16toUTF8 because that doesn't let us handle OOM.
87 if (!AppendUTF16toUTF8(aInput
, input
, fallible
)) {
88 aRv
.Throw(NS_ERROR_OUT_OF_MEMORY
);
92 nsCOMPtr
<nsIURI
> resolvedURI
;
93 nsresult rv
= NS_NewURI(getter_AddRefs(resolvedURI
), input
, nullptr,
94 aDocument
->GetBaseURI());
95 if (NS_WARN_IF(NS_FAILED(rv
))) {
96 aRv
.ThrowTypeError
<MSG_INVALID_URL
>(input
);
98 return resolvedURI
.forget();
100 void GetRequestURLFromDocument(Document
* aDocument
, const nsAString
& aInput
,
101 nsAString
& aRequestURL
, nsACString
& aURLfragment
,
103 nsCOMPtr
<nsIURI
> resolvedURI
= ParseURLFromDocument(aDocument
, aInput
, aRv
);
107 // This fails with URIs with weird protocols, even when they are valid,
108 // so we ignore the failure
109 nsAutoCString credentials
;
110 Unused
<< resolvedURI
->GetUserPass(credentials
);
111 if (!credentials
.IsEmpty()) {
112 aRv
.ThrowTypeError
<MSG_URL_HAS_CREDENTIALS
>(NS_ConvertUTF16toUTF8(aInput
));
116 nsCOMPtr
<nsIURI
> resolvedURIClone
;
117 aRv
= NS_GetURIWithoutRef(resolvedURI
, getter_AddRefs(resolvedURIClone
));
118 if (NS_WARN_IF(aRv
.Failed())) {
122 aRv
= resolvedURIClone
->GetSpec(spec
);
123 if (NS_WARN_IF(aRv
.Failed())) {
126 CopyUTF8toUTF16(spec
, aRequestURL
);
128 // Get the fragment from nsIURI.
129 aRv
= resolvedURI
->GetRef(aURLfragment
);
130 if (NS_WARN_IF(aRv
.Failed())) {
134 already_AddRefed
<nsIURI
> ParseURLFromChrome(const nsAString
& aInput
,
136 MOZ_ASSERT(NS_IsMainThread());
137 // Don't use NS_ConvertUTF16toUTF8 because that doesn't let us handle OOM.
139 if (!AppendUTF16toUTF8(aInput
, input
, fallible
)) {
140 aRv
.Throw(NS_ERROR_OUT_OF_MEMORY
);
144 nsCOMPtr
<nsIURI
> uri
;
145 nsresult rv
= NS_NewURI(getter_AddRefs(uri
), input
);
147 aRv
.ThrowTypeError
<MSG_INVALID_URL
>(input
);
151 void GetRequestURLFromChrome(const nsAString
& aInput
, nsAString
& aRequestURL
,
152 nsACString
& aURLfragment
, ErrorResult
& aRv
) {
153 nsCOMPtr
<nsIURI
> uri
= ParseURLFromChrome(aInput
, aRv
);
157 // This fails with URIs with weird protocols, even when they are valid,
158 // so we ignore the failure
159 nsAutoCString credentials
;
160 Unused
<< uri
->GetUserPass(credentials
);
161 if (!credentials
.IsEmpty()) {
162 aRv
.ThrowTypeError
<MSG_URL_HAS_CREDENTIALS
>(NS_ConvertUTF16toUTF8(aInput
));
166 nsCOMPtr
<nsIURI
> uriClone
;
167 aRv
= NS_GetURIWithoutRef(uri
, getter_AddRefs(uriClone
));
168 if (NS_WARN_IF(aRv
.Failed())) {
172 aRv
= uriClone
->GetSpec(spec
);
173 if (NS_WARN_IF(aRv
.Failed())) {
176 CopyUTF8toUTF16(spec
, aRequestURL
);
178 // Get the fragment from nsIURI.
179 aRv
= uri
->GetRef(aURLfragment
);
180 if (NS_WARN_IF(aRv
.Failed())) {
184 already_AddRefed
<URL
> ParseURLFromWorker(nsIGlobalObject
* aGlobal
,
185 const nsAString
& aInput
,
187 WorkerPrivate
* worker
= GetCurrentThreadWorkerPrivate();
189 worker
->AssertIsOnWorkerThread();
191 NS_ConvertUTF8toUTF16
baseURL(worker
->GetLocationInfo().mHref
);
192 RefPtr
<URL
> url
= URL::Constructor(aGlobal
, aInput
, baseURL
, aRv
);
193 if (NS_WARN_IF(aRv
.Failed())) {
194 aRv
.ThrowTypeError
<MSG_INVALID_URL
>(NS_ConvertUTF16toUTF8(aInput
));
198 void GetRequestURLFromWorker(nsIGlobalObject
* aGlobal
, const nsAString
& aInput
,
199 nsAString
& aRequestURL
, nsACString
& aURLfragment
,
201 RefPtr
<URL
> url
= ParseURLFromWorker(aGlobal
, aInput
, aRv
);
206 url
->GetUsername(username
);
209 url
->GetPassword(password
);
211 if (!username
.IsEmpty() || !password
.IsEmpty()) {
212 aRv
.ThrowTypeError
<MSG_URL_HAS_CREDENTIALS
>(NS_ConvertUTF16toUTF8(aInput
));
216 // Get the fragment from URL.
217 nsAutoString fragment
;
218 url
->GetHash(fragment
);
220 // Note: URL::GetHash() includes the "#" and we want the fragment with out
222 if (!fragment
.IsEmpty()) {
223 CopyUTF16toUTF8(Substring(fragment
, 1), aURLfragment
);
226 url
->SetHash(u
""_ns
);
227 url
->GetHref(aRequestURL
);
230 class ReferrerSameOriginChecker final
: public WorkerMainThreadRunnable
{
232 ReferrerSameOriginChecker(WorkerPrivate
* aWorkerPrivate
,
233 const nsAString
& aReferrerURL
, nsresult
& aResult
)
234 : WorkerMainThreadRunnable(aWorkerPrivate
,
235 "Fetch :: Referrer same origin check"_ns
),
236 mReferrerURL(aReferrerURL
),
238 mWorkerPrivate
->AssertIsOnWorkerThread();
241 bool MainThreadRun() override
{
242 nsCOMPtr
<nsIURI
> uri
;
243 if (NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri
), mReferrerURL
))) {
244 nsCOMPtr
<nsIPrincipal
> principal
= mWorkerPrivate
->GetPrincipal();
246 mResult
= principal
->CheckMayLoad(uri
,
247 /* allowIfInheritsPrincipal */ false);
254 const nsString mReferrerURL
;
261 SafeRefPtr
<Request
> Request::Constructor(const GlobalObject
& aGlobal
,
262 const RequestOrUSVString
& aInput
,
263 const RequestInit
& aInit
,
265 nsCOMPtr
<nsIGlobalObject
> global
= do_QueryInterface(aGlobal
.GetAsSupports());
266 return Constructor(global
, aGlobal
.Context(), aInput
, aInit
, aRv
);
270 SafeRefPtr
<Request
> Request::Constructor(nsIGlobalObject
* aGlobal
,
272 const RequestOrUSVString
& aInput
,
273 const RequestInit
& aInit
,
275 bool hasCopiedBody
= false;
276 SafeRefPtr
<InternalRequest
> request
;
278 RefPtr
<AbortSignal
> signal
;
279 bool bodyFromInit
= false;
281 if (aInput
.IsRequest()) {
282 RefPtr
<Request
> inputReq
= &aInput
.GetAsRequest();
283 nsCOMPtr
<nsIInputStream
> body
;
285 if (aInit
.mBody
.WasPassed() && !aInit
.mBody
.Value().IsNull()) {
287 hasCopiedBody
= true;
289 inputReq
->GetBody(getter_AddRefs(body
));
290 if (inputReq
->BodyUsed()) {
291 aRv
.ThrowTypeError
<MSG_FETCH_BODY_CONSUMED_ERROR
>();
295 // The body will be copied when GetRequestConstructorCopy() is executed.
297 hasCopiedBody
= true;
301 request
= inputReq
->GetInternalRequest();
302 signal
= inputReq
->GetOrCreateSignal();
304 // aInput is USVString.
305 // We need to get url before we create a InternalRequest.
307 input
.Assign(aInput
.GetAsUSVString());
308 nsAutoString requestURL
;
310 if (NS_IsMainThread()) {
311 nsCOMPtr
<nsPIDOMWindowInner
> inner(do_QueryInterface(aGlobal
));
312 Document
* doc
= inner
? inner
->GetExtantDoc() : nullptr;
314 GetRequestURLFromDocument(doc
, input
, requestURL
, fragment
, aRv
);
316 // If we don't have a document, we must assume that this is a full URL.
317 GetRequestURLFromChrome(input
, requestURL
, fragment
, aRv
);
320 GetRequestURLFromWorker(aGlobal
, input
, requestURL
, fragment
, aRv
);
325 request
= MakeSafeRefPtr
<InternalRequest
>(NS_ConvertUTF16toUTF8(requestURL
),
328 request
= request
->GetRequestConstructorCopy(aGlobal
, aRv
);
329 if (NS_WARN_IF(aRv
.Failed())) {
332 Maybe
<RequestMode
> mode
;
333 if (aInit
.mMode
.WasPassed()) {
334 if (aInit
.mMode
.Value() == RequestMode::Navigate
) {
335 aRv
.ThrowTypeError
<MSG_INVALID_REQUEST_MODE
>("navigate");
339 mode
.emplace(aInit
.mMode
.Value());
341 Maybe
<RequestCredentials
> credentials
;
342 if (aInit
.mCredentials
.WasPassed()) {
343 credentials
.emplace(aInit
.mCredentials
.Value());
345 Maybe
<RequestCache
> cache
;
346 if (aInit
.mCache
.WasPassed()) {
347 cache
.emplace(aInit
.mCache
.Value());
349 if (aInput
.IsUSVString()) {
350 if (mode
.isNothing()) {
351 mode
.emplace(RequestMode::Cors
);
353 if (credentials
.isNothing()) {
354 credentials
.emplace(RequestCredentials::Same_origin
);
356 if (cache
.isNothing()) {
357 cache
.emplace(RequestCache::Default
);
361 if (aInit
.IsAnyMemberPresent() && request
->Mode() == RequestMode::Navigate
) {
362 mode
= Some(RequestMode::Same_origin
);
365 if (aInit
.IsAnyMemberPresent()) {
366 request
->SetReferrer(
367 NS_LITERAL_STRING_FROM_CSTRING(kFETCH_CLIENT_REFERRER_STR
));
368 request
->SetReferrerPolicy(ReferrerPolicy::_empty
);
370 if (aInit
.mReferrer
.WasPassed()) {
371 const nsString
& referrer
= aInit
.mReferrer
.Value();
372 if (referrer
.IsEmpty()) {
373 request
->SetReferrer(u
""_ns
);
375 nsAutoString referrerURL
;
376 if (NS_IsMainThread()) {
377 nsCOMPtr
<nsPIDOMWindowInner
> inner(do_QueryInterface(aGlobal
));
378 Document
* doc
= inner
? inner
->GetExtantDoc() : nullptr;
379 nsCOMPtr
<nsIURI
> uri
;
381 uri
= ParseURLFromDocument(doc
, referrer
, aRv
);
383 // If we don't have a document, we must assume that this is a full
385 uri
= ParseURLFromChrome(referrer
, aRv
);
387 if (NS_WARN_IF(aRv
.Failed())) {
388 aRv
.ThrowTypeError
<MSG_INVALID_REFERRER_URL
>(
389 NS_ConvertUTF16toUTF8(referrer
));
394 CopyUTF8toUTF16(spec
, referrerURL
);
395 if (!referrerURL
.EqualsLiteral(kFETCH_CLIENT_REFERRER_STR
)) {
396 nsCOMPtr
<nsIPrincipal
> principal
= aGlobal
->PrincipalOrNull();
399 principal
->CheckMayLoad(uri
,
400 /* allowIfInheritsPrincipal */ false);
402 referrerURL
.AssignLiteral(kFETCH_CLIENT_REFERRER_STR
);
407 RefPtr
<URL
> url
= ParseURLFromWorker(aGlobal
, referrer
, aRv
);
408 if (NS_WARN_IF(aRv
.Failed())) {
409 aRv
.ThrowTypeError
<MSG_INVALID_REFERRER_URL
>(
410 NS_ConvertUTF16toUTF8(referrer
));
413 url
->GetHref(referrerURL
);
414 if (!referrerURL
.EqualsLiteral(kFETCH_CLIENT_REFERRER_STR
)) {
415 WorkerPrivate
* worker
= GetCurrentThreadWorkerPrivate();
417 // ReferrerSameOriginChecker uses a sync loop to get the main thread
418 // to perform the same-origin check. Overall, on Workers this method
419 // can create 3 sync loops (two for constructing URLs and one here) so
420 // in the future we may want to optimize it all by off-loading all of
421 // this work in a single sync loop.
422 RefPtr
<ReferrerSameOriginChecker
> checker
=
423 new ReferrerSameOriginChecker(worker
, referrerURL
, rv
);
424 IgnoredErrorResult error
;
425 checker
->Dispatch(Canceling
, error
);
426 if (error
.Failed() || NS_FAILED(rv
)) {
427 referrerURL
.AssignLiteral(kFETCH_CLIENT_REFERRER_STR
);
431 request
->SetReferrer(referrerURL
);
435 if (aInit
.mReferrerPolicy
.WasPassed()) {
436 request
->SetReferrerPolicy(aInit
.mReferrerPolicy
.Value());
439 if (aInit
.mSignal
.WasPassed()) {
440 signal
= aInit
.mSignal
.Value();
443 // https://fetch.spec.whatwg.org/#dom-global-fetch
444 // https://fetch.spec.whatwg.org/#dom-request
445 // The priority of init overrides input's priority.
446 if (aInit
.mPriority
.WasPassed()) {
447 request
->SetPriorityMode(aInit
.mPriority
.Value());
450 UniquePtr
<mozilla::ipc::PrincipalInfo
> principalInfo
;
451 nsILoadInfo::CrossOriginEmbedderPolicy coep
=
452 nsILoadInfo::EMBEDDER_POLICY_NULL
;
454 if (NS_IsMainThread()) {
455 nsCOMPtr
<nsPIDOMWindowInner
> window
= do_QueryInterface(aGlobal
);
457 nsCOMPtr
<Document
> doc
;
458 doc
= window
->GetExtantDoc();
460 request
->SetEnvironmentReferrerPolicy(doc
->GetReferrerPolicy());
462 principalInfo
.reset(new mozilla::ipc::PrincipalInfo());
464 PrincipalToPrincipalInfo(doc
->NodePrincipal(), principalInfo
.get());
465 if (NS_WARN_IF(NS_FAILED(rv
))) {
466 aRv
.ThrowTypeError
<MSG_FETCH_BODY_CONSUMED_ERROR
>();
470 if (window
->GetWindowContext()) {
471 coep
= window
->GetWindowContext()->GetEmbedderPolicy();
475 WorkerPrivate
* worker
= GetCurrentThreadWorkerPrivate();
477 worker
->AssertIsOnWorkerThread();
478 request
->SetEnvironmentReferrerPolicy(worker
->GetReferrerPolicy());
480 MakeUnique
<mozilla::ipc::PrincipalInfo
>(worker
->GetPrincipalInfo());
481 coep
= worker
->GetEmbedderPolicy();
482 // For dedicated worker, the response must respect the owner's COEP.
483 if (coep
== nsILoadInfo::EMBEDDER_POLICY_NULL
&&
484 worker
->IsDedicatedWorker()) {
485 coep
= worker
->GetOwnerEmbedderPolicy();
490 request
->SetPrincipalInfo(std::move(principalInfo
));
491 request
->SetEmbedderPolicy(coep
);
494 request
->SetMode(mode
.value());
497 if (credentials
.isSome()) {
498 request
->SetCredentialsMode(credentials
.value());
501 if (cache
.isSome()) {
502 if (cache
.value() == RequestCache::Only_if_cached
&&
503 request
->Mode() != RequestMode::Same_origin
) {
504 aRv
.ThrowTypeError
<MSG_ONLY_IF_CACHED_WITHOUT_SAME_ORIGIN
>(
505 GetEnumString(request
->Mode()));
508 request
->SetCacheMode(cache
.value());
511 if (aInit
.mRedirect
.WasPassed()) {
512 request
->SetRedirectMode(aInit
.mRedirect
.Value());
515 if (aInit
.mIntegrity
.WasPassed()) {
516 request
->SetIntegrity(aInit
.mIntegrity
.Value());
519 if (aInit
.mMozErrors
.WasPassed() && aInit
.mMozErrors
.Value()) {
520 request
->SetMozErrors();
523 // Request constructor step 14.
524 if (aInit
.mMethod
.WasPassed()) {
525 nsAutoCString
method(aInit
.mMethod
.Value());
527 // Step 14.1. Disallow forbidden methods, and anything that is not a HTTP
528 // token, since HTTP states that Method may be any of the defined values or
529 // a token (extension method).
530 nsAutoCString outMethod
;
531 nsresult rv
= FetchUtil::GetValidRequestMethod(method
, outMethod
);
533 aRv
.ThrowTypeError
<MSG_INVALID_REQUEST_METHOD
>(method
);
538 request
->SetMethod(outMethod
);
541 RefPtr
<InternalHeaders
> requestHeaders
= request
->Headers();
543 RefPtr
<InternalHeaders
> headers
;
544 if (aInit
.mHeaders
.WasPassed()) {
545 RefPtr
<Headers
> h
= Headers::Create(aGlobal
, aInit
.mHeaders
.Value(), aRv
);
549 headers
= h
->GetInternalHeaders();
551 headers
= new InternalHeaders(*requestHeaders
);
554 requestHeaders
->Clear();
555 // From "Let r be a new Request object associated with request and a new
556 // Headers object whose guard is "request"."
557 requestHeaders
->SetGuard(HeadersGuardEnum::Request
, aRv
);
558 MOZ_ASSERT(!aRv
.Failed());
560 if (request
->Mode() == RequestMode::No_cors
) {
561 if (!request
->HasSimpleMethod()) {
562 nsAutoCString method
;
563 request
->GetMethod(method
);
564 aRv
.ThrowTypeError
<MSG_INVALID_REQUEST_METHOD
>(method
);
568 requestHeaders
->SetGuard(HeadersGuardEnum::Request_no_cors
, aRv
);
574 requestHeaders
->Fill(*headers
, aRv
);
579 if ((aInit
.mBody
.WasPassed() && !aInit
.mBody
.Value().IsNull()) ||
581 // HEAD and GET are not allowed to have a body.
582 nsAutoCString method
;
583 request
->GetMethod(method
);
584 // method is guaranteed to be uppercase due to step 14.2 above.
585 if (method
.EqualsLiteral("HEAD") || method
.EqualsLiteral("GET")) {
586 aRv
.ThrowTypeError("HEAD or GET Request cannot have a body.");
591 if (aInit
.mBody
.WasPassed()) {
592 const Nullable
<fetch::OwningBodyInit
>& bodyInitNullable
=
594 if (!bodyInitNullable
.IsNull()) {
595 const fetch::OwningBodyInit
& bodyInit
= bodyInitNullable
.Value();
596 nsCOMPtr
<nsIInputStream
> stream
;
597 nsAutoCString contentTypeWithCharset
;
598 uint64_t contentLength
= 0;
599 aRv
= ExtractByteStreamFromBody(bodyInit
, getter_AddRefs(stream
),
600 contentTypeWithCharset
, contentLength
);
601 if (NS_WARN_IF(aRv
.Failed())) {
605 nsCOMPtr
<nsIInputStream
> temporaryBody
= stream
;
607 if (!contentTypeWithCharset
.IsVoid() &&
608 !requestHeaders
->Has("Content-Type"_ns
, aRv
)) {
609 requestHeaders
->Append("Content-Type"_ns
, contentTypeWithCharset
, aRv
);
612 if (NS_WARN_IF(aRv
.Failed())) {
617 request
->SetBody(nullptr, 0);
620 request
->SetBody(temporaryBody
, contentLength
);
625 MakeSafeRefPtr
<Request
>(aGlobal
, std::move(request
), signal
);
627 if (aInput
.IsRequest() && !bodyFromInit
) {
628 RefPtr
<Request
> inputReq
= &aInput
.GetAsRequest();
629 nsCOMPtr
<nsIInputStream
> body
;
630 inputReq
->GetBody(getter_AddRefs(body
));
632 inputReq
->SetBody(nullptr, 0);
633 inputReq
->SetBodyUsed(aCx
, aRv
);
634 if (NS_WARN_IF(aRv
.Failed())) {
642 SafeRefPtr
<Request
> Request::Clone(ErrorResult
& aRv
) {
644 aRv
.ThrowTypeError
<MSG_FETCH_BODY_CONSUMED_ERROR
>();
648 SafeRefPtr
<InternalRequest
> ir
= mRequest
->Clone();
650 aRv
.Throw(NS_ERROR_FAILURE
);
654 return MakeSafeRefPtr
<Request
>(mOwner
, std::move(ir
), GetOrCreateSignal());
657 Headers
* Request::Headers_() {
659 mHeaders
= new Headers(mOwner
, mRequest
->Headers());
665 AbortSignal
* Request::GetOrCreateSignal() {
667 mSignal
= new AbortSignal(mOwner
, false, JS::UndefinedHandleValue
);
673 AbortSignalImpl
* Request::GetSignalImpl() const { return mSignal
; }
675 AbortSignalImpl
* Request::GetSignalImplToConsumeBody() const {
676 // This is a hack, see Response::GetSignalImplToConsumeBody.
680 } // namespace mozilla::dom