123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652 |
- /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- #include "Request.h"
- #include "nsIURI.h"
- #include "nsNetUtil.h"
- #include "nsPIDOMWindow.h"
- #include "mozilla/ErrorResult.h"
- #include "mozilla/dom/Headers.h"
- #include "mozilla/dom/Fetch.h"
- #include "mozilla/dom/FetchUtil.h"
- #include "mozilla/dom/Promise.h"
- #include "mozilla/dom/URL.h"
- #include "mozilla/Unused.h"
- #include "WorkerPrivate.h"
- #include "WorkerRunnable.h"
- #include "WorkerScope.h"
- #include "Workers.h"
- namespace mozilla {
- namespace dom {
- using namespace workers;
- NS_IMPL_CYCLE_COLLECTING_ADDREF(Request)
- NS_IMPL_CYCLE_COLLECTING_RELEASE(Request)
- NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Request, mOwner, mHeaders)
- NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Request)
- NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
- NS_INTERFACE_MAP_ENTRY(nsISupports)
- NS_INTERFACE_MAP_END
- Request::Request(nsIGlobalObject* aOwner, InternalRequest* aRequest, AbortSignal* aSignal)
- : FetchBody<Request>()
- , mOwner(aOwner)
- , mRequest(aRequest)
- , mSignal(aSignal)
- {
- MOZ_ASSERT(aRequest->Headers()->Guard() == HeadersGuardEnum::Immutable ||
- aRequest->Headers()->Guard() == HeadersGuardEnum::Request ||
- aRequest->Headers()->Guard() == HeadersGuardEnum::Request_no_cors);
- SetMimeType();
-
- // aSignal can be null.
- }
- Request::~Request()
- {
- }
- // static
- bool
- Request::RequestContextEnabled(JSContext* aCx, JSObject* aObj)
- {
- if (NS_IsMainThread()) {
- return Preferences::GetBool("dom.requestcontext.enabled", false);
- }
- using namespace workers;
- // Otherwise, check the pref via the WorkerPrivate
- WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
- if (!workerPrivate) {
- return false;
- }
- return workerPrivate->RequestContextEnabled();
- }
- already_AddRefed<InternalRequest>
- Request::GetInternalRequest()
- {
- RefPtr<InternalRequest> r = mRequest;
- return r.forget();
- }
- namespace {
- already_AddRefed<nsIURI>
- ParseURLFromDocument(nsIDocument* aDocument, const nsAString& aInput,
- ErrorResult& aRv)
- {
- MOZ_ASSERT(aDocument);
- MOZ_ASSERT(NS_IsMainThread());
- nsCOMPtr<nsIURI> baseURI = aDocument->GetBaseURI();
- nsCOMPtr<nsIURI> resolvedURI;
- aRv = NS_NewURI(getter_AddRefs(resolvedURI), aInput, nullptr, baseURI);
- if (NS_WARN_IF(aRv.Failed())) {
- aRv.ThrowTypeError<MSG_INVALID_URL>(aInput);
- }
- return resolvedURI.forget();
- }
- void
- GetRequestURLFromDocument(nsIDocument* aDocument, const nsAString& aInput,
- nsAString& aRequestURL, nsACString& aURLfragment,
- ErrorResult& aRv)
- {
- nsCOMPtr<nsIURI> resolvedURI = ParseURLFromDocument(aDocument, aInput, aRv);
- if (aRv.Failed()) {
- return;
- }
- // This fails with URIs with weird protocols, even when they are valid,
- // so we ignore the failure
- nsAutoCString credentials;
- Unused << resolvedURI->GetUserPass(credentials);
- if (!credentials.IsEmpty()) {
- aRv.ThrowTypeError<MSG_URL_HAS_CREDENTIALS>(aInput);
- return;
- }
- nsCOMPtr<nsIURI> resolvedURIClone;
- // We use CloneIgnoringRef to strip away the fragment even if the original URI
- // is immutable.
- aRv = resolvedURI->CloneIgnoringRef(getter_AddRefs(resolvedURIClone));
- if (NS_WARN_IF(aRv.Failed())) {
- return;
- }
- nsAutoCString spec;
- aRv = resolvedURIClone->GetSpec(spec);
- if (NS_WARN_IF(aRv.Failed())) {
- return;
- }
- CopyUTF8toUTF16(spec, aRequestURL);
- // Get the fragment from nsIURI.
- aRv = resolvedURI->GetRef(aURLfragment);
- if (NS_WARN_IF(aRv.Failed())) {
- return;
- }
- }
- already_AddRefed<nsIURI>
- ParseURLFromChrome(const nsAString& aInput, ErrorResult& aRv)
- {
- MOZ_ASSERT(NS_IsMainThread());
- nsCOMPtr<nsIURI> uri;
- aRv = NS_NewURI(getter_AddRefs(uri), aInput, nullptr, nullptr);
- if (NS_WARN_IF(aRv.Failed())) {
- aRv.ThrowTypeError<MSG_INVALID_URL>(aInput);
- }
- return uri.forget();
- }
- void
- GetRequestURLFromChrome(const nsAString& aInput, nsAString& aRequestURL,
- nsACString& aURLfragment, ErrorResult& aRv)
- {
- nsCOMPtr<nsIURI> uri = ParseURLFromChrome(aInput, aRv);
- if (aRv.Failed()) {
- return;
- }
- // This fails with URIs with weird protocols, even when they are valid,
- // so we ignore the failure
- nsAutoCString credentials;
- Unused << uri->GetUserPass(credentials);
- if (!credentials.IsEmpty()) {
- aRv.ThrowTypeError<MSG_URL_HAS_CREDENTIALS>(aInput);
- return;
- }
- nsCOMPtr<nsIURI> uriClone;
- // We use CloneIgnoringRef to strip away the fragment even if the original URI
- // is immutable.
- aRv = uri->CloneIgnoringRef(getter_AddRefs(uriClone));
- if (NS_WARN_IF(aRv.Failed())) {
- return;
- }
- nsAutoCString spec;
- aRv = uriClone->GetSpec(spec);
- if (NS_WARN_IF(aRv.Failed())) {
- return;
- }
- CopyUTF8toUTF16(spec, aRequestURL);
- // Get the fragment from nsIURI.
- aRv = uri->GetRef(aURLfragment);
- if (NS_WARN_IF(aRv.Failed())) {
- return;
- }
- }
- already_AddRefed<URL>
- ParseURLFromWorker(const GlobalObject& aGlobal, const nsAString& aInput,
- ErrorResult& aRv)
- {
- workers::WorkerPrivate* worker = workers::GetCurrentThreadWorkerPrivate();
- MOZ_ASSERT(worker);
- worker->AssertIsOnWorkerThread();
- NS_ConvertUTF8toUTF16 baseURL(worker->GetLocationInfo().mHref);
- RefPtr<URL> url = URL::WorkerConstructor(aGlobal, aInput, baseURL, aRv);
- if (NS_WARN_IF(aRv.Failed())) {
- aRv.ThrowTypeError<MSG_INVALID_URL>(aInput);
- }
- return url.forget();
- }
- void
- GetRequestURLFromWorker(const GlobalObject& aGlobal, const nsAString& aInput,
- nsAString& aRequestURL, nsACString& aURLfragment,
- ErrorResult& aRv)
- {
- RefPtr<URL> url = ParseURLFromWorker(aGlobal, aInput, aRv);
- if (aRv.Failed()) {
- return;
- }
- nsString username;
- url->GetUsername(username, aRv);
- if (NS_WARN_IF(aRv.Failed())) {
- return;
- }
- nsString password;
- url->GetPassword(password, aRv);
- if (NS_WARN_IF(aRv.Failed())) {
- return;
- }
- if (!username.IsEmpty() || !password.IsEmpty()) {
- aRv.ThrowTypeError<MSG_URL_HAS_CREDENTIALS>(aInput);
- return;
- }
- // Get the fragment from URL.
- nsAutoString fragment;
- url->GetHash(fragment, aRv);
- if (NS_WARN_IF(aRv.Failed())) {
- return;
- }
- // Note: URL::GetHash() includes the "#" and we want the fragment with out
- // the hash symbol.
- if (!fragment.IsEmpty()) {
- CopyUTF16toUTF8(Substring(fragment, 1), aURLfragment);
- }
- url->SetHash(EmptyString(), aRv);
- if (NS_WARN_IF(aRv.Failed())) {
- return;
- }
- url->Stringify(aRequestURL, aRv);
- if (NS_WARN_IF(aRv.Failed())) {
- return;
- }
- }
- class ReferrerSameOriginChecker final : public WorkerMainThreadRunnable
- {
- public:
- ReferrerSameOriginChecker(workers::WorkerPrivate* aWorkerPrivate,
- const nsAString& aReferrerURL,
- nsresult& aResult)
- : WorkerMainThreadRunnable(aWorkerPrivate,
- NS_LITERAL_CSTRING("Fetch :: Referrer same origin check")),
- mReferrerURL(aReferrerURL),
- mResult(aResult)
- {
- mWorkerPrivate->AssertIsOnWorkerThread();
- }
- bool
- MainThreadRun() override
- {
- nsCOMPtr<nsIURI> uri;
- if (NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), mReferrerURL))) {
- nsCOMPtr<nsIPrincipal> principal = mWorkerPrivate->GetPrincipal();
- if (principal) {
- mResult = principal->CheckMayLoad(uri, /* report */ false,
- /* allowIfInheritsPrincipal */ false);
- }
- }
- return true;
- }
- private:
- const nsString mReferrerURL;
- nsresult& mResult;
- };
- } // namespace
- /*static*/ already_AddRefed<Request>
- Request::Constructor(const GlobalObject& aGlobal,
- const RequestOrUSVString& aInput,
- const RequestInit& aInit, ErrorResult& aRv)
- {
- nsCOMPtr<nsIInputStream> temporaryBody;
- RefPtr<InternalRequest> request;
- nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
-
- RefPtr<AbortSignal> signal;
- if (aInput.IsRequest()) {
- RefPtr<Request> inputReq = &aInput.GetAsRequest();
- nsCOMPtr<nsIInputStream> body;
- inputReq->GetBody(getter_AddRefs(body));
- if (inputReq->BodyUsed()) {
- aRv.ThrowTypeError<MSG_FETCH_BODY_CONSUMED_ERROR>();
- return nullptr;
- }
- if (body) {
- temporaryBody = body;
- }
- request = inputReq->GetInternalRequest();
- signal = inputReq->GetOrCreateSignal();
- } else {
- // aInput is USVString.
- // We need to get url before we create a InternalRequest.
- nsAutoString input;
- input.Assign(aInput.GetAsUSVString());
- nsAutoString requestURL;
- nsCString fragment;
- if (NS_IsMainThread()) {
- nsIDocument* doc = GetEntryDocument();
- if (doc) {
- GetRequestURLFromDocument(doc, input, requestURL, fragment, aRv);
- } else {
- // If we don't have a document, we must assume that this is a full URL.
- GetRequestURLFromChrome(input, requestURL, fragment, aRv);
- }
- } else {
- GetRequestURLFromWorker(aGlobal, input, requestURL, fragment, aRv);
- }
- if (NS_WARN_IF(aRv.Failed())) {
- return nullptr;
- }
- request = new InternalRequest(NS_ConvertUTF16toUTF8(requestURL), fragment);
- }
- request = request->GetRequestConstructorCopy(global, aRv);
- if (NS_WARN_IF(aRv.Failed())) {
- return nullptr;
- }
- RequestMode fallbackMode = RequestMode::EndGuard_;
- RequestCredentials fallbackCredentials = RequestCredentials::EndGuard_;
- RequestCache fallbackCache = RequestCache::EndGuard_;
- if (aInput.IsUSVString()) {
- fallbackMode = RequestMode::Cors;
- fallbackCredentials = RequestCredentials::Same_origin;
- fallbackCache = RequestCache::Default;
- }
- RequestMode mode = aInit.mMode.WasPassed() ? aInit.mMode.Value() : fallbackMode;
- RequestCredentials credentials =
- aInit.mCredentials.WasPassed() ? aInit.mCredentials.Value()
- : fallbackCredentials;
- if (mode == RequestMode::Navigate ||
- (aInit.IsAnyMemberPresent() && request->Mode() == RequestMode::Navigate)) {
- mode = RequestMode::Same_origin;
- }
- if (aInit.IsAnyMemberPresent()) {
- request->SetReferrer(NS_LITERAL_STRING(kFETCH_CLIENT_REFERRER_STR));
- request->SetReferrerPolicy(ReferrerPolicy::_empty);
- }
- if (aInit.mReferrer.WasPassed()) {
- const nsString& referrer = aInit.mReferrer.Value();
- if (referrer.IsEmpty()) {
- request->SetReferrer(NS_LITERAL_STRING(""));
- } else {
- nsAutoString referrerURL;
- if (NS_IsMainThread()) {
- nsIDocument* doc = GetEntryDocument();
- nsCOMPtr<nsIURI> uri;
- if (doc) {
- uri = ParseURLFromDocument(doc, referrer, aRv);
- } else {
- // If we don't have a document, we must assume that this is a full URL.
- uri = ParseURLFromChrome(referrer, aRv);
- }
- if (NS_WARN_IF(aRv.Failed())) {
- aRv.ThrowTypeError<MSG_INVALID_REFERRER_URL>(referrer);
- return nullptr;
- }
- nsAutoCString spec;
- uri->GetSpec(spec);
- CopyUTF8toUTF16(spec, referrerURL);
- if (!referrerURL.EqualsLiteral(kFETCH_CLIENT_REFERRER_STR)) {
- nsCOMPtr<nsIPrincipal> principal = global->PrincipalOrNull();
- if (principal) {
- nsresult rv = principal->CheckMayLoad(uri, /* report */ false,
- /* allowIfInheritsPrincipal */ false);
- if (NS_FAILED(rv)) {
- referrerURL.AssignLiteral(kFETCH_CLIENT_REFERRER_STR);
- }
- }
- }
- } else {
- RefPtr<URL> url = ParseURLFromWorker(aGlobal, referrer, aRv);
- if (NS_WARN_IF(aRv.Failed())) {
- aRv.ThrowTypeError<MSG_INVALID_REFERRER_URL>(referrer);
- return nullptr;
- }
- url->Stringify(referrerURL, aRv);
- if (NS_WARN_IF(aRv.Failed())) {
- aRv.ThrowTypeError<MSG_INVALID_REFERRER_URL>(referrer);
- return nullptr;
- }
- if (!referrerURL.EqualsLiteral(kFETCH_CLIENT_REFERRER_STR)) {
- workers::WorkerPrivate* worker = workers::GetCurrentThreadWorkerPrivate();
- nsresult rv = NS_OK;
- // ReferrerSameOriginChecker uses a sync loop to get the main thread
- // to perform the same-origin check. Overall, on Workers this method
- // can create 3 sync loops (two for constructing URLs and one here) so
- // in the future we may want to optimize it all by off-loading all of
- // this work in a single sync loop.
- RefPtr<ReferrerSameOriginChecker> checker =
- new ReferrerSameOriginChecker(worker, referrerURL, rv);
- IgnoredErrorResult error;
- checker->Dispatch(Terminating, error);
- if (error.Failed() || NS_FAILED(rv)) {
- referrerURL.AssignLiteral(kFETCH_CLIENT_REFERRER_STR);
- }
- }
- }
- request->SetReferrer(referrerURL);
- }
- }
- if (aInit.mReferrerPolicy.WasPassed()) {
- request->SetReferrerPolicy(aInit.mReferrerPolicy.Value());
- }
- if (aInit.mSignal.WasPassed()) {
- signal = aInit.mSignal.Value();
- }
- if (NS_IsMainThread()) {
- nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(global);
- if (window) {
- nsCOMPtr<nsIDocument> doc;
- doc = window->GetExtantDoc();
- if (doc) {
- request->SetEnvironmentReferrerPolicy(doc->GetReferrerPolicy());
- }
- }
- } else {
- workers::WorkerPrivate* worker = workers::GetCurrentThreadWorkerPrivate();
- if (worker) {
- worker->AssertIsOnWorkerThread();
- request->SetEnvironmentReferrerPolicy(worker->GetReferrerPolicy());
- }
- }
- if (mode != RequestMode::EndGuard_) {
- request->ClearCreatedByFetchEvent();
- request->SetMode(mode);
- }
- if (credentials != RequestCredentials::EndGuard_) {
- request->ClearCreatedByFetchEvent();
- request->SetCredentialsMode(credentials);
- }
- RequestCache cache = aInit.mCache.WasPassed() ?
- aInit.mCache.Value() : fallbackCache;
- if (cache != RequestCache::EndGuard_) {
- if (cache == RequestCache::Only_if_cached &&
- request->Mode() != RequestMode::Same_origin) {
- uint32_t t = static_cast<uint32_t>(request->Mode());
- NS_ConvertASCIItoUTF16 modeString(RequestModeValues::strings[t].value,
- RequestModeValues::strings[t].length);
- aRv.ThrowTypeError<MSG_ONLY_IF_CACHED_WITHOUT_SAME_ORIGIN>(modeString);
- return nullptr;
- }
- request->ClearCreatedByFetchEvent();
- request->SetCacheMode(cache);
- }
- if (aInit.mRedirect.WasPassed()) {
- request->SetRedirectMode(aInit.mRedirect.Value());
- }
- if (aInit.mIntegrity.WasPassed()) {
- request->SetIntegrity(aInit.mIntegrity.Value());
- }
- // Request constructor step 14.
- if (aInit.mMethod.WasPassed()) {
- nsAutoCString method(aInit.mMethod.Value());
- // Step 14.1. Disallow forbidden methods, and anything that is not a HTTP
- // token, since HTTP states that Method may be any of the defined values or
- // a token (extension method).
- nsAutoCString outMethod;
- nsresult rv = FetchUtil::GetValidRequestMethod(method, outMethod);
- if (NS_FAILED(rv)) {
- NS_ConvertUTF8toUTF16 label(method);
- aRv.ThrowTypeError<MSG_INVALID_REQUEST_METHOD>(label);
- return nullptr;
- }
- // Step 14.2
- request->ClearCreatedByFetchEvent();
- request->SetMethod(outMethod);
- }
- RefPtr<InternalHeaders> requestHeaders = request->Headers();
- RefPtr<InternalHeaders> headers;
- if (aInit.mHeaders.WasPassed()) {
- RefPtr<Headers> h = Headers::Constructor(aGlobal, aInit.mHeaders.Value(), aRv);
- if (aRv.Failed()) {
- return nullptr;
- }
- request->ClearCreatedByFetchEvent();
- headers = h->GetInternalHeaders();
- } else {
- headers = new InternalHeaders(*requestHeaders);
- }
- requestHeaders->Clear();
- // From "Let r be a new Request object associated with request and a new
- // Headers object whose guard is "request"."
- requestHeaders->SetGuard(HeadersGuardEnum::Request, aRv);
- MOZ_ASSERT(!aRv.Failed());
- if (request->Mode() == RequestMode::No_cors) {
- if (!request->HasSimpleMethod()) {
- nsAutoCString method;
- request->GetMethod(method);
- NS_ConvertUTF8toUTF16 label(method);
- aRv.ThrowTypeError<MSG_INVALID_REQUEST_METHOD>(label);
- return nullptr;
- }
- if (!request->GetIntegrity().IsEmpty()) {
- aRv.ThrowTypeError<MSG_REQUEST_INTEGRITY_METADATA_NOT_EMPTY>();
- return nullptr;
- }
- requestHeaders->SetGuard(HeadersGuardEnum::Request_no_cors, aRv);
- if (aRv.Failed()) {
- return nullptr;
- }
- }
- requestHeaders->Fill(*headers, aRv);
- if (aRv.Failed()) {
- return nullptr;
- }
- if ((aInit.mBody.WasPassed() && !aInit.mBody.Value().IsNull()) ||
- temporaryBody) {
- // HEAD and GET are not allowed to have a body.
- nsAutoCString method;
- request->GetMethod(method);
- // method is guaranteed to be uppercase due to step 14.2 above.
- if (method.EqualsLiteral("HEAD") || method.EqualsLiteral("GET")) {
- aRv.ThrowTypeError<MSG_NO_BODY_ALLOWED_FOR_GET_AND_HEAD>();
- return nullptr;
- }
- }
- if (aInit.mBody.WasPassed()) {
- const Nullable<OwningArrayBufferOrArrayBufferViewOrBlobOrFormDataOrUSVStringOrURLSearchParams>& bodyInitNullable =
- aInit.mBody.Value();
- if (!bodyInitNullable.IsNull()) {
- const OwningArrayBufferOrArrayBufferViewOrBlobOrFormDataOrUSVStringOrURLSearchParams& bodyInit =
- bodyInitNullable.Value();
- nsCOMPtr<nsIInputStream> stream;
- nsAutoCString contentType;
- uint64_t contentLengthUnused;
- aRv = ExtractByteStreamFromBody(bodyInit,
- getter_AddRefs(stream),
- contentType,
- contentLengthUnused);
- if (NS_WARN_IF(aRv.Failed())) {
- return nullptr;
- }
- temporaryBody = stream;
- if (!contentType.IsVoid() &&
- !requestHeaders->Has(NS_LITERAL_CSTRING("Content-Type"), aRv)) {
- requestHeaders->Append(NS_LITERAL_CSTRING("Content-Type"),
- contentType, aRv);
- }
- if (NS_WARN_IF(aRv.Failed())) {
- return nullptr;
- }
- request->ClearCreatedByFetchEvent();
- request->SetBody(temporaryBody);
- }
- }
- RefPtr<Request> domRequest = new Request(global, request, signal);
- domRequest->SetMimeType();
- if (aInput.IsRequest()) {
- RefPtr<Request> inputReq = &aInput.GetAsRequest();
- nsCOMPtr<nsIInputStream> body;
- inputReq->GetBody(getter_AddRefs(body));
- if (body) {
- inputReq->SetBody(nullptr);
- inputReq->SetBodyUsed();
- }
- }
- return domRequest.forget();
- }
- already_AddRefed<Request>
- Request::Clone(ErrorResult& aRv)
- {
- if (BodyUsed()) {
- aRv.ThrowTypeError<MSG_FETCH_BODY_CONSUMED_ERROR>();
- return nullptr;
- }
- RefPtr<InternalRequest> ir = mRequest->Clone();
- if (!ir) {
- aRv.Throw(NS_ERROR_FAILURE);
- return nullptr;
- }
- RefPtr<Request> request = new Request(mOwner, ir, GetOrCreateSignal());
- return request.forget();
- }
- Headers*
- Request::Headers_()
- {
- if (!mHeaders) {
- mHeaders = new Headers(mOwner, mRequest->Headers());
- }
- return mHeaders;
- }
- AbortSignal*
- Request::GetOrCreateSignal()
- {
- if (!mSignal) {
- mSignal = new AbortSignal(false);
- }
- return mSignal;
- }
- AbortSignal*
- Request::GetSignal() const
- {
- return mSignal;
- }
- } // namespace dom
- } // namespace mozilla
|