Bug 1460310 - Separate HTTP and SPDY identifiers into separate namespaces. r?mcmanus draft
authorNicholas Hurley <hurley@mozilla.com>
Fri, 01 Jun 2018 11:32:05 -0700
changeset 802950 4c3d1e6488f747f423300fb80ea6c16b56868a5f
parent 802711 9900cebb1f9000bd05731ba67736b7c51f7eb812
push id112006
push userbmo:hurley@mozilla.com
push dateFri, 01 Jun 2018 18:33:01 +0000
reviewersmcmanus
bugs1460310
milestone62.0a1
Bug 1460310 - Separate HTTP and SPDY identifiers into separate namespaces. r?mcmanus MozReview-Commit-ID: E55YpGK7PXI
netwerk/base/Dashboard.cpp
netwerk/base/DashboardTypes.h
netwerk/protocol/http/ASpdySession.cpp
netwerk/protocol/http/ASpdySession.h
netwerk/protocol/http/AlternateServices.cpp
netwerk/protocol/http/ConnectionDiagnostics.cpp
netwerk/protocol/http/Http2Session.cpp
netwerk/protocol/http/Http2Session.h
netwerk/protocol/http/HttpBaseChannel.cpp
netwerk/protocol/http/PHttpChannelParams.h
netwerk/protocol/http/nsAHttpConnection.h
netwerk/protocol/http/nsHttp.cpp
netwerk/protocol/http/nsHttp.h
netwerk/protocol/http/nsHttpChannel.cpp
netwerk/protocol/http/nsHttpConnection.cpp
netwerk/protocol/http/nsHttpConnection.h
netwerk/protocol/http/nsHttpHandler.cpp
netwerk/protocol/http/nsHttpHandler.h
netwerk/protocol/http/nsHttpRequestHead.cpp
netwerk/protocol/http/nsHttpRequestHead.h
netwerk/protocol/http/nsHttpResponseHead.cpp
netwerk/protocol/http/nsHttpResponseHead.h
netwerk/protocol/http/nsHttpTransaction.cpp
netwerk/protocol/http/nsHttpTransaction.h
--- a/netwerk/base/Dashboard.cpp
+++ b/netwerk/base/Dashboard.cpp
@@ -844,40 +844,40 @@ Dashboard::GetRcwnData(RcwnData *aData)
     }
 
     aData->mCallback->OnDashboardDataAvailable(val);
 
     return NS_OK;
 }
 
 void
-HttpConnInfo::SetHTTP1ProtocolVersion(uint8_t pv)
+HttpConnInfo::SetHTTP1ProtocolVersion(HttpVersion pv)
 {
     switch (pv) {
-    case NS_HTTP_VERSION_0_9:
+    case HttpVersion::v0_9:
         protocolVersion.AssignLiteral(u"http/0.9");
         break;
-    case NS_HTTP_VERSION_1_0:
+    case HttpVersion::v1_0:
         protocolVersion.AssignLiteral(u"http/1.0");
         break;
-    case NS_HTTP_VERSION_1_1:
+    case HttpVersion::v1_1:
         protocolVersion.AssignLiteral(u"http/1.1");
         break;
-    case NS_HTTP_VERSION_2_0:
+    case HttpVersion::v2_0:
         protocolVersion.AssignLiteral(u"http/2.0");
         break;
     default:
         protocolVersion.AssignLiteral(u"unknown protocol version");
     }
 }
 
 void
-HttpConnInfo::SetHTTP2ProtocolVersion(uint8_t pv)
+HttpConnInfo::SetHTTP2ProtocolVersion(SpdyVersion pv)
 {
-    MOZ_ASSERT(pv == HTTP_VERSION_2);
+    MOZ_ASSERT(pv == SpdyVersion::HTTP_2);
     protocolVersion.AssignLiteral(u"h2");
 }
 
 NS_IMETHODIMP
 Dashboard::GetLogPath(nsACString &aLogPath)
 {
     aLogPath.SetCapacity(2048);
     uint32_t len = LogModule::GetLogFile(aLogPath.BeginWriting(), 2048);
--- a/netwerk/base/DashboardTypes.h
+++ b/netwerk/base/DashboardTypes.h
@@ -1,15 +1,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_net_DashboardTypes_h_
 #define mozilla_net_DashboardTypes_h_
 
+#include "nsHttp.h"
 #include "nsString.h"
 #include "nsTArray.h"
 
 namespace mozilla {
 namespace net {
 
 struct SocketInfo
 {
@@ -37,18 +38,18 @@ struct DNSCacheEntries
 };
 
 struct HttpConnInfo
 {
     uint32_t ttl;
     uint32_t rtt;
     nsString protocolVersion;
 
-    void SetHTTP1ProtocolVersion(uint8_t pv);
-    void SetHTTP2ProtocolVersion(uint8_t pv);
+    void SetHTTP1ProtocolVersion(HttpVersion pv);
+    void SetHTTP2ProtocolVersion(SpdyVersion pv);
 };
 
 struct HttpRetParams
 {
     nsCString host;
     nsTArray<HttpConnInfo>   active;
     nsTArray<HttpConnInfo>   idle;
     nsTArray<HalfOpenSockets> halfOpens;
--- a/netwerk/protocol/http/ASpdySession.cpp
+++ b/netwerk/protocol/http/ASpdySession.cpp
@@ -20,40 +20,40 @@
 #include "Http2Session.h"
 
 #include "mozilla/Telemetry.h"
 
 namespace mozilla {
 namespace net {
 
 ASpdySession *
-ASpdySession::NewSpdySession(uint32_t version,
+ASpdySession::NewSpdySession(net::SpdyVersion version,
                              nsISocketTransport *aTransport,
                              bool attemptingEarlyData)
 {
   // This is a necko only interface, so we can enforce version
   // requests as a precondition
-  MOZ_ASSERT(version == HTTP_VERSION_2,
+  MOZ_ASSERT(version == SpdyVersion::HTTP_2,
              "Unsupported spdy version");
 
   // Don't do a runtime check of IsSpdyV?Enabled() here because pref value
   // may have changed since starting negotiation. The selected protocol comes
   // from a list provided in the SERVER HELLO filtered by our acceptable
   // versions, so there is no risk of the server ignoring our prefs.
 
-  Telemetry::Accumulate(Telemetry::SPDY_VERSION2, version);
+  Telemetry::Accumulate(Telemetry::SPDY_VERSION2, static_cast<uint32_t>(version));
 
   return new Http2Session(aTransport, version, attemptingEarlyData);
 }
 
 SpdyInformation::SpdyInformation()
 {
   // highest index of enabled protocols is the
   // most preferred for ALPN negotiaton
-  Version[0] = HTTP_VERSION_2;
+  Version[0] = SpdyVersion::HTTP_2;
   VersionString[0] = NS_LITERAL_CSTRING("h2");
   ALPNCallbacks[0] = Http2Session::ALPNCallback;
 }
 
 bool
 SpdyInformation::ProtocolEnabled(uint32_t index) const
 {
   MOZ_ASSERT(index < kCount, "index out of range");
--- a/netwerk/protocol/http/ASpdySession.h
+++ b/netwerk/protocol/http/ASpdySession.h
@@ -23,19 +23,19 @@ public:
 
   virtual MOZ_MUST_USE bool
   AddStream(nsAHttpTransaction *, int32_t, bool, nsIInterfaceRequestor *) = 0;
   virtual bool CanReuse() = 0;
   virtual bool RoomForMoreStreams() = 0;
   virtual PRIntervalTime IdleTime() = 0;
   virtual uint32_t ReadTimeoutTick(PRIntervalTime now) = 0;
   virtual void DontReuse() = 0;
-  virtual uint32_t SpdyVersion() = 0;
+  virtual enum SpdyVersion SpdyVersion() = 0;
 
-  static ASpdySession *NewSpdySession(uint32_t version, nsISocketTransport *, bool);
+  static ASpdySession *NewSpdySession(net::SpdyVersion version, nsISocketTransport *, bool);
 
   virtual bool TestJoinConnection(const nsACString &hostname, int32_t port) = 0;
   virtual bool JoinConnection(const nsACString &hostname, int32_t port) = 0;
 
   // MaybeReTunnel() is called by the connection manager when it cannot
   // dispatch a tunneled transaction. That might be because the tunnels it
   // expects to see are dead (and we may or may not be able to make more),
   // or it might just need to wait longer for one of them to become free.
@@ -103,17 +103,17 @@ public:
 
   // determine the index (0..kCount-1) of the spdy information that
   // correlates to the npn string. NS_FAILED() if no match is found.
   MOZ_MUST_USE nsresult GetNPNIndex(const nsACString &npnString, uint32_t *result) const;
 
   // determine if a version of the protocol is enabled for index < kCount
   bool ProtocolEnabled(uint32_t index) const;
 
-  uint8_t   Version[kCount]; // telemetry enum e.g. SPDY_VERSION_31
+  SpdyVersion Version[kCount]; // telemetry enum e.g. SPDY_VERSION_31
   nsCString VersionString[kCount]; // npn string e.g. "spdy/3.1"
 
   // the ALPNCallback function allows the protocol stack to decide whether or
   // not to offer a particular protocol based on the known TLS information
   // that we will offer in the client hello (such as version). There has
   // not been a Server Hello received yet, so not much else can be considered.
   ALPNCallback ALPNCallbacks[kCount];
 };
--- a/netwerk/protocol/http/AlternateServices.cpp
+++ b/netwerk/protocol/http/AlternateServices.cpp
@@ -486,19 +486,19 @@ private:
     }
 
     if (NS_FAILED(reason) || !mRunning || !mConnection) {
       LOG(("AltSvcTransaction::MaybeValidate %p Failed due to precondition", this));
       return;
     }
 
     // insist on >= http/2
-    uint32_t version = mConnection->Version();
-    LOG(("AltSvcTransaction::MaybeValidate() %p version %d\n", this, version));
-    if (version != HTTP_VERSION_2) {
+    HttpVersion version = mConnection->Version();
+    LOG(("AltSvcTransaction::MaybeValidate() %p version %d\n", this, static_cast<int32_t>(version)));
+    if (version != HttpVersion::v2_0) {
       LOG(("AltSvcTransaction::MaybeValidate %p Failed due to protocol version", this));
       return;
     }
 
     nsCOMPtr<nsISupports> secInfo;
     mConnection->GetSecurityInfo(getter_AddRefs(secInfo));
     nsCOMPtr<nsISSLSocketControl> socketControl = do_QueryInterface(secInfo);
 
@@ -732,25 +732,25 @@ TransactionObserver::Complete(nsHttpTran
   mRanOnce = true;
 
   RefPtr<nsAHttpConnection> conn = aTrans->GetConnectionReference();
   LOG(("TransactionObserver::Complete %p aTrans %p reason %" PRIx32 " conn %p\n",
        this, aTrans, static_cast<uint32_t>(reason), conn.get()));
   if (!conn) {
     return;
   }
-  uint32_t version = conn->Version();
+  HttpVersion version = conn->Version();
   mVersionOK = (((reason == NS_BASE_STREAM_CLOSED) || (reason == NS_OK)) &&
-                conn->Version() == HTTP_VERSION_2);
+                conn->Version() == HttpVersion::v2_0);
 
   nsCOMPtr<nsISupports> secInfo;
   conn->GetSecurityInfo(getter_AddRefs(secInfo));
   nsCOMPtr<nsISSLSocketControl> socketControl = do_QueryInterface(secInfo);
   LOG(("TransactionObserver::Complete version %u socketControl %p\n",
-       version, socketControl.get()));
+       static_cast<int32_t>(version), socketControl.get()));
   if (!socketControl) {
     return;
   }
 
   mAuthOK = !socketControl->GetFailedVerification();
   LOG(("TransactionObserve::Complete %p trans %p authOK %d versionOK %d\n",
        this, aTrans, mAuthOK, mVersionOK));
 }
--- a/netwerk/protocol/http/ConnectionDiagnostics.cpp
+++ b/netwerk/protocol/http/ConnectionDiagnostics.cpp
@@ -131,17 +131,17 @@ void
 nsHttpConnection::PrintDiagnostics(nsCString &log)
 {
   log.AppendPrintf("    CanDirectlyActivate = %d\n", CanDirectlyActivate());
 
   log.AppendPrintf("    npncomplete = %d  setupSSLCalled = %d\n",
                    mNPNComplete, mSetupSSLCalled);
 
   log.AppendPrintf("    spdyVersion = %d  reportedSpdy = %d everspdy = %d\n",
-                   mUsingSpdyVersion, mReportedSpdy, mEverUsedSpdy);
+                   static_cast<int32_t>(mUsingSpdyVersion), mReportedSpdy, mEverUsedSpdy);
 
   log.AppendPrintf("    iskeepalive = %d  dontReuse = %d isReused = %d\n",
                    IsKeepAlive(), mDontReuse, mIsReused);
 
   log.AppendPrintf("    mTransaction = %d mSpdySession = %d\n",
                    !!mTransaction.get(), !!mSpdySession.get());
 
   PRIntervalTime now = PR_IntervalNow();
--- a/netwerk/protocol/http/Http2Session.cpp
+++ b/netwerk/protocol/http/Http2Session.cpp
@@ -63,17 +63,17 @@ const uint8_t Http2Session::kMagicHello[
 };
 
 #define RETURN_SESSION_ERROR(o,x)  \
 do {                             \
   (o)->mGoAwayReason = (x);      \
   return NS_ERROR_ILLEGAL_VALUE; \
   } while (0)
 
-Http2Session::Http2Session(nsISocketTransport *aSocketTransport, uint32_t version, bool attemptingEarlyData)
+Http2Session::Http2Session(nsISocketTransport *aSocketTransport, enum SpdyVersion version, bool attemptingEarlyData)
   : mSocketTransport(aSocketTransport)
   , mSegmentReader(nullptr)
   , mSegmentWriter(nullptr)
   , mNextStreamID(3) // 1 is reserved for Updgrade handshakes
   , mLastPushedID(0)
   , mConcurrentHighWater(0)
   , mDownstreamState(BUFFERING_OPENING_SETTINGS)
   , mInputFrameBufferSize(kDefaultBufferSize)
@@ -634,20 +634,20 @@ Http2Session::DontReuse()
   }
 
   mShouldGoAway = true;
   if (!mClosed && !mStreamTransactionHash.Count()) {
     Close(NS_OK);
   }
 }
 
-uint32_t
+enum SpdyVersion
 Http2Session::SpdyVersion()
 {
-  return HTTP_VERSION_2;
+  return SpdyVersion::HTTP_2;
 }
 
 uint32_t
 Http2Session::GetWriteQueueSize()
 {
   MOZ_ASSERT(OnSocketThread(), "not on socket thread");
 
   return mReadyForWrite.GetSize();
--- a/netwerk/protocol/http/Http2Session.h
+++ b/netwerk/protocol/http/Http2Session.h
@@ -41,23 +41,23 @@ class Http2Session final : public ASpdyS
 
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSAHTTPTRANSACTION
   NS_DECL_NSAHTTPCONNECTION(mConnection)
   NS_DECL_NSAHTTPSEGMENTREADER
   NS_DECL_NSAHTTPSEGMENTWRITER
 
-  Http2Session(nsISocketTransport *, uint32_t version, bool attemptingEarlyData);
+  Http2Session(nsISocketTransport *, enum SpdyVersion version, bool attemptingEarlyData);
 
   MOZ_MUST_USE bool AddStream(nsAHttpTransaction *, int32_t,
                               bool, nsIInterfaceRequestor *) override;
   bool CanReuse() override { return !mShouldGoAway && !mClosed; }
   bool RoomForMoreStreams() override;
-  uint32_t SpdyVersion() override;
+  enum SpdyVersion SpdyVersion() override;
   bool TestJoinConnection(const nsACString &hostname, int32_t port) override;
   bool JoinConnection(const nsACString &hostname, int32_t port) override;
 
   // When the connection is active this is called up to once every 1 second
   // return the interval (in seconds) that the connection next wants to
   // have this invoked. It might happen sooner depending on the needs of
   // other connections.
   uint32_t  ReadTimeoutTick(PRIntervalTime now) override;
--- a/netwerk/protocol/http/HttpBaseChannel.cpp
+++ b/netwerk/protocol/http/HttpBaseChannel.cpp
@@ -2326,17 +2326,17 @@ HttpBaseChannel::GetProtocolVersion(nsAC
       NS_SUCCEEDED(ssl->GetNegotiatedNPN(protocol)) &&
       !protocol.IsEmpty()) {
     // The negotiated protocol was not empty so we can use it.
     aProtocolVersion = protocol;
     return NS_OK;
   }
 
   if (mResponseHead) {
-    uint32_t version = mResponseHead->Version();
+    HttpVersion version = mResponseHead->Version();
     aProtocolVersion.Assign(nsHttp::GetProtocolVersion(version));
     return NS_OK;
   }
 
   return NS_ERROR_NOT_AVAILABLE;
 }
 
 
@@ -2418,37 +2418,37 @@ HttpBaseChannel::SetDocumentURI(nsIURI *
 
   mDocumentURI = aDocumentURI;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 HttpBaseChannel::GetRequestVersion(uint32_t *major, uint32_t *minor)
 {
-  nsHttpVersion version = mRequestHead.Version();
-
-  if (major) { *major = version / 10; }
-  if (minor) { *minor = version % 10; }
+  HttpVersion version = mRequestHead.Version();
+
+  if (major) { *major = static_cast<uint32_t>(version) / 10; }
+  if (minor) { *minor = static_cast<uint32_t>(version) % 10; }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 HttpBaseChannel::GetResponseVersion(uint32_t *major, uint32_t *minor)
 {
   if (!mResponseHead)
   {
     *major = *minor = 0; // we should at least be kind about it
     return NS_ERROR_NOT_AVAILABLE;
   }
 
-  nsHttpVersion version = mResponseHead->Version();
-
-  if (major) { *major = version / 10; }
-  if (minor) { *minor = version % 10; }
+  HttpVersion version = mResponseHead->Version();
+
+  if (major) { *major = static_cast<uint32_t>(version) / 10; }
+  if (minor) { *minor = static_cast<uint32_t>(version) % 10; }
 
   return NS_OK;
 }
 
 void
 HttpBaseChannel::NotifySetCookie(char const *aCookie)
 {
   nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
--- a/netwerk/protocol/http/PHttpChannelParams.h
+++ b/netwerk/protocol/http/PHttpChannelParams.h
@@ -192,42 +192,44 @@ struct ParamTraits<mozilla::net::nsHttpH
 template<>
 struct ParamTraits<mozilla::net::nsHttpResponseHead>
 {
   typedef mozilla::net::nsHttpResponseHead paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, aParam.mHeaders);
-    WriteParam(aMsg, aParam.mVersion);
+    WriteParam(aMsg, static_cast<uint32_t>(aParam.mVersion));
     WriteParam(aMsg, aParam.mStatus);
     WriteParam(aMsg, aParam.mStatusText);
     WriteParam(aMsg, aParam.mContentLength);
     WriteParam(aMsg, aParam.mContentType);
     WriteParam(aMsg, aParam.mContentCharset);
     WriteParam(aMsg, aParam.mCacheControlPrivate);
     WriteParam(aMsg, aParam.mCacheControlNoStore);
     WriteParam(aMsg, aParam.mCacheControlNoCache);
     WriteParam(aMsg, aParam.mPragmaNoCache);
   }
 
   static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
+    uint32_t version;
     if (!ReadParam(aMsg, aIter, &aResult->mHeaders)             ||
-        !ReadParam(aMsg, aIter, &aResult->mVersion)             ||
+        !ReadParam(aMsg, aIter, &version)             ||
         !ReadParam(aMsg, aIter, &aResult->mStatus)              ||
         !ReadParam(aMsg, aIter, &aResult->mStatusText)          ||
         !ReadParam(aMsg, aIter, &aResult->mContentLength)       ||
         !ReadParam(aMsg, aIter, &aResult->mContentType)         ||
         !ReadParam(aMsg, aIter, &aResult->mContentCharset)      ||
         !ReadParam(aMsg, aIter, &aResult->mCacheControlPrivate) ||
         !ReadParam(aMsg, aIter, &aResult->mCacheControlNoStore) ||
         !ReadParam(aMsg, aIter, &aResult->mCacheControlNoCache) ||
         !ReadParam(aMsg, aIter, &aResult->mPragmaNoCache))
       return false;
 
+    aResult->mVersion = static_cast<mozilla::net::HttpVersion>(version);
     return true;
   }
 };
 
 } // namespace IPC
 
 #endif // mozilla_net_PHttpChannelParams_h
--- a/netwerk/protocol/http/nsAHttpConnection.h
+++ b/netwerk/protocol/http/nsAHttpConnection.h
@@ -138,17 +138,17 @@ 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;
 
     // nsHttp.h version
-    virtual uint32_t Version() = 0;
+    virtual HttpVersion Version() = 0;
 
     // A notification of the current active tab id change.
     virtual void TopLevelOuterContentWindowIdChanged(uint64_t windowId) = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsAHttpConnection, NS_AHTTPCONNECTION_IID)
 
 #define NS_DECL_NSAHTTPCONNECTION(fwdObject)                    \
@@ -214,21 +214,21 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsAHttpCon
     }                                      \
     nsISocketTransport *Transport()        \
       override                         \
     {                                      \
         if (!(fwdObject))                  \
             return nullptr;                 \
         return (fwdObject)->Transport();   \
     }                                      \
-    uint32_t Version() override        \
+    HttpVersion Version() override        \
     {                                      \
         return (fwdObject) ?               \
             (fwdObject)->Version() :       \
-            NS_HTTP_VERSION_UNKNOWN;       \
+            mozilla::net::HttpVersion::UNKNOWN;       \
     }                                      \
     bool IsProxyConnectInProgress() override                \
     {                                                       \
         return (!fwdObject) ? false :                       \
                (fwdObject)->IsProxyConnectInProgress();     \
     }                                                       \
     bool LastTransactionExpectedNoContent() override        \
     {                                                       \
--- a/netwerk/protocol/http/nsHttp.cpp
+++ b/netwerk/protocol/http/nsHttp.cpp
@@ -233,29 +233,28 @@ IsValidToken(const char *start, const ch
         if (idx > 127 || !kValidTokenMap[idx])
             return false;
     }
 
     return true;
 }
 
 const char*
-GetProtocolVersion(uint32_t pv)
+GetProtocolVersion(HttpVersion pv)
 {
     switch (pv) {
-    case HTTP_VERSION_2:
-    case NS_HTTP_VERSION_2_0:
+    case HttpVersion::v2_0:
         return "h2";
-    case NS_HTTP_VERSION_1_0:
+    case HttpVersion::v1_0:
         return "http/1.0";
-    case NS_HTTP_VERSION_1_1:
+    case HttpVersion::v1_1:
         return "http/1.1";
     default:
         NS_WARNING(nsPrintfCString("Unkown protocol version: 0x%X. "
-                                   "Please file a bug", pv).get());
+                                   "Please file a bug", static_cast<uint32_t>(pv)).get());
         return "http/1.1";
     }
 }
 
 // static
 void
 TrimHTTPWhitespace(const nsACString& aSource, nsACString& aDest)
 {
@@ -568,16 +567,25 @@ TimeStamp const GetLastActiveTabLoadOpti
 void
 SetLastActiveTabLoadOptimizationHit(TimeStamp const &when)
 {
   if (gHttpHandler) {
     gHttpHandler->SetLastActiveTabLoadOptimizationHit(when);
   }
 }
 
+HttpVersion
+GetHttpVersionFromSpdy(SpdyVersion sv)
+{
+    MOZ_DIAGNOSTIC_ASSERT(sv != SpdyVersion::NONE);
+    MOZ_ASSERT(sv == SpdyVersion::HTTP_2);
+
+    return HttpVersion::v2_0;
+}
+
 } // namespace nsHttp
 
 
 template<typename T> void
 localEnsureBuffer(UniquePtr<T[]> &buf, uint32_t newSize,
              uint32_t preserve, uint32_t &objSize)
 {
   if (objSize >= newSize)
--- a/netwerk/protocol/http/nsHttp.h
+++ b/netwerk/protocol/http/nsHttp.h
@@ -11,53 +11,53 @@
 #include "prtime.h"
 #include "nsAutoPtr.h"
 #include "nsString.h"
 #include "nsError.h"
 #include "nsTArray.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/UniquePtr.h"
 
-// http version codes
-#define NS_HTTP_VERSION_UNKNOWN  0
-#define NS_HTTP_VERSION_0_9      9
-#define NS_HTTP_VERSION_1_0     10
-#define NS_HTTP_VERSION_1_1     11
-#define NS_HTTP_VERSION_2_0     20
-
 class nsICacheEntry;
 
 namespace mozilla {
 
 class Mutex;
 
 namespace net {
     class nsHttpResponseHead;
     class nsHttpRequestHead;
     class CacheControlParser;
 
-    enum {
+    enum class HttpVersion {
+        UNKNOWN = 0,
+        v0_9 = 9,
+        v1_0 = 10,
+        v1_1 = 11,
+        v2_0 = 20
+    };
+
+    enum class SpdyVersion {
+        NONE = 0,
         // SPDY_VERSION_2 = 2, REMOVED
         // SPDY_VERSION_3 = 3, REMOVED
         // SPDY_VERSION_31 = 4, REMOVED
-        HTTP_VERSION_2 = 5
+        HTTP_2 = 5
 
         // leave room for official versions. telem goes to 48
         // 24 was a internal spdy/3.1
         // 25 was spdy/4a2
         // 26 was http/2-draft08 and http/2-draft07 (they were the same)
         // 27 was http/2-draft09, h2-10, and h2-11
         // 28 was http/2-draft12
         // 29 was http/2-draft13
         // 30 was h2-14 and h2-15
         // 31 was h2-16
     };
 
-typedef uint8_t nsHttpVersion;
-
 //-----------------------------------------------------------------------------
 // http connection capabilities
 //-----------------------------------------------------------------------------
 
 #define NS_HTTP_ALLOW_KEEPALIVE      (1<<0)
 #define NS_HTTP_LARGE_KEEPALIVE      (1<<1)
 
 // a transaction with this caps flag will continue to own the connection,
@@ -192,17 +192,17 @@ namespace nsHttp
         const char *next;
         return ParseInt64(input, &next, result) && *next == '\0';
     }
 
     // Return whether the HTTP status code represents a permanent redirect
     bool IsPermanentRedirect(uint32_t httpStatus);
 
     // Returns the APLN token which represents the used protocol version.
-    const char* GetProtocolVersion(uint32_t pv);
+    const char* GetProtocolVersion(HttpVersion pv);
 
     bool ValidationRequired(bool isForcedValid, nsHttpResponseHead *cachedResponseHead,
                    uint32_t loadFlags, bool allowStaleCacheContent,
                    bool isImmutable, bool customConditionalRequest,
                    nsHttpRequestHead &requestHead,
                    nsICacheEntry *entry, CacheControlParser &cacheControlRequest,
                    bool fromPreviousSession);
 
@@ -220,16 +220,18 @@ namespace nsHttp
     // Called when an optimization feature affecting active vs background tab load
     // took place.  Called only on the parent process and only updates
     // mLastActiveTabLoadOptimizationHit timestamp to now.
     void NotifyActiveTabLoadOptimization();
     TimeStamp const GetLastActiveTabLoadOptimizationHit();
     void SetLastActiveTabLoadOptimizationHit(TimeStamp const &when);
     bool IsBeforeLastActiveTabLoadOptimization(TimeStamp const &when);
 
+    HttpVersion GetHttpVersionFromSpdy(SpdyVersion sv);
+
     // Declare all atoms
     //
     // The atom names and values are stored in nsHttpAtomList.h and are brought
     // to you by the magic of C preprocessing.  Add new atoms to nsHttpAtomList
     // and all support logic will be auto-generated.
     //
 #define HTTP_ATOM(_name, _value) extern nsHttpAtom _name;
 #include "nsHttpAtomList.h"
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -1045,28 +1045,28 @@ nsHttpChannel::SetupTransaction()
     if (mLoadFlags & LOAD_BYPASS_CACHE) {
         // We need to send 'Pragma:no-cache' to inhibit proxy caching even if
         // no proxy is configured since we might be talking with a transparent
         // proxy, i.e. one that operates at the network level.  See bug #14772.
         rv = mRequestHead.SetHeaderOnce(nsHttp::Pragma, "no-cache", true);
         MOZ_ASSERT(NS_SUCCEEDED(rv));
         // If we're configured to speak HTTP/1.1 then also send 'Cache-control:
         // no-cache'
-        if (mRequestHead.Version() >= NS_HTTP_VERSION_1_1) {
+        if (mRequestHead.Version() >= HttpVersion::v1_1) {
             rv = mRequestHead.SetHeaderOnce(nsHttp::Cache_Control, "no-cache", true);
             MOZ_ASSERT(NS_SUCCEEDED(rv));
         }
     }
     else if ((mLoadFlags & VALIDATE_ALWAYS) && !mCacheEntryIsWriteOnly) {
         // We need to send 'Cache-Control: max-age=0' to force each cache along
         // the path to the origin server to revalidate its own entry, if any,
         // with the next cache or server.  See bug #84847.
         //
         // If we're configured to speak HTTP/1.0 then just send 'Pragma: no-cache'
-        if (mRequestHead.Version() >= NS_HTTP_VERSION_1_1)
+        if (mRequestHead.Version() >= HttpVersion::v1_1)
             rv = mRequestHead.SetHeaderOnce(nsHttp::Cache_Control, "max-age=0", true);
         else
             rv = mRequestHead.SetHeaderOnce(nsHttp::Pragma, "no-cache", true);
         MOZ_ASSERT(NS_SUCCEEDED(rv));
     }
 
     if (mResuming) {
         char byteRange[32];
@@ -1464,17 +1464,17 @@ nsHttpChannel::CallOnStartRequest()
         }
     }
 
     bool unknownDecoderStarted = false;
     if (mResponseHead && !mResponseHead->HasContentType()) {
         MOZ_ASSERT(mConnectionInfo, "Should have connection info here");
         if (!mContentTypeHint.IsEmpty())
             mResponseHead->SetContentType(mContentTypeHint);
-        else if (mResponseHead->Version() == NS_HTTP_VERSION_0_9 &&
+        else if (mResponseHead->Version() == HttpVersion::v0_9 &&
                  mConnectionInfo->OriginPort() != mConnectionInfo->DefaultPort())
             mResponseHead->SetContentType(NS_LITERAL_CSTRING(TEXT_PLAIN));
         else {
             // Uh-oh.  We had better find out what type we are!
             nsCOMPtr<nsIStreamConverterService> serv;
             rv = gHttpHandler->
                 GetStreamConverterService(getter_AddRefs(serv));
             // If we failed, we just fall through to the "normal" case
@@ -2483,19 +2483,19 @@ nsHttpChannel::ContinueProcessResponse2(
         } else if (successfulReval) {
             cacheDisposition = kCacheHitViaReval;
         } else {
             cacheDisposition = kCacheMissedViaReval;
         }
         AccumulateCacheHitTelemetry(cacheDisposition);
 
         Telemetry::Accumulate(Telemetry::HTTP_RESPONSE_VERSION,
-                              mResponseHead->Version());
-
-        if (mResponseHead->Version() == NS_HTTP_VERSION_0_9) {
+                              static_cast<uint32_t>(mResponseHead->Version()));
+
+        if (mResponseHead->Version() == HttpVersion::v0_9) {
             // DefaultPortTopLevel = 0, DefaultPortSubResource = 1,
             // NonDefaultPortTopLevel = 2, NonDefaultPortSubResource = 3
             uint32_t v09Info = 0;
             if (!(mLoadFlags & LOAD_INITIAL_DOCUMENT_URI)) {
                 v09Info += 1;
             }
             if (mConnectionInfo->OriginPort() != mConnectionInfo->DefaultPort()) {
                 v09Info += 2;
@@ -7264,17 +7264,17 @@ nsHttpChannel::OnStopRequest(nsIRequest 
         upgradeChanDisposition = Telemetry::LABELS_HTTP_CHANNEL_DISPOSITION_UPGRADE::cancel;
     } else if (!mUsedNetwork ||
                (mRaceCacheWithNetwork &&
                 mFirstResponseSource == RESPONSE_FROM_CACHE)) {
         chanDisposition = kHttpDisk;
         upgradeChanDisposition = Telemetry::LABELS_HTTP_CHANNEL_DISPOSITION_UPGRADE::disk;
     } else if (NS_SUCCEEDED(status) &&
                mResponseHead &&
-               mResponseHead->Version() != NS_HTTP_VERSION_0_9) {
+               mResponseHead->Version() != HttpVersion::v0_9) {
         chanDisposition = kHttpNetOK;
         upgradeChanDisposition = Telemetry::LABELS_HTTP_CHANNEL_DISPOSITION_UPGRADE::netOk;
     } else if (!mTransferSize) {
         chanDisposition = kHttpNetEarlyFail;
         upgradeChanDisposition = Telemetry::LABELS_HTTP_CHANNEL_DISPOSITION_UPGRADE::netEarlyFail;
     } else {
         chanDisposition = kHttpNetLateFail;
         upgradeChanDisposition = Telemetry::LABELS_HTTP_CHANNEL_DISPOSITION_UPGRADE::netLateFail;
--- a/netwerk/protocol/http/nsHttpConnection.cpp
+++ b/netwerk/protocol/http/nsHttpConnection.cpp
@@ -70,21 +70,21 @@ nsHttpConnection::nsHttpConnection()
     , mExperienced(false)
     , mInSpdyTunnel(false)
     , mForcePlainText(false)
     , mTrafficStamp(false)
     , mHttp1xTransactionCount(0)
     , mRemainingConnectionUses(0xffffffff)
     , mNPNComplete(false)
     , mSetupSSLCalled(false)
-    , mUsingSpdyVersion(0)
+    , mUsingSpdyVersion(SpdyVersion::NONE)
     , mPriority(nsISupportsPriority::PRIORITY_NORMAL)
     , mReportedSpdy(false)
     , mEverUsedSpdy(false)
-    , mLastHttpResponseVersion(NS_HTTP_VERSION_1_1)
+    , mLastHttpResponseVersion(HttpVersion::v1_1)
     , mTransactionCaps(0)
     , mDefaultTimeoutFactor(1)
     , mResponseTimeoutEnabled(false)
     , mTCPKeepaliveConfig(kTCPKeepaliveDisabled)
     , mForceSendPending(false)
     , m0RTTChecked(false)
     , mWaitingFor0RTTResponse(false)
     , mContentBytesWritten0RTT(0)
@@ -241,17 +241,17 @@ nsHttpConnection::MoveTransactionsToSpdy
             }
         }
     }
 
     return NS_OK;
 }
 
 void
-nsHttpConnection::Start0RTTSpdy(uint8_t spdyVersion)
+nsHttpConnection::Start0RTTSpdy(SpdyVersion spdyVersion)
 {
     LOG(("nsHttpConnection::Start0RTTSpdy [this=%p]", this));
 
     MOZ_ASSERT(OnSocketThread(), "not on socket thread");
 
     mDid0RTTSpdy = true;
     mUsingSpdyVersion = spdyVersion;
     mSpdySession = ASpdySession::NewSpdySession(spdyVersion, mSocketTransport,
@@ -271,17 +271,17 @@ nsHttpConnection::Start0RTTSpdy(uint8_t 
              "transactions rv=%" PRIx32 , this, static_cast<uint32_t>(rv)));
         return;
     }
 
     mTransaction = mSpdySession;
 }
 
 void
-nsHttpConnection::StartSpdy(nsISSLSocketControl *sslControl, uint8_t spdyVersion)
+nsHttpConnection::StartSpdy(nsISSLSocketControl *sslControl, SpdyVersion spdyVersion)
 {
     LOG(("nsHttpConnection::StartSpdy [this=%p, mDid0RTTSpdy=%d]\n", this, mDid0RTTSpdy));
 
     MOZ_ASSERT(OnSocketThread(), "not on socket thread");
     MOZ_ASSERT(!mSpdySession || mDid0RTTSpdy);
 
     mUsingSpdyVersion = spdyVersion;
     mEverUsedSpdy = true;
@@ -601,17 +601,17 @@ npnComplete:
             mTransaction->Close(NS_ERROR_NET_RESET);
         }
         mContentBytesWritten0RTT = 0;
     }
 
     if (mDid0RTTSpdy && negotiatedNPN != mEarlyNegotiatedALPN) {
         // Reset the work done by Start0RTTSpdy
         LOG(("nsHttpConnection::EnsureNPNComplete [this=%p] resetting Start0RTTSpdy", this));
-        mUsingSpdyVersion = 0;
+        mUsingSpdyVersion = SpdyVersion::NONE;
         mTransaction = nullptr;
         mSpdySession = nullptr;
         // We have to reset this here, just in case we end up starting spdy again,
         // so it can actually do everything it needs to do.
         mDid0RTTSpdy = false;
     }
     return true;
 }
@@ -652,17 +652,17 @@ nsHttpConnection::Activate(nsAHttpTransa
     }
 
     if (caps & NS_HTTP_LARGE_KEEPALIVE) {
         mDefaultTimeoutFactor = 10; // don't ever lower
     }
 
     mTransactionCaps = caps;
     mPriority = pri;
-    if (mTransaction && mUsingSpdyVersion) {
+    if (mTransaction && (mUsingSpdyVersion != SpdyVersion::NONE)) {
         return AddTransaction(trans, pri);
     }
 
     NS_ENSURE_ARG_POINTER(trans);
     NS_ENSURE_TRUE(!mTransaction, NS_ERROR_IN_PROGRESS);
 
     // If TCP fast Open has been used and conection was idle for some time
     // we will be cautious and watch out for bug 1395494.
@@ -835,17 +835,17 @@ nsHttpConnection::SetupNPNList(nsISSLSoc
     return rv;
 }
 
 nsresult
 nsHttpConnection::AddTransaction(nsAHttpTransaction *httpTransaction,
                                  int32_t priority)
 {
     MOZ_ASSERT(OnSocketThread(), "not on socket thread");
-    MOZ_ASSERT(mSpdySession && mUsingSpdyVersion,
+    MOZ_ASSERT(mSpdySession && (mUsingSpdyVersion != SpdyVersion::NONE),
                "AddTransaction to live http connection without spdy");
 
     // If this is a wild card nshttpconnection (i.e. a spdy proxy) then
     // it is important to start the stream using the specific connection
     // info of the transaction to ensure it is routed on the right tunnel
 
     nsHttpConnectionInfo *transCI = httpTransaction->ConnectionInfo();
 
@@ -1017,17 +1017,18 @@ nsHttpConnection::CanReuse()
     canReuse = canReuse && (IdleTime() < mIdleTimeout) && IsAlive();
 
     // An idle persistent connection should not have data waiting to be read
     // before a request is sent. Data here is likely a 408 timeout response
     // which we would deal with later on through the restart logic, but that
     // path is more expensive than just closing the socket now.
 
     uint64_t dataSize;
-    if (canReuse && mSocketIn && !mUsingSpdyVersion && mHttp1xTransactionCount &&
+    if (canReuse && mSocketIn && (mUsingSpdyVersion == SpdyVersion::NONE) &&
+        mHttp1xTransactionCount &&
         NS_SUCCEEDED(mSocketIn->Available(&dataSize)) && dataSize) {
         LOG(("nsHttpConnection::CanReuse %p %s"
              "Socket not reusable because read data pending (%" PRIu64 ") on it.\n",
              this, mConnInfo->Origin(), dataSize));
         canReuse = false;
     }
     return canReuse;
 }
@@ -1163,18 +1164,18 @@ nsHttpConnection::OnHeadersAvailable(nsA
 
         // timeouts that are not caused by persistent connection reuse should
         // not be retried for browser compatibility reasons. bug 907800. The
         // server driven close is implicit in the 408.
         explicitClose = true;
         explicitKeepAlive = false;
     }
 
-    if ((responseHead->Version() < NS_HTTP_VERSION_1_1) ||
-        (requestHead->Version() < NS_HTTP_VERSION_1_1)) {
+    if ((responseHead->Version() < HttpVersion::v1_1) ||
+        (requestHead->Version() < HttpVersion::v1_1)) {
         // HTTP/1.0 connections are by default NOT persistent
         if (explicitKeepAlive)
             mKeepAlive = true;
         else
             mKeepAlive = false;
     }
     else {
         // HTTP/1.1 connections are by default persistent
@@ -1189,17 +1190,17 @@ nsHttpConnection::OnHeadersAvailable(nsA
     // a "keep-alive" connection is by definition capable of being reused, and
     // we only care about being able to reuse it once.  if a timeout is not
     // specified then we use our advertized timeout value.
     bool foundKeepAliveMax = false;
     if (mKeepAlive) {
         nsAutoCString keepAlive;
         Unused << responseHead->GetHeader(nsHttp::Keep_Alive, keepAlive);
 
-        if (!mUsingSpdyVersion) {
+        if (mUsingSpdyVersion == SpdyVersion::NONE) {
             const char *cp = PL_strcasestr(keepAlive.get(), "timeout=");
             if (cp)
                 mIdleTimeout = PR_SecondsToInterval((uint32_t) atoi(cp + 8));
             else
                 mIdleTimeout = gHttpHandler->IdleTimeout() * mDefaultTimeoutFactor;
 
             cp = PL_strcasestr(keepAlive.get(), "max=");
             if (cp) {
@@ -1210,25 +1211,25 @@ nsHttpConnection::OnHeadersAvailable(nsA
                 }
             }
         }
 
         LOG(("Connection can be reused [this=%p idle-timeout=%usec]\n",
              this, PR_IntervalToSeconds(mIdleTimeout)));
     }
 
-    if (!foundKeepAliveMax && mRemainingConnectionUses && !mUsingSpdyVersion)
+    if (!foundKeepAliveMax && mRemainingConnectionUses && (mUsingSpdyVersion == SpdyVersion::NONE))
         --mRemainingConnectionUses;
 
     // If we're doing a proxy connect, we need to check whether or not
     // it was successful.  If so, we have to reset the transaction and step-up
     // the socket connection if using SSL. Finally, we have to wake up the
     // socket write request.
     if (mProxyConnectStream) {
-        MOZ_ASSERT(!mUsingSpdyVersion,
+        MOZ_ASSERT(mUsingSpdyVersion == SpdyVersion::NONE,
                    "SPDY NPN Complete while using proxy connect stream");
         mProxyConnectStream = nullptr;
         bool isHttps =
             mTransaction ? mTransaction->ConnectionInfo()->EndToEndSSL() :
             mConnInfo->EndToEndSSL();
 
         if (responseStatus == 200) {
             LOG(("proxy CONNECT succeeded! endtoendssl=%d\n", isHttps));
@@ -1311,17 +1312,17 @@ nsHttpConnection::SetIsReusedAfter(uint3
     mConsiderReusedAfterInterval = PR_MillisecondsToInterval(afterMilliseconds);
 }
 
 nsresult
 nsHttpConnection::TakeTransport(nsISocketTransport  **aTransport,
                                 nsIAsyncInputStream **aInputStream,
                                 nsIAsyncOutputStream **aOutputStream)
 {
-    if (mUsingSpdyVersion)
+    if (mUsingSpdyVersion != SpdyVersion::NONE)
         return NS_ERROR_FAILURE;
     if (mTransaction && !mTransaction->IsDone())
         return NS_ERROR_IN_PROGRESS;
     if (!(mSocketTransport && mSocketIn && mSocketOut))
         return NS_ERROR_NOT_INITIALIZED;
 
     if (mInputOverflow)
         mSocketIn = mInputOverflow.forget();
@@ -1441,17 +1442,17 @@ nsHttpConnection::ReadTimeoutTick(PRInte
 void
 nsHttpConnection::UpdateTCPKeepalive(nsITimer *aTimer, void *aClosure)
 {
     MOZ_ASSERT(aTimer);
     MOZ_ASSERT(aClosure);
 
     nsHttpConnection *self = static_cast<nsHttpConnection*>(aClosure);
 
-    if (NS_WARN_IF(self->mUsingSpdyVersion)) {
+    if (NS_WARN_IF(self->mUsingSpdyVersion != SpdyVersion::NONE)) {
         return;
     }
 
     // Do not reduce keepalive probe frequency for idle connections.
     if (self->mIdleMonitoring) {
         return;
     }
 
@@ -1677,17 +1678,17 @@ nsHttpConnection::ForceSend()
 }
 
 void
 nsHttpConnection::BeginIdleMonitoring()
 {
     LOG(("nsHttpConnection::BeginIdleMonitoring [this=%p]\n", this));
     MOZ_ASSERT(OnSocketThread(), "not on socket thread");
     MOZ_ASSERT(!mTransaction, "BeginIdleMonitoring() while active");
-    MOZ_ASSERT(!mUsingSpdyVersion, "Idle monitoring of spdy not allowed");
+    MOZ_ASSERT(mUsingSpdyVersion == SpdyVersion::NONE, "Idle monitoring of spdy not allowed");
 
     LOG(("Entering Idle Monitoring Mode [this=%p]", this));
     mIdleMonitoring = true;
     if (mSocketIn)
         mSocketIn->AsyncWait(this, 0, 0, nullptr);
 }
 
 void
@@ -1700,20 +1701,23 @@ nsHttpConnection::EndIdleMonitoring()
     if (mIdleMonitoring) {
         LOG(("Leaving Idle Monitoring Mode [this=%p]", this));
         mIdleMonitoring = false;
         if (mSocketIn)
             mSocketIn->AsyncWait(nullptr, 0, 0, nullptr);
     }
 }
 
-uint32_t
+HttpVersion
 nsHttpConnection::Version()
 {
-    return mUsingSpdyVersion  ? mUsingSpdyVersion : mLastHttpResponseVersion;
+    if (mUsingSpdyVersion != SpdyVersion::NONE) {
+        return nsHttp::GetHttpVersionFromSpdy(mUsingSpdyVersion);
+    }
+    return mLastHttpResponseVersion;
 }
 
 //-----------------------------------------------------------------------------
 // nsHttpConnection <private>
 //-----------------------------------------------------------------------------
 
 void
 nsHttpConnection::CloseTransaction(nsAHttpTransaction *trans, nsresult reason,
@@ -1728,20 +1732,20 @@ nsHttpConnection::CloseTransaction(nsAHt
 
     if (mCurrentBytesRead > mMaxBytesRead)
         mMaxBytesRead = mCurrentBytesRead;
 
     // mask this error code because its not a real error.
     if (reason == NS_BASE_STREAM_CLOSED)
         reason = NS_OK;
 
-    if (mUsingSpdyVersion) {
+    if (mUsingSpdyVersion != SpdyVersion::NONE) {
         DontReuse();
         // if !mSpdySession then mUsingSpdyVersion must be false for canreuse()
-        mUsingSpdyVersion = 0;
+        mUsingSpdyVersion = SpdyVersion::NONE;
         mSpdySession = nullptr;
     }
 
     if (mTransaction) {
         mHttp1xTransactionCount += mTransaction->Http1xTransactionCount();
 
         mTransaction->Close(reason);
         mTransaction = nullptr;
@@ -2130,32 +2134,32 @@ nsHttpConnection::MakeConnectString(nsAH
     return NS_OK;
 }
 
 nsresult
 nsHttpConnection::SetupProxyConnect()
 {
     LOG(("nsHttpConnection::SetupProxyConnect [this=%p]\n", this));
     NS_ENSURE_TRUE(!mProxyConnectStream, NS_ERROR_ALREADY_INITIALIZED);
-    MOZ_ASSERT(!mUsingSpdyVersion,
+    MOZ_ASSERT(mUsingSpdyVersion == SpdyVersion::NONE,
                "SPDY NPN Complete while using proxy connect stream");
 
     nsAutoCString buf;
     nsHttpRequestHead request;
     nsresult rv = MakeConnectString(mTransaction, &request, buf);
     if (NS_FAILED(rv)) {
         return rv;
     }
     return NS_NewCStringInputStream(getter_AddRefs(mProxyConnectStream), Move(buf));
 }
 
 nsresult
 nsHttpConnection::StartShortLivedTCPKeepalives()
 {
-    if (mUsingSpdyVersion) {
+    if (mUsingSpdyVersion != SpdyVersion::NONE) {
         return NS_OK;
     }
     MOZ_ASSERT(mSocketTransport);
     if (!mSocketTransport) {
         return NS_ERROR_NOT_INITIALIZED;
     }
 
     nsresult rv = NS_OK;
@@ -2221,18 +2225,18 @@ nsHttpConnection::StartShortLivedTCPKeep
     }
 
     return NS_OK;
 }
 
 nsresult
 nsHttpConnection::StartLongLivedTCPKeepalives()
 {
-    MOZ_ASSERT(!mUsingSpdyVersion, "Don't use TCP Keepalive with SPDY!");
-    if (NS_WARN_IF(mUsingSpdyVersion)) {
+    MOZ_ASSERT(mUsingSpdyVersion == SpdyVersion::NONE, "Don't use TCP Keepalive with SPDY!");
+    if (NS_WARN_IF(mUsingSpdyVersion != SpdyVersion::NONE)) {
         return NS_OK;
     }
     MOZ_ASSERT(mSocketTransport);
     if (!mSocketTransport) {
         return NS_ERROR_NOT_INITIALIZED;
     }
 
     nsresult rv = NS_OK;
@@ -2448,21 +2452,21 @@ nsHttpConnection::CloseConnectionFastOpe
     MOZ_ASSERT(!mCurrentBytesRead);
     MOZ_ASSERT(OnSocketThread(), "not on socket thread");
 
     mFastOpenStatus = TFO_FAILED;
     RefPtr<nsAHttpTransaction> trans;
 
     DontReuse();
 
-    if (mUsingSpdyVersion) {
+    if (mUsingSpdyVersion != SpdyVersion::NONE) {
         // If we have a http2 connection just restart it as if 0rtt failed.
         // For http2 we do not need to do similar thing as for http1 because
         // backup connection will pick immediately all this transaction anyway.
-        mUsingSpdyVersion = 0;
+        mUsingSpdyVersion = SpdyVersion::NONE;
         if (mSpdySession) {
             mTransaction->SetFastOpenStatus(TFO_FAILED);
             Unused << mSpdySession->Finish0RTT(true, true);
         }
         mSpdySession = nullptr;
     } else {
         // For http1 we want to make this transaction an absolute priority to
         // get the backup connection so we will return it from here.
--- a/netwerk/protocol/http/nsHttpConnection.h
+++ b/netwerk/protocol/http/nsHttpConnection.h
@@ -93,17 +93,17 @@ public:
     // Close the underlying socket transport.
     void Close(nsresult reason, bool aIsShutdown = false);
 
     //-------------------------------------------------------------------------
     // XXX document when these are ok to call
 
     bool IsKeepAlive()
     {
-        return mUsingSpdyVersion || (mKeepAliveMask && mKeepAlive);
+        return (mUsingSpdyVersion != SpdyVersion::NONE) || (mKeepAliveMask && mKeepAlive);
     }
     bool CanReuse();   // can this connection be reused?
     bool CanDirectlyActivate();
 
     // Returns time in seconds for how long connection can be reused.
     uint32_t TimeToLive();
 
     void DontReuse();
@@ -155,35 +155,35 @@ public:
     void     GetSecurityInfo(nsISupports **);
     bool     IsPersistent() { return IsKeepAlive() && !mDontReuse; }
     bool     IsReused();
     void     SetIsReusedAfter(uint32_t afterMilliseconds);
     MOZ_MUST_USE nsresult PushBack(const char *data, uint32_t length);
     MOZ_MUST_USE nsresult ResumeSend();
     MOZ_MUST_USE nsresult ResumeRecv();
     int64_t  MaxBytesRead() {return mMaxBytesRead;}
-    uint8_t GetLastHttpResponseVersion() { return mLastHttpResponseVersion; }
+    HttpVersion GetLastHttpResponseVersion() { return mLastHttpResponseVersion; }
 
     friend class HttpConnectionForceIO;
     MOZ_MUST_USE nsresult ForceSend();
     MOZ_MUST_USE nsresult ForceRecv();
 
     static MOZ_MUST_USE nsresult ReadFromStream(nsIInputStream *, void *,
                                                 const char *, uint32_t,
                                                 uint32_t, uint32_t *);
 
     // When a persistent connection is in the connection manager idle
     // connection pool, the nsHttpConnection still reads errors and hangups
     // on the socket so that it can be proactively released if the server
     // initiates a termination. Only call on socket thread.
     void BeginIdleMonitoring();
     void EndIdleMonitoring();
 
-    bool UsingSpdy() { return !!mUsingSpdyVersion; }
-    uint8_t GetSpdyVersion() { return mUsingSpdyVersion; }
+    bool UsingSpdy() { return (mUsingSpdyVersion != SpdyVersion::NONE); }
+    SpdyVersion GetSpdyVersion() { return mUsingSpdyVersion; }
     bool EverUsedSpdy() { return mEverUsedSpdy; }
     PRIntervalTime Rtt() { return mRtt; }
 
     // true when connection SSL NPN phase is complete and we know
     // authoritatively whether UsingSpdy() or not.
     bool ReportedNPN() { return mReportedSpdy; }
 
     // When the connection is active this is called up to once every 1 second
@@ -226,17 +226,17 @@ public:
     // NoTraffic() returns true if there's been no traffic on the (non-spdy)
     // connection since CheckForTraffic() was called.
     bool NoTraffic() {
         return mTrafficStamp &&
             (mTrafficCount == (mTotalBytesWritten + mTotalBytesRead)) &&
             !mFastOpen;
     }
     // override of nsAHttpConnection
-    virtual uint32_t Version();
+    virtual HttpVersion Version();
 
     bool TestJoinConnection(const nsACString &hostname, int32_t port);
     bool JoinConnection(const nsACString &hostname, int32_t port);
 
     void SetFastOpenStatus(uint8_t tfoStatus);
     uint8_t GetFastOpenStatus() {
       return mFastOpenStatus;
     }
@@ -272,20 +272,20 @@ private:
 
     // Makes certain the SSL handshake is complete and NPN negotiation
     // has had a chance to happen
     MOZ_MUST_USE bool EnsureNPNComplete(nsresult &aOut0RTTWriteHandshakeValue,
                                         uint32_t &aOut0RTTBytesWritten);
     void     SetupSSL();
 
     // Start the Spdy transaction handler when NPN indicates spdy/*
-    void     StartSpdy(nsISSLSocketControl *ssl, uint8_t versionLevel);
+    void     StartSpdy(nsISSLSocketControl *ssl, SpdyVersion versionLevel);
     // Like the above, but do the bare minimum to do 0RTT data, so we can back
     // it out, if necessary
-    void     Start0RTTSpdy(uint8_t versionLevel);
+    void     Start0RTTSpdy(SpdyVersion versionLevel);
 
     // Helpers for Start*Spdy
     nsresult TryTakeSubTransactions(nsTArray<RefPtr<nsAHttpTransaction> > &list);
     nsresult MoveTransactionsToSpdy(nsresult status, nsTArray<RefPtr<nsAHttpTransaction> > &list);
 
     // Directly Add a transaction to an active connection for SPDY
     MOZ_MUST_USE nsresult AddTransaction(nsAHttpTransaction *, int32_t);
 
@@ -365,27 +365,27 @@ private:
     // on this persistent connection.
     uint32_t                        mRemainingConnectionUses;
 
     // SPDY related
     bool                            mNPNComplete;
     bool                            mSetupSSLCalled;
 
     // version level in use, 0 if unused
-    uint8_t                         mUsingSpdyVersion;
+    SpdyVersion                     mUsingSpdyVersion;
 
     RefPtr<ASpdySession>            mSpdySession;
     int32_t                         mPriority;
     bool                            mReportedSpdy;
 
     // mUsingSpdyVersion is cleared when mSpdySession is freed, this is permanent
     bool                            mEverUsedSpdy;
 
     // mLastHttpResponseVersion stores the last response's http version seen.
-    uint8_t                         mLastHttpResponseVersion;
+    HttpVersion                     mLastHttpResponseVersion;
 
     // The capabailities associated with the most recent transaction
     uint32_t                        mTransactionCaps;
 
     // If a large keepalive has been requested for any trans,
     // scale the default by this factor
     uint32_t                        mDefaultTimeoutFactor;
 
--- a/netwerk/protocol/http/nsHttpHandler.cpp
+++ b/netwerk/protocol/http/nsHttpHandler.cpp
@@ -184,18 +184,18 @@ nsHttpHandler::GetInstance()
         MOZ_ASSERT(NS_SUCCEEDED(rv));
         ClearOnShutdown(&gHttpHandler);
     }
     RefPtr<nsHttpHandler> httpHandler = gHttpHandler;
     return httpHandler.forget();
 }
 
 nsHttpHandler::nsHttpHandler()
-    : mHttpVersion(NS_HTTP_VERSION_1_1)
-    , mProxyHttpVersion(NS_HTTP_VERSION_1_1)
+    : mHttpVersion(HttpVersion::v1_1)
+    , mProxyHttpVersion(HttpVersion::v1_1)
     , mCapabilities(NS_HTTP_ALLOW_KEEPALIVE)
     , mReferrerLevel(0xff) // by default we always send a referrer
     , mSpoofReferrerSource(false)
     , mHideOnionReferrerSource(false)
     , mReferrerTrimmingPolicy(0)
     , mReferrerXOriginTrimmingPolicy(0)
     , mReferrerXOriginPolicy(0)
     , mFastFallbackToIPv4(false)
@@ -1382,32 +1382,32 @@ nsHttpHandler::PrefsChanged(nsIPrefBranc
             mFallbackSynTimeout = (uint16_t) clamped(val, 0, 10 * 60);
     }
 
     if (PREF_CHANGED(HTTP_PREF("version"))) {
         nsAutoCString httpVersion;
         prefs->GetCharPref(HTTP_PREF("version"), httpVersion);
         if (!httpVersion.IsVoid()) {
             if (httpVersion.EqualsLiteral("1.1"))
-                mHttpVersion = NS_HTTP_VERSION_1_1;
+                mHttpVersion = HttpVersion::v1_1;
             else if (httpVersion.EqualsLiteral("0.9"))
-                mHttpVersion = NS_HTTP_VERSION_0_9;
+                mHttpVersion = HttpVersion::v0_9;
             else
-                mHttpVersion = NS_HTTP_VERSION_1_0;
+                mHttpVersion = HttpVersion::v1_0;
         }
     }
 
     if (PREF_CHANGED(HTTP_PREF("proxy.version"))) {
         nsAutoCString httpVersion;
         prefs->GetCharPref(HTTP_PREF("proxy.version"), httpVersion);
         if (!httpVersion.IsVoid()) {
             if (httpVersion.EqualsLiteral("1.1"))
-                mProxyHttpVersion = NS_HTTP_VERSION_1_1;
+                mProxyHttpVersion = HttpVersion::v1_1;
             else
-                mProxyHttpVersion = NS_HTTP_VERSION_1_0;
+                mProxyHttpVersion = HttpVersion::v1_0;
             // it does not make sense to issue a HTTP/0.9 request to a proxy server
         }
     }
 
     if (PREF_CHANGED(HTTP_PREF("qos"))) {
         rv = prefs->GetIntPref(HTTP_PREF("qos"), &val);
         if (NS_SUCCEEDED(rv))
             mQoSBits = (uint8_t) clamped(val, 0, 0xff);
--- a/netwerk/protocol/http/nsHttpHandler.h
+++ b/netwerk/protocol/http/nsHttpHandler.h
@@ -73,18 +73,18 @@ public:
     MOZ_MUST_USE nsresult AddStandardRequestHeaders(nsHttpRequestHead *,
                                                     bool isSecure);
     MOZ_MUST_USE nsresult AddConnectionHeader(nsHttpRequestHead *,
                                               uint32_t capabilities);
     bool     IsAcceptableEncoding(const char *encoding, bool isSecure);
 
     const nsCString& UserAgent();
 
-    nsHttpVersion  HttpVersion()             { return mHttpVersion; }
-    nsHttpVersion  ProxyHttpVersion()        { return mProxyHttpVersion; }
+    enum HttpVersion    HttpVersion()             { return mHttpVersion; }
+    enum HttpVersion    ProxyHttpVersion()        { return mProxyHttpVersion; }
     uint8_t        ReferrerLevel()           { return mReferrerLevel; }
     bool           SpoofReferrerSource()     { return mSpoofReferrerSource; }
     bool           HideOnionReferrerSource() { return mHideOnionReferrerSource; }
     uint8_t        ReferrerTrimmingPolicy()  { return mReferrerTrimmingPolicy; }
     uint8_t        ReferrerXOriginTrimmingPolicy() {
         return mReferrerXOriginTrimmingPolicy;
     }
     uint8_t        ReferrerXOriginPolicy()   { return mReferrerXOriginPolicy; }
@@ -461,18 +461,18 @@ private:
 
     // the connection manager
     RefPtr<nsHttpConnectionMgr> mConnMgr;
 
     //
     // prefs
     //
 
-    uint8_t  mHttpVersion;
-    uint8_t  mProxyHttpVersion;
+    enum HttpVersion mHttpVersion;
+    enum HttpVersion mProxyHttpVersion;
     uint32_t mCapabilities;
     uint8_t  mReferrerLevel;
     uint8_t  mSpoofReferrerSource;
     uint8_t  mHideOnionReferrerSource;
     uint8_t  mReferrerTrimmingPolicy;
     uint8_t  mReferrerXOriginTrimmingPolicy;
     uint8_t  mReferrerXOriginPolicy;
 
--- a/netwerk/protocol/http/nsHttpRequestHead.cpp
+++ b/netwerk/protocol/http/nsHttpRequestHead.cpp
@@ -13,17 +13,17 @@
 // nsHttpRequestHead
 //-----------------------------------------------------------------------------
 
 namespace mozilla {
 namespace net {
 
 nsHttpRequestHead::nsHttpRequestHead()
     : mMethod(NS_LITERAL_CSTRING("GET"))
-    , mVersion(NS_HTTP_VERSION_1_1)
+    , mVersion(HttpVersion::v1_1)
     , mParsedMethod(kMethod_Get)
     , mHTTPS(false)
     , mRecursiveMutex("nsHttpRequestHead.mRecursiveMutex")
     , mInVisitHeaders(false)
 {
     MOZ_COUNT_CTOR(nsHttpRequestHead);
 }
 
@@ -45,17 +45,17 @@ nsHttpRequestHead::Headers() const
 void
 nsHttpRequestHead::SetHeaders(const nsHttpHeaderArray& aHeaders)
 {
     RecursiveMutexAutoLock mon(mRecursiveMutex);
     mHeaders = aHeaders;
 }
 
 void
-nsHttpRequestHead::SetVersion(nsHttpVersion version)
+nsHttpRequestHead::SetVersion(HttpVersion version)
 {
     RecursiveMutexAutoLock mon(mRecursiveMutex);
     mVersion = version;
 }
 
 void
 nsHttpRequestHead::SetRequestURI(const nsACString& s)
 {
@@ -90,17 +90,17 @@ nsHttpRequestHead::VisitHeaders(nsIHttpH
 
 void
 nsHttpRequestHead::Method(nsACString &aMethod)
 {
     RecursiveMutexAutoLock mon(mRecursiveMutex);
     aMethod = mMethod;
 }
 
-nsHttpVersion
+HttpVersion
 nsHttpRequestHead::Version()
 {
     RecursiveMutexAutoLock mon(mRecursiveMutex);
     return mVersion;
 }
 
 void
 nsHttpRequestHead::RequestURI(nsACString &aRequestURI)
@@ -365,20 +365,20 @@ nsHttpRequestHead::Flatten(nsACString &b
     // note: the first append is intentional.
 
     buf.Append(mMethod);
     buf.Append(' ');
     buf.Append(mRequestURI);
     buf.AppendLiteral(" HTTP/");
 
     switch (mVersion) {
-    case NS_HTTP_VERSION_1_1:
+    case HttpVersion::v1_1:
         buf.AppendLiteral("1.1");
         break;
-    case NS_HTTP_VERSION_0_9:
+    case HttpVersion::v0_9:
         buf.AppendLiteral("0.9");
         break;
     default:
         buf.AppendLiteral("1.0");
     }
 
     buf.AppendLiteral("\r\n");
 
--- a/netwerk/protocol/http/nsHttpRequestHead.h
+++ b/netwerk/protocol/http/nsHttpRequestHead.h
@@ -31,29 +31,29 @@ public:
     // nsHttpRequestHead lock!!!
     const nsHttpHeaderArray &Headers() const;
     void Enter() { mRecursiveMutex.Lock(); }
     void Exit() { mRecursiveMutex.Unlock(); }
 
     void SetHeaders(const nsHttpHeaderArray& aHeaders);
 
     void SetMethod(const nsACString &method);
-    void SetVersion(nsHttpVersion version);
+    void SetVersion(HttpVersion version);
     void SetRequestURI(const nsACString& s);
     void SetPath(const nsACString& s);
     uint32_t HeaderCount();
 
     // Using this function it is possible to itereate through all headers
     // automatically under one lock.
     MOZ_MUST_USE nsresult
     VisitHeaders(nsIHttpHeaderVisitor *visitor,
                  nsHttpHeaderArray::VisitorFilter filter =
                      nsHttpHeaderArray::eFilterAll);
     void Method(nsACString &aMethod);
-    nsHttpVersion Version();
+    HttpVersion Version();
     void RequestURI(nsACString &RequestURI);
     void Path(nsACString &aPath);
     void SetHTTPS(bool val);
     bool IsHTTPS();
 
     void SetOrigin(const nsACString &scheme, const nsACString &host,
                    int32_t port);
     void Origin(nsACString &aOrigin);
@@ -103,17 +103,17 @@ public:
     bool IsHead() { return EqualsMethod(kMethod_Head); }
     bool IsPut() { return EqualsMethod(kMethod_Put); }
     bool IsTrace() { return EqualsMethod(kMethod_Trace); }
     void ParseHeaderSet(const char *buffer);
 private:
     // All members must be copy-constructable and assignable
     nsHttpHeaderArray mHeaders;
     nsCString         mMethod;
-    nsHttpVersion     mVersion;
+    HttpVersion       mVersion;
 
     // mRequestURI and mPath are strings instead of an nsIURI
     // because this is used off the main thread
     nsCString         mRequestURI;
     nsCString         mPath;
 
     nsCString         mOrigin;
     ParsedMethodType  mParsedMethod;
--- a/netwerk/protocol/http/nsHttpResponseHead.cpp
+++ b/netwerk/protocol/http/nsHttpResponseHead.cpp
@@ -62,17 +62,17 @@ nsHttpResponseHead::operator=(const nsHt
     mCacheControlNoStore = other.mCacheControlNoStore;
     mCacheControlNoCache = other.mCacheControlNoCache;
     mCacheControlImmutable = other.mCacheControlImmutable;
     mPragmaNoCache = other.mPragmaNoCache;
 
     return *this;
 }
 
-nsHttpVersion
+HttpVersion
 nsHttpResponseHead::Version()
 {
     RecursiveMutexAutoLock monitor(mRecursiveMutex);
     return mVersion;
 }
 
 uint16_t
 nsHttpResponseHead::Status()
@@ -258,23 +258,23 @@ nsHttpResponseHead::SetContentLength(int
         MOZ_ASSERT(NS_SUCCEEDED(rv));
     }
 }
 
 void
 nsHttpResponseHead::Flatten(nsACString &buf, bool pruneTransients)
 {
     RecursiveMutexAutoLock monitor(mRecursiveMutex);
-    if (mVersion == NS_HTTP_VERSION_0_9)
+    if (mVersion == HttpVersion::v0_9)
         return;
 
     buf.AppendLiteral("HTTP/");
-    if (mVersion == NS_HTTP_VERSION_2_0)
+    if (mVersion == HttpVersion::v2_0)
         buf.AppendLiteral("2.0 ");
-    else if (mVersion == NS_HTTP_VERSION_1_1)
+    else if (mVersion == HttpVersion::v1_1)
         buf.AppendLiteral("1.1 ");
     else
         buf.AppendLiteral("1.0 ");
 
     buf.Append(nsPrintfCString("%u", unsigned(mStatus)) +
                NS_LITERAL_CSTRING(" ") +
                mStatusText +
                NS_LITERAL_CSTRING("\r\n"));
@@ -282,17 +282,17 @@ nsHttpResponseHead::Flatten(nsACString &
 
     mHeaders.Flatten(buf, false, pruneTransients);
 }
 
 void
 nsHttpResponseHead::FlattenNetworkOriginalHeaders(nsACString &buf)
 {
     RecursiveMutexAutoLock monitor(mRecursiveMutex);
-    if (mVersion == NS_HTTP_VERSION_0_9) {
+    if (mVersion == HttpVersion::v0_9) {
         return;
     }
 
     mHeaders.FlattenOriginalHeader(buf);
 }
 
 nsresult
 nsHttpResponseHead::ParseCachedHead(const char *block)
@@ -550,17 +550,17 @@ nsHttpResponseHead::ParseStatusLine_lock
     const char *end = line.EndReading();
     const char *p = start;
 
     // HTTP-Version
     ParseVersion(start);
 
     int32_t index = line.FindChar(' ');
 
-    if ((mVersion == NS_HTTP_VERSION_0_9) || (index == -1)) {
+    if ((mVersion == HttpVersion::v0_9) || (index == -1)) {
         mStatus = 200;
         AssignDefaultStatusText();
     }
     else {
         // Status-Code
         p += index + 1;
         mStatus = (uint16_t) atoi(p);
         if (mStatus == 0) {
@@ -841,17 +841,17 @@ nsHttpResponseHead::IsResumable()
 {
     RecursiveMutexAutoLock monitor(mRecursiveMutex);
     // even though some HTTP/1.0 servers may support byte range requests, we're not
     // going to bother with them, since those servers wouldn't understand If-Range.
     // Also, while in theory it may be possible to resume when the status code
     // is not 200, it is unlikely to be worth the trouble, especially for
     // non-2xx responses.
     return mStatus == 200 &&
-           mVersion >= NS_HTTP_VERSION_1_1 &&
+           mVersion >= HttpVersion::v1_1 &&
            mHeaders.PeekHeader(nsHttp::Content_Length) &&
            (mHeaders.PeekHeader(nsHttp::ETag) ||
             mHeaders.PeekHeader(nsHttp::Last_Modified)) &&
            mHeaders.HasHeaderValue(nsHttp::Accept_Ranges, "bytes");
 }
 
 bool
 nsHttpResponseHead::ExpiresInPast()
@@ -934,17 +934,17 @@ void
 nsHttpResponseHead::Reset()
 {
     LOG(("nsHttpResponseHead::Reset\n"));
 
     RecursiveMutexAutoLock monitor(mRecursiveMutex);
 
     mHeaders.Clear();
 
-    mVersion = NS_HTTP_VERSION_1_1;
+    mVersion = HttpVersion::v1_1;
     mStatus = 200;
     mContentLength = -1;
     mCacheControlPrivate = false;
     mCacheControlNoStore = false;
     mCacheControlNoCache = false;
     mCacheControlImmutable = false;
     mPragmaNoCache = false;
     mStatusText.Truncate();
@@ -1121,53 +1121,53 @@ nsHttpResponseHead::ParseVersion(const c
 
     LOG(("nsHttpResponseHead::ParseVersion [version=%s]\n", str));
 
     // make sure we have HTTP at the beginning
     if (PL_strncasecmp(str, "HTTP", 4) != 0) {
         if (PL_strncasecmp(str, "ICY ", 4) == 0) {
             // ShoutCast ICY is HTTP/1.0-like. Assume it is HTTP/1.0.
             LOG(("Treating ICY as HTTP 1.0\n"));
-            mVersion = NS_HTTP_VERSION_1_0;
+            mVersion = HttpVersion::v1_0;
             return;
         }
         LOG(("looks like a HTTP/0.9 response\n"));
-        mVersion = NS_HTTP_VERSION_0_9;
+        mVersion = HttpVersion::v0_9;
         return;
     }
     str += 4;
 
     if (*str != '/') {
         LOG(("server did not send a version number; assuming HTTP/1.0\n"));
         // NCSA/1.5.2 has a bug in which it fails to send a version number
         // if the request version is HTTP/1.1, so we fall back on HTTP/1.0
-        mVersion = NS_HTTP_VERSION_1_0;
+        mVersion = HttpVersion::v1_0;
         return;
     }
 
     char *p = PL_strchr(str, '.');
     if (p == nullptr) {
         LOG(("mal-formed server version; assuming HTTP/1.0\n"));
-        mVersion = NS_HTTP_VERSION_1_0;
+        mVersion = HttpVersion::v1_0;
         return;
     }
 
     ++p; // let b point to the minor version
 
     int major = atoi(str + 1);
     int minor = atoi(p);
 
     if ((major > 2) || ((major == 2) && (minor >= 0)))
-        mVersion = NS_HTTP_VERSION_2_0;
+        mVersion = HttpVersion::v2_0;
     else if ((major == 1) && (minor >= 1))
         // at least HTTP/1.1
-        mVersion = NS_HTTP_VERSION_1_1;
+        mVersion = HttpVersion::v1_1;
     else
         // treat anything else as version 1.0
-        mVersion = NS_HTTP_VERSION_1_0;
+        mVersion = HttpVersion::v1_0;
 }
 
 void
 nsHttpResponseHead::ParseCacheControl(const char *val)
 {
     if (!(val && *val)) {
         // clear flags
         mCacheControlPrivate = false;
--- a/netwerk/protocol/http/nsHttpResponseHead.h
+++ b/netwerk/protocol/http/nsHttpResponseHead.h
@@ -24,34 +24,34 @@ namespace mozilla { namespace net {
 //-----------------------------------------------------------------------------
 // nsHttpResponseHead represents the status line and headers from an HTTP
 // response.
 //-----------------------------------------------------------------------------
 
 class nsHttpResponseHead
 {
 public:
-    nsHttpResponseHead() : mVersion(NS_HTTP_VERSION_1_1)
+    nsHttpResponseHead() : mVersion(HttpVersion::v1_1)
                          , mStatus(200)
                          , mContentLength(-1)
                          , mCacheControlPrivate(false)
                          , mCacheControlNoStore(false)
                          , mCacheControlNoCache(false)
                          , mCacheControlImmutable(false)
                          , mPragmaNoCache(false)
                          , mRecursiveMutex("nsHttpResponseHead.mRecursiveMutex")
                          , mInVisitHeaders(false) {}
 
     nsHttpResponseHead(const nsHttpResponseHead &aOther);
     nsHttpResponseHead &operator=(const nsHttpResponseHead &aOther);
 
     void Enter() { mRecursiveMutex.Lock(); }
     void Exit() { mRecursiveMutex.Unlock(); }
 
-    nsHttpVersion Version();
+    HttpVersion Version();
 // X11's Xlib.h #defines 'Status' to 'int' on some systems!
 #undef Status
     uint16_t Status();
     void StatusText(nsACString &aStatusText);
     int64_t ContentLength();
     void ContentType(nsACString &aContentType);
     void ContentCharset(nsACString &aContentCharset);
     bool Private();
@@ -168,17 +168,17 @@ private:
     MOZ_MUST_USE nsresult GetLastModifiedValue_locked(uint32_t *result) const
     {
         return ParseDateHeader(nsHttp::Last_Modified, result);
     }
 
 private:
     // All members must be copy-constructable and assignable
     nsHttpHeaderArray mHeaders;
-    nsHttpVersion     mVersion;
+    HttpVersion       mVersion;
     uint16_t          mStatus;
     nsCString         mStatusText;
     int64_t           mContentLength;
     nsCString         mContentType;
     nsCString         mContentCharset;
     bool              mCacheControlPrivate;
     bool              mCacheControlNoStore;
     bool              mCacheControlNoCache;
--- a/netwerk/protocol/http/nsHttpTransaction.cpp
+++ b/netwerk/protocol/http/nsHttpTransaction.cpp
@@ -96,17 +96,17 @@ nsHttpTransaction::nsHttpTransaction()
     , mInvalidResponseBytesRead(0)
     , mPushedStream(nullptr)
     , mInitialRwin(0)
     , mChunkedDecoder(nullptr)
     , mStatus(NS_OK)
     , mPriority(0)
     , mRestartCount(0)
     , mCaps(0)
-    , mHttpVersion(NS_HTTP_VERSION_UNKNOWN)
+    , mHttpVersion(HttpVersion::UNKNOWN)
     , mHttpResponseCode(0)
     , mCurrentHttpResponseHeaderSize(0)
     , mThrottlingReadAllowance(THROTTLE_NO_LIMIT)
     , mCapsToClear(0)
     , mResponseIsComplete(false)
     , mReadingStopped(false)
     , mClosed(false)
     , mConnected(false)
@@ -531,35 +531,26 @@ void
 nsHttpTransaction::OnActivated()
 {
     MOZ_ASSERT(OnSocketThread());
 
     if (mActivated) {
         return;
     }
 
-    if (mConnection && mRequestHead) {
+    if (mConnection && mRequestHead && mConnection->Version() >= HttpVersion::v2_0) {
         // So this is fun. On http/2, we want to send TE: Trailers, to be
         // spec-compliant. So we add it to the request head here. The fun part
         // is that adding a header to the request head at this point has no
         // effect on what we send on the wire, as the headers are already
         // flattened (in Init()) by the time we get here. So the *real* adding
         // of the header happens in the h2 compression code. We still have to
         // add the header to the request head here, though, so that devtools can
         // show that we sent the header. FUN!
-        // Oh, and we can't just check for version >= NS_HTTP_VERSION_2_0 because
-        // right now, mConnection->Version() returns HTTP_VERSION_2 (=5) instead
-        // of NS_HTTP_VERSION_2_0 (=20) for... reasons.
-        bool isOldHttp = (mConnection->Version() == NS_HTTP_VERSION_0_9 ||
-                          mConnection->Version() == NS_HTTP_VERSION_1_0 ||
-                          mConnection->Version() == NS_HTTP_VERSION_1_1 ||
-                          mConnection->Version() == NS_HTTP_VERSION_UNKNOWN);
-        if (!isOldHttp) {
-            Unused << mRequestHead->SetHeader(nsHttp::TE, NS_LITERAL_CSTRING("Trailers"));
-        }
+        Unused << mRequestHead->SetHeader(nsHttp::TE, NS_LITERAL_CSTRING("Trailers"));
     }
 
     mActivated = true;
     gHttpHandler->ConnMgr()->AddActiveTransaction(this);
 }
 
 void
 nsHttpTransaction::GetSecurityCallbacks(nsIInterfaceRequestor **cb)
@@ -1147,17 +1138,17 @@ nsHttpTransaction::Close(nsresult reason
     }
 
     if ((mChunkedDecoder || (mContentLength >= int64_t(0))) &&
         (NS_SUCCEEDED(reason) && !mResponseIsComplete)) {
 
         NS_WARNING("Partial transfer, incomplete HTTP response received");
 
         if ((mHttpResponseCode / 100 == 2) &&
-            (mHttpVersion >= NS_HTTP_VERSION_1_1)) {
+            (mHttpVersion >= HttpVersion::v1_1)) {
             FrameCheckLevel clevel = gHttpHandler->GetEnforceH1Framing();
             if (clevel >= FRAMECHECK_BARELY) {
                 if ((clevel == FRAMECHECK_STRICT) ||
                     (mChunkedDecoder && mChunkedDecoder->GetChunkRemaining()) ||
                     (!mChunkedDecoder && !mContentDecoding && mContentDecodingCheck) ) {
                     reason = NS_ERROR_NET_PARTIAL_TRANSFER;
                     LOG(("Partial transfer, incomplete HTTP response received: %s",
                          mChunkedDecoder ? "broken chunk" : "c-l underrun"));
@@ -1179,17 +1170,17 @@ nsHttpTransaction::Close(nsresult reason
         // section, and there may still be a header line unparsed.  let's make
         // sure we parse the remaining header line, and then hopefully, the
         // response will be usable (see bug 88792).
         if (!mHaveAllHeaders) {
             char data = '\n';
             uint32_t unused;
             Unused << ParseHead(&data, 1, &unused);
 
-            if (mResponseHead->Version() == NS_HTTP_VERSION_0_9) {
+            if (mResponseHead->Version() == HttpVersion::v0_9) {
                 // Reject 0 byte HTTP/0.9 Responses - bug 423506
                 LOG(("nsHttpTransaction::Close %p 0 Byte 0.9 Response", this));
                 reason = NS_ERROR_NET_RESET;
             }
         }
 
         // honor the sticky connection flag...
         if (mCaps & NS_HTTP_STICKY_CONNECTION)
@@ -1398,17 +1389,17 @@ nsHttpTransaction::ParseLine(nsACString 
 {
     LOG(("nsHttpTransaction::ParseLine [%s]\n", PromiseFlatCString(line).get()));
     nsresult rv = NS_OK;
 
     if (!mHaveStatusLine) {
         mResponseHead->ParseStatusLine(line);
         mHaveStatusLine = true;
         // XXX this should probably never happen
-        if (mResponseHead->Version() == NS_HTTP_VERSION_0_9)
+        if (mResponseHead->Version() == HttpVersion::v0_9)
             mHaveAllHeaders = true;
     }
     else {
         rv = mResponseHead->ParseHeaderLine(line);
     }
     return rv;
 }
 
@@ -1670,17 +1661,17 @@ nsHttpTransaction::HandleContentStart()
                 return NS_ERROR_NET_RESET;
             }
             break;
         case 425:
             LOG(("Too Early."));
             if ((mEarlyDataDisposition == EARLY_425) && !mDoNotTryEarlyData) {
                 mDoNotTryEarlyData = true;
                 mForceRestart = true; // force restart has built in loop protection
-                if (mConnection->Version() == HTTP_VERSION_2) {
+                if (mConnection->Version() == HttpVersion::v2_0) {
                     mReuseOnRestart = true;
                 }
                 return NS_ERROR_NET_RESET;
             }
             break;
         }
 
         if (mResponseHead->Status() == 200 &&
@@ -1695,17 +1686,17 @@ nsHttpTransaction::HandleContentStart()
         } else {
             // grab the content-length from the response headers
             mContentLength = mResponseHead->ContentLength();
 
             // handle chunked encoding here, so we'll know immediately when
             // we're done with the socket.  please note that _all_ other
             // decoding is done when the channel receives the content data
             // so as not to block the socket transport thread too much.
-            if (mResponseHead->Version() >= NS_HTTP_VERSION_1_0 &&
+            if (mResponseHead->Version() >= HttpVersion::v1_0 &&
                 mResponseHead->HasHeaderValue(nsHttp::Transfer_Encoding, "chunked")) {
                 // we only support the "chunked" transfer encoding right now.
                 mChunkedDecoder = new nsHttpChunkedDecoder();
                 LOG(("nsHttpTransaction %p chunked decoder created\n", this));
                 // Ignore server specified Content-Length.
                 if (mContentLength != int64_t(-1)) {
                     LOG(("nsHttpTransaction %p chunked with C-L ignores C-L\n", this));
                     mContentLength = -1;
@@ -1754,17 +1745,17 @@ nsHttpTransaction::HandleContent(char *b
         if (NS_FAILED(rv)) return rv;
     }
     else if (mContentLength >= int64_t(0)) {
         // HTTP/1.0 servers have been known to send erroneous Content-Length
         // headers. So, unless the connection is persistent, we must make
         // allowances for a possibly invalid Content-Length header. Thus, if
         // NOT persistent, we simply accept everything in |buf|.
         if (mConnection->IsPersistent() || mPreserveStream ||
-            mHttpVersion >= NS_HTTP_VERSION_1_1) {
+            mHttpVersion >= HttpVersion::v1_1) {
             int64_t remaining = mContentLength - mContentRead;
             *contentRead = uint32_t(std::min<int64_t>(count, remaining));
             *contentRemaining = count - *contentRead;
         }
         else {
             *contentRead = count;
             // mContentLength might need to be increased...
             int64_t position = mContentRead + int64_t(count);
--- a/netwerk/protocol/http/nsHttpTransaction.h
+++ b/netwerk/protocol/http/nsHttpTransaction.h
@@ -308,17 +308,17 @@ private:
 
     nsresult                        mStatus;
 
     int16_t                         mPriority;
 
     uint16_t                        mRestartCount;        // the number of times this transaction has been restarted
     uint32_t                        mCaps;
 
-    nsHttpVersion                   mHttpVersion;
+    HttpVersion                     mHttpVersion;
     uint16_t                        mHttpResponseCode;
 
     uint32_t                        mCurrentHttpResponseHeaderSize;
 
     int32_t const THROTTLE_NO_LIMIT = -1;
     // This can have 3 possible values:
     // * THROTTLE_NO_LIMIT - this means the transaction is not in any way limited
     //                       to read the response, this is the default