LCOV - code coverage report
Current view: top level - dom/fetch - Request.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 107 345 31.0 %
Date: 2017-07-14 16:53:18 Functions: 13 25 52.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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/. */
       6             : 
       7             : #include "Request.h"
       8             : 
       9             : #include "nsIURI.h"
      10             : #include "nsPIDOMWindow.h"
      11             : 
      12             : #include "mozilla/ErrorResult.h"
      13             : #include "mozilla/dom/Headers.h"
      14             : #include "mozilla/dom/Fetch.h"
      15             : #include "mozilla/dom/FetchUtil.h"
      16             : #include "mozilla/dom/Promise.h"
      17             : #include "mozilla/dom/URL.h"
      18             : #include "mozilla/dom/WorkerPrivate.h"
      19             : #include "mozilla/Unused.h"
      20             : 
      21             : #include "WorkerPrivate.h"
      22             : 
      23             : namespace mozilla {
      24             : namespace dom {
      25             : 
      26           1 : NS_IMPL_CYCLE_COLLECTING_ADDREF(Request)
      27           2 : NS_IMPL_CYCLE_COLLECTING_RELEASE(Request)
      28           1 : NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Request, mOwner, mHeaders)
      29             : 
      30           7 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Request)
      31           0 :   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
      32           0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
      33           0 : NS_INTERFACE_MAP_END
      34             : 
      35           1 : Request::Request(nsIGlobalObject* aOwner, InternalRequest* aRequest)
      36             :   : FetchBody<Request>(aOwner)
      37           1 :   , mRequest(aRequest)
      38             : {
      39           1 :   MOZ_ASSERT(aRequest->Headers()->Guard() == HeadersGuardEnum::Immutable ||
      40             :              aRequest->Headers()->Guard() == HeadersGuardEnum::Request ||
      41             :              aRequest->Headers()->Guard() == HeadersGuardEnum::Request_no_cors);
      42           1 :   SetMimeType();
      43           1 : }
      44             : 
      45           2 : Request::~Request()
      46             : {
      47           3 : }
      48             : 
      49             : // static
      50             : bool
      51           4 : Request::RequestContextEnabled(JSContext* aCx, JSObject* aObj)
      52             : {
      53           4 :   if (NS_IsMainThread()) {
      54           3 :     return Preferences::GetBool("dom.requestcontext.enabled", false);
      55             :   }
      56             : 
      57             :   using namespace workers;
      58             : 
      59             :   // Otherwise, check the pref via the WorkerPrivate
      60           1 :   WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
      61           1 :   if (!workerPrivate) {
      62           0 :     return false;
      63             :   }
      64             : 
      65           1 :   return workerPrivate->RequestContextEnabled();
      66             : }
      67             : 
      68             : already_AddRefed<InternalRequest>
      69           1 : Request::GetInternalRequest()
      70             : {
      71           2 :   RefPtr<InternalRequest> r = mRequest;
      72           2 :   return r.forget();
      73             : }
      74             : 
      75             : namespace {
      76             : already_AddRefed<nsIURI>
      77           0 : ParseURLFromDocument(nsIDocument* aDocument, const nsAString& aInput,
      78             :                      ErrorResult& aRv)
      79             : {
      80           0 :   MOZ_ASSERT(aDocument);
      81           0 :   MOZ_ASSERT(NS_IsMainThread());
      82             : 
      83           0 :   nsCOMPtr<nsIURI> baseURI = aDocument->GetBaseURI();
      84           0 :   nsCOMPtr<nsIURI> resolvedURI;
      85           0 :   aRv = NS_NewURI(getter_AddRefs(resolvedURI), aInput, nullptr, baseURI);
      86           0 :   if (NS_WARN_IF(aRv.Failed())) {
      87           0 :     aRv.ThrowTypeError<MSG_INVALID_URL>(aInput);
      88             :   }
      89           0 :   return resolvedURI.forget();
      90             : }
      91             : void
      92           0 : GetRequestURLFromDocument(nsIDocument* aDocument, const nsAString& aInput,
      93             :                           nsAString& aRequestURL, nsACString& aURLfragment,
      94             :                           ErrorResult& aRv)
      95             : {
      96           0 :   nsCOMPtr<nsIURI> resolvedURI = ParseURLFromDocument(aDocument, aInput, aRv);
      97           0 :   if (aRv.Failed()) {
      98           0 :     return;
      99             :   }
     100             :   // This fails with URIs with weird protocols, even when they are valid,
     101             :   // so we ignore the failure
     102           0 :   nsAutoCString credentials;
     103           0 :   Unused << resolvedURI->GetUserPass(credentials);
     104           0 :   if (!credentials.IsEmpty()) {
     105           0 :     aRv.ThrowTypeError<MSG_URL_HAS_CREDENTIALS>(aInput);
     106           0 :     return;
     107             :   }
     108             : 
     109           0 :   nsCOMPtr<nsIURI> resolvedURIClone;
     110             :   // We use CloneIgnoringRef to strip away the fragment even if the original URI
     111             :   // is immutable.
     112           0 :   aRv = resolvedURI->CloneIgnoringRef(getter_AddRefs(resolvedURIClone));
     113           0 :   if (NS_WARN_IF(aRv.Failed())) {
     114           0 :     return;
     115             :   }
     116           0 :   nsAutoCString spec;
     117           0 :   aRv = resolvedURIClone->GetSpec(spec);
     118           0 :   if (NS_WARN_IF(aRv.Failed())) {
     119           0 :     return;
     120             :   }
     121           0 :   CopyUTF8toUTF16(spec, aRequestURL);
     122             : 
     123             :   // Get the fragment from nsIURI.
     124           0 :   aRv = resolvedURI->GetRef(aURLfragment);
     125           0 :   if (NS_WARN_IF(aRv.Failed())) {
     126           0 :     return;
     127             :   }
     128             : }
     129             : already_AddRefed<nsIURI>
     130           1 : ParseURLFromChrome(const nsAString& aInput, ErrorResult& aRv)
     131             : {
     132           1 :   MOZ_ASSERT(NS_IsMainThread());
     133           2 :   nsCOMPtr<nsIURI> uri;
     134           1 :   aRv = NS_NewURI(getter_AddRefs(uri), aInput, nullptr, nullptr);
     135           1 :   if (NS_WARN_IF(aRv.Failed())) {
     136           0 :     aRv.ThrowTypeError<MSG_INVALID_URL>(aInput);
     137             :   }
     138           2 :   return uri.forget();
     139             : }
     140             : void
     141           1 : GetRequestURLFromChrome(const nsAString& aInput, nsAString& aRequestURL,
     142             :                         nsACString& aURLfragment, ErrorResult& aRv)
     143             : {
     144           2 :   nsCOMPtr<nsIURI> uri = ParseURLFromChrome(aInput, aRv);
     145           1 :   if (aRv.Failed()) {
     146           0 :     return;
     147             :   }
     148             :   // This fails with URIs with weird protocols, even when they are valid,
     149             :   // so we ignore the failure
     150           2 :   nsAutoCString credentials;
     151           1 :   Unused << uri->GetUserPass(credentials);
     152           1 :   if (!credentials.IsEmpty()) {
     153           0 :     aRv.ThrowTypeError<MSG_URL_HAS_CREDENTIALS>(aInput);
     154           0 :     return;
     155             :   }
     156             : 
     157           2 :   nsCOMPtr<nsIURI> uriClone;
     158             :   // We use CloneIgnoringRef to strip away the fragment even if the original URI
     159             :   // is immutable.
     160           1 :   aRv = uri->CloneIgnoringRef(getter_AddRefs(uriClone));
     161           1 :   if (NS_WARN_IF(aRv.Failed())) {
     162           0 :     return;
     163             :   }
     164           2 :   nsAutoCString spec;
     165           1 :   aRv = uriClone->GetSpec(spec);
     166           1 :   if (NS_WARN_IF(aRv.Failed())) {
     167           0 :     return;
     168             :   }
     169           1 :   CopyUTF8toUTF16(spec, aRequestURL);
     170             : 
     171             :   // Get the fragment from nsIURI.
     172           1 :   aRv = uri->GetRef(aURLfragment);
     173           1 :   if (NS_WARN_IF(aRv.Failed())) {
     174           0 :     return;
     175             :   }
     176             : }
     177             : already_AddRefed<URL>
     178           0 : ParseURLFromWorker(const GlobalObject& aGlobal, const nsAString& aInput,
     179             :                    ErrorResult& aRv)
     180             : {
     181           0 :   workers::WorkerPrivate* worker = workers::GetCurrentThreadWorkerPrivate();
     182           0 :   MOZ_ASSERT(worker);
     183           0 :   worker->AssertIsOnWorkerThread();
     184             : 
     185           0 :   NS_ConvertUTF8toUTF16 baseURL(worker->GetLocationInfo().mHref);
     186           0 :   RefPtr<URL> url = URL::WorkerConstructor(aGlobal, aInput, baseURL, aRv);
     187           0 :   if (NS_WARN_IF(aRv.Failed())) {
     188           0 :     aRv.ThrowTypeError<MSG_INVALID_URL>(aInput);
     189             :   }
     190           0 :   return url.forget();
     191             : }
     192             : void
     193           0 : GetRequestURLFromWorker(const GlobalObject& aGlobal, const nsAString& aInput,
     194             :                         nsAString& aRequestURL, nsACString& aURLfragment,
     195             :                         ErrorResult& aRv)
     196             : {
     197           0 :   RefPtr<URL> url = ParseURLFromWorker(aGlobal, aInput, aRv);
     198           0 :   if (aRv.Failed()) {
     199           0 :     return;
     200             :   }
     201           0 :   nsString username;
     202           0 :   url->GetUsername(username, aRv);
     203           0 :   if (NS_WARN_IF(aRv.Failed())) {
     204           0 :     return;
     205             :   }
     206             : 
     207           0 :   nsString password;
     208           0 :   url->GetPassword(password, aRv);
     209           0 :   if (NS_WARN_IF(aRv.Failed())) {
     210           0 :     return;
     211             :   }
     212           0 :   if (!username.IsEmpty() || !password.IsEmpty()) {
     213           0 :     aRv.ThrowTypeError<MSG_URL_HAS_CREDENTIALS>(aInput);
     214           0 :     return;
     215             :   }
     216             :   // Get the fragment from URL.
     217           0 :   nsAutoString fragment;
     218           0 :   url->GetHash(fragment, aRv);
     219           0 :   if (NS_WARN_IF(aRv.Failed())) {
     220           0 :     return;
     221             :   }
     222             : 
     223             :   // Note: URL::GetHash() includes the "#" and we want the fragment with out
     224             :   // the hash symbol.
     225           0 :   if (!fragment.IsEmpty()) {
     226           0 :     CopyUTF16toUTF8(Substring(fragment, 1), aURLfragment);
     227             :   }
     228             : 
     229           0 :   url->SetHash(EmptyString(), aRv);
     230           0 :   if (NS_WARN_IF(aRv.Failed())) {
     231           0 :     return;
     232             :   }
     233           0 :   url->Stringify(aRequestURL, aRv);
     234           0 :   if (NS_WARN_IF(aRv.Failed())) {
     235           0 :     return;
     236             :   }
     237             : }
     238             : 
     239           0 : class ReferrerSameOriginChecker final : public workers::WorkerMainThreadRunnable
     240             : {
     241             : public:
     242           0 :   ReferrerSameOriginChecker(workers::WorkerPrivate* aWorkerPrivate,
     243             :                             const nsAString& aReferrerURL,
     244             :                             nsresult& aResult)
     245           0 :     : workers::WorkerMainThreadRunnable(aWorkerPrivate,
     246           0 :                                         NS_LITERAL_CSTRING("Fetch :: Referrer same origin check")),
     247             :       mReferrerURL(aReferrerURL),
     248           0 :       mResult(aResult)
     249             :   {
     250           0 :     mWorkerPrivate->AssertIsOnWorkerThread();
     251           0 :   }
     252             : 
     253             :   bool
     254           0 :   MainThreadRun() override
     255             :   {
     256           0 :     nsCOMPtr<nsIURI> uri;
     257           0 :     if (NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), mReferrerURL))) {
     258           0 :       nsCOMPtr<nsIPrincipal> principal = mWorkerPrivate->GetPrincipal();
     259           0 :       if (principal) {
     260           0 :         mResult = principal->CheckMayLoad(uri, /* report */ false,
     261           0 :                                           /* allowIfInheritsPrincipal */ false);
     262             :       }
     263             :     }
     264           0 :     return true;
     265             :   }
     266             : 
     267             : private:
     268             :   const nsString mReferrerURL;
     269             :   nsresult& mResult;
     270             : };
     271             : 
     272             : } // namespace
     273             : 
     274             : /*static*/ already_AddRefed<Request>
     275           1 : Request::Constructor(const GlobalObject& aGlobal,
     276             :                      const RequestOrUSVString& aInput,
     277             :                      const RequestInit& aInit, ErrorResult& aRv)
     278             : {
     279           1 :   bool hasCopiedBody = false;
     280           2 :   RefPtr<InternalRequest> request;
     281             : 
     282           2 :   nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
     283             : 
     284           1 :   if (aInput.IsRequest()) {
     285           0 :     RefPtr<Request> inputReq = &aInput.GetAsRequest();
     286           0 :     nsCOMPtr<nsIInputStream> body;
     287           0 :     inputReq->GetBody(getter_AddRefs(body));
     288           0 :     if (inputReq->BodyUsed()) {
     289           0 :       aRv.ThrowTypeError<MSG_FETCH_BODY_CONSUMED_ERROR>();
     290           0 :       return nullptr;
     291             :     }
     292             : 
     293             :     // The body will be copied when GetRequestConstructorCopy() is executed.
     294           0 :     if (body) {
     295           0 :       hasCopiedBody = true;
     296             :     }
     297             : 
     298           0 :     request = inputReq->GetInternalRequest();
     299             :   } else {
     300             :     // aInput is USVString.
     301             :     // We need to get url before we create a InternalRequest.
     302           2 :     nsAutoString input;
     303           1 :     input.Assign(aInput.GetAsUSVString());
     304           2 :     nsAutoString requestURL;
     305           2 :     nsCString fragment;
     306           1 :     if (NS_IsMainThread()) {
     307           1 :       nsIDocument* doc = GetEntryDocument();
     308           1 :       if (doc) {
     309           0 :         GetRequestURLFromDocument(doc, input, requestURL, fragment, aRv);
     310             :       } else {
     311             :         // If we don't have a document, we must assume that this is a full URL.
     312           1 :         GetRequestURLFromChrome(input, requestURL, fragment, aRv);
     313             :       }
     314             :     } else {
     315           0 :       GetRequestURLFromWorker(aGlobal, input, requestURL, fragment, aRv);
     316             :     }
     317           1 :     if (NS_WARN_IF(aRv.Failed())) {
     318           0 :       return nullptr;
     319             :     }
     320           2 :     request = new InternalRequest(NS_ConvertUTF16toUTF8(requestURL), fragment);
     321             :   }
     322           1 :   request = request->GetRequestConstructorCopy(global, aRv);
     323           1 :   if (NS_WARN_IF(aRv.Failed())) {
     324           0 :     return nullptr;
     325             :   }
     326           1 :   RequestMode fallbackMode = RequestMode::EndGuard_;
     327           1 :   RequestCredentials fallbackCredentials = RequestCredentials::EndGuard_;
     328           1 :   RequestCache fallbackCache = RequestCache::EndGuard_;
     329           1 :   if (aInput.IsUSVString()) {
     330           1 :     fallbackMode = RequestMode::Cors;
     331           1 :     fallbackCredentials = RequestCredentials::Omit;
     332           1 :     fallbackCache = RequestCache::Default;
     333             :   }
     334             : 
     335           1 :   RequestMode mode = aInit.mMode.WasPassed() ? aInit.mMode.Value() : fallbackMode;
     336             :   RequestCredentials credentials =
     337           1 :     aInit.mCredentials.WasPassed() ? aInit.mCredentials.Value()
     338           1 :                                    : fallbackCredentials;
     339             : 
     340           2 :   if (mode == RequestMode::Navigate ||
     341           1 :       (aInit.IsAnyMemberPresent() && request->Mode() == RequestMode::Navigate)) {
     342           0 :     mode = RequestMode::Same_origin;
     343             :   }
     344             : 
     345           1 :   if (aInit.IsAnyMemberPresent()) {
     346           0 :     request->SetReferrer(NS_LITERAL_STRING(kFETCH_CLIENT_REFERRER_STR));
     347           0 :     request->SetReferrerPolicy(ReferrerPolicy::_empty);
     348             :   }
     349           1 :   if (aInit.mReferrer.WasPassed()) {
     350           0 :     const nsString& referrer = aInit.mReferrer.Value();
     351           0 :     if (referrer.IsEmpty()) {
     352           0 :       request->SetReferrer(NS_LITERAL_STRING(""));
     353             :     } else {
     354           0 :       nsAutoString referrerURL;
     355           0 :       if (NS_IsMainThread()) {
     356           0 :         nsIDocument* doc = GetEntryDocument();
     357           0 :         nsCOMPtr<nsIURI> uri;
     358           0 :         if (doc) {
     359           0 :           uri = ParseURLFromDocument(doc, referrer, aRv);
     360             :         } else {
     361             :           // If we don't have a document, we must assume that this is a full URL.
     362           0 :           uri = ParseURLFromChrome(referrer, aRv);
     363             :         }
     364           0 :         if (NS_WARN_IF(aRv.Failed())) {
     365           0 :           aRv.ThrowTypeError<MSG_INVALID_REFERRER_URL>(referrer);
     366           0 :           return nullptr;
     367             :         }
     368           0 :         nsAutoCString spec;
     369           0 :         uri->GetSpec(spec);
     370           0 :         CopyUTF8toUTF16(spec, referrerURL);
     371           0 :         if (!referrerURL.EqualsLiteral(kFETCH_CLIENT_REFERRER_STR)) {
     372           0 :           nsCOMPtr<nsIPrincipal> principal = global->PrincipalOrNull();
     373           0 :           if (principal) {
     374           0 :             nsresult rv = principal->CheckMayLoad(uri, /* report */ false,
     375           0 :                                                   /* allowIfInheritsPrincipal */ false);
     376           0 :             if (NS_FAILED(rv)) {
     377           0 :               referrerURL.AssignLiteral(kFETCH_CLIENT_REFERRER_STR);
     378             :             }
     379             :           }
     380             :         }
     381             :       } else {
     382           0 :         RefPtr<URL> url = ParseURLFromWorker(aGlobal, referrer, aRv);
     383           0 :         if (NS_WARN_IF(aRv.Failed())) {
     384           0 :           aRv.ThrowTypeError<MSG_INVALID_REFERRER_URL>(referrer);
     385           0 :           return nullptr;
     386             :         }
     387           0 :         url->Stringify(referrerURL, aRv);
     388           0 :         if (NS_WARN_IF(aRv.Failed())) {
     389           0 :           aRv.ThrowTypeError<MSG_INVALID_REFERRER_URL>(referrer);
     390           0 :           return nullptr;
     391             :         }
     392           0 :         if (!referrerURL.EqualsLiteral(kFETCH_CLIENT_REFERRER_STR)) {
     393           0 :           workers::WorkerPrivate* worker = workers::GetCurrentThreadWorkerPrivate();
     394           0 :           nsresult rv = NS_OK;
     395             :           // ReferrerSameOriginChecker uses a sync loop to get the main thread
     396             :           // to perform the same-origin check.  Overall, on Workers this method
     397             :           // can create 3 sync loops (two for constructing URLs and one here) so
     398             :           // in the future we may want to optimize it all by off-loading all of
     399             :           // this work in a single sync loop.
     400             :           RefPtr<ReferrerSameOriginChecker> checker =
     401           0 :             new ReferrerSameOriginChecker(worker, referrerURL, rv);
     402           0 :           IgnoredErrorResult error;
     403           0 :           checker->Dispatch(Terminating, error);
     404           0 :           if (error.Failed() || NS_FAILED(rv)) {
     405           0 :             referrerURL.AssignLiteral(kFETCH_CLIENT_REFERRER_STR);
     406             :           }
     407             :         }
     408             :       }
     409           0 :       request->SetReferrer(referrerURL);
     410             :     }
     411             :   }
     412             : 
     413           1 :   if (aInit.mReferrerPolicy.WasPassed()) {
     414           0 :     request->SetReferrerPolicy(aInit.mReferrerPolicy.Value());
     415             :   }
     416             : 
     417           1 :   if (NS_IsMainThread()) {
     418           2 :     nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(global);
     419           1 :     if (window) {
     420           0 :       nsCOMPtr<nsIDocument> doc;
     421           0 :       doc = window->GetExtantDoc();
     422           0 :       if (doc) {
     423           0 :         request->SetEnvironmentReferrerPolicy(doc->GetReferrerPolicy());
     424             :       }
     425             :     }
     426             :   } else {
     427           0 :     workers::WorkerPrivate* worker = workers::GetCurrentThreadWorkerPrivate();
     428           0 :     if (worker) {
     429           0 :       worker->AssertIsOnWorkerThread();
     430           0 :       request->SetEnvironmentReferrerPolicy(worker->GetReferrerPolicy());
     431             :     }
     432             :   }
     433             : 
     434           1 :   if (mode != RequestMode::EndGuard_) {
     435           1 :     request->ClearCreatedByFetchEvent();
     436           1 :     request->SetMode(mode);
     437             :   }
     438             : 
     439           1 :   if (credentials != RequestCredentials::EndGuard_) {
     440           1 :     request->ClearCreatedByFetchEvent();
     441           1 :     request->SetCredentialsMode(credentials);
     442             :   }
     443             : 
     444           1 :   RequestCache cache = aInit.mCache.WasPassed() ?
     445           1 :                        aInit.mCache.Value() : fallbackCache;
     446           1 :   if (cache != RequestCache::EndGuard_) {
     447           1 :     if (cache == RequestCache::Only_if_cached &&
     448           0 :         request->Mode() != RequestMode::Same_origin) {
     449           0 :       uint32_t t = static_cast<uint32_t>(request->Mode());
     450           0 :       NS_ConvertASCIItoUTF16 modeString(RequestModeValues::strings[t].value,
     451           0 :                                         RequestModeValues::strings[t].length);
     452           0 :       aRv.ThrowTypeError<MSG_ONLY_IF_CACHED_WITHOUT_SAME_ORIGIN>(modeString);
     453           0 :       return nullptr;
     454             :     }
     455           1 :     request->ClearCreatedByFetchEvent();
     456           1 :     request->SetCacheMode(cache);
     457             :   }
     458             : 
     459           1 :   if (aInit.mRedirect.WasPassed()) {
     460           0 :     request->SetRedirectMode(aInit.mRedirect.Value());
     461             :   }
     462             : 
     463           1 :   if (aInit.mIntegrity.WasPassed()) {
     464           0 :     request->SetIntegrity(aInit.mIntegrity.Value());
     465             :   }
     466             : 
     467             :   // Request constructor step 14.
     468           1 :   if (aInit.mMethod.WasPassed()) {
     469           0 :     nsAutoCString method(aInit.mMethod.Value());
     470             : 
     471             :     // Step 14.1. Disallow forbidden methods, and anything that is not a HTTP
     472             :     // token, since HTTP states that Method may be any of the defined values or
     473             :     // a token (extension method).
     474           0 :     nsAutoCString outMethod;
     475           0 :     nsresult rv = FetchUtil::GetValidRequestMethod(method, outMethod);
     476           0 :     if (NS_FAILED(rv)) {
     477           0 :       NS_ConvertUTF8toUTF16 label(method);
     478           0 :       aRv.ThrowTypeError<MSG_INVALID_REQUEST_METHOD>(label);
     479           0 :       return nullptr;
     480             :     }
     481             : 
     482             :     // Step 14.2
     483           0 :     request->ClearCreatedByFetchEvent();
     484           0 :     request->SetMethod(outMethod);
     485             :   }
     486             : 
     487           2 :   RefPtr<InternalHeaders> requestHeaders = request->Headers();
     488             : 
     489           2 :   RefPtr<InternalHeaders> headers;
     490           1 :   if (aInit.mHeaders.WasPassed()) {
     491           0 :     RefPtr<Headers> h = Headers::Constructor(aGlobal, aInit.mHeaders.Value(), aRv);
     492           0 :     if (aRv.Failed()) {
     493           0 :       return nullptr;
     494             :     }
     495           0 :     request->ClearCreatedByFetchEvent();
     496           0 :     headers = h->GetInternalHeaders();
     497             :   } else {
     498           2 :     headers = new InternalHeaders(*requestHeaders);
     499             :   }
     500             : 
     501           1 :   requestHeaders->Clear();
     502             :   // From "Let r be a new Request object associated with request and a new
     503             :   // Headers object whose guard is "request"."
     504           1 :   requestHeaders->SetGuard(HeadersGuardEnum::Request, aRv);
     505           1 :   MOZ_ASSERT(!aRv.Failed());
     506             : 
     507           1 :   if (request->Mode() == RequestMode::No_cors) {
     508           0 :     if (!request->HasSimpleMethod()) {
     509           0 :       nsAutoCString method;
     510           0 :       request->GetMethod(method);
     511           0 :       NS_ConvertUTF8toUTF16 label(method);
     512           0 :       aRv.ThrowTypeError<MSG_INVALID_REQUEST_METHOD>(label);
     513           0 :       return nullptr;
     514             :     }
     515             : 
     516           0 :     if (!request->GetIntegrity().IsEmpty()) {
     517           0 :       aRv.ThrowTypeError<MSG_REQUEST_INTEGRITY_METADATA_NOT_EMPTY>();
     518           0 :       return nullptr;
     519             :     }
     520             : 
     521           0 :     requestHeaders->SetGuard(HeadersGuardEnum::Request_no_cors, aRv);
     522           0 :     if (aRv.Failed()) {
     523           0 :       return nullptr;
     524             :     }
     525             :   }
     526             : 
     527           1 :   requestHeaders->Fill(*headers, aRv);
     528           1 :   if (aRv.Failed()) {
     529           0 :     return nullptr;
     530             :   }
     531             : 
     532           1 :   if ((aInit.mBody.WasPassed() && !aInit.mBody.Value().IsNull()) ||
     533             :       hasCopiedBody) {
     534             :     // HEAD and GET are not allowed to have a body.
     535           0 :     nsAutoCString method;
     536           0 :     request->GetMethod(method);
     537             :     // method is guaranteed to be uppercase due to step 14.2 above.
     538           0 :     if (method.EqualsLiteral("HEAD") || method.EqualsLiteral("GET")) {
     539           0 :       aRv.ThrowTypeError<MSG_NO_BODY_ALLOWED_FOR_GET_AND_HEAD>();
     540           0 :       return nullptr;
     541             :     }
     542             :   }
     543             : 
     544           1 :   if (aInit.mBody.WasPassed()) {
     545           0 :     const Nullable<fetch::OwningBodyInit>& bodyInitNullable = aInit.mBody.Value();
     546           0 :     if (!bodyInitNullable.IsNull()) {
     547           0 :       const fetch::OwningBodyInit& bodyInit = bodyInitNullable.Value();
     548           0 :       nsCOMPtr<nsIInputStream> stream;
     549           0 :       nsAutoCString contentTypeWithCharset;
     550             :       uint64_t contentLengthUnused;
     551           0 :       aRv = ExtractByteStreamFromBody(bodyInit,
     552           0 :                                       getter_AddRefs(stream),
     553             :                                       contentTypeWithCharset,
     554           0 :                                       contentLengthUnused);
     555           0 :       if (NS_WARN_IF(aRv.Failed())) {
     556           0 :         return nullptr;
     557             :       }
     558             : 
     559           0 :       nsCOMPtr<nsIInputStream> temporaryBody = stream;
     560             : 
     561           0 :       if (!contentTypeWithCharset.IsVoid() &&
     562           0 :           !requestHeaders->Has(NS_LITERAL_CSTRING("Content-Type"), aRv)) {
     563           0 :         requestHeaders->Append(NS_LITERAL_CSTRING("Content-Type"),
     564           0 :                                contentTypeWithCharset, aRv);
     565             :       }
     566             : 
     567           0 :       if (NS_WARN_IF(aRv.Failed())) {
     568           0 :         return nullptr;
     569             :       }
     570             : 
     571           0 :       request->ClearCreatedByFetchEvent();
     572             : 
     573           0 :       if (hasCopiedBody) {
     574           0 :         request->SetBody(nullptr);
     575             :       }
     576             : 
     577           0 :       request->SetBody(temporaryBody);
     578             :     }
     579             :   }
     580             : 
     581           3 :   RefPtr<Request> domRequest = new Request(global, request);
     582           1 :   domRequest->SetMimeType();
     583             : 
     584           1 :   if (aInput.IsRequest()) {
     585           0 :     RefPtr<Request> inputReq = &aInput.GetAsRequest();
     586           0 :     nsCOMPtr<nsIInputStream> body;
     587           0 :     inputReq->GetBody(getter_AddRefs(body));
     588           0 :     if (body) {
     589           0 :       inputReq->SetBody(nullptr);
     590           0 :       inputReq->SetBodyUsed();
     591             :     }
     592             :   }
     593           1 :   return domRequest.forget();
     594             : }
     595             : 
     596             : already_AddRefed<Request>
     597           0 : Request::Clone(ErrorResult& aRv) const
     598             : {
     599           0 :   if (BodyUsed()) {
     600           0 :     aRv.ThrowTypeError<MSG_FETCH_BODY_CONSUMED_ERROR>();
     601           0 :     return nullptr;
     602             :   }
     603             : 
     604           0 :   RefPtr<InternalRequest> ir = mRequest->Clone();
     605           0 :   if (!ir) {
     606           0 :     aRv.Throw(NS_ERROR_FAILURE);
     607           0 :     return nullptr;
     608             :   }
     609             : 
     610           0 :   RefPtr<Request> request = new Request(mOwner, ir);
     611           0 :   return request.forget();
     612             : }
     613             : 
     614             : Headers*
     615           0 : Request::Headers_()
     616             : {
     617           0 :   if (!mHeaders) {
     618           0 :     mHeaders = new Headers(mOwner, mRequest->Headers());
     619             :   }
     620             : 
     621           0 :   return mHeaders;
     622             : }
     623             : 
     624             : } // namespace dom
     625             : } // namespace mozilla

Generated by: LCOV version 1.13