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 nsACString
& aInput
,
83 MOZ_ASSERT(aDocument
);
84 MOZ_ASSERT(NS_IsMainThread());
86 nsCOMPtr
<nsIURI
> resolvedURI
;
87 nsresult rv
= NS_NewURI(getter_AddRefs(resolvedURI
), aInput
, nullptr,
88 aDocument
->GetBaseURI());
89 if (NS_WARN_IF(NS_FAILED(rv
))) {
90 aRv
.ThrowTypeError
<MSG_INVALID_URL
>(aInput
);
92 return resolvedURI
.forget();
94 void GetRequestURLFromDocument(Document
* aDocument
, const nsACString
& aInput
,
95 nsACString
& aRequestURL
,
96 nsACString
& aURLfragment
, ErrorResult
& aRv
) {
97 nsCOMPtr
<nsIURI
> resolvedURI
= ParseURLFromDocument(aDocument
, aInput
, aRv
);
101 // This fails with URIs with weird protocols, even when they are valid,
102 // so we ignore the failure
103 nsAutoCString credentials
;
104 Unused
<< resolvedURI
->GetUserPass(credentials
);
105 if (!credentials
.IsEmpty()) {
106 aRv
.ThrowTypeError
<MSG_URL_HAS_CREDENTIALS
>(aInput
);
110 nsCOMPtr
<nsIURI
> resolvedURIClone
;
111 aRv
= NS_GetURIWithoutRef(resolvedURI
, getter_AddRefs(resolvedURIClone
));
112 if (NS_WARN_IF(aRv
.Failed())) {
115 aRv
= resolvedURIClone
->GetSpec(aRequestURL
);
116 if (NS_WARN_IF(aRv
.Failed())) {
120 // Get the fragment from nsIURI.
121 aRv
= resolvedURI
->GetRef(aURLfragment
);
122 if (NS_WARN_IF(aRv
.Failed())) {
126 already_AddRefed
<nsIURI
> ParseURLFromChrome(const nsACString
& aInput
,
128 MOZ_ASSERT(NS_IsMainThread());
130 nsCOMPtr
<nsIURI
> uri
;
131 nsresult rv
= NS_NewURI(getter_AddRefs(uri
), aInput
);
133 aRv
.ThrowTypeError
<MSG_INVALID_URL
>(aInput
);
137 void GetRequestURLFromChrome(const nsACString
& aInput
, nsACString
& aRequestURL
,
138 nsACString
& aURLfragment
, ErrorResult
& aRv
) {
139 nsCOMPtr
<nsIURI
> uri
= ParseURLFromChrome(aInput
, aRv
);
143 // This fails with URIs with weird protocols, even when they are valid,
144 // so we ignore the failure
145 nsAutoCString credentials
;
146 Unused
<< uri
->GetUserPass(credentials
);
147 if (!credentials
.IsEmpty()) {
148 aRv
.ThrowTypeError
<MSG_URL_HAS_CREDENTIALS
>(aInput
);
152 nsCOMPtr
<nsIURI
> uriClone
;
153 aRv
= NS_GetURIWithoutRef(uri
, getter_AddRefs(uriClone
));
154 if (NS_WARN_IF(aRv
.Failed())) {
157 aRv
= uriClone
->GetSpec(aRequestURL
);
158 if (NS_WARN_IF(aRv
.Failed())) {
162 // Get the fragment from nsIURI.
163 aRv
= uri
->GetRef(aURLfragment
);
164 if (NS_WARN_IF(aRv
.Failed())) {
168 already_AddRefed
<URL
> ParseURLFromWorker(nsIGlobalObject
* aGlobal
,
169 const nsACString
& aInput
,
171 WorkerPrivate
* worker
= GetCurrentThreadWorkerPrivate();
173 worker
->AssertIsOnWorkerThread();
175 const auto& baseURL
= worker
->GetLocationInfo().mHref
;
176 RefPtr
<URL
> url
= URL::Constructor(aGlobal
, aInput
, baseURL
, aRv
);
177 if (NS_WARN_IF(aRv
.Failed())) {
178 aRv
.ThrowTypeError
<MSG_INVALID_URL
>(aInput
);
182 void GetRequestURLFromWorker(nsIGlobalObject
* aGlobal
, const nsACString
& aInput
,
183 nsACString
& aRequestURL
, nsACString
& aURLfragment
,
185 RefPtr
<URL
> url
= ParseURLFromWorker(aGlobal
, aInput
, aRv
);
190 url
->GetUsername(username
);
193 url
->GetPassword(password
);
195 if (!username
.IsEmpty() || !password
.IsEmpty()) {
196 aRv
.ThrowTypeError
<MSG_URL_HAS_CREDENTIALS
>(aInput
);
200 // Get the fragment from URL.
201 nsAutoCString fragment
;
202 url
->GetHash(fragment
);
204 // Note: URL::GetHash() includes the "#" and we want the fragment with out
206 if (!fragment
.IsEmpty()) {
207 aURLfragment
= Substring(fragment
, 1);
211 url
->GetHref(aRequestURL
);
214 class ReferrerSameOriginChecker final
: public WorkerMainThreadRunnable
{
216 ReferrerSameOriginChecker(WorkerPrivate
* aWorkerPrivate
,
217 const nsACString
& aReferrerURL
, nsresult
& aResult
)
218 : WorkerMainThreadRunnable(aWorkerPrivate
,
219 "Fetch :: Referrer same origin check"_ns
),
220 mReferrerURL(aReferrerURL
),
222 mWorkerPrivate
->AssertIsOnWorkerThread();
225 bool MainThreadRun() override
{
226 nsCOMPtr
<nsIURI
> uri
;
227 if (NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri
), mReferrerURL
))) {
228 if (nsCOMPtr
<nsIPrincipal
> principal
= mWorkerPrivate
->GetPrincipal()) {
229 mResult
= principal
->CheckMayLoad(uri
,
230 /* allowIfInheritsPrincipal */ false);
237 const nsCString mReferrerURL
;
244 SafeRefPtr
<Request
> Request::Constructor(const GlobalObject
& aGlobal
,
245 const RequestOrUTF8String
& aInput
,
246 const RequestInit
& aInit
,
248 nsCOMPtr
<nsIGlobalObject
> global
= do_QueryInterface(aGlobal
.GetAsSupports());
249 return Constructor(global
, aGlobal
.Context(), aInput
, aInit
,
250 aGlobal
.CallerType(), aRv
);
254 SafeRefPtr
<Request
> Request::Constructor(
255 nsIGlobalObject
* aGlobal
, JSContext
* aCx
, const RequestOrUTF8String
& aInput
,
256 const RequestInit
& aInit
, CallerType aCallerType
, ErrorResult
& aRv
) {
257 bool hasCopiedBody
= false;
258 SafeRefPtr
<InternalRequest
> request
;
260 RefPtr
<AbortSignal
> signal
;
261 bool bodyFromInit
= false;
263 if (aInput
.IsRequest()) {
264 RefPtr
<Request
> inputReq
= &aInput
.GetAsRequest();
265 nsCOMPtr
<nsIInputStream
> body
;
267 if (aInit
.mBody
.WasPassed() && !aInit
.mBody
.Value().IsNull()) {
269 hasCopiedBody
= true;
271 inputReq
->GetBody(getter_AddRefs(body
));
272 if (inputReq
->BodyUsed()) {
273 aRv
.ThrowTypeError
<MSG_FETCH_BODY_CONSUMED_ERROR
>();
277 // The body will be copied when GetRequestConstructorCopy() is executed.
279 hasCopiedBody
= true;
283 request
= inputReq
->GetInternalRequest();
284 signal
= inputReq
->GetOrCreateSignal();
286 // aInput is UTF8String.
287 // We need to get url before we create a InternalRequest.
288 const nsACString
& input
= aInput
.GetAsUTF8String();
289 nsAutoCString requestURL
;
291 if (NS_IsMainThread()) {
292 nsCOMPtr
<nsPIDOMWindowInner
> inner(do_QueryInterface(aGlobal
));
293 Document
* doc
= inner
? inner
->GetExtantDoc() : nullptr;
295 GetRequestURLFromDocument(doc
, input
, requestURL
, fragment
, aRv
);
297 // If we don't have a document, we must assume that this is a full URL.
298 GetRequestURLFromChrome(input
, requestURL
, fragment
, aRv
);
301 GetRequestURLFromWorker(aGlobal
, input
, requestURL
, fragment
, aRv
);
306 request
= MakeSafeRefPtr
<InternalRequest
>(requestURL
, fragment
);
308 request
= request
->GetRequestConstructorCopy(aGlobal
, aRv
);
309 if (NS_WARN_IF(aRv
.Failed())) {
312 Maybe
<RequestMode
> mode
;
313 if (aInit
.mMode
.WasPassed()) {
314 if (aInit
.mMode
.Value() == RequestMode::Navigate
) {
315 aRv
.ThrowTypeError
<MSG_INVALID_REQUEST_MODE
>("navigate");
319 mode
.emplace(aInit
.mMode
.Value());
321 Maybe
<RequestCredentials
> credentials
;
322 if (aInit
.mCredentials
.WasPassed()) {
323 credentials
.emplace(aInit
.mCredentials
.Value());
325 Maybe
<RequestCache
> cache
;
326 if (aInit
.mCache
.WasPassed()) {
327 cache
.emplace(aInit
.mCache
.Value());
329 if (aInput
.IsUTF8String()) {
330 if (mode
.isNothing()) {
331 mode
.emplace(RequestMode::Cors
);
333 if (credentials
.isNothing()) {
334 if (aCallerType
== CallerType::System
&&
335 StaticPrefs::network_fetch_systemDefaultsToOmittingCredentials()) {
336 credentials
.emplace(RequestCredentials::Omit
);
338 credentials
.emplace(RequestCredentials::Same_origin
);
341 if (cache
.isNothing()) {
342 cache
.emplace(RequestCache::Default
);
346 if (aInit
.IsAnyMemberPresent() && request
->Mode() == RequestMode::Navigate
) {
347 mode
= Some(RequestMode::Same_origin
);
350 if (aInit
.IsAnyMemberPresent()) {
351 request
->SetReferrer(nsLiteralCString(kFETCH_CLIENT_REFERRER_STR
));
352 request
->SetReferrerPolicy(ReferrerPolicy::_empty
);
354 if (aInit
.mReferrer
.WasPassed()) {
355 const nsCString
& referrer
= aInit
.mReferrer
.Value();
356 if (referrer
.IsEmpty()) {
357 request
->SetReferrer(""_ns
);
359 nsAutoCString referrerURL
;
360 if (NS_IsMainThread()) {
361 nsCOMPtr
<nsPIDOMWindowInner
> inner(do_QueryInterface(aGlobal
));
362 Document
* doc
= inner
? inner
->GetExtantDoc() : nullptr;
363 nsCOMPtr
<nsIURI
> uri
;
365 uri
= ParseURLFromDocument(doc
, referrer
, aRv
);
367 // If we don't have a document, we must assume that this is a full
369 uri
= ParseURLFromChrome(referrer
, aRv
);
371 if (NS_WARN_IF(aRv
.Failed())) {
372 aRv
.ThrowTypeError
<MSG_INVALID_REFERRER_URL
>(referrer
);
375 uri
->GetSpec(referrerURL
);
376 if (!referrerURL
.EqualsLiteral(kFETCH_CLIENT_REFERRER_STR
)) {
377 nsCOMPtr
<nsIPrincipal
> principal
= aGlobal
->PrincipalOrNull();
380 principal
->CheckMayLoad(uri
,
381 /* allowIfInheritsPrincipal */ false);
383 referrerURL
.AssignLiteral(kFETCH_CLIENT_REFERRER_STR
);
388 RefPtr
<URL
> url
= ParseURLFromWorker(aGlobal
, referrer
, aRv
);
389 if (NS_WARN_IF(aRv
.Failed())) {
390 aRv
.ThrowTypeError
<MSG_INVALID_REFERRER_URL
>(referrer
);
393 url
->GetHref(referrerURL
);
394 if (!referrerURL
.EqualsLiteral(kFETCH_CLIENT_REFERRER_STR
)) {
395 WorkerPrivate
* worker
= GetCurrentThreadWorkerPrivate();
397 // ReferrerSameOriginChecker uses a sync loop to get the main thread
398 // to perform the same-origin check. Overall, on Workers this method
399 // can create 3 sync loops (two for constructing URLs and one here) so
400 // in the future we may want to optimize it all by off-loading all of
401 // this work in a single sync loop.
402 RefPtr
<ReferrerSameOriginChecker
> checker
=
403 new ReferrerSameOriginChecker(worker
, referrerURL
, rv
);
404 IgnoredErrorResult error
;
405 checker
->Dispatch(Canceling
, error
);
406 if (error
.Failed() || NS_FAILED(rv
)) {
407 referrerURL
.AssignLiteral(kFETCH_CLIENT_REFERRER_STR
);
411 request
->SetReferrer(referrerURL
);
415 if (aInit
.mReferrerPolicy
.WasPassed()) {
416 request
->SetReferrerPolicy(aInit
.mReferrerPolicy
.Value());
419 if (aInit
.mSignal
.WasPassed()) {
420 signal
= aInit
.mSignal
.Value();
423 // https://fetch.spec.whatwg.org/#dom-global-fetch
424 // https://fetch.spec.whatwg.org/#dom-request
425 // The priority of init overrides input's priority.
426 if (aInit
.mPriority
.WasPassed()) {
427 request
->SetPriorityMode(aInit
.mPriority
.Value());
430 UniquePtr
<mozilla::ipc::PrincipalInfo
> principalInfo
;
431 nsILoadInfo::CrossOriginEmbedderPolicy coep
=
432 nsILoadInfo::EMBEDDER_POLICY_NULL
;
434 if (NS_IsMainThread()) {
435 nsCOMPtr
<nsPIDOMWindowInner
> window
= do_QueryInterface(aGlobal
);
437 nsCOMPtr
<Document
> doc
;
438 doc
= window
->GetExtantDoc();
440 request
->SetEnvironmentReferrerPolicy(doc
->GetReferrerPolicy());
442 principalInfo
.reset(new mozilla::ipc::PrincipalInfo());
444 PrincipalToPrincipalInfo(doc
->NodePrincipal(), principalInfo
.get());
445 if (NS_WARN_IF(NS_FAILED(rv
))) {
446 aRv
.ThrowTypeError
<MSG_FETCH_BODY_CONSUMED_ERROR
>();
450 if (window
->GetWindowContext()) {
451 coep
= window
->GetWindowContext()->GetEmbedderPolicy();
455 WorkerPrivate
* worker
= GetCurrentThreadWorkerPrivate();
457 worker
->AssertIsOnWorkerThread();
458 request
->SetEnvironmentReferrerPolicy(worker
->GetReferrerPolicy());
460 MakeUnique
<mozilla::ipc::PrincipalInfo
>(worker
->GetPrincipalInfo());
461 coep
= worker
->GetEmbedderPolicy();
462 // For dedicated worker, the response must respect the owner's COEP.
463 if (coep
== nsILoadInfo::EMBEDDER_POLICY_NULL
&&
464 worker
->IsDedicatedWorker()) {
465 coep
= worker
->GetOwnerEmbedderPolicy();
470 request
->SetPrincipalInfo(std::move(principalInfo
));
471 request
->SetEmbedderPolicy(coep
);
474 request
->SetMode(mode
.value());
477 if (credentials
.isSome()) {
478 request
->SetCredentialsMode(credentials
.value());
481 if (cache
.isSome()) {
482 if (cache
.value() == RequestCache::Only_if_cached
&&
483 request
->Mode() != RequestMode::Same_origin
) {
484 aRv
.ThrowTypeError
<MSG_ONLY_IF_CACHED_WITHOUT_SAME_ORIGIN
>(
485 GetEnumString(request
->Mode()));
488 request
->SetCacheMode(cache
.value());
491 if (aInit
.mRedirect
.WasPassed()) {
492 request
->SetRedirectMode(aInit
.mRedirect
.Value());
495 if (aInit
.mIntegrity
.WasPassed()) {
496 request
->SetIntegrity(aInit
.mIntegrity
.Value());
499 if (aInit
.mKeepalive
.WasPassed()) {
500 request
->SetKeepalive(aInit
.mKeepalive
.Value());
503 if (aInit
.mMozErrors
.WasPassed() && aInit
.mMozErrors
.Value()) {
504 request
->SetMozErrors();
507 // Request constructor step 14.
508 if (aInit
.mMethod
.WasPassed()) {
509 nsAutoCString
method(aInit
.mMethod
.Value());
511 // Step 14.1. Disallow forbidden methods, and anything that is not a HTTP
512 // token, since HTTP states that Method may be any of the defined values or
513 // a token (extension method).
514 nsAutoCString outMethod
;
515 nsresult rv
= FetchUtil::GetValidRequestMethod(method
, outMethod
);
517 aRv
.ThrowTypeError
<MSG_INVALID_REQUEST_METHOD
>(method
);
522 request
->SetMethod(outMethod
);
525 RefPtr
<InternalHeaders
> requestHeaders
= request
->Headers();
527 RefPtr
<InternalHeaders
> headers
;
528 if (aInit
.mHeaders
.WasPassed()) {
529 RefPtr
<Headers
> h
= Headers::Create(aGlobal
, aInit
.mHeaders
.Value(), aRv
);
533 headers
= h
->GetInternalHeaders();
535 headers
= new InternalHeaders(*requestHeaders
);
538 requestHeaders
->Clear();
539 // From "Let r be a new Request object associated with request and a new
540 // Headers object whose guard is "request"."
541 requestHeaders
->SetGuard(HeadersGuardEnum::Request
, aRv
);
542 MOZ_ASSERT(!aRv
.Failed());
544 if (request
->Mode() == RequestMode::No_cors
) {
545 if (!request
->HasSimpleMethod()) {
546 nsAutoCString method
;
547 request
->GetMethod(method
);
548 aRv
.ThrowTypeError
<MSG_INVALID_REQUEST_METHOD
>(method
);
552 requestHeaders
->SetGuard(HeadersGuardEnum::Request_no_cors
, aRv
);
558 requestHeaders
->Fill(*headers
, aRv
);
563 if ((aInit
.mBody
.WasPassed() && !aInit
.mBody
.Value().IsNull()) ||
565 // HEAD and GET are not allowed to have a body.
566 nsAutoCString method
;
567 request
->GetMethod(method
);
568 // method is guaranteed to be uppercase due to step 14.2 above.
569 if (method
.EqualsLiteral("HEAD") || method
.EqualsLiteral("GET")) {
570 aRv
.ThrowTypeError("HEAD or GET Request cannot have a body.");
575 if (aInit
.mBody
.WasPassed()) {
576 const Nullable
<fetch::OwningBodyInit
>& bodyInitNullable
=
578 if (!bodyInitNullable
.IsNull()) {
579 const fetch::OwningBodyInit
& bodyInit
= bodyInitNullable
.Value();
580 nsCOMPtr
<nsIInputStream
> stream
;
581 nsAutoCString contentTypeWithCharset
;
582 uint64_t contentLength
= 0;
583 aRv
= ExtractByteStreamFromBody(bodyInit
, getter_AddRefs(stream
),
584 contentTypeWithCharset
, contentLength
);
585 if (NS_WARN_IF(aRv
.Failed())) {
589 nsCOMPtr
<nsIInputStream
> temporaryBody
= stream
;
591 if (!contentTypeWithCharset
.IsVoid() &&
592 !requestHeaders
->Has("Content-Type"_ns
, aRv
)) {
593 requestHeaders
->Append("Content-Type"_ns
, contentTypeWithCharset
, aRv
);
596 if (NS_WARN_IF(aRv
.Failed())) {
601 request
->SetBody(nullptr, 0);
604 request
->SetBody(temporaryBody
, contentLength
);
609 MakeSafeRefPtr
<Request
>(aGlobal
, std::move(request
), signal
);
611 if (aInput
.IsRequest() && !bodyFromInit
) {
612 RefPtr
<Request
> inputReq
= &aInput
.GetAsRequest();
613 nsCOMPtr
<nsIInputStream
> body
;
614 inputReq
->GetBody(getter_AddRefs(body
));
616 inputReq
->SetBody(nullptr, 0);
617 inputReq
->SetBodyUsed(aCx
, aRv
);
618 if (NS_WARN_IF(aRv
.Failed())) {
626 SafeRefPtr
<Request
> Request::Clone(ErrorResult
& aRv
) {
628 aRv
.ThrowTypeError
<MSG_FETCH_BODY_CONSUMED_ERROR
>();
632 SafeRefPtr
<InternalRequest
> ir
= mRequest
->Clone();
634 aRv
.Throw(NS_ERROR_FAILURE
);
638 return MakeSafeRefPtr
<Request
>(mOwner
, std::move(ir
), GetOrCreateSignal());
641 Headers
* Request::Headers_() {
643 mHeaders
= new Headers(mOwner
, mRequest
->Headers());
649 AbortSignal
* Request::GetOrCreateSignal() {
651 mSignal
= new AbortSignal(mOwner
, false, JS::UndefinedHandleValue
);
657 AbortSignalImpl
* Request::GetSignalImpl() const { return mSignal
; }
659 AbortSignalImpl
* Request::GetSignalImplToConsumeBody() const {
660 // This is a hack, see Response::GetSignalImplToConsumeBody.
664 } // namespace mozilla::dom