bug 378637 part 13 - https proxying changes to casting and trans lifecycle r=hurley
authorPatrick McManus <mcmanus@ducksong.com>
Fri, 16 May 2014 11:46:12 -0400
changeset 183608 ab6d433e563b
parent 183607 1d1935f80c97
child 183609 3e4ecea736c3
push id26799
push userphilringnalda@gmail.com
push date2014-05-18 00:55 +0000
treeherdermozilla-central@00ef3a7d7aa7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewershurley
bugs378637
milestone32.0a1
bug 378637 part 13 - https proxying changes to casting and trans lifecycle r=hurley
netwerk/protocol/http/NullHttpTransaction.cpp
netwerk/protocol/http/NullHttpTransaction.h
netwerk/protocol/http/SpdySession3.cpp
netwerk/protocol/http/SpdyStream3.cpp
netwerk/protocol/http/TunnelUtils.cpp
netwerk/protocol/http/TunnelUtils.h
netwerk/protocol/http/nsAHttpConnection.h
netwerk/protocol/http/nsAHttpTransaction.h
netwerk/protocol/http/nsHttpConnection.cpp
netwerk/protocol/http/nsHttpTransaction.h
--- a/netwerk/protocol/http/NullHttpTransaction.cpp
+++ b/netwerk/protocol/http/NullHttpTransaction.cpp
@@ -10,17 +10,17 @@
 #include "nsHttp.h"
 #include "NullHttpTransaction.h"
 #include "nsHttpHandler.h"
 #include "nsHttpRequestHead.h"
 
 namespace mozilla {
 namespace net {
 
-NS_IMPL_ISUPPORTS(NullHttpTransaction, nsISupportsWeakReference)
+NS_IMPL_ISUPPORTS(NullHttpTransaction, NullHttpTransaction, nsISupportsWeakReference)
 
 NullHttpTransaction::NullHttpTransaction(nsHttpConnectionInfo *ci,
                                          nsIInterfaceRequestor *callbacks,
                                          uint32_t caps)
   : mStatus(NS_OK)
   , mCaps(caps | NS_HTTP_ALLOW_KEEPALIVE)
   , mCapsToClear(0)
   , mCallbacks(callbacks)
--- a/netwerk/protocol/http/NullHttpTransaction.h
+++ b/netwerk/protocol/http/NullHttpTransaction.h
@@ -16,19 +16,24 @@
 // anticipation of a real transaction needing to use it soon.
 
 namespace mozilla { namespace net {
 
 class nsAHttpConnection;
 class nsHttpConnectionInfo;
 class nsHttpRequestHead;
 
+// 6c445340-3b82-4345-8efa-4902c3b8805a
+#define NS_NULLHTTPTRANSACTION_IID \
+{ 0x6c445340, 0x3b82, 0x4345, {0x8e, 0xfa, 0x49, 0x02, 0xc3, 0xb8, 0x80, 0x5a }}
+
 class NullHttpTransaction : public nsAHttpTransaction
 {
 public:
+  NS_DECLARE_STATIC_IID_ACCESSOR(NS_NULLHTTPTRANSACTION_IID)
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSAHTTPTRANSACTION
 
   NullHttpTransaction(nsHttpConnectionInfo *ci,
                       nsIInterfaceRequestor *callbacks,
                       uint32_t caps);
   virtual ~NullHttpTransaction();
 
@@ -52,11 +57,13 @@ private:
   uint32_t mCapsToClear;
   nsRefPtr<nsAHttpConnection> mConnection;
   nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
   nsRefPtr<nsHttpConnectionInfo> mConnectionInfo;
   nsHttpRequestHead *mRequestHead;
   bool mIsDone;
 };
 
+NS_DEFINE_STATIC_IID_ACCESSOR(NullHttpTransaction, NS_NULLHTTPTRANSACTION_IID)
+
 }} // namespace mozilla::net
 
 #endif // mozilla_net_NullHttpTransaction_h
--- a/netwerk/protocol/http/SpdySession3.cpp
+++ b/netwerk/protocol/http/SpdySession3.cpp
@@ -2533,16 +2533,17 @@ SpdySession3::DispatchOnTunnel(nsAHttpTr
     SpdyStream3 *tunnel = mStreamTransactionHash.Get(connectTrans);
     MOZ_ASSERT(tunnel);
     RegisterTunnel(tunnel);
   }
 
   // requeue it. The connection manager is responsible for actually putting
   // this on the tunnel connection with the specific ci now that it
   // has DontRouteViaWildCard set.
+  trans->EnableKeepAlive();
   gHttpHandler->InitiateTransaction(trans, trans->Priority());
 }
 
 //-----------------------------------------------------------------------------
 // Modified methods of nsAHttpConnection
 //-----------------------------------------------------------------------------
 
 void
--- a/netwerk/protocol/http/SpdyStream3.cpp
+++ b/netwerk/protocol/http/SpdyStream3.cpp
@@ -478,20 +478,17 @@ SpdyStream3::ParseHttpRequestHeaders(con
   // to make life easy for any gateways
   CompressToFrame(NS_LITERAL_CSTRING(":method"));
   CompressToFrame(methodHeader, strlen(methodHeader));
 
   CompressToFrame(NS_LITERAL_CSTRING(":path"));
   if (!mTransaction->RequestHead()->IsConnect()) {
     CompressToFrame(mTransaction->RequestHead()->RequestURI());
   } else {
-#ifdef DEBUG
-    nsRefPtr<SpdyConnectTransaction> qiTrans(do_QueryObject(mTransaction));
-    MOZ_ASSERT(qiTrans);
-#endif
+    MOZ_ASSERT(mTransaction->QuerySpdyConnectTransaction());
     mIsTunnel = true;
     // Connect places host:port in :path. Don't use default port.
     nsHttpConnectionInfo *ci = mTransaction->ConnectionInfo();
     if (!ci) {
       return NS_ERROR_UNEXPECTED;
     }
     nsAutoCString route;
     route = ci->GetHost();
@@ -1557,16 +1554,16 @@ SpdyStream3::ClearTransactionsBlockedOnT
     return;
   }
   gHttpHandler->ConnMgr()->ProcessPendingQ(mTransaction->ConnectionInfo());
 }
 
 void
 SpdyStream3::MapStreamToHttpConnection()
 {
-  nsRefPtr<SpdyConnectTransaction> qiTrans(do_QueryObject(mTransaction));
+  nsRefPtr<SpdyConnectTransaction> qiTrans(mTransaction->QuerySpdyConnectTransaction());
   MOZ_ASSERT(qiTrans);
   qiTrans->MapStreamToHttpConnection(mSocketTransport,
                                      mTransaction->ConnectionInfo());
 }
 
 } // namespace mozilla::net
 } // namespace mozilla
--- a/netwerk/protocol/http/TunnelUtils.cpp
+++ b/netwerk/protocol/http/TunnelUtils.cpp
@@ -29,26 +29,29 @@ namespace mozilla {
 namespace net {
 
 static PRDescIdentity sLayerIdentity;
 static PRIOMethods sLayerMethods;
 static PRIOMethods *sLayerMethodsPtr = nullptr;
 
 TLSFilterTransaction::TLSFilterTransaction(nsAHttpTransaction *aWrapped,
                                            const char *aTLSHost,
-                                           int32_t aTLSPort)
+                                           int32_t aTLSPort,
+                                           nsAHttpSegmentReader *aReader,
+                                           nsAHttpSegmentWriter *aWriter)
   : mTransaction(aWrapped)
   , mEncryptedTextUsed(0)
   , mEncryptedTextSize(0)
-  , mSegmentReader(nullptr)
-  , mSegmentWriter(nullptr)
+  , mSegmentReader(aReader)
+  , mSegmentWriter(aWriter)
   , mForce(false)
   , mNudgeCounter(0)
 {
   MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
+  LOG(("TLSFilterTransaction ctor %p\n", this));
 
   nsCOMPtr<nsISocketProvider> provider;
   nsCOMPtr<nsISocketProviderService> spserv =
     do_GetService(NS_SOCKETPROVIDERSERVICE_CONTRACTID);
 
   if (spserv) {
     spserv->GetSocketProvider("ssl", getter_AddRefs(provider));
   }
@@ -86,16 +89,17 @@ TLSFilterTransaction::TLSFilterTransacti
     if (secCtrl) {
       secCtrl->SetNotificationCallbacks(callbacks);
     }
   }
 }
 
 TLSFilterTransaction::~TLSFilterTransaction()
 {
+  LOG(("TLSFilterTransaction dtor %p\n", this));
   Cleanup();
 }
 
 void
 TLSFilterTransaction::Cleanup()
 {
   if (mTransaction) {
     mTransaction->Close(NS_ERROR_ABORT);
@@ -329,17 +333,16 @@ TLSFilterTransaction::WriteSegments(nsAH
   LOG(("TLSFilterTransaction::WriteSegments %p max=%d\n", this, aCount));
 
   if (!mTransaction) {
     return NS_ERROR_UNEXPECTED;
   }
 
   mSegmentWriter = aWriter;
   nsresult rv = mTransaction->WriteSegments(this, aCount, outCountWritten);
-  mSegmentWriter = nullptr;
   LOG(("TLSFilterTransaction %p called trans->WriteSegments rv=%x %d\n",
        this, rv, *outCountWritten));
   return rv;
 }
 
 nsresult
 TLSFilterTransaction::GetTransactionSecurityInfo(nsISupports **outSecInfo)
 {
@@ -347,35 +350,26 @@ TLSFilterTransaction::GetTransactionSecu
     return NS_ERROR_FAILURE;
   }
 
   NS_ADDREF(*outSecInfo = mSecInfo);
   return NS_OK;
 }
 
 nsresult
-TLSFilterTransaction::NudgeTunnel(NudgeTunnelCallback *aCallback,
-                                  nsAHttpSegmentReader *aReader,
-                                  nsAHttpSegmentWriter *aWriter)
+TLSFilterTransaction::NudgeTunnel(NudgeTunnelCallback *aCallback)
 {
   MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
   LOG(("TLSFilterTransaction %p NudgeTunnel\n", this));
   mNudgeCallback = nullptr;
 
   if (!mSecInfo) {
     return NS_ERROR_FAILURE;
   }
 
-  if (aReader) {
-    mSegmentReader = aReader;
-  }
-  if (aWriter) {
-    mSegmentWriter = aWriter;
-  }
-
   uint32_t notUsed;
   PR_Write(mFD, "", 0);
   OnReadSegment("", 0, &notUsed);
 
   // The SSL Layer does some unusual things with PR_Poll that makes it a bad
   // match for multiplexed SSL sessions. We work around this by manually polling for
   // the moment during the brief handshake phase or otherwise blocked on write.
   // Thankfully this is a pretty unusual state. NSPR doesn't help us here -
@@ -760,17 +754,17 @@ private:
   nsIInputStreamCallback *mCallback;
   nsresult mStatus;
 };
 
 SpdyConnectTransaction::SpdyConnectTransaction(nsHttpConnectionInfo *ci,
                                                nsIInterfaceRequestor *callbacks,
                                                uint32_t caps,
                                                nsAHttpTransaction *trans,
-                                               ASpdySession *session)
+                                               nsAHttpConnection *session)
   : NullHttpTransaction(ci, callbacks, caps | NS_HTTP_ALLOW_KEEPALIVE)
   , mConnectStringOffset(0)
   , mSession(session)
   , mSegmentReader(nullptr)
   , mInputDataSize(0)
   , mInputDataUsed(0)
   , mInputDataOffset(0)
   , mOutputDataSize(0)
@@ -1001,59 +995,66 @@ OutputStreamShim::AsyncWait(nsIOutputStr
 
   if (target &&
       (NS_FAILED(target->IsOnCurrentThread(&currentThread)) || !currentThread)) {
     return NS_ERROR_FAILURE;
   }
 
   LOG(("OutputStreamShim::AsyncWait %p callback %p\n", this, callback));
   mCallback = callback;
-  nsRefPtr<SpdyConnectTransaction> trans = do_QueryReferent(mWeakTrans);
+
+  nsRefPtr<NullHttpTransaction> baseTrans(do_QueryReferent(mWeakTrans));
+  if (!baseTrans) {
+    return NS_ERROR_FAILURE;
+  }
+  SpdyConnectTransaction *trans = baseTrans->QuerySpdyConnectTransaction();
+  MOZ_ASSERT(trans);
   if (!trans) {
-    return NS_ERROR_FAILURE;
+    return NS_ERROR_UNEXPECTED;
   }
 
-  nsRefPtr<nsAHttpConnection> spdySession(do_QueryObject(trans->mSession));
-  if (!spdySession) {
-    return NS_ERROR_UNEXPECTED;
-  }
-  spdySession->TransactionHasDataToWrite(trans);
+  trans->mSession->TransactionHasDataToWrite(trans);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 OutputStreamShim::CloseWithStatus(nsresult reason)
 {
-  nsRefPtr<SpdyConnectTransaction> trans = do_QueryReferent(mWeakTrans);
-  if (!trans) {
+  nsRefPtr<NullHttpTransaction> baseTrans(do_QueryReferent(mWeakTrans));
+  if (!baseTrans) {
     return NS_ERROR_FAILURE;
   }
-
-  nsRefPtr<nsAHttpConnection> spdySession(do_QueryObject(trans->mSession));
-  if (!spdySession) {
+  SpdyConnectTransaction *trans = baseTrans->QuerySpdyConnectTransaction();
+  MOZ_ASSERT(trans);
+  if (!trans) {
     return NS_ERROR_UNEXPECTED;
   }
 
-  spdySession->CloseTransaction(trans, reason);
+  trans->mSession->CloseTransaction(trans, reason);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 OutputStreamShim::Close()
 {
   return CloseWithStatus(NS_OK);
 }
 
 NS_IMETHODIMP
 OutputStreamShim::Flush()
 {
-  nsRefPtr<SpdyConnectTransaction> trans = do_QueryReferent(mWeakTrans);
+  nsRefPtr<NullHttpTransaction> baseTrans(do_QueryReferent(mWeakTrans));
+  if (!baseTrans) {
+    return NS_ERROR_FAILURE;
+  }
+  SpdyConnectTransaction *trans = baseTrans->QuerySpdyConnectTransaction();
+  MOZ_ASSERT(trans);
   if (!trans) {
-    return NS_ERROR_FAILURE;
+    return NS_ERROR_UNEXPECTED;
   }
 
   uint32_t count = trans->mOutputDataUsed - trans->mOutputDataOffset;
   if (!count) {
     return NS_OK;
   }
 
   uint32_t countRead;
@@ -1067,40 +1068,41 @@ NS_IMETHODIMP
 OutputStreamShim::Write(const char * aBuf, uint32_t aCount, uint32_t *_retval)
 {
   MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
 
   if (NS_FAILED(mStatus)) {
     return mStatus;
   }
 
-  nsRefPtr<SpdyConnectTransaction> trans = do_QueryReferent(mWeakTrans);
+  nsRefPtr<NullHttpTransaction> baseTrans(do_QueryReferent(mWeakTrans));
+  if (!baseTrans) {
+    return NS_ERROR_FAILURE;
+  }
+  SpdyConnectTransaction *trans = baseTrans->QuerySpdyConnectTransaction();
+  MOZ_ASSERT(trans);
   if (!trans) {
-    return NS_ERROR_FAILURE;
+    return NS_ERROR_UNEXPECTED;
   }
 
   if ((trans->mOutputDataUsed + aCount) >= 512000) {
     *_retval = 0;
     // time for some flow control;
     return NS_BASE_STREAM_WOULD_BLOCK;
   }
 
   EnsureBuffer(trans->mOutputData, trans->mOutputDataUsed + aCount,
                trans->mOutputDataUsed, trans->mOutputDataSize);
   memcpy(trans->mOutputData + trans->mOutputDataUsed,
           aBuf, aCount);
   trans->mOutputDataUsed += aCount;
   *_retval = aCount;
   LOG(("OutputStreamShim::Write %p new %d total %d\n", this, aCount, trans->mOutputDataUsed));
 
-  nsRefPtr<nsAHttpConnection> spdySession(do_QueryObject(trans->mSession));
-  if (!spdySession) {
-    return NS_ERROR_UNEXPECTED;
-  }
-  spdySession->TransactionHasDataToWrite(trans);
+  trans->mSession->TransactionHasDataToWrite(trans);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 OutputStreamShim::WriteFrom(nsIInputStream *aFromStream, uint32_t aCount, uint32_t *_retval)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
@@ -1134,60 +1136,70 @@ InputStreamShim::AsyncWait(nsIInputStrea
   LOG(("InputStreamShim::AsyncWait %p callback %p\n", this, callback));
   mCallback = callback;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 InputStreamShim::CloseWithStatus(nsresult reason)
 {
-  nsRefPtr<SpdyConnectTransaction> trans = do_QueryReferent(mWeakTrans);
-  if (!trans) {
+  nsRefPtr<NullHttpTransaction> baseTrans(do_QueryReferent(mWeakTrans));
+  if (!baseTrans) {
     return NS_ERROR_FAILURE;
   }
-
-  nsRefPtr<nsAHttpConnection> spdySession(do_QueryObject(trans->mSession));
-  if (!spdySession) {
+  SpdyConnectTransaction *trans = baseTrans->QuerySpdyConnectTransaction();
+  MOZ_ASSERT(trans);
+  if (!trans) {
     return NS_ERROR_UNEXPECTED;
   }
 
-  spdySession->CloseTransaction(trans, reason);
+  trans->mSession->CloseTransaction(trans, reason);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 InputStreamShim::Close()
 {
   return CloseWithStatus(NS_OK);
 }
 
 NS_IMETHODIMP
 InputStreamShim::Available(uint64_t *_retval)
 {
-  nsRefPtr<SpdyConnectTransaction> trans = do_QueryReferent(mWeakTrans);
+  nsRefPtr<NullHttpTransaction> baseTrans(do_QueryReferent(mWeakTrans));
+  if (!baseTrans) {
+    return NS_ERROR_FAILURE;
+  }
+  SpdyConnectTransaction *trans = baseTrans->QuerySpdyConnectTransaction();
+  MOZ_ASSERT(trans);
   if (!trans) {
-    return NS_ERROR_FAILURE;
+    return NS_ERROR_UNEXPECTED;
   }
 
   *_retval = trans->mInputDataUsed - trans->mInputDataOffset;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 InputStreamShim::Read(char *aBuf, uint32_t aCount, uint32_t *_retval)
 {
   MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
 
   if (NS_FAILED(mStatus)) {
     return mStatus;
   }
 
-  nsRefPtr<SpdyConnectTransaction> trans = do_QueryReferent(mWeakTrans);
+  nsRefPtr<NullHttpTransaction> baseTrans(do_QueryReferent(mWeakTrans));
+  if (!baseTrans) {
+    return NS_ERROR_FAILURE;
+  }
+  SpdyConnectTransaction *trans = baseTrans->QuerySpdyConnectTransaction();
+  MOZ_ASSERT(trans);
   if (!trans) {
-    return NS_ERROR_FAILURE;
+    return NS_ERROR_UNEXPECTED;
   }
 
   uint32_t avail = trans->mInputDataUsed - trans->mInputDataOffset;
   uint32_t tocopy = std::min(aCount, avail);
   *_retval = tocopy;
   memcpy(aBuf, trans->mInputData + trans->mInputDataOffset, tocopy);
   trans->mInputDataOffset += tocopy;
   if (trans->mInputDataOffset == trans->mInputDataUsed) {
--- a/netwerk/protocol/http/TunnelUtils.h
+++ b/netwerk/protocol/http/TunnelUtils.h
@@ -103,25 +103,25 @@ class TLSFilterTransaction MOZ_FINAL
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSAHTTPTRANSACTION
   NS_DECL_NSAHTTPSEGMENTREADER
   NS_DECL_NSAHTTPSEGMENTWRITER
   NS_DECL_NSITIMERCALLBACK
 
   TLSFilterTransaction(nsAHttpTransaction *aWrappedTransaction,
-                       const char *tlsHost, int32_t tlsPort);
+                       const char *tlsHost, int32_t tlsPort,
+                       nsAHttpSegmentReader *reader,
+                       nsAHttpSegmentWriter *writer);
   ~TLSFilterTransaction();
 
   const nsAHttpTransaction *Transaction() const { return mTransaction.get(); }
   nsresult CommitToSegmentSize(uint32_t size, bool forceCommitment);
   nsresult GetTransactionSecurityInfo(nsISupports **);
-  nsresult NudgeTunnel(NudgeTunnelCallback *callback,
-                       nsAHttpSegmentReader *reader,
-                       nsAHttpSegmentWriter *writer);
+  nsresult NudgeTunnel(NudgeTunnelCallback *callback);
 
 private:
   nsresult StartTimerCallback();
   void Cleanup();
   int32_t FilterOutput(const char *aBuf, int32_t aAmount);
   int32_t FilterInput(char *aBuf, int32_t aAmount);
 
   static PRStatus GetPeerName(PRFileDesc *fd, PRNetAddr*addr);
@@ -164,19 +164,21 @@ class ASpdySession;
 
 class SpdyConnectTransaction MOZ_FINAL : public NullHttpTransaction
 {
 public:
   SpdyConnectTransaction(nsHttpConnectionInfo *ci,
                          nsIInterfaceRequestor *callbacks,
                          uint32_t caps,
                          nsAHttpTransaction *trans,
-                         ASpdySession *session);
+                         nsAHttpConnection *session);
   ~SpdyConnectTransaction();
 
+  SpdyConnectTransaction *QuerySpdyConnectTransaction() { return this; }
+
   void MapStreamToHttpConnection(nsISocketTransport *aTransport,
                                  nsHttpConnectionInfo *aConnInfo);
 
   nsresult ReadSegments(nsAHttpSegmentReader *reader,
                         uint32_t count, uint32_t *countRead) MOZ_OVERRIDE MOZ_FINAL;
   nsresult WriteSegments(nsAHttpSegmentWriter *writer,
                          uint32_t count, uint32_t *countWritten) MOZ_OVERRIDE MOZ_FINAL;
   nsHttpRequestHead *RequestHead() MOZ_OVERRIDE MOZ_FINAL;
@@ -188,17 +190,17 @@ private:
 
   nsresult Flush(uint32_t count, uint32_t *countRead);
   void CreateShimError(nsresult code);
 
   nsCString             mConnectString;
   uint32_t              mConnectStringOffset;
   nsHttpRequestHead     *mRequestHead;
 
-  ASpdySession         *mSession;
+  nsAHttpConnection    *mSession;
   nsAHttpSegmentReader *mSegmentReader;
 
   nsAutoArrayPtr<char> mInputData;
   uint32_t             mInputDataSize;
   uint32_t             mInputDataUsed;
   uint32_t             mInputDataOffset;
 
   nsAutoArrayPtr<char> mOutputData;
--- a/netwerk/protocol/http/nsAHttpConnection.h
+++ b/netwerk/protocol/http/nsAHttpConnection.h
@@ -16,19 +16,25 @@ namespace mozilla { namespace net {
 
 class nsHttpConnectionInfo;
 class nsHttpConnection;
 
 //-----------------------------------------------------------------------------
 // Abstract base class for a HTTP connection
 //-----------------------------------------------------------------------------
 
+// 5a66aed7-eede-468b-ac2b-e5fb431fcc5c
+#define NS_AHTTPCONNECTION_IID \
+{ 0x5a66aed7, 0xeede, 0x468b, {0xac, 0x2b, 0xe5, 0xfb, 0x43, 0x1f, 0xcc, 0x5c }}
+
 class nsAHttpConnection : public nsISupports
 {
 public:
+    NS_DECLARE_STATIC_IID_ACCESSOR(NS_AHTTPCONNECTION_IID)
+
     //-------------------------------------------------------------------------
     // NOTE: these methods may only be called on the socket thread.
     //-------------------------------------------------------------------------
 
     //
     // called by a transaction when the response headers have all been read.
     // the connection can force the transaction to reset it's response headers,
     // and prepare for a new set of response headers, by setting |*reset=TRUE|.
@@ -131,16 +137,18 @@ public:
     // not count CONNECT tunnel setup
     virtual int64_t BytesWritten() = 0;
 
     // Update the callbacks used to provide security info. May be called on
     // any thread.
     virtual void SetSecurityCallbacks(nsIInterfaceRequestor* aCallbacks) = 0;
 };
 
+NS_DEFINE_STATIC_IID_ACCESSOR(nsAHttpConnection, NS_AHTTPCONNECTION_IID)
+
 #define NS_DECL_NSAHTTPCONNECTION(fwdObject)                    \
     nsresult OnHeadersAvailable(nsAHttpTransaction *, nsHttpRequestHead *, nsHttpResponseHead *, bool *reset); \
     void CloseTransaction(nsAHttpTransaction *, nsresult); \
     nsresult TakeTransport(nsISocketTransport **,    \
                            nsIAsyncInputStream **,   \
                            nsIAsyncOutputStream **); \
     bool IsPersistent(); \
     bool IsReused(); \
--- a/netwerk/protocol/http/nsAHttpTransaction.h
+++ b/netwerk/protocol/http/nsAHttpTransaction.h
@@ -18,29 +18,36 @@ namespace mozilla { namespace net {
 
 class nsAHttpConnection;
 class nsAHttpSegmentReader;
 class nsAHttpSegmentWriter;
 class nsHttpTransaction;
 class nsHttpPipeline;
 class nsHttpRequestHead;
 class nsHttpConnectionInfo;
+class SpdyConnectTransaction;
 
 //----------------------------------------------------------------------------
 // Abstract base class for a HTTP transaction:
 //
 // A transaction is a "sink" for the response data.  The connection pushes
 // data to the transaction by writing to it.  The transaction supports
 // WriteSegments and may refuse to accept data if its buffers are full (its
 // write function returns NS_BASE_STREAM_WOULD_BLOCK in this case).
 //----------------------------------------------------------------------------
 
+// 2af6d634-13e3-494c-8903-c9dce5c22fc0
+#define NS_AHTTPTRANSACTION_IID \
+{ 0x2af6d634, 0x13e3, 0x494c, {0x89, 0x03, 0xc9, 0xdc, 0xe5, 0xc2, 0x2f, 0xc0 }}
+
 class nsAHttpTransaction : public nsSupportsWeakReference
 {
 public:
+    NS_DECLARE_STATIC_IID_ACCESSOR(NS_AHTTPTRANSACTION_IID)
+
     // called by the connection when it takes ownership of the transaction.
     virtual void SetConnection(nsAHttpConnection *) = 0;
 
     // used to obtain the connection associated with this transaction
     virtual nsAHttpConnection *Connection() = 0;
 
     // called by the connection to get security callbacks to set on the
     // socket transport.
@@ -126,16 +133,21 @@ public:
     // its IO functions all the time.
     virtual bool IsNullTransaction() { return false; }
 
     // If we used rtti this would be the result of doing
     // dynamic_cast<nsHttpTransaction *>(this).. i.e. it can be nullptr for
     // non nsHttpTransaction implementations of nsAHttpTransaction
     virtual nsHttpTransaction *QueryHttpTransaction() { return nullptr; }
 
+    // If we used rtti this would be the result of doing
+    // dynamic_cast<SpdyConnectTransaction *>(this).. i.e. it can be nullptr for
+    // other types
+    virtual SpdyConnectTransaction *QuerySpdyConnectTransaction() { return nullptr; }
+
     // return the load group connection information associated with the transaction
     virtual nsILoadGroupConnectionInfo *LoadGroupConnectionInfo() { return nullptr; }
 
     // return the connection information associated with the transaction
     virtual nsHttpConnectionInfo *ConnectionInfo() = 0;
 
     // The base definition of these is done in nsHttpTransaction.cpp
     virtual bool ResponseTimeoutEnabled() const;
@@ -171,16 +183,18 @@ public:
     // overload. If it returns NS_FAILURE the connection should be considered
     // authoritative.
     virtual nsresult GetTransactionSecurityInfo(nsISupports **)
     {
         return NS_ERROR_NOT_IMPLEMENTED;
     }
 };
 
+NS_DEFINE_STATIC_IID_ACCESSOR(nsAHttpTransaction, NS_AHTTPTRANSACTION_IID)
+
 #define NS_DECL_NSAHTTPTRANSACTION \
     void SetConnection(nsAHttpConnection *); \
     nsAHttpConnection *Connection(); \
     void GetSecurityCallbacks(nsIInterfaceRequestor **);       \
     void OnTransportStatus(nsITransport* transport, \
                            nsresult status, uint64_t progress); \
     bool     IsDone(); \
     nsresult Status(); \
--- a/netwerk/protocol/http/nsHttpConnection.cpp
+++ b/netwerk/protocol/http/nsHttpConnection.cpp
@@ -1342,17 +1342,17 @@ nsHttpConnection::ForceRecv()
 // trigger an asynchronous write
 nsresult
 nsHttpConnection::ForceSend()
 {
     LOG(("nsHttpConnection::ForceSend [this=%p]\n", this));
     MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
 
     if (mTLSFilter) {
-        return mTLSFilter->NudgeTunnel(this, this, this);
+        return mTLSFilter->NudgeTunnel(this);
     }
 
     return NS_DispatchToCurrentThread(new nsHttpConnectionForceIO(this, false));
 }
 
 void
 nsHttpConnection::BeginIdleMonitoring()
 {
@@ -1532,17 +1532,17 @@ nsHttpConnection::OnSocketWritable()
             // wait for the transaction to call ResumeSend.
             if (rv == NS_BASE_STREAM_WOULD_BLOCK)
                 rv = NS_OK;
             again = false;
         } else if (NS_FAILED(mSocketOutCondition)) {
             if (mSocketOutCondition == NS_BASE_STREAM_WOULD_BLOCK) {
                 if (mTLSFilter) {
                     LOG(("  blocked tunnel (handshake?)\n"));
-                    mTLSFilter->NudgeTunnel(this, this, this);
+                    mTLSFilter->NudgeTunnel(this);
                 } else {
                     rv = mSocketOut->AsyncWait(this, 0, 0, nullptr); // continue writing
                 }
             } else {
                 rv = mSocketOutCondition;
             }
             again = false;
         } else if (!transactionBytes) {
@@ -1711,17 +1711,18 @@ void
 nsHttpConnection::SetupSecondaryTLS()
 {
     MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
     MOZ_ASSERT(!mTLSFilter);
     LOG(("nsHttpConnection %p SetupSecondaryTLS %s %d\n",
          this, mConnInfo->Host(), mConnInfo->Port()));
     mTLSFilter = new TLSFilterTransaction(mTransaction,
                                           mConnInfo->Host(),
-                                          mConnInfo->Port());
+                                          mConnInfo->Port(),
+                                          this, this);
     if (mTransaction) {
         mTransaction = mTLSFilter;
     }
 }
 
 void
 nsHttpConnection::SetInSpdyTunnel(bool arg)
 {
--- a/netwerk/protocol/http/nsHttpTransaction.h
+++ b/netwerk/protocol/http/nsHttpTransaction.h
@@ -104,16 +104,17 @@ public:
 
     // setting mDontRouteViaWildCard to true means the transaction should only
     // be dispatched on a specific ConnectionInfo Hash Key (as opposed to a
     // generic wild card one). That means in the specific case of carrying this
     // transaction on an HTTP/2 tunnel it will only be dispatched onto an
     // existing tunnel instead of triggering creation of a new one.
     void SetDontRouteViaWildCard(bool var) { mDontRouteViaWildCard = var; }
     bool DontRouteViaWildCard() { return mDontRouteViaWildCard; }
+    void EnableKeepAlive() { mCaps |= NS_HTTP_ALLOW_KEEPALIVE; }
 
     // SetPriority() may only be used by the connection manager.
     void    SetPriority(int32_t priority) { mPriority = priority; }
     int32_t    Priority()                 { return mPriority; }
 
     const TimingStruct& Timings() const { return mTimings; }
     enum Classifier Classification() { return mClassification; }