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
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 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; }