Bug 1419146 - Respect mozErrors in Request. r?bkelly draft
authorEdouard Oger <eoger@fastmail.com>
Mon, 20 Nov 2017 17:07:26 -0500
changeset 700791 6e44316b7f7b1c6ca6ddef576051fb6f81e98f1b
parent 700576 5c48b5edfc4ca945a2eaa5896454f3f4efa9052a
child 741002 a4697bfbd3b5062a8f3f825337945b00f402e6b1
push id89974
push userbmo:eoger@fastmail.com
push dateMon, 20 Nov 2017 22:10:26 +0000
reviewersbkelly
bugs1419146
milestone59.0a1
Bug 1419146 - Respect mozErrors in Request. r?bkelly MozReview-Commit-ID: Lbx395q7BYF
dom/fetch/Fetch.cpp
dom/fetch/InternalRequest.cpp
dom/fetch/InternalRequest.h
dom/fetch/Request.cpp
dom/fetch/Request.h
dom/tests/mochitest/fetch/test_fetch_basic.js
dom/tests/unit/test_Fetch.js
dom/webidl/Request.webidl
--- a/dom/fetch/Fetch.cpp
+++ b/dom/fetch/Fetch.cpp
@@ -440,19 +440,18 @@ FetchRequest(nsIGlobalObject* aGlobal, c
       if (NS_WARN_IF(NS_FAILED(rv))) {
         aRv.Throw(rv);
         return nullptr;
       }
     }
 
     Telemetry::Accumulate(Telemetry::FETCH_IS_MAINTHREAD, 1);
 
-    bool mozErrors = aInit.mMozErrors.WasPassed() ? aInit.mMozErrors.Value() : false;
     RefPtr<MainThreadFetchResolver> resolver =
-      new MainThreadFetchResolver(p, observer, signal, mozErrors);
+      new MainThreadFetchResolver(p, observer, signal, request->MozErrors());
     RefPtr<FetchDriver> fetch =
       new FetchDriver(r, principal, loadGroup,
                       aGlobal->EventTargetFor(TaskCategory::Other), isTrackingFetch);
     fetch->SetDocument(doc);
     resolver->SetLoadGroup(loadGroup);
     aRv = fetch->Fetch(signal, resolver);
     if (NS_WARN_IF(aRv.Failed())) {
       return nullptr;
--- a/dom/fetch/InternalRequest.cpp
+++ b/dom/fetch/InternalRequest.cpp
@@ -36,16 +36,17 @@ InternalRequest::GetRequestConstructorCo
   // use the appropriate window/document/principal and other Gecko security
   // mechanisms as appropriate.
   copy->mSameOriginDataURL = true;
   copy->mPreserveContentCodings = true;
   copy->mReferrer = mReferrer;
   copy->mReferrerPolicy = mReferrerPolicy;
   copy->mEnvironmentReferrerPolicy = mEnvironmentReferrerPolicy;
   copy->mIntegrity = mIntegrity;
+  copy->mMozErrors = mMozErrors;
 
   copy->mContentPolicyType = mContentPolicyTypeOverridden ?
                              mContentPolicyType :
                              nsIContentPolicy::TYPE_FETCH;
   copy->mMode = mMode;
   copy->mCredentialsMode = mCredentialsMode;
   copy->mCacheMode = mCacheMode;
   copy->mRedirectMode = mRedirectMode;
@@ -85,16 +86,17 @@ InternalRequest::InternalRequest(const n
   , mReferrer(NS_LITERAL_STRING(kFETCH_CLIENT_REFERRER_STR))
   , mReferrerPolicy(ReferrerPolicy::_empty)
   , mEnvironmentReferrerPolicy(net::RP_Unset)
   , mMode(RequestMode::No_cors)
   , mCredentialsMode(RequestCredentials::Omit)
   , mResponseTainting(LoadTainting::Basic)
   , mCacheMode(RequestCache::Default)
   , mRedirectMode(RequestRedirect::Follow)
+  , mMozErrors(false)
   , mAuthenticationFlag(false)
   , mForceOriginHeader(false)
   , mPreserveContentCodings(false)
     // FIXME(nsm): This should be false by default, but will lead to the
     // algorithm never loading data: URLs right now. See Bug 1018872 about
     // how certain contexts will override it to set it to true. Fetch
     // specification does not handle this yet.
   , mSameOriginDataURL(true)
@@ -125,16 +127,17 @@ InternalRequest::InternalRequest(const n
   , mReferrerPolicy(aReferrerPolicy)
   , mEnvironmentReferrerPolicy(net::RP_Unset)
   , mMode(aMode)
   , mCredentialsMode(aRequestCredentials)
   , mResponseTainting(LoadTainting::Basic)
   , mCacheMode(aCacheMode)
   , mRedirectMode(aRequestRedirect)
   , mIntegrity(aIntegrity)
+  , mMozErrors(false)
   , mAuthenticationFlag(false)
   , mForceOriginHeader(false)
   , mPreserveContentCodings(false)
     // FIXME See the above comment in the default constructor.
   , mSameOriginDataURL(true)
   , mSkipServiceWorker(false)
   , mSynchronous(false)
   , mUnsafeRequest(false)
@@ -153,16 +156,17 @@ InternalRequest::InternalRequest(const I
   , mReferrerPolicy(aOther.mReferrerPolicy)
   , mEnvironmentReferrerPolicy(aOther.mEnvironmentReferrerPolicy)
   , mMode(aOther.mMode)
   , mCredentialsMode(aOther.mCredentialsMode)
   , mResponseTainting(aOther.mResponseTainting)
   , mCacheMode(aOther.mCacheMode)
   , mRedirectMode(aOther.mRedirectMode)
   , mIntegrity(aOther.mIntegrity)
+  , mMozErrors(aOther.mMozErrors)
   , mFragment(aOther.mFragment)
   , mAuthenticationFlag(aOther.mAuthenticationFlag)
   , mForceOriginHeader(aOther.mForceOriginHeader)
   , mPreserveContentCodings(aOther.mPreserveContentCodings)
   , mSameOriginDataURL(aOther.mSameOriginDataURL)
   , mSkipServiceWorker(aOther.mSkipServiceWorker)
   , mSynchronous(aOther.mSynchronous)
   , mUnsafeRequest(aOther.mUnsafeRequest)
--- a/dom/fetch/InternalRequest.h
+++ b/dom/fetch/InternalRequest.h
@@ -397,16 +397,29 @@ public:
     return mIntegrity;
   }
   void
   SetIntegrity(const nsAString& aIntegrity)
   {
     MOZ_ASSERT(mIntegrity.IsEmpty());
     mIntegrity.Assign(aIntegrity);
   }
+
+  bool
+  MozErrors() const
+  {
+    return mMozErrors;
+  }
+
+  void
+  SetMozErrors()
+  {
+    mMozErrors = true;
+  }
+
   const nsCString&
   GetFragment() const
   {
     return mFragment;
   }
 
   nsContentPolicyType
   ContentPolicyType() const
@@ -576,16 +589,17 @@ private:
   // could be associated with nsIHttpChannel.
   net::ReferrerPolicy mEnvironmentReferrerPolicy;
   RequestMode mMode;
   RequestCredentials mCredentialsMode;
   MOZ_INIT_OUTSIDE_CTOR LoadTainting mResponseTainting;
   RequestCache mCacheMode;
   RequestRedirect mRedirectMode;
   nsString mIntegrity;
+  bool mMozErrors;
   nsCString mFragment;
   MOZ_INIT_OUTSIDE_CTOR bool mAuthenticationFlag;
   MOZ_INIT_OUTSIDE_CTOR bool mForceOriginHeader;
   MOZ_INIT_OUTSIDE_CTOR bool mPreserveContentCodings;
   MOZ_INIT_OUTSIDE_CTOR bool mSameOriginDataURL;
   MOZ_INIT_OUTSIDE_CTOR bool mSkipServiceWorker;
   MOZ_INIT_OUTSIDE_CTOR bool mSynchronous;
   MOZ_INIT_OUTSIDE_CTOR bool mUnsafeRequest;
--- a/dom/fetch/Request.cpp
+++ b/dom/fetch/Request.cpp
@@ -497,16 +497,20 @@ Request::Constructor(const GlobalObject&
   if (aInit.mRedirect.WasPassed()) {
     request->SetRedirectMode(aInit.mRedirect.Value());
   }
 
   if (aInit.mIntegrity.WasPassed()) {
     request->SetIntegrity(aInit.mIntegrity.Value());
   }
 
+  if (aInit.mMozErrors.WasPassed() && aInit.mMozErrors.Value()) {
+    request->SetMozErrors();
+  }
+
   // 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;
--- a/dom/fetch/Request.h
+++ b/dom/fetch/Request.h
@@ -83,16 +83,22 @@ public:
   }
 
   void
   GetIntegrity(nsAString& aIntegrity) const
   {
     aIntegrity = mRequest->GetIntegrity();
   }
 
+  bool
+  MozErrors() const
+  {
+    return mRequest->MozErrors();
+  }
+
   RequestContext
   Context() const
   {
     return mRequest->Context();
   }
 
   void
   OverrideContentPolicyType(nsContentPolicyType aContentPolicyType)
--- a/dom/tests/mochitest/fetch/test_fetch_basic.js
+++ b/dom/tests/mochitest/fetch/test_fetch_basic.js
@@ -98,16 +98,26 @@ function testMozErrors() {
   // mozErrors shouldn't be available to content and be ignored.
   return fetch("http://localhost:4/should/fail", { mozErrors: true }).then(res => {
     ok(false, "Request should not succeed");
   }).catch(err => {
     ok(err instanceof TypeError);
   });
 }
 
+function testRequestMozErrors() {
+  // mozErrors shouldn't be available to content and be ignored.
+  const r = new Request("http://localhost:4/should/fail", { mozErrors: true });
+  return fetch(r).then(res => {
+    ok(false, "Request should not succeed");
+  }).catch(err => {
+    ok(err instanceof TypeError);
+  });
+}
+
 function runTest() {
   return Promise.resolve()
     .then(testAboutURL)
     .then(testDataURL)
     .then(testSameOriginBlobURL)
     .then(testNonGetBlobURL)
     .then(testMozErrors)
     // Put more promise based tests here.
--- a/dom/tests/unit/test_Fetch.js
+++ b/dom/tests/unit/test_Fetch.js
@@ -219,16 +219,29 @@ add_test(function test_mozError() {
     do_throw("Request should not succeed");
   }).catch(err => {
     do_check_eq(err.result, Cr.NS_ERROR_CONNECTION_REFUSED);
     do_test_finished();
     run_next_test();
   });
 });
 
+add_test(function test_request_mozError() {
+  do_test_pending();
+  // try a server that's not there
+  const r = new Request("http://localhost:4/should/fail", { mozErrors: true });
+  fetch(r).then(response => {
+    do_throw("Request should not succeed");
+  }).catch(err => {
+    do_check_eq(err.result, Cr.NS_ERROR_CONNECTION_REFUSED);
+    do_test_finished();
+    run_next_test();
+  });
+});
+
 // test POSTing some JSON data
 add_test(function test_PostJSONData() {
   do_test_pending();
 
   let testData = createTestData("/postJSONData");
   testData.request.body = "{\"foo\": \"bar\"}";
 
   server.registerPathHandler(testData.testPath, function(aRequest, aResponse) {
--- a/dom/webidl/Request.webidl
+++ b/dom/webidl/Request.webidl
@@ -22,16 +22,21 @@ interface Request {
   readonly attribute USVString referrer;
   readonly attribute ReferrerPolicy referrerPolicy;
   readonly attribute RequestMode mode;
   readonly attribute RequestCredentials credentials;
   readonly attribute RequestCache cache;
   readonly attribute RequestRedirect redirect;
   readonly attribute DOMString integrity;
 
+  // If a main-thread fetch() promise rejects, the error passed will be a
+  // nsresult code.
+  [ChromeOnly]
+  readonly attribute boolean mozErrors;
+
   [BinaryName="getOrCreateSignal"]
   readonly attribute AbortSignal signal;
 
   [Throws,
    NewObject] Request clone();
 
   // Bug 1124638 - Allow chrome callers to set the context.
   [ChromeOnly]
@@ -46,18 +51,16 @@ dictionary RequestInit {
   USVString referrer;
   ReferrerPolicy referrerPolicy;
   RequestMode mode;
   RequestCredentials credentials;
   RequestCache cache;
   RequestRedirect redirect;
   DOMString integrity;
 
-  // If a main-thread fetch() promise rejects, the error passed will be a
-  // nsresult code.
   [ChromeOnly]
   boolean mozErrors;
 
   AbortSignal? signal;
 
   [Func="FetchObserver::IsEnabled"]
   ObserverCallback observe;
 };