Bug 1226909 part 2: Let CORS preflight logic grab information from nsILoadInfo rather than duplicate it. r=ckerschb
authorJonas Sicking <jonas@sicking.cc>
Sat, 05 Dec 2015 01:46:20 -0800
changeset 309932 26318a5e3006ab8a596dc015affcff43aac4ded8
parent 309931 9ae2af3cf86d7df085146971d1e55a9b13fe4c9c
child 309933 4dbf06183e6c2cb1c288f779aaacb3feaadbad29
push id5513
push userraliiev@mozilla.com
push dateMon, 25 Jan 2016 13:55:34 +0000
treeherdermozilla-beta@5ee97dd05b5c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersckerschb
bugs1226909
milestone45.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1226909 part 2: Let CORS preflight logic grab information from nsILoadInfo rather than duplicate it. r=ckerschb
dom/base/Navigator.cpp
dom/base/nsXMLHttpRequest.cpp
dom/fetch/FetchDriver.cpp
netwerk/ipc/NeckoChannelParams.ipdlh
netwerk/protocol/http/HttpBaseChannel.cpp
netwerk/protocol/http/HttpBaseChannel.h
netwerk/protocol/http/HttpChannelChild.cpp
netwerk/protocol/http/HttpChannelParent.cpp
netwerk/protocol/http/nsCORSListenerProxy.cpp
netwerk/protocol/http/nsCORSListenerProxy.h
netwerk/protocol/http/nsHttpChannel.cpp
netwerk/protocol/http/nsIHttpChannelInternal.idl
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -1199,17 +1199,18 @@ Navigator::SendBeacon(const nsAString& a
     aRv.Throw(NS_ERROR_CONTENT_BLOCKED);
     return false;
   }
 
   nsCOMPtr<nsIChannel> channel;
   rv = NS_NewChannel(getter_AddRefs(channel),
                      uri,
                      doc,
-                     nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS,
+                     nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS |
+                     nsILoadInfo::SEC_REQUIRE_CORS_WITH_CREDENTIALS,
                      nsIContentPolicy::TYPE_BEACON);
 
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
     return false;
   }
 
   nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(channel);
@@ -1336,19 +1337,17 @@ Navigator::SendBeacon(const nsAString& a
     nsCOMPtr<nsIHttpChannelInternal> internalChannel =
       do_QueryInterface(channel);
     if (!internalChannel) {
       aRv.Throw(NS_ERROR_FAILURE);
       return false;
     }
     nsTArray<nsCString> unsafeHeaders;
     unsafeHeaders.AppendElement(NS_LITERAL_CSTRING("Content-Type"));
-    rv = internalChannel->SetCorsPreflightParameters(unsafeHeaders,
-                                                     true,
-                                                     doc->NodePrincipal());
+    rv = internalChannel->SetCorsPreflightParameters(unsafeHeaders);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       aRv.Throw(rv);
       return false;
     }
   }
 
   rv = channel->AsyncOpen2(beaconListener);
   if (NS_FAILED(rv)) {
--- a/dom/base/nsXMLHttpRequest.cpp
+++ b/dom/base/nsXMLHttpRequest.cpp
@@ -2890,18 +2890,17 @@ nsXMLHttpRequest::Send(nsIVariant* aVari
     mState |= XML_HTTP_REQUEST_NEED_AC_PREFLIGHT_IF_XSITE;
   }
 
   // Set up the preflight if needed
   if ((mState & XML_HTTP_REQUEST_USE_XSITE_AC) &&
       (mState & XML_HTTP_REQUEST_NEED_AC_PREFLIGHT_IF_XSITE)) {
     NS_ENSURE_TRUE(internalHttpChannel, NS_ERROR_DOM_BAD_URI);
 
-    rv = internalHttpChannel->SetCorsPreflightParameters(mCORSUnsafeHeaders,
-                                                         withCredentials, mPrincipal);
+    rv = internalHttpChannel->SetCorsPreflightParameters(mCORSUnsafeHeaders);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   mIsMappedArrayBuffer = false;
   if (mResponseType == XML_HTTP_RESPONSE_TYPE_ARRAYBUFFER &&
       Preferences::GetBool("dom.mapped_arraybuffer.enabled", false)) {
     nsCOMPtr<nsIURI> uri;
     nsAutoCString scheme;
--- a/dom/fetch/FetchDriver.cpp
+++ b/dom/fetch/FetchDriver.cpp
@@ -418,20 +418,17 @@ FetchDriver::HttpFetch()
     mRequest->SetRedirectMode(RequestRedirect::Error);
 
     nsAutoTArray<nsCString, 5> unsafeHeaders;
     mRequest->Headers()->GetUnsafeHeaders(unsafeHeaders);
 
     nsCOMPtr<nsIHttpChannelInternal> internalChan = do_QueryInterface(httpChan);
     NS_ENSURE_TRUE(internalChan, NS_ERROR_DOM_BAD_URI);
 
-    rv = internalChan->SetCorsPreflightParameters(
-      unsafeHeaders,
-      mRequest->GetCredentialsMode() == RequestCredentials::Include,
-      mPrincipal);
+    rv = internalChan->SetCorsPreflightParameters(unsafeHeaders);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   rv = chan->AsyncOpen2(this);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Step 4 onwards of "HTTP Fetch" is handled internally by Necko.
   return NS_OK;
--- a/netwerk/ipc/NeckoChannelParams.ipdlh
+++ b/netwerk/ipc/NeckoChannelParams.ipdlh
@@ -60,18 +60,16 @@ union OptionalLoadInfoArgs
 union OptionalHttpResponseHead
 {
   void_t;
   nsHttpResponseHead;
 };
 
 struct CorsPreflightArgs
 {
-  bool          withCredentials;
-  PrincipalInfo preflightPrincipal;
   nsCString[]   unsafeHeaders;
 };
 
 union OptionalCorsPreflightArgs
 {
   void_t;
   CorsPreflightArgs;
 };
--- a/netwerk/protocol/http/HttpBaseChannel.cpp
+++ b/netwerk/protocol/http/HttpBaseChannel.cpp
@@ -94,17 +94,16 @@ HttpBaseChannel::HttpBaseChannel()
   , mCorsIncludeCredentials(false)
   , mCorsMode(nsIHttpChannelInternal::CORS_MODE_NO_CORS)
   , mRedirectMode(nsIHttpChannelInternal::REDIRECT_MODE_FOLLOW)
   , mOnStartRequestCalled(false)
   , mTransferSize(0)
   , mDecodedBodySize(0)
   , mEncodedBodySize(0)
   , mRequireCORSPreflight(false)
-  , mWithCredentials(false)
   , mReportCollector(new ConsoleReportCollector())
   , mForceMainDocumentChannel(false)
 {
   LOG(("Creating HttpBaseChannel @%x\n", this));
 
   // Subfields of unions cannot be targeted in an initializer list.
 #ifdef MOZ_VALGRIND
   // Zero the entire unions so that Valgrind doesn't complain when we send them
@@ -2605,18 +2604,17 @@ HttpBaseChannel::SetupReplacementChannel
 
   nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(newChannel);
   if (!httpChannel)
     return NS_OK; // no other options to set
 
   // Preserve the CORS preflight information.
   nsCOMPtr<nsIHttpChannelInternal> httpInternal = do_QueryInterface(newChannel);
   if (mRequireCORSPreflight && httpInternal) {
-    rv = httpInternal->SetCorsPreflightParameters(mUnsafeHeaders, mWithCredentials,
-                                                  mPreflightPrincipal);
+    rv = httpInternal->SetCorsPreflightParameters(mUnsafeHeaders);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
 
   if (preserveMethod) {
     nsCOMPtr<nsIUploadChannel> uploadChannel =
       do_QueryInterface(httpChannel);
@@ -3103,24 +3101,20 @@ HttpBaseChannel::EnsureSchedulingContext
     }
 
     // Set the load group connection scope on the transaction
     rootLoadGroup->GetSchedulingContextID(&mSchedulingContextID);
     return true;
 }
 
 NS_IMETHODIMP
-HttpBaseChannel::SetCorsPreflightParameters(const nsTArray<nsCString>& aUnsafeHeaders,
-                                            bool aWithCredentials,
-                                            nsIPrincipal* aPrincipal)
+HttpBaseChannel::SetCorsPreflightParameters(const nsTArray<nsCString>& aUnsafeHeaders)
 {
   ENSURE_CALLED_BEFORE_CONNECT();
 
   mRequireCORSPreflight = true;
   mUnsafeHeaders = aUnsafeHeaders;
-  mWithCredentials = aWithCredentials;
-  mPreflightPrincipal = aPrincipal;
   return NS_OK;
 }
 
 } // namespace net
 } // namespace mozilla
 
--- a/netwerk/protocol/http/HttpBaseChannel.h
+++ b/netwerk/protocol/http/HttpBaseChannel.h
@@ -208,19 +208,17 @@ public:
   NS_IMETHOD GetCorsIncludeCredentials(bool* aInclude) override;
   NS_IMETHOD SetCorsIncludeCredentials(bool aInclude) override;
   NS_IMETHOD GetCorsMode(uint32_t* aCorsMode) override;
   NS_IMETHOD SetCorsMode(uint32_t aCorsMode) override;
   NS_IMETHOD GetRedirectMode(uint32_t* aRedirectMode) override;
   NS_IMETHOD SetRedirectMode(uint32_t aRedirectMode) override;
   NS_IMETHOD GetTopWindowURI(nsIURI **aTopWindowURI) override;
   NS_IMETHOD GetProxyURI(nsIURI **proxyURI) override;
-  NS_IMETHOD SetCorsPreflightParameters(const nsTArray<nsCString>& unsafeHeaders,
-                                        bool aWithCredentials,
-                                        nsIPrincipal* aPrincipal) override;
+  NS_IMETHOD SetCorsPreflightParameters(const nsTArray<nsCString>& unsafeHeaders) override;
 
   inline void CleanRedirectCacheChainIfNecessary()
   {
       mRedirectedCachekeys = nullptr;
   }
   NS_IMETHOD HTTPUpgrade(const nsACString & aProtocolName,
                          nsIHttpUpgradeListener *aListener) override;
 
@@ -487,19 +485,17 @@ protected:
 
   // The network interface id that's associated with this channel.
   nsCString mNetworkInterfaceId;
 
   nsID mSchedulingContextID;
   bool EnsureSchedulingContextID();
 
   bool                              mRequireCORSPreflight;
-  bool                              mWithCredentials;
   nsTArray<nsCString>               mUnsafeHeaders;
-  nsCOMPtr<nsIPrincipal>            mPreflightPrincipal;
 
   nsCOMPtr<nsIConsoleReportCollector> mReportCollector;
 
   bool mForceMainDocumentChannel;
 };
 
 // Share some code while working around C++'s absurd inability to handle casting
 // of member functions between base/derived types.
--- a/netwerk/protocol/http/HttpChannelChild.cpp
+++ b/netwerk/protocol/http/HttpChannelChild.cpp
@@ -1843,22 +1843,17 @@ HttpChannelChild::ContinueAsyncOpen()
     }
 
     optionalFDs = fdSet;
   }
 
   OptionalCorsPreflightArgs optionalCorsPreflightArgs;
   if (mRequireCORSPreflight) {
     CorsPreflightArgs args;
-    args.withCredentials() = mWithCredentials;
     args.unsafeHeaders() = mUnsafeHeaders;
-    nsresult rv = PrincipalToPrincipalInfo(mPreflightPrincipal, &args.preflightPrincipal());
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
     optionalCorsPreflightArgs = args;
   } else {
     optionalCorsPreflightArgs = mozilla::void_t();
   }
 
   // NB: This call forces us to cache mTopWindowURI if we haven't already.
   nsCOMPtr<nsIURI> uri;
   GetTopWindowURI(getter_AddRefs(uri));
--- a/netwerk/protocol/http/HttpChannelParent.cpp
+++ b/netwerk/protocol/http/HttpChannelParent.cpp
@@ -471,21 +471,17 @@ HttpChannelParent::DoAsyncOpen(  const U
     Unused << fdSetActor->Send__delete__(fdSetActor);
   } else if (aFds.type() == OptionalFileDescriptorSet::TArrayOfFileDescriptor) {
     const_cast<OptionalFileDescriptorSet&>(aFds).
       get_ArrayOfFileDescriptor().SwapElements(fds);
   }
 
   if (aCorsPreflightArgs.type() == OptionalCorsPreflightArgs::TCorsPreflightArgs) {
     const CorsPreflightArgs& args = aCorsPreflightArgs.get_CorsPreflightArgs();
-    nsCOMPtr<nsIPrincipal> preflightPrincipal =
-      PrincipalInfoToPrincipal(args.preflightPrincipal());
-    rv = mChannel->SetCorsPreflightParameters(args.unsafeHeaders(),
-                                              args.withCredentials(),
-                                              preflightPrincipal);
+    rv = mChannel->SetCorsPreflightParameters(args.unsafeHeaders());
     if (NS_FAILED(rv)) {
       return SendFailedAsyncOpen(rv);
     }
   }
 
   nsCOMPtr<nsIInputStream> stream = DeserializeInputStream(uploadStream, fds);
   if (stream) {
     mChannel->InternalSetUploadStream(stream);
--- a/netwerk/protocol/http/nsCORSListenerProxy.cpp
+++ b/netwerk/protocol/http/nsCORSListenerProxy.cpp
@@ -1231,19 +1231,17 @@ nsCORSListenerProxy::RemoveFromCorsPrefl
   MOZ_ASSERT(XRE_IsParentProcess());
   if (sPreflightCache) {
     sPreflightCache->RemoveEntries(aURI, aRequestingPrincipal);
   }
 }
 
 nsresult
 nsCORSListenerProxy::StartCORSPreflight(nsIChannel* aRequestChannel,
-                                        nsIPrincipal* aPrincipal,
                                         nsICorsPreflightCallback* aCallback,
-                                        bool aWithCredentials,
                                         nsTArray<nsCString>& aUnsafeHeaders,
                                         nsIChannel** aPreflightChannel)
 {
   *aPreflightChannel = nullptr;
 
   if (gDisableCORS) {
     LogBlockedRequest(aRequestChannel, "CORSDisabled", nullptr);
     return NS_ERROR_DOM_BAD_URI;
@@ -1259,38 +1257,39 @@ nsCORSListenerProxy::StartCORSPreflight(
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsILoadInfo> originalLoadInfo = aRequestChannel->GetLoadInfo();
   MOZ_ASSERT(originalLoadInfo, "can not perform CORS preflight without a loadInfo");
   if (!originalLoadInfo) {
     return NS_ERROR_FAILURE;
   }
 
-  nsCOMPtr<nsILoadInfo> loadInfo = static_cast<mozilla::LoadInfo*>
-    (originalLoadInfo.get())->CloneForNewRequest();
+  MOZ_ASSERT(originalLoadInfo->GetSecurityMode() ==
+             nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS,
+             "how did we end up here?");
 
-  nsSecurityFlags securityMode = loadInfo->GetSecurityMode();
-
-  MOZ_ASSERT(securityMode == 0 ||
-             securityMode == nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS,
-             "how did we end up here?");
+  nsCOMPtr<nsIPrincipal> principal = originalLoadInfo->LoadingPrincipal();
+  bool withCredentials = originalLoadInfo->GetRequireCorsWithCredentials();
 
   nsPreflightCache::CacheEntry* entry =
     sPreflightCache ?
-    sPreflightCache->GetEntry(uri, aPrincipal, aWithCredentials, false) :
+    sPreflightCache->GetEntry(uri, principal, withCredentials, false) :
     nullptr;
 
   if (entry && entry->CheckRequest(method, aUnsafeHeaders)) {
     aCallback->OnPreflightSucceeded();
     return NS_OK;
   }
 
   // Either it wasn't cached or the cached result has expired. Build a
   // channel for the OPTIONS request.
 
+  nsCOMPtr<nsILoadInfo> loadInfo = static_cast<mozilla::LoadInfo*>
+    (originalLoadInfo.get())->CloneForNewRequest();
+
   nsCOMPtr<nsILoadGroup> loadGroup;
   rv = aRequestChannel->GetLoadGroup(getter_AddRefs(loadGroup));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsLoadFlags loadFlags;
   rv = aRequestChannel->GetLoadFlags(&loadFlags);
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -1342,34 +1341,24 @@ nsCORSListenerProxy::StartCORSPreflight(
     rv = preHttp->
       SetRequestHeader(NS_LITERAL_CSTRING("Access-Control-Request-Headers"),
                        headers, false);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   // Set up listener which will start the original channel
   RefPtr<nsCORSPreflightListener> preflightListener =
-    new nsCORSPreflightListener(aPrincipal, aCallback, aWithCredentials,
+    new nsCORSPreflightListener(principal, aCallback, withCredentials,
                                 method, preflightHeaders);
 
   rv = preflightChannel->SetNotificationCallbacks(preflightListener);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Start preflight
-  if (securityMode == nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS) {
-    rv = preflightChannel->AsyncOpen2(preflightListener);
-  }
-  else {
-    RefPtr<nsCORSListenerProxy> corsListener =
-      new nsCORSListenerProxy(preflightListener, aPrincipal,
-                              aWithCredentials);
-    rv = corsListener->Init(preflightChannel, DataURIHandling::Disallow);
-    NS_ENSURE_SUCCESS(rv, rv);
-    rv = preflightChannel->AsyncOpen(corsListener, nullptr);
-  }
+  rv = preflightChannel->AsyncOpen2(preflightListener);
   NS_ENSURE_SUCCESS(rv, rv);
   
   // Return newly created preflight channel
   preflightChannel.forget(aPreflightChannel);
 
   return NS_OK;
 }
 
--- a/netwerk/protocol/http/nsCORSListenerProxy.h
+++ b/netwerk/protocol/http/nsCORSListenerProxy.h
@@ -67,19 +67,17 @@ private:
   // Only HttpChannelParent can call RemoveFromCorsPreflightCache
   friend class mozilla::net::HttpChannelParent;
   // Only nsHttpChannel can invoke CORS preflights
   friend class mozilla::net::nsHttpChannel;
 
   static void RemoveFromCorsPreflightCache(nsIURI* aURI,
                                            nsIPrincipal* aRequestingPrincipal);
   static nsresult StartCORSPreflight(nsIChannel* aRequestChannel,
-                                     nsIPrincipal* aPrincipal,
                                      nsICorsPreflightCallback* aCallback,
-                                     bool aWithCredentials,
                                      nsTArray<nsCString>& aACUnsafeHeaders,
                                      nsIChannel** aPreflightChannel);
 
   ~nsCORSListenerProxy();
 
   nsresult UpdateChannel(nsIChannel* aChannel, DataURIHandling aAllowDataURI);
   nsresult CheckRequestApproved(nsIRequest* aRequest);
 
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -446,19 +446,17 @@ nsresult
 nsHttpChannel::ContinueConnect()
 {
     // If we need to start a CORS preflight, do it now!
     // Note that it is important to do this before the early returns below.
     if (!mIsCorsPreflightDone && mRequireCORSPreflight &&
         mInterceptCache != INTERCEPTED) {
         MOZ_ASSERT(!mPreflightChannel);
         nsresult rv =
-            nsCORSListenerProxy::StartCORSPreflight(this,
-                                                    mPreflightPrincipal, this,
-                                                    mWithCredentials,
+            nsCORSListenerProxy::StartCORSPreflight(this, this,
                                                     mUnsafeHeaders,
                                                     getter_AddRefs(mPreflightChannel));
         return rv;
     }
 
     MOZ_RELEASE_ASSERT(!(mRequireCORSPreflight &&
                          mInterceptCache != INTERCEPTED) ||
                        mIsCorsPreflightDone,
--- a/netwerk/protocol/http/nsIHttpChannelInternal.idl
+++ b/netwerk/protocol/http/nsIHttpChannelInternal.idl
@@ -34,17 +34,17 @@ interface nsIHttpUpgradeListener : nsISu
                               in nsIAsyncOutputStream aSocketOut);
 };
 
 /**
  * Dumping ground for http.  This interface will never be frozen.  If you are
  * using any feature exposed by this interface, be aware that this interface
  * will change and you will be broken.  You have been warned.
  */
-[scriptable, uuid(23b3f883-ce09-4350-8f67-1d9858d619e1)]
+[scriptable, uuid(dad4b7b1-b7cc-484f-9cac-5267ab0835a2)]
 interface nsIHttpChannelInternal : nsISupports
 {
     /**
      * An http channel can own a reference to the document URI
      */
     attribute nsIURI documentURI;
 
     /**
@@ -257,12 +257,10 @@ interface nsIHttpChannelInternal : nsISu
      */
     readonly attribute nsIURI proxyURI;
 
     /**
      * Make cross-origin CORS loads happen with a CORS preflight, and specify
      * the CORS preflight parameters.
      */
     [noscript]
-    void setCorsPreflightParameters(in StringArrayRef unsafeHeaders,
-                                    in boolean withCredentials,
-                                    in nsIPrincipal preflightPrincipal);
+    void setCorsPreflightParameters(in StringArrayRef unsafeHeaders);
 };