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/StaticPrefs_network.h"
16 #include "mozilla/dom/Headers.h"
17 #include "mozilla/dom/Fetch.h"
18 #include "mozilla/dom/FetchUtil.h"
19 #include "mozilla/dom/Promise.h"
20 #include "mozilla/dom/URL.h"
21 #include "mozilla/dom/WorkerPrivate.h"
22 #include "mozilla/dom/WorkerRunnable.h"
23 #include "mozilla/dom/WindowContext.h"
24 #include "mozilla/ipc/PBackgroundSharedTypes.h"
25 #include "mozilla/Unused.h"
27 #include "mozilla/dom/ReadableStreamDefaultReader.h"
29 namespace mozilla::dom
{
31 NS_IMPL_ADDREF_INHERITED(Request
, FetchBody
<Request
>)
32 NS_IMPL_RELEASE_INHERITED(Request
, FetchBody
<Request
>)
34 // Can't use _INHERITED macro here because FetchBody<Request> is abstract.
35 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(Request
)
37 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(Request
, FetchBody
<Request
>)
38 NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner
)
39 NS_IMPL_CYCLE_COLLECTION_UNLINK(mHeaders
)
40 NS_IMPL_CYCLE_COLLECTION_UNLINK(mSignal
)
41 NS_IMPL_CYCLE_COLLECTION_UNLINK(mFetchStreamReader
)
42 NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
43 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
45 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(Request
, FetchBody
<Request
>)
46 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner
)
47 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mHeaders
)
48 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSignal
)
49 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFetchStreamReader
)
50 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
52 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Request
)
53 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
54 NS_INTERFACE_MAP_END_INHERITING(FetchBody
<Request
>)
56 Request::Request(nsIGlobalObject
* aOwner
, SafeRefPtr
<InternalRequest
> aRequest
,
58 : FetchBody
<Request
>(aOwner
), mRequest(std::move(aRequest
)) {
59 MOZ_ASSERT(mRequest
->Headers()->Guard() == HeadersGuardEnum::Immutable
||
60 mRequest
->Headers()->Guard() == HeadersGuardEnum::Request
||
61 mRequest
->Headers()->Guard() == HeadersGuardEnum::Request_no_cors
);
63 // If we don't have a signal as argument, we will create it when required by
64 // content, otherwise the Request's signal must follow what has been passed.
65 JS::Rooted
<JS::Value
> reason(RootingCx(), aSignal
->RawReason());
66 mSignal
= new AbortSignal(aOwner
, aSignal
->Aborted(), reason
);
67 if (!mSignal
->Aborted()) {
68 mSignal
->Follow(aSignal
);
73 Request::~Request() = default;
75 SafeRefPtr
<InternalRequest
> Request::GetInternalRequest() {
76 return mRequest
.clonePtr();
80 already_AddRefed
<nsIURI
> ParseURLFromDocument(Document
* aDocument
,
81 const nsAString
& aInput
,
83 MOZ_ASSERT(aDocument
);
84 MOZ_ASSERT(NS_IsMainThread());
86 // Don't use NS_ConvertUTF16toUTF8 because that doesn't let us handle OOM.
88 if (!AppendUTF16toUTF8(aInput
, input
, fallible
)) {
89 aRv
.Throw(NS_ERROR_OUT_OF_MEMORY
);
93 nsCOMPtr
<nsIURI
> resolvedURI
;
94 nsresult rv
= NS_NewURI(getter_AddRefs(resolvedURI
), input
, nullptr,
95 aDocument
->GetBaseURI());
96 if (NS_WARN_IF(NS_FAILED(rv
))) {
97 aRv
.ThrowTypeError
<MSG_INVALID_URL
>(input
);
99 return resolvedURI
.forget();
101 void GetRequestURLFromDocument(Document
* aDocument
, const nsAString
& aInput
,
102 nsAString
& aRequestURL
, nsACString
& aURLfragment
,
104 nsCOMPtr
<nsIURI
> resolvedURI
= ParseURLFromDocument(aDocument
, aInput
, aRv
);
108 // This fails with URIs with weird protocols, even when they are valid,
109 // so we ignore the failure
110 nsAutoCString credentials
;
111 Unused
<< resolvedURI
->GetUserPass(credentials
);
112 if (!credentials
.IsEmpty()) {
113 aRv
.ThrowTypeError
<MSG_URL_HAS_CREDENTIALS
>(NS_ConvertUTF16toUTF8(aInput
));
117 nsCOMPtr
<nsIURI
> resolvedURIClone
;
118 aRv
= NS_GetURIWithoutRef(resolvedURI
, getter_AddRefs(resolvedURIClone
));
119 if (NS_WARN_IF(aRv
.Failed())) {
123 aRv
= resolvedURIClone
->GetSpec(spec
);
124 if (NS_WARN_IF(aRv
.Failed())) {
127 CopyUTF8toUTF16(spec
, aRequestURL
);
129 // Get the fragment from nsIURI.
130 aRv
= resolvedURI
->GetRef(aURLfragment
);
131 if (NS_WARN_IF(aRv
.Failed())) {
135 already_AddRefed
<nsIURI
> ParseURLFromChrome(const nsAString
& aInput
,
137 MOZ_ASSERT(NS_IsMainThread());
138 // Don't use NS_ConvertUTF16toUTF8 because that doesn't let us handle OOM.
140 if (!AppendUTF16toUTF8(aInput
, input
, fallible
)) {
141 aRv
.Throw(NS_ERROR_OUT_OF_MEMORY
);
145 nsCOMPtr
<nsIURI
> uri
;
146 nsresult rv
= NS_NewURI(getter_AddRefs(uri
), input
);
148 aRv
.ThrowTypeError
<MSG_INVALID_URL
>(input
);
152 void GetRequestURLFromChrome(const nsAString
& aInput
, nsAString
& aRequestURL
,
153 nsACString
& aURLfragment
, ErrorResult
& aRv
) {
154 nsCOMPtr
<nsIURI
> uri
= ParseURLFromChrome(aInput
, aRv
);
158 // This fails with URIs with weird protocols, even when they are valid,
159 // so we ignore the failure
160 nsAutoCString credentials
;
161 Unused
<< uri
->GetUserPass(credentials
);
162 if (!credentials
.IsEmpty()) {
163 aRv
.ThrowTypeError
<MSG_URL_HAS_CREDENTIALS
>(NS_ConvertUTF16toUTF8(aInput
));
167 nsCOMPtr
<nsIURI
> uriClone
;
168 aRv
= NS_GetURIWithoutRef(uri
, getter_AddRefs(uriClone
));
169 if (NS_WARN_IF(aRv
.Failed())) {
173 aRv
= uriClone
->GetSpec(spec
);
174 if (NS_WARN_IF(aRv
.Failed())) {
177 CopyUTF8toUTF16(spec
, aRequestURL
);
179 // Get the fragment from nsIURI.
180 aRv
= uri
->GetRef(aURLfragment
);
181 if (NS_WARN_IF(aRv
.Failed())) {
185 already_AddRefed
<URL
> ParseURLFromWorker(nsIGlobalObject
* aGlobal
,
186 const nsAString
& aInput
,
188 WorkerPrivate
* worker
= GetCurrentThreadWorkerPrivate();
190 worker
->AssertIsOnWorkerThread();
192 NS_ConvertUTF8toUTF16
baseURL(worker
->GetLocationInfo().mHref
);
193 RefPtr
<URL
> url
= URL::Constructor(aGlobal
, aInput
, baseURL
, aRv
);
194 if (NS_WARN_IF(aRv
.Failed())) {
195 aRv
.ThrowTypeError
<MSG_INVALID_URL
>(NS_ConvertUTF16toUTF8(aInput
));
199 void GetRequestURLFromWorker(nsIGlobalObject
* aGlobal
, const nsAString
& aInput
,
200 nsAString
& aRequestURL
, nsACString
& aURLfragment
,
202 RefPtr
<URL
> url
= ParseURLFromWorker(aGlobal
, aInput
, aRv
);
207 url
->GetUsername(username
);
210 url
->GetPassword(password
);
212 if (!username
.IsEmpty() || !password
.IsEmpty()) {
213 aRv
.ThrowTypeError
<MSG_URL_HAS_CREDENTIALS
>(NS_ConvertUTF16toUTF8(aInput
));
217 // Get the fragment from URL.
218 nsAutoString fragment
;
219 url
->GetHash(fragment
);
221 // Note: URL::GetHash() includes the "#" and we want the fragment with out
223 if (!fragment
.IsEmpty()) {
224 CopyUTF16toUTF8(Substring(fragment
, 1), aURLfragment
);
227 url
->SetHash(u
""_ns
);
228 url
->GetHref(aRequestURL
);
231 class ReferrerSameOriginChecker final
: public WorkerMainThreadRunnable
{
233 ReferrerSameOriginChecker(WorkerPrivate
* aWorkerPrivate
,
234 const nsAString
& aReferrerURL
, nsresult
& aResult
)
235 : WorkerMainThreadRunnable(aWorkerPrivate
,
236 "Fetch :: Referrer same origin check"_ns
),
237 mReferrerURL(aReferrerURL
),
239 mWorkerPrivate
->AssertIsOnWorkerThread();
242 bool MainThreadRun() override
{
243 nsCOMPtr
<nsIURI
> uri
;
244 if (NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri
), mReferrerURL
))) {
245 nsCOMPtr
<nsIPrincipal
> principal
= mWorkerPrivate
->GetPrincipal();
247 mResult
= principal
->CheckMayLoad(uri
,
248 /* allowIfInheritsPrincipal */ false);
255 const nsString mReferrerURL
;
262 SafeRefPtr
<Request
> Request::Constructor(const GlobalObject
& aGlobal
,
263 const RequestOrUSVString
& aInput
,
264 const RequestInit
& aInit
,
266 nsCOMPtr
<nsIGlobalObject
> global
= do_QueryInterface(aGlobal
.GetAsSupports());
267 return Constructor(global
, aGlobal
.Context(), aInput
, aInit
,
268 aGlobal
.CallerType(), aRv
);
272 SafeRefPtr
<Request
> Request::Constructor(
273 nsIGlobalObject
* aGlobal
, JSContext
* aCx
, const RequestOrUSVString
& aInput
,
274 const RequestInit
& aInit
, CallerType aCallerType
, ErrorResult
& aRv
) {
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 if (aCallerType
== CallerType::System
&&
355 StaticPrefs::network_fetch_systemDefaultsToOmittingCredentials()) {
356 credentials
.emplace(RequestCredentials::Omit
);
358 credentials
.emplace(RequestCredentials::Same_origin
);
361 if (cache
.isNothing()) {
362 cache
.emplace(RequestCache::Default
);
366 if (aInit
.IsAnyMemberPresent() && request
->Mode() == RequestMode::Navigate
) {
367 mode
= Some(RequestMode::Same_origin
);
370 if (aInit
.IsAnyMemberPresent()) {
371 request
->SetReferrer(
372 NS_LITERAL_STRING_FROM_CSTRING(kFETCH_CLIENT_REFERRER_STR
));
373 request
->SetReferrerPolicy(ReferrerPolicy::_empty
);
375 if (aInit
.mReferrer
.WasPassed()) {
376 const nsString
& referrer
= aInit
.mReferrer
.Value();
377 if (referrer
.IsEmpty()) {
378 request
->SetReferrer(u
""_ns
);
380 nsAutoString referrerURL
;
381 if (NS_IsMainThread()) {
382 nsCOMPtr
<nsPIDOMWindowInner
> inner(do_QueryInterface(aGlobal
));
383 Document
* doc
= inner
? inner
->GetExtantDoc() : nullptr;
384 nsCOMPtr
<nsIURI
> uri
;
386 uri
= ParseURLFromDocument(doc
, referrer
, aRv
);
388 // If we don't have a document, we must assume that this is a full
390 uri
= ParseURLFromChrome(referrer
, aRv
);
392 if (NS_WARN_IF(aRv
.Failed())) {
393 aRv
.ThrowTypeError
<MSG_INVALID_REFERRER_URL
>(
394 NS_ConvertUTF16toUTF8(referrer
));
399 CopyUTF8toUTF16(spec
, referrerURL
);
400 if (!referrerURL
.EqualsLiteral(kFETCH_CLIENT_REFERRER_STR
)) {
401 nsCOMPtr
<nsIPrincipal
> principal
= aGlobal
->PrincipalOrNull();
404 principal
->CheckMayLoad(uri
,
405 /* allowIfInheritsPrincipal */ false);
407 referrerURL
.AssignLiteral(kFETCH_CLIENT_REFERRER_STR
);
412 RefPtr
<URL
> url
= ParseURLFromWorker(aGlobal
, referrer
, aRv
);
413 if (NS_WARN_IF(aRv
.Failed())) {
414 aRv
.ThrowTypeError
<MSG_INVALID_REFERRER_URL
>(
415 NS_ConvertUTF16toUTF8(referrer
));
418 url
->GetHref(referrerURL
);
419 if (!referrerURL
.EqualsLiteral(kFETCH_CLIENT_REFERRER_STR
)) {
420 WorkerPrivate
* worker
= GetCurrentThreadWorkerPrivate();
422 // ReferrerSameOriginChecker uses a sync loop to get the main thread
423 // to perform the same-origin check. Overall, on Workers this method
424 // can create 3 sync loops (two for constructing URLs and one here) so
425 // in the future we may want to optimize it all by off-loading all of
426 // this work in a single sync loop.
427 RefPtr
<ReferrerSameOriginChecker
> checker
=
428 new ReferrerSameOriginChecker(worker
, referrerURL
, rv
);
429 IgnoredErrorResult error
;
430 checker
->Dispatch(Canceling
, error
);
431 if (error
.Failed() || NS_FAILED(rv
)) {
432 referrerURL
.AssignLiteral(kFETCH_CLIENT_REFERRER_STR
);
436 request
->SetReferrer(referrerURL
);
440 if (aInit
.mReferrerPolicy
.WasPassed()) {
441 request
->SetReferrerPolicy(aInit
.mReferrerPolicy
.Value());
444 if (aInit
.mSignal
.WasPassed()) {
445 signal
= aInit
.mSignal
.Value();
448 // https://fetch.spec.whatwg.org/#dom-global-fetch
449 // https://fetch.spec.whatwg.org/#dom-request
450 // The priority of init overrides input's priority.
451 if (aInit
.mPriority
.WasPassed()) {
452 request
->SetPriorityMode(aInit
.mPriority
.Value());
455 UniquePtr
<mozilla::ipc::PrincipalInfo
> principalInfo
;
456 nsILoadInfo::CrossOriginEmbedderPolicy coep
=
457 nsILoadInfo::EMBEDDER_POLICY_NULL
;
459 if (NS_IsMainThread()) {
460 nsCOMPtr
<nsPIDOMWindowInner
> window
= do_QueryInterface(aGlobal
);
462 nsCOMPtr
<Document
> doc
;
463 doc
= window
->GetExtantDoc();
465 request
->SetEnvironmentReferrerPolicy(doc
->GetReferrerPolicy());
467 principalInfo
.reset(new mozilla::ipc::PrincipalInfo());
469 PrincipalToPrincipalInfo(doc
->NodePrincipal(), principalInfo
.get());
470 if (NS_WARN_IF(NS_FAILED(rv
))) {
471 aRv
.ThrowTypeError
<MSG_FETCH_BODY_CONSUMED_ERROR
>();
475 if (window
->GetWindowContext()) {
476 coep
= window
->GetWindowContext()->GetEmbedderPolicy();
480 WorkerPrivate
* worker
= GetCurrentThreadWorkerPrivate();
482 worker
->AssertIsOnWorkerThread();
483 request
->SetEnvironmentReferrerPolicy(worker
->GetReferrerPolicy());
485 MakeUnique
<mozilla::ipc::PrincipalInfo
>(worker
->GetPrincipalInfo());
486 coep
= worker
->GetEmbedderPolicy();
487 // For dedicated worker, the response must respect the owner's COEP.
488 if (coep
== nsILoadInfo::EMBEDDER_POLICY_NULL
&&
489 worker
->IsDedicatedWorker()) {
490 coep
= worker
->GetOwnerEmbedderPolicy();
495 request
->SetPrincipalInfo(std::move(principalInfo
));
496 request
->SetEmbedderPolicy(coep
);
499 request
->SetMode(mode
.value());
502 if (credentials
.isSome()) {
503 request
->SetCredentialsMode(credentials
.value());
506 if (cache
.isSome()) {
507 if (cache
.value() == RequestCache::Only_if_cached
&&
508 request
->Mode() != RequestMode::Same_origin
) {
509 aRv
.ThrowTypeError
<MSG_ONLY_IF_CACHED_WITHOUT_SAME_ORIGIN
>(
510 GetEnumString(request
->Mode()));
513 request
->SetCacheMode(cache
.value());
516 if (aInit
.mRedirect
.WasPassed()) {
517 request
->SetRedirectMode(aInit
.mRedirect
.Value());
520 if (aInit
.mIntegrity
.WasPassed()) {
521 request
->SetIntegrity(aInit
.mIntegrity
.Value());
524 if (aInit
.mKeepalive
.WasPassed()) {
525 request
->SetKeepalive(aInit
.mKeepalive
.Value());
528 if (aInit
.mMozErrors
.WasPassed() && aInit
.mMozErrors
.Value()) {
529 request
->SetMozErrors();
532 // Request constructor step 14.
533 if (aInit
.mMethod
.WasPassed()) {
534 nsAutoCString
method(aInit
.mMethod
.Value());
536 // Step 14.1. Disallow forbidden methods, and anything that is not a HTTP
537 // token, since HTTP states that Method may be any of the defined values or
538 // a token (extension method).
539 nsAutoCString outMethod
;
540 nsresult rv
= FetchUtil::GetValidRequestMethod(method
, outMethod
);
542 aRv
.ThrowTypeError
<MSG_INVALID_REQUEST_METHOD
>(method
);
547 request
->SetMethod(outMethod
);
550 RefPtr
<InternalHeaders
> requestHeaders
= request
->Headers();
552 RefPtr
<InternalHeaders
> headers
;
553 if (aInit
.mHeaders
.WasPassed()) {
554 RefPtr
<Headers
> h
= Headers::Create(aGlobal
, aInit
.mHeaders
.Value(), aRv
);
558 headers
= h
->GetInternalHeaders();
560 headers
= new InternalHeaders(*requestHeaders
);
563 requestHeaders
->Clear();
564 // From "Let r be a new Request object associated with request and a new
565 // Headers object whose guard is "request"."
566 requestHeaders
->SetGuard(HeadersGuardEnum::Request
, aRv
);
567 MOZ_ASSERT(!aRv
.Failed());
569 if (request
->Mode() == RequestMode::No_cors
) {
570 if (!request
->HasSimpleMethod()) {
571 nsAutoCString method
;
572 request
->GetMethod(method
);
573 aRv
.ThrowTypeError
<MSG_INVALID_REQUEST_METHOD
>(method
);
577 requestHeaders
->SetGuard(HeadersGuardEnum::Request_no_cors
, aRv
);
583 requestHeaders
->Fill(*headers
, aRv
);
588 if ((aInit
.mBody
.WasPassed() && !aInit
.mBody
.Value().IsNull()) ||
590 // HEAD and GET are not allowed to have a body.
591 nsAutoCString method
;
592 request
->GetMethod(method
);
593 // method is guaranteed to be uppercase due to step 14.2 above.
594 if (method
.EqualsLiteral("HEAD") || method
.EqualsLiteral("GET")) {
595 aRv
.ThrowTypeError("HEAD or GET Request cannot have a body.");
600 if (aInit
.mBody
.WasPassed()) {
601 const Nullable
<fetch::OwningBodyInit
>& bodyInitNullable
=
603 if (!bodyInitNullable
.IsNull()) {
604 const fetch::OwningBodyInit
& bodyInit
= bodyInitNullable
.Value();
605 nsCOMPtr
<nsIInputStream
> stream
;
606 nsAutoCString contentTypeWithCharset
;
607 uint64_t contentLength
= 0;
608 aRv
= ExtractByteStreamFromBody(bodyInit
, getter_AddRefs(stream
),
609 contentTypeWithCharset
, contentLength
);
610 if (NS_WARN_IF(aRv
.Failed())) {
614 nsCOMPtr
<nsIInputStream
> temporaryBody
= stream
;
616 if (!contentTypeWithCharset
.IsVoid() &&
617 !requestHeaders
->Has("Content-Type"_ns
, aRv
)) {
618 requestHeaders
->Append("Content-Type"_ns
, contentTypeWithCharset
, aRv
);
621 if (NS_WARN_IF(aRv
.Failed())) {
626 request
->SetBody(nullptr, 0);
629 request
->SetBody(temporaryBody
, contentLength
);
634 MakeSafeRefPtr
<Request
>(aGlobal
, std::move(request
), signal
);
636 if (aInput
.IsRequest() && !bodyFromInit
) {
637 RefPtr
<Request
> inputReq
= &aInput
.GetAsRequest();
638 nsCOMPtr
<nsIInputStream
> body
;
639 inputReq
->GetBody(getter_AddRefs(body
));
641 inputReq
->SetBody(nullptr, 0);
642 inputReq
->SetBodyUsed(aCx
, aRv
);
643 if (NS_WARN_IF(aRv
.Failed())) {
651 SafeRefPtr
<Request
> Request::Clone(ErrorResult
& aRv
) {
653 aRv
.ThrowTypeError
<MSG_FETCH_BODY_CONSUMED_ERROR
>();
657 SafeRefPtr
<InternalRequest
> ir
= mRequest
->Clone();
659 aRv
.Throw(NS_ERROR_FAILURE
);
663 return MakeSafeRefPtr
<Request
>(mOwner
, std::move(ir
), GetOrCreateSignal());
666 Headers
* Request::Headers_() {
668 mHeaders
= new Headers(mOwner
, mRequest
->Headers());
674 AbortSignal
* Request::GetOrCreateSignal() {
676 mSignal
= new AbortSignal(mOwner
, false, JS::UndefinedHandleValue
);
682 AbortSignalImpl
* Request::GetSignalImpl() const { return mSignal
; }
684 AbortSignalImpl
* Request::GetSignalImplToConsumeBody() const {
685 // This is a hack, see Response::GetSignalImplToConsumeBody.
689 } // namespace mozilla::dom