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/. */
10 #include "nsNetUtil.h"
11 #include "nsPIDOMWindow.h"
13 #include "mozilla/ErrorResult.h"
14 #include "mozilla/dom/Headers.h"
15 #include "mozilla/dom/Fetch.h"
16 #include "mozilla/dom/FetchUtil.h"
17 #include "mozilla/dom/Promise.h"
18 #include "mozilla/dom/URL.h"
19 #include "mozilla/dom/WorkerPrivate.h"
20 #include "mozilla/dom/WorkerRunnable.h"
21 #include "mozilla/dom/WindowContext.h"
22 #include "mozilla/Unused.h"
24 namespace mozilla::dom
{
26 NS_IMPL_ADDREF_INHERITED(Request
, FetchBody
<Request
>)
27 NS_IMPL_RELEASE_INHERITED(Request
, FetchBody
<Request
>)
29 NS_IMPL_CYCLE_COLLECTION_CLASS(Request
)
31 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(Request
, FetchBody
<Request
>)
32 NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner
)
33 NS_IMPL_CYCLE_COLLECTION_UNLINK(mHeaders
)
34 NS_IMPL_CYCLE_COLLECTION_UNLINK(mSignal
)
35 AbortFollower::Unlink(static_cast<AbortFollower
*>(tmp
));
36 NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
37 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
39 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(Request
, FetchBody
<Request
>)
40 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner
)
41 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mHeaders
)
42 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSignal
)
43 AbortFollower::Traverse(static_cast<AbortFollower
*>(tmp
), cb
);
44 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
46 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(Request
, FetchBody
<Request
>)
47 NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mReadableStreamBody
)
48 MOZ_DIAGNOSTIC_ASSERT(!tmp
->mReadableStreamReader
);
49 NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mReadableStreamReader
)
50 NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
51 NS_IMPL_CYCLE_COLLECTION_TRACE_END
53 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Request
)
54 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
55 NS_INTERFACE_MAP_END_INHERITING(FetchBody
<Request
>)
57 Request::Request(nsIGlobalObject
* aOwner
, SafeRefPtr
<InternalRequest
> aRequest
,
59 : FetchBody
<Request
>(aOwner
), mRequest(std::move(aRequest
)) {
60 MOZ_ASSERT(mRequest
->Headers()->Guard() == HeadersGuardEnum::Immutable
||
61 mRequest
->Headers()->Guard() == HeadersGuardEnum::Request
||
62 mRequest
->Headers()->Guard() == HeadersGuardEnum::Request_no_cors
);
64 // If we don't have a signal as argument, we will create it when required by
65 // content, otherwise the Request's signal must follow what has been passed.
66 mSignal
= new AbortSignal(aOwner
, aSignal
->Aborted());
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
, aRv
);
271 SafeRefPtr
<Request
> Request::Constructor(nsIGlobalObject
* aGlobal
,
273 const RequestOrUSVString
& aInput
,
274 const RequestInit
& aInit
,
276 bool hasCopiedBody
= false;
277 SafeRefPtr
<InternalRequest
> request
;
279 RefPtr
<AbortSignal
> signal
;
281 if (aInput
.IsRequest()) {
282 RefPtr
<Request
> inputReq
= &aInput
.GetAsRequest();
283 nsCOMPtr
<nsIInputStream
> body
;
284 inputReq
->GetBody(getter_AddRefs(body
));
285 bool used
= inputReq
->GetBodyUsed(aRv
);
286 if (NS_WARN_IF(aRv
.Failed())) {
290 aRv
.ThrowTypeError
<MSG_FETCH_BODY_CONSUMED_ERROR
>();
294 // The body will be copied when GetRequestConstructorCopy() is executed.
296 hasCopiedBody
= true;
299 request
= inputReq
->GetInternalRequest();
300 signal
= inputReq
->GetOrCreateSignal();
302 // aInput is USVString.
303 // We need to get url before we create a InternalRequest.
305 input
.Assign(aInput
.GetAsUSVString());
306 nsAutoString requestURL
;
308 if (NS_IsMainThread()) {
309 nsCOMPtr
<nsPIDOMWindowInner
> inner(do_QueryInterface(aGlobal
));
310 Document
* doc
= inner
? inner
->GetExtantDoc() : nullptr;
312 GetRequestURLFromDocument(doc
, input
, requestURL
, fragment
, aRv
);
314 // If we don't have a document, we must assume that this is a full URL.
315 GetRequestURLFromChrome(input
, requestURL
, fragment
, aRv
);
318 GetRequestURLFromWorker(aGlobal
, input
, requestURL
, fragment
, aRv
);
323 request
= MakeSafeRefPtr
<InternalRequest
>(NS_ConvertUTF16toUTF8(requestURL
),
326 request
= request
->GetRequestConstructorCopy(aGlobal
, aRv
);
327 if (NS_WARN_IF(aRv
.Failed())) {
330 RequestMode fallbackMode
= RequestMode::EndGuard_
;
331 RequestCredentials fallbackCredentials
= RequestCredentials::EndGuard_
;
332 RequestCache fallbackCache
= RequestCache::EndGuard_
;
333 if (aInput
.IsUSVString()) {
334 fallbackMode
= RequestMode::Cors
;
335 fallbackCredentials
= RequestCredentials::Same_origin
;
336 fallbackCache
= RequestCache::Default
;
340 aInit
.mMode
.WasPassed() ? aInit
.mMode
.Value() : fallbackMode
;
341 RequestCredentials credentials
= aInit
.mCredentials
.WasPassed()
342 ? aInit
.mCredentials
.Value()
343 : fallbackCredentials
;
345 if (mode
== RequestMode::Navigate
) {
346 aRv
.ThrowTypeError
<MSG_INVALID_REQUEST_MODE
>("navigate");
349 if (aInit
.IsAnyMemberPresent() && request
->Mode() == RequestMode::Navigate
) {
350 mode
= RequestMode::Same_origin
;
353 if (aInit
.IsAnyMemberPresent()) {
354 request
->SetReferrer(
355 NS_LITERAL_STRING_FROM_CSTRING(kFETCH_CLIENT_REFERRER_STR
));
356 request
->SetReferrerPolicy(ReferrerPolicy::_empty
);
358 if (aInit
.mReferrer
.WasPassed()) {
359 const nsString
& referrer
= aInit
.mReferrer
.Value();
360 if (referrer
.IsEmpty()) {
361 request
->SetReferrer(u
""_ns
);
363 nsAutoString referrerURL
;
364 if (NS_IsMainThread()) {
365 nsCOMPtr
<nsPIDOMWindowInner
> inner(do_QueryInterface(aGlobal
));
366 Document
* doc
= inner
? inner
->GetExtantDoc() : nullptr;
367 nsCOMPtr
<nsIURI
> uri
;
369 uri
= ParseURLFromDocument(doc
, referrer
, aRv
);
371 // If we don't have a document, we must assume that this is a full
373 uri
= ParseURLFromChrome(referrer
, aRv
);
375 if (NS_WARN_IF(aRv
.Failed())) {
376 aRv
.ThrowTypeError
<MSG_INVALID_REFERRER_URL
>(
377 NS_ConvertUTF16toUTF8(referrer
));
382 CopyUTF8toUTF16(spec
, referrerURL
);
383 if (!referrerURL
.EqualsLiteral(kFETCH_CLIENT_REFERRER_STR
)) {
384 nsCOMPtr
<nsIPrincipal
> principal
= aGlobal
->PrincipalOrNull();
387 principal
->CheckMayLoad(uri
,
388 /* allowIfInheritsPrincipal */ false);
390 referrerURL
.AssignLiteral(kFETCH_CLIENT_REFERRER_STR
);
395 RefPtr
<URL
> url
= ParseURLFromWorker(aGlobal
, referrer
, aRv
);
396 if (NS_WARN_IF(aRv
.Failed())) {
397 aRv
.ThrowTypeError
<MSG_INVALID_REFERRER_URL
>(
398 NS_ConvertUTF16toUTF8(referrer
));
401 url
->GetHref(referrerURL
);
402 if (!referrerURL
.EqualsLiteral(kFETCH_CLIENT_REFERRER_STR
)) {
403 WorkerPrivate
* worker
= GetCurrentThreadWorkerPrivate();
405 // ReferrerSameOriginChecker uses a sync loop to get the main thread
406 // to perform the same-origin check. Overall, on Workers this method
407 // can create 3 sync loops (two for constructing URLs and one here) so
408 // in the future we may want to optimize it all by off-loading all of
409 // this work in a single sync loop.
410 RefPtr
<ReferrerSameOriginChecker
> checker
=
411 new ReferrerSameOriginChecker(worker
, referrerURL
, rv
);
412 IgnoredErrorResult error
;
413 checker
->Dispatch(Canceling
, error
);
414 if (error
.Failed() || NS_FAILED(rv
)) {
415 referrerURL
.AssignLiteral(kFETCH_CLIENT_REFERRER_STR
);
419 request
->SetReferrer(referrerURL
);
423 if (aInit
.mReferrerPolicy
.WasPassed()) {
424 request
->SetReferrerPolicy(aInit
.mReferrerPolicy
.Value());
427 if (aInit
.mSignal
.WasPassed()) {
428 signal
= aInit
.mSignal
.Value();
431 UniquePtr
<mozilla::ipc::PrincipalInfo
> principalInfo
;
432 nsILoadInfo::CrossOriginEmbedderPolicy coep
=
433 nsILoadInfo::EMBEDDER_POLICY_NULL
;
435 if (NS_IsMainThread()) {
436 nsCOMPtr
<nsPIDOMWindowInner
> window
= do_QueryInterface(aGlobal
);
438 nsCOMPtr
<Document
> doc
;
439 doc
= window
->GetExtantDoc();
441 request
->SetEnvironmentReferrerPolicy(doc
->GetReferrerPolicy());
443 principalInfo
.reset(new mozilla::ipc::PrincipalInfo());
445 PrincipalToPrincipalInfo(doc
->NodePrincipal(), principalInfo
.get());
446 if (NS_WARN_IF(NS_FAILED(rv
))) {
447 aRv
.ThrowTypeError
<MSG_FETCH_BODY_CONSUMED_ERROR
>();
451 if (window
->GetWindowContext()) {
452 coep
= window
->GetWindowContext()->GetEmbedderPolicy();
456 WorkerPrivate
* worker
= GetCurrentThreadWorkerPrivate();
458 worker
->AssertIsOnWorkerThread();
459 request
->SetEnvironmentReferrerPolicy(worker
->GetReferrerPolicy());
461 MakeUnique
<mozilla::ipc::PrincipalInfo
>(worker
->GetPrincipalInfo());
462 coep
= worker
->GetEmbedderPolicy();
463 // For dedicated worker, the response must respect the owner's COEP.
464 if (coep
== nsILoadInfo::EMBEDDER_POLICY_NULL
&&
465 worker
->IsDedicatedWorker()) {
466 coep
= worker
->GetOwnerEmbedderPolicy();
471 request
->SetPrincipalInfo(std::move(principalInfo
));
472 request
->SetEmbedderPolicy(coep
);
474 if (mode
!= RequestMode::EndGuard_
) {
475 request
->SetMode(mode
);
478 if (credentials
!= RequestCredentials::EndGuard_
) {
479 request
->SetCredentialsMode(credentials
);
483 aInit
.mCache
.WasPassed() ? aInit
.mCache
.Value() : fallbackCache
;
484 if (cache
!= RequestCache::EndGuard_
) {
485 if (cache
== RequestCache::Only_if_cached
&&
486 request
->Mode() != RequestMode::Same_origin
) {
487 nsCString
modeString(RequestModeValues::GetString(request
->Mode()));
488 aRv
.ThrowTypeError
<MSG_ONLY_IF_CACHED_WITHOUT_SAME_ORIGIN
>(modeString
);
491 request
->SetCacheMode(cache
);
494 if (aInit
.mRedirect
.WasPassed()) {
495 request
->SetRedirectMode(aInit
.mRedirect
.Value());
498 if (aInit
.mIntegrity
.WasPassed()) {
499 request
->SetIntegrity(aInit
.mIntegrity
.Value());
502 if (aInit
.mMozErrors
.WasPassed() && aInit
.mMozErrors
.Value()) {
503 request
->SetMozErrors();
506 // Request constructor step 14.
507 if (aInit
.mMethod
.WasPassed()) {
508 nsAutoCString
method(aInit
.mMethod
.Value());
510 // Step 14.1. Disallow forbidden methods, and anything that is not a HTTP
511 // token, since HTTP states that Method may be any of the defined values or
512 // a token (extension method).
513 nsAutoCString outMethod
;
514 nsresult rv
= FetchUtil::GetValidRequestMethod(method
, outMethod
);
516 aRv
.ThrowTypeError
<MSG_INVALID_REQUEST_METHOD
>(method
);
521 request
->SetMethod(outMethod
);
524 RefPtr
<InternalHeaders
> requestHeaders
= request
->Headers();
526 RefPtr
<InternalHeaders
> headers
;
527 if (aInit
.mHeaders
.WasPassed()) {
528 RefPtr
<Headers
> h
= Headers::Create(aGlobal
, aInit
.mHeaders
.Value(), aRv
);
532 headers
= h
->GetInternalHeaders();
534 headers
= new InternalHeaders(*requestHeaders
);
537 requestHeaders
->Clear();
538 // From "Let r be a new Request object associated with request and a new
539 // Headers object whose guard is "request"."
540 requestHeaders
->SetGuard(HeadersGuardEnum::Request
, aRv
);
541 MOZ_ASSERT(!aRv
.Failed());
543 if (request
->Mode() == RequestMode::No_cors
) {
544 if (!request
->HasSimpleMethod()) {
545 nsAutoCString method
;
546 request
->GetMethod(method
);
547 aRv
.ThrowTypeError
<MSG_INVALID_REQUEST_METHOD
>(method
);
551 requestHeaders
->SetGuard(HeadersGuardEnum::Request_no_cors
, aRv
);
557 requestHeaders
->Fill(*headers
, aRv
);
562 if ((aInit
.mBody
.WasPassed() && !aInit
.mBody
.Value().IsNull()) ||
564 // HEAD and GET are not allowed to have a body.
565 nsAutoCString method
;
566 request
->GetMethod(method
);
567 // method is guaranteed to be uppercase due to step 14.2 above.
568 if (method
.EqualsLiteral("HEAD") || method
.EqualsLiteral("GET")) {
569 aRv
.ThrowTypeError("HEAD or GET Request cannot have a body.");
574 if (aInit
.mBody
.WasPassed()) {
575 const Nullable
<fetch::OwningBodyInit
>& bodyInitNullable
=
577 if (!bodyInitNullable
.IsNull()) {
578 const fetch::OwningBodyInit
& bodyInit
= bodyInitNullable
.Value();
579 nsCOMPtr
<nsIInputStream
> stream
;
580 nsAutoCString contentTypeWithCharset
;
581 uint64_t contentLength
= 0;
582 aRv
= ExtractByteStreamFromBody(bodyInit
, getter_AddRefs(stream
),
583 contentTypeWithCharset
, contentLength
);
584 if (NS_WARN_IF(aRv
.Failed())) {
588 nsCOMPtr
<nsIInputStream
> temporaryBody
= stream
;
590 if (!contentTypeWithCharset
.IsVoid() &&
591 !requestHeaders
->Has("Content-Type"_ns
, aRv
)) {
592 requestHeaders
->Append("Content-Type"_ns
, contentTypeWithCharset
, aRv
);
595 if (NS_WARN_IF(aRv
.Failed())) {
600 request
->SetBody(nullptr, 0);
603 request
->SetBody(temporaryBody
, contentLength
);
608 MakeSafeRefPtr
<Request
>(aGlobal
, std::move(request
), signal
);
610 if (aInput
.IsRequest()) {
611 RefPtr
<Request
> inputReq
= &aInput
.GetAsRequest();
612 nsCOMPtr
<nsIInputStream
> body
;
613 inputReq
->GetBody(getter_AddRefs(body
));
615 inputReq
->SetBody(nullptr, 0);
616 inputReq
->SetBodyUsed(aCx
, aRv
);
617 if (NS_WARN_IF(aRv
.Failed())) {
625 SafeRefPtr
<Request
> Request::Clone(ErrorResult
& aRv
) {
626 bool used
= GetBodyUsed(aRv
);
627 if (NS_WARN_IF(aRv
.Failed())) {
631 aRv
.ThrowTypeError
<MSG_FETCH_BODY_CONSUMED_ERROR
>();
635 SafeRefPtr
<InternalRequest
> ir
= mRequest
->Clone();
637 aRv
.Throw(NS_ERROR_FAILURE
);
641 return MakeSafeRefPtr
<Request
>(mOwner
, std::move(ir
), GetOrCreateSignal());
644 Headers
* Request::Headers_() {
646 mHeaders
= new Headers(mOwner
, mRequest
->Headers());
652 AbortSignal
* Request::GetOrCreateSignal() {
654 mSignal
= new AbortSignal(mOwner
, false);
660 AbortSignalImpl
* Request::GetSignalImpl() const { return mSignal
; }
662 } // namespace mozilla::dom