Bug 1460310 - Separate HTTP and SPDY identifiers into separate namespaces. r=dragana
authorNicholas Hurley <hurley@mozilla.com>
Fri, 01 Jun 2018 11:32:05 -0700
changeset 475976 6a6e61fb16661ee52992f0171e5d84d82986918f
parent 475975 436a6ebd505e53d110c4e238e9dce0a7bbfa9db1
child 475977 5c20da9b09875a22bfde156ebd5e372a0de8d0d1
push id9374
push userjlund@mozilla.com
push dateMon, 18 Jun 2018 21:43:20 +0000
treeherdermozilla-beta@160e085dfb0b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdragana
bugs1460310
milestone62.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 1460310 - Separate HTTP and SPDY identifiers into separate namespaces. r=dragana 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), std::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)
@@ -1383,32 +1383,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