Bug 1346392 - Force non-spdy on sticky auth connections. r=dragana, a=lizzard
authorNicholas Hurley <hurley@mozilla.com>
Tue, 28 Mar 2017 17:15:23 -0700
changeset 395837 a4b7a2a843e5ba87c87aba60fbdc10795c6dcb48
parent 395836 e82a6f21f043a75e8f8e5d935d173a2ff25a9144
child 395838 cef7b5c139ef710202d2e95ec7b9ab84b9e9b2a2
push id1468
push userasasaki@mozilla.com
push dateMon, 05 Jun 2017 19:31:07 +0000
treeherdermozilla-release@0641fc6ee9d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdragana, lizzard
bugs1346392
milestone54.0a2
Bug 1346392 - Force non-spdy on sticky auth connections. r=dragana, a=lizzard MozReview-Commit-ID: IkYTVgetKsn
netwerk/protocol/http/nsHttpChannel.cpp
netwerk/protocol/http/nsHttpChannel.h
netwerk/protocol/http/nsHttpChannelAuthProvider.cpp
netwerk/protocol/http/nsHttpTransaction.cpp
netwerk/protocol/http/nsHttpTransaction.h
netwerk/protocol/http/nsIHttpAuthenticableChannel.idl
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -5538,16 +5538,35 @@ NS_IMETHODIMP nsHttpChannel::CloseSticky
     }
 
     // This turns the IsPersistent() indicator on the connection to false,
     // and makes us throw it away in OnStopRequest.
     conn->DontReuse();
     return NS_OK;
 }
 
+NS_IMETHODIMP nsHttpChannel::ForceNoSpdy()
+{
+    LOG(("nsHttpChannel::ForceNoSpdy this=%p", this));
+
+    MOZ_ASSERT(mTransaction);
+    if (!mTransaction) {
+        return NS_ERROR_UNEXPECTED;
+    }
+
+    mAllowSpdy = 0;
+    mCaps |= NS_HTTP_DISALLOW_SPDY;
+
+    if (!(mTransaction->Caps() & NS_HTTP_DISALLOW_SPDY)) {
+        mTransaction->DisableSpdy();
+    }
+
+    return NS_OK;
+}
+
 //-----------------------------------------------------------------------------
 // nsHttpChannel::nsISupports
 //-----------------------------------------------------------------------------
 
 NS_IMPL_ADDREF_INHERITED(nsHttpChannel, HttpBaseChannel)
 NS_IMPL_RELEASE_INHERITED(nsHttpChannel, HttpBaseChannel)
 
 NS_INTERFACE_MAP_BEGIN(nsHttpChannel)
--- a/netwerk/protocol/http/nsHttpChannel.h
+++ b/netwerk/protocol/http/nsHttpChannel.h
@@ -111,16 +111,17 @@ public:
     NS_IMETHOD GetServerResponseHeader(nsACString & aServerResponseHeader) override;
     NS_IMETHOD GetProxyChallenges(nsACString & aChallenges) override;
     NS_IMETHOD GetWWWChallenges(nsACString & aChallenges) override;
     NS_IMETHOD SetProxyCredentials(const nsACString & aCredentials) override;
     NS_IMETHOD SetWWWCredentials(const nsACString & aCredentials) override;
     NS_IMETHOD OnAuthAvailable() override;
     NS_IMETHOD OnAuthCancelled(bool userCancel) override;
     NS_IMETHOD CloseStickyConnection() override;
+    NS_IMETHOD ForceNoSpdy() override;
     // Functions we implement from nsIHttpAuthenticableChannel but are
     // declared in HttpBaseChannel must be implemented in this class. We
     // just call the HttpBaseChannel:: impls.
     NS_IMETHOD GetLoadFlags(nsLoadFlags *aLoadFlags) override;
     NS_IMETHOD GetURI(nsIURI **aURI) override;
     NS_IMETHOD GetNotificationCallbacks(nsIInterfaceRequestor **aCallbacks) override;
     NS_IMETHOD GetLoadGroup(nsILoadGroup **aLoadGroup) override;
     NS_IMETHOD GetRequestMethod(nsACString& aMethod) override;
--- a/netwerk/protocol/http/nsHttpChannelAuthProvider.cpp
+++ b/netwerk/protocol/http/nsHttpChannelAuthProvider.cpp
@@ -812,16 +812,20 @@ nsHttpChannelAuthProvider::GetCredential
           //   as non-valid and we would ask the user again ; clearing it forces
           //   use of the cached identity and not asking the user again
           mProxyIdent.Clear();
         }
         mConnectionBased = false;
     }
 
     mConnectionBased = !!(authFlags & nsIHttpAuthenticator::CONNECTION_BASED);
+    if (mConnectionBased) {
+        rv = mAuthChannel->ForceNoSpdy();
+        MOZ_ASSERT(NS_SUCCEEDED(rv));
+    }
 
     if (identityInvalid) {
         if (entry) {
             if (ident->Equals(entry->Identity())) {
                 if (!identFromURI) {
                     LOG(("  clearing bad auth cache entry\n"));
                     // ok, we've already tried this user identity, so clear the
                     // corresponding entry from the auth cache.
--- a/netwerk/protocol/http/nsHttpTransaction.cpp
+++ b/netwerk/protocol/http/nsHttpTransaction.cpp
@@ -1784,16 +1784,21 @@ void
 nsHttpTransaction::CheckForStickyAuthScheme()
 {
   LOG(("nsHttpTransaction::CheckForStickyAuthScheme this=%p", this));
 
   MOZ_ASSERT(mHaveAllHeaders);
   MOZ_ASSERT(mResponseHead);
   MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
 
+  if (mClosed) {
+      LOG(("  closed, not checking"));
+      return;
+  }
+
   CheckForStickyAuthSchemeAt(nsHttp::WWW_Authenticate);
   CheckForStickyAuthSchemeAt(nsHttp::Proxy_Authenticate);
 }
 
 void
 nsHttpTransaction::CheckForStickyAuthSchemeAt(nsHttpAtom const& header)
 {
   if (mCaps & NS_HTTP_STICKY_CONNECTION) {
--- a/netwerk/protocol/http/nsHttpTransaction.h
+++ b/netwerk/protocol/http/nsHttpTransaction.h
@@ -126,16 +126,18 @@ public:
     const TimeStamp GetPendingTime() { return mPendingTime; }
 
     // overload of nsAHttpTransaction::RequestContext()
     nsIRequestContext *RequestContext() override { return mRequestContext.get(); }
     void SetRequestContext(nsIRequestContext *aRequestContext);
     void DispatchedAsBlocking();
     void RemoveDispatchedAsBlocking();
 
+    void DisableSpdy() override;
+
     nsHttpTransaction *QueryHttpTransaction() override { return this; }
 
     Http2PushedStream *GetPushedStream() { return mPushedStream; }
     Http2PushedStream *TakePushedStream()
     {
         Http2PushedStream *r = mPushedStream;
         mPushedStream = nullptr;
         return r;
@@ -186,17 +188,16 @@ private:
                                        uint32_t, uint32_t, uint32_t *);
     static nsresult WritePipeSegment(nsIOutputStream *, void *, char *,
                                      uint32_t, uint32_t, uint32_t *);
 
     bool TimingEnabled() const { return mCaps & NS_HTTP_TIMING_ENABLED; }
 
     bool ResponseTimeoutEnabled() const final;
 
-    void DisableSpdy() override;
     void ReuseConnectionOnRestartOK(bool reuseOk) override { mReuseOnRestart = reuseOk; }
 
     // Called right after we parsed the response head.  Checks for connection based
     // authentication schemes in reponse headers for WWW and Proxy authentication.
     // If such is found in any of them, NS_HTTP_STICKY_CONNECTION is set in mCaps.
     // We need the sticky flag be set early to keep the connection from very start
     // of the authentication process.
     void CheckForStickyAuthScheme();
--- a/netwerk/protocol/http/nsIHttpAuthenticableChannel.idl
+++ b/netwerk/protocol/http/nsIHttpAuthenticableChannel.idl
@@ -107,9 +107,15 @@ interface nsIHttpAuthenticableChannel : 
     void onAuthCancelled(in boolean userCancel);
 
     /**
      * Tells the channel to drop and close any sticky connection, since this
      * connection oriented schema cannot be negotiated second time on
      * the same connection.
      */
     void closeStickyConnection();
+
+    /**
+     * Tells the channel to not use SPDY-like protocols, since this will be
+     * using connection-oriented auth.
+     */
+    void forceNoSpdy();
 };