diff --git a/DEPS b/DEPS
index 38f1e6a..df76365 100644
--- a/DEPS
+++ b/DEPS
@@ -67,7 +67,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': '7faf1aa95d25774c40942b407c8164935d79122a',
+  'v8_revision': 'd48dc2e0aef07c4f6c290bee2ac6077974cf2aca',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
diff --git a/build/android/pylib/symbols/stack_symbolizer.py b/build/android/pylib/symbols/stack_symbolizer.py
index 8ddf1f3..6de896a 100644
--- a/build/android/pylib/symbols/stack_symbolizer.py
+++ b/build/android/pylib/symbols/stack_symbolizer.py
@@ -92,10 +92,12 @@
     if self._enable_relocation_packing and self._apk_libs:
       for apk_lib in self._apk_libs:
         cmd.extend(['--packed-lib', apk_lib])
+    env = dict(os.environ)
+    env['PYTHONDONTWRITEBYTECODE'] = '1'
     with tempfile.NamedTemporaryFile() as f:
       f.write('\n'.join(data_to_symbolize))
       f.flush()
-      _, output = cmd_helper.GetCmdStatusAndOutput(cmd + [f.name])
+      _, output = cmd_helper.GetCmdStatusAndOutput(cmd + [f.name], env=env)
     for line in output.splitlines():
       if not include_stack and 'Stack Data:' in line:
         break
diff --git a/build/config/freetype/BUILD.gn b/build/config/freetype/BUILD.gn
index 991419c..0ba90271 100644
--- a/build/config/freetype/BUILD.gn
+++ b/build/config/freetype/BUILD.gn
@@ -10,7 +10,7 @@
     public_configs = [ "//build/linux:freetype_from_pkgconfig" ]
   } else {
     public_deps = [
-      "//third_party/freetype",
+      "//third_party:freetype_harfbuzz",
     ]
   }
 }
diff --git a/build/linux/BUILD.gn b/build/linux/BUILD.gn
index caa860e..1573bb0 100644
--- a/build/linux/BUILD.gn
+++ b/build/linux/BUILD.gn
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 
 import("//build/config/features.gni")
+import("//build/config/freetype/freetype.gni")
 import("//build/config/linux/pkg_config.gni")
 
 if (use_gio) {
@@ -33,11 +34,16 @@
 
 # Looking for libspeechd? Use //third_party/speech-dispatcher
 
-if (!is_chromecast) {
+if (use_system_freetype) {
+  assert(!is_chromecast)
+
   # Only provided for distributions which prefer to keep linking to FreeType on
   # the system, use with caution,for details see build/config/freetype/BUILD.gn.
   pkg_config("freetype_from_pkgconfig") {
-    visibility = [ ":freetype2" ]
+    visibility = [
+      "//third_party:freetype_harfbuzz",
+      "//third_party/harfbuzz-ng:harfbuzz_source",
+    ]
     packages = [ "freetype2" ]
   }
 }
diff --git a/chrome/browser/chromeos/login/active_directory_login_browsertest.cc b/chrome/browser/chromeos/login/active_directory_login_browsertest.cc
index da138eac..75656a3 100644
--- a/chrome/browser/chromeos/login/active_directory_login_browsertest.cc
+++ b/chrome/browser/chromeos/login/active_directory_login_browsertest.cc
@@ -51,6 +51,16 @@
 constexpr char kAdWelcomMessage[] = "welcomeMsg";
 constexpr char kAdAutocompleteRealm[] = "userInput /deep/ #domainLabel";
 
+constexpr char kAdPasswordChangeId[] = "ad-password-change";
+constexpr char kAdAnimatedPages[] = "animatedPages";
+constexpr char kAdOldPasswordInput[] = "oldPassword";
+constexpr char kAdNewPassword1Input[] = "newPassword1";
+constexpr char kAdNewPassword2Input[] = "newPassword2";
+constexpr char kNewPassword[] = "new_password";
+constexpr char kDifferentNewPassword[] = "different_new_password";
+
+constexpr char kCloseButtonId[] = "closeButton";
+
 class TestAuthPolicyClient : public FakeAuthPolicyClient {
  public:
   TestAuthPolicyClient() { FakeAuthPolicyClient::set_started(true); }
@@ -66,23 +76,11 @@
       else
         account_info.set_account_id(object_guid);
     }
-    if (!auth_closure_.is_null()) {
-      base::SequencedTaskRunnerHandle::Get()->PostNonNestableTask(
-          FROM_HERE, std::move(auth_closure_));
-    }
     base::SequencedTaskRunnerHandle::Get()->PostNonNestableTask(
         FROM_HERE,
         base::BindOnce(std::move(callback), auth_error_, account_info));
   }
 
-  void set_auth_closure(base::OnceClosure auth_closure) {
-    auth_closure_ = std::move(auth_closure);
-  }
-
- protected:
-  // If set called before calling AuthCallback in AuthenticateUser.
-  base::OnceClosure auth_closure_;
-
  private:
   DISALLOW_COPY_AND_ASSIGN(TestAuthPolicyClient);
 };
@@ -132,6 +130,22 @@
     loop.Run();
   }
 
+  void TriggerPasswordChangeScreen() {
+    OobeScreenWaiter screen_waiter(
+        OobeScreen::SCREEN_ACTIVE_DIRECTORY_PASSWORD_CHANGE);
+
+    fake_auth_policy_client()->set_auth_error(
+        authpolicy::ERROR_PASSWORD_EXPIRED);
+    SubmitActiveDirectoryCredentials(kTestActiveDirectoryUser, kPassword);
+    screen_waiter.Wait();
+    TestAdPasswordChangeError(std::string());
+  }
+
+  void ClosePasswordChangeScreen() {
+    js_checker().Evaluate(JSElement(kAdPasswordChangeId, kCloseButtonId) +
+                          ".fire('tap')");
+  }
+
   void SetupTestAuthPolicyClient() {
     auto test_client = base::MakeUnique<TestAuthPolicyClient>();
     fake_auth_policy_client_ = test_client.get();
@@ -169,6 +183,17 @@
     JSExpect("!Oobe.getInstance().headerHidden");
   }
 
+  // Checks if Active Directory password change screen is shown.
+  void TestPasswordChangeVisible() {
+    // Checks if Gaia signin is hidden.
+    JSExpect("document.querySelector('#signin-frame').hidden");
+    // Checks if Active Directory signin is visible.
+    JSExpect("!document.querySelector('#ad-password-change').hidden");
+    JSExpect(JSElement(kAdPasswordChangeId, kAdAnimatedPages) +
+             ".selected == 0");
+    JSExpect("!" + JSElement(kAdPasswordChangeId, kCloseButtonId) + ".hidden");
+  }
+
   // Checks if user input is marked as invalid.
   void TestUserError() {
     TestLoginVisible();
@@ -201,6 +226,20 @@
     JSExpect(JSElement(kAdOfflineAuthId, kAdAutocompleteRealm) + ".hidden");
   }
 
+  // Checks if Active Directory password change screen is shown. Also checks if
+  // |invalid_element| is invalidated and all the other elements are valid.
+  void TestAdPasswordChangeError(const std::string& invalid_element) {
+    TestPasswordChangeVisible();
+    for (const char* element :
+         {kAdOldPasswordInput, kAdNewPassword1Input, kAdNewPassword2Input}) {
+      std::string js_assertion =
+          JSElement(kAdPasswordChangeId, element) + ".isInvalid";
+      if (element != invalid_element)
+        js_assertion = "!" + js_assertion;
+      JSExpect(js_assertion);
+    }
+  }
+
   // Sets username and password for the Active Directory login and submits it.
   void SubmitActiveDirectoryCredentials(const std::string& username,
                                         const std::string& password) {
@@ -212,6 +251,24 @@
                           ".fire('tap')");
   }
 
+  // Sets username and password for the Active Directory login and submits it.
+  void SubmitActiveDirectoryPasswordChangeCredentials(
+      const std::string& old_password,
+      const std::string& new_password1,
+      const std::string& new_password2) {
+    js_checker().ExecuteAsync(
+        JSElement(kAdPasswordChangeId, kAdOldPasswordInput) + ".value='" +
+        old_password + "'");
+    js_checker().ExecuteAsync(
+        JSElement(kAdPasswordChangeId, kAdNewPassword1Input) + ".value='" +
+        new_password1 + "'");
+    js_checker().ExecuteAsync(
+        JSElement(kAdPasswordChangeId, kAdNewPassword2Input) + ".value='" +
+        new_password2 + "'");
+    js_checker().Evaluate(JSElement(kAdPasswordChangeId, kAdButton) +
+                          ".fire('tap')");
+  }
+
   void SetupActiveDirectoryJSNotifications() {
     js_checker().Evaluate(
         "var testInvalidateAd = login.GaiaSigninScreen.invalidateAd;"
@@ -322,4 +379,86 @@
   TestDomainVisible();
 }
 
+// Marks as Active Directory enterprise device and OOBE as completed.
+IN_PROC_BROWSER_TEST_F(ActiveDirectoryLoginTest,
+                       PRE_PasswordChange_LoginSuccess) {
+  MarkAsActiveDirectoryEnterprise();
+}
+
+// Test successful Active Directory login from the password change screen.
+IN_PROC_BROWSER_TEST_F(ActiveDirectoryLoginTest, PasswordChange_LoginSuccess) {
+  TestLoginVisible();
+  TestDomainVisible();
+
+  TriggerPasswordChangeScreen();
+
+  // Password accepted by AuthPolicyClient.
+  fake_auth_policy_client()->set_auth_error(authpolicy::ERROR_NONE);
+  content::WindowedNotificationObserver session_start_waiter(
+      chrome::NOTIFICATION_SESSION_STARTED,
+      content::NotificationService::AllSources());
+  SubmitActiveDirectoryPasswordChangeCredentials(kPassword, kNewPassword,
+                                                 kNewPassword);
+  session_start_waiter.Wait();
+}
+
+// Marks as Active Directory enterprise device and OOBE as completed.
+IN_PROC_BROWSER_TEST_F(ActiveDirectoryLoginTest, PRE_PasswordChange_UIErrors) {
+  MarkAsActiveDirectoryEnterprise();
+}
+
+// Test different UI errors for Active Directory password change screen.
+IN_PROC_BROWSER_TEST_F(ActiveDirectoryLoginTest, PasswordChange_UIErrors) {
+  TestLoginVisible();
+  TestDomainVisible();
+
+  TriggerPasswordChangeScreen();
+  // Password rejected by UX.
+  // Empty passwords.
+  SubmitActiveDirectoryPasswordChangeCredentials("", "", "");
+  TestAdPasswordChangeError(kAdOldPasswordInput);
+
+  // Empty new password.
+  SubmitActiveDirectoryPasswordChangeCredentials(kPassword, "", "");
+  TestAdPasswordChangeError(kAdNewPassword1Input);
+
+  // Empty confirmation of the new password.
+  SubmitActiveDirectoryPasswordChangeCredentials(kPassword, kNewPassword, "");
+  TestAdPasswordChangeError(kAdNewPassword2Input);
+
+  // Confirmation of password is different from new password.
+  SubmitActiveDirectoryPasswordChangeCredentials(kPassword, kNewPassword,
+                                                 kDifferentNewPassword);
+  TestAdPasswordChangeError(kAdNewPassword2Input);
+
+  // Password rejected by AuthPolicyClient.
+  fake_auth_policy_client()->set_auth_error(authpolicy::ERROR_BAD_PASSWORD);
+  SubmitActiveDirectoryPasswordChangeCredentials(kPassword, kNewPassword,
+                                                 kNewPassword);
+  TestAdPasswordChangeError(kAdOldPasswordInput);
+}
+
+// Marks as Active Directory enterprise device and OOBE as completed.
+IN_PROC_BROWSER_TEST_F(ActiveDirectoryLoginTest,
+                       PRE_PasswordChange_ReopenClearErrors) {
+  MarkAsActiveDirectoryEnterprise();
+}
+
+// Test reopening Active Directory password change screen clears errors.
+IN_PROC_BROWSER_TEST_F(ActiveDirectoryLoginTest,
+                       PasswordChange_ReopenClearErrors) {
+  TestLoginVisible();
+  TestDomainVisible();
+
+  TriggerPasswordChangeScreen();
+
+  // Empty new password.
+  SubmitActiveDirectoryPasswordChangeCredentials("", "", "");
+  TestAdPasswordChangeError(kAdOldPasswordInput);
+
+  ClosePasswordChangeScreen();
+  TestLoginVisible();
+  TriggerPasswordChangeScreen();
+}
+
 }  // namespace chromeos
diff --git a/chrome/browser/ui/libgtkui/BUILD.gn b/chrome/browser/ui/libgtkui/BUILD.gn
index 33b4f820..884fc42e 100644
--- a/chrome/browser/ui/libgtkui/BUILD.gn
+++ b/chrome/browser/ui/libgtkui/BUILD.gn
@@ -97,10 +97,10 @@
              "//printing",
              "//skia",
 
-             # GTK pulls pangoft2, which requires HarfBuzz symbols. Since we
-             # link our own HarfBuzz, avoid mixing symbols from system HarfBuzz
-             # and own ones, hence the dependency to harfbuzz-ng here.
-             "//third_party/harfbuzz-ng",
+             # GTK pulls pangoft2, which requires HarfBuzz symbols. When linking
+             # our own HarfBuzz avoid mixing symbols from system HarfBuzz and
+             # our own through the indirect dependency to harfbuzz-ng here.
+             "//third_party:freetype_harfbuzz",
              "//ui/aura",
              "//ui/base",
              "//ui/base/ime",
diff --git a/components/cronet/android/cronet_url_request_context_adapter.cc b/components/cronet/android/cronet_url_request_context_adapter.cc
index 54c1c7e..a8f4a27 100644
--- a/components/cronet/android/cronet_url_request_context_adapter.cc
+++ b/components/cronet/android/cronet_url_request_context_adapter.cc
@@ -451,7 +451,7 @@
           static_cast<uint16_t>(quic_hint->alternate_port));
       context_->http_server_properties()->SetQuicAlternativeService(
           quic_server, alternative_service, base::Time::Max(),
-          net::QuicVersionVector());
+          net::QuicTransportVersionVector());
     }
   }
 
diff --git a/components/cronet/android/test/quic_test_server.cc b/components/cronet/android/test/quic_test_server.cc
index d98e541..b1c7ab664 100644
--- a/components/cronet/android/test/quic_test_server.cc
+++ b/components/cronet/android/test/quic_test_server.cc
@@ -55,8 +55,8 @@
       directory.Append("quic_test.example.com.key.sct")));
   g_quic_server = new net::QuicSimpleServer(
       std::move(proof_source), config,
-      net::QuicCryptoServerConfig::ConfigOptions(), net::AllSupportedVersions(),
-      g_quic_response_cache);
+      net::QuicCryptoServerConfig::ConfigOptions(),
+      net::AllSupportedTransportVersions(), g_quic_response_cache);
 
   // Start listening.
   int rv = g_quic_server->Listen(
diff --git a/components/cronet/ios/cronet_environment.mm b/components/cronet/ios/cronet_environment.mm
index da193f2..ce76b280 100644
--- a/components/cronet/ios/cronet_environment.mm
+++ b/components/cronet/ios/cronet_environment.mm
@@ -404,7 +404,7 @@
                                          quic_hint.port());
     main_context_->http_server_properties()->SetQuicAlternativeService(
         quic_hint_server, alternative_service, base::Time::Max(),
-        net::QuicVersionVector());
+        net::QuicTransportVersionVector());
   }
 
   main_context_->transport_security_state()
diff --git a/components/grpc_support/test/get_stream_engine.cc b/components/grpc_support/test/get_stream_engine.cc
index 7a71807..d26022d8 100644
--- a/components/grpc_support/test/get_stream_engine.cc
+++ b/components/grpc_support/test/get_stream_engine.cc
@@ -55,7 +55,7 @@
       url::SchemeHostPort quic_hint_server("https", kTestServerHost, 443);
       server_properties_->SetQuicAlternativeService(
           quic_hint_server, alternative_service, base::Time::Max(),
-          net::QuicVersionVector());
+          net::QuicTransportVersionVector());
 
       request_context_->set_cert_verifier(mock_cert_verifier_.get());
       request_context_->set_host_resolver(host_resolver_.get());
diff --git a/components/grpc_support/test/quic_test_server.cc b/components/grpc_support/test/quic_test_server.cc
index 1d2ad5b..fade232 100644
--- a/components/grpc_support/test/quic_test_server.cc
+++ b/components/grpc_support/test/quic_test_server.cc
@@ -91,8 +91,8 @@
 
   g_quic_server = new net::QuicSimpleServer(
       std::move(proof_source), config,
-      net::QuicCryptoServerConfig::ConfigOptions(), net::AllSupportedVersions(),
-      g_quic_response_cache);
+      net::QuicCryptoServerConfig::ConfigOptions(),
+      net::AllSupportedTransportVersions(), g_quic_response_cache);
 
   // Start listening on an unbound port.
   int rv = g_quic_server->Listen(
diff --git a/components/network_session_configurator/browser/network_session_configurator.cc b/components/network_session_configurator/browser/network_session_configurator.cc
index 2b35e17..9ee73c9 100644
--- a/components/network_session_configurator/browser/network_session_configurator.cc
+++ b/components/network_session_configurator/browser/network_session_configurator.cc
@@ -237,7 +237,7 @@
   return 0;
 }
 
-net::QuicVersionVector GetQuicVersions(
+net::QuicTransportVersionVector GetQuicVersions(
     const VariationParameters& quic_trial_params) {
   return network_session_configurator::ParseQuicVersions(
       GetVariationParam(quic_trial_params, "quic_version"));
@@ -306,7 +306,7 @@
 
   params->quic_user_agent_id = quic_user_agent_id;
 
-  net::QuicVersionVector supported_versions =
+  net::QuicTransportVersionVector supported_versions =
       GetQuicVersions(quic_trial_params);
   if (!supported_versions.empty())
     params->quic_supported_versions = supported_versions;
@@ -316,9 +316,11 @@
 
 namespace network_session_configurator {
 
-net::QuicVersionVector ParseQuicVersions(const std::string& quic_versions) {
-  net::QuicVersionVector supported_versions;
-  net::QuicVersionVector all_supported_versions = net::AllSupportedVersions();
+net::QuicTransportVersionVector ParseQuicVersions(
+    const std::string& quic_versions) {
+  net::QuicTransportVersionVector supported_versions;
+  net::QuicTransportVersionVector all_supported_versions =
+      net::AllSupportedTransportVersions();
 
   for (const base::StringPiece& version : base::SplitStringPiece(
            quic_versions, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)) {
@@ -385,7 +387,7 @@
     }
 
     if (command_line.HasSwitch(switches::kQuicVersion)) {
-      net::QuicVersionVector supported_versions =
+      net::QuicTransportVersionVector supported_versions =
           network_session_configurator::ParseQuicVersions(
               command_line.GetSwitchValueASCII(switches::kQuicVersion));
       if (!supported_versions.empty())
diff --git a/components/network_session_configurator/browser/network_session_configurator.h b/components/network_session_configurator/browser/network_session_configurator.h
index f9845a24..a3e624c26 100644
--- a/components/network_session_configurator/browser/network_session_configurator.h
+++ b/components/network_session_configurator/browser/network_session_configurator.h
@@ -20,7 +20,8 @@
 // trials and command line.
 
 // Parse serialized QUIC versions string.
-net::QuicVersionVector ParseQuicVersions(const std::string& quic_versions);
+net::QuicTransportVersionVector ParseQuicVersions(
+    const std::string& quic_versions);
 
 // Configure |params| based on field trials and command line,
 // and forcing (policy or other command line) arguments.
diff --git a/components/network_session_configurator/browser/network_session_configurator_unittest.cc b/components/network_session_configurator/browser/network_session_configurator_unittest.cc
index 74720bd..d71c3271 100644
--- a/components/network_session_configurator/browser/network_session_configurator_unittest.cc
+++ b/components/network_session_configurator/browser/network_session_configurator_unittest.cc
@@ -287,14 +287,14 @@
 TEST_F(NetworkSessionConfiguratorTest, QuicVersionFromFieldTrialParams) {
   std::map<std::string, std::string> field_trial_params;
   field_trial_params["quic_version"] =
-      net::QuicVersionToString(net::AllSupportedVersions().back());
+      net::QuicVersionToString(net::AllSupportedTransportVersions().back());
   variations::AssociateVariationParams("QUIC", "Enabled", field_trial_params);
   base::FieldTrialList::CreateFieldTrial("QUIC", "Enabled");
 
   ParseFieldTrials();
 
-  net::QuicVersionVector supported_versions;
-  supported_versions.push_back(net::AllSupportedVersions().back());
+  net::QuicTransportVersionVector supported_versions;
+  supported_versions.push_back(net::AllSupportedTransportVersions().back());
   EXPECT_EQ(supported_versions, params_.quic_supported_versions);
 }
 
@@ -302,8 +302,9 @@
        MultipleQuicVersionFromFieldTrialParams) {
   std::map<std::string, std::string> field_trial_params;
   std::string quic_versions =
-      net::QuicVersionToString(net::AllSupportedVersions().front()) + "," +
-      net::QuicVersionToString(net::AllSupportedVersions().back());
+      net::QuicVersionToString(net::AllSupportedTransportVersions().front()) +
+      "," +
+      net::QuicVersionToString(net::AllSupportedTransportVersions().back());
 
   field_trial_params["quic_version"] = quic_versions;
   variations::AssociateVariationParams("QUIC", "Enabled", field_trial_params);
@@ -311,17 +312,18 @@
 
   ParseFieldTrials();
 
-  net::QuicVersionVector supported_versions;
-  supported_versions.push_back(net::AllSupportedVersions().front());
-  supported_versions.push_back(net::AllSupportedVersions().back());
+  net::QuicTransportVersionVector supported_versions;
+  supported_versions.push_back(net::AllSupportedTransportVersions().front());
+  supported_versions.push_back(net::AllSupportedTransportVersions().back());
   EXPECT_EQ(supported_versions, params_.quic_supported_versions);
 }
 
 TEST_F(NetworkSessionConfiguratorTest, SameQuicVersionsFromFieldTrialParams) {
   std::map<std::string, std::string> field_trial_params;
   std::string quic_versions =
-      net::QuicVersionToString(net::AllSupportedVersions().front()) + "," +
-      net::QuicVersionToString(net::AllSupportedVersions().front());
+      net::QuicVersionToString(net::AllSupportedTransportVersions().front()) +
+      "," +
+      net::QuicVersionToString(net::AllSupportedTransportVersions().front());
 
   field_trial_params["quic_version"] = quic_versions;
   variations::AssociateVariationParams("QUIC", "Enabled", field_trial_params);
@@ -329,8 +331,8 @@
 
   ParseFieldTrials();
 
-  net::QuicVersionVector supported_versions;
-  supported_versions.push_back(net::AllSupportedVersions().front());
+  net::QuicTransportVersionVector supported_versions;
+  supported_versions.push_back(net::AllSupportedTransportVersions().front());
   EXPECT_EQ(supported_versions, params_.quic_supported_versions);
 }
 
@@ -458,7 +460,8 @@
 }
 
 TEST_F(NetworkSessionConfiguratorTest, QuicVersion) {
-  net::QuicVersionVector supported_versions = net::AllSupportedVersions();
+  net::QuicTransportVersionVector supported_versions =
+      net::AllSupportedTransportVersions();
   for (const auto& version : supported_versions) {
     base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
     command_line.AppendSwitch(switches::kEnableQuic);
diff --git a/components/url_formatter/BUILD.gn b/components/url_formatter/BUILD.gn
index b4ce96f..ef526ac 100644
--- a/components/url_formatter/BUILD.gn
+++ b/components/url_formatter/BUILD.gn
@@ -28,13 +28,12 @@
     "//components/url_formatter/top_domains",
     "//net",
     "//third_party/icu",
+    "//ui/gfx",
     "//url",
   ]
 
   if (is_android) {
     deps += [ "android:jni_headers" ]
-  } else {
-    deps += [ "//ui/gfx" ]
   }
 }
 
@@ -55,8 +54,4 @@
     "//ui/gfx",
     "//url",
   ]
-
-  if (is_android) {
-    deps -= [ "//ui/gfx" ]
-  }
 }
diff --git a/components/url_formatter/elide_url.cc b/components/url_formatter/elide_url.cc
index f42c9b8b2..c83e95d 100644
--- a/components/url_formatter/elide_url.cc
+++ b/components/url_formatter/elide_url.cc
@@ -8,6 +8,7 @@
 
 #include "base/i18n/rtl.h"
 #include "base/logging.h"
+#include "base/numerics/ranges.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/string_split.h"
@@ -16,15 +17,12 @@
 #include "components/url_formatter/url_formatter.h"
 #include "net/base/escape.h"
 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+#include "ui/gfx/text_elider.h"
+#include "ui/gfx/text_utils.h"
 #include "url/gurl.h"
 #include "url/origin.h"
 #include "url/url_constants.h"
 
-#if !defined(OS_ANDROID)
-#include "ui/gfx/text_elider.h"  // nogncheck
-#include "ui/gfx/text_utils.h"  // nogncheck
-#endif
-
 namespace {
 
 #if !defined(OS_ANDROID)
@@ -142,6 +140,81 @@
       base::ASCIIToUTF16(host_in_puny) : host;
 }
 
+// Adjust the components of |parsed| to describe a portion of a previous URL.
+// |offset| and |length| describe the substring range.  Components that fall
+// completely outside the specified range are invalidated, while others are
+// clamped to fit.  If |offset| is non-zero, the start positions of all valid
+// components are reduced by this offset.
+void AdjustParsed(int length, int offset, url::Parsed* parsed) {
+  DCHECK_GE(length, 0);
+  DCHECK_GE(offset, 0);
+
+  const std::vector<url::Component*> components = {
+      &(parsed->scheme), &(parsed->username), &(parsed->password),
+      &(parsed->host),   &(parsed->port),     &(parsed->path),
+      &(parsed->query),  &(parsed->ref),
+  };
+
+  for (auto* component : components) {
+    if (!component->is_valid())
+      continue;
+    int begin = base::ClampToRange(component->begin - offset, 0, length);
+    int end = base::ClampToRange(component->end() - offset, 0, length);
+    component->begin = begin;
+    component->len = end - begin;
+    if (component->len == 0)
+      component->reset();
+  }
+}
+
+// Elide a URL string with ellipsis at either the head or tail end, and adjust
+// |parsed| accordingly. This allows a formatted URL to be elided while
+// maintaining a Parsed description of the result.
+base::string16 ElideParsedUrlString(const base::string16& original,
+                                    const gfx::FontList& font_list,
+                                    float available_pixel_width,
+                                    gfx::ElideBehavior behavior,
+                                    url::Parsed* parsed) {
+  DCHECK(behavior == gfx::ELIDE_TAIL || behavior == gfx::ELIDE_HEAD);
+
+  base::string16 elided =
+      gfx::ElideText(original, font_list, available_pixel_width, behavior);
+  if (elided == original)
+    return elided;
+
+  // If elision reduced the string to a tiny remaining fragment, standardize it.
+  if (elided == (base::string16(gfx::kEllipsisUTF16) + gfx::kEllipsisUTF16))
+    elided = base::string16(gfx::kEllipsisUTF16);
+
+  int offset =
+      (behavior == gfx::ELIDE_HEAD) ? original.size() - elided.size() : 0;
+  AdjustParsed(elided.size(), offset, parsed);
+  return elided;
+}
+
+// Elide the path and onward components of a URL string to fit a specified
+// width, if possible.  If trimming these components allows the URL to fit,
+// |url_string| and |parsed| are updated and the function returns true.
+// Otherwise, inputs are untouched and the function returns false.
+bool ElideAfterHost(base::string16* url_string,
+                    const gfx::FontList& font_list,
+                    float available_pixel_width,
+                    url::Parsed* parsed) {
+  DCHECK(parsed->host.is_nonempty());
+  DCHECK(parsed->path.is_nonempty() || parsed->query.is_nonempty() ||
+         parsed->ref.is_nonempty());
+
+  const base::string16 shortest = url_string->substr(0, parsed->host.end()) +
+                                  gfx::kForwardSlash +
+                                  base::string16(gfx::kEllipsisUTF16);
+  if (available_pixel_width >= gfx::GetStringWidthF(shortest, font_list)) {
+    *url_string = ElideParsedUrlString(
+        *url_string, font_list, available_pixel_width, gfx::ELIDE_TAIL, parsed);
+    return true;
+  }
+  return false;
+}
+
 }  // namespace
 
 namespace url_formatter {
@@ -163,7 +236,6 @@
   if (available_pixel_width <= 0)
     return url_string;
 
-  // If non-standard, return plain eliding.
   if (!url.IsStandard())
     return gfx::ElideText(url_string, font_list, available_pixel_width,
                           gfx::ELIDE_TAIL);
@@ -427,4 +499,58 @@
   return result;
 }
 
+base::string16 ElideUrlSimple(const GURL& url,
+                              const gfx::FontList& font_list,
+                              float available_pixel_width,
+                              url::Parsed* parsed) {
+  DCHECK_NE(parsed, nullptr);
+
+  base::string16 url_string = url_formatter::FormatUrl(
+      url, url_formatter::kFormatUrlOmitDefaults, net::UnescapeRule::SPACES,
+      parsed, nullptr, nullptr);
+
+  if (available_pixel_width <= 0 ||
+      available_pixel_width >= gfx::GetStringWidthF(url_string, font_list)) {
+    return url_string;
+  }
+
+  // If non-standard, a file, or there is no host, simply elide from the right.
+  if (!url.IsStandard() || url.SchemeIsFile() || !parsed->host.is_nonempty()) {
+    return ElideParsedUrlString(url_string, font_list, available_pixel_width,
+                                gfx::ELIDE_TAIL, parsed);
+  }
+
+  bool has_path_ref_query = parsed->path.is_nonempty() ||
+                            parsed->query.is_nonempty() ||
+                            parsed->ref.is_nonempty();
+
+  // Try fitting the host with scheme preserved.
+  if (has_path_ref_query &&
+      ElideAfterHost(&url_string, font_list, available_pixel_width, parsed)) {
+    return url_string;
+  }
+
+  // Remove the scheme and try fitting the host again.
+  if (parsed->host.begin > 0) {
+    url_string.erase(0, parsed->host.begin);
+    AdjustParsed(url_string.size(), parsed->host.begin, parsed);
+
+    if (has_path_ref_query &&
+        ElideAfterHost(&url_string, font_list, available_pixel_width, parsed)) {
+      return url_string;
+    }
+  }
+
+  // Fully elide everything after the host, as none of it can fit.
+  if (has_path_ref_query) {
+    url_string = url_string.substr(0, parsed->host.end()) + gfx::kForwardSlash +
+                 base::string16(gfx::kEllipsisUTF16);
+    AdjustParsed(url_string.size(), 0, parsed);
+  }
+
+  // Only host remains, so elide from the left.
+  return ElideParsedUrlString(url_string, font_list, available_pixel_width,
+                              gfx::ELIDE_HEAD, parsed);
+}
+
 }  // namespace url_formatter
diff --git a/components/url_formatter/elide_url.h b/components/url_formatter/elide_url.h
index 8f53bf2..73d4d43 100644
--- a/components/url_formatter/elide_url.h
+++ b/components/url_formatter/elide_url.h
@@ -20,6 +20,7 @@
 
 namespace url {
 class Origin;
+struct Parsed;
 }
 
 namespace url_formatter {
@@ -28,7 +29,7 @@
 // gfx::GetStringWidthF which is not implemented in Android
 #if !defined(OS_ANDROID)
 // This function takes a GURL object and elides it. It returns a string
-// which composed of parts from subdomain, domain, path, filename and query.
+// composed of parts from subdomain, domain, path, filename and query.
 // A "..." is added automatically at the end if the elided string is bigger
 // than the |available_pixel_width|. For |available_pixel_width| == 0, a
 // formatted, but un-elided, string is returned.
@@ -52,6 +53,26 @@
                          float available_pixel_width);
 #endif  // !defined(OS_ANDROID)
 
+// Similar to ElideUrl, this function shortens a URL to fit a specified width,
+// but does so according to the origin presentation guidance at:
+// https://www.chromium.org/Home/chromium-security/enamel
+//
+// This method differs from ElideUrl in that:
+// - A Parsed structure is returned, allowing regions of the elided URL to be
+//   colored or styled. For example, if a path is completely elided to an
+//   ellipsis, the path component will describe the ellipsis.
+// - When necessary, the host portion is elided from the left, to preserve the
+//   TLD as long as possible. Subdomain is not treated specially.
+// - The path is elided from the right, with no special handling of the last
+//   path element, to avoid potentially long runtimes.
+//
+// This function should be merged with ElideUrl to have a single elision method.
+// See http://crbug.com/772476.
+base::string16 ElideUrlSimple(const GURL& url,
+                              const gfx::FontList& font_list,
+                              float available_pixel_width,
+                              url::Parsed* parsed);
+
 enum class SchemeDisplay {
   SHOW,
   OMIT_HTTP_AND_HTTPS,
diff --git a/components/url_formatter/elide_url_unittest.cc b/components/url_formatter/elide_url_unittest.cc
index 5d0b3a2..e15ae12 100644
--- a/components/url_formatter/elide_url_unittest.cc
+++ b/components/url_formatter/elide_url_unittest.cc
@@ -11,41 +11,89 @@
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
+#include "components/url_formatter/url_formatter.h"
+#include "net/base/escape.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/font_list.h"
+#include "ui/gfx/text_elider.h"
+#include "ui/gfx/text_utils.h"
 #include "url/gurl.h"
 #include "url/origin.h"
 
-#if !defined(OS_ANDROID)
-#include "ui/gfx/font_list.h"  // nogncheck
-#include "ui/gfx/text_elider.h"  // nogncheck
-#include "ui/gfx/text_utils.h"  // nogncheck
-#endif
-
 namespace {
 
+enum ElisionMethod {
+  kMethodOriginal,
+  kMethodSimple,
+};
+
 struct Testcase {
   const std::string input;
   const std::string output;
 };
 
-#if !defined(OS_ANDROID)
-void RunElisionTest(const std::vector<Testcase>& testcases) {
-  const gfx::FontList font_list;
-  for (const auto& testcase : testcases) {
-    SCOPED_TRACE("Eliding " + testcase.input);
-    const GURL url(testcase.input);
-    const float available_width =
-        gfx::GetStringWidthF(base::UTF8ToUTF16(testcase.output), font_list);
-    EXPECT_EQ(base::UTF8ToUTF16(testcase.output),
-              url_formatter::ElideUrl(url, font_list, available_width));
-  }
-}
-
 struct ProgressiveTestcase {
   const std::string input;
   const std::vector<std::string> output;
 };
 
+struct UrlComponent {
+  url::Parsed::ComponentType type;
+  int begin;
+  int len;
+};
+
+struct ParsingTestcase {
+  const std::string input;
+  const std::string output;
+  const std::vector<UrlComponent> components;
+};
+
+base::string16 Elide(const GURL& url,
+                     const gfx::FontList& font_list,
+                     float available_width,
+                     ElisionMethod method) {
+  switch (method) {
+    case kMethodSimple: {
+      url::Parsed parsed;
+      return url_formatter::ElideUrlSimple(url, font_list, available_width,
+                                           &parsed);
+    }
+#if !defined(OS_ANDROID)
+    case kMethodOriginal:
+      return url_formatter::ElideUrl(url, font_list, available_width);
+#endif
+    default:
+      NOTREACHED();
+      return base::string16();
+  }
+}
+
+url::Component* GetComponent(url::Parsed* parsed,
+                             url::Parsed::ComponentType type) {
+  switch (type) {
+    case url::Parsed::SCHEME:
+      return &parsed->scheme;
+    case url::Parsed::USERNAME:
+      return &parsed->username;
+    case url::Parsed::PASSWORD:
+      return &parsed->password;
+    case url::Parsed::HOST:
+      return &parsed->host;
+    case url::Parsed::PORT:
+      return &parsed->port;
+    case url::Parsed::PATH:
+      return &parsed->path;
+    case url::Parsed::QUERY:
+      return &parsed->query;
+    case url::Parsed::REF:
+      return &parsed->ref;
+    default:
+      NOTREACHED();
+      return nullptr;
+  }
+}
+
 // Verify that one or more URLs passes through an explicit sequence of elided
 // strings as available space progressively decreases. This helps ensure that
 // transitional corner cases are handled properly. To be tolerant of
@@ -62,7 +110,8 @@
 // google.com/in...   <- Must match.
 //
 void RunProgressiveElisionTest(
-    const std::vector<ProgressiveTestcase>& testcases) {
+    const std::vector<ProgressiveTestcase>& testcases,
+    ElisionMethod method) {
   const gfx::FontList font_list;
   for (const auto& testcase : testcases) {
     SCOPED_TRACE("Eliding " + testcase.input);
@@ -87,7 +136,7 @@
     for (size_t i = 0; i < testcase.output.size(); i++) {
       const auto& expected = testcase.output[i];
       base::string16 expected_utf16 = base::UTF8ToUTF16(expected);
-      base::string16 elided = url_formatter::ElideUrl(url, font_list, width);
+      base::string16 elided = Elide(url, font_list, width, method);
       if (expected_utf16 != elided) {
         if (i > 0 && i < testcase.output.size() - 1 &&
             mismatches < kMaxConsecutiveMismatches) {
@@ -106,6 +155,20 @@
   }
 }
 
+#if !defined(OS_ANDROID)
+
+void RunElisionTest(const std::vector<Testcase>& testcases) {
+  const gfx::FontList font_list;
+  for (const auto& testcase : testcases) {
+    SCOPED_TRACE("Eliding " + testcase.input);
+    const GURL url(testcase.input);
+    const float available_width =
+        gfx::GetStringWidthF(base::UTF8ToUTF16(testcase.output), font_list);
+    EXPECT_EQ(base::UTF8ToUTF16(testcase.output),
+              url_formatter::ElideUrl(url, font_list, available_width));
+  }
+}
+
 // Test eliding of commonplace URLs.
 TEST(TextEliderTest, TestGeneralEliding) {
   const std::string kEllipsisStr(gfx::kEllipsis);
@@ -191,7 +254,7 @@
            /* clang-format on */
        }},
   };
-  RunProgressiveElisionTest(progressive_testcases);
+  RunProgressiveElisionTest(progressive_testcases, kMethodOriginal);
 }
 
 // When there is very little space available, the elision code will shorten
@@ -329,7 +392,7 @@
      }},
   };
 
-  RunProgressiveElisionTest(progressive_testcases);
+  RunProgressiveElisionTest(progressive_testcases, kMethodOriginal);
 
   const std::vector<Testcase> testcases = {
       // Eliding file URLs with nothing after the ':' shouldn't crash.
@@ -667,4 +730,154 @@
       << "Explicitly test the url::Origin which takes an empty, invalid URL";
 }
 
+TEST(TextEliderTest, TestSimpleElisionMethod) {
+  const std::string kEllipsisStr(gfx::kEllipsis);
+  const std::vector<ProgressiveTestcase> testcases = {
+      {"https://www.abc.com/def/",
+       {
+           /* clang-format off */
+           {"https://www.abc.com/def/"},
+           {"https://www.abc.com/d" + kEllipsisStr},
+           {"https://www.abc.com/" + kEllipsisStr},
+           {"www.abc.com/def/"},
+           {"www.abc.com/d" + kEllipsisStr},
+           {"www.abc.com/" + kEllipsisStr},
+           {kEllipsisStr + "ww.abc.com/" + kEllipsisStr},
+           {kEllipsisStr + "w.abc.com/" + kEllipsisStr},
+           {kEllipsisStr + ".abc.com/" + kEllipsisStr},
+           {kEllipsisStr + "abc.com/" + kEllipsisStr},
+           {kEllipsisStr + "bc.com/" + kEllipsisStr},
+           {kEllipsisStr + "c.com/" + kEllipsisStr},
+           {kEllipsisStr + ".com/" + kEllipsisStr},
+           {kEllipsisStr + "com/" + kEllipsisStr},
+           {kEllipsisStr + "om/" + kEllipsisStr},
+           {kEllipsisStr + "m/" + kEllipsisStr},
+           {kEllipsisStr + "/" + kEllipsisStr},
+           {kEllipsisStr},
+           {""},
+           /* clang-format on */
+       }},
+      {"file://fs/file",
+       {
+           /* clang-format off */
+           "file://fs/file",
+           "file://fs/fi" + kEllipsisStr,
+           "file://fs/f" + kEllipsisStr,
+           "file://fs/" + kEllipsisStr,
+           "file://fs" + kEllipsisStr,
+           "file://f" + kEllipsisStr,
+           "file://" + kEllipsisStr,
+           "file:/" + kEllipsisStr,
+           "file:" + kEllipsisStr,
+           "file" + kEllipsisStr,
+           "fil" + kEllipsisStr,
+           "fi" + kEllipsisStr,
+           "f" + kEllipsisStr,
+           kEllipsisStr,
+           "",
+           /* clang-format on */
+       }},
+  };
+  RunProgressiveElisionTest(testcases, kMethodSimple);
+}
+
+// Verify that the secure elision method returns URL component data that
+// correctly represents the elided URL.
+void RunElisionParsingTest(const std::vector<ParsingTestcase>& testcases) {
+  const gfx::FontList font_list;
+  for (const auto& testcase : testcases) {
+    SCOPED_TRACE(testcase.input + " to " + testcase.output);
+
+    const GURL url(testcase.input);
+    const float available_width =
+        gfx::GetStringWidthF(base::UTF8ToUTF16(testcase.output), font_list);
+
+    url::Parsed parsed;
+    auto elided =
+        url_formatter::ElideUrlSimple(url, font_list, available_width, &parsed);
+    EXPECT_EQ(base::UTF8ToUTF16(testcase.output), elided);
+
+    // Build an expected Parsed struct from the sparse test expectations.
+    url::Parsed expected;
+    for (const auto& expectation : testcase.components) {
+      url::Component* component = GetComponent(&expected, expectation.type);
+      component->begin = expectation.begin;
+      component->len = expectation.len;
+    }
+
+    const std::vector<url::Parsed::ComponentType> kComponents = {
+        url::Parsed::SCHEME, url::Parsed::USERNAME, url::Parsed::PASSWORD,
+        url::Parsed::HOST,   url::Parsed::PORT,     url::Parsed::PATH,
+        url::Parsed::QUERY,  url::Parsed::REF,
+    };
+    for (const auto& type : kComponents) {
+      EXPECT_EQ(GetComponent(&expected, type)->begin,
+                GetComponent(&parsed, type)->begin)
+          << " in component " << type;
+      EXPECT_EQ(GetComponent(&expected, type)->len,
+                GetComponent(&parsed, type)->len)
+          << " in component " << type;
+    }
+  }
+}
+
+// Verify that during elision, the parsed URL components are properly modified.
+TEST(TextEliderTest, TestElisionParsingAdjustments) {
+  const std::string kEllipsisStr(gfx::kEllipsis);
+  const std::vector<ParsingTestcase> testcases = {
+      // HTTPS with path.
+      {"https://www.google.com/intl/en/ads/",
+       "https://www.google.com/intl/en/ads/",
+       {{url::Parsed::ComponentType::SCHEME, 0, 5},
+        {url::Parsed::ComponentType::HOST, 8, 14},
+        {url::Parsed::ComponentType::PATH, 22, 13}}},
+      {"https://www.google.com/intl/en/ads/",
+       "https://www.google.com/intl/en/a" + kEllipsisStr,
+       {{url::Parsed::ComponentType::SCHEME, 0, 5},
+        {url::Parsed::ComponentType::HOST, 8, 14},
+        {url::Parsed::ComponentType::PATH, 22, 11}}},
+      {"https://www.google.com/intl/en/ads/",
+       "https://www.google.com/" + kEllipsisStr,
+       {{url::Parsed::ComponentType::SCHEME, 0, 5},
+        {url::Parsed::ComponentType::HOST, 8, 14},
+        {url::Parsed::ComponentType::PATH, 22, 2}}},
+      {"https://www.google.com/intl/en/ads/",
+       kEllipsisStr + "google.com/" + kEllipsisStr,
+       {{url::Parsed::ComponentType::HOST, 0, 11},
+        {url::Parsed::ComponentType::PATH, 11, 2}}},
+      {"https://www.google.com/intl/en/ads/",
+       kEllipsisStr,
+       {{url::Parsed::ComponentType::PATH, 0, 1}}},
+      // HTTPS with no path.
+      {"https://www.google.com/",
+       "www.google.com",
+       {{url::Parsed::ComponentType::HOST, 0, 14}}},
+      {"https://www.google.com/",
+       kEllipsisStr,
+       {{url::Parsed::ComponentType::HOST, 0, 1}}},
+      // HTTP with no path.
+      {"http://www.google.com/",
+       "www.google.com",
+       {{url::Parsed::ComponentType::HOST, 0, 14}}},
+      // File URLs.
+      {"file:///C:/path1/path2",
+       "file:///C:/path1/" + kEllipsisStr,
+       {{url::Parsed::ComponentType::SCHEME, 0, 4},
+        {url::Parsed::ComponentType::PATH, 7, 11}}},
+      {"file:///C:/path1/path2",
+       "fi" + kEllipsisStr,
+       {{url::Parsed::ComponentType::SCHEME, 0, 3}}},
+      {"file:///C:/path1/path2",
+       kEllipsisStr,
+       {{url::Parsed::ComponentType::SCHEME, 0, 1}}},
+      // RTL URL.
+      {"http://127.0.0.1/ا/http://attack.com‬",
+       kEllipsisStr + "7.0.0.1/" + kEllipsisStr,
+       {{url::Parsed::ComponentType::HOST, 0, 8},
+        {url::Parsed::ComponentType::PATH, 8, 2}}},
+  };
+
+  RunElisionParsingTest(testcases);
+}
+
 }  // namespace
diff --git a/content/shell/BUILD.gn b/content/shell/BUILD.gn
index afe5698..8254082 100644
--- a/content/shell/BUILD.gn
+++ b/content/shell/BUILD.gn
@@ -386,7 +386,7 @@
   }
 
   if (is_linux) {
-    deps += [ "//third_party/freetype" ]
+    deps += [ "//build/config/freetype" ]
   }
 
   if (!enable_plugins) {
diff --git a/docs/linux_build_instructions.md b/docs/linux_build_instructions.md
index f11ce267..d251b6bb 100644
--- a/docs/linux_build_instructions.md
+++ b/docs/linux_build_instructions.md
@@ -122,6 +122,15 @@
 This section contains some things you can change to speed up your builds,
 sorted so that the things that make the biggest difference are first.
 
+#### Jumbo/Unity builds
+
+Jumbo builds merge many translation units ("source files") and compile them
+together. Since a large portion of Chromium's code is in shared header files,
+this dramatically reduces the total amount of work needed. Check out the
+[Jumbo / Unity builds](jumbo.md) for more information.
+
+Enable jumbo builds by setting the GN arg `use_jumbo_build=true`.
+
 #### Disable NaCl
 
 By default, the build includes support for
diff --git a/docs/mac_build_instructions.md b/docs/mac_build_instructions.md
index 7e9b3f2..bf811b4 100644
--- a/docs/mac_build_instructions.md
+++ b/docs/mac_build_instructions.md
@@ -132,6 +132,17 @@
 rebuilds and linking faster (at the cost of not getting symbolized backtraces
 in gdb).
 
+#### Jumbo/Unity builds
+
+Jumbo builds merge many translation units ("source files") and compile them
+together. Since a large portion of Chromium's code is in shared header files,
+this dramatically reduces the total amount of work needed. Check out the
+[Jumbo / Unity builds](jumbo.md) for more information.
+
+Enable jumbo builds by setting the GN arg `use_jumbo_build=true`.
+
+#### CCache
+
 You might also want to [install ccache](ccache_mac.md) to speed up the build.
 
 ## Build Chromium
diff --git a/headless/BUILD.gn b/headless/BUILD.gn
index 6d7e184..95822b0 100644
--- a/headless/BUILD.gn
+++ b/headless/BUILD.gn
@@ -245,8 +245,8 @@
     ]
 
     deps = [
+      "//build/config/freetype",
       "//third_party/fontconfig",
-      "//third_party/freetype",
     ]
 
     configs += [ ":headless_implementation" ]
diff --git a/net/BUILD.gn b/net/BUILD.gn
index 2ca509c..45a815e 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -1177,12 +1177,24 @@
       "quic/core/crypto/aes_128_gcm_12_decrypter.h",
       "quic/core/crypto/aes_128_gcm_12_encrypter.cc",
       "quic/core/crypto/aes_128_gcm_12_encrypter.h",
+      "quic/core/crypto/aes_128_gcm_decrypter.cc",
+      "quic/core/crypto/aes_128_gcm_decrypter.h",
+      "quic/core/crypto/aes_128_gcm_encrypter.cc",
+      "quic/core/crypto/aes_128_gcm_encrypter.h",
+      "quic/core/crypto/aes_256_gcm_decrypter.cc",
+      "quic/core/crypto/aes_256_gcm_decrypter.h",
+      "quic/core/crypto/aes_256_gcm_encrypter.cc",
+      "quic/core/crypto/aes_256_gcm_encrypter.h",
       "quic/core/crypto/cert_compressor.cc",
       "quic/core/crypto/cert_compressor.h",
       "quic/core/crypto/chacha20_poly1305_decrypter.cc",
       "quic/core/crypto/chacha20_poly1305_decrypter.h",
       "quic/core/crypto/chacha20_poly1305_encrypter.cc",
       "quic/core/crypto/chacha20_poly1305_encrypter.h",
+      "quic/core/crypto/chacha20_poly1305_tls_decrypter.cc",
+      "quic/core/crypto/chacha20_poly1305_tls_decrypter.h",
+      "quic/core/crypto/chacha20_poly1305_tls_encrypter.cc",
+      "quic/core/crypto/chacha20_poly1305_tls_encrypter.h",
       "quic/core/crypto/channel_id.cc",
       "quic/core/crypto/channel_id.h",
       "quic/core/crypto/common_cert_set.cc",
@@ -4970,9 +4982,15 @@
     "quic/core/congestion_control/windowed_filter_test.cc",
     "quic/core/crypto/aes_128_gcm_12_decrypter_test.cc",
     "quic/core/crypto/aes_128_gcm_12_encrypter_test.cc",
+    "quic/core/crypto/aes_128_gcm_decrypter_test.cc",
+    "quic/core/crypto/aes_128_gcm_encrypter_test.cc",
+    "quic/core/crypto/aes_256_gcm_decrypter_test.cc",
+    "quic/core/crypto/aes_256_gcm_encrypter_test.cc",
     "quic/core/crypto/cert_compressor_test.cc",
     "quic/core/crypto/chacha20_poly1305_decrypter_test.cc",
     "quic/core/crypto/chacha20_poly1305_encrypter_test.cc",
+    "quic/core/crypto/chacha20_poly1305_tls_decrypter_test.cc",
+    "quic/core/crypto/chacha20_poly1305_tls_encrypter_test.cc",
     "quic/core/crypto/channel_id_test.cc",
     "quic/core/crypto/common_cert_set_test.cc",
     "quic/core/crypto/crypto_framer_test.cc",
diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h
index c6501bb7..ebbf81a 100644
--- a/net/http/http_network_session.h
+++ b/net/http/http_network_session.h
@@ -120,7 +120,7 @@
     // QUIC runtime configuration options.
 
     // Versions of QUIC which may be used.
-    QuicVersionVector quic_supported_versions;
+    QuicTransportVersionVector quic_supported_versions;
     // User agent description to send in the QUIC handshake.
     std::string quic_user_agent_id;
     // Limit on the size of QUIC packets.
diff --git a/net/http/http_server_properties.cc b/net/http/http_server_properties.cc
index a1289cae..b28084586 100644
--- a/net/http/http_server_properties.cc
+++ b/net/http/http_server_properties.cc
@@ -86,14 +86,14 @@
     base::Time expiration) {
   DCHECK_EQ(alternative_service.protocol, kProtoHTTP2);
   return AlternativeServiceInfo(alternative_service, expiration,
-                                QuicVersionVector());
+                                QuicTransportVersionVector());
 }
 
 // static
 AlternativeServiceInfo AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
     const AlternativeService& alternative_service,
     base::Time expiration,
-    const QuicVersionVector& advertised_versions) {
+    const QuicTransportVersionVector& advertised_versions) {
   DCHECK_EQ(alternative_service.protocol, kProtoQUIC);
   return AlternativeServiceInfo(alternative_service, expiration,
                                 advertised_versions);
@@ -106,7 +106,7 @@
 AlternativeServiceInfo::AlternativeServiceInfo(
     const AlternativeService& alternative_service,
     base::Time expiration,
-    const QuicVersionVector& advertised_versions)
+    const QuicTransportVersionVector& advertised_versions)
     : alternative_service_(alternative_service), expiration_(expiration) {
   if (alternative_service_.protocol == kProtoQUIC) {
     advertised_versions_ = advertised_versions;
diff --git a/net/http/http_server_properties.h b/net/http/http_server_properties.h
index bdcbfc5..6983403 100644
--- a/net/http/http_server_properties.h
+++ b/net/http/http_server_properties.h
@@ -131,7 +131,7 @@
   static AlternativeServiceInfo CreateQuicAlternativeServiceInfo(
       const AlternativeService& alternative_service,
       base::Time expiration,
-      const QuicVersionVector& advertised_versions);
+      const QuicTransportVersionVector& advertised_versions);
 
   AlternativeServiceInfo();
   ~AlternativeServiceInfo();
@@ -170,7 +170,8 @@
     expiration_ = expiration;
   }
 
-  void set_advertised_versions(const QuicVersionVector& advertised_versions) {
+  void set_advertised_versions(
+      const QuicTransportVersionVector& advertised_versions) {
     if (alternative_service_.protocol != kProtoQUIC)
       return;
 
@@ -190,14 +191,14 @@
 
   base::Time expiration() const { return expiration_; }
 
-  const QuicVersionVector& advertised_versions() const {
+  const QuicTransportVersionVector& advertised_versions() const {
     return advertised_versions_;
   }
 
  private:
   AlternativeServiceInfo(const AlternativeService& alternative_service,
                          base::Time expiration,
-                         const QuicVersionVector& advertised_versions);
+                         const QuicTransportVersionVector& advertised_versions);
 
   AlternativeService alternative_service_;
   base::Time expiration_;
@@ -206,7 +207,7 @@
   // by Chrome. If empty, defaults to versions used by the current instance of
   // the netstack.
   // This list MUST be sorted in ascending order.
-  QuicVersionVector advertised_versions_;
+  QuicTransportVersionVector advertised_versions_;
 };
 
 struct NET_EXPORT SupportsQuic {
@@ -328,7 +329,7 @@
       const url::SchemeHostPort& origin,
       const AlternativeService& alternative_service,
       base::Time expiration,
-      const QuicVersionVector& advertised_versions) = 0;
+      const QuicTransportVersionVector& advertised_versions) = 0;
 
   // Set alternative services for |origin|.  Previous alternative services for
   // |origin| are discarded.
diff --git a/net/http/http_server_properties_impl.cc b/net/http/http_server_properties_impl.cc
index e614a78..523a4b0b 100644
--- a/net/http/http_server_properties_impl.cc
+++ b/net/http/http_server_properties_impl.cc
@@ -383,7 +383,7 @@
     const url::SchemeHostPort& origin,
     const AlternativeService& alternative_service,
     base::Time expiration,
-    const QuicVersionVector& advertised_versions) {
+    const QuicTransportVersionVector& advertised_versions) {
   DCHECK(alternative_service.protocol == kProtoQUIC);
 
   return SetAlternativeServices(
diff --git a/net/http/http_server_properties_impl.h b/net/http/http_server_properties_impl.h
index aa6a86dc..9a0dfa36 100644
--- a/net/http/http_server_properties_impl.h
+++ b/net/http/http_server_properties_impl.h
@@ -107,7 +107,7 @@
       const url::SchemeHostPort& origin,
       const AlternativeService& alternative_service,
       base::Time expiration,
-      const QuicVersionVector& advertised_versions) override;
+      const QuicTransportVersionVector& advertised_versions) override;
   bool SetAlternativeServices(const url::SchemeHostPort& origin,
                               const AlternativeServiceInfoVector&
                                   alternative_service_info_vector) override;
diff --git a/net/http/http_server_properties_manager.cc b/net/http/http_server_properties_manager.cc
index 60591797..3997b2459 100644
--- a/net/http/http_server_properties_manager.cc
+++ b/net/http/http_server_properties_manager.cc
@@ -220,7 +220,7 @@
     const url::SchemeHostPort& origin,
     const AlternativeService& alternative_service,
     base::Time expiration,
-    const QuicVersionVector& advertised_versions) {
+    const QuicTransportVersionVector& advertised_versions) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   const bool changed = http_server_properties_impl_->SetQuicAlternativeService(
       origin, alternative_service, expiration, advertised_versions);
@@ -820,7 +820,7 @@
                << "server: " << server_str;
       return false;
     }
-    QuicVersionVector advertised_versions;
+    QuicTransportVersionVector advertised_versions;
     for (const auto& value : *versions_list) {
       int version;
       if (!value.GetAsInteger(&version)) {
@@ -828,7 +828,7 @@
                  << server_str;
         return false;
       }
-      advertised_versions.push_back(QuicVersion(version));
+      advertised_versions.push_back(QuicTransportVersion(version));
     }
     alternative_service_info->set_advertised_versions(advertised_versions);
   }
diff --git a/net/http/http_server_properties_manager.h b/net/http/http_server_properties_manager.h
index 88f96c1..1d415475 100644
--- a/net/http/http_server_properties_manager.h
+++ b/net/http/http_server_properties_manager.h
@@ -101,7 +101,7 @@
       const url::SchemeHostPort& origin,
       const AlternativeService& alternative_service,
       base::Time expiration,
-      const QuicVersionVector& advertised_versions) override;
+      const QuicTransportVersionVector& advertised_versions) override;
   bool SetAlternativeServices(const url::SchemeHostPort& origin,
                               const AlternativeServiceInfoVector&
                                   alternative_service_info_vector) override;
diff --git a/net/http/http_server_properties_manager_unittest.cc b/net/http/http_server_properties_manager_unittest.cc
index 6748139..5a87782 100644
--- a/net/http/http_server_properties_manager_unittest.cc
+++ b/net/http/http_server_properties_manager_unittest.cc
@@ -137,7 +137,7 @@
   MockPrefDelegate* pref_delegate_;  // Owned by HttpServerPropertiesManager.
   std::unique_ptr<HttpServerPropertiesManager> http_server_props_manager_;
   base::Time one_day_from_now_;
-  QuicVersionVector advertised_versions_;
+  QuicTransportVersionVector advertised_versions_;
 
   // Overrides the main thread's message loop with a mock tick clock.
   base::ScopedMockTimeMessageLoopTaskRunner test_task_runner_;
@@ -1293,7 +1293,8 @@
   AlternativeService quic_alternative_service1(kProtoQUIC, "", 443);
   base::Time expiration1;
   ASSERT_TRUE(base::Time::FromUTCString("2036-12-01 10:00:00", &expiration1));
-  QuicVersionVector advertised_versions = {QUIC_VERSION_37, QUIC_VERSION_35};
+  QuicTransportVersionVector advertised_versions = {QUIC_VERSION_37,
+                                                    QUIC_VERSION_35};
   alternative_service_info_vector.push_back(
       AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
           quic_alternative_service1, expiration1, advertised_versions));
@@ -1399,7 +1400,7 @@
   EXPECT_EQ(123, alternative_service_info_vector[1].alternative_service().port);
   EXPECT_EQ(base::Time::Max(), alternative_service_info_vector[1].expiration());
   // Verify advertised versions.
-  const QuicVersionVector loaded_advertised_versions =
+  const QuicTransportVersionVector loaded_advertised_versions =
       alternative_service_info_vector[1].advertised_versions();
   EXPECT_EQ(2u, loaded_advertised_versions.size());
   EXPECT_EQ(QUIC_VERSION_35, loaded_advertised_versions[0]);
@@ -1459,7 +1460,8 @@
   // AlternativeService.
   AlternativeServiceInfoVector alternative_service_info_vector_2;
   // Quic alternative service set with two advertised QUIC versions.
-  QuicVersionVector advertised_versions = {QUIC_VERSION_37, QUIC_VERSION_35};
+  QuicTransportVersionVector advertised_versions = {QUIC_VERSION_37,
+                                                    QUIC_VERSION_35};
   alternative_service_info_vector_2.push_back(
       AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
           quic_alternative_service1, expiration1, advertised_versions));
@@ -1488,7 +1490,8 @@
   // #3: Set AlternativeService with same advertised_versions.
   AlternativeServiceInfoVector alternative_service_info_vector_3;
   // A same set of QUIC versions but listed in a different order.
-  QuicVersionVector advertised_versions_2 = {QUIC_VERSION_35, QUIC_VERSION_37};
+  QuicTransportVersionVector advertised_versions_2 = {QUIC_VERSION_35,
+                                                      QUIC_VERSION_37};
   alternative_service_info_vector_3.push_back(
       AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
           quic_alternative_service1, expiration1, advertised_versions_2));
diff --git a/net/http/http_stream_factory.cc b/net/http/http_stream_factory.cc
index 4c21ffce..51741ff 100644
--- a/net/http/http_stream_factory.cc
+++ b/net/http/http_stream_factory.cc
@@ -52,10 +52,11 @@
       continue;
     }
     // Check if QUIC version is supported. Filter supported QUIC versions.
-    QuicVersionVector advertised_versions;
+    QuicTransportVersionVector advertised_versions;
     if (protocol == kProtoQUIC && !alternative_service_entry.version.empty()) {
       bool match_found = false;
-      for (QuicVersion supported : session->params().quic_supported_versions) {
+      for (QuicTransportVersion supported :
+           session->params().quic_supported_versions) {
         for (uint16_t advertised : alternative_service_entry.version) {
           if (supported == advertised) {
             match_found = true;
diff --git a/net/http/http_stream_factory_impl_job.cc b/net/http/http_stream_factory_impl_job.cc
index 2822212..6d72d6b0 100644
--- a/net/http/http_stream_factory_impl_job.cc
+++ b/net/http/http_stream_factory_impl_job.cc
@@ -161,7 +161,7 @@
                                 HostPortPair destination,
                                 GURL origin_url,
                                 NextProto alternative_protocol,
-                                QuicVersion quic_version,
+                                QuicTransportVersion quic_version,
                                 const ProxyServer& alternative_proxy_server,
                                 bool enable_ip_based_pooling,
                                 NetLog* net_log)
@@ -1487,7 +1487,7 @@
     HostPortPair destination,
     GURL origin_url,
     NextProto alternative_protocol,
-    QuicVersion quic_version,
+    QuicTransportVersion quic_version,
     bool enable_ip_based_pooling,
     NetLog* net_log) {
   return std::make_unique<HttpStreamFactoryImpl::Job>(
diff --git a/net/http/http_stream_factory_impl_job.h b/net/http/http_stream_factory_impl_job.h
index 7bc00f0..3fdec07 100644
--- a/net/http/http_stream_factory_impl_job.h
+++ b/net/http/http_stream_factory_impl_job.h
@@ -190,7 +190,7 @@
       HostPortPair destination,
       GURL origin_url,
       NextProto alternative_protocol,
-      QuicVersion quic_version,
+      QuicTransportVersion quic_version,
       const ProxyServer& alternative_proxy_server,
       bool enable_ip_based_pooling,
       NetLog* net_log);
@@ -447,9 +447,9 @@
   // True if Job uses QUIC.
   const bool using_quic_;
 
-  // QuicVersion that should be used to connect to the QUIC server if Job uses
-  // QUIC.
-  QuicVersion quic_version_;
+  // QuicTransportVersion that should be used to connect to the QUIC server if
+  // Job uses QUIC.
+  QuicTransportVersion quic_version_;
 
   // True if Alternative Service protocol field requires that HTTP/2 is used.
   // In this case, Job fails if it cannot pool to an existing SpdySession and
@@ -542,7 +542,7 @@
       HostPortPair destination,
       GURL origin_url,
       NextProto alternative_protocol,
-      QuicVersion quic_version,
+      QuicTransportVersion quic_version,
       bool enable_ip_based_pooling,
       NetLog* net_log);
 
diff --git a/net/http/http_stream_factory_impl_job_controller.cc b/net/http/http_stream_factory_impl_job_controller.cc
index ca52a77b..1bf48b9 100644
--- a/net/http/http_stream_factory_impl_job_controller.cc
+++ b/net/http/http_stream_factory_impl_job_controller.cc
@@ -802,7 +802,7 @@
   // Create an alternative job if alternative service is set up for this domain.
   alternative_service_info_ =
       GetAlternativeServiceInfoFor(request_info_, delegate_, stream_type_);
-  QuicVersion quic_version = QUIC_VERSION_UNSUPPORTED;
+  QuicTransportVersion quic_version = QUIC_VERSION_UNSUPPORTED;
   if (alternative_service_info_.protocol() == kProtoQUIC) {
     quic_version =
         SelectQuicVersion(alternative_service_info_.advertised_versions());
@@ -1171,15 +1171,15 @@
   return first_alternative_service_info;
 }
 
-QuicVersion HttpStreamFactoryImpl::JobController::SelectQuicVersion(
-    const QuicVersionVector& advertised_versions) {
-  const QuicVersionVector& supported_versions =
+QuicTransportVersion HttpStreamFactoryImpl::JobController::SelectQuicVersion(
+    const QuicTransportVersionVector& advertised_versions) {
+  const QuicTransportVersionVector& supported_versions =
       session_->params().quic_supported_versions;
   if (advertised_versions.empty())
     return supported_versions[0];
 
-  for (const QuicVersion& supported : supported_versions) {
-    for (const QuicVersion& advertised : advertised_versions) {
+  for (const QuicTransportVersion& supported : supported_versions) {
+    for (const QuicTransportVersion& advertised : advertised_versions) {
       if (supported == advertised) {
         DCHECK_NE(QUIC_VERSION_UNSUPPORTED, supported);
         return supported;
diff --git a/net/http/http_stream_factory_impl_job_controller.h b/net/http/http_stream_factory_impl_job_controller.h
index 32ca2626..24a4da31 100644
--- a/net/http/http_stream_factory_impl_job_controller.h
+++ b/net/http/http_stream_factory_impl_job_controller.h
@@ -277,12 +277,13 @@
       HttpStreamRequest::Delegate* delegate,
       HttpStreamRequest::StreamType stream_type);
 
-  // Returns a QuicVersion that has been advertised in |advertised_versions|
-  // and is supported.  If more than one QuicVersions are supported, the first
-  // matched in the supported versions will be returned.  If no mutually
-  // supported version is found, QUIC_VERSION_UNSUPPORTED_VERSION will be
-  // returned.
-  QuicVersion SelectQuicVersion(const QuicVersionVector& advertised_versions);
+  // Returns a QuicTransportVersion that has been advertised in
+  // |advertised_versions| and is supported.  If more than one
+  // QuicTransportVersions are supported, the first matched in the supported
+  // versions will be returned.  If no mutually supported version is found,
+  // QUIC_VERSION_UNSUPPORTED_VERSION will be returned.
+  QuicTransportVersion SelectQuicVersion(
+      const QuicTransportVersionVector& advertised_versions);
 
   // Remove session from the SpdySessionRequestMap.
   void RemoveRequestFromSpdySessionRequestMap();
diff --git a/net/http/http_stream_factory_impl_job_controller_unittest.cc b/net/http/http_stream_factory_impl_job_controller_unittest.cc
index 3ac4398..1f376040 100644
--- a/net/http/http_stream_factory_impl_job_controller_unittest.cc
+++ b/net/http/http_stream_factory_impl_job_controller_unittest.cc
@@ -2170,7 +2170,7 @@
 
   // Set alternative service with no advertised version.
   session_->http_server_properties()->SetQuicAlternativeService(
-      server, alternative_service, expiration, QuicVersionVector());
+      server, alternative_service, expiration, QuicTransportVersionVector());
 
   AlternativeServiceInfo alt_svc_info =
       JobControllerPeer::GetAlternativeServiceInfoFor(
@@ -2181,7 +2181,7 @@
 
   // Set alternative service for the same server with the same list of versions
   // that is supported.
-  QuicVersionVector supported_versions =
+  QuicTransportVersionVector supported_versions =
       session_->params().quic_supported_versions;
   ASSERT_TRUE(session_->http_server_properties()->SetQuicAlternativeService(
       server, alternative_service, expiration, supported_versions));
@@ -2192,9 +2192,9 @@
   std::sort(supported_versions.begin(), supported_versions.end());
   EXPECT_EQ(supported_versions, alt_svc_info.advertised_versions());
 
-  QuicVersion unsupported_version_1(QUIC_VERSION_UNSUPPORTED);
-  QuicVersion unsupported_version_2(QUIC_VERSION_UNSUPPORTED);
-  for (const QuicVersion& version : AllSupportedVersions()) {
+  QuicTransportVersion unsupported_version_1(QUIC_VERSION_UNSUPPORTED);
+  QuicTransportVersion unsupported_version_2(QUIC_VERSION_UNSUPPORTED);
+  for (const QuicTransportVersion& version : AllSupportedTransportVersions()) {
     if (std::find(supported_versions.begin(), supported_versions.end(),
                   version) != supported_versions.end())
       continue;
@@ -2209,7 +2209,7 @@
   // Set alternative service for the same server with two QUIC versions:
   // - one unsupported version: |unsupported_version_1|,
   // - one supported version: session_->params().quic_supported_versions[0].
-  QuicVersionVector mixed_quic_versions = {
+  QuicTransportVersionVector mixed_quic_versions = {
       unsupported_version_1, session_->params().quic_supported_versions[0]};
   ASSERT_TRUE(session_->http_server_properties()->SetQuicAlternativeService(
       server, alternative_service, expiration, mixed_quic_versions));
diff --git a/net/http/http_stream_factory_impl_unittest.cc b/net/http/http_stream_factory_impl_unittest.cc
index ba9eff3..5c3a0a0 100644
--- a/net/http/http_stream_factory_impl_unittest.cc
+++ b/net/http/http_stream_factory_impl_unittest.cc
@@ -2236,7 +2236,7 @@
 
 class HttpStreamFactoryBidirectionalQuicTest
     : public ::testing::Test,
-      public ::testing::WithParamInterface<QuicVersion> {
+      public ::testing::WithParamInterface<QuicTransportVersion> {
  protected:
   HttpStreamFactoryBidirectionalQuicTest()
       : default_url_(kDefaultUrl),
@@ -2266,7 +2266,8 @@
 
   void Initialize() {
     params_.enable_quic = true;
-    params_.quic_supported_versions = test::SupportedVersions(GetParam());
+    params_.quic_supported_versions =
+        test::SupportedTransportVersions(GetParam());
 
     HttpNetworkSession::Context session_context;
     session_context.http_server_properties = &http_server_properties_;
@@ -2344,7 +2345,7 @@
 
 INSTANTIATE_TEST_CASE_P(Version,
                         HttpStreamFactoryBidirectionalQuicTest,
-                        ::testing::ValuesIn(AllSupportedVersions()));
+                        ::testing::ValuesIn(AllSupportedTransportVersions()));
 
 TEST_P(HttpStreamFactoryBidirectionalQuicTest,
        RequestBidirectionalStreamImplQuicAlternative) {
diff --git a/net/http/http_stream_factory_test_util.cc b/net/http/http_stream_factory_test_util.cc
index 8333f704..fff12f7 100644
--- a/net/http/http_stream_factory_test_util.cc
+++ b/net/http/http_stream_factory_test_util.cc
@@ -27,7 +27,7 @@
     HostPortPair destination,
     GURL origin_url,
     NextProto alternative_protocol,
-    QuicVersion quic_version,
+    QuicTransportVersion quic_version,
     const ProxyServer& alternative_proxy_server,
     bool enable_ip_based_pooling,
     NetLog* net_log)
@@ -98,7 +98,7 @@
     HostPortPair destination,
     GURL origin_url,
     NextProto alternative_protocol,
-    QuicVersion quic_version,
+    QuicTransportVersion quic_version,
     bool enable_ip_based_pooling,
     NetLog* net_log) {
   auto alternative_job = std::make_unique<MockHttpStreamFactoryImplJob>(
diff --git a/net/http/http_stream_factory_test_util.h b/net/http/http_stream_factory_test_util.h
index 736fda1..238cc50 100644
--- a/net/http/http_stream_factory_test_util.h
+++ b/net/http/http_stream_factory_test_util.h
@@ -118,7 +118,7 @@
                                HostPortPair destination,
                                GURL origin_url,
                                NextProto alternative_protocol,
-                               QuicVersion quic_version,
+                               QuicTransportVersion quic_version,
                                const ProxyServer& alternative_proxy_server,
                                bool enable_ip_based_pooling,
                                NetLog* net_log);
@@ -162,7 +162,7 @@
       HostPortPair destination,
       GURL origin_url,
       NextProto alternative_protocol,
-      QuicVersion quic_version,
+      QuicTransportVersion quic_version,
       bool enable_ip_based_pooling,
       NetLog* net_log) override;
 
diff --git a/net/quic/chromium/bidirectional_stream_quic_impl_unittest.cc b/net/quic/chromium/bidirectional_stream_quic_impl_unittest.cc
index c4f0ef9..300bca1 100644
--- a/net/quic/chromium/bidirectional_stream_quic_impl_unittest.cc
+++ b/net/quic/chromium/bidirectional_stream_quic_impl_unittest.cc
@@ -379,7 +379,7 @@
 }  // namespace
 
 class BidirectionalStreamQuicImplTest
-    : public ::testing::TestWithParam<QuicVersion> {
+    : public ::testing::TestWithParam<QuicTransportVersion> {
  protected:
   static const bool kFin = true;
   static const bool kIncludeVersion = true;
@@ -474,7 +474,7 @@
         connection_id_, QuicSocketAddress(QuicSocketAddressImpl(peer_addr_)),
         helper_.get(), alarm_factory_.get(),
         new QuicChromiumPacketWriter(socket.get()), true /* owns_writer */,
-        Perspective::IS_CLIENT, SupportedVersions(GetParam()));
+        Perspective::IS_CLIENT, SupportedTransportVersions(GetParam()));
     base::TimeTicks dns_end = base::TimeTicks::Now();
     base::TimeTicks dns_start = dns_end - base::TimeDelta::FromMilliseconds(1);
 
@@ -772,7 +772,7 @@
 
 INSTANTIATE_TEST_CASE_P(Version,
                         BidirectionalStreamQuicImplTest,
-                        ::testing::ValuesIn(AllSupportedVersions()));
+                        ::testing::ValuesIn(AllSupportedTransportVersions()));
 
 TEST_P(BidirectionalStreamQuicImplTest, GetRequest) {
   SetRequest("GET", "/", DEFAULT_PRIORITY);
diff --git a/net/quic/chromium/crypto/proof_source_chromium.cc b/net/quic/chromium/crypto/proof_source_chromium.cc
index 1ce25217..3732d80 100644
--- a/net/quic/chromium/crypto/proof_source_chromium.cc
+++ b/net/quic/chromium/crypto/proof_source_chromium.cc
@@ -80,7 +80,7 @@
     const QuicSocketAddress& server_addr,
     const string& hostname,
     const string& server_config,
-    QuicVersion quic_version,
+    QuicTransportVersion quic_version,
     QuicStringPiece chlo_hash,
     const QuicTagVector& /* connection_options */,
     QuicReferenceCountedPointer<ProofSource::Chain>* out_chain,
@@ -136,7 +136,7 @@
 void ProofSourceChromium::GetProof(const QuicSocketAddress& server_addr,
                                    const std::string& hostname,
                                    const std::string& server_config,
-                                   QuicVersion quic_version,
+                                   QuicTransportVersion quic_version,
                                    QuicStringPiece chlo_hash,
                                    const QuicTagVector& connection_options,
                                    std::unique_ptr<Callback> callback) {
diff --git a/net/quic/chromium/crypto/proof_source_chromium.h b/net/quic/chromium/crypto/proof_source_chromium.h
index 0a5079cc..911d70c 100644
--- a/net/quic/chromium/crypto/proof_source_chromium.h
+++ b/net/quic/chromium/crypto/proof_source_chromium.h
@@ -36,7 +36,7 @@
   void GetProof(const QuicSocketAddress& server_ip,
                 const std::string& hostname,
                 const std::string& server_config,
-                QuicVersion quic_version,
+                QuicTransportVersion quic_version,
                 QuicStringPiece chlo_hash,
                 const QuicTagVector& connection_options,
                 std::unique_ptr<Callback> callback) override;
@@ -56,7 +56,7 @@
   bool GetProofInner(const QuicSocketAddress& server_ip,
                      const std::string& hostname,
                      const std::string& server_config,
-                     QuicVersion quic_version,
+                     QuicTransportVersion quic_version,
                      QuicStringPiece chlo_hash,
                      const QuicTagVector& connection_options,
                      QuicReferenceCountedPointer<ProofSource::Chain>* out_chain,
diff --git a/net/quic/chromium/crypto/proof_test_chromium.cc b/net/quic/chromium/crypto/proof_test_chromium.cc
index 05ae7c4c..6258191 100644
--- a/net/quic/chromium/crypto/proof_test_chromium.cc
+++ b/net/quic/chromium/crypto/proof_test_chromium.cc
@@ -56,7 +56,7 @@
                      const string& hostname,
                      const uint16_t port,
                      const string& server_config,
-                     QuicVersion quic_version,
+                     QuicTransportVersion quic_version,
                      QuicStringPiece chlo_hash,
                      const std::vector<string>& certs,
                      const string& proof,
@@ -115,13 +115,13 @@
   QuicCryptoProof* proof_;
 };
 
-class ProofTest : public ::testing::TestWithParam<QuicVersion> {};
+class ProofTest : public ::testing::TestWithParam<QuicTransportVersion> {};
 
 }  // namespace
 
-INSTANTIATE_TEST_CASE_P(QuicVersion,
+INSTANTIATE_TEST_CASE_P(QuicTransportVersion,
                         ProofTest,
-                        ::testing::ValuesIn(AllSupportedVersions()));
+                        ::testing::ValuesIn(AllSupportedTransportVersions()));
 
 // TODO(rtenneti): Enable testing of ProofVerifier. See http://crbug.com/514468.
 TEST_P(ProofTest, DISABLED_Verify) {
@@ -135,7 +135,7 @@
   const uint16_t port = 8443;
   const string first_chlo_hash = "first chlo hash bytes";
   const string second_chlo_hash = "first chlo hash bytes";
-  const QuicVersion quic_version = GetParam();
+  const QuicTransportVersion quic_version = GetParam();
 
   bool called = false;
   bool first_called = false;
diff --git a/net/quic/chromium/crypto/proof_verifier_chromium.cc b/net/quic/chromium/crypto/proof_verifier_chromium.cc
index e6c9821..bc85469 100644
--- a/net/quic/chromium/crypto/proof_verifier_chromium.cc
+++ b/net/quic/chromium/crypto/proof_verifier_chromium.cc
@@ -67,7 +67,7 @@
       const std::string& hostname,
       const uint16_t port,
       const std::string& server_config,
-      QuicVersion quic_version,
+      QuicTransportVersion quic_version,
       QuicStringPiece chlo_hash,
       const std::vector<std::string>& certs,
       const std::string& cert_sct,
@@ -112,7 +112,7 @@
   int DoVerifyCertComplete(int result);
 
   bool VerifySignature(const std::string& signed_data,
-                       QuicVersion quic_version,
+                       QuicTransportVersion quic_version,
                        QuicStringPiece chlo_hash,
                        const std::string& signature,
                        const std::string& cert);
@@ -198,7 +198,7 @@
     const string& hostname,
     const uint16_t port,
     const string& server_config,
-    QuicVersion quic_version,
+    QuicTransportVersion quic_version,
     QuicStringPiece chlo_hash,
     const std::vector<string>& certs,
     const std::string& cert_sct,
@@ -457,11 +457,12 @@
   return result;
 }
 
-bool ProofVerifierChromium::Job::VerifySignature(const string& signed_data,
-                                                 QuicVersion quic_version,
-                                                 QuicStringPiece chlo_hash,
-                                                 const string& signature,
-                                                 const string& cert) {
+bool ProofVerifierChromium::Job::VerifySignature(
+    const string& signed_data,
+    QuicTransportVersion quic_version,
+    QuicStringPiece chlo_hash,
+    const string& signature,
+    const string& cert) {
   QuicStringPiece spki;
   if (!asn1::ExtractSPKIFromDERCert(cert, &spki)) {
     DLOG(WARNING) << "ExtractSPKIFromDERCert failed";
@@ -542,7 +543,7 @@
     const std::string& hostname,
     const uint16_t port,
     const std::string& server_config,
-    QuicVersion quic_version,
+    QuicTransportVersion quic_version,
     QuicStringPiece chlo_hash,
     const std::vector<std::string>& certs,
     const std::string& cert_sct,
diff --git a/net/quic/chromium/crypto/proof_verifier_chromium.h b/net/quic/chromium/crypto/proof_verifier_chromium.h
index e6f4622..f5b0db50 100644
--- a/net/quic/chromium/crypto/proof_verifier_chromium.h
+++ b/net/quic/chromium/crypto/proof_verifier_chromium.h
@@ -77,7 +77,7 @@
       const std::string& hostname,
       const uint16_t port,
       const std::string& server_config,
-      QuicVersion quic_version,
+      QuicTransportVersion quic_version,
       QuicStringPiece chlo_hash,
       const std::vector<std::string>& certs,
       const std::string& cert_sct,
diff --git a/net/quic/chromium/quic_chromium_client_session.cc b/net/quic/chromium/quic_chromium_client_session.cc
index 82d7928..26d724d 100644
--- a/net/quic/chromium/quic_chromium_client_session.cc
+++ b/net/quic/chromium/quic_chromium_client_session.cc
@@ -200,7 +200,7 @@
       quic_error_(QUIC_NO_ERROR),
       port_migration_detected_(false),
       server_id_(session_->server_id()),
-      quic_version_(session->connection()->version()),
+      quic_version_(session->connection()->transport_version()),
       push_handle_(nullptr),
       was_ever_used_(false) {
   DCHECK(session_);
@@ -223,7 +223,7 @@
 }
 
 void QuicChromiumClientSession::Handle::OnSessionClosed(
-    QuicVersion quic_version,
+    QuicTransportVersion quic_version,
     int net_error,
     QuicErrorCode quic_error,
     bool port_migration_detected,
@@ -275,11 +275,11 @@
   }
 }
 
-QuicVersion QuicChromiumClientSession::Handle::GetQuicVersion() const {
+QuicTransportVersion QuicChromiumClientSession::Handle::GetQuicVersion() const {
   if (!session_)
     return quic_version_;
 
-  return session_->connection()->version();
+  return session_->connection()->transport_version();
 }
 
 void QuicChromiumClientSession::Handle::ResetPromised(
@@ -801,9 +801,9 @@
 void QuicChromiumClientSession::AddHandle(Handle* handle) {
   if (going_away_) {
     RecordUnexpectedObservers(ADD_OBSERVER);
-    handle->OnSessionClosed(connection()->version(), ERR_UNEXPECTED, error(),
-                            port_migration_detected_, GetConnectTiming(),
-                            WasConnectionEverUsed());
+    handle->OnSessionClosed(connection()->transport_version(), ERR_UNEXPECTED,
+                            error(), port_migration_detected_,
+                            GetConnectTiming(), WasConnectionEverUsed());
     return;
   }
 
@@ -1361,7 +1361,7 @@
   }
 
   UMA_HISTOGRAM_SPARSE_SLOWLY("Net.QuicSession.QuicVersion",
-                              connection()->version());
+                              connection()->transport_version());
   NotifyFactoryOfSessionGoingAway();
   QuicSession::OnConnectionClosed(error, error_details, source);
 
@@ -1381,7 +1381,7 @@
 }
 
 void QuicChromiumClientSession::OnSuccessfulVersionNegotiation(
-    const QuicVersion& version) {
+    const QuicTransportVersion& version) {
   logger_->OnSuccessfulVersionNegotiation(version);
   QuicSpdySession::OnSuccessfulVersionNegotiation(version);
 }
@@ -1609,9 +1609,9 @@
   while (!handles_.empty()) {
     Handle* handle = *handles_.begin();
     handles_.erase(handle);
-    handle->OnSessionClosed(connection()->version(), net_error, error(),
-                            port_migration_detected_, GetConnectTiming(),
-                            WasConnectionEverUsed());
+    handle->OnSessionClosed(connection()->transport_version(), net_error,
+                            error(), port_migration_detected_,
+                            GetConnectTiming(), WasConnectionEverUsed());
   }
 }
 
@@ -1637,7 +1637,8 @@
 std::unique_ptr<base::Value> QuicChromiumClientSession::GetInfoAsValue(
     const std::set<HostPortPair>& aliases) {
   std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
-  dict->SetString("version", QuicVersionToString(connection()->version()));
+  dict->SetString("version",
+                  QuicVersionToString(connection()->transport_version()));
   dict->SetInteger("open_streams", GetNumOpenOutgoingStreams());
   std::unique_ptr<base::ListValue> stream_list(new base::ListValue());
   for (DynamicStreamMap::const_iterator it = dynamic_streams().begin();
@@ -1854,8 +1855,8 @@
   return connect_timing_;
 }
 
-QuicVersion QuicChromiumClientSession::GetQuicVersion() const {
-  return connection()->version();
+QuicTransportVersion QuicChromiumClientSession::GetQuicVersion() const {
+  return connection()->transport_version();
 }
 
 size_t QuicChromiumClientSession::EstimateMemoryUsage() const {
diff --git a/net/quic/chromium/quic_chromium_client_session.h b/net/quic/chromium/quic_chromium_client_session.h
index 0ed8d04..91366dc 100644
--- a/net/quic/chromium/quic_chromium_client_session.h
+++ b/net/quic/chromium/quic_chromium_client_session.h
@@ -134,7 +134,7 @@
     bool SharesSameSession(const Handle& other) const;
 
     // Returns the QUIC version used by the session.
-    QuicVersion GetQuicVersion() const;
+    QuicTransportVersion GetQuicVersion() const;
 
     // Copies the remote udp address into |address| and returns a net error
     // code.
@@ -177,7 +177,7 @@
     void OnCryptoHandshakeConfirmed();
 
     // Called when the session is closed with a net error.
-    void OnSessionClosed(QuicVersion quic_version,
+    void OnSessionClosed(QuicTransportVersion quic_version,
                          int net_error,
                          QuicErrorCode quic_error,
                          bool port_migration_detected,
@@ -204,7 +204,7 @@
     QuicErrorCode quic_error_;
     bool port_migration_detected_;
     QuicServerId server_id_;
-    QuicVersion quic_version_;
+    QuicTransportVersion quic_version_;
     LoadTimingInfo::ConnectTiming connect_timing_;
     QuicClientPushPromiseIndex* push_promise_index_;
 
@@ -371,7 +371,8 @@
   void OnConnectionClosed(QuicErrorCode error,
                           const std::string& error_details,
                           ConnectionCloseSource source) override;
-  void OnSuccessfulVersionNegotiation(const QuicVersion& version) override;
+  void OnSuccessfulVersionNegotiation(
+      const QuicTransportVersion& version) override;
   void OnPathDegrading() override;
   bool HasOpenDynamicStreams() const override;
 
@@ -479,7 +480,7 @@
 
   const LoadTimingInfo::ConnectTiming& GetConnectTiming();
 
-  QuicVersion GetQuicVersion() const;
+  QuicTransportVersion GetQuicVersion() const;
 
   // Returns the estimate of dynamically allocated memory in bytes.
   // See base/trace_event/memory_usage_estimator.h.
diff --git a/net/quic/chromium/quic_chromium_client_session_test.cc b/net/quic/chromium/quic_chromium_client_session_test.cc
index 0b20929..83fa7506 100644
--- a/net/quic/chromium/quic_chromium_client_session_test.cc
+++ b/net/quic/chromium/quic_chromium_client_session_test.cc
@@ -81,7 +81,7 @@
 };
 
 class QuicChromiumClientSessionTest
-    : public ::testing::TestWithParam<QuicVersion> {
+    : public ::testing::TestWithParam<QuicTransportVersion> {
  public:
   QuicChromiumClientSessionTest()
       : crypto_config_(crypto_test_utils::ProofVerifierForTesting()),
@@ -126,7 +126,7 @@
     QuicConnection* connection = new QuicConnection(
         0, QuicSocketAddress(QuicSocketAddressImpl(kIpEndPoint)), &helper_,
         &alarm_factory_, writer, true, Perspective::IS_CLIENT,
-        SupportedVersions(GetParam()));
+        SupportedTransportVersions(GetParam()));
     session_.reset(new TestingQuicChromiumClientSession(
         connection, std::move(socket),
         /*stream_factory=*/nullptr, &crypto_client_stream_factory_, &clock_,
@@ -201,7 +201,7 @@
 
 INSTANTIATE_TEST_CASE_P(Tests,
                         QuicChromiumClientSessionTest,
-                        ::testing::ValuesIn(AllSupportedVersions()));
+                        ::testing::ValuesIn(AllSupportedTransportVersions()));
 
 TEST_P(QuicChromiumClientSessionTest, CryptoConnect) {
   MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
@@ -1093,7 +1093,6 @@
 }
 
 TEST_P(QuicChromiumClientSessionTest, MigrateToSocket) {
-  FLAGS_quic_reloadable_flag_quic_use_stream_notifier2 = false;
   MockRead old_reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
   std::unique_ptr<QuicEncryptedPacket> settings_packet(
       client_maker_.MakeInitialSettingsPacket(1, nullptr));
@@ -1150,11 +1149,9 @@
   struct iovec iov[1];
   iov[0].iov_base = data;
   iov[0].iov_len = 4;
-  if (session_->save_data_before_consumption()) {
-    QuicStreamPeer::SendBuffer(stream).SaveStreamData(
-        QuicIOVector(iov, arraysize(iov), 4), 0, 4);
-    QuicStreamPeer::SetStreamBytesWritten(4, stream);
-  }
+  QuicStreamPeer::SendBuffer(stream).SaveStreamData(
+      QuicIOVector(iov, arraysize(iov), 4), 0, 4);
+  QuicStreamPeer::SetStreamBytesWritten(4, stream);
   session_->WritevData(stream, stream->id(),
                        QuicIOVector(iov, arraysize(iov), 4), 0, NO_FIN,
                        nullptr);
diff --git a/net/quic/chromium/quic_chromium_client_stream_test.cc b/net/quic/chromium/quic_chromium_client_stream_test.cc
index 2b6f40d5..148459fd 100644
--- a/net/quic/chromium/quic_chromium_client_stream_test.cc
+++ b/net/quic/chromium/quic_chromium_client_stream_test.cc
@@ -153,14 +153,14 @@
 MockQuicClientSessionBase::~MockQuicClientSessionBase() {}
 
 class QuicChromiumClientStreamTest
-    : public ::testing::TestWithParam<QuicVersion> {
+    : public ::testing::TestWithParam<QuicTransportVersion> {
  public:
   QuicChromiumClientStreamTest()
       : crypto_config_(crypto_test_utils::ProofVerifierForTesting()),
         session_(new MockQuicConnection(&helper_,
                                         &alarm_factory_,
                                         Perspective::IS_CLIENT,
-                                        SupportedVersions(GetParam())),
+                                        SupportedTransportVersions(GetParam())),
                  &push_promise_index_) {
     stream_ = new QuicChromiumClientStream(kTestStreamId, &session_,
                                            NetLogWithSource());
@@ -254,7 +254,7 @@
 
 INSTANTIATE_TEST_CASE_P(Version,
                         QuicChromiumClientStreamTest,
-                        ::testing::ValuesIn(AllSupportedVersions()));
+                        ::testing::ValuesIn(AllSupportedTransportVersions()));
 
 TEST_P(QuicChromiumClientStreamTest, Handle) {
   EXPECT_TRUE(handle_->IsOpen());
diff --git a/net/quic/chromium/quic_connection_logger.cc b/net/quic/chromium/quic_connection_logger.cc
index 8096427..6e42adc 100644
--- a/net/quic/chromium/quic_connection_logger.cc
+++ b/net/quic/chromium/quic_connection_logger.cc
@@ -203,7 +203,7 @@
     NetLogCaptureMode /* capture_mode */) {
   auto dict = std::make_unique<base::DictionaryValue>();
   auto versions = std::make_unique<base::ListValue>();
-  for (QuicVersionVector::const_iterator it = packet->versions.begin();
+  for (QuicTransportVersionVector::const_iterator it = packet->versions.begin();
        it != packet->versions.end(); ++it) {
     versions->AppendString(QuicVersionToString(*it));
   }
@@ -524,7 +524,7 @@
 }
 
 void QuicConnectionLogger::OnProtocolVersionMismatch(
-    QuicVersion received_version) {
+    QuicTransportVersion received_version) {
   // TODO(rtenneti): Add logging.
 }
 
@@ -713,7 +713,7 @@
 }
 
 void QuicConnectionLogger::OnSuccessfulVersionNegotiation(
-    const QuicVersion& version) {
+    const QuicTransportVersion& version) {
   if (!net_log_is_capturing_)
     return;
   string quic_version = QuicVersionToString(version);
diff --git a/net/quic/chromium/quic_connection_logger.h b/net/quic/chromium/quic_connection_logger.h
index 0a459ce..173f85a 100644
--- a/net/quic/chromium/quic_connection_logger.h
+++ b/net/quic/chromium/quic_connection_logger.h
@@ -58,7 +58,7 @@
   void OnIncorrectConnectionId(QuicConnectionId connection_id) override;
   void OnUndecryptablePacket() override;
   void OnDuplicatePacket(QuicPacketNumber packet_number) override;
-  void OnProtocolVersionMismatch(QuicVersion version) override;
+  void OnProtocolVersionMismatch(QuicTransportVersion version) override;
   void OnPacketHeader(const QuicPacketHeader& header) override;
   void OnStreamFrame(const QuicStreamFrame& frame) override;
   void OnAckFrame(const QuicAckFrame& frame) override;
@@ -76,7 +76,8 @@
   void OnConnectionClosed(QuicErrorCode error,
                           const std::string& error_details,
                           ConnectionCloseSource source) override;
-  void OnSuccessfulVersionNegotiation(const QuicVersion& version) override;
+  void OnSuccessfulVersionNegotiation(
+      const QuicTransportVersion& version) override;
   void OnRttChanged(QuicTime::Delta rtt) const override;
 
   void OnCryptoHandshakeMessageReceived(const CryptoHandshakeMessage& message);
diff --git a/net/quic/chromium/quic_end_to_end_unittest.cc b/net/quic/chromium/quic_end_to_end_unittest.cc
index 97a8147..b601451 100644
--- a/net/quic/chromium/quic_end_to_end_unittest.cc
+++ b/net/quic/chromium/quic_end_to_end_unittest.cc
@@ -181,7 +181,8 @@
     server_config_options_.token_binding_params = QuicTagVector{kTB10, kP256};
     server_.reset(new QuicSimpleServer(
         crypto_test_utils::ProofSourceForTesting(), server_config_,
-        server_config_options_, AllSupportedVersions(), &response_cache_));
+        server_config_options_, AllSupportedTransportVersions(),
+        &response_cache_));
     server_->Listen(server_address_);
     server_address_ = server_->server_address();
     server_->StartReading();
diff --git a/net/quic/chromium/quic_http_stream.cc b/net/quic/chromium/quic_http_stream.cc
index ce389f7a..fbeb7fd7 100644
--- a/net/quic/chromium/quic_http_stream.cc
+++ b/net/quic/chromium/quic_http_stream.cc
@@ -74,7 +74,7 @@
 }
 
 HttpResponseInfo::ConnectionInfo QuicHttpStream::ConnectionInfoFromQuicVersion(
-    QuicVersion quic_version) {
+    QuicTransportVersion quic_version) {
   switch (quic_version) {
     case QUIC_VERSION_UNSUPPORTED:
       return HttpResponseInfo::CONNECTION_INFO_QUIC_UNKNOWN_VERSION;
diff --git a/net/quic/chromium/quic_http_stream.h b/net/quic/chromium/quic_http_stream.h
index 9add6840..77945b8 100644
--- a/net/quic/chromium/quic_http_stream.h
+++ b/net/quic/chromium/quic_http_stream.h
@@ -66,7 +66,7 @@
   void SetPriority(RequestPriority priority) override;
 
   static HttpResponseInfo::ConnectionInfo ConnectionInfoFromQuicVersion(
-      QuicVersion quic_version);
+      QuicTransportVersion quic_version);
 
  private:
   friend class test::QuicHttpStreamPeer;
diff --git a/net/quic/chromium/quic_http_stream_test.cc b/net/quic/chromium/quic_http_stream_test.cc
index 11076be..1ae50ba 100644
--- a/net/quic/chromium/quic_http_stream_test.cc
+++ b/net/quic/chromium/quic_http_stream_test.cc
@@ -77,7 +77,7 @@
 
 class TestQuicConnection : public QuicConnection {
  public:
-  TestQuicConnection(const QuicVersionVector& versions,
+  TestQuicConnection(const QuicTransportVersionVector& versions,
                      QuicConnectionId connection_id,
                      IPEndPoint address,
                      QuicChromiumConnectionHelper* helper,
@@ -161,7 +161,8 @@
   }
 };
 
-class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> {
+class QuicHttpStreamTest
+    : public ::testing::TestWithParam<QuicTransportVersion> {
  public:
   void CloseStream(QuicHttpStream* stream, int /*rv*/) { stream->Close(false); }
 
@@ -263,8 +264,7 @@
         .WillRepeatedly(Return(kMaxPacketSize));
     EXPECT_CALL(*send_algorithm_, PacingRate(_))
         .WillRepeatedly(Return(QuicBandwidth::Zero()));
-    EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _))
-        .WillRepeatedly(Return(QuicTime::Delta::Zero()));
+    EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true));
     EXPECT_CALL(*send_algorithm_, BandwidthEstimate())
         .WillRepeatedly(Return(QuicBandwidth::Zero()));
     EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)).Times(AnyNumber());
@@ -275,10 +275,10 @@
         new QuicChromiumConnectionHelper(&clock_, &random_generator_));
     alarm_factory_.reset(new QuicChromiumAlarmFactory(runner_.get(), &clock_));
 
-    connection_ =
-        new TestQuicConnection(SupportedVersions(GetParam()), connection_id_,
-                               peer_addr_, helper_.get(), alarm_factory_.get(),
-                               new QuicChromiumPacketWriter(socket.get()));
+    connection_ = new TestQuicConnection(
+        SupportedTransportVersions(GetParam()), connection_id_, peer_addr_,
+        helper_.get(), alarm_factory_.get(),
+        new QuicChromiumPacketWriter(socket.get()));
     connection_->set_visitor(&visitor_);
     connection_->SetSendAlgorithm(send_algorithm_);
 
@@ -580,7 +580,7 @@
 
 INSTANTIATE_TEST_CASE_P(Version,
                         QuicHttpStreamTest,
-                        ::testing::ValuesIn(AllSupportedVersions()));
+                        ::testing::ValuesIn(AllSupportedTransportVersions()));
 
 TEST_P(QuicHttpStreamTest, RenewStreamForAuth) {
   Initialize();
diff --git a/net/quic/chromium/quic_network_transaction_unittest.cc b/net/quic/chromium/quic_network_transaction_unittest.cc
index bfb6ecf2..22fce42 100644
--- a/net/quic/chromium/quic_network_transaction_unittest.cc
+++ b/net/quic/chromium/quic_network_transaction_unittest.cc
@@ -124,14 +124,14 @@
     return os;
   }
 
-  QuicVersion version;
+  QuicTransportVersion version;
   DestinationType destination_type;
 };
 
 std::string GenerateQuicVersionsListForAltSvcHeader(
-    const QuicVersionVector& versions) {
+    const QuicTransportVersionVector& versions) {
   std::string result = "";
-  for (const QuicVersion& version : versions) {
+  for (const QuicTransportVersion& version : versions) {
     if (!result.empty())
       result.append(",");
     result.append(base::IntToString(version));
@@ -141,8 +141,9 @@
 
 std::vector<PoolingTestParams> GetPoolingTestParams() {
   std::vector<PoolingTestParams> params;
-  QuicVersionVector all_supported_versions = AllSupportedVersions();
-  for (const QuicVersion version : all_supported_versions) {
+  QuicTransportVersionVector all_supported_versions =
+      AllSupportedTransportVersions();
+  for (const QuicTransportVersion version : all_supported_versions) {
     params.push_back(PoolingTestParams{version, SAME_AS_FIRST});
     params.push_back(PoolingTestParams{version, SAME_AS_SECOND});
     params.push_back(PoolingTestParams{version, DIFFERENT});
@@ -236,11 +237,11 @@
 
 class QuicNetworkTransactionTest
     : public PlatformTest,
-      public ::testing::WithParamInterface<QuicVersion> {
+      public ::testing::WithParamInterface<QuicTransportVersion> {
  protected:
   QuicNetworkTransactionTest()
       : version_(GetParam()),
-        supported_versions_(SupportedVersions(version_)),
+        supported_versions_(SupportedTransportVersions(version_)),
         client_maker_(version_,
                       0,
                       &clock_,
@@ -513,7 +514,7 @@
         std::move(headers), offset);
   }
 
-  void CreateSession(const QuicVersionVector& supported_versions) {
+  void CreateSession(const QuicTransportVersionVector& supported_versions) {
     session_params_.enable_quic = true;
     session_params_.quic_supported_versions = supported_versions;
 
@@ -753,8 +754,8 @@
     ASSERT_TRUE(ssl_data->cert);
   }
 
-  const QuicVersion version_;
-  QuicVersionVector supported_versions_;
+  const QuicTransportVersion version_;
+  QuicTransportVersionVector supported_versions_;
   QuicFlagSaver flags_;  // Save/restore all QUIC flag values.
   MockClock clock_;
   QuicTestPacketMaker client_maker_;
@@ -806,7 +807,7 @@
 
 INSTANTIATE_TEST_CASE_P(Version,
                         QuicNetworkTransactionTest,
-                        ::testing::ValuesIn(AllSupportedVersions()));
+                        ::testing::ValuesIn(AllSupportedTransportVersions()));
 
 TEST_P(QuicNetworkTransactionTest, SocketWatcherEnabled) {
   session_params_.origins_to_force_quic_on.insert(
@@ -1198,10 +1199,10 @@
 }
 
 TEST_P(QuicNetworkTransactionTest, DoNotUseQuicForUnsupportedVersion) {
-  QuicVersion unsupported_version = QUIC_VERSION_UNSUPPORTED;
+  QuicTransportVersion unsupported_version = QUIC_VERSION_UNSUPPORTED;
   // Add support for another QUIC version besides |version_|. Also find a
   // unsupported version.
-  for (const QuicVersion& version : AllSupportedVersions()) {
+  for (const QuicTransportVersion& version : AllSupportedTransportVersions()) {
     if (version == version_)
       continue;
     if (supported_versions_.size() != 2) {
@@ -1235,7 +1236,7 @@
   // the response from the server will advertise new Alt-Svc with supported
   // versions.
   std::string advertised_versions_list_str =
-      GenerateQuicVersionsListForAltSvcHeader(AllSupportedVersions());
+      GenerateQuicVersionsListForAltSvcHeader(AllSupportedTransportVersions());
   std::string altsvc_header =
       base::StringPrintf("Alt-Svc: quic=\":443\"; v=\"%s\"\r\n\r\n",
                          advertised_versions_list_str.c_str());
@@ -1473,8 +1474,8 @@
 
   // Add support for another QUIC version besides |version_| on the client side.
   // Also find a different version advertised by the server.
-  QuicVersion advertised_version_2 = QUIC_VERSION_UNSUPPORTED;
-  for (const QuicVersion& version : AllSupportedVersions()) {
+  QuicTransportVersion advertised_version_2 = QUIC_VERSION_UNSUPPORTED;
+  for (const QuicTransportVersion& version : AllSupportedTransportVersions()) {
     if (version == version_)
       continue;
     if (supported_versions_.size() != 2) {
@@ -1532,8 +1533,8 @@
   // The QuicStreamFactoy will pick the preferred QUIC_VERSION: |version_|,
   // which is verified as the PacketMakers are using |version_|.
 
-  QuicVersion common_version_2 = QUIC_VERSION_UNSUPPORTED;
-  for (const QuicVersion& version : AllSupportedVersions()) {
+  QuicTransportVersion common_version_2 = QUIC_VERSION_UNSUPPORTED;
+  for (const QuicTransportVersion& version : AllSupportedTransportVersions()) {
     if (version == version_)
       continue;
     common_version_2 = version;
@@ -1695,7 +1696,7 @@
 TEST_P(QuicNetworkTransactionTest,
        StoreMutuallySupportedVersionsWhenProcessAltSvc) {
   // Add support for another QUIC version besides |version_|.
-  for (const QuicVersion& version : AllSupportedVersions()) {
+  for (const QuicTransportVersion& version : AllSupportedTransportVersions()) {
     if (version == version_)
       continue;
     supported_versions_.push_back(version);
@@ -1703,7 +1704,7 @@
   }
 
   std::string advertised_versions_list_str =
-      GenerateQuicVersionsListForAltSvcHeader(AllSupportedVersions());
+      GenerateQuicVersionsListForAltSvcHeader(AllSupportedTransportVersions());
   std::string altsvc_header =
       base::StringPrintf("Alt-Svc: quic=\":443\"; v=\"%s\"\r\n\r\n",
                          advertised_versions_list_str.c_str());
@@ -4846,7 +4847,6 @@
 }
 
 TEST_P(QuicNetworkTransactionTest, QuicForceHolBlocking) {
-  FLAGS_quic_reloadable_flag_quic_use_stream_notifier2 = false;
   session_params_.origins_to_force_quic_on.insert(
       HostPortPair::FromString("mail.example.org:443"));
 
@@ -5066,7 +5066,7 @@
  protected:
   QuicNetworkTransactionWithDestinationTest()
       : version_(GetParam().version),
-        supported_versions_(SupportedVersions(version_)),
+        supported_versions_(SupportedTransportVersions(version_)),
         destination_type_(GetParam().destination_type),
         cert_transparency_verifier_(new MultiLogCTVerifier()),
         ssl_config_service_(new SSLConfigServiceDefaults),
@@ -5270,8 +5270,8 @@
   }
 
   MockClock clock_;
-  QuicVersion version_;
-  QuicVersionVector supported_versions_;
+  QuicTransportVersion version_;
+  QuicTransportVersionVector supported_versions_;
   DestinationType destination_type_;
   std::string origin1_;
   std::string origin2_;
diff --git a/net/quic/chromium/quic_proxy_client_socket_unittest.cc b/net/quic/chromium/quic_proxy_client_socket_unittest.cc
index 621a345..6de97a9 100644
--- a/net/quic/chromium/quic_proxy_client_socket_unittest.cc
+++ b/net/quic/chromium/quic_proxy_client_socket_unittest.cc
@@ -70,7 +70,8 @@
 const QuicStreamId kClientDataStreamId1 = kHeadersStreamId + 2;
 }  // namespace
 
-class QuicProxyClientSocketTest : public ::testing::TestWithParam<QuicVersion> {
+class QuicProxyClientSocketTest
+    : public ::testing::TestWithParam<QuicTransportVersion> {
  protected:
   static const bool kFin = true;
   static const bool kIncludeVersion = true;
@@ -80,7 +81,7 @@
 
   static size_t GetStreamFrameDataLengthFromPacketLength(
       QuicByteCount packet_length,
-      QuicVersion version,
+      QuicTransportVersion version,
       bool include_version,
       bool include_diversification_nonce,
       QuicConnectionIdLength connection_id_length,
@@ -145,8 +146,7 @@
         .WillRepeatedly(Return(kMaxPacketSize));
     EXPECT_CALL(*send_algorithm_, PacingRate(_))
         .WillRepeatedly(Return(QuicBandwidth::Zero()));
-    EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _))
-        .WillRepeatedly(Return(QuicTime::Delta::Zero()));
+    EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true));
     EXPECT_CALL(*send_algorithm_, BandwidthEstimate())
         .WillRepeatedly(Return(QuicBandwidth::Zero()));
     EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)).Times(AnyNumber());
@@ -162,7 +162,7 @@
     QuicConnection* connection = new QuicConnection(
         connection_id_, QuicSocketAddress(QuicSocketAddressImpl(peer_addr_)),
         helper_.get(), alarm_factory_.get(), writer, true /* owns_writer */,
-        Perspective::IS_CLIENT, SupportedVersions(GetParam()));
+        Perspective::IS_CLIENT, SupportedTransportVersions(GetParam()));
     connection->set_visitor(&visitor_);
     QuicConnectionPeer::SetSendAlgorithm(connection, send_algorithm_);
 
@@ -465,7 +465,7 @@
     ASSERT_EQ(SpdyString(data, len), SpdyString(read_buf_->data(), len));
   }
 
-  QuicVersion version_;
+  QuicTransportVersion version_;
 
   // order of destruction of these members matter
   MockClock clock_;
@@ -1484,7 +1484,7 @@
 
 INSTANTIATE_TEST_CASE_P(Version,
                         QuicProxyClientSocketTest,
-                        ::testing::ValuesIn(AllSupportedVersions()));
+                        ::testing::ValuesIn(AllSupportedTransportVersions()));
 
 }  // namespace test
 }  // namespace net
diff --git a/net/quic/chromium/quic_stream_factory.cc b/net/quic/chromium/quic_stream_factory.cc
index 4627cf8..034e8a7 100644
--- a/net/quic/chromium/quic_stream_factory.cc
+++ b/net/quic/chromium/quic_stream_factory.cc
@@ -335,7 +335,7 @@
 class QuicStreamFactory::Job {
  public:
   Job(QuicStreamFactory* factory,
-      const QuicVersion& quic_version,
+      const QuicTransportVersion& quic_version,
       HostResolver* host_resolver,
       const QuicSessionKey& key,
       bool was_alternative_service_recently_broken,
@@ -392,7 +392,7 @@
   bool in_loop_;  // Temporary to investigate crbug.com/750271.
   IoState io_state_;
   QuicStreamFactory* factory_;
-  QuicVersion quic_version_;
+  QuicTransportVersion quic_version_;
   HostResolver* host_resolver_;
   std::unique_ptr<HostResolver::Request> request_;
   const QuicSessionKey key_;
@@ -412,7 +412,7 @@
 };
 
 QuicStreamFactory::Job::Job(QuicStreamFactory* factory,
-                            const QuicVersion& quic_version,
+                            const QuicTransportVersion& quic_version,
                             HostResolver* host_resolver,
                             const QuicSessionKey& key,
                             bool was_alternative_service_recently_broken,
@@ -504,7 +504,7 @@
   if (!session_)
     return;
   details->connection_info = QuicHttpStream::ConnectionInfoFromQuicVersion(
-      session_->connection()->version());
+      session_->connection()->transport_version());
   details->quic_connection_error = session_->error();
 }
 
@@ -621,7 +621,7 @@
 }
 
 int QuicStreamRequest::Request(const HostPortPair& destination,
-                               QuicVersion quic_version,
+                               QuicTransportVersion quic_version,
                                PrivacyMode privacy_mode,
                                int cert_verify_flags,
                                const GURL& url,
@@ -889,7 +889,7 @@
 
 int QuicStreamFactory::Create(const QuicServerId& server_id,
                               const HostPortPair& destination,
-                              QuicVersion quic_version,
+                              QuicTransportVersion quic_version,
                               int cert_verify_flags,
                               const GURL& url,
                               QuicStringPiece method,
@@ -1550,7 +1550,7 @@
 }
 
 int QuicStreamFactory::CreateSession(const QuicSessionKey& key,
-                                     const QuicVersion& quic_version,
+                                     const QuicTransportVersion& quic_version,
                                      int cert_verify_flags,
                                      bool require_confirmation,
                                      const AddressList& address_list,
diff --git a/net/quic/chromium/quic_stream_factory.h b/net/quic/chromium/quic_stream_factory.h
index f96ba54..f7fc299 100644
--- a/net/quic/chromium/quic_stream_factory.h
+++ b/net/quic/chromium/quic_stream_factory.h
@@ -123,7 +123,7 @@
   // |destination| will be resolved and resulting IPEndPoint used to open a
   // QuicConnection.  This can be different than HostPortPair::FromURL(url).
   int Request(const HostPortPair& destination,
-              QuicVersion quic_version,
+              QuicTransportVersion quic_version,
               PrivacyMode privacy_mode,
               int cert_verify_flags,
               const GURL& url,
@@ -243,7 +243,7 @@
   // OnRequestComplete asynchronously.
   int Create(const QuicServerId& server_id,
              const HostPortPair& destination,
-             QuicVersion quic_version,
+             QuicTransportVersion quic_version,
              int cert_verify_flags,
              const GURL& url,
              QuicStringPiece method,
@@ -413,7 +413,7 @@
   bool HasActiveJob(const QuicServerId& server_id) const;
   bool HasActiveCertVerifierJob(const QuicServerId& server_id) const;
   int CreateSession(const QuicSessionKey& key,
-                    const QuicVersion& quic_version,
+                    const QuicTransportVersion& quic_version,
                     int cert_verify_flags,
                     bool require_confirmation,
                     const AddressList& address_list,
diff --git a/net/quic/chromium/quic_stream_factory_test.cc b/net/quic/chromium/quic_stream_factory_test.cc
index fc0d5a8..4cb5e50 100644
--- a/net/quic/chromium/quic_stream_factory_test.cc
+++ b/net/quic/chromium/quic_stream_factory_test.cc
@@ -106,12 +106,13 @@
     return os;
   }
 
-  QuicVersion version;
+  QuicTransportVersion version;
 };
 
 std::vector<TestParams> GetTestParams() {
   std::vector<TestParams> params;
-  QuicVersionVector all_supported_versions = AllSupportedVersions();
+  QuicTransportVersionVector all_supported_versions =
+      AllSupportedTransportVersions();
   for (const auto& version : all_supported_versions)
     params.push_back(TestParams{version});
   return params;
@@ -139,14 +140,15 @@
     return os;
   }
 
-  QuicVersion version;
+  QuicTransportVersion version;
   DestinationType destination_type;
 };
 
 std::vector<PoolingTestParams> GetPoolingTestParams() {
   std::vector<PoolingTestParams> params;
-  QuicVersionVector all_supported_versions = AllSupportedVersions();
-  for (const QuicVersion version : all_supported_versions) {
+  QuicTransportVersionVector all_supported_versions =
+      AllSupportedTransportVersions();
+  for (const QuicTransportVersion version : all_supported_versions) {
     params.push_back(PoolingTestParams{version, SAME_AS_FIRST});
     params.push_back(PoolingTestParams{version, SAME_AS_SECOND});
     params.push_back(PoolingTestParams{version, DIFFERENT});
@@ -166,7 +168,7 @@
 
 class QuicStreamFactoryTestBase {
  protected:
-  explicit QuicStreamFactoryTestBase(QuicVersion version)
+  explicit QuicStreamFactoryTestBase(QuicTransportVersion version)
       : ssl_config_service_(new MockSSLConfigService),
         random_generator_(0),
         runner_(new TestTaskRunner(&clock_)),
@@ -695,7 +697,7 @@
   MockRandom random_generator_;
   MockClock clock_;
   scoped_refptr<TestTaskRunner> runner_;
-  QuicVersion version_;
+  QuicTransportVersion version_;
   QuicTestPacketMaker client_maker_;
   QuicTestPacketMaker server_maker_;
   HttpServerPropertiesImpl http_server_properties_;
diff --git a/net/quic/chromium/quic_test_packet_maker.cc b/net/quic/chromium/quic_test_packet_maker.cc
index d73b55c9..6f960b83 100644
--- a/net/quic/chromium/quic_test_packet_maker.cc
+++ b/net/quic/chromium/quic_test_packet_maker.cc
@@ -15,8 +15,17 @@
 
 namespace net {
 namespace test {
+namespace {
 
-QuicTestPacketMaker::QuicTestPacketMaker(QuicVersion version,
+QuicAckFrame MakeAckFrame(QuicPacketNumber largest_observed) {
+  QuicAckFrame ack;
+  ack.largest_observed = largest_observed;
+  return ack;
+}
+
+}  // namespace
+
+QuicTestPacketMaker::QuicTestPacketMaker(QuicTransportVersion version,
                                          QuicConnectionId connection_id,
                                          MockClock* clock,
                                          const std::string& host,
@@ -129,7 +138,8 @@
   frames.push_back(QuicFrame(&rst));
   DVLOG(1) << "Adding frame: " << frames[2];
 
-  QuicFramer framer(SupportedVersions(version_), clock_->Now(), perspective_);
+  QuicFramer framer(SupportedTransportVersions(version_), clock_->Now(),
+                    perspective_);
   std::unique_ptr<QuicPacket> packet(
       BuildUnsizedDataPacket(&framer, header, frames));
   char buffer[kMaxPacketSize];
@@ -181,7 +191,8 @@
   frames.push_back(QuicFrame(&close));
   DVLOG(1) << "Adding frame: " << frames[2];
 
-  QuicFramer framer(SupportedVersions(version_), clock_->Now(), perspective_);
+  QuicFramer framer(SupportedTransportVersions(version_), clock_->Now(),
+                    perspective_);
   std::unique_ptr<QuicPacket> packet(
       BuildUnsizedDataPacket(&framer, header, frames));
   char buffer[kMaxPacketSize];
@@ -260,7 +271,8 @@
     ack.packets.AddRange(1, largest_received + 1);
   }
 
-  QuicFramer framer(SupportedVersions(version_), clock_->Now(), perspective_);
+  QuicFramer framer(SupportedTransportVersions(version_), clock_->Now(),
+                    perspective_);
   QuicFrames frames;
   QuicFrame ack_frame(&ack);
   DVLOG(1) << "Adding frame: " << ack_frame;
@@ -646,7 +658,8 @@
 std::unique_ptr<QuicReceivedPacket>
 QuicTestPacketMaker::MakeMultipleFramesPacket(const QuicPacketHeader& header,
                                               const QuicFrames& frames) {
-  QuicFramer framer(SupportedVersions(version_), clock_->Now(), perspective_);
+  QuicFramer framer(SupportedTransportVersions(version_), clock_->Now(),
+                    perspective_);
   std::unique_ptr<QuicPacket> packet(
       BuildUnsizedDataPacket(&framer, header, frames));
   char buffer[kMaxPacketSize];
diff --git a/net/quic/chromium/quic_test_packet_maker.h b/net/quic/chromium/quic_test_packet_maker.h
index a25b08ea..c476d82 100644
--- a/net/quic/chromium/quic_test_packet_maker.h
+++ b/net/quic/chromium/quic_test_packet_maker.h
@@ -27,7 +27,7 @@
 
 class QuicTestPacketMaker {
  public:
-  QuicTestPacketMaker(QuicVersion version,
+  QuicTestPacketMaker(QuicTransportVersion version,
                       QuicConnectionId connection_id,
                       MockClock* clock,
                       const std::string& host,
@@ -257,7 +257,7 @@
   void InitializeHeader(QuicPacketNumber packet_number,
                         bool should_include_version);
 
-  QuicVersion version_;
+  QuicTransportVersion version_;
   QuicConnectionId connection_id_;
   MockClock* clock_;  // Owned by QuicStreamFactory.
   std::string host_;
diff --git a/net/quic/core/congestion_control/bbr_sender.cc b/net/quic/core/congestion_control/bbr_sender.cc
index d27e438..e7888ca8 100644
--- a/net/quic/core/congestion_control/bbr_sender.cc
+++ b/net/quic/core/congestion_control/bbr_sender.cc
@@ -142,12 +142,8 @@
                          is_retransmittable);
 }
 
-QuicTime::Delta BbrSender::TimeUntilSend(QuicTime /* now */,
-                                         QuicByteCount bytes_in_flight) {
-  if (bytes_in_flight < GetCongestionWindow()) {
-    return QuicTime::Delta::Zero();
-  }
-  return QuicTime::Delta::Infinite();
+bool BbrSender::CanSend(QuicByteCount bytes_in_flight) {
+  return bytes_in_flight < GetCongestionWindow();
 }
 
 QuicBandwidth BbrSender::PacingRate(QuicByteCount bytes_in_flight) const {
@@ -231,7 +227,7 @@
                                   QuicByteCount prior_in_flight,
                                   QuicTime event_time,
                                   const AckedPacketVector& acked_packets,
-                                  const CongestionVector& lost_packets) {
+                                  const LostPacketVector& lost_packets) {
   const QuicByteCount total_bytes_acked_before = sampler_->total_bytes_acked();
 
   bool is_round_start = false;
@@ -280,7 +276,7 @@
       sampler_->total_bytes_acked() - total_bytes_acked_before;
   QuicByteCount bytes_lost = 0;
   for (const auto& packet : lost_packets) {
-    bytes_lost += packet.second;
+    bytes_lost += packet.bytes_lost;
   }
 
   // After the model is updated, recalculate the pacing rate and congestion
@@ -337,9 +333,9 @@
   pacing_gain_ = kPacingGain[cycle_current_offset_];
 }
 
-void BbrSender::DiscardLostPackets(const CongestionVector& lost_packets) {
-  for (const auto& packet : lost_packets) {
-    sampler_->OnPacketLost(packet.first);
+void BbrSender::DiscardLostPackets(const LostPacketVector& lost_packets) {
+  for (const LostPacket& packet : lost_packets) {
+    sampler_->OnPacketLost(packet.packet_number);
   }
 }
 
diff --git a/net/quic/core/congestion_control/bbr_sender.h b/net/quic/core/congestion_control/bbr_sender.h
index 97860e7..72282fd4 100644
--- a/net/quic/core/congestion_control/bbr_sender.h
+++ b/net/quic/core/congestion_control/bbr_sender.h
@@ -110,7 +110,7 @@
                          QuicByteCount prior_in_flight,
                          QuicTime event_time,
                          const AckedPacketVector& acked_packets,
-                         const CongestionVector& lost_packets) override;
+                         const LostPacketVector& lost_packets) override;
   void OnPacketSent(QuicTime sent_time,
                     QuicByteCount bytes_in_flight,
                     QuicPacketNumber packet_number,
@@ -118,8 +118,7 @@
                     HasRetransmittableData is_retransmittable) override;
   void OnRetransmissionTimeout(bool packets_retransmitted) override {}
   void OnConnectionMigration() override {}
-  QuicTime::Delta TimeUntilSend(QuicTime now,
-                                QuicByteCount bytes_in_flight) override;
+  bool CanSend(QuicByteCount bytes_in_flight) override;
   QuicBandwidth PacingRate(QuicByteCount bytes_in_flight) const override;
   QuicBandwidth BandwidthEstimate() const override;
   QuicByteCount GetCongestionWindow() const override;
@@ -168,7 +167,7 @@
   void EnterProbeBandwidthMode(QuicTime now);
 
   // Discards the lost packets from BandwidthSampler state.
-  void DiscardLostPackets(const CongestionVector& lost_packets);
+  void DiscardLostPackets(const LostPacketVector& lost_packets);
   // Updates the round-trip counter if a round-trip has passed.  Returns true if
   // the counter has been advanced.
   bool UpdateRoundTripCounter(QuicPacketNumber last_acked_packet);
diff --git a/net/quic/core/congestion_control/bbr_sender_test.cc b/net/quic/core/congestion_control/bbr_sender_test.cc
index fd103674..2ca6f1d 100644
--- a/net/quic/core/congestion_control/bbr_sender_test.cc
+++ b/net/quic/core/congestion_control/bbr_sender_test.cc
@@ -258,9 +258,9 @@
   // At startup make sure we are at the default.
   EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
   // At startup make sure we can send.
-  EXPECT_TRUE(sender_->TimeUntilSend(clock_->Now(), 0).IsZero());
+  EXPECT_TRUE(sender_->CanSend(0));
   // Make sure we can send.
-  EXPECT_TRUE(sender_->TimeUntilSend(clock_->Now(), 0).IsZero());
+  EXPECT_TRUE(sender_->CanSend(0));
   // And that window is un-affected.
   EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
 
diff --git a/net/quic/core/congestion_control/cubic.cc b/net/quic/core/congestion_control/cubic.cc
index 4849cf9..37d0aaf 100644
--- a/net/quic/core/congestion_control/cubic.cc
+++ b/net/quic/core/congestion_control/cubic.cc
@@ -9,6 +9,7 @@
 #include <cstdint>
 
 #include "net/quic/core/quic_packets.h"
+#include "net/quic/platform/api/quic_flag_utils.h"
 #include "net/quic/platform/api/quic_flags.h"
 #include "net/quic/platform/api/quic_logging.h"
 
@@ -41,10 +42,13 @@
       epoch_(QuicTime::Zero()),
       app_limited_start_time_(QuicTime::Zero()),
       last_update_time_(QuicTime::Zero()),
-      fix_convex_mode_(false),
-      fix_beta_last_max_(false),
-      allow_per_ack_updates_(false) {
+      fix_convex_mode_(FLAGS_quic_reloadable_flag_quic_enable_cubic_fixes),
+      fix_beta_last_max_(fix_convex_mode_),
+      allow_per_ack_updates_(fix_convex_mode_) {
   ResetCubicState();
+  if (fix_convex_mode_) {
+    QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_enable_cubic_fixes, 1, 2);
+  }
 }
 
 void Cubic::SetNumConnections(int num_connections) {
diff --git a/net/quic/core/congestion_control/cubic_bytes.cc b/net/quic/core/congestion_control/cubic_bytes.cc
index 4d9807f8..33dc0de 100644
--- a/net/quic/core/congestion_control/cubic_bytes.cc
+++ b/net/quic/core/congestion_control/cubic_bytes.cc
@@ -9,6 +9,7 @@
 #include <cstdint>
 
 #include "net/quic/core/quic_packets.h"
+#include "net/quic/platform/api/quic_flag_utils.h"
 #include "net/quic/platform/api/quic_flags.h"
 #include "net/quic/platform/api/quic_logging.h"
 
@@ -41,11 +42,14 @@
       num_connections_(kDefaultNumConnections),
       epoch_(QuicTime::Zero()),
       last_update_time_(QuicTime::Zero()),
-      fix_convex_mode_(false),
-      fix_cubic_quantization_(false),
-      fix_beta_last_max_(false),
-      allow_per_ack_updates_(false) {
+      fix_convex_mode_(FLAGS_quic_reloadable_flag_quic_enable_cubic_fixes),
+      fix_cubic_quantization_(fix_convex_mode_),
+      fix_beta_last_max_(fix_convex_mode_),
+      allow_per_ack_updates_(fix_convex_mode_) {
   ResetCubicState();
+  if (fix_convex_mode_) {
+    QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_enable_cubic_fixes, 2, 2);
+  }
 }
 
 void CubicBytes::SetNumConnections(int num_connections) {
@@ -179,6 +183,7 @@
       ((event_time + delay_min - epoch_).ToMicroseconds() << 10) /
       kNumMicrosPerSecond;
 
+  // TODO(ianswett): Change to uint64_t once fix_convex_mode_ is always enabled.
   int64_t offset = time_to_origin_point_ - elapsed_time;
   if (fix_convex_mode_) {
     // Right-shifts of negative, signed numbers have
diff --git a/net/quic/core/congestion_control/general_loss_algorithm.cc b/net/quic/core/congestion_control/general_loss_algorithm.cc
index f71f0ed5..8833ddf 100644
--- a/net/quic/core/congestion_control/general_loss_algorithm.cc
+++ b/net/quic/core/congestion_control/general_loss_algorithm.cc
@@ -63,7 +63,7 @@
     QuicTime time,
     const RttStats& rtt_stats,
     QuicPacketNumber largest_newly_acked,
-    SendAlgorithmInterface::CongestionVector* packets_lost) {
+    LostPacketVector* packets_lost) {
   loss_detection_timeout_ = QuicTime::Zero();
   QuicTime::Delta max_rtt =
       std::max(rtt_stats.previous_srtt(), rtt_stats.latest_rtt());
@@ -82,7 +82,7 @@
       // FACK based loss detection.
       if (largest_newly_acked - packet_number >=
           kNumberOfNacksBeforeRetransmission) {
-        packets_lost->push_back(std::make_pair(packet_number, it->bytes_sent));
+        packets_lost->push_back(LostPacket(packet_number, it->bytes_sent));
         continue;
       }
     } else if (loss_type_ == kLazyFack) {
@@ -92,7 +92,7 @@
           largest_previously_acked_ > packet_number &&
           largest_previously_acked_ - packet_number >=
               (kNumberOfNacksBeforeRetransmission - 1)) {
-        packets_lost->push_back(std::make_pair(packet_number, it->bytes_sent));
+        packets_lost->push_back(LostPacket(packet_number, it->bytes_sent));
         continue;
       }
     }
@@ -109,14 +109,14 @@
         loss_detection_timeout_ = when_lost;
         break;
       }
-      packets_lost->push_back(std::make_pair(packet_number, it->bytes_sent));
+      packets_lost->push_back(LostPacket(packet_number, it->bytes_sent));
       continue;
     }
 
     // NACK-based loss detection allows for a max reordering window of 1 RTT.
     if (it->sent_time + rtt_stats.smoothed_rtt() <
         unacked_packets.GetTransmissionInfo(largest_newly_acked).sent_time) {
-      packets_lost->push_back(std::make_pair(packet_number, it->bytes_sent));
+      packets_lost->push_back(LostPacket(packet_number, it->bytes_sent));
       continue;
     }
   }
diff --git a/net/quic/core/congestion_control/general_loss_algorithm.h b/net/quic/core/congestion_control/general_loss_algorithm.h
index 281a139..bb46b54 100644
--- a/net/quic/core/congestion_control/general_loss_algorithm.h
+++ b/net/quic/core/congestion_control/general_loss_algorithm.h
@@ -36,12 +36,11 @@
   void SetLossDetectionType(LossDetectionType loss_type);
 
   // Uses |largest_acked| and time to decide when packets are lost.
-  void DetectLosses(
-      const QuicUnackedPacketMap& unacked_packets,
-      QuicTime time,
-      const RttStats& rtt_stats,
-      QuicPacketNumber largest_newly_acked,
-      SendAlgorithmInterface::CongestionVector* packets_lost) override;
+  void DetectLosses(const QuicUnackedPacketMap& unacked_packets,
+                    QuicTime time,
+                    const RttStats& rtt_stats,
+                    QuicPacketNumber largest_newly_acked,
+                    LostPacketVector* packets_lost) override;
 
   // Returns a non-zero value when the early retransmit timer is active.
   QuicTime GetLossTimeout() const override;
diff --git a/net/quic/core/congestion_control/general_loss_algorithm_test.cc b/net/quic/core/congestion_control/general_loss_algorithm_test.cc
index 8716860..7a90f9b 100644
--- a/net/quic/core/congestion_control/general_loss_algorithm_test.cc
+++ b/net/quic/core/congestion_control/general_loss_algorithm_test.cc
@@ -54,12 +54,12 @@
     if (largest_newly_acked > unacked_packets_.largest_observed()) {
       unacked_packets_.IncreaseLargestObserved(largest_newly_acked);
     }
-    SendAlgorithmInterface::CongestionVector lost_packets;
+    LostPacketVector lost_packets;
     loss_algorithm_.DetectLosses(unacked_packets_, clock_.Now(), rtt_stats_,
                                  largest_newly_acked, &lost_packets);
     ASSERT_EQ(losses_expected.size(), lost_packets.size());
     for (size_t i = 0; i < losses_expected.size(); ++i) {
-      EXPECT_EQ(lost_packets[i].first, losses_expected[i]);
+      EXPECT_EQ(lost_packets[i].packet_number, losses_expected[i]);
     }
   }
 
diff --git a/net/quic/core/congestion_control/loss_detection_interface.h b/net/quic/core/congestion_control/loss_detection_interface.h
index 919de77..36f8891 100644
--- a/net/quic/core/congestion_control/loss_detection_interface.h
+++ b/net/quic/core/congestion_control/loss_detection_interface.h
@@ -24,12 +24,11 @@
   virtual LossDetectionType GetLossDetectionType() const = 0;
 
   // Called when a new ack arrives or the loss alarm fires.
-  virtual void DetectLosses(
-      const QuicUnackedPacketMap& unacked_packets,
-      QuicTime time,
-      const RttStats& rtt_stats,
-      QuicPacketNumber largest_newly_acked,
-      SendAlgorithmInterface::CongestionVector* packets_lost) = 0;
+  virtual void DetectLosses(const QuicUnackedPacketMap& unacked_packets,
+                            QuicTime time,
+                            const RttStats& rtt_stats,
+                            QuicPacketNumber largest_newly_acked,
+                            LostPacketVector* packets_lost) = 0;
 
   // Get the time the LossDetectionAlgorithm wants to re-evaluate losses.
   // Returns QuicTime::Zero if no alarm needs to be set.
diff --git a/net/quic/core/congestion_control/pacing_sender.cc b/net/quic/core/congestion_control/pacing_sender.cc
index 321fa7c..f53a3ae 100644
--- a/net/quic/core/congestion_control/pacing_sender.cc
+++ b/net/quic/core/congestion_control/pacing_sender.cc
@@ -25,7 +25,8 @@
       burst_tokens_(kInitialUnpacedBurst),
       last_delayed_packet_sent_time_(QuicTime::Zero()),
       ideal_next_packet_send_time_(QuicTime::Zero()),
-      was_last_send_delayed_(false) {}
+      was_last_send_delayed_(false),
+      initial_burst_size_(kInitialUnpacedBurst) {}
 
 PacingSender::~PacingSender() {}
 
@@ -34,12 +35,11 @@
   sender_ = sender;
 }
 
-void PacingSender::OnCongestionEvent(
-    bool rtt_updated,
-    QuicByteCount bytes_in_flight,
-    QuicTime event_time,
-    const SendAlgorithmInterface::AckedPacketVector& acked_packets,
-    const SendAlgorithmInterface::CongestionVector& lost_packets) {
+void PacingSender::OnCongestionEvent(bool rtt_updated,
+                                     QuicByteCount bytes_in_flight,
+                                     QuicTime event_time,
+                                     const AckedPacketVector& acked_packets,
+                                     const LostPacketVector& lost_packets) {
   DCHECK(sender_ != nullptr);
   if (!lost_packets.empty()) {
     // Clear any burst tokens when entering recovery.
@@ -67,7 +67,7 @@
     // limit it to the equivalent of a single bulk write, not exceeding the
     // current CWND in packets.
     burst_tokens_ = std::min(
-        kInitialUnpacedBurst,
+        initial_burst_size_,
         static_cast<uint32_t>(sender_->GetCongestionWindow() / kDefaultTCPMSS));
   }
   if (burst_tokens_ > 0) {
@@ -110,17 +110,15 @@
 QuicTime::Delta PacingSender::TimeUntilSend(QuicTime now,
                                             QuicByteCount bytes_in_flight) {
   DCHECK(sender_ != nullptr);
-  QuicTime::Delta time_until_send =
-      sender_->TimeUntilSend(now, bytes_in_flight);
-  if (burst_tokens_ > 0 || bytes_in_flight == 0) {
-    // Don't pace if we have burst tokens available or leaving quiescence.
-    return time_until_send;
+
+  if (!sender_->CanSend(bytes_in_flight)) {
+    // The underlying sender prevents sending.
+    return QuicTime::Delta::Infinite();
   }
 
-  if (!time_until_send.IsZero()) {
-    DCHECK(time_until_send.IsInfinite());
-    // The underlying sender prevents sending.
-    return time_until_send;
+  if (burst_tokens_ > 0 || bytes_in_flight == 0) {
+    // Don't pace if we have burst tokens available or leaving quiescence.
+    return QuicTime::Delta::Zero();
   }
 
   // If the next send time is within the alarm granularity, send immediately.
diff --git a/net/quic/core/congestion_control/pacing_sender.h b/net/quic/core/congestion_control/pacing_sender.h
index 02ace9bf95..5b3ee82 100644
--- a/net/quic/core/congestion_control/pacing_sender.h
+++ b/net/quic/core/congestion_control/pacing_sender.h
@@ -25,6 +25,10 @@
 
 namespace net {
 
+namespace test {
+class QuicSentPacketManagerPeer;
+}  // namespace test
+
 class QUIC_EXPORT_PRIVATE PacingSender {
  public:
   PacingSender();
@@ -39,12 +43,11 @@
     max_pacing_rate_ = max_pacing_rate;
   }
 
-  void OnCongestionEvent(
-      bool rtt_updated,
-      QuicByteCount bytes_in_flight,
-      QuicTime event_time,
-      const SendAlgorithmInterface::AckedPacketVector& acked_packets,
-      const SendAlgorithmInterface::CongestionVector& lost_packets);
+  void OnCongestionEvent(bool rtt_updated,
+                         QuicByteCount bytes_in_flight,
+                         QuicTime event_time,
+                         const AckedPacketVector& acked_packets,
+                         const LostPacketVector& lost_packets);
 
   void OnPacketSent(QuicTime sent_time,
                     QuicByteCount bytes_in_flight,
@@ -57,6 +60,8 @@
   QuicBandwidth PacingRate(QuicByteCount bytes_in_flight) const;
 
  private:
+  friend class test::QuicSentPacketManagerPeer;
+
   // Underlying sender. Not owned.
   SendAlgorithmInterface* sender_;
   // If not QuicBandidth::Zero, the maximum rate the PacingSender will use.
@@ -68,6 +73,7 @@
   QuicTime last_delayed_packet_sent_time_;
   QuicTime ideal_next_packet_send_time_;  // When can the next packet be sent.
   bool was_last_send_delayed_;  // True when the last send was delayed.
+  uint32_t initial_burst_size_;
 
   DISALLOW_COPY_AND_ASSIGN(PacingSender);
 };
diff --git a/net/quic/core/congestion_control/pacing_sender_test.cc b/net/quic/core/congestion_control/pacing_sender_test.cc
index a3393552..82b39169 100644
--- a/net/quic/core/congestion_control/pacing_sender_test.cc
+++ b/net/quic/core/congestion_control/pacing_sender_test.cc
@@ -46,9 +46,9 @@
     EXPECT_CALL(*mock_sender_, PacingRate(_)).WillRepeatedly(Return(bandwidth));
     if (burst_size == 0) {
       EXPECT_CALL(*mock_sender_, OnCongestionEvent(_, _, _, _, _));
-      SendAlgorithmInterface::CongestionVector lost_packets;
-      lost_packets.push_back(std::make_pair(1, kMaxPacketSize));
-      SendAlgorithmInterface::AckedPacketVector empty;
+      LostPacketVector lost_packets;
+      lost_packets.push_back(LostPacket(1, kMaxPacketSize));
+      AckedPacketVector empty;
       pacing_sender_->OnCongestionEvent(true, 1234, clock_.Now(), empty,
                                         lost_packets);
     } else if (burst_size != kInitialBurstPackets) {
@@ -64,8 +64,8 @@
     // In order for the packet to be sendable, the underlying sender must
     // permit it to be sent immediately.
     for (int i = 0; i < 2; ++i) {
-      EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(), bytes_in_flight))
-          .WillOnce(Return(zero_time_));
+      EXPECT_CALL(*mock_sender_, CanSend(bytes_in_flight))
+          .WillOnce(Return(true));
       // Verify that the packet can be sent immediately.
       EXPECT_EQ(zero_time_,
                 pacing_sender_->TimeUntilSend(clock_.Now(), bytes_in_flight));
@@ -92,8 +92,8 @@
     // In order for the packet to be sendable, the underlying sender must
     // permit it to be sent immediately.
     for (int i = 0; i < 2; ++i) {
-      EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(), kBytesInFlight))
-          .WillOnce(Return(zero_time_));
+      EXPECT_CALL(*mock_sender_, CanSend(kBytesInFlight))
+          .WillOnce(Return(true));
       // Verify that the packet is delayed.
       EXPECT_EQ(delay.ToMicroseconds(),
                 pacing_sender_->TimeUntilSend(clock_.Now(), kBytesInFlight)
@@ -104,8 +104,8 @@
   void UpdateRtt() {
     EXPECT_CALL(*mock_sender_,
                 OnCongestionEvent(true, kBytesInFlight, _, _, _));
-    SendAlgorithmInterface::AckedPacketVector empty_acked;
-    SendAlgorithmInterface::CongestionVector empty_lost;
+    AckedPacketVector empty_acked;
+    LostPacketVector empty_lost;
     pacing_sender_->OnCongestionEvent(true, kBytesInFlight, clock_.Now(),
                                       empty_acked, empty_lost);
   }
@@ -120,8 +120,7 @@
 
 TEST_F(PacingSenderTest, NoSend) {
   for (int i = 0; i < 2; ++i) {
-    EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(), kBytesInFlight))
-        .WillOnce(Return(infinite_time_));
+    EXPECT_CALL(*mock_sender_, CanSend(kBytesInFlight)).WillOnce(Return(false));
     EXPECT_EQ(infinite_time_,
               pacing_sender_->TimeUntilSend(clock_.Now(), kBytesInFlight));
   }
@@ -129,8 +128,7 @@
 
 TEST_F(PacingSenderTest, SendNow) {
   for (int i = 0; i < 2; ++i) {
-    EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(), kBytesInFlight))
-        .WillOnce(Return(zero_time_));
+    EXPECT_CALL(*mock_sender_, CanSend(kBytesInFlight)).WillOnce(Return(true));
     EXPECT_EQ(zero_time_,
               pacing_sender_->TimeUntilSend(clock_.Now(), kBytesInFlight));
   }
@@ -320,18 +318,17 @@
   CheckPacketIsSentImmediately();
 
   // Losing a packet will set clear burst tokens.
-  SendAlgorithmInterface::CongestionVector lost_packets;
-  lost_packets.push_back(std::make_pair(1, kMaxPacketSize));
-  SendAlgorithmInterface::AckedPacketVector empty_acked;
-  EXPECT_CALL(*mock_sender_, OnCongestionEvent(true, kMaxPacketSize, _,
-                                               IsEmpty(), lost_packets));
+  LostPacketVector lost_packets;
+  lost_packets.push_back(LostPacket(1, kMaxPacketSize));
+  AckedPacketVector empty_acked;
+  EXPECT_CALL(*mock_sender_,
+              OnCongestionEvent(true, kMaxPacketSize, _, IsEmpty(), _));
   pacing_sender_->OnCongestionEvent(true, kMaxPacketSize, clock_.Now(),
                                     empty_acked, lost_packets);
   // One packet is sent immediately, because of 1ms pacing granularity.
   CheckPacketIsSentImmediately();
   // Ensure packets are immediately paced.
-  EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(), kDefaultTCPMSS))
-      .WillOnce(Return(zero_time_));
+  EXPECT_CALL(*mock_sender_, CanSend(kDefaultTCPMSS)).WillOnce(Return(true));
   // Verify the next packet is paced and delayed 2ms due to granularity.
   EXPECT_EQ(QuicTime::Delta::FromMilliseconds(2),
             pacing_sender_->TimeUntilSend(clock_.Now(), kDefaultTCPMSS));
diff --git a/net/quic/core/congestion_control/prr_sender.cc b/net/quic/core/congestion_control/prr_sender.cc
index d834a212..541f635e 100644
--- a/net/quic/core/congestion_control/prr_sender.cc
+++ b/net/quic/core/congestion_control/prr_sender.cc
@@ -35,13 +35,12 @@
   ++ack_count_since_loss_;
 }
 
-QuicTime::Delta PrrSender::TimeUntilSend(
-    QuicByteCount congestion_window,
-    QuicByteCount bytes_in_flight,
-    QuicByteCount slowstart_threshold) const {
+bool PrrSender::CanSend(QuicByteCount congestion_window,
+                        QuicByteCount bytes_in_flight,
+                        QuicByteCount slowstart_threshold) const {
   // Return QuicTime::Zero in order to ensure limited transmit always works.
   if (bytes_sent_since_loss_ == 0 || bytes_in_flight < kMaxSegmentSize) {
-    return QuicTime::Delta::Zero();
+    return true;
   }
   if (congestion_window > bytes_in_flight) {
     // During PRR-SSRB, limit outgoing packets to 1 extra MSS per ack, instead
@@ -50,9 +49,9 @@
     //   limit = MAX(prr_delivered - prr_out, DeliveredData) + MSS
     if (bytes_delivered_since_loss_ + ack_count_since_loss_ * kMaxSegmentSize <=
         bytes_sent_since_loss_) {
-      return QuicTime::Delta::Infinite();
+      return false;
     }
-    return QuicTime::Delta::Zero();
+    return true;
   }
   // Implement Proportional Rate Reduction (RFC6937).
   // Checks a simplified version of the PRR formula that doesn't use division:
@@ -60,9 +59,9 @@
   //   CEIL(prr_delivered * ssthresh / BytesInFlightAtLoss) - prr_sent
   if (bytes_delivered_since_loss_ * slowstart_threshold >
       bytes_sent_since_loss_ * bytes_in_flight_before_loss_) {
-    return QuicTime::Delta::Zero();
+    return true;
   }
-  return QuicTime::Delta::Infinite();
+  return false;
 }
 
 }  // namespace net
diff --git a/net/quic/core/congestion_control/prr_sender.h b/net/quic/core/congestion_control/prr_sender.h
index 2bc842a..a3cc013b 100644
--- a/net/quic/core/congestion_control/prr_sender.h
+++ b/net/quic/core/congestion_control/prr_sender.h
@@ -22,9 +22,9 @@
   void OnPacketLost(QuicByteCount prior_in_flight);
   void OnPacketSent(QuicByteCount sent_bytes);
   void OnPacketAcked(QuicByteCount acked_bytes);
-  QuicTime::Delta TimeUntilSend(QuicByteCount congestion_window,
-                                QuicByteCount bytes_in_flight,
-                                QuicByteCount slowstart_threshold) const;
+  bool CanSend(QuicByteCount congestion_window,
+               QuicByteCount bytes_in_flight,
+               QuicByteCount slowstart_threshold) const;
 
  private:
   // Bytes sent and acked since the last loss event.
diff --git a/net/quic/core/congestion_control/prr_sender_test.cc b/net/quic/core/congestion_control/prr_sender_test.cc
index 94e78738..3f7c187a 100644
--- a/net/quic/core/congestion_control/prr_sender_test.cc
+++ b/net/quic/core/congestion_control/prr_sender_test.cc
@@ -31,15 +31,13 @@
   // Ack a packet. PRR allows one packet to leave immediately.
   prr.OnPacketAcked(kMaxSegmentSize);
   bytes_in_flight -= kMaxSegmentSize;
-  EXPECT_EQ(QuicTime::Delta::Zero(),
-            prr.TimeUntilSend(congestion_window, bytes_in_flight,
-                              ssthresh_after_loss * kMaxSegmentSize));
+  EXPECT_TRUE(prr.CanSend(congestion_window, bytes_in_flight,
+                          ssthresh_after_loss * kMaxSegmentSize));
   // Send retransmission.
   prr.OnPacketSent(kMaxSegmentSize);
   // PRR shouldn't allow sending any more packets.
-  EXPECT_EQ(QuicTime::Delta::Infinite(),
-            prr.TimeUntilSend(congestion_window, bytes_in_flight,
-                              ssthresh_after_loss * kMaxSegmentSize));
+  EXPECT_FALSE(prr.CanSend(congestion_window, bytes_in_flight,
+                           ssthresh_after_loss * kMaxSegmentSize));
 
   // One packet is lost, and one ack was consumed above. PRR now paces
   // transmissions through the remaining 48 acks. PRR will alternatively
@@ -48,15 +46,13 @@
     // Ack a packet. PRR shouldn't allow sending a packet in response.
     prr.OnPacketAcked(kMaxSegmentSize);
     bytes_in_flight -= kMaxSegmentSize;
-    EXPECT_EQ(QuicTime::Delta::Infinite(),
-              prr.TimeUntilSend(congestion_window, bytes_in_flight,
-                                ssthresh_after_loss * kMaxSegmentSize));
+    EXPECT_FALSE(prr.CanSend(congestion_window, bytes_in_flight,
+                             ssthresh_after_loss * kMaxSegmentSize));
     // Ack another packet. PRR should now allow sending a packet in response.
     prr.OnPacketAcked(kMaxSegmentSize);
     bytes_in_flight -= kMaxSegmentSize;
-    EXPECT_EQ(QuicTime::Delta::Zero(),
-              prr.TimeUntilSend(congestion_window, bytes_in_flight,
-                                ssthresh_after_loss * kMaxSegmentSize));
+    EXPECT_TRUE(prr.CanSend(congestion_window, bytes_in_flight,
+                            ssthresh_after_loss * kMaxSegmentSize));
     // Send a packet in response.
     prr.OnPacketSent(kMaxSegmentSize);
     bytes_in_flight += kMaxSegmentSize;
@@ -69,9 +65,8 @@
     // Ack a packet.
     prr.OnPacketAcked(kMaxSegmentSize);
     bytes_in_flight -= kMaxSegmentSize;
-    EXPECT_EQ(QuicTime::Delta::Zero(),
-              prr.TimeUntilSend(congestion_window, bytes_in_flight,
-                                ssthresh_after_loss * kMaxSegmentSize));
+    EXPECT_TRUE(prr.CanSend(congestion_window, bytes_in_flight,
+                            ssthresh_after_loss * kMaxSegmentSize));
     // Send a packet in response, since PRR allows it.
     prr.OnPacketSent(kMaxSegmentSize);
     bytes_in_flight += kMaxSegmentSize;
@@ -79,9 +74,8 @@
     // Since bytes_in_flight is equal to the congestion_window,
     // PRR disallows sending.
     EXPECT_EQ(congestion_window, bytes_in_flight);
-    EXPECT_EQ(QuicTime::Delta::Infinite(),
-              prr.TimeUntilSend(congestion_window, bytes_in_flight,
-                                ssthresh_after_loss * kMaxSegmentSize));
+    EXPECT_FALSE(prr.CanSend(congestion_window, bytes_in_flight,
+                             ssthresh_after_loss * kMaxSegmentSize));
   }
 }
 
@@ -102,26 +96,23 @@
     bytes_in_flight -= kMaxSegmentSize;
     // PRR-SSRB should allow two packets to be sent.
     for (int j = 0; j < 2; ++j) {
-      EXPECT_EQ(QuicTime::Delta::Zero(),
-                prr.TimeUntilSend(congestion_window, bytes_in_flight,
-                                  ssthresh_after_loss * kMaxSegmentSize));
+      EXPECT_TRUE(prr.CanSend(congestion_window, bytes_in_flight,
+                              ssthresh_after_loss * kMaxSegmentSize));
       // Send a packet in response.
       prr.OnPacketSent(kMaxSegmentSize);
       bytes_in_flight += kMaxSegmentSize;
     }
     // PRR should allow no more than 2 packets in response to an ack.
-    EXPECT_EQ(QuicTime::Delta::Infinite(),
-              prr.TimeUntilSend(congestion_window, bytes_in_flight,
-                                ssthresh_after_loss * kMaxSegmentSize));
+    EXPECT_FALSE(prr.CanSend(congestion_window, bytes_in_flight,
+                             ssthresh_after_loss * kMaxSegmentSize));
   }
 
   // Out of SSRB mode, PRR allows one send in response to each ack.
   for (int i = 0; i < 10; ++i) {
     prr.OnPacketAcked(kMaxSegmentSize);
     bytes_in_flight -= kMaxSegmentSize;
-    EXPECT_EQ(QuicTime::Delta::Zero(),
-              prr.TimeUntilSend(congestion_window, bytes_in_flight,
-                                ssthresh_after_loss * kMaxSegmentSize));
+    EXPECT_TRUE(prr.CanSend(congestion_window, bytes_in_flight,
+                            ssthresh_after_loss * kMaxSegmentSize));
     // Send a packet in response.
     prr.OnPacketSent(kMaxSegmentSize);
     bytes_in_flight += kMaxSegmentSize;
diff --git a/net/quic/core/congestion_control/send_algorithm_interface.h b/net/quic/core/congestion_control/send_algorithm_interface.h
index b147a73..e5c2f3f 100644
--- a/net/quic/core/congestion_control/send_algorithm_interface.h
+++ b/net/quic/core/congestion_control/send_algorithm_interface.h
@@ -16,6 +16,7 @@
 #include "net/quic/core/quic_connection_stats.h"
 #include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_time.h"
+#include "net/quic/core/quic_types.h"
 #include "net/quic/core/quic_unacked_packet_map.h"
 #include "net/quic/platform/api/quic_clock.h"
 #include "net/quic/platform/api/quic_export.h"
@@ -29,30 +30,6 @@
 
 class QUIC_EXPORT_PRIVATE SendAlgorithmInterface {
  public:
-  struct AckedPacket {
-    AckedPacket(QuicPacketNumber packet_number,
-                QuicPacketLength bytes_acked,
-                QuicTime receive_timestamp)
-        : packet_number(packet_number),
-          bytes_acked(bytes_acked),
-          receive_timestamp(receive_timestamp) {}
-
-    QuicPacketNumber packet_number;
-    // Number of bytes sent in the packet that was acknowledged.
-    QuicPacketLength bytes_acked;
-    // The time |packet_number| was received by the peer, according to the
-    // optional timestamp the peer included in the ACK frame which acknowledged
-    // |packet_number|. Zero if no timestamp was available for this packet.
-    QuicTime receive_timestamp;
-  };
-
-  // A vector of acked packets.
-  typedef std::vector<AckedPacket> AckedPacketVector;
-
-  // A sorted vector of packets.
-  typedef std::vector<std::pair<QuicPacketNumber, QuicPacketLength>>
-      CongestionVector;
-
   static SendAlgorithmInterface* Create(
       const QuicClock* clock,
       const RttStats* rtt_stats,
@@ -80,7 +57,7 @@
                                  QuicByteCount prior_in_flight,
                                  QuicTime event_time,
                                  const AckedPacketVector& acked_packets,
-                                 const CongestionVector& lost_packets) = 0;
+                                 const LostPacketVector& lost_packets) = 0;
 
   // Inform that we sent |bytes| to the wire, and if the packet is
   // retransmittable.  |bytes_in_flight| is the number of bytes in flight before
@@ -99,9 +76,9 @@
   // Called when connection migrates and cwnd needs to be reset.
   virtual void OnConnectionMigration() = 0;
 
-  // Calculate the time until we can send the next packet.
-  virtual QuicTime::Delta TimeUntilSend(QuicTime now,
-                                        QuicByteCount bytes_in_flight) = 0;
+  // Make decision on whether the sender can send right now.  Note that even
+  // when this method returns true, the sending can be delayed due to pacing.
+  virtual bool CanSend(QuicByteCount bytes_in_flight) = 0;
 
   // The pacing rate of the send algorithm.  May be zero if the rate is unknown.
   virtual QuicBandwidth PacingRate(QuicByteCount bytes_in_flight) const = 0;
diff --git a/net/quic/core/congestion_control/tcp_cubic_sender_base.cc b/net/quic/core/congestion_control/tcp_cubic_sender_base.cc
index 2a9d694..f76b0ef 100644
--- a/net/quic/core/congestion_control/tcp_cubic_sender_base.cc
+++ b/net/quic/core/congestion_control/tcp_cubic_sender_base.cc
@@ -114,18 +114,18 @@
     QuicByteCount prior_in_flight,
     QuicTime event_time,
     const AckedPacketVector& acked_packets,
-    const CongestionVector& lost_packets) {
+    const LostPacketVector& lost_packets) {
   if (rtt_updated && InSlowStart() &&
       hybrid_slow_start_.ShouldExitSlowStart(
           rtt_stats_->latest_rtt(), rtt_stats_->min_rtt(),
           GetCongestionWindow() / kDefaultTCPMSS)) {
     ExitSlowstart();
   }
-  for (CongestionVector::const_iterator it = lost_packets.begin();
-       it != lost_packets.end(); ++it) {
-    OnPacketLost(it->first, it->second, prior_in_flight);
+  for (const LostPacket& lost_packet : lost_packets) {
+    OnPacketLost(lost_packet.packet_number, lost_packet.bytes_lost,
+                 prior_in_flight);
   }
-  for (const SendAlgorithmInterface::AckedPacket acked_packet : acked_packets) {
+  for (const AckedPacket acked_packet : acked_packets) {
     OnPacketAcked(acked_packet.packet_number, acked_packet.bytes_acked,
                   prior_in_flight, event_time);
   }
@@ -173,21 +173,19 @@
   hybrid_slow_start_.OnPacketSent(packet_number);
 }
 
-QuicTime::Delta TcpCubicSenderBase::TimeUntilSend(
-    QuicTime /* now */,
-    QuicByteCount bytes_in_flight) {
+bool TcpCubicSenderBase::CanSend(QuicByteCount bytes_in_flight) {
   if (!no_prr_ && InRecovery()) {
     // PRR is used when in recovery.
-    return prr_.TimeUntilSend(GetCongestionWindow(), bytes_in_flight,
-                              GetSlowStartThreshold());
+    return prr_.CanSend(GetCongestionWindow(), bytes_in_flight,
+                        GetSlowStartThreshold());
   }
   if (GetCongestionWindow() > bytes_in_flight) {
-    return QuicTime::Delta::Zero();
+    return true;
   }
   if (min4_mode_ && bytes_in_flight < 4 * kDefaultTCPMSS) {
-    return QuicTime::Delta::Zero();
+    return true;
   }
-  return QuicTime::Delta::Infinite();
+  return false;
 }
 
 QuicBandwidth TcpCubicSenderBase::PacingRate(
diff --git a/net/quic/core/congestion_control/tcp_cubic_sender_base.h b/net/quic/core/congestion_control/tcp_cubic_sender_base.h
index 12c3d05..f31fa1d 100644
--- a/net/quic/core/congestion_control/tcp_cubic_sender_base.h
+++ b/net/quic/core/congestion_control/tcp_cubic_sender_base.h
@@ -52,7 +52,7 @@
                          QuicByteCount prior_in_flight,
                          QuicTime event_time,
                          const AckedPacketVector& acked_packets,
-                         const CongestionVector& lost_packets) override;
+                         const LostPacketVector& lost_packets) override;
   void OnPacketSent(QuicTime sent_time,
                     QuicByteCount bytes_in_flight,
                     QuicPacketNumber packet_number,
@@ -60,8 +60,7 @@
                     HasRetransmittableData is_retransmittable) override;
   void OnRetransmissionTimeout(bool packets_retransmitted) override;
   void OnConnectionMigration() override;
-  QuicTime::Delta TimeUntilSend(QuicTime now,
-                                QuicByteCount bytes_in_flight) override;
+  bool CanSend(QuicByteCount bytes_in_flight) override;
   QuicBandwidth PacingRate(QuicByteCount bytes_in_flight) const override;
   QuicBandwidth BandwidthEstimate() const override;
   bool InSlowStart() const override;
diff --git a/net/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc b/net/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc
index 2f4314c4..1cd69ab 100644
--- a/net/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc
+++ b/net/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc
@@ -67,15 +67,13 @@
   int SendAvailableSendWindow(QuicPacketLength packet_length) {
     // Send as long as TimeUntilSend returns Zero.
     int packets_sent = 0;
-    bool can_send =
-        sender_->TimeUntilSend(clock_.Now(), bytes_in_flight_).IsZero();
+    bool can_send = sender_->CanSend(bytes_in_flight_);
     while (can_send) {
       sender_->OnPacketSent(clock_.Now(), bytes_in_flight_, packet_number_++,
                             kDefaultTCPMSS, HAS_RETRANSMITTABLE_DATA);
       ++packets_sent;
       bytes_in_flight_ += kDefaultTCPMSS;
-      can_send =
-          sender_->TimeUntilSend(clock_.Now(), bytes_in_flight_).IsZero();
+      can_send = sender_->CanSend(bytes_in_flight_);
     }
     return packets_sent;
   }
@@ -84,12 +82,12 @@
   void AckNPackets(int n) {
     sender_->rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(60),
                                   QuicTime::Delta::Zero(), clock_.Now());
-    SendAlgorithmInterface::AckedPacketVector acked_packets;
-    SendAlgorithmInterface::CongestionVector lost_packets;
+    AckedPacketVector acked_packets;
+    LostPacketVector lost_packets;
     for (int i = 0; i < n; ++i) {
       ++acked_packet_number_;
-      acked_packets.push_back(SendAlgorithmInterface::AckedPacket(
-          acked_packet_number_, kDefaultTCPMSS, QuicTime::Zero()));
+      acked_packets.push_back(
+          AckedPacket(acked_packet_number_, kDefaultTCPMSS, QuicTime::Zero()));
     }
     sender_->OnCongestionEvent(true, bytes_in_flight_, clock_.Now(),
                                acked_packets, lost_packets);
@@ -100,12 +98,11 @@
   void LoseNPackets(int n) { LoseNPackets(n, kDefaultTCPMSS); }
 
   void LoseNPackets(int n, QuicPacketLength packet_length) {
-    SendAlgorithmInterface::AckedPacketVector acked_packets;
-    SendAlgorithmInterface::CongestionVector lost_packets;
+    AckedPacketVector acked_packets;
+    LostPacketVector lost_packets;
     for (int i = 0; i < n; ++i) {
       ++acked_packet_number_;
-      lost_packets.push_back(
-          std::make_pair(acked_packet_number_, packet_length));
+      lost_packets.push_back(LostPacket(acked_packet_number_, packet_length));
     }
     sender_->OnCongestionEvent(false, bytes_in_flight_, clock_.Now(),
                                acked_packets, lost_packets);
@@ -114,9 +111,9 @@
 
   // Does not increment acked_packet_number_.
   void LosePacket(QuicPacketNumber packet_number) {
-    SendAlgorithmInterface::AckedPacketVector acked_packets;
-    SendAlgorithmInterface::CongestionVector lost_packets;
-    lost_packets.push_back(std::make_pair(packet_number, kDefaultTCPMSS));
+    AckedPacketVector acked_packets;
+    LostPacketVector lost_packets;
+    lost_packets.push_back(LostPacket(packet_number, kDefaultTCPMSS));
     sender_->OnCongestionEvent(false, bytes_in_flight_, clock_.Now(),
                                acked_packets, lost_packets);
     bytes_in_flight_ -= kDefaultTCPMSS;
@@ -134,26 +131,24 @@
   // At startup make sure we are at the default.
   EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
   // At startup make sure we can send.
-  EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0).IsZero());
+  EXPECT_TRUE(sender_->CanSend(0));
   // Make sure we can send.
-  EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0).IsZero());
+  EXPECT_TRUE(sender_->CanSend(0));
   // And that window is un-affected.
   EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
 
   // Fill the send window with data, then verify that we can't send.
   SendAvailableSendWindow();
-  EXPECT_FALSE(
-      sender_->TimeUntilSend(clock_.Now(), sender_->GetCongestionWindow())
-          .IsZero());
+  EXPECT_FALSE(sender_->CanSend(sender_->GetCongestionWindow()));
 }
 
 TEST_F(TcpCubicSenderBytesTest, ApplicationLimitedSlowStart) {
   // Send exactly 10 packets and ensure the CWND ends at 14 packets.
   const int kNumberOfAcks = 5;
   // At startup make sure we can send.
-  EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0).IsZero());
+  EXPECT_TRUE(sender_->CanSend(0));
   // Make sure we can send.
-  EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0).IsZero());
+  EXPECT_TRUE(sender_->CanSend(0));
 
   SendAvailableSendWindow();
   for (int i = 0; i < kNumberOfAcks; ++i) {
@@ -168,10 +163,10 @@
 TEST_F(TcpCubicSenderBytesTest, ExponentialSlowStart) {
   const int kNumberOfAcks = 20;
   // At startup make sure we can send.
-  EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0).IsZero());
+  EXPECT_TRUE(sender_->CanSend(0));
   EXPECT_EQ(QuicBandwidth::Zero(), sender_->BandwidthEstimate());
   // Make sure we can send.
-  EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0).IsZero());
+  EXPECT_TRUE(sender_->CanSend(0));
 
   for (int i = 0; i < kNumberOfAcks; ++i) {
     // Send our full send window.
@@ -367,7 +362,7 @@
   // Simulate abandoning all packets by supplying a bytes_in_flight of 0.
   // PRR should now allow a packet to be sent, even though prr's state variables
   // believe it has sent enough packets.
-  EXPECT_EQ(QuicTime::Delta::Zero(), sender_->TimeUntilSend(clock_.Now(), 0));
+  EXPECT_TRUE(sender_->CanSend(0));
 }
 
 TEST_F(TcpCubicSenderBytesTest, SlowStartPacketLossPRR) {
@@ -444,7 +439,7 @@
   LoseNPackets(num_packets_to_lose);
   // Immediately after the loss, ensure at least one packet can be sent.
   // Losses without subsequent acks can occur with timer based loss detection.
-  EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), bytes_in_flight_).IsZero());
+  EXPECT_TRUE(sender_->CanSend(bytes_in_flight_));
   AckNPackets(1);
 
   // We should now have fallen out of slow start with a reduced window.
@@ -699,14 +694,10 @@
   sender_->SetFromConfig(config, Perspective::IS_SERVER);
   sender_->OnRetransmissionTimeout(true);
   EXPECT_EQ(kDefaultTCPMSS, sender_->GetCongestionWindow());
-  EXPECT_TRUE(
-      sender_->TimeUntilSend(QuicTime::Zero(), kDefaultTCPMSS).IsZero());
-  EXPECT_TRUE(
-      sender_->TimeUntilSend(QuicTime::Zero(), 2 * kDefaultTCPMSS).IsZero());
-  EXPECT_TRUE(
-      sender_->TimeUntilSend(QuicTime::Zero(), 3 * kDefaultTCPMSS).IsZero());
-  EXPECT_FALSE(
-      sender_->TimeUntilSend(QuicTime::Zero(), 4 * kDefaultTCPMSS).IsZero());
+  EXPECT_TRUE(sender_->CanSend(kDefaultTCPMSS));
+  EXPECT_TRUE(sender_->CanSend(2 * kDefaultTCPMSS));
+  EXPECT_TRUE(sender_->CanSend(3 * kDefaultTCPMSS));
+  EXPECT_FALSE(sender_->CanSend(4 * kDefaultTCPMSS));
 }
 
 TEST_F(TcpCubicSenderBytesTest, NoPRR) {
@@ -777,12 +768,11 @@
       &clock_, &rtt_stats, /*unacked_packets=*/nullptr, kCubicBytes,
       QuicRandom::GetInstance(), &stats, kInitialCongestionWindow));
 
-  SendAlgorithmInterface::AckedPacketVector acked_packets;
-  SendAlgorithmInterface::CongestionVector missing_packets;
+  AckedPacketVector acked_packets;
+  LostPacketVector missing_packets;
   for (uint64_t i = 1; i < kDefaultMaxCongestionWindowPackets; ++i) {
     acked_packets.clear();
-    acked_packets.push_back(
-        SendAlgorithmInterface::AckedPacket(i, 1350, QuicTime::Zero()));
+    acked_packets.push_back(AckedPacket(i, 1350, QuicTime::Zero()));
     sender->OnCongestionEvent(true, sender->GetCongestionWindow(), clock_.Now(),
                               acked_packets, missing_packets);
   }
@@ -815,7 +805,13 @@
     AckNPackets(1);
     SendAvailableSendWindow();
   }
-  EXPECT_EQ(bytes_in_flight_, sender_->GetCongestionWindow());
+  if (FLAGS_quic_reloadable_flag_quic_enable_cubic_fixes) {
+    // Bytes in flight may be larger than the CWND if the CWND isn't an exact
+    // multiple of the packet sizes being sent.
+    EXPECT_GE(bytes_in_flight_, sender_->GetCongestionWindow());
+  } else {
+    EXPECT_EQ(bytes_in_flight_, sender_->GetCongestionWindow());
+  }
   saved_cwnd = sender_->GetCongestionWindow();
 
   // Advance time 2 seconds waiting for an ack.
diff --git a/net/quic/core/congestion_control/tcp_cubic_sender_packets_test.cc b/net/quic/core/congestion_control/tcp_cubic_sender_packets_test.cc
index 8246c074..6da0c20d 100644
--- a/net/quic/core/congestion_control/tcp_cubic_sender_packets_test.cc
+++ b/net/quic/core/congestion_control/tcp_cubic_sender_packets_test.cc
@@ -74,17 +74,15 @@
   }
 
   int SendAvailableSendWindow(QuicPacketLength packet_length) {
-    // Send as long as TimeUntilSend returns Zero.
+    // Send as long as CanSend returns Zero.
     int packets_sent = 0;
-    bool can_send =
-        sender_->TimeUntilSend(clock_.Now(), bytes_in_flight_).IsZero();
+    bool can_send = sender_->CanSend(bytes_in_flight_);
     while (can_send) {
       sender_->OnPacketSent(clock_.Now(), bytes_in_flight_, packet_number_++,
                             kDefaultTCPMSS, HAS_RETRANSMITTABLE_DATA);
       ++packets_sent;
       bytes_in_flight_ += kDefaultTCPMSS;
-      can_send =
-          sender_->TimeUntilSend(clock_.Now(), bytes_in_flight_).IsZero();
+      can_send = sender_->CanSend(bytes_in_flight_);
     }
     return packets_sent;
   }
@@ -93,12 +91,12 @@
   void AckNPackets(int n) {
     sender_->rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(60),
                                   QuicTime::Delta::Zero(), clock_.Now());
-    SendAlgorithmInterface::AckedPacketVector acked_packets;
-    SendAlgorithmInterface::CongestionVector lost_packets;
+    AckedPacketVector acked_packets;
+    LostPacketVector lost_packets;
     for (int i = 0; i < n; ++i) {
       ++acked_packet_number_;
-      acked_packets.push_back(SendAlgorithmInterface::AckedPacket(
-          acked_packet_number_, kDefaultTCPMSS, QuicTime::Zero()));
+      acked_packets.push_back(
+          AckedPacket(acked_packet_number_, kDefaultTCPMSS, QuicTime::Zero()));
     }
     sender_->OnCongestionEvent(true, bytes_in_flight_, clock_.Now(),
                                acked_packets, lost_packets);
@@ -109,12 +107,11 @@
   void LoseNPackets(int n) { LoseNPackets(n, kDefaultTCPMSS); }
 
   void LoseNPackets(int n, QuicPacketLength packet_length) {
-    SendAlgorithmInterface::AckedPacketVector acked_packets;
-    SendAlgorithmInterface::CongestionVector lost_packets;
+    AckedPacketVector acked_packets;
+    LostPacketVector lost_packets;
     for (int i = 0; i < n; ++i) {
       ++acked_packet_number_;
-      lost_packets.push_back(
-          std::make_pair(acked_packet_number_, packet_length));
+      lost_packets.push_back(LostPacket(acked_packet_number_, packet_length));
     }
     sender_->OnCongestionEvent(false, bytes_in_flight_, clock_.Now(),
                                acked_packets, lost_packets);
@@ -123,9 +120,9 @@
 
   // Does not increment acked_packet_number_.
   void LosePacket(QuicPacketNumber packet_number) {
-    SendAlgorithmInterface::AckedPacketVector acked_packets;
-    SendAlgorithmInterface::CongestionVector lost_packets;
-    lost_packets.push_back(std::make_pair(packet_number, kDefaultTCPMSS));
+    AckedPacketVector acked_packets;
+    LostPacketVector lost_packets;
+    lost_packets.push_back(LostPacket(packet_number, kDefaultTCPMSS));
     sender_->OnCongestionEvent(false, bytes_in_flight_, clock_.Now(),
                                acked_packets, lost_packets);
     bytes_in_flight_ -= kDefaultTCPMSS;
@@ -143,26 +140,24 @@
   // At startup make sure we are at the default.
   EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
   // At startup make sure we can send.
-  EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0).IsZero());
+  EXPECT_TRUE(sender_->CanSend(0));
   // Make sure we can send.
-  EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0).IsZero());
+  EXPECT_TRUE(sender_->CanSend(0));
   // And that window is un-affected.
   EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
 
   // Fill the send window with data, then verify that we can't send.
   SendAvailableSendWindow();
-  EXPECT_FALSE(
-      sender_->TimeUntilSend(clock_.Now(), sender_->GetCongestionWindow())
-          .IsZero());
+  EXPECT_FALSE(sender_->CanSend(sender_->GetCongestionWindow()));
 }
 
 TEST_F(TcpCubicSenderPacketsTest, ApplicationLimitedSlowStart) {
   // Send exactly 10 packets and ensure the CWND ends at 14 packets.
   const int kNumberOfAcks = 5;
   // At startup make sure we can send.
-  EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0).IsZero());
+  EXPECT_TRUE(sender_->CanSend(0));
   // Make sure we can send.
-  EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0).IsZero());
+  EXPECT_TRUE(sender_->CanSend(0));
 
   SendAvailableSendWindow();
   for (int i = 0; i < kNumberOfAcks; ++i) {
@@ -177,10 +172,10 @@
 TEST_F(TcpCubicSenderPacketsTest, ExponentialSlowStart) {
   const int kNumberOfAcks = 20;
   // At startup make sure we can send.
-  EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0).IsZero());
+  EXPECT_TRUE(sender_->CanSend(0));
   EXPECT_EQ(QuicBandwidth::Zero(), sender_->BandwidthEstimate());
   // Make sure we can send.
-  EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), 0).IsZero());
+  EXPECT_TRUE(sender_->CanSend(0));
 
   for (int i = 0; i < kNumberOfAcks; ++i) {
     // Send our full send window.
@@ -376,7 +371,7 @@
   // Simulate abandoning all packets by supplying a bytes_in_flight of 0.
   // PRR should now allow a packet to be sent, even though prr's state
   // variables believe it has sent enough packets.
-  EXPECT_EQ(QuicTime::Delta::Zero(), sender_->TimeUntilSend(clock_.Now(), 0));
+  EXPECT_TRUE(sender_->CanSend(0));
 }
 
 TEST_F(TcpCubicSenderPacketsTest, SlowStartPacketLossPRR) {
@@ -453,7 +448,7 @@
   LoseNPackets(num_packets_to_lose);
   // Immediately after the loss, ensure at least one packet can be sent.
   // Losses without subsequent acks can occur with timer based loss detection.
-  EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), bytes_in_flight_).IsZero());
+  EXPECT_TRUE(sender_->CanSend(bytes_in_flight_));
   AckNPackets(1);
 
   // We should now have fallen out of slow start with a reduced window.
@@ -802,14 +797,10 @@
   sender_->SetFromConfig(config, Perspective::IS_SERVER);
   sender_->OnRetransmissionTimeout(true);
   EXPECT_EQ(1u, sender_->congestion_window());
-  EXPECT_TRUE(
-      sender_->TimeUntilSend(QuicTime::Zero(), kDefaultTCPMSS).IsZero());
-  EXPECT_TRUE(
-      sender_->TimeUntilSend(QuicTime::Zero(), 2 * kDefaultTCPMSS).IsZero());
-  EXPECT_TRUE(
-      sender_->TimeUntilSend(QuicTime::Zero(), 3 * kDefaultTCPMSS).IsZero());
-  EXPECT_FALSE(
-      sender_->TimeUntilSend(QuicTime::Zero(), 4 * kDefaultTCPMSS).IsZero());
+  EXPECT_TRUE(sender_->CanSend(kDefaultTCPMSS));
+  EXPECT_TRUE(sender_->CanSend(2 * kDefaultTCPMSS));
+  EXPECT_TRUE(sender_->CanSend(3 * kDefaultTCPMSS));
+  EXPECT_FALSE(sender_->CanSend(4 * kDefaultTCPMSS));
 }
 
 TEST_F(TcpCubicSenderPacketsTest, NoPRR) {
@@ -883,12 +874,11 @@
       &clock_, &rtt_stats, /*unacked_packets=*/nullptr, kCubic,
       QuicRandom::GetInstance(), &stats, kInitialCongestionWindow));
 
-  SendAlgorithmInterface::AckedPacketVector acked_packets;
-  SendAlgorithmInterface::CongestionVector missing_packets;
+  AckedPacketVector acked_packets;
+  LostPacketVector missing_packets;
   for (uint64_t i = 1; i < kDefaultMaxCongestionWindowPackets; ++i) {
     acked_packets.clear();
-    acked_packets.push_back(
-        SendAlgorithmInterface::AckedPacket(i, 1350, QuicTime::Zero()));
+    acked_packets.push_back(AckedPacket(i, 1350, QuicTime::Zero()));
     sender->OnCongestionEvent(true, sender->GetCongestionWindow(), clock_.Now(),
                               acked_packets, missing_packets);
   }
diff --git a/net/quic/core/crypto/aead_base_decrypter.cc b/net/quic/core/crypto/aead_base_decrypter.cc
index b72c2454..ae4440b 100644
--- a/net/quic/core/crypto/aead_base_decrypter.cc
+++ b/net/quic/core/crypto/aead_base_decrypter.cc
@@ -43,17 +43,19 @@
 AeadBaseDecrypter::AeadBaseDecrypter(const EVP_AEAD* aead_alg,
                                      size_t key_size,
                                      size_t auth_tag_size,
-                                     size_t nonce_prefix_size)
+                                     size_t nonce_prefix_size,
+                                     bool use_ietf_nonce_construction)
     : aead_alg_(aead_alg),
       key_size_(key_size),
       auth_tag_size_(auth_tag_size),
       nonce_prefix_size_(nonce_prefix_size),
+      use_ietf_nonce_construction_(use_ietf_nonce_construction),
       have_preliminary_key_(false) {
   DCHECK_GT(256u, key_size);
   DCHECK_GT(256u, auth_tag_size);
   DCHECK_GT(256u, nonce_prefix_size);
   DCHECK_LE(key_size_, sizeof(key_));
-  DCHECK_LE(nonce_prefix_size_, sizeof(nonce_prefix_));
+  DCHECK_LE(nonce_prefix_size_, sizeof(iv_));
 }
 
 AeadBaseDecrypter::~AeadBaseDecrypter() {}
@@ -76,11 +78,28 @@
 }
 
 bool AeadBaseDecrypter::SetNoncePrefix(QuicStringPiece nonce_prefix) {
+  if (use_ietf_nonce_construction_) {
+    QUIC_BUG << "Attempted to set nonce prefix on IETF QUIC crypter";
+    return false;
+  }
   DCHECK_EQ(nonce_prefix.size(), nonce_prefix_size_);
   if (nonce_prefix.size() != nonce_prefix_size_) {
     return false;
   }
-  memcpy(nonce_prefix_, nonce_prefix.data(), nonce_prefix.size());
+  memcpy(iv_, nonce_prefix.data(), nonce_prefix.size());
+  return true;
+}
+
+bool AeadBaseDecrypter::SetIV(QuicStringPiece iv) {
+  if (!use_ietf_nonce_construction_) {
+    QUIC_BUG << "Attempted to set IV on Google QUIC crypter";
+    return false;
+  }
+  DCHECK_EQ(iv.size(), nonce_prefix_size_ + sizeof(QuicPacketNumber));
+  if (iv.size() != nonce_prefix_size_ + sizeof(QuicPacketNumber)) {
+    return false;
+  }
+  memcpy(iv_, iv.data(), iv.size());
   return true;
 }
 
@@ -101,8 +120,7 @@
   string key, nonce_prefix;
   DiversifyPreliminaryKey(
       QuicStringPiece(reinterpret_cast<const char*>(key_), key_size_),
-      QuicStringPiece(reinterpret_cast<const char*>(nonce_prefix_),
-                      nonce_prefix_size_),
+      QuicStringPiece(reinterpret_cast<const char*>(iv_), nonce_prefix_size_),
       nonce, key_size_, nonce_prefix_size_, &key, &nonce_prefix);
 
   if (!SetKey(key) || !SetNoncePrefix(nonce_prefix)) {
@@ -114,7 +132,7 @@
   return true;
 }
 
-bool AeadBaseDecrypter::DecryptPacket(QuicVersion /*version*/,
+bool AeadBaseDecrypter::DecryptPacket(QuicTransportVersion /*version*/,
                                       QuicPacketNumber packet_number,
                                       QuicStringPiece associated_data,
                                       QuicStringPiece ciphertext,
@@ -130,10 +148,17 @@
     return false;
   }
 
-  uint8_t nonce[sizeof(nonce_prefix_) + sizeof(packet_number)];
+  uint8_t nonce[kMaxIVSize];
   const size_t nonce_size = nonce_prefix_size_ + sizeof(packet_number);
-  memcpy(nonce, nonce_prefix_, nonce_prefix_size_);
-  memcpy(nonce + nonce_prefix_size_, &packet_number, sizeof(packet_number));
+  memcpy(nonce, iv_, nonce_size);
+  if (use_ietf_nonce_construction_) {
+    for (size_t i = 0; i < sizeof(packet_number); ++i) {
+      nonce[nonce_prefix_size_ + i] ^=
+          (packet_number >> ((sizeof(packet_number) - i + 1) * 8)) & 0xff;
+    }
+  } else {
+    memcpy(nonce + nonce_prefix_size_, &packet_number, sizeof(packet_number));
+  }
   if (!EVP_AEAD_CTX_open(
           ctx_.get(), reinterpret_cast<uint8_t*>(output), output_length,
           max_output_length, reinterpret_cast<const uint8_t*>(nonce),
@@ -157,7 +182,7 @@
   if (nonce_prefix_size_ == 0) {
     return QuicStringPiece();
   }
-  return QuicStringPiece(reinterpret_cast<const char*>(nonce_prefix_),
+  return QuicStringPiece(reinterpret_cast<const char*>(iv_),
                          nonce_prefix_size_);
 }
 
diff --git a/net/quic/core/crypto/aead_base_decrypter.h b/net/quic/core/crypto/aead_base_decrypter.h
index 02edd67a..9746e9d 100644
--- a/net/quic/core/crypto/aead_base_decrypter.h
+++ b/net/quic/core/crypto/aead_base_decrypter.h
@@ -22,15 +22,17 @@
   AeadBaseDecrypter(const EVP_AEAD* aead_alg,
                     size_t key_size,
                     size_t auth_tag_size,
-                    size_t nonce_prefix_size);
+                    size_t nonce_prefix_size,
+                    bool use_ietf_nonce_construction);
   ~AeadBaseDecrypter() override;
 
   // QuicDecrypter implementation
   bool SetKey(QuicStringPiece key) override;
   bool SetNoncePrefix(QuicStringPiece nonce_prefix) override;
+  bool SetIV(QuicStringPiece iv) override;
   bool SetPreliminaryKey(QuicStringPiece key) override;
   bool SetDiversificationNonce(const DiversificationNonce& nonce) override;
-  bool DecryptPacket(QuicVersion version,
+  bool DecryptPacket(QuicTransportVersion version,
                      QuicPacketNumber packet_number,
                      QuicStringPiece associated_data,
                      QuicStringPiece ciphertext,
@@ -46,18 +48,20 @@
   // exceed the maximum.
   static const size_t kMaxKeySize = 32;
   static const size_t kMaxNoncePrefixSize = 4;
+  static const size_t kMaxIVSize = 12;
 
  private:
   const EVP_AEAD* const aead_alg_;
   const size_t key_size_;
   const size_t auth_tag_size_;
   const size_t nonce_prefix_size_;
+  const bool use_ietf_nonce_construction_;
   bool have_preliminary_key_;
 
   // The key.
   unsigned char key_[kMaxKeySize];
   // The nonce prefix.
-  unsigned char nonce_prefix_[kMaxNoncePrefixSize];
+  unsigned char iv_[kMaxIVSize];
 
   ScopedEVPAEADCtx ctx_;
 
diff --git a/net/quic/core/crypto/aead_base_encrypter.cc b/net/quic/core/crypto/aead_base_encrypter.cc
index 5620db92..45c113c 100644
--- a/net/quic/core/crypto/aead_base_encrypter.cc
+++ b/net/quic/core/crypto/aead_base_encrypter.cc
@@ -8,6 +8,7 @@
 
 #include "net/quic/core/quic_utils.h"
 #include "net/quic/platform/api/quic_aligned.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
 #include "net/quic/platform/api/quic_logging.h"
 #include "third_party/boringssl/src/include/openssl/err.h"
 #include "third_party/boringssl/src/include/openssl/evp.h"
@@ -40,13 +41,15 @@
 AeadBaseEncrypter::AeadBaseEncrypter(const EVP_AEAD* aead_alg,
                                      size_t key_size,
                                      size_t auth_tag_size,
-                                     size_t nonce_prefix_size)
+                                     size_t nonce_prefix_size,
+                                     bool use_ietf_nonce_construction)
     : aead_alg_(aead_alg),
       key_size_(key_size),
       auth_tag_size_(auth_tag_size),
-      nonce_prefix_size_(nonce_prefix_size) {
+      nonce_prefix_size_(nonce_prefix_size),
+      use_ietf_nonce_construction_(use_ietf_nonce_construction) {
   DCHECK_LE(key_size_, sizeof(key_));
-  DCHECK_LE(nonce_prefix_size_, sizeof(nonce_prefix_));
+  DCHECK_LE(nonce_prefix_size_, sizeof(iv_));
   DCHECK_GE(kMaxNonceSize, nonce_prefix_size_);
 }
 
@@ -71,11 +74,28 @@
 }
 
 bool AeadBaseEncrypter::SetNoncePrefix(QuicStringPiece nonce_prefix) {
+  if (use_ietf_nonce_construction_) {
+    QUIC_BUG << "Attempted to set nonce prefix on IETF QUIC crypter";
+    return false;
+  }
   DCHECK_EQ(nonce_prefix.size(), nonce_prefix_size_);
   if (nonce_prefix.size() != nonce_prefix_size_) {
     return false;
   }
-  memcpy(nonce_prefix_, nonce_prefix.data(), nonce_prefix.size());
+  memcpy(iv_, nonce_prefix.data(), nonce_prefix.size());
+  return true;
+}
+
+bool AeadBaseEncrypter::SetIV(QuicStringPiece iv) {
+  if (!use_ietf_nonce_construction_) {
+    QUIC_BUG << "Attempted to set IV on Google QUIC crypter";
+    return false;
+  }
+  DCHECK_EQ(iv.size(), nonce_prefix_size_ + sizeof(QuicPacketNumber));
+  if (iv.size() != nonce_prefix_size_ + sizeof(QuicPacketNumber)) {
+    return false;
+  }
+  memcpy(iv_, iv.data(), iv.size());
   return true;
 }
 
@@ -100,7 +120,7 @@
   return true;
 }
 
-bool AeadBaseEncrypter::EncryptPacket(QuicVersion /*version*/,
+bool AeadBaseEncrypter::EncryptPacket(QuicTransportVersion /*version*/,
                                       QuicPacketNumber packet_number,
                                       QuicStringPiece associated_data,
                                       QuicStringPiece plaintext,
@@ -115,9 +135,16 @@
   // same packet number twice.
   const size_t nonce_size = nonce_prefix_size_ + sizeof(packet_number);
   QUIC_ALIGNED(4) char nonce_buffer[kMaxNonceSize];
-  memcpy(nonce_buffer, nonce_prefix_, nonce_prefix_size_);
-  memcpy(nonce_buffer + nonce_prefix_size_, &packet_number,
-         sizeof(packet_number));
+  memcpy(nonce_buffer, iv_, nonce_size);
+  if (use_ietf_nonce_construction_) {
+    for (size_t i = 0; i < sizeof(packet_number); ++i) {
+      nonce_buffer[nonce_prefix_size_ + i] ^=
+          (packet_number >> ((sizeof(packet_number) - i + 1) * 8)) & 0xff;
+    }
+  } else {
+    memcpy(nonce_buffer + nonce_prefix_size_, &packet_number,
+           sizeof(packet_number));
+  }
 
   if (!Encrypt(QuicStringPiece(nonce_buffer, nonce_size), associated_data,
                plaintext, reinterpret_cast<unsigned char*>(output))) {
@@ -151,7 +178,7 @@
   if (nonce_prefix_size_ == 0) {
     return QuicStringPiece();
   }
-  return QuicStringPiece(reinterpret_cast<const char*>(nonce_prefix_),
+  return QuicStringPiece(reinterpret_cast<const char*>(iv_),
                          nonce_prefix_size_);
 }
 
diff --git a/net/quic/core/crypto/aead_base_encrypter.h b/net/quic/core/crypto/aead_base_encrypter.h
index 707cbb4..8a9da14 100644
--- a/net/quic/core/crypto/aead_base_encrypter.h
+++ b/net/quic/core/crypto/aead_base_encrypter.h
@@ -22,13 +22,15 @@
   AeadBaseEncrypter(const EVP_AEAD* aead_alg,
                     size_t key_size,
                     size_t auth_tag_size,
-                    size_t nonce_prefix_size);
+                    size_t nonce_prefix_size,
+                    bool use_ietf_nonce_construction);
   ~AeadBaseEncrypter() override;
 
   // QuicEncrypter implementation
   bool SetKey(QuicStringPiece key) override;
   bool SetNoncePrefix(QuicStringPiece nonce_prefix) override;
-  bool EncryptPacket(QuicVersion version,
+  bool SetIV(QuicStringPiece iv) override;
+  bool EncryptPacket(QuicTransportVersion version,
                      QuicPacketNumber packet_number,
                      QuicStringPiece associated_data,
                      QuicStringPiece plaintext,
@@ -55,17 +57,19 @@
   // exceed the maximum.
   static const size_t kMaxKeySize = 32;
   static const size_t kMaxNoncePrefixSize = 4;
+  static const size_t kMaxIVSize = 12;
 
  private:
   const EVP_AEAD* const aead_alg_;
   const size_t key_size_;
   const size_t auth_tag_size_;
   const size_t nonce_prefix_size_;
+  const bool use_ietf_nonce_construction_;
 
   // The key.
   unsigned char key_[kMaxKeySize];
   // The nonce prefix.
-  unsigned char nonce_prefix_[kMaxNoncePrefixSize];
+  unsigned char iv_[kMaxIVSize];
 
   ScopedEVPAEADCtx ctx_;
 
diff --git a/net/quic/core/crypto/aes_128_gcm_12_decrypter.cc b/net/quic/core/crypto/aes_128_gcm_12_decrypter.cc
index c57be8b..737a12a 100644
--- a/net/quic/core/crypto/aes_128_gcm_12_decrypter.cc
+++ b/net/quic/core/crypto/aes_128_gcm_12_decrypter.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -22,7 +22,8 @@
     : AeadBaseDecrypter(EVP_aead_aes_128_gcm(),
                         kKeySize,
                         kAuthTagSize,
-                        kNoncePrefixSize) {
+                        kNoncePrefixSize,
+                        /* use_ietf_nonce_construction */ false) {
   static_assert(kKeySize <= kMaxKeySize, "key size too big");
   static_assert(kNoncePrefixSize <= kMaxNoncePrefixSize,
                 "nonce prefix size too big");
diff --git a/net/quic/core/crypto/aes_128_gcm_12_decrypter.h b/net/quic/core/crypto/aes_128_gcm_12_decrypter.h
index ecf2a9a..dc5e820 100644
--- a/net/quic/core/crypto/aes_128_gcm_12_decrypter.h
+++ b/net/quic/core/crypto/aes_128_gcm_12_decrypter.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/net/quic/core/crypto/aes_128_gcm_12_encrypter.cc b/net/quic/core/crypto/aes_128_gcm_12_encrypter.cc
index dde7e3e3..173a259 100644
--- a/net/quic/core/crypto/aes_128_gcm_12_encrypter.cc
+++ b/net/quic/core/crypto/aes_128_gcm_12_encrypter.cc
@@ -19,7 +19,8 @@
     : AeadBaseEncrypter(EVP_aead_aes_128_gcm(),
                         kKeySize,
                         kAuthTagSize,
-                        kNoncePrefixSize) {
+                        kNoncePrefixSize,
+                        /* use_ietf_nonce_construction */ false) {
   static_assert(kKeySize <= kMaxKeySize, "key size too big");
   static_assert(kNoncePrefixSize <= kMaxNoncePrefixSize,
                 "nonce prefix size too big");
diff --git a/net/quic/core/crypto/aes_128_gcm_12_encrypter_test.cc b/net/quic/core/crypto/aes_128_gcm_12_encrypter_test.cc
index bf98368..029a278 100644
--- a/net/quic/core/crypto/aes_128_gcm_12_encrypter_test.cc
+++ b/net/quic/core/crypto/aes_128_gcm_12_encrypter_test.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/net/quic/core/crypto/aes_128_gcm_decrypter.cc b/net/quic/core/crypto/aes_128_gcm_decrypter.cc
new file mode 100644
index 0000000..f2b2d07
--- /dev/null
+++ b/net/quic/core/crypto/aes_128_gcm_decrypter.cc
@@ -0,0 +1,38 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/core/crypto/aes_128_gcm_decrypter.h"
+
+#include "net/quic/platform/api/quic_flag_utils.h"
+#include "net/quic/platform/api/quic_flags.h"
+#include "third_party/boringssl/src/include/openssl/aead.h"
+#include "third_party/boringssl/src/include/openssl/tls1.h"
+
+namespace net {
+
+namespace {
+
+const size_t kKeySize = 16;
+const size_t kNoncePrefixSize = 4;
+
+}  // namespace
+
+Aes128GcmDecrypter::Aes128GcmDecrypter()
+    : AeadBaseDecrypter(EVP_aead_aes_128_gcm(),
+                        kKeySize,
+                        kAuthTagSize,
+                        kNoncePrefixSize,
+                        /* use_ietf_nonce_construction */ true) {
+  static_assert(kKeySize <= kMaxKeySize, "key size too big");
+  static_assert(kNoncePrefixSize <= kMaxNoncePrefixSize,
+                "nonce prefix size too big");
+}
+
+Aes128GcmDecrypter::~Aes128GcmDecrypter() {}
+
+uint32_t Aes128GcmDecrypter::cipher_id() const {
+  return TLS1_CK_AES_128_GCM_SHA256;
+}
+
+}  // namespace net
diff --git a/net/quic/core/crypto/aes_128_gcm_decrypter.h b/net/quic/core/crypto/aes_128_gcm_decrypter.h
new file mode 100644
index 0000000..68d7a133
--- /dev/null
+++ b/net/quic/core/crypto/aes_128_gcm_decrypter.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_QUIC_CORE_CRYPTO_AES_128_GCM_DECRYPTER_H_
+#define NET_QUIC_CORE_CRYPTO_AES_128_GCM_DECRYPTER_H_
+
+#include <cstdint>
+
+#include "base/macros.h"
+#include "net/quic/core/crypto/aead_base_decrypter.h"
+#include "net/quic/platform/api/quic_export.h"
+
+namespace net {
+
+// An Aes128GcmDecrypter is a QuicDecrypter that implements the
+// AEAD_AES_128_GCM algorithm specified in RFC 5116 for use in IETF QUIC.
+//
+// It uses an authentication tag of 16 bytes (128 bits). It uses a 12 byte IV
+// that is XOR'd with the packet number to compute the nonce.
+class QUIC_EXPORT_PRIVATE Aes128GcmDecrypter : public AeadBaseDecrypter {
+ public:
+  enum {
+    kAuthTagSize = 16,
+  };
+
+  Aes128GcmDecrypter();
+  ~Aes128GcmDecrypter() override;
+
+  uint32_t cipher_id() const override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(Aes128GcmDecrypter);
+};
+
+}  // namespace net
+
+#endif  // NET_QUIC_CORE_CRYPTO_AES_128_GCM_DECRYPTER_H_
diff --git a/net/quic/core/crypto/aes_128_gcm_decrypter_test.cc b/net/quic/core/crypto/aes_128_gcm_decrypter_test.cc
new file mode 100644
index 0000000..336d5d8
--- /dev/null
+++ b/net/quic/core/crypto/aes_128_gcm_decrypter_test.cc
@@ -0,0 +1,275 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/core/crypto/aes_128_gcm_decrypter.h"
+
+#include <memory>
+
+#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_test.h"
+#include "net/quic/platform/api/quic_text_utils.h"
+#include "net/quic/test_tools/quic_test_utils.h"
+
+using std::string;
+
+namespace {
+
+// The AES GCM test vectors come from the file gcmDecrypt128.rsp
+// downloaded from http://csrc.nist.gov/groups/STM/cavp/index.html on
+// 2013-02-01. The test vectors in that file look like this:
+//
+// [Keylen = 128]
+// [IVlen = 96]
+// [PTlen = 0]
+// [AADlen = 0]
+// [Taglen = 128]
+//
+// Count = 0
+// Key = cf063a34d4a9a76c2c86787d3f96db71
+// IV = 113b9785971864c83b01c787
+// CT =
+// AAD =
+// Tag = 72ac8493e3a5228b5d130a69d2510e42
+// PT =
+//
+// Count = 1
+// Key = a49a5e26a2f8cb63d05546c2a62f5343
+// IV = 907763b19b9b4ab6bd4f0281
+// CT =
+// AAD =
+// Tag = a2be08210d8c470a8df6e8fbd79ec5cf
+// FAIL
+//
+// ...
+//
+// The gcmDecrypt128.rsp file is huge (2.6 MB), so I selected just a
+// few test vectors for this unit test.
+
+// Describes a group of test vectors that all have a given key length, IV
+// length, plaintext length, AAD length, and tag length.
+struct TestGroupInfo {
+  size_t key_len;
+  size_t iv_len;
+  size_t pt_len;
+  size_t aad_len;
+  size_t tag_len;
+};
+
+// Each test vector consists of six strings of lowercase hexadecimal digits.
+// The strings may be empty (zero length). A test vector with a nullptr |key|
+// marks the end of an array of test vectors.
+struct TestVector {
+  // Input:
+  const char* key;
+  const char* iv;
+  const char* ct;
+  const char* aad;
+  const char* tag;
+
+  // Expected output:
+  const char* pt;  // An empty string "" means decryption succeeded and
+                   // the plaintext is zero-length. nullptr means decryption
+                   // failed.
+};
+
+const TestGroupInfo test_group_info[] = {
+    {128, 96, 0, 0, 128},     {128, 96, 0, 128, 128},   {128, 96, 128, 0, 128},
+    {128, 96, 408, 160, 128}, {128, 96, 408, 720, 128}, {128, 96, 104, 0, 128},
+};
+
+const TestVector test_group_0[] = {
+    {"cf063a34d4a9a76c2c86787d3f96db71", "113b9785971864c83b01c787", "", "",
+     "72ac8493e3a5228b5d130a69d2510e42", ""},
+    {
+        "a49a5e26a2f8cb63d05546c2a62f5343", "907763b19b9b4ab6bd4f0281", "", "",
+        "a2be08210d8c470a8df6e8fbd79ec5cf",
+        nullptr  // FAIL
+    },
+    {nullptr}};
+
+const TestVector test_group_1[] = {
+    {
+        "d1f6af919cde85661208bdce0c27cb22", "898c6929b435017bf031c3c5", "",
+        "7c5faa40e636bbc91107e68010c92b9f", "ae45f11777540a2caeb128be8092468a",
+        nullptr  // FAIL
+    },
+    {"2370e320d4344208e0ff5683f243b213", "04dbb82f044d30831c441228", "",
+     "d43a8e5089eea0d026c03a85178b27da", "2a049c049d25aa95969b451d93c31c6e",
+     ""},
+    {nullptr}};
+
+const TestVector test_group_2[] = {
+    {"e98b72a9881a84ca6b76e0f43e68647a", "8b23299fde174053f3d652ba",
+     "5a3c1cf1985dbb8bed818036fdd5ab42", "", "23c7ab0f952b7091cd324835043b5eb5",
+     "28286a321293253c3e0aa2704a278032"},
+    {"33240636cd3236165f1a553b773e728e", "17c4d61493ecdc8f31700b12",
+     "47bb7e23f7bdfe05a8091ac90e4f8b2e", "", "b723c70e931d9785f40fd4ab1d612dc9",
+     "95695a5b12f2870b9cc5fdc8f218a97d"},
+    {
+        "5164df856f1e9cac04a79b808dc5be39", "e76925d5355e0584ce871b2b",
+        "0216c899c88d6e32c958c7e553daa5bc", "",
+        "a145319896329c96df291f64efbe0e3a",
+        nullptr  // FAIL
+    },
+    {nullptr}};
+
+const TestVector test_group_3[] = {
+    {"af57f42c60c0fc5a09adb81ab86ca1c3", "a2dc01871f37025dc0fc9a79",
+     "b9a535864f48ea7b6b1367914978f9bfa087d854bb0e269bed8d279d2eea1210e48947"
+     "338b22f9bad09093276a331e9c79c7f4",
+     "41dc38988945fcb44faf2ef72d0061289ef8efd8",
+     "4f71e72bde0018f555c5adcce062e005",
+     "3803a0727eeb0ade441e0ec107161ded2d425ec0d102f21f51bf2cf9947c7ec4aa7279"
+     "5b2f69b041596e8817d0a3c16f8fadeb"},
+    {"ebc753e5422b377d3cb64b58ffa41b61", "2e1821efaced9acf1f241c9b",
+     "069567190554e9ab2b50a4e1fbf9c147340a5025fdbd201929834eaf6532325899ccb9"
+     "f401823e04b05817243d2142a3589878",
+     "b9673412fd4f88ba0e920f46dd6438ff791d8eef",
+     "534d9234d2351cf30e565de47baece0b",
+     "39077edb35e9c5a4b1e4c2a6b9bb1fce77f00f5023af40333d6d699014c2bcf4209c18"
+     "353a18017f5b36bfc00b1f6dcb7ed485"},
+    {
+        "52bdbbf9cf477f187ec010589cb39d58", "d3be36d3393134951d324b31",
+        "700188da144fa692cf46e4a8499510a53d90903c967f7f13e8a1bd8151a74adc4fe63e"
+        "32b992760b3a5f99e9a47838867000a9",
+        "93c4fc6a4135f54d640b0c976bf755a06a292c33",
+        "8ca4e38aa3dfa6b1d0297021ccf3ea5f",
+        nullptr  // FAIL
+    },
+    {nullptr}};
+
+const TestVector test_group_4[] = {
+    {"da2bb7d581493d692380c77105590201", "44aa3e7856ca279d2eb020c6",
+     "9290d430c9e89c37f0446dbd620c9a6b34b1274aeb6f911f75867efcf95b6feda69f1a"
+     "f4ee16c761b3c9aeac3da03aa9889c88",
+     "4cd171b23bddb3a53cdf959d5c1710b481eb3785a90eb20a2345ee00d0bb7868c367ab"
+     "12e6f4dd1dee72af4eee1d197777d1d6499cc541f34edbf45cda6ef90b3c024f9272d7"
+     "2ec1909fb8fba7db88a4d6f7d3d925980f9f9f72",
+     "9e3ac938d3eb0cadd6f5c9e35d22ba38",
+     "9bbf4c1a2742f6ac80cb4e8a052e4a8f4f07c43602361355b717381edf9fabd4cb7e3a"
+     "d65dbd1378b196ac270588dd0621f642"},
+    {"d74e4958717a9d5c0e235b76a926cae8", "0b7471141e0c70b1995fd7b1",
+     "e701c57d2330bf066f9ff8cf3ca4343cafe4894651cd199bdaaa681ba486b4a65c5a22"
+     "b0f1420be29ea547d42c713bc6af66aa",
+     "4a42b7aae8c245c6f1598a395316e4b8484dbd6e64648d5e302021b1d3fa0a38f46e22"
+     "bd9c8080b863dc0016482538a8562a4bd0ba84edbe2697c76fd039527ac179ec5506cf"
+     "34a6039312774cedebf4961f3978b14a26509f96",
+     "e192c23cb036f0b31592989119eed55d",
+     "840d9fb95e32559fb3602e48590280a172ca36d9b49ab69510f5bd552bfab7a306f85f"
+     "f0a34bc305b88b804c60b90add594a17"},
+    {
+        "1986310c725ac94ecfe6422e75fc3ee7", "93ec4214fa8e6dc4e3afc775",
+        "b178ec72f85a311ac4168f42a4b2c23113fbea4b85f4b9dabb74e143eb1b8b0a361e02"
+        "43edfd365b90d5b325950df0ada058f9",
+        "e80b88e62c49c958b5e0b8b54f532d9ff6aa84c8a40132e93e55b59fc24e8decf28463"
+        "139f155d1e8ce4ee76aaeefcd245baa0fc519f83a5fb9ad9aa40c4b21126013f576c42"
+        "72c2cb136c8fd091cc4539877a5d1e72d607f960",
+        "8b347853f11d75e81e8a95010be81f17",
+        nullptr  // FAIL
+    },
+    {nullptr}};
+
+const TestVector test_group_5[] = {
+    {"387218b246c1a8257748b56980e50c94", "dd7e014198672be39f95b69d",
+     "cdba9e73eaf3d38eceb2b04a8d", "", "ecf90f4a47c9c626d6fb2c765d201556",
+     "48f5b426baca03064554cc2b30"},
+    {"294de463721e359863887c820524b3d4", "3338b35c9d57a5d28190e8c9",
+     "2f46634e74b8e4c89812ac83b9", "", "dabd506764e68b82a7e720aa18da0abe",
+     "46a2e55c8e264df211bd112685"},
+    {"28ead7fd2179e0d12aa6d5d88c58c2dc", "5055347f18b4d5add0ae5c41",
+     "142d8210c3fb84774cdbd0447a", "", "5fd321d9cdb01952dc85f034736c2a7d",
+     "3b95b981086ee73cc4d0cc1422"},
+    {
+        "7d7b6c988137b8d470c57bf674a09c87", "9edf2aa970d016ac962e1fd8",
+        "a85b66c3cb5eab91d5bdc8bc0e", "", "dc054efc01f3afd21d9c2484819f569a",
+        nullptr  // FAIL
+    },
+    {nullptr}};
+
+const TestVector* const test_group_array[] = {
+    test_group_0, test_group_1, test_group_2,
+    test_group_3, test_group_4, test_group_5,
+};
+
+}  // namespace
+
+namespace net {
+namespace test {
+
+// DecryptWithNonce wraps the |Decrypt| method of |decrypter| to allow passing
+// in an nonce and also to allocate the buffer needed for the plaintext.
+QuicData* DecryptWithNonce(Aes128GcmDecrypter* decrypter,
+                           QuicStringPiece nonce,
+                           QuicStringPiece associated_data,
+                           QuicStringPiece ciphertext) {
+  decrypter->SetIV(nonce);
+  std::unique_ptr<char[]> output(new char[ciphertext.length()]);
+  size_t output_length = 0;
+  const bool success = decrypter->DecryptPacket(
+      QuicVersionMax(), 0, associated_data, ciphertext, output.get(),
+      &output_length, ciphertext.length());
+  if (!success) {
+    return nullptr;
+  }
+  return new QuicData(output.release(), output_length, true);
+}
+
+class Aes128GcmDecrypterTest : public QuicTest {};
+
+TEST_F(Aes128GcmDecrypterTest, Decrypt) {
+  for (size_t i = 0; i < arraysize(test_group_array); i++) {
+    SCOPED_TRACE(i);
+    const TestVector* test_vectors = test_group_array[i];
+    const TestGroupInfo& test_info = test_group_info[i];
+    for (size_t j = 0; test_vectors[j].key != nullptr; j++) {
+      // If not present then decryption is expected to fail.
+      bool has_pt = test_vectors[j].pt;
+
+      // Decode the test vector.
+      string key = QuicTextUtils::HexDecode(test_vectors[j].key);
+      string iv = QuicTextUtils::HexDecode(test_vectors[j].iv);
+      string ct = QuicTextUtils::HexDecode(test_vectors[j].ct);
+      string aad = QuicTextUtils::HexDecode(test_vectors[j].aad);
+      string tag = QuicTextUtils::HexDecode(test_vectors[j].tag);
+      string pt;
+      if (has_pt) {
+        pt = QuicTextUtils::HexDecode(test_vectors[j].pt);
+      }
+
+      // The test vector's lengths should look sane. Note that the lengths
+      // in |test_info| are in bits.
+      EXPECT_EQ(test_info.key_len, key.length() * 8);
+      EXPECT_EQ(test_info.iv_len, iv.length() * 8);
+      EXPECT_EQ(test_info.pt_len, ct.length() * 8);
+      EXPECT_EQ(test_info.aad_len, aad.length() * 8);
+      EXPECT_EQ(test_info.tag_len, tag.length() * 8);
+      if (has_pt) {
+        EXPECT_EQ(test_info.pt_len, pt.length() * 8);
+      }
+      string ciphertext = ct + tag;
+
+      Aes128GcmDecrypter decrypter;
+      ASSERT_TRUE(decrypter.SetKey(key));
+
+      std::unique_ptr<QuicData> decrypted(DecryptWithNonce(
+          &decrypter, iv,
+          // This deliberately tests that the decrypter can handle an AAD that
+          // is set to nullptr, as opposed to a zero-length, non-nullptr
+          // pointer.
+          aad.length() ? aad : QuicStringPiece(), ciphertext));
+      if (!decrypted.get()) {
+        EXPECT_FALSE(has_pt);
+        continue;
+      }
+      EXPECT_TRUE(has_pt);
+
+      ASSERT_EQ(pt.length(), decrypted->length());
+      test::CompareCharArraysWithHexError("plaintext", decrypted->data(),
+                                          pt.length(), pt.data(), pt.length());
+    }
+  }
+}
+
+}  // namespace test
+}  // namespace net
diff --git a/net/quic/core/crypto/aes_128_gcm_encrypter.cc b/net/quic/core/crypto/aes_128_gcm_encrypter.cc
new file mode 100644
index 0000000..65f3030
--- /dev/null
+++ b/net/quic/core/crypto/aes_128_gcm_encrypter.cc
@@ -0,0 +1,31 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/core/crypto/aes_128_gcm_encrypter.h"
+
+#include "third_party/boringssl/src/include/openssl/evp.h"
+
+namespace net {
+
+namespace {
+
+const size_t kKeySize = 16;
+const size_t kNoncePrefixSize = 4;
+
+}  // namespace
+
+Aes128GcmEncrypter::Aes128GcmEncrypter()
+    : AeadBaseEncrypter(EVP_aead_aes_128_gcm(),
+                        kKeySize,
+                        kAuthTagSize,
+                        kNoncePrefixSize,
+                        /* use_ietf_nonce_construction */ true) {
+  static_assert(kKeySize <= kMaxKeySize, "key size too big");
+  static_assert(kNoncePrefixSize <= kMaxNoncePrefixSize,
+                "nonce prefix size too big");
+}
+
+Aes128GcmEncrypter::~Aes128GcmEncrypter() {}
+
+}  // namespace net
diff --git a/net/quic/core/crypto/aes_128_gcm_encrypter.h b/net/quic/core/crypto/aes_128_gcm_encrypter.h
new file mode 100644
index 0000000..2eef1ac
--- /dev/null
+++ b/net/quic/core/crypto/aes_128_gcm_encrypter.h
@@ -0,0 +1,34 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_QUIC_CORE_CRYPTO_AES_128_GCM_ENCRYPTER_H_
+#define NET_QUIC_CORE_CRYPTO_AES_128_GCM_ENCRYPTER_H_
+
+#include "base/macros.h"
+#include "net/quic/core/crypto/aead_base_encrypter.h"
+#include "net/quic/platform/api/quic_export.h"
+
+namespace net {
+
+// An Aes128GcmEncrypter is a QuicEncrypter that implements the
+// AEAD_AES_128_GCM algorithm specified in RFC 5116 for use in IETF QUIC.
+//
+// It uses an authentication tag of 16 bytes (128 bits). It uses a 12 byte IV
+// that is XOR'd with the packet number to compute the nonce.
+class QUIC_EXPORT_PRIVATE Aes128GcmEncrypter : public AeadBaseEncrypter {
+ public:
+  enum {
+    kAuthTagSize = 16,
+  };
+
+  Aes128GcmEncrypter();
+  ~Aes128GcmEncrypter() override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(Aes128GcmEncrypter);
+};
+
+}  // namespace net
+
+#endif  // NET_QUIC_CORE_CRYPTO_AES_128_GCM_ENCRYPTER_H_
diff --git a/net/quic/core/crypto/aes_128_gcm_encrypter_test.cc b/net/quic/core/crypto/aes_128_gcm_encrypter_test.cc
new file mode 100644
index 0000000..31e0bc9
--- /dev/null
+++ b/net/quic/core/crypto/aes_128_gcm_encrypter_test.cc
@@ -0,0 +1,235 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/core/crypto/aes_128_gcm_encrypter.h"
+
+#include <memory>
+
+#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_test.h"
+#include "net/quic/platform/api/quic_text_utils.h"
+#include "net/quic/test_tools/quic_test_utils.h"
+
+using std::string;
+
+namespace {
+
+// The AES GCM test vectors come from the file gcmEncryptExtIV128.rsp
+// downloaded from http://csrc.nist.gov/groups/STM/cavp/index.html on
+// 2013-02-01. The test vectors in that file look like this:
+//
+// [Keylen = 128]
+// [IVlen = 96]
+// [PTlen = 0]
+// [AADlen = 0]
+// [Taglen = 128]
+//
+// Count = 0
+// Key = 11754cd72aec309bf52f7687212e8957
+// IV = 3c819d9a9bed087615030b65
+// PT =
+// AAD =
+// CT =
+// Tag = 250327c674aaf477aef2675748cf6971
+//
+// Count = 1
+// Key = ca47248ac0b6f8372a97ac43508308ed
+// IV = ffd2b598feabc9019262d2be
+// PT =
+// AAD =
+// CT =
+// Tag = 60d20404af527d248d893ae495707d1a
+//
+// ...
+//
+// The gcmEncryptExtIV128.rsp file is huge (2.8 MB), so I selected just a
+// few test vectors for this unit test.
+
+// Describes a group of test vectors that all have a given key length, IV
+// length, plaintext length, AAD length, and tag length.
+struct TestGroupInfo {
+  size_t key_len;
+  size_t iv_len;
+  size_t pt_len;
+  size_t aad_len;
+  size_t tag_len;
+};
+
+// Each test vector consists of six strings of lowercase hexadecimal digits.
+// The strings may be empty (zero length). A test vector with a nullptr |key|
+// marks the end of an array of test vectors.
+struct TestVector {
+  const char* key;
+  const char* iv;
+  const char* pt;
+  const char* aad;
+  const char* ct;
+  const char* tag;
+};
+
+const TestGroupInfo test_group_info[] = {
+    {128, 96, 0, 0, 128},     {128, 96, 0, 128, 128},   {128, 96, 128, 0, 128},
+    {128, 96, 408, 160, 128}, {128, 96, 408, 720, 128}, {128, 96, 104, 0, 128},
+};
+
+const TestVector test_group_0[] = {
+    {"11754cd72aec309bf52f7687212e8957", "3c819d9a9bed087615030b65", "", "", "",
+     "250327c674aaf477aef2675748cf6971"},
+    {"ca47248ac0b6f8372a97ac43508308ed", "ffd2b598feabc9019262d2be", "", "", "",
+     "60d20404af527d248d893ae495707d1a"},
+    {nullptr}};
+
+const TestVector test_group_1[] = {
+    {"77be63708971c4e240d1cb79e8d77feb", "e0e00f19fed7ba0136a797f3", "",
+     "7a43ec1d9c0a5a78a0b16533a6213cab", "",
+     "209fcc8d3675ed938e9c7166709dd946"},
+    {"7680c5d3ca6154758e510f4d25b98820", "f8f105f9c3df4965780321f8", "",
+     "c94c410194c765e3dcc7964379758ed3", "",
+     "94dca8edfcf90bb74b153c8d48a17930"},
+    {nullptr}};
+
+const TestVector test_group_2[] = {
+    {"7fddb57453c241d03efbed3ac44e371c", "ee283a3fc75575e33efd4887",
+     "d5de42b461646c255c87bd2962d3b9a2", "", "2ccda4a5415cb91e135c2a0f78c9b2fd",
+     "b36d1df9b9d5e596f83e8b7f52971cb3"},
+    {"ab72c77b97cb5fe9a382d9fe81ffdbed", "54cc7dc2c37ec006bcc6d1da",
+     "007c5e5b3e59df24a7c355584fc1518d", "", "0e1bde206a07a9c2c1b65300f8c64997",
+     "2b4401346697138c7a4891ee59867d0c"},
+    {nullptr}};
+
+const TestVector test_group_3[] = {
+    {"fe47fcce5fc32665d2ae399e4eec72ba", "5adb9609dbaeb58cbd6e7275",
+     "7c0e88c88899a779228465074797cd4c2e1498d259b54390b85e3eef1c02df60e743f1"
+     "b840382c4bccaf3bafb4ca8429bea063",
+     "88319d6e1d3ffa5f987199166c8a9b56c2aeba5a",
+     "98f4826f05a265e6dd2be82db241c0fbbbf9ffb1c173aa83964b7cf539304373636525"
+     "3ddbc5db8778371495da76d269e5db3e",
+     "291ef1982e4defedaa2249f898556b47"},
+    {"ec0c2ba17aa95cd6afffe949da9cc3a8", "296bce5b50b7d66096d627ef",
+     "b85b3753535b825cbe5f632c0b843c741351f18aa484281aebec2f45bb9eea2d79d987"
+     "b764b9611f6c0f8641843d5d58f3a242",
+     "f8d00f05d22bf68599bcdeb131292ad6e2df5d14",
+     "a7443d31c26bdf2a1c945e29ee4bd344a99cfaf3aa71f8b3f191f83c2adfc7a0716299"
+     "5506fde6309ffc19e716eddf1a828c5a",
+     "890147971946b627c40016da1ecf3e77"},
+    {nullptr}};
+
+const TestVector test_group_4[] = {
+    {"2c1f21cf0f6fb3661943155c3e3d8492", "23cb5ff362e22426984d1907",
+     "42f758836986954db44bf37c6ef5e4ac0adaf38f27252a1b82d02ea949c8a1a2dbc0d6"
+     "8b5615ba7c1220ff6510e259f06655d8",
+     "5d3624879d35e46849953e45a32a624d6a6c536ed9857c613b572b0333e701557a713e"
+     "3f010ecdf9a6bd6c9e3e44b065208645aff4aabee611b391528514170084ccf587177f"
+     "4488f33cfb5e979e42b6e1cfc0a60238982a7aec",
+     "81824f0e0d523db30d3da369fdc0d60894c7a0a20646dd015073ad2732bd989b14a222"
+     "b6ad57af43e1895df9dca2a5344a62cc",
+     "57a3ee28136e94c74838997ae9823f3a"},
+    {"d9f7d2411091f947b4d6f1e2d1f0fb2e", "e1934f5db57cc983e6b180e7",
+     "73ed042327f70fe9c572a61545eda8b2a0c6e1d6c291ef19248e973aee6c312012f490"
+     "c2c6f6166f4a59431e182663fcaea05a",
+     "0a8a18a7150e940c3d87b38e73baee9a5c049ee21795663e264b694a949822b639092d"
+     "0e67015e86363583fcf0ca645af9f43375f05fdb4ce84f411dcbca73c2220dea03a201"
+     "15d2e51398344b16bee1ed7c499b353d6c597af8",
+     "aaadbd5c92e9151ce3db7210b8714126b73e43436d242677afa50384f2149b831f1d57"
+     "3c7891c2a91fbc48db29967ec9542b23",
+     "21b51ca862cb637cdd03b99a0f93b134"},
+    {nullptr}};
+
+const TestVector test_group_5[] = {
+    {"fe9bb47deb3a61e423c2231841cfd1fb", "4d328eb776f500a2f7fb47aa",
+     "f1cc3818e421876bb6b8bbd6c9", "", "b88c5c1977b35b517b0aeae967",
+     "43fd4727fe5cdb4b5b42818dea7ef8c9"},
+    {"6703df3701a7f54911ca72e24dca046a", "12823ab601c350ea4bc2488c",
+     "793cd125b0b84a043e3ac67717", "", "b2051c80014f42f08735a7b0cd",
+     "38e6bcd29962e5f2c13626b85a877101"},
+    {nullptr}};
+
+const TestVector* const test_group_array[] = {
+    test_group_0, test_group_1, test_group_2,
+    test_group_3, test_group_4, test_group_5,
+};
+
+}  // namespace
+
+namespace net {
+namespace test {
+
+// EncryptWithNonce wraps the |Encrypt| method of |encrypter| to allow passing
+// in an nonce and also to allocate the buffer needed for the ciphertext.
+QuicData* EncryptWithNonce(Aes128GcmEncrypter* encrypter,
+                           QuicStringPiece nonce,
+                           QuicStringPiece associated_data,
+                           QuicStringPiece plaintext) {
+  size_t ciphertext_size = encrypter->GetCiphertextSize(plaintext.length());
+  std::unique_ptr<char[]> ciphertext(new char[ciphertext_size]);
+
+  if (!encrypter->Encrypt(nonce, associated_data, plaintext,
+                          reinterpret_cast<unsigned char*>(ciphertext.get()))) {
+    return nullptr;
+  }
+
+  return new QuicData(ciphertext.release(), ciphertext_size, true);
+}
+
+class Aes128GcmEncrypterTest : public QuicTest {};
+
+TEST_F(Aes128GcmEncrypterTest, Encrypt) {
+  for (size_t i = 0; i < arraysize(test_group_array); i++) {
+    SCOPED_TRACE(i);
+    const TestVector* test_vectors = test_group_array[i];
+    const TestGroupInfo& test_info = test_group_info[i];
+    for (size_t j = 0; test_vectors[j].key != nullptr; j++) {
+      // Decode the test vector.
+      string key = QuicTextUtils::HexDecode(test_vectors[j].key);
+      string iv = QuicTextUtils::HexDecode(test_vectors[j].iv);
+      string pt = QuicTextUtils::HexDecode(test_vectors[j].pt);
+      string aad = QuicTextUtils::HexDecode(test_vectors[j].aad);
+      string ct = QuicTextUtils::HexDecode(test_vectors[j].ct);
+      string tag = QuicTextUtils::HexDecode(test_vectors[j].tag);
+
+      // The test vector's lengths should look sane. Note that the lengths
+      // in |test_info| are in bits.
+      EXPECT_EQ(test_info.key_len, key.length() * 8);
+      EXPECT_EQ(test_info.iv_len, iv.length() * 8);
+      EXPECT_EQ(test_info.pt_len, pt.length() * 8);
+      EXPECT_EQ(test_info.aad_len, aad.length() * 8);
+      EXPECT_EQ(test_info.pt_len, ct.length() * 8);
+      EXPECT_EQ(test_info.tag_len, tag.length() * 8);
+
+      Aes128GcmEncrypter encrypter;
+      ASSERT_TRUE(encrypter.SetKey(key));
+      std::unique_ptr<QuicData> encrypted(EncryptWithNonce(
+          &encrypter, iv,
+          // This deliberately tests that the encrypter can handle an AAD that
+          // is set to nullptr, as opposed to a zero-length, non-nullptr
+          // pointer.
+          aad.length() ? aad : QuicStringPiece(), pt));
+      ASSERT_TRUE(encrypted.get());
+
+      ASSERT_EQ(ct.length() + tag.length(), encrypted->length());
+      test::CompareCharArraysWithHexError("ciphertext", encrypted->data(),
+                                          ct.length(), ct.data(), ct.length());
+      test::CompareCharArraysWithHexError(
+          "authentication tag", encrypted->data() + ct.length(), tag.length(),
+          tag.data(), tag.length());
+    }
+  }
+}
+
+TEST_F(Aes128GcmEncrypterTest, GetMaxPlaintextSize) {
+  Aes128GcmEncrypter encrypter;
+  EXPECT_EQ(1000u, encrypter.GetMaxPlaintextSize(1016));
+  EXPECT_EQ(100u, encrypter.GetMaxPlaintextSize(116));
+  EXPECT_EQ(10u, encrypter.GetMaxPlaintextSize(26));
+}
+
+TEST_F(Aes128GcmEncrypterTest, GetCiphertextSize) {
+  Aes128GcmEncrypter encrypter;
+  EXPECT_EQ(1016u, encrypter.GetCiphertextSize(1000));
+  EXPECT_EQ(116u, encrypter.GetCiphertextSize(100));
+  EXPECT_EQ(26u, encrypter.GetCiphertextSize(10));
+}
+
+}  // namespace test
+}  // namespace net
diff --git a/net/quic/core/crypto/aes_256_gcm_decrypter.cc b/net/quic/core/crypto/aes_256_gcm_decrypter.cc
new file mode 100644
index 0000000..7374797
--- /dev/null
+++ b/net/quic/core/crypto/aes_256_gcm_decrypter.cc
@@ -0,0 +1,38 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/core/crypto/aes_256_gcm_decrypter.h"
+
+#include "net/quic/platform/api/quic_flag_utils.h"
+#include "net/quic/platform/api/quic_flags.h"
+#include "third_party/boringssl/src/include/openssl/aead.h"
+#include "third_party/boringssl/src/include/openssl/tls1.h"
+
+namespace net {
+
+namespace {
+
+const size_t kKeySize = 32;
+const size_t kNoncePrefixSize = 4;
+
+}  // namespace
+
+Aes256GcmDecrypter::Aes256GcmDecrypter()
+    : AeadBaseDecrypter(EVP_aead_aes_256_gcm(),
+                        kKeySize,
+                        kAuthTagSize,
+                        kNoncePrefixSize,
+                        /* use_ietf_nonce_construction */ true) {
+  static_assert(kKeySize <= kMaxKeySize, "key size too big");
+  static_assert(kNoncePrefixSize <= kMaxNoncePrefixSize,
+                "nonce prefix size too big");
+}
+
+Aes256GcmDecrypter::~Aes256GcmDecrypter() {}
+
+uint32_t Aes256GcmDecrypter::cipher_id() const {
+  return TLS1_CK_AES_256_GCM_SHA384;
+}
+
+}  // namespace net
diff --git a/net/quic/core/crypto/aes_256_gcm_decrypter.h b/net/quic/core/crypto/aes_256_gcm_decrypter.h
new file mode 100644
index 0000000..74a7c4c
--- /dev/null
+++ b/net/quic/core/crypto/aes_256_gcm_decrypter.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_QUIC_CORE_CRYPTO_AES_256_GCM_DECRYPTER_H_
+#define NET_QUIC_CORE_CRYPTO_AES_256_GCM_DECRYPTER_H_
+
+#include <cstdint>
+
+#include "base/macros.h"
+#include "net/quic/core/crypto/aead_base_decrypter.h"
+#include "net/quic/platform/api/quic_export.h"
+
+namespace net {
+
+// An Aes256GcmDecrypter is a QuicDecrypter that implements the
+// AEAD_AES_256_GCM algorithm specified in RFC 5116 for use in IETF QUIC.
+//
+// It uses an authentication tag of 16 bytes (128 bits). It uses a 12 byte IV
+// that is XOR'd with the packet number to compute the nonce.
+class QUIC_EXPORT_PRIVATE Aes256GcmDecrypter : public AeadBaseDecrypter {
+ public:
+  enum {
+    kAuthTagSize = 16,
+  };
+
+  Aes256GcmDecrypter();
+  ~Aes256GcmDecrypter() override;
+
+  uint32_t cipher_id() const override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(Aes256GcmDecrypter);
+};
+
+}  // namespace net
+
+#endif  // NET_QUIC_CORE_CRYPTO_AES_256_GCM_DECRYPTER_H_
diff --git a/net/quic/core/crypto/aes_256_gcm_decrypter_test.cc b/net/quic/core/crypto/aes_256_gcm_decrypter_test.cc
new file mode 100644
index 0000000..90adcee
--- /dev/null
+++ b/net/quic/core/crypto/aes_256_gcm_decrypter_test.cc
@@ -0,0 +1,279 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/core/crypto/aes_256_gcm_decrypter.h"
+
+#include <memory>
+
+#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_test.h"
+#include "net/quic/platform/api/quic_text_utils.h"
+#include "net/quic/test_tools/quic_test_utils.h"
+
+using std::string;
+
+namespace {
+
+// The AES GCM test vectors come from the file gcmDecrypt256.rsp
+// downloaded from
+// https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/CAVP-TESTING-BLOCK-CIPHER-MODES#GCMVS
+// on 2017-09-27. The test vectors in that file look like this:
+//
+// [Keylen = 256]
+// [IVlen = 96]
+// [PTlen = 0]
+// [AADlen = 0]
+// [Taglen = 128]
+//
+// Count = 0
+// Key = f5a2b27c74355872eb3ef6c5feafaa740e6ae990d9d48c3bd9bb8235e589f010
+// IV = 58d2240f580a31c1d24948e9
+// CT =
+// AAD =
+// Tag = 15e051a5e4a5f5da6cea92e2ebee5bac
+// PT =
+//
+// Count = 1
+// Key = e5a8123f2e2e007d4e379ba114a2fb66e6613f57c72d4e4f024964053028a831
+// IV = 51e43385bf533e168427e1ad
+// CT =
+// AAD =
+// Tag = 38fe845c66e66bdd884c2aecafd280e6
+// FAIL
+//
+// ...
+//
+// The gcmDecrypt256.rsp file is huge (3.0 MB), so a few test vectors were
+// selected for this unit test.
+
+// Describes a group of test vectors that all have a given key length, IV
+// length, plaintext length, AAD length, and tag length.
+struct TestGroupInfo {
+  size_t key_len;
+  size_t iv_len;
+  size_t pt_len;
+  size_t aad_len;
+  size_t tag_len;
+};
+
+// Each test vector consists of six strings of lowercase hexadecimal digits.
+// The strings may be empty (zero length). A test vector with a nullptr |key|
+// marks the end of an array of test vectors.
+struct TestVector {
+  // Input:
+  const char* key;
+  const char* iv;
+  const char* ct;
+  const char* aad;
+  const char* tag;
+
+  // Expected output:
+  const char* pt;  // An empty string "" means decryption succeeded and
+                   // the plaintext is zero-length. nullptr means decryption
+                   // failed.
+};
+
+const TestGroupInfo test_group_info[] = {
+    {256, 96, 0, 0, 128},     {256, 96, 0, 128, 128},   {256, 96, 128, 0, 128},
+    {256, 96, 408, 160, 128}, {256, 96, 408, 720, 128}, {256, 96, 104, 0, 128},
+};
+
+const TestVector test_group_0[] = {
+    {"f5a2b27c74355872eb3ef6c5feafaa740e6ae990d9d48c3bd9bb8235e589f010",
+     "58d2240f580a31c1d24948e9", "", "", "15e051a5e4a5f5da6cea92e2ebee5bac",
+     ""},
+    {
+        "e5a8123f2e2e007d4e379ba114a2fb66e6613f57c72d4e4f024964053028a831",
+        "51e43385bf533e168427e1ad", "", "", "38fe845c66e66bdd884c2aecafd280e6",
+        nullptr  // FAIL
+    },
+    {nullptr}};
+
+const TestVector test_group_1[] = {
+    {"6dfdafd6703c285c01f14fd10a6012862b2af950d4733abb403b2e745b26945d",
+     "3749d0b3d5bacb71be06ade6", "", "c0d249871992e70302ae008193d1e89f",
+     "4aa4cc69f84ee6ac16d9bfb4e05de500", ""},
+    {
+        "2c392a5eb1a9c705371beda3a901c7c61dca4d93b4291de1dd0dd15ec11ffc45",
+        "0723fb84a08f4ea09841f32a", "", "140be561b6171eab942c486a94d33d43",
+        "aa0e1c9b57975bfc91aa137231977d2c", nullptr  // FAIL
+    },
+    {nullptr}};
+
+const TestVector test_group_2[] = {
+    {"4c8ebfe1444ec1b2d503c6986659af2c94fafe945f72c1e8486a5acfedb8a0f8",
+     "473360e0ad24889959858995", "d2c78110ac7e8f107c0df0570bd7c90c", "",
+     "c26a379b6d98ef2852ead8ce83a833a7", "7789b41cb3ee548814ca0b388c10b343"},
+    {"3934f363fd9f771352c4c7a060682ed03c2864223a1573b3af997e2ababd60ab",
+     "efe2656d878c586e41c539c4", "e0de64302ac2d04048d65a87d2ad09fe", "",
+     "33cbd8d2fb8a3a03e30c1eb1b53c1d99", "697aff2d6b77e5ed6232770e400c1ead"},
+    {
+        "c997768e2d14e3d38259667a6649079de77beb4543589771e5068e6cd7cd0b14",
+        "835090aed9552dbdd45277e2", "9f6607d68e22ccf21928db0986be126e", "",
+        "f32617f67c574fd9f44ef76ff880ab9f", nullptr  // FAIL
+    },
+    {nullptr}};
+
+const TestVector test_group_3[] = {
+    {
+        "e9d381a9c413bee66175d5586a189836e5c20f5583535ab4d3f3e612dc21700e",
+        "23e81571da1c7821c681c7ca",
+        "a25f3f580306cd5065d22a6b7e9660110af7204bb77d370f7f34bee547feeff7b32a59"
+        "6fce29c9040e68b1589aad48da881990",
+        "6f39c9ae7b8e8a58a95f0dd8ea6a9087cbccdfd6",
+        "5b6dcd70eefb0892fab1539298b92a4b",
+        nullptr  // FAIL
+    },
+    {"6450d4501b1e6cfbe172c4c8570363e96b496591b842661c28c2f6c908379cad",
+     "7e4262035e0bf3d60e91668a",
+     "5a99b336fd3cfd82f10fb08f7045012415f0d9a06bb92dcf59c6f0dbe62d433671aacb8a1"
+     "c52ce7bbf6aea372bf51e2ba79406",
+     "f1c522f026e4c5d43851da516a1b78768ab18171",
+     "fe93b01636f7bb0458041f213e98de65",
+     "17449e236ef5858f6d891412495ead4607bfae2a2d735182a2a0242f9d52fc5345ef912db"
+     "e16f3bb4576fe3bcafe336dee6085"},
+    {"90f2e71ccb1148979cb742efc8f921de95457d898c84ce28edeed701650d3a26",
+     "aba58ad60047ba553f6e4c98",
+     "3fc77a5fe9203d091c7916587c9763cf2e4d0d53ca20b078b851716f1dab4873fe342b7b3"
+     "01402f015d00263bf3f77c58a99d6",
+     "2abe465df6e5be47f05b92c9a93d76ae3611fac5",
+     "9cb3d04637048bc0bddef803ffbb56cf",
+     "1d21639640e11638a2769e3fab78778f84be3f4a8ce28dfd99cb2e75171e05ea8e94e30aa"
+     "78b54bb402b39d613616a8ed951dc"},
+    {nullptr}};
+
+const TestVector test_group_4[] = {
+    {
+        "e36aca93414b13f5313e76a7244588ee116551d1f34c32859166f2eb0ac1a9b7",
+        "e9e701b1ccef6bddd03391d8",
+        "5b059ac6733b6de0e8cf5b88b7301c02c993426f71bb12abf692e9deeacfac1ff1644c"
+        "87d4df130028f515f0feda636309a24d",
+        "6a08fe6e55a08f283cec4c4b37676e770f402af6102f548ad473ec6236da764f7076ff"
+        "d41bbd9611b439362d899682b7b0f839fc5a68d9df54afd1e2b3c4e7d072454ee27111"
+        "d52193d28b9c4f925d2a8b451675af39191a2cba",
+        "43c7c9c93cc265fc8e192000e0417b5b",
+        nullptr  // FAIL
+    },
+    {"5f72046245d3f4a0877e50a86554bfd57d1c5e073d1ed3b5451f6d0fc2a8507a",
+     "ea6f5b391e44b751b26bce6f",
+     "0e6e0b2114c40769c15958d965a14dcf50b680e0185a4409d77d894ca15b1e698dd83b353"
+     "6b18c05d8cd0873d1edce8150ecb5",
+     "9b3a68c941d42744673fb60fea49075eae77322e7e70e34502c115b6495ebfc796d629080"
+     "7653c6b53cd84281bd0311656d0013f44619d2748177e99e8f8347c989a7b59f9d8dcf00f"
+     "31db0684a4a83e037e8777bae55f799b0d",
+     "fdaaff86ceb937502cd9012d03585800",
+     "b0a881b751cc1eb0c912a4cf9bd971983707dbd2411725664503455c55db25cdb19bc669c"
+     "2654a3a8011de6bf7eff3f9f07834"},
+    {"ab639bae205547607506522bd3cdca7861369e2b42ef175ff135f6ba435d5a8e",
+     "5fbb63eb44bd59fee458d8f6",
+     "9a34c62bed0972285503a32812877187a54dedbd55d2317fed89282bf1af4ba0b6bb9f9e1"
+     "6dd86da3b441deb7841262bc6bd63",
+     "1ef2b1768b805587935ffaf754a11bd2a305076d6374f1f5098b1284444b78f55408a786d"
+     "a37e1b7f1401c330d3585ef56f3e4d35eaaac92e1381d636477dc4f4beaf559735e902d6b"
+     "e58723257d4ac1ed9bd213de387f35f3c4",
+     "e0299e079bff46fd12e36d1c60e41434",
+     "e5a3ce804a8516cdd12122c091256b789076576040dbf3c55e8be3c016025896b8a72532b"
+     "fd51196cc82efca47aa0fd8e2e0dc"},
+    {nullptr}};
+
+const TestVector test_group_5[] = {
+    {
+        "8b37c4b8cf634704920059866ad96c49e9da502c63fca4a3a7a4dcec74cb0610",
+        "cb59344d2b06c4ae57cd0ea4", "66ab935c93555e786b775637a3", "",
+        "d8733acbb564d8afaa99d7ca2e2f92a9", nullptr  // FAIL
+    },
+    {"a71dac1377a3bf5d7fb1b5e36bee70d2e01de2a84a1c1009ba7448f7f26131dc",
+     "c5b60dda3f333b1146e9da7c", "43af49ec1ae3738a20755034d6", "",
+     "6f80b6ef2d8830a55eb63680a8dff9e0", "5b87141335f2becac1a559e05f"},
+    {"dc1f64681014be221b00793bbcf5a5bc675b968eb7a3a3d5aa5978ef4fa45ecc",
+     "056ae9a1a69e38af603924fe", "33013a48d9ea0df2911d583271", "",
+     "5b8f9cc22303e979cd1524187e9f70fe", "2a7e05612191c8bce2f529dca9"},
+    {nullptr}};
+
+const TestVector* const test_group_array[] = {
+    test_group_0, test_group_1, test_group_2,
+    test_group_3, test_group_4, test_group_5,
+};
+
+}  // namespace
+
+namespace net {
+namespace test {
+
+// DecryptWithNonce wraps the |Decrypt| method of |decrypter| to allow passing
+// in an nonce and also to allocate the buffer needed for the plaintext.
+QuicData* DecryptWithNonce(Aes256GcmDecrypter* decrypter,
+                           QuicStringPiece nonce,
+                           QuicStringPiece associated_data,
+                           QuicStringPiece ciphertext) {
+  decrypter->SetIV(nonce);
+  std::unique_ptr<char[]> output(new char[ciphertext.length()]);
+  size_t output_length = 0;
+  const bool success = decrypter->DecryptPacket(
+      QuicVersionMax(), 0, associated_data, ciphertext, output.get(),
+      &output_length, ciphertext.length());
+  if (!success) {
+    return nullptr;
+  }
+  return new QuicData(output.release(), output_length, true);
+}
+
+class Aes256GcmDecrypterTest : public QuicTest {};
+
+TEST_F(Aes256GcmDecrypterTest, Decrypt) {
+  for (size_t i = 0; i < arraysize(test_group_array); i++) {
+    SCOPED_TRACE(i);
+    const TestVector* test_vectors = test_group_array[i];
+    const TestGroupInfo& test_info = test_group_info[i];
+    for (size_t j = 0; test_vectors[j].key != nullptr; j++) {
+      // If not present then decryption is expected to fail.
+      bool has_pt = test_vectors[j].pt;
+
+      // Decode the test vector.
+      string key = QuicTextUtils::HexDecode(test_vectors[j].key);
+      string iv = QuicTextUtils::HexDecode(test_vectors[j].iv);
+      string ct = QuicTextUtils::HexDecode(test_vectors[j].ct);
+      string aad = QuicTextUtils::HexDecode(test_vectors[j].aad);
+      string tag = QuicTextUtils::HexDecode(test_vectors[j].tag);
+      string pt;
+      if (has_pt) {
+        pt = QuicTextUtils::HexDecode(test_vectors[j].pt);
+      }
+
+      // The test vector's lengths should look sane. Note that the lengths
+      // in |test_info| are in bits.
+      EXPECT_EQ(test_info.key_len, key.length() * 8);
+      EXPECT_EQ(test_info.iv_len, iv.length() * 8);
+      EXPECT_EQ(test_info.pt_len, ct.length() * 8);
+      EXPECT_EQ(test_info.aad_len, aad.length() * 8);
+      EXPECT_EQ(test_info.tag_len, tag.length() * 8);
+      if (has_pt) {
+        EXPECT_EQ(test_info.pt_len, pt.length() * 8);
+      }
+      string ciphertext = ct + tag;
+
+      Aes256GcmDecrypter decrypter;
+      ASSERT_TRUE(decrypter.SetKey(key));
+
+      std::unique_ptr<QuicData> decrypted(DecryptWithNonce(
+          &decrypter, iv,
+          // This deliberately tests that the decrypter can handle an AAD that
+          // is set to nullptr, as opposed to a zero-length, non-nullptr
+          // pointer.
+          aad.length() ? aad : QuicStringPiece(), ciphertext));
+      if (!decrypted.get()) {
+        EXPECT_FALSE(has_pt);
+        continue;
+      }
+      EXPECT_TRUE(has_pt);
+
+      ASSERT_EQ(pt.length(), decrypted->length());
+      test::CompareCharArraysWithHexError("plaintext", decrypted->data(),
+                                          pt.length(), pt.data(), pt.length());
+    }
+  }
+}
+
+}  // namespace test
+}  // namespace net
diff --git a/net/quic/core/crypto/aes_256_gcm_encrypter.cc b/net/quic/core/crypto/aes_256_gcm_encrypter.cc
new file mode 100644
index 0000000..4d146a75
--- /dev/null
+++ b/net/quic/core/crypto/aes_256_gcm_encrypter.cc
@@ -0,0 +1,31 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/core/crypto/aes_256_gcm_encrypter.h"
+
+#include "third_party/boringssl/src/include/openssl/evp.h"
+
+namespace net {
+
+namespace {
+
+const size_t kKeySize = 32;
+const size_t kNoncePrefixSize = 4;
+
+}  // namespace
+
+Aes256GcmEncrypter::Aes256GcmEncrypter()
+    : AeadBaseEncrypter(EVP_aead_aes_256_gcm(),
+                        kKeySize,
+                        kAuthTagSize,
+                        kNoncePrefixSize,
+                        /* use_ietf_nonce_construction */ true) {
+  static_assert(kKeySize <= kMaxKeySize, "key size too big");
+  static_assert(kNoncePrefixSize <= kMaxNoncePrefixSize,
+                "nonce prefix size too big");
+}
+
+Aes256GcmEncrypter::~Aes256GcmEncrypter() {}
+
+}  // namespace net
diff --git a/net/quic/core/crypto/aes_256_gcm_encrypter.h b/net/quic/core/crypto/aes_256_gcm_encrypter.h
new file mode 100644
index 0000000..f648a1ea
--- /dev/null
+++ b/net/quic/core/crypto/aes_256_gcm_encrypter.h
@@ -0,0 +1,34 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_QUIC_CORE_CRYPTO_AES_256_GCM_ENCRYPTER_H_
+#define NET_QUIC_CORE_CRYPTO_AES_256_GCM_ENCRYPTER_H_
+
+#include "base/macros.h"
+#include "net/quic/core/crypto/aead_base_encrypter.h"
+#include "net/quic/platform/api/quic_export.h"
+
+namespace net {
+
+// An Aes256GcmEncrypter is a QuicEncrypter that implements the
+// AEAD_AES_256_GCM algorithm specified in RFC 5116 for use in IETF QUIC.
+//
+// It uses an authentication tag of 16 bytes (128 bits). It uses a 12 byte IV
+// that is XOR'd with the packet number to compute the nonce.
+class QUIC_EXPORT_PRIVATE Aes256GcmEncrypter : public AeadBaseEncrypter {
+ public:
+  enum {
+    kAuthTagSize = 16,
+  };
+
+  Aes256GcmEncrypter();
+  ~Aes256GcmEncrypter() override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(Aes256GcmEncrypter);
+};
+
+}  // namespace net
+
+#endif  // NET_QUIC_CORE_CRYPTO_AES_256_GCM_ENCRYPTER_H_
diff --git a/net/quic/core/crypto/aes_256_gcm_encrypter_test.cc b/net/quic/core/crypto/aes_256_gcm_encrypter_test.cc
new file mode 100644
index 0000000..16683cc
--- /dev/null
+++ b/net/quic/core/crypto/aes_256_gcm_encrypter_test.cc
@@ -0,0 +1,242 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/core/crypto/aes_256_gcm_encrypter.h"
+
+#include <memory>
+
+#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_test.h"
+#include "net/quic/platform/api/quic_text_utils.h"
+#include "net/quic/test_tools/quic_test_utils.h"
+
+using std::string;
+
+namespace {
+
+// The AES GCM test vectors come from the file gcmEncryptExtIV256.rsp
+// downloaded from
+// https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/CAVP-TESTING-BLOCK-CIPHER-MODES#GCMVS
+// on 2017-09-27. The test vectors in that file look like this:
+//
+// [Keylen = 256]
+// [IVlen = 96]
+// [PTlen = 0]
+// [AADlen = 0]
+// [Taglen = 128]
+//
+// Count = 0
+// Key = b52c505a37d78eda5dd34f20c22540ea1b58963cf8e5bf8ffa85f9f2492505b4
+// IV = 516c33929df5a3284ff463d7
+// PT =
+// AAD =
+// CT =
+// Tag = bdc1ac884d332457a1d2664f168c76f0
+//
+// Count = 1
+// Key = 5fe0861cdc2690ce69b3658c7f26f8458eec1c9243c5ba0845305d897e96ca0f
+// IV = 770ac1a5a3d476d5d96944a1
+// PT =
+// AAD =
+// CT =
+// Tag = 196d691e1047093ca4b3d2ef4baba216
+//
+// ...
+//
+// The gcmEncryptExtIV256.rsp file is huge (3.2 MB), so a few test vectors were
+// selected for this unit test.
+
+// Describes a group of test vectors that all have a given key length, IV
+// length, plaintext length, AAD length, and tag length.
+struct TestGroupInfo {
+  size_t key_len;
+  size_t iv_len;
+  size_t pt_len;
+  size_t aad_len;
+  size_t tag_len;
+};
+
+// Each test vector consists of six strings of lowercase hexadecimal digits.
+// The strings may be empty (zero length). A test vector with a nullptr |key|
+// marks the end of an array of test vectors.
+struct TestVector {
+  const char* key;
+  const char* iv;
+  const char* pt;
+  const char* aad;
+  const char* ct;
+  const char* tag;
+};
+
+const TestGroupInfo test_group_info[] = {
+    {256, 96, 0, 0, 128},     {256, 96, 0, 128, 128},   {256, 96, 128, 0, 128},
+    {256, 96, 408, 160, 128}, {256, 96, 408, 720, 128}, {256, 96, 104, 0, 128},
+};
+
+const TestVector test_group_0[] = {
+    {"b52c505a37d78eda5dd34f20c22540ea1b58963cf8e5bf8ffa85f9f2492505b4",
+     "516c33929df5a3284ff463d7", "", "", "",
+     "bdc1ac884d332457a1d2664f168c76f0"},
+    {"5fe0861cdc2690ce69b3658c7f26f8458eec1c9243c5ba0845305d897e96ca0f",
+     "770ac1a5a3d476d5d96944a1", "", "", "",
+     "196d691e1047093ca4b3d2ef4baba216"},
+    {nullptr}};
+
+const TestVector test_group_1[] = {
+    {"78dc4e0aaf52d935c3c01eea57428f00ca1fd475f5da86a49c8dd73d68c8e223",
+     "d79cf22d504cc793c3fb6c8a", "", "b96baa8c1c75a671bfb2d08d06be5f36", "",
+     "3e5d486aa2e30b22e040b85723a06e76"},
+    {"4457ff33683cca6ca493878bdc00373893a9763412eef8cddb54f91318e0da88",
+     "699d1f29d7b8c55300bb1fd2", "", "6749daeea367d0e9809e2dc2f309e6e3", "",
+     "d60c74d2517fde4a74e0cd4709ed43a9"},
+    {nullptr}};
+
+const TestVector test_group_2[] = {
+    {"31bdadd96698c204aa9ce1448ea94ae1fb4a9a0b3c9d773b51bb1822666b8f22",
+     "0d18e06c7c725ac9e362e1ce", "2db5168e932556f8089a0622981d017d", "",
+     "fa4362189661d163fcd6a56d8bf0405a", "d636ac1bbedd5cc3ee727dc2ab4a9489"},
+    {"460fc864972261c2560e1eb88761ff1c992b982497bd2ac36c04071cbb8e5d99",
+     "8a4a16b9e210eb68bcb6f58d", "99e4e926ffe927f691893fb79a96b067", "",
+     "133fc15751621b5f325c7ff71ce08324", "ec4e87e0cf74a13618d0b68636ba9fa7"},
+    {nullptr}};
+
+const TestVector test_group_3[] = {
+    {"24501ad384e473963d476edcfe08205237acfd49b5b8f33857f8114e863fec7f",
+     "9ff18563b978ec281b3f2794",
+     "27f348f9cdc0c5bd5e66b1ccb63ad920ff2219d14e8d631b3872265cf117ee86757accb15"
+     "8bd9abb3868fdc0d0b074b5f01b2c",
+     "adb5ec720ccf9898500028bf34afccbcaca126ef",
+     "eb7cb754c824e8d96f7c6d9b76c7d26fb874ffbf1d65c6f64a698d839b0b06145dae82057"
+     "ad55994cf59ad7f67c0fa5e85fab8",
+     "bc95c532fecc594c36d1550286a7a3f0"},
+    {"fb43f5ab4a1738a30c1e053d484a94254125d55dccee1ad67c368bc1a985d235",
+     "9fbb5f8252db0bca21f1c230",
+     "34b797bb82250e23c5e796db2c37e488b3b99d1b981cea5e5b0c61a0b39adb6bd6ef1f507"
+     "22e2e4f81115cfcf53f842e2a6c08",
+     "98f8ae1735c39f732e2cbee1156dabeb854ec7a2",
+     "871cd53d95a8b806bd4821e6c4456204d27fd704ba3d07ce25872dc604ea5c5ea13322186"
+     "b7489db4fa060c1fd4159692612c8",
+     "07b48e4a32fac47e115d7ac7445d8330"},
+    {nullptr}};
+
+const TestVector test_group_4[] = {
+    {"148579a3cbca86d5520d66c0ec71ca5f7e41ba78e56dc6eebd566fed547fe691",
+     "b08a5ea1927499c6ecbfd4e0",
+     "9d0b15fdf1bd595f91f8b3abc0f7dec927dfd4799935a1795d9ce00c9b879434420fe42c2"
+     "75a7cd7b39d638fb81ca52b49dc41",
+     "e4f963f015ffbb99ee3349bbaf7e8e8e6c2a71c230a48f9d59860a29091d2747e01a5ca57"
+     "2347e247d25f56ba7ae8e05cde2be3c97931292c02370208ecd097ef692687fecf2f419d3"
+     "200162a6480a57dad408a0dfeb492e2c5d",
+     "2097e372950a5e9383c675e89eea1c314f999159f5611344b298cda45e62843716f215f82"
+     "ee663919c64002a5c198d7878fd3f",
+     "adbecdb0d5c2224d804d2886ff9a5760"},
+    {"e49af19182faef0ebeeba9f2d3be044e77b1212358366e4ef59e008aebcd9788",
+     "e7f37d79a6a487a5a703edbb",
+     "461cd0caf7427a3d44408d825ed719237272ecd503b9094d1f62c97d63ed83a0b50bdc804"
+     "ffdd7991da7a5b6dcf48d4bcd2cbc",
+     "19a9a1cfc647346781bef51ed9070d05f99a0e0192a223c5cd2522dbdf97d9739dd39fb17"
+     "8ade3339e68774b058aa03e9a20a9a205bc05f32381df4d63396ef691fefd5a71b49a2ad8"
+     "2d5ea428778ca47ee1398792762413cff4",
+     "32ca3588e3e56eb4c8301b009d8b84b8a900b2b88ca3c21944205e9dd7311757b51394ae9"
+     "0d8bb3807b471677614f4198af909",
+     "3e403d035c71d88f1be1a256c89ba6ad"},
+    {nullptr}};
+
+const TestVector test_group_5[] = {
+    {"82c4f12eeec3b2d3d157b0f992d292b237478d2cecc1d5f161389b97f999057a",
+     "7b40b20f5f397177990ef2d1", "982a296ee1cd7086afad976945", "",
+     "ec8e05a0471d6b43a59ca5335f", "113ddeafc62373cac2f5951bb9165249"},
+    {"db4340af2f835a6c6d7ea0ca9d83ca81ba02c29b7410f221cb6071114e393240",
+     "40e438357dd80a85cac3349e", "8ddb3397bd42853193cb0f80c9", "",
+     "b694118c85c41abf69e229cb0f", "c07f1b8aafbd152f697eb67f2a85fe45"},
+    {nullptr}};
+
+const TestVector* const test_group_array[] = {
+    test_group_0, test_group_1, test_group_2,
+    test_group_3, test_group_4, test_group_5,
+};
+
+}  // namespace
+
+namespace net {
+namespace test {
+
+// EncryptWithNonce wraps the |Encrypt| method of |encrypter| to allow passing
+// in an nonce and also to allocate the buffer needed for the ciphertext.
+QuicData* EncryptWithNonce(Aes256GcmEncrypter* encrypter,
+                           QuicStringPiece nonce,
+                           QuicStringPiece associated_data,
+                           QuicStringPiece plaintext) {
+  size_t ciphertext_size = encrypter->GetCiphertextSize(plaintext.length());
+  std::unique_ptr<char[]> ciphertext(new char[ciphertext_size]);
+
+  if (!encrypter->Encrypt(nonce, associated_data, plaintext,
+                          reinterpret_cast<unsigned char*>(ciphertext.get()))) {
+    return nullptr;
+  }
+
+  return new QuicData(ciphertext.release(), ciphertext_size, true);
+}
+
+class Aes256GcmEncrypterTest : public QuicTest {};
+
+TEST_F(Aes256GcmEncrypterTest, Encrypt) {
+  for (size_t i = 0; i < arraysize(test_group_array); i++) {
+    SCOPED_TRACE(i);
+    const TestVector* test_vectors = test_group_array[i];
+    const TestGroupInfo& test_info = test_group_info[i];
+    for (size_t j = 0; test_vectors[j].key != nullptr; j++) {
+      // Decode the test vector.
+      string key = QuicTextUtils::HexDecode(test_vectors[j].key);
+      string iv = QuicTextUtils::HexDecode(test_vectors[j].iv);
+      string pt = QuicTextUtils::HexDecode(test_vectors[j].pt);
+      string aad = QuicTextUtils::HexDecode(test_vectors[j].aad);
+      string ct = QuicTextUtils::HexDecode(test_vectors[j].ct);
+      string tag = QuicTextUtils::HexDecode(test_vectors[j].tag);
+
+      // The test vector's lengths should look sane. Note that the lengths
+      // in |test_info| are in bits.
+      EXPECT_EQ(test_info.key_len, key.length() * 8);
+      EXPECT_EQ(test_info.iv_len, iv.length() * 8);
+      EXPECT_EQ(test_info.pt_len, pt.length() * 8);
+      EXPECT_EQ(test_info.aad_len, aad.length() * 8);
+      EXPECT_EQ(test_info.pt_len, ct.length() * 8);
+      EXPECT_EQ(test_info.tag_len, tag.length() * 8);
+
+      Aes256GcmEncrypter encrypter;
+      ASSERT_TRUE(encrypter.SetKey(key));
+      std::unique_ptr<QuicData> encrypted(EncryptWithNonce(
+          &encrypter, iv,
+          // This deliberately tests that the encrypter can handle an AAD that
+          // is set to nullptr, as opposed to a zero-length, non-nullptr
+          // pointer.
+          aad.length() ? aad : QuicStringPiece(), pt));
+      ASSERT_TRUE(encrypted.get());
+
+      ASSERT_EQ(ct.length() + tag.length(), encrypted->length());
+      test::CompareCharArraysWithHexError("ciphertext", encrypted->data(),
+                                          ct.length(), ct.data(), ct.length());
+      test::CompareCharArraysWithHexError(
+          "authentication tag", encrypted->data() + ct.length(), tag.length(),
+          tag.data(), tag.length());
+    }
+  }
+}
+
+TEST_F(Aes256GcmEncrypterTest, GetMaxPlaintextSize) {
+  Aes256GcmEncrypter encrypter;
+  EXPECT_EQ(1000u, encrypter.GetMaxPlaintextSize(1016));
+  EXPECT_EQ(100u, encrypter.GetMaxPlaintextSize(116));
+  EXPECT_EQ(10u, encrypter.GetMaxPlaintextSize(26));
+}
+
+TEST_F(Aes256GcmEncrypterTest, GetCiphertextSize) {
+  Aes256GcmEncrypter encrypter;
+  EXPECT_EQ(1016u, encrypter.GetCiphertextSize(1000));
+  EXPECT_EQ(116u, encrypter.GetCiphertextSize(100));
+  EXPECT_EQ(26u, encrypter.GetCiphertextSize(10));
+}
+
+}  // namespace test
+}  // namespace net
diff --git a/net/quic/core/crypto/chacha20_poly1305_decrypter.cc b/net/quic/core/crypto/chacha20_poly1305_decrypter.cc
index c734cb4c..0c5a2667 100644
--- a/net/quic/core/crypto/chacha20_poly1305_decrypter.cc
+++ b/net/quic/core/crypto/chacha20_poly1305_decrypter.cc
@@ -22,7 +22,8 @@
     : AeadBaseDecrypter(EVP_aead_chacha20_poly1305(),
                         kKeySize,
                         kAuthTagSize,
-                        kNoncePrefixSize) {
+                        kNoncePrefixSize,
+                        /* use_ietf_nonce_construction */ false) {
   static_assert(kKeySize <= kMaxKeySize, "key size too big");
   static_assert(kNoncePrefixSize <= kMaxNoncePrefixSize,
                 "nonce prefix size too big");
diff --git a/net/quic/core/crypto/chacha20_poly1305_decrypter.h b/net/quic/core/crypto/chacha20_poly1305_decrypter.h
index ed5532e6..2a45fba 100644
--- a/net/quic/core/crypto/chacha20_poly1305_decrypter.h
+++ b/net/quic/core/crypto/chacha20_poly1305_decrypter.h
@@ -14,13 +14,12 @@
 namespace net {
 
 // A ChaCha20Poly1305Decrypter is a QuicDecrypter that implements the
-// AEAD_CHACHA20_POLY1305 algorithm specified in
-// draft-agl-tls-chacha20poly1305-04, except that it truncates the Poly1305
-// authenticator to 12 bytes. Create an instance by calling
-// QuicDecrypter::Create(kCC12).
+// AEAD_CHACHA20_POLY1305 algorithm specified in RFC 7539, except that
+// it truncates the Poly1305 authenticator to 12 bytes. Create an instance
+// by calling QuicDecrypter::Create(kCC20).
 //
-// It uses an authentication tag of 16 bytes (128 bits). There is no
-// fixed nonce prefix.
+// It uses an authentication tag of 12 bytes (96 bits). The fixed prefix of the
+// nonce is four bytes.
 class QUIC_EXPORT_PRIVATE ChaCha20Poly1305Decrypter : public AeadBaseDecrypter {
  public:
   enum {
diff --git a/net/quic/core/crypto/chacha20_poly1305_encrypter.cc b/net/quic/core/crypto/chacha20_poly1305_encrypter.cc
index 520ed17..54de72c9 100644
--- a/net/quic/core/crypto/chacha20_poly1305_encrypter.cc
+++ b/net/quic/core/crypto/chacha20_poly1305_encrypter.cc
@@ -19,7 +19,8 @@
     : AeadBaseEncrypter(EVP_aead_chacha20_poly1305(),
                         kKeySize,
                         kAuthTagSize,
-                        kNoncePrefixSize) {
+                        kNoncePrefixSize,
+                        /* use_ietf_nonce_construction */ false) {
   static_assert(kKeySize <= kMaxKeySize, "key size too big");
   static_assert(kNoncePrefixSize <= kMaxNoncePrefixSize,
                 "nonce prefix size too big");
diff --git a/net/quic/core/crypto/chacha20_poly1305_encrypter.h b/net/quic/core/crypto/chacha20_poly1305_encrypter.h
index dd4d4a6..90729013 100644
--- a/net/quic/core/crypto/chacha20_poly1305_encrypter.h
+++ b/net/quic/core/crypto/chacha20_poly1305_encrypter.h
@@ -14,10 +14,10 @@
 // A ChaCha20Poly1305Encrypter is a QuicEncrypter that implements the
 // AEAD_CHACHA20_POLY1305 algorithm specified in RFC 7539, except that
 // it truncates the Poly1305 authenticator to 12 bytes. Create an instance
-// by calling QuicEncrypter::Create(kCC12).
+// by calling QuicEncrypter::Create(kCC20).
 //
-// It uses an authentication tag of 16 bytes (128 bits). There is no
-// fixed nonce prefix.
+// It uses an authentication tag of 12 bytes (96 bits). The fixed prefix of the
+// nonce is four bytes.
 class QUIC_EXPORT_PRIVATE ChaCha20Poly1305Encrypter : public AeadBaseEncrypter {
  public:
   enum {
diff --git a/net/quic/core/crypto/chacha20_poly1305_tls_decrypter.cc b/net/quic/core/crypto/chacha20_poly1305_tls_decrypter.cc
new file mode 100644
index 0000000..bef248a
--- /dev/null
+++ b/net/quic/core/crypto/chacha20_poly1305_tls_decrypter.cc
@@ -0,0 +1,38 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/core/crypto/chacha20_poly1305_tls_decrypter.h"
+
+#include "net/quic/platform/api/quic_flag_utils.h"
+#include "net/quic/platform/api/quic_flags.h"
+#include "third_party/boringssl/src/include/openssl/aead.h"
+#include "third_party/boringssl/src/include/openssl/tls1.h"
+
+namespace net {
+
+namespace {
+
+const size_t kKeySize = 32;
+const size_t kNoncePrefixSize = 4;
+
+}  // namespace
+
+ChaCha20Poly1305TlsDecrypter::ChaCha20Poly1305TlsDecrypter()
+    : AeadBaseDecrypter(EVP_aead_chacha20_poly1305(),
+                        kKeySize,
+                        kAuthTagSize,
+                        kNoncePrefixSize,
+                        /* use_ietf_nonce_construction */ true) {
+  static_assert(kKeySize <= kMaxKeySize, "key size too big");
+  static_assert(kNoncePrefixSize <= kMaxNoncePrefixSize,
+                "nonce prefix size too big");
+}
+
+ChaCha20Poly1305TlsDecrypter::~ChaCha20Poly1305TlsDecrypter() {}
+
+uint32_t ChaCha20Poly1305TlsDecrypter::cipher_id() const {
+  return TLS1_CK_CHACHA20_POLY1305_SHA256;
+}
+
+}  // namespace net
diff --git a/net/quic/core/crypto/chacha20_poly1305_tls_decrypter.h b/net/quic/core/crypto/chacha20_poly1305_tls_decrypter.h
new file mode 100644
index 0000000..85dcb750
--- /dev/null
+++ b/net/quic/core/crypto/chacha20_poly1305_tls_decrypter.h
@@ -0,0 +1,39 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_QUIC_CORE_CRYPTO_CHACHA20_POLY1305_TLS_DECRYPTER_H_
+#define NET_QUIC_CORE_CRYPTO_CHACHA20_POLY1305_TLS_DECRYPTER_H_
+
+#include <cstdint>
+
+#include "base/macros.h"
+#include "net/quic/core/crypto/aead_base_decrypter.h"
+#include "net/quic/platform/api/quic_export.h"
+
+namespace net {
+
+// A ChaCha20Poly1305TlsDecrypter is a QuicDecrypter that implements the
+// AEAD_CHACHA20_POLY1305 algorithm specified in RFC 7539 for use in IETF QUIC.
+//
+// It uses an authentication tag of 16 bytes (128 bits). It uses a 12 bytes IV
+// that is XOR'd with the packet number to compute the nonce.
+class QUIC_EXPORT_PRIVATE ChaCha20Poly1305TlsDecrypter
+    : public AeadBaseDecrypter {
+ public:
+  enum {
+    kAuthTagSize = 16,
+  };
+
+  ChaCha20Poly1305TlsDecrypter();
+  ~ChaCha20Poly1305TlsDecrypter() override;
+
+  uint32_t cipher_id() const override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ChaCha20Poly1305TlsDecrypter);
+};
+
+}  // namespace net
+
+#endif  // NET_QUIC_CORE_CRYPTO_CHACHA20_POLY1305_TLS_DECRYPTER_H_
diff --git a/net/quic/core/crypto/chacha20_poly1305_tls_decrypter_test.cc b/net/quic/core/crypto/chacha20_poly1305_tls_decrypter_test.cc
new file mode 100644
index 0000000..910f53e
--- /dev/null
+++ b/net/quic/core/crypto/chacha20_poly1305_tls_decrypter_test.cc
@@ -0,0 +1,172 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/core/crypto/chacha20_poly1305_tls_decrypter.h"
+
+#include <memory>
+
+#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_test.h"
+#include "net/quic/platform/api/quic_text_utils.h"
+#include "net/quic/test_tools/quic_test_utils.h"
+
+using std::string;
+
+namespace {
+
+// The test vectors come from RFC 7539 Section 2.8.2.
+
+// Each test vector consists of six strings of lowercase hexadecimal digits.
+// The strings may be empty (zero length). A test vector with a nullptr |key|
+// marks the end of an array of test vectors.
+struct TestVector {
+  // Input:
+  const char* key;
+  const char* iv;
+  const char* fixed;
+  const char* aad;
+  const char* ct;
+
+  // Expected output:
+  const char* pt;  // An empty string "" means decryption succeeded and
+                   // the plaintext is zero-length. nullptr means decryption
+                   // failed.
+};
+
+const TestVector test_vectors[] = {
+    {"808182838485868788898a8b8c8d8e8f"
+     "909192939495969798999a9b9c9d9e9f",
+
+     "4041424344454647",
+
+     "07000000",
+
+     "50515253c0c1c2c3c4c5c6c7",
+
+     "d31a8d34648e60db7b86afbc53ef7ec2"
+     "a4aded51296e08fea9e2b5a736ee62d6"
+     "3dbea45e8ca9671282fafb69da92728b"
+     "1a71de0a9e060b2905d6a5b67ecd3b36"
+     "92ddbd7f2d778b8c9803aee328091b58"
+     "fab324e4fad675945585808b4831d7bc"
+     "3ff4def08e4b7a9de576d26586cec64b"
+     "6116"
+     "1ae10b594f09e26a7e902ecbd0600691",
+
+     "4c616469657320616e642047656e746c"
+     "656d656e206f662074686520636c6173"
+     "73206f66202739393a20496620492063"
+     "6f756c64206f6666657220796f75206f"
+     "6e6c79206f6e652074697020666f7220"
+     "746865206675747572652c2073756e73"
+     "637265656e20776f756c642062652069"
+     "742e"},
+    // Modify the ciphertext (Poly1305 authenticator).
+    {"808182838485868788898a8b8c8d8e8f"
+     "909192939495969798999a9b9c9d9e9f",
+
+     "4041424344454647",
+
+     "07000000",
+
+     "50515253c0c1c2c3c4c5c6c7",
+
+     "d31a8d34648e60db7b86afbc53ef7ec2"
+     "a4aded51296e08fea9e2b5a736ee62d6"
+     "3dbea45e8ca9671282fafb69da92728b"
+     "1a71de0a9e060b2905d6a5b67ecd3b36"
+     "92ddbd7f2d778b8c9803aee328091b58"
+     "fab324e4fad675945585808b4831d7bc"
+     "3ff4def08e4b7a9de576d26586cec64b"
+     "6116"
+     "1ae10b594f09e26a7e902eccd0600691",
+
+     nullptr},
+    // Modify the associated data.
+    {"808182838485868788898a8b8c8d8e8f"
+     "909192939495969798999a9b9c9d9e9f",
+
+     "4041424344454647",
+
+     "07000000",
+
+     "60515253c0c1c2c3c4c5c6c7",
+
+     "d31a8d34648e60db7b86afbc53ef7ec2"
+     "a4aded51296e08fea9e2b5a736ee62d6"
+     "3dbea45e8ca9671282fafb69da92728b"
+     "1a71de0a9e060b2905d6a5b67ecd3b36"
+     "92ddbd7f2d778b8c9803aee328091b58"
+     "fab324e4fad675945585808b4831d7bc"
+     "3ff4def08e4b7a9de576d26586cec64b"
+     "6116"
+     "1ae10b594f09e26a7e902ecbd0600691",
+
+     nullptr},
+    {nullptr}};
+
+}  // namespace
+
+namespace net {
+namespace test {
+
+// DecryptWithNonce wraps the |Decrypt| method of |decrypter| to allow passing
+// in an nonce and also to allocate the buffer needed for the plaintext.
+QuicData* DecryptWithNonce(ChaCha20Poly1305TlsDecrypter* decrypter,
+                           QuicStringPiece nonce,
+                           QuicStringPiece associated_data,
+                           QuicStringPiece ciphertext) {
+  decrypter->SetIV(nonce);
+  std::unique_ptr<char[]> output(new char[ciphertext.length()]);
+  size_t output_length = 0;
+  const bool success = decrypter->DecryptPacket(
+      QuicVersionMax(), 0, associated_data, ciphertext, output.get(),
+      &output_length, ciphertext.length());
+  if (!success) {
+    return nullptr;
+  }
+  return new QuicData(output.release(), output_length, true);
+}
+
+class ChaCha20Poly1305TlsDecrypterTest : public QuicTest {};
+
+TEST_F(ChaCha20Poly1305TlsDecrypterTest, Decrypt) {
+  for (size_t i = 0; test_vectors[i].key != nullptr; i++) {
+    // If not present then decryption is expected to fail.
+    bool has_pt = test_vectors[i].pt;
+
+    // Decode the test vector.
+    string key = QuicTextUtils::HexDecode(test_vectors[i].key);
+    string iv = QuicTextUtils::HexDecode(test_vectors[i].iv);
+    string fixed = QuicTextUtils::HexDecode(test_vectors[i].fixed);
+    string aad = QuicTextUtils::HexDecode(test_vectors[i].aad);
+    string ct = QuicTextUtils::HexDecode(test_vectors[i].ct);
+    string pt;
+    if (has_pt) {
+      pt = QuicTextUtils::HexDecode(test_vectors[i].pt);
+    }
+
+    ChaCha20Poly1305TlsDecrypter decrypter;
+    ASSERT_TRUE(decrypter.SetKey(key));
+    std::unique_ptr<QuicData> decrypted(DecryptWithNonce(
+        &decrypter, fixed + iv,
+        // This deliberately tests that the decrypter can handle an AAD that
+        // is set to nullptr, as opposed to a zero-length, non-nullptr pointer.
+        QuicStringPiece(aad.length() ? aad.data() : nullptr, aad.length()),
+        ct));
+    if (!decrypted.get()) {
+      EXPECT_FALSE(has_pt);
+      continue;
+    }
+    EXPECT_TRUE(has_pt);
+
+    EXPECT_EQ(16u, ct.size() - decrypted->length());
+    ASSERT_EQ(pt.length(), decrypted->length());
+    test::CompareCharArraysWithHexError("plaintext", decrypted->data(),
+                                        pt.length(), pt.data(), pt.length());
+  }
+}
+
+}  // namespace test
+}  // namespace net
diff --git a/net/quic/core/crypto/chacha20_poly1305_tls_encrypter.cc b/net/quic/core/crypto/chacha20_poly1305_tls_encrypter.cc
new file mode 100644
index 0000000..d9fb477
--- /dev/null
+++ b/net/quic/core/crypto/chacha20_poly1305_tls_encrypter.cc
@@ -0,0 +1,31 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/core/crypto/chacha20_poly1305_tls_encrypter.h"
+
+#include "third_party/boringssl/src/include/openssl/evp.h"
+
+namespace net {
+
+namespace {
+
+const size_t kKeySize = 32;
+const size_t kNoncePrefixSize = 4;
+
+}  // namespace
+
+ChaCha20Poly1305TlsEncrypter::ChaCha20Poly1305TlsEncrypter()
+    : AeadBaseEncrypter(EVP_aead_chacha20_poly1305(),
+                        kKeySize,
+                        kAuthTagSize,
+                        kNoncePrefixSize,
+                        /* use_ietf_nonce_construction */ true) {
+  static_assert(kKeySize <= kMaxKeySize, "key size too big");
+  static_assert(kNoncePrefixSize <= kMaxNoncePrefixSize,
+                "nonce prefix size too big");
+}
+
+ChaCha20Poly1305TlsEncrypter::~ChaCha20Poly1305TlsEncrypter() {}
+
+}  // namespace net
diff --git a/net/quic/core/crypto/chacha20_poly1305_tls_encrypter.h b/net/quic/core/crypto/chacha20_poly1305_tls_encrypter.h
new file mode 100644
index 0000000..a6674ba
--- /dev/null
+++ b/net/quic/core/crypto/chacha20_poly1305_tls_encrypter.h
@@ -0,0 +1,35 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_QUIC_CORE_CRYPTO_CHACHA20_POLY1305_TLS_ENCRYPTER_H_
+#define NET_QUIC_CORE_CRYPTO_CHACHA20_POLY1305_TLS_ENCRYPTER_H_
+
+#include "base/macros.h"
+#include "net/quic/core/crypto/aead_base_encrypter.h"
+#include "net/quic/platform/api/quic_export.h"
+
+namespace net {
+
+// A ChaCha20Poly1305Encrypter is a QuicEncrypter that implements the
+// AEAD_CHACHA20_POLY1305 algorithm specified in RFC 7539 for use in IETF QUIC.
+//
+// It uses an authentication tag of 16 bytes (128 bits). It uses a 12 byte IV
+// that is XOR'd with the packet number to compute the nonce.
+class QUIC_EXPORT_PRIVATE ChaCha20Poly1305TlsEncrypter
+    : public AeadBaseEncrypter {
+ public:
+  enum {
+    kAuthTagSize = 16,
+  };
+
+  ChaCha20Poly1305TlsEncrypter();
+  ~ChaCha20Poly1305TlsEncrypter() override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ChaCha20Poly1305TlsEncrypter);
+};
+
+}  // namespace net
+
+#endif  // NET_QUIC_CORE_CRYPTO_CHACHA20_POLY1305_TLS_ENCRYPTER_H_
diff --git a/net/quic/core/crypto/chacha20_poly1305_tls_encrypter_test.cc b/net/quic/core/crypto/chacha20_poly1305_tls_encrypter_test.cc
new file mode 100644
index 0000000..c475176
--- /dev/null
+++ b/net/quic/core/crypto/chacha20_poly1305_tls_encrypter_test.cc
@@ -0,0 +1,156 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/core/crypto/chacha20_poly1305_tls_encrypter.h"
+
+#include <memory>
+
+#include "net/quic/core/crypto/chacha20_poly1305_tls_decrypter.h"
+#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_test.h"
+#include "net/quic/platform/api/quic_text_utils.h"
+#include "net/quic/test_tools/quic_test_utils.h"
+
+using std::string;
+
+namespace {
+
+// The test vectors come from RFC 7539 Section 2.8.2.
+
+// Each test vector consists of five strings of lowercase hexadecimal digits.
+// The strings may be empty (zero length). A test vector with a nullptr |key|
+// marks the end of an array of test vectors.
+struct TestVector {
+  const char* key;
+  const char* pt;
+  const char* iv;
+  const char* fixed;
+  const char* aad;
+  const char* ct;
+};
+
+const TestVector test_vectors[] = {{
+                                       "808182838485868788898a8b8c8d8e8f"
+                                       "909192939495969798999a9b9c9d9e9f",
+
+                                       "4c616469657320616e642047656e746c"
+                                       "656d656e206f662074686520636c6173"
+                                       "73206f66202739393a20496620492063"
+                                       "6f756c64206f6666657220796f75206f"
+                                       "6e6c79206f6e652074697020666f7220"
+                                       "746865206675747572652c2073756e73"
+                                       "637265656e20776f756c642062652069"
+                                       "742e",
+
+                                       "4041424344454647",
+
+                                       "07000000",
+
+                                       "50515253c0c1c2c3c4c5c6c7",
+
+                                       "d31a8d34648e60db7b86afbc53ef7ec2"
+                                       "a4aded51296e08fea9e2b5a736ee62d6"
+                                       "3dbea45e8ca9671282fafb69da92728b"
+                                       "1a71de0a9e060b2905d6a5b67ecd3b36"
+                                       "92ddbd7f2d778b8c9803aee328091b58"
+                                       "fab324e4fad675945585808b4831d7bc"
+                                       "3ff4def08e4b7a9de576d26586cec64b"
+                                       "6116"
+                                       "1ae10b594f09e26a7e902ecbd0600691",
+                                   },
+                                   {nullptr}};
+
+}  // namespace
+
+namespace net {
+namespace test {
+
+// EncryptWithNonce wraps the |Encrypt| method of |encrypter| to allow passing
+// in an nonce and also to allocate the buffer needed for the ciphertext.
+QuicData* EncryptWithNonce(ChaCha20Poly1305TlsEncrypter* encrypter,
+                           QuicStringPiece nonce,
+                           QuicStringPiece associated_data,
+                           QuicStringPiece plaintext) {
+  size_t ciphertext_size = encrypter->GetCiphertextSize(plaintext.length());
+  std::unique_ptr<char[]> ciphertext(new char[ciphertext_size]);
+
+  if (!encrypter->Encrypt(nonce, associated_data, plaintext,
+                          reinterpret_cast<unsigned char*>(ciphertext.get()))) {
+    return nullptr;
+  }
+
+  return new QuicData(ciphertext.release(), ciphertext_size, true);
+}
+
+class ChaCha20Poly1305TlsEncrypterTest : public QuicTest {};
+
+TEST_F(ChaCha20Poly1305TlsEncrypterTest, EncryptThenDecrypt) {
+  ChaCha20Poly1305TlsEncrypter encrypter;
+  ChaCha20Poly1305TlsDecrypter decrypter;
+
+  string key = QuicTextUtils::HexDecode(test_vectors[0].key);
+  ASSERT_TRUE(encrypter.SetKey(key));
+  ASSERT_TRUE(decrypter.SetKey(key));
+  ASSERT_TRUE(encrypter.SetIV("abcdefghijkl"));
+  ASSERT_TRUE(decrypter.SetIV("abcdefghijkl"));
+
+  QuicPacketNumber packet_number = UINT64_C(0x123456789ABC);
+  string associated_data = "associated_data";
+  string plaintext = "plaintext";
+  char encrypted[1024];
+  size_t len;
+  ASSERT_TRUE(encrypter.EncryptPacket(QuicVersionMax(), packet_number,
+                                      associated_data, plaintext, encrypted,
+                                      &len, arraysize(encrypted)));
+  QuicStringPiece ciphertext(encrypted, len);
+  char decrypted[1024];
+  ASSERT_TRUE(decrypter.DecryptPacket(QuicVersionMax(), packet_number,
+                                      associated_data, ciphertext, decrypted,
+                                      &len, arraysize(decrypted)));
+}
+
+TEST_F(ChaCha20Poly1305TlsEncrypterTest, Encrypt) {
+  for (size_t i = 0; test_vectors[i].key != nullptr; i++) {
+    // Decode the test vector.
+    string key = QuicTextUtils::HexDecode(test_vectors[i].key);
+    string pt = QuicTextUtils::HexDecode(test_vectors[i].pt);
+    string iv = QuicTextUtils::HexDecode(test_vectors[i].iv);
+    string fixed = QuicTextUtils::HexDecode(test_vectors[i].fixed);
+    string aad = QuicTextUtils::HexDecode(test_vectors[i].aad);
+    string ct = QuicTextUtils::HexDecode(test_vectors[i].ct);
+
+    ChaCha20Poly1305TlsEncrypter encrypter;
+    ASSERT_TRUE(encrypter.SetKey(key));
+    std::unique_ptr<QuicData> encrypted(EncryptWithNonce(
+        &encrypter, fixed + iv,
+        // This deliberately tests that the encrypter can handle an AAD that
+        // is set to nullptr, as opposed to a zero-length, non-nullptr pointer.
+        QuicStringPiece(aad.length() ? aad.data() : nullptr, aad.length()),
+        pt));
+    ASSERT_TRUE(encrypted.get());
+    EXPECT_EQ(16u, ct.size() - pt.size());
+    EXPECT_EQ(16u, encrypted->length() - pt.size());
+
+    test::CompareCharArraysWithHexError("ciphertext", encrypted->data(),
+                                        encrypted->length(), ct.data(),
+                                        ct.length());
+  }
+}
+
+TEST_F(ChaCha20Poly1305TlsEncrypterTest, GetMaxPlaintextSize) {
+  ChaCha20Poly1305TlsEncrypter encrypter;
+  EXPECT_EQ(1000u, encrypter.GetMaxPlaintextSize(1016));
+  EXPECT_EQ(100u, encrypter.GetMaxPlaintextSize(116));
+  EXPECT_EQ(10u, encrypter.GetMaxPlaintextSize(26));
+}
+
+TEST_F(ChaCha20Poly1305TlsEncrypterTest, GetCiphertextSize) {
+  ChaCha20Poly1305TlsEncrypter encrypter;
+  EXPECT_EQ(1016u, encrypter.GetCiphertextSize(1000));
+  EXPECT_EQ(116u, encrypter.GetCiphertextSize(100));
+  EXPECT_EQ(26u, encrypter.GetCiphertextSize(10));
+}
+
+}  // namespace test
+}  // namespace net
diff --git a/net/quic/core/crypto/crypto_handshake_message.cc b/net/quic/core/crypto/crypto_handshake_message.cc
index 3499a553..9081294 100644
--- a/net/quic/core/crypto/crypto_handshake_message.cc
+++ b/net/quic/core/crypto/crypto_handshake_message.cc
@@ -71,10 +71,11 @@
   serialized_.reset();
 }
 
-void CryptoHandshakeMessage::SetVersionVector(QuicTag tag,
-                                              QuicVersionVector versions) {
+void CryptoHandshakeMessage::SetVersionVector(
+    QuicTag tag,
+    QuicTransportVersionVector versions) {
   QuicVersionLabelVector version_labels;
-  for (QuicVersion version : versions) {
+  for (QuicTransportVersion version : versions) {
     if (!FLAGS_quic_reloadable_flag_quic_use_net_byte_order_version_label) {
       version_labels.push_back(QuicVersionToQuicVersionLabel(version));
     } else {
@@ -87,7 +88,8 @@
   SetVector(tag, version_labels);
 }
 
-void CryptoHandshakeMessage::SetVersion(QuicTag tag, QuicVersion version) {
+void CryptoHandshakeMessage::SetVersion(QuicTag tag,
+                                        QuicTransportVersion version) {
   if (!FLAGS_quic_reloadable_flag_quic_use_net_byte_order_version_label) {
     SetValue(tag, QuicVersionToQuicVersionLabel(version));
   } else {
@@ -234,6 +236,11 @@
   return GetPOD(tag, out, sizeof(uint64_t));
 }
 
+QuicErrorCode CryptoHandshakeMessage::GetUint128(QuicTag tag,
+                                                 uint128* out) const {
+  return GetPOD(tag, out, sizeof(uint128));
+}
+
 size_t CryptoHandshakeMessage::size() const {
   size_t ret = sizeof(QuicTag) + sizeof(uint16_t) /* number of entries */ +
                sizeof(uint16_t) /* padding */;
diff --git a/net/quic/core/crypto/crypto_handshake_message.h b/net/quic/core/crypto/crypto_handshake_message.h
index 7e93bcb9..2f22a0dbf 100644
--- a/net/quic/core/crypto/crypto_handshake_message.h
+++ b/net/quic/core/crypto/crypto_handshake_message.h
@@ -11,6 +11,7 @@
 #include <string>
 #include <vector>
 
+#include "net/base/int128.h"
 #include "net/quic/core/quic_packets.h"
 #include "net/quic/platform/api/quic_export.h"
 #include "net/quic/platform/api/quic_string_piece.h"
@@ -61,11 +62,11 @@
 
   // Sets an element with the given tag to the on-the-wire representation of
   // |version|.
-  void SetVersion(QuicTag tag, QuicVersion version);
+  void SetVersion(QuicTag tag, QuicTransportVersion version);
 
   // Sets an element with the given tag to the on-the-wire representation of
   // the elements in |versions|.
-  void SetVersionVector(QuicTag tag, QuicVersionVector versions);
+  void SetVersionVector(QuicTag tag, QuicTransportVersionVector versions);
 
   // Returns the message tag.
   QuicTag tag() const { return tag_; }
@@ -106,6 +107,7 @@
                               QuicStringPiece* out) const;
   QuicErrorCode GetUint32(QuicTag tag, uint32_t* out) const;
   QuicErrorCode GetUint64(QuicTag tag, uint64_t* out) const;
+  QuicErrorCode GetUint128(QuicTag tag, uint128* out) const;
 
   // size returns 4 (message tag) + 2 (uint16_t, number of entries) +
   // (4 (tag) + 4 (end offset))*tag_value_map_.size() + ∑ value sizes.
diff --git a/net/quic/core/crypto/crypto_protocol.h b/net/quic/core/crypto/crypto_protocol.h
index 5a629739..95cac333 100644
--- a/net/quic/core/crypto/crypto_protocol.h
+++ b/net/quic/core/crypto/crypto_protocol.h
@@ -216,6 +216,8 @@
 const QuicTag kCADR = TAG('C', 'A', 'D', 'R');   // Client IP address and port
 const QuicTag kASAD = TAG('A', 'S', 'A', 'D');   // Alternate Server IP address
                                                  // and port.
+const QuicTag kSRST = TAG('S', 'R', 'S', 'T');   // Stateless reset token used
+                                                 // in IETF public reset packet
 
 // CETV tags
 const QuicTag kCIDK = TAG('C', 'I', 'D', 'K');   // ChannelID key
diff --git a/net/quic/core/crypto/crypto_server_test.cc b/net/quic/core/crypto/crypto_server_test.cc
index 2dd719c..346cc2a 100644
--- a/net/quic/core/crypto/crypto_server_test.cc
+++ b/net/quic/core/crypto/crypto_server_test.cc
@@ -57,7 +57,7 @@
 struct TestParams {
   TestParams(bool enable_stateless_rejects,
              bool use_stateless_rejects,
-             QuicVersionVector supported_versions)
+             QuicTransportVersionVector supported_versions)
       : enable_stateless_rejects(enable_stateless_rejects),
         use_stateless_rejects(use_stateless_rejects),
         supported_versions(std::move(supported_versions)) {}
@@ -66,8 +66,8 @@
     os << "  enable_stateless_rejects: " << p.enable_stateless_rejects
        << std::endl;
     os << "  use_stateless_rejects: " << p.use_stateless_rejects << std::endl;
-    os << "  versions: " << QuicVersionVectorToString(p.supported_versions)
-       << " }";
+    os << "  versions: "
+       << QuicTransportVersionVectorToString(p.supported_versions) << " }";
     return os;
   }
 
@@ -79,7 +79,7 @@
   // enable_stateless_rejects is false.
   bool use_stateless_rejects;
   // Versions supported by client and server.
-  QuicVersionVector supported_versions;
+  QuicTransportVersionVector supported_versions;
 };
 
 // Constructs various test permutations.
@@ -89,7 +89,8 @@
   for (bool enable_stateless_rejects : kTrueFalse) {
     for (bool use_stateless_rejects : kTrueFalse) {
       // Start with all versions, remove highest on each iteration.
-      QuicVersionVector supported_versions = AllSupportedVersions();
+      QuicTransportVersionVector supported_versions =
+          AllSupportedTransportVersions();
       while (!supported_versions.empty()) {
         params.push_back(TestParams(enable_stateless_rejects,
                                     use_stateless_rejects, supported_versions));
@@ -393,8 +394,8 @@
   MockRandom rand_for_id_generation_;
   MockClock clock_;
   QuicSocketAddress client_address_;
-  QuicVersionVector supported_versions_;
-  QuicVersion client_version_;
+  QuicTransportVersionVector supported_versions_;
+  QuicTransportVersion client_version_;
   string client_version_string_;
   QuicCryptoServerConfig config_;
   QuicCryptoServerConfigPeer peer_;
diff --git a/net/quic/core/crypto/crypto_utils.cc b/net/quic/core/crypto/crypto_utils.cc
index e348ce7..8cdda7a1 100644
--- a/net/quic/core/crypto/crypto_utils.cc
+++ b/net/quic/core/crypto/crypto_utils.cc
@@ -179,7 +179,7 @@
 
 QuicErrorCode CryptoUtils::ValidateServerHello(
     const CryptoHandshakeMessage& server_hello,
-    const QuicVersionVector& negotiated_versions,
+    const QuicTransportVersionVector& negotiated_versions,
     string* error_details) {
   DCHECK(error_details != nullptr);
 
@@ -214,8 +214,8 @@
 
 QuicErrorCode CryptoUtils::ValidateClientHello(
     const CryptoHandshakeMessage& client_hello,
-    QuicVersion version,
-    const QuicVersionVector& supported_versions,
+    QuicTransportVersion version,
+    const QuicTransportVersionVector& supported_versions,
     string* error_details) {
   if (client_hello.tag() != kCHLO) {
     *error_details = "Bad tag";
@@ -232,7 +232,7 @@
     *error_details = "client hello missing version list";
     return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
   }
-  QuicVersion client_version =
+  QuicTransportVersion client_version =
       QuicVersionLabelToQuicVersion(client_version_label);
   if (client_version != version) {
     // Just because client_version is a valid version enum doesn't mean that
diff --git a/net/quic/core/crypto/crypto_utils.h b/net/quic/core/crypto/crypto_utils.h
index 54f2c73..537f1505 100644
--- a/net/quic/core/crypto/crypto_utils.h
+++ b/net/quic/core/crypto/crypto_utils.h
@@ -124,7 +124,7 @@
   // code and sets |error_details|.
   static QuicErrorCode ValidateServerHello(
       const CryptoHandshakeMessage& server_hello,
-      const QuicVersionVector& negotiated_versions,
+      const QuicTransportVersionVector& negotiated_versions,
       std::string* error_details);
 
   // Validates that |client_hello| is actually a CHLO and that this is not part
@@ -135,8 +135,8 @@
   // code and sets |error_details|.
   static QuicErrorCode ValidateClientHello(
       const CryptoHandshakeMessage& client_hello,
-      QuicVersion version,
-      const QuicVersionVector& supported_versions,
+      QuicTransportVersion version,
+      const QuicTransportVersionVector& supported_versions,
       std::string* error_details);
 
   // Returns the name of the HandshakeFailureReason as a char*
diff --git a/net/quic/core/crypto/null_decrypter.cc b/net/quic/core/crypto/null_decrypter.cc
index fad0ae21..6dc7cad 100644
--- a/net/quic/core/crypto/null_decrypter.cc
+++ b/net/quic/core/crypto/null_decrypter.cc
@@ -26,6 +26,10 @@
   return nonce_prefix.empty();
 }
 
+bool NullDecrypter::SetIV(QuicStringPiece iv) {
+  return iv.empty();
+}
+
 bool NullDecrypter::SetPreliminaryKey(QuicStringPiece key) {
   QUIC_BUG << "Should not be called";
   return false;
@@ -36,7 +40,7 @@
   return true;
 }
 
-bool NullDecrypter::DecryptPacket(QuicVersion version,
+bool NullDecrypter::DecryptPacket(QuicTransportVersion version,
                                   QuicPacketNumber /*packet_number*/,
                                   QuicStringPiece associated_data,
                                   QuicStringPiece ciphertext,
@@ -87,7 +91,7 @@
   return true;
 }
 
-uint128 NullDecrypter::ComputeHash(QuicVersion version,
+uint128 NullDecrypter::ComputeHash(QuicTransportVersion version,
                                    const QuicStringPiece data1,
                                    const QuicStringPiece data2) const {
   uint128 correct_hash;
diff --git a/net/quic/core/crypto/null_decrypter.h b/net/quic/core/crypto/null_decrypter.h
index 01e2f17..63d923b1 100644
--- a/net/quic/core/crypto/null_decrypter.h
+++ b/net/quic/core/crypto/null_decrypter.h
@@ -31,9 +31,10 @@
   // QuicDecrypter implementation
   bool SetKey(QuicStringPiece key) override;
   bool SetNoncePrefix(QuicStringPiece nonce_prefix) override;
+  bool SetIV(QuicStringPiece iv) override;
   bool SetPreliminaryKey(QuicStringPiece key) override;
   bool SetDiversificationNonce(const DiversificationNonce& nonce) override;
-  bool DecryptPacket(QuicVersion version,
+  bool DecryptPacket(QuicTransportVersion version,
                      QuicPacketNumber packet_number,
                      QuicStringPiece associated_data,
                      QuicStringPiece ciphertext,
@@ -47,7 +48,7 @@
 
  private:
   bool ReadHash(QuicDataReader* reader, uint128* hash);
-  uint128 ComputeHash(QuicVersion version,
+  uint128 ComputeHash(QuicTransportVersion version,
                       QuicStringPiece data1,
                       QuicStringPiece data2) const;
 
diff --git a/net/quic/core/crypto/null_encrypter.cc b/net/quic/core/crypto/null_encrypter.cc
index 4d25921d..0cc7f3d8 100644
--- a/net/quic/core/crypto/null_encrypter.cc
+++ b/net/quic/core/crypto/null_encrypter.cc
@@ -24,7 +24,11 @@
   return nonce_prefix.empty();
 }
 
-bool NullEncrypter::EncryptPacket(QuicVersion version,
+bool NullEncrypter::SetIV(QuicStringPiece iv) {
+  return iv.empty();
+}
+
+bool NullEncrypter::EncryptPacket(QuicTransportVersion version,
                                   QuicPacketNumber /*packet_number*/,
                                   QuicStringPiece associated_data,
                                   QuicStringPiece plaintext,
diff --git a/net/quic/core/crypto/null_encrypter.h b/net/quic/core/crypto/null_encrypter.h
index c768c6467..d6f114eb 100644
--- a/net/quic/core/crypto/null_encrypter.h
+++ b/net/quic/core/crypto/null_encrypter.h
@@ -27,7 +27,8 @@
   // QuicEncrypter implementation
   bool SetKey(QuicStringPiece key) override;
   bool SetNoncePrefix(QuicStringPiece nonce_prefix) override;
-  bool EncryptPacket(QuicVersion version,
+  bool SetIV(QuicStringPiece iv) override;
+  bool EncryptPacket(QuicTransportVersion version,
                      QuicPacketNumber packet_number,
                      QuicStringPiece associated_data,
                      QuicStringPiece plaintext,
diff --git a/net/quic/core/crypto/proof_source.h b/net/quic/core/crypto/proof_source.h
index d44591c..bc28b6a 100644
--- a/net/quic/core/crypto/proof_source.h
+++ b/net/quic/core/crypto/proof_source.h
@@ -116,7 +116,7 @@
   virtual void GetProof(const QuicSocketAddress& server_address,
                         const std::string& hostname,
                         const std::string& server_config,
-                        QuicVersion quic_version,
+                        QuicTransportVersion transport_version,
                         QuicStringPiece chlo_hash,
                         const QuicTagVector& connection_options,
                         std::unique_ptr<Callback> callback) = 0;
diff --git a/net/quic/core/crypto/proof_verifier.h b/net/quic/core/crypto/proof_verifier.h
index f0bb821d..8b02294 100644
--- a/net/quic/core/crypto/proof_verifier.h
+++ b/net/quic/core/crypto/proof_verifier.h
@@ -78,7 +78,7 @@
       const std::string& hostname,
       const uint16_t port,
       const std::string& server_config,
-      QuicVersion quic_version,
+      QuicTransportVersion transport_version,
       QuicStringPiece chlo_hash,
       const std::vector<std::string>& certs,
       const std::string& cert_sct,
diff --git a/net/quic/core/crypto/quic_crypto_client_config.cc b/net/quic/core/crypto/quic_crypto_client_config.cc
index ea0c53c..9c77f54f 100644
--- a/net/quic/core/crypto/quic_crypto_client_config.cc
+++ b/net/quic/core/crypto/quic_crypto_client_config.cc
@@ -421,7 +421,7 @@
 
 void QuicCryptoClientConfig::FillInchoateClientHello(
     const QuicServerId& server_id,
-    const QuicVersion preferred_version,
+    const QuicTransportVersion preferred_version,
     const CachedState* cached,
     QuicRandom* rand,
     bool demand_x509_proof,
@@ -498,7 +498,7 @@
 QuicErrorCode QuicCryptoClientConfig::FillClientHello(
     const QuicServerId& server_id,
     QuicConnectionId connection_id,
-    const QuicVersion preferred_version,
+    const QuicTransportVersion preferred_version,
     const CachedState* cached,
     QuicWallTime now,
     QuicRandom* rand,
@@ -721,7 +721,7 @@
 QuicErrorCode QuicCryptoClientConfig::CacheNewServerConfig(
     const CryptoHandshakeMessage& message,
     QuicWallTime now,
-    QuicVersion version,
+    QuicTransportVersion version,
     QuicStringPiece chlo_hash,
     const std::vector<string>& cached_certs,
     CachedState* cached,
@@ -793,7 +793,7 @@
 QuicErrorCode QuicCryptoClientConfig::ProcessRejection(
     const CryptoHandshakeMessage& rej,
     QuicWallTime now,
-    const QuicVersion version,
+    const QuicTransportVersion version,
     QuicStringPiece chlo_hash,
     CachedState* cached,
     QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params,
@@ -837,8 +837,8 @@
 QuicErrorCode QuicCryptoClientConfig::ProcessServerHello(
     const CryptoHandshakeMessage& server_hello,
     QuicConnectionId connection_id,
-    QuicVersion version,
-    const QuicVersionVector& negotiated_versions,
+    QuicTransportVersion version,
+    const QuicTransportVersionVector& negotiated_versions,
     CachedState* cached,
     QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params,
     string* error_details) {
@@ -900,7 +900,7 @@
 QuicErrorCode QuicCryptoClientConfig::ProcessServerConfigUpdate(
     const CryptoHandshakeMessage& server_config_update,
     QuicWallTime now,
-    const QuicVersion version,
+    const QuicTransportVersion version,
     QuicStringPiece chlo_hash,
     CachedState* cached,
     QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params,
diff --git a/net/quic/core/crypto/quic_crypto_client_config.h b/net/quic/core/crypto/quic_crypto_client_config.h
index ee72afaa..e5b413e 100644
--- a/net/quic/core/crypto/quic_crypto_client_config.h
+++ b/net/quic/core/crypto/quic_crypto_client_config.h
@@ -229,7 +229,7 @@
   // certificate related fields.
   void FillInchoateClientHello(
       const QuicServerId& server_id,
-      const QuicVersion preferred_version,
+      const QuicTransportVersion preferred_version,
       const CachedState* cached,
       QuicRandom* rand,
       bool demand_x509_proof,
@@ -253,7 +253,7 @@
   QuicErrorCode FillClientHello(
       const QuicServerId& server_id,
       QuicConnectionId connection_id,
-      const QuicVersion preferred_version,
+      const QuicTransportVersion preferred_version,
       const CachedState* cached,
       QuicWallTime now,
       QuicRandom* rand,
@@ -271,7 +271,7 @@
   QuicErrorCode ProcessRejection(
       const CryptoHandshakeMessage& rej,
       QuicWallTime now,
-      QuicVersion version,
+      QuicTransportVersion version,
       QuicStringPiece chlo_hash,
       CachedState* cached,
       QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params,
@@ -289,8 +289,8 @@
   QuicErrorCode ProcessServerHello(
       const CryptoHandshakeMessage& server_hello,
       QuicConnectionId connection_id,
-      QuicVersion version,
-      const QuicVersionVector& negotiated_versions,
+      QuicTransportVersion version,
+      const QuicTransportVersionVector& negotiated_versions,
       CachedState* cached,
       QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params,
       std::string* error_details);
@@ -303,7 +303,7 @@
   QuicErrorCode ProcessServerConfigUpdate(
       const CryptoHandshakeMessage& server_update,
       QuicWallTime now,
-      const QuicVersion version,
+      const QuicTransportVersion version,
       QuicStringPiece chlo_hash,
       CachedState* cached,
       QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params,
@@ -356,7 +356,7 @@
   QuicErrorCode CacheNewServerConfig(
       const CryptoHandshakeMessage& message,
       QuicWallTime now,
-      const QuicVersion version,
+      const QuicTransportVersion version,
       QuicStringPiece chlo_hash,
       const std::vector<std::string>& cached_certs,
       CachedState* cached,
diff --git a/net/quic/core/crypto/quic_crypto_client_config_test.cc b/net/quic/core/crypto/quic_crypto_client_config_test.cc
index 78db122d..642e6a8 100644
--- a/net/quic/core/crypto/quic_crypto_client_config_test.cc
+++ b/net/quic/core/crypto/quic_crypto_client_config_test.cc
@@ -301,13 +301,14 @@
 }
 
 TEST_F(QuicCryptoClientConfigTest, ProcessServerDowngradeAttack) {
-  QuicVersionVector supported_versions = AllSupportedVersions();
+  QuicTransportVersionVector supported_versions =
+      AllSupportedTransportVersions();
   if (supported_versions.size() == 1) {
     // No downgrade attack is possible if the client only supports one version.
     return;
   }
 
-  QuicVersionVector supported_version_vector;
+  QuicTransportVersionVector supported_version_vector;
   for (size_t i = supported_versions.size(); i > 0; --i) {
     supported_version_vector.push_back(supported_versions[i - 1]);
   }
@@ -488,8 +489,8 @@
   QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting());
   EXPECT_EQ(QUIC_NO_ERROR,
             config.ProcessRejection(rej, QuicWallTime::FromUNIXSeconds(0),
-                                    AllSupportedVersions().front(), "", &cached,
-                                    out_params, &error));
+                                    AllSupportedTransportVersions().front(), "",
+                                    &cached, out_params, &error));
   EXPECT_FALSE(cached.has_server_designated_connection_id());
   EXPECT_FALSE(cached.has_server_nonce());
 }
@@ -509,8 +510,8 @@
   QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting());
   EXPECT_EQ(QUIC_NO_ERROR,
             config.ProcessRejection(rej, QuicWallTime::FromUNIXSeconds(0),
-                                    AllSupportedVersions().front(), "", &cached,
-                                    out_params, &error));
+                                    AllSupportedTransportVersions().front(), "",
+                                    &cached, out_params, &error));
   cached.SetProofValid();
   EXPECT_FALSE(cached.IsComplete(QuicWallTime::FromUNIXSeconds(long_ttl)));
   EXPECT_FALSE(
@@ -536,8 +537,8 @@
   QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting());
   EXPECT_EQ(QUIC_NO_ERROR,
             config.ProcessRejection(rej, QuicWallTime::FromUNIXSeconds(0),
-                                    AllSupportedVersions().front(), "", &cached,
-                                    out_params, &error));
+                                    AllSupportedTransportVersions().front(), "",
+                                    &cached, out_params, &error));
   EXPECT_TRUE(cached.has_server_designated_connection_id());
   EXPECT_EQ(QuicEndian::NetToHost64(kConnectionId),
             cached.GetNextServerDesignatedConnectionId());
@@ -558,8 +559,8 @@
   QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting());
   EXPECT_EQ(QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND,
             config.ProcessRejection(rej, QuicWallTime::FromUNIXSeconds(0),
-                                    AllSupportedVersions().front(), "", &cached,
-                                    out_params, &error));
+                                    AllSupportedTransportVersions().front(), "",
+                                    &cached, out_params, &error));
   EXPECT_FALSE(cached.has_server_designated_connection_id());
   EXPECT_EQ("Missing kRCID", error);
 }
@@ -569,8 +570,8 @@
   CryptoHandshakeMessage msg;
   msg.set_tag(kSHLO);
   // Choose the latest version.
-  QuicVersionVector supported_versions;
-  QuicVersion version = AllSupportedVersions().front();
+  QuicTransportVersionVector supported_versions;
+  QuicTransportVersion version = AllSupportedTransportVersions().front();
   supported_versions.push_back(version);
   msg.SetVersionVector(kVER, supported_versions);
 
diff --git a/net/quic/core/crypto/quic_crypto_server_config.cc b/net/quic/core/crypto/quic_crypto_server_config.cc
index 21ec446a..2206e44 100644
--- a/net/quic/core/crypto/quic_crypto_server_config.cc
+++ b/net/quic/core/crypto/quic_crypto_server_config.cc
@@ -431,7 +431,7 @@
     const CryptoHandshakeMessage& client_hello,
     const QuicIpAddress& client_ip,
     const QuicSocketAddress& server_address,
-    QuicVersion version,
+    QuicTransportVersion version,
     const QuicClock* clock,
     QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
     std::unique_ptr<ValidateClientHelloResultCallback> done_cb) const {
@@ -528,8 +528,8 @@
       bool reject_only,
       QuicConnectionId connection_id,
       const QuicSocketAddress& client_address,
-      QuicVersion version,
-      const QuicVersionVector& supported_versions,
+      QuicTransportVersion version,
+      const QuicTransportVersionVector& supported_versions,
       bool use_stateless_rejects,
       QuicConnectionId server_designated_connection_id,
       const QuicClock* clock,
@@ -588,8 +588,8 @@
   const bool reject_only_;
   const QuicConnectionId connection_id_;
   const QuicSocketAddress client_address_;
-  const QuicVersion version_;
-  const QuicVersionVector supported_versions_;
+  const QuicTransportVersion version_;
+  const QuicTransportVersionVector supported_versions_;
   const bool use_stateless_rejects_;
   const QuicConnectionId server_designated_connection_id_;
   const QuicClock* const clock_;
@@ -613,8 +613,8 @@
     QuicConnectionId connection_id,
     const QuicSocketAddress& server_address,
     const QuicSocketAddress& client_address,
-    QuicVersion version,
-    const QuicVersionVector& supported_versions,
+    QuicTransportVersion version,
+    const QuicTransportVersionVector& supported_versions,
     bool use_stateless_rejects,
     QuicConnectionId server_designated_connection_id,
     const QuicClock* clock,
@@ -728,8 +728,8 @@
     bool reject_only,
     QuicConnectionId connection_id,
     const QuicSocketAddress& client_address,
-    QuicVersion version,
-    const QuicVersionVector& supported_versions,
+    QuicTransportVersion version,
+    const QuicTransportVersionVector& supported_versions,
     bool use_stateless_rejects,
     QuicConnectionId server_designated_connection_id,
     const QuicClock* clock,
@@ -1120,7 +1120,7 @@
       const QuicCryptoServerConfig& config,
       bool found_error,
       const QuicIpAddress& server_ip,
-      QuicVersion version,
+      QuicTransportVersion version,
       QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>
           requested_config,
       QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>
@@ -1157,7 +1157,7 @@
   const QuicCryptoServerConfig& config_;
   const bool found_error_;
   const QuicIpAddress& server_ip_;
-  const QuicVersion version_;
+  const QuicTransportVersion version_;
   const QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>
       requested_config_;
   const QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>
@@ -1170,7 +1170,7 @@
 
 void QuicCryptoServerConfig::EvaluateClientHello(
     const QuicSocketAddress& server_address,
-    QuicVersion version,
+    QuicTransportVersion version,
     QuicReferenceCountedPointer<Config> requested_config,
     QuicReferenceCountedPointer<Config> primary_config,
     QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
@@ -1279,7 +1279,7 @@
 void QuicCryptoServerConfig::EvaluateClientHelloAfterGetProof(
     bool found_error,
     const QuicIpAddress& server_ip,
-    QuicVersion version,
+    QuicTransportVersion version,
     QuicReferenceCountedPointer<Config> requested_config,
     QuicReferenceCountedPointer<Config> primary_config,
     QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
@@ -1325,7 +1325,7 @@
 }
 
 void QuicCryptoServerConfig::BuildServerConfigUpdateMessage(
-    QuicVersion version,
+    QuicTransportVersion version,
     QuicStringPiece chlo_hash,
     const SourceAddressTokens& previous_source_address_tokens,
     const QuicSocketAddress& server_address,
@@ -1376,7 +1376,7 @@
 QuicCryptoServerConfig::BuildServerConfigUpdateMessageProofSourceCallback::
     BuildServerConfigUpdateMessageProofSourceCallback(
         const QuicCryptoServerConfig* config,
-        QuicVersion version,
+        QuicTransportVersion version,
         QuicCompressedCertsCache* compressed_certs_cache,
         const CommonCertSets* common_cert_sets,
         const QuicCryptoNegotiatedParameters& params,
@@ -1406,7 +1406,7 @@
 }
 
 void QuicCryptoServerConfig::FinishBuildServerConfigUpdateMessage(
-    QuicVersion version,
+    QuicTransportVersion version,
     QuicCompressedCertsCache* compressed_certs_cache,
     const CommonCertSets* common_cert_sets,
     const string& client_common_set_hashes,
@@ -1442,7 +1442,7 @@
 }
 
 void QuicCryptoServerConfig::BuildRejection(
-    QuicVersion version,
+    QuicTransportVersion version,
     QuicWallTime now,
     const Config& config,
     const CryptoHandshakeMessage& client_hello,
diff --git a/net/quic/core/crypto/quic_crypto_server_config.h b/net/quic/core/crypto/quic_crypto_server_config.h
index 4094855..4c354be 100644
--- a/net/quic/core/crypto/quic_crypto_server_config.h
+++ b/net/quic/core/crypto/quic_crypto_server_config.h
@@ -273,7 +273,7 @@
       const CryptoHandshakeMessage& client_hello,
       const QuicIpAddress& client_ip,
       const QuicSocketAddress& server_address,
-      QuicVersion version,
+      QuicTransportVersion version,
       const QuicClock* clock,
       QuicReferenceCountedPointer<QuicSignedServerConfig> crypto_proof,
       std::unique_ptr<ValidateClientHelloResultCallback> done_cb) const;
@@ -314,8 +314,8 @@
       QuicConnectionId connection_id,
       const QuicSocketAddress& server_address,
       const QuicSocketAddress& client_address,
-      QuicVersion version,
-      const QuicVersionVector& supported_versions,
+      QuicTransportVersion version,
+      const QuicTransportVersionVector& supported_versions,
       bool use_stateless_rejects,
       QuicConnectionId server_designated_connection_id,
       const QuicClock* clock,
@@ -335,7 +335,7 @@
   //
   // |cached_network_params| is optional, and can be nullptr.
   void BuildServerConfigUpdateMessage(
-      QuicVersion version,
+      QuicTransportVersion version,
       QuicStringPiece chlo_hash,
       const SourceAddressTokens& previous_source_address_tokens,
       const QuicSocketAddress& server_address,
@@ -484,7 +484,7 @@
   // written to |info|.
   void EvaluateClientHello(
       const QuicSocketAddress& server_address,
-      QuicVersion version,
+      QuicTransportVersion version,
       QuicReferenceCountedPointer<Config> requested_config,
       QuicReferenceCountedPointer<Config> primary_config,
       QuicReferenceCountedPointer<QuicSignedServerConfig> crypto_proof,
@@ -505,7 +505,7 @@
   void EvaluateClientHelloAfterGetProof(
       bool found_error,
       const QuicIpAddress& server_ip,
-      QuicVersion version,
+      QuicTransportVersion version,
       QuicReferenceCountedPointer<Config> requested_config,
       QuicReferenceCountedPointer<Config> primary_config,
       QuicReferenceCountedPointer<QuicSignedServerConfig> crypto_proof,
@@ -528,8 +528,8 @@
       bool reject_only,
       QuicConnectionId connection_id,
       const QuicSocketAddress& client_address,
-      QuicVersion version,
-      const QuicVersionVector& supported_versions,
+      QuicTransportVersion version,
+      const QuicTransportVersionVector& supported_versions,
       bool use_stateless_rejects,
       QuicConnectionId server_designated_connection_id,
       const QuicClock* clock,
@@ -545,7 +545,7 @@
 
   // BuildRejection sets |out| to be a REJ message in reply to |client_hello|.
   void BuildRejection(
-      QuicVersion version,
+      QuicTransportVersion version,
       QuicWallTime now,
       const Config& config,
       const CryptoHandshakeMessage& client_hello,
@@ -655,7 +655,7 @@
         delete;
     BuildServerConfigUpdateMessageProofSourceCallback(
         const QuicCryptoServerConfig* config,
-        QuicVersion version,
+        QuicTransportVersion version,
         QuicCompressedCertsCache* compressed_certs_cache,
         const CommonCertSets* common_cert_sets,
         const QuicCryptoNegotiatedParameters& params,
@@ -669,7 +669,7 @@
 
    private:
     const QuicCryptoServerConfig* config_;
-    const QuicVersion version_;
+    const QuicTransportVersion version_;
     QuicCompressedCertsCache* compressed_certs_cache_;
     const CommonCertSets* common_cert_sets_;
     const std::string client_common_set_hashes_;
@@ -683,7 +683,7 @@
   // the proof has been acquired.  Finishes building the server config update
   // message and invokes |cb|.
   void FinishBuildServerConfigUpdateMessage(
-      QuicVersion version,
+      QuicTransportVersion version,
       QuicCompressedCertsCache* compressed_certs_cache,
       const CommonCertSets* common_cert_sets,
       const std::string& client_common_set_hashes,
diff --git a/net/quic/core/crypto/quic_decrypter.h b/net/quic/core/crypto/quic_decrypter.h
index 7b6003e..5b6258f 100644
--- a/net/quic/core/crypto/quic_decrypter.h
+++ b/net/quic/core/crypto/quic_decrypter.h
@@ -27,7 +27,7 @@
   virtual bool SetKey(QuicStringPiece key) = 0;
 
   // Sets the fixed initial bytes of the nonce. Returns true on success,
-  // false on failure.
+  // false on failure. This method must only be used with Google QUIC crypters.
   //
   // NOTE: The nonce prefix is the client_write_iv or server_write_iv
   // derived from the master secret. A 64-bit packet number will
@@ -43,6 +43,33 @@
   // packet number, even when retransmitting a lost packet.
   virtual bool SetNoncePrefix(QuicStringPiece nonce_prefix) = 0;
 
+  // Sets |iv| as the initialization vector to use when constructing the nonce.
+  // Returns true on success, false on failure. This method must only be used
+  // with IETF QUIC crypters.
+  //
+  // Google QUIC and IETF QUIC use different nonce constructions. This method
+  // must be used when using IETF QUIC; SetNoncePrefix must be used when using
+  // Google QUIC.
+  //
+  // The nonce is constructed as follows (draft-ietf-quic-tls section 5.3):
+  //
+  //    <---------------- max(8, N_MIN) bytes ----------------->
+  //   +--------------------------------------------------------+
+  //   |                 packet protection IV                   |
+  //   +--------------------------------------------------------+
+  //                             XOR
+  //                          <------------ 64 bits ----------->
+  //   +---------------------+----------------------------------+
+  //   |        zeroes       |   reconstructed packet number    |
+  //   +---------------------+----------------------------------+
+  //
+  // The nonce is the packet protection IV (|iv|) XOR'd with the left-padded
+  // reconstructed packet number.
+  //
+  // The security of the nonce format requires that QUIC never reuse a
+  // packet number, even when retransmitting a lost packet.
+  virtual bool SetIV(QuicStringPiece iv) = 0;
+
   // Sets the encryption key. Returns true on success, false on failure.
   // |DecryptPacket| may not be called until |SetDiversificationNonce| is
   // called and the preliminary keying material will be combined with that
@@ -67,7 +94,7 @@
   // to form the nonce.
   // TODO(wtc): add a way for DecryptPacket to report decryption failure due
   // to non-authentic inputs, as opposed to other reasons for failure.
-  virtual bool DecryptPacket(QuicVersion version,
+  virtual bool DecryptPacket(QuicTransportVersion version,
                              QuicPacketNumber packet_number,
                              QuicStringPiece associated_data,
                              QuicStringPiece ciphertext,
diff --git a/net/quic/core/crypto/quic_encrypter.h b/net/quic/core/crypto/quic_encrypter.h
index 03aa6df..c9e21f3a 100644
--- a/net/quic/core/crypto/quic_encrypter.h
+++ b/net/quic/core/crypto/quic_encrypter.h
@@ -26,7 +26,7 @@
   virtual bool SetKey(QuicStringPiece key) = 0;
 
   // Sets the fixed initial bytes of the nonce. Returns true on success,
-  // false on failure.
+  // false on failure. This method must only be used with Google QUIC crypters.
   //
   // NOTE: The nonce prefix is the client_write_iv or server_write_iv
   // derived from the master secret. A 64-bit packet number will
@@ -42,6 +42,33 @@
   // packet number, even when retransmitting a lost packet.
   virtual bool SetNoncePrefix(QuicStringPiece nonce_prefix) = 0;
 
+  // Sets |iv| as the initialization vector to use when constructing the nonce.
+  // Returns true on success, false on failure. This method must only be used
+  // with IETF QUIC crypters.
+  //
+  // Google QUIC and IETF QUIC use different nonce constructions. This method
+  // must be used when using IETF QUIC; SetNoncePrefix must be used when using
+  // Google QUIC.
+  //
+  // The nonce is constructed as follows (draft-ietf-quic-tls section 5.3):
+  //
+  //    <---------------- max(8, N_MIN) bytes ----------------->
+  //   +--------------------------------------------------------+
+  //   |                 packet protection IV                   |
+  //   +--------------------------------------------------------+
+  //                             XOR
+  //                          <------------ 64 bits ----------->
+  //   +---------------------+----------------------------------+
+  //   |        zeroes       |   reconstructed packet number    |
+  //   +---------------------+----------------------------------+
+  //
+  // The nonce is the packet protection IV (|iv|) XOR'd with the left-padded
+  // reconstructed packet number.
+  //
+  // The security of the nonce format requires that QUIC never reuse a
+  // packet number, even when retransmitting a lost packet.
+  virtual bool SetIV(QuicStringPiece iv) = 0;
+
   // Writes encrypted |plaintext| and a MAC over |plaintext| and
   // |associated_data| into output. Sets |output_length| to the number of
   // bytes written. Returns true on success or false if there was an error.
@@ -49,7 +76,7 @@
   // SetNoncePrefix() to form the nonce. |output| must not overlap with
   // |associated_data|. If |output| overlaps with |plaintext| then
   // |plaintext| must be <= |output|.
-  virtual bool EncryptPacket(QuicVersion version,
+  virtual bool EncryptPacket(QuicTransportVersion version,
                              QuicPacketNumber packet_number,
                              QuicStringPiece associated_data,
                              QuicStringPiece plaintext,
diff --git a/net/quic/core/frames/quic_frames_test.cc b/net/quic/core/frames/quic_frames_test.cc
index 323e8cd..7db8ee3 100644
--- a/net/quic/core/frames/quic_frames_test.cc
+++ b/net/quic/core/frames/quic_frames_test.cc
@@ -25,7 +25,7 @@
 
 TEST_F(QuicFramesTest, AckFrameToString) {
   QuicAckFrame frame;
-  frame.largest_observed = 2;
+  frame.largest_observed = 5;
   frame.ack_delay_time = QuicTime::Delta::FromMicroseconds(3);
   frame.packets.Add(4);
   frame.packets.Add(5);
@@ -34,7 +34,7 @@
   std::ostringstream stream;
   stream << frame;
   EXPECT_EQ(
-      "{ largest_observed: 2, ack_delay_time: 3, "
+      "{ largest_observed: 5, ack_delay_time: 3, "
       "packets: [ 4 5  ], received_packets: [ 6 at 7  ] }\n",
       stream.str());
 }
diff --git a/net/quic/core/frames/quic_stream_frame.h b/net/quic/core/frames/quic_stream_frame.h
index 4d280fc..76aa0d9c 100644
--- a/net/quic/core/frames/quic_stream_frame.h
+++ b/net/quic/core/frames/quic_stream_frame.h
@@ -64,11 +64,10 @@
   QuicPacketLength data_length;
   const char* data_buffer;
   QuicStreamOffset offset;  // Location of this data in the stream.
-  // TODO(fayang): When deprecating
-  // quic_reloadable_flag_quic_save_data_before_consumption2: (1) Remove buffer
-  // from QuicStreamFrame; (2) remove the constructor uses UniqueStreamBuffer
-  // and (3) Move definition of UniqueStreamBuffer to QuicStreamSendBuffer.
-  // nullptr when the QuicStreamFrame is received, and non-null when sent.
+  // TODO(fayang): (1) Remove buffer from QuicStreamFrame; (2) remove the
+  // constructor uses UniqueStreamBuffer and (3) Move definition of
+  // UniqueStreamBuffer to QuicStreamSendBuffer. nullptr when the
+  // QuicStreamFrame is received, and non-null when sent.
   UniqueStreamBuffer buffer;
 
  private:
diff --git a/net/quic/core/quic_config.cc b/net/quic/core/quic_config.cc
index c26d9c1..104333a4 100644
--- a/net/quic/core/quic_config.cc
+++ b/net/quic/core/quic_config.cc
@@ -180,6 +180,71 @@
   return error;
 }
 
+QuicFixedUint128::QuicFixedUint128(QuicTag tag, QuicConfigPresence presence)
+    : QuicConfigValue(tag, presence),
+      has_send_value_(false),
+      has_receive_value_(false) {}
+QuicFixedUint128::~QuicFixedUint128() {}
+
+bool QuicFixedUint128::HasSendValue() const {
+  return has_send_value_;
+}
+
+uint128 QuicFixedUint128::GetSendValue() const {
+  QUIC_BUG_IF(!has_send_value_)
+      << "No send value to get for tag:" << QuicTagToString(tag_);
+  return send_value_;
+}
+
+void QuicFixedUint128::SetSendValue(uint128 value) {
+  has_send_value_ = true;
+  send_value_ = value;
+}
+
+bool QuicFixedUint128::HasReceivedValue() const {
+  return has_receive_value_;
+}
+
+uint128 QuicFixedUint128::GetReceivedValue() const {
+  QUIC_BUG_IF(!has_receive_value_)
+      << "No receive value to get for tag:" << QuicTagToString(tag_);
+  return receive_value_;
+}
+
+void QuicFixedUint128::SetReceivedValue(uint128 value) {
+  has_receive_value_ = true;
+  receive_value_ = value;
+}
+
+void QuicFixedUint128::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
+  if (has_send_value_) {
+    out->SetValue(tag_, send_value_);
+  }
+}
+
+QuicErrorCode QuicFixedUint128::ProcessPeerHello(
+    const CryptoHandshakeMessage& peer_hello,
+    HelloType hello_type,
+    string* error_details) {
+  DCHECK(error_details != nullptr);
+  QuicErrorCode error = peer_hello.GetUint128(tag_, &receive_value_);
+  switch (error) {
+    case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
+      if (presence_ == PRESENCE_OPTIONAL) {
+        return QUIC_NO_ERROR;
+      }
+      *error_details = "Missing " + QuicTagToString(tag_);
+      break;
+    case QUIC_NO_ERROR:
+      has_receive_value_ = true;
+      break;
+    default:
+      *error_details = "Bad " + QuicTagToString(tag_);
+      break;
+  }
+  return error;
+}
+
 QuicFixedTagVector::QuicFixedTagVector(QuicTag name,
                                        QuicConfigPresence presence)
     : QuicConfigValue(name, presence),
@@ -337,7 +402,8 @@
       socket_receive_buffer_(kSRBF, PRESENCE_OPTIONAL),
       connection_migration_disabled_(kNCMR, PRESENCE_OPTIONAL),
       alternate_server_address_(kASAD, PRESENCE_OPTIONAL),
-      support_max_header_list_size_(kSMHL, PRESENCE_OPTIONAL) {
+      support_max_header_list_size_(kSMHL, PRESENCE_OPTIONAL),
+      stateless_reset_token_(kSRST, PRESENCE_OPTIONAL) {
   SetDefaults();
 }
 
@@ -567,6 +633,18 @@
   return support_max_header_list_size_.HasReceivedValue();
 }
 
+void QuicConfig::SetStatelessResetTokenToSend(uint128 stateless_reset_token) {
+  stateless_reset_token_.SetSendValue(stateless_reset_token);
+}
+
+bool QuicConfig::HasReceivedStatelessResetToken() const {
+  return stateless_reset_token_.HasReceivedValue();
+}
+
+uint128 QuicConfig::ReceivedStatelessResetToken() const {
+  return stateless_reset_token_.GetReceivedValue();
+}
+
 bool QuicConfig::negotiated() const {
   // TODO(ianswett): Add the negotiated parameters once and iterate over all
   // of them in negotiated, ToHandshakeMessage, ProcessClientHello, and
@@ -608,6 +686,7 @@
   connection_options_.ToHandshakeMessage(out);
   alternate_server_address_.ToHandshakeMessage(out);
   support_max_header_list_size_.ToHandshakeMessage(out);
+  stateless_reset_token_.ToHandshakeMessage(out);
 }
 
 QuicErrorCode QuicConfig::ProcessPeerHello(
@@ -665,6 +744,10 @@
     error = support_max_header_list_size_.ProcessPeerHello(
         peer_hello, hello_type, error_details);
   }
+  if (error == QUIC_NO_ERROR) {
+    error = stateless_reset_token_.ProcessPeerHello(peer_hello, hello_type,
+                                                    error_details);
+  }
   return error;
 }
 
diff --git a/net/quic/core/quic_config.h b/net/quic/core/quic_config.h
index 770d90b..e367b4ba 100644
--- a/net/quic/core/quic_config.h
+++ b/net/quic/core/quic_config.h
@@ -9,6 +9,7 @@
 #include <cstdint>
 #include <string>
 
+#include "net/base/int128.h"
 #include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_time.h"
 #include "net/quic/platform/api/quic_export.h"
@@ -146,6 +147,39 @@
   bool has_receive_value_;
 };
 
+// Stores uint128 from CHLO or SHLO messages that are not negotiated.
+class QUIC_EXPORT_PRIVATE QuicFixedUint128 : public QuicConfigValue {
+ public:
+  QuicFixedUint128(QuicTag tag, QuicConfigPresence presence);
+  ~QuicFixedUint128() override;
+
+  bool HasSendValue() const;
+
+  uint128 GetSendValue() const;
+
+  void SetSendValue(uint128 value);
+
+  bool HasReceivedValue() const;
+
+  uint128 GetReceivedValue() const;
+
+  void SetReceivedValue(uint128 value);
+
+  // If has_send_value is true, serialises |tag_| and |send_value_| to |out|.
+  void ToHandshakeMessage(CryptoHandshakeMessage* out) const override;
+
+  // Sets |value_| to the corresponding value from |peer_hello_| if it exists.
+  QuicErrorCode ProcessPeerHello(const CryptoHandshakeMessage& peer_hello,
+                                 HelloType hello_type,
+                                 std::string* error_details) override;
+
+ private:
+  uint128 send_value_;
+  bool has_send_value_;
+  uint128 receive_value_;
+  bool has_receive_value_;
+};
+
 // Stores tag from CHLO or SHLO messages that are not negotiated.
 class QUIC_EXPORT_PRIVATE QuicFixedTagVector : public QuicConfigValue {
  public:
@@ -359,6 +393,12 @@
 
   bool SupportMaxHeaderListSize() const;
 
+  void SetStatelessResetTokenToSend(uint128 stateless_reset_token);
+
+  bool HasReceivedStatelessResetToken() const;
+
+  uint128 ReceivedStatelessResetToken() const;
+
   bool negotiated() const;
 
   // ToHandshakeMessage serialises the settings in this object as a series of
@@ -421,6 +461,9 @@
 
   // Whether support HTTP/2 SETTINGS_MAX_HEADER_LIST_SIZE SETTINGS frame.
   QuicFixedUint32 support_max_header_list_size_;
+
+  // Stateless reset token used in IETF public reset packet.
+  QuicFixedUint128 stateless_reset_token_;
 };
 
 }  // namespace net
diff --git a/net/quic/core/quic_config_test.cc b/net/quic/core/quic_config_test.cc
index 2c72991..fe27a11 100644
--- a/net/quic/core/quic_config_test.cc
+++ b/net/quic/core/quic_config_test.cc
@@ -107,6 +107,7 @@
   QuicIpAddress host;
   host.FromString("127.0.3.1");
   const QuicSocketAddress kTestServerAddress = QuicSocketAddress(host, 1234);
+  const uint128 kTestResetToken = MakeUint128(0, 10111100001);
   QuicConfig server_config;
   QuicTagVector cgst;
   cgst.push_back(kQBIC);
@@ -121,6 +122,7 @@
   server_config.SetInitialSessionFlowControlWindowToSend(
       2 * kInitialSessionFlowControlWindowForTest);
   server_config.SetAlternateServerAddressToSend(kTestServerAddress);
+  server_config.SetStatelessResetTokenToSend(kTestResetToken);
   CryptoHandshakeMessage msg;
   server_config.ToHandshakeMessage(&msg);
   string error_details;
@@ -139,6 +141,8 @@
             2 * kInitialSessionFlowControlWindowForTest);
   EXPECT_TRUE(config_.HasReceivedAlternateServerAddress());
   EXPECT_EQ(kTestServerAddress, config_.ReceivedAlternateServerAddress());
+  EXPECT_TRUE(config_.HasReceivedStatelessResetToken());
+  EXPECT_EQ(kTestResetToken, config_.ReceivedStatelessResetToken());
 }
 
 TEST_F(QuicConfigTest, MissingOptionalValuesInCHLO) {
diff --git a/net/quic/core/quic_connection.cc b/net/quic/core/quic_connection.cc
index 70e0f07..ac906d4e 100644
--- a/net/quic/core/quic_connection.cc
+++ b/net/quic/core/quic_connection.cc
@@ -170,14 +170,15 @@
 #define ENDPOINT \
   (perspective_ == Perspective::IS_SERVER ? "Server: " : "Client: ")
 
-QuicConnection::QuicConnection(QuicConnectionId connection_id,
-                               QuicSocketAddress address,
-                               QuicConnectionHelperInterface* helper,
-                               QuicAlarmFactory* alarm_factory,
-                               QuicPacketWriter* writer,
-                               bool owns_writer,
-                               Perspective perspective,
-                               const QuicVersionVector& supported_versions)
+QuicConnection::QuicConnection(
+    QuicConnectionId connection_id,
+    QuicSocketAddress address,
+    QuicConnectionHelperInterface* helper,
+    QuicAlarmFactory* alarm_factory,
+    QuicPacketWriter* writer,
+    bool owns_writer,
+    Perspective perspective,
+    const QuicTransportVersionVector& supported_versions)
     : framer_(supported_versions,
               helper->GetClock()->ApproximateNow(),
               perspective),
@@ -366,7 +367,7 @@
     QUIC_FLAG_COUNT(quic_reloadable_flag_quic_enable_3rtos);
     close_connection_after_three_rtos_ = true;
   }
-  if (version() > QUIC_VERSION_37 &&
+  if (transport_version() > QUIC_VERSION_37 &&
       config.HasClientSentConnectionOption(kNSTP, perspective_)) {
     no_stop_waiting_frames_ = true;
   }
@@ -402,13 +403,14 @@
 }
 
 bool QuicConnection::SelectMutualVersion(
-    const QuicVersionVector& available_versions) {
+    const QuicTransportVersionVector& available_versions) {
   // Try to find the highest mutual version by iterating over supported
   // versions, starting with the highest, and breaking out of the loop once we
   // find a matching version in the provided available_versions vector.
-  const QuicVersionVector& supported_versions = framer_.supported_versions();
+  const QuicTransportVersionVector& supported_versions =
+      framer_.supported_versions();
   for (size_t i = 0; i < supported_versions.size(); ++i) {
-    const QuicVersion& version = supported_versions[i];
+    const QuicTransportVersion& version = supported_versions[i];
     if (QuicContainsValue(available_versions, version)) {
       framer_.set_version(version);
       return true;
@@ -446,7 +448,8 @@
                                ConnectionCloseSource::FROM_PEER);
 }
 
-bool QuicConnection::OnProtocolVersionMismatch(QuicVersion received_version) {
+bool QuicConnection::OnProtocolVersionMismatch(
+    QuicTransportVersion received_version) {
   QUIC_DLOG(INFO) << ENDPOINT << "Received packet with mismatched version "
                   << received_version;
   // TODO(satyamshekhar): Implement no server state in this mode.
@@ -457,7 +460,7 @@
                                  ConnectionCloseSource::FROM_SELF);
     return false;
   }
-  DCHECK_NE(version(), received_version);
+  DCHECK_NE(transport_version(), received_version);
 
   if (debug_visitor_ != nullptr) {
     debug_visitor_->OnProtocolVersionMismatch(received_version);
@@ -527,7 +530,7 @@
     return;
   }
 
-  if (QuicContainsValue(packet.versions, version())) {
+  if (QuicContainsValue(packet.versions, transport_version())) {
     const string error_details =
         "Server already supports client's version and should have accepted the "
         "connection.";
@@ -543,16 +546,17 @@
   if (!SelectMutualVersion(packet.versions)) {
     CloseConnection(
         QUIC_INVALID_VERSION,
-        QuicStrCat("No common version found. Supported versions: {",
-                   QuicVersionVectorToString(framer_.supported_versions()),
-                   "}, peer supported versions: {",
-                   QuicVersionVectorToString(packet.versions), "}"),
+        QuicStrCat(
+            "No common version found. Supported versions: {",
+            QuicTransportVersionVectorToString(framer_.supported_versions()),
+            "}, peer supported versions: {",
+            QuicTransportVersionVectorToString(packet.versions), "}"),
         ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
     return;
   }
 
-  QUIC_DLOG(INFO) << ENDPOINT
-                  << "Negotiated version: " << QuicVersionToString(version());
+  QUIC_DLOG(INFO) << ENDPOINT << "Negotiated version: "
+                  << QuicVersionToString(transport_version());
   version_negotiation_state_ = NEGOTIATION_IN_PROGRESS;
   RetransmitUnackedPackets(ALL_UNACKED_RETRANSMISSION);
 }
@@ -959,7 +963,7 @@
   ++num_packets_received_since_last_ack_sent_;
   // Always send an ack every 20 packets in order to allow the peer to discard
   // information from the SentPacketManager and provide an RTT measurement.
-  if (version() <= QUIC_VERSION_38 &&
+  if (transport_version() <= QUIC_VERSION_38 &&
       num_packets_received_since_last_ack_sent_ >=
           kMaxPacketsReceivedBeforeAckSend) {
     ack_queued_ = true;
@@ -1058,7 +1062,8 @@
     return;
   }
   QUIC_DLOG(INFO) << ENDPOINT << "Sending version negotiation packet: {"
-                  << QuicVersionVectorToString(framer_.supported_versions())
+                  << QuicTransportVersionVectorToString(
+                         framer_.supported_versions())
                   << "}";
   std::unique_ptr<QuicEncryptedPacket> version_packet(
       packet_generator_.SerializeVersionNegotiationPacket(
@@ -1100,19 +1105,8 @@
   // SHLO from the server, leading to two different decrypters at the server.)
   ScopedRetransmissionScheduler alarm_delayer(this);
   ScopedPacketBundler ack_bundler(this, SEND_ACK_IF_PENDING);
-  // The optimized path may be used for data only packets which fit into a
-  // standard buffer and don't need padding.
-  const bool flag_run_fast_path =
-      FLAGS_quic_reloadable_flag_quic_consuming_data_faster;
-  if (!flag_run_fast_path && id != kCryptoStreamId &&
-      !packet_generator_.HasQueuedFrames() &&
-      iov.total_length > kMaxPacketSize && state != FIN_AND_PADDING) {
-    // Use the fast path to send full data packets.
-    return packet_generator_.ConsumeDataFastPath(
-        id, iov, offset, state != NO_FIN, 0, ack_listener);
-  }
-  return packet_generator_.ConsumeData(
-      id, iov, offset, state, std::move(ack_listener), flag_run_fast_path);
+  return packet_generator_.ConsumeData(id, iov, offset, state,
+                                       std::move(ack_listener));
 }
 
 void QuicConnection::SendRstStream(QuicStreamId id,
@@ -1395,11 +1389,11 @@
         return false;
       } else {
         DCHECK_EQ(1u, header.public_header.versions.size());
-        DCHECK_EQ(header.public_header.versions[0], version());
+        DCHECK_EQ(header.public_header.versions[0], transport_version());
         version_negotiation_state_ = NEGOTIATED_VERSION;
-        visitor_->OnSuccessfulVersionNegotiation(version());
+        visitor_->OnSuccessfulVersionNegotiation(transport_version());
         if (debug_visitor_ != nullptr) {
-          debug_visitor_->OnSuccessfulVersionNegotiation(version());
+          debug_visitor_->OnSuccessfulVersionNegotiation(transport_version());
         }
       }
     } else {
@@ -1408,9 +1402,9 @@
       // it should stop sending version since the version negotiation is done.
       packet_generator_.StopSendingVersion();
       version_negotiation_state_ = NEGOTIATED_VERSION;
-      visitor_->OnSuccessfulVersionNegotiation(version());
+      visitor_->OnSuccessfulVersionNegotiation(transport_version());
       if (debug_visitor_ != nullptr) {
-        debug_visitor_->OnSuccessfulVersionNegotiation(version());
+        debug_visitor_->OnSuccessfulVersionNegotiation(transport_version());
       }
     }
   }
@@ -1732,7 +1726,7 @@
     return;
   }
 
-  if (version() > QUIC_VERSION_38) {
+  if (transport_version() > QUIC_VERSION_38) {
     if (serialized_packet->retransmittable_frames.empty() &&
         serialized_packet->original_packet_number == 0) {
       // Increment consecutive_num_packets_with_no_retransmittable_frames_ if
diff --git a/net/quic/core/quic_connection.h b/net/quic/core/quic_connection.h
index deb7d68..036b042 100644
--- a/net/quic/core/quic_connection.h
+++ b/net/quic/core/quic_connection.h
@@ -121,7 +121,8 @@
   virtual void OnWriteBlocked() = 0;
 
   // Called once a specific QUIC version is agreed by both endpoints.
-  virtual void OnSuccessfulVersionNegotiation(const QuicVersion& version) = 0;
+  virtual void OnSuccessfulVersionNegotiation(
+      const QuicTransportVersion& version) = 0;
 
   // Called when a blocked socket becomes writable.
   virtual void OnCanWrite() = 0;
@@ -199,7 +200,7 @@
 
   // Called when the protocol version on the received packet doensn't match
   // current protocol version of the connection.
-  virtual void OnProtocolVersionMismatch(QuicVersion version) {}
+  virtual void OnProtocolVersionMismatch(QuicTransportVersion version) {}
 
   // Called when the complete header of a packet has been parsed.
   virtual void OnPacketHeader(const QuicPacketHeader& header) {}
@@ -248,7 +249,8 @@
                                   ConnectionCloseSource source) {}
 
   // Called when the version negotiation is successful.
-  virtual void OnSuccessfulVersionNegotiation(const QuicVersion& version) {}
+  virtual void OnSuccessfulVersionNegotiation(
+      const QuicTransportVersion& version) {}
 
   // Called when a CachedNetworkParameters is sent to the client.
   virtual void OnSendConnectionState(
@@ -317,7 +319,7 @@
                  QuicPacketWriter* writer,
                  bool owns_writer,
                  Perspective perspective,
-                 const QuicVersionVector& supported_versions);
+                 const QuicTransportVersionVector& supported_versions);
   ~QuicConnection() override;
 
   // Sets connection parameters from the supplied |config|.
@@ -425,16 +427,24 @@
   void SetSelfAddress(QuicSocketAddress address) { self_address_ = address; }
 
   // The version of the protocol this connection is using.
-  QuicVersion version() const { return framer_.version(); }
+  QuicTransportVersion transport_version() const {
+    return framer_.transport_version();
+  }
+
+  // The QuicVersionLabel for the version this connection is using.
+  QuicVersionLabel version_label() const {
+    return framer_.last_version_label();
+  }
 
   // The versions of the protocol that this connection supports.
-  const QuicVersionVector& supported_versions() const {
+  const QuicTransportVersionVector& supported_versions() const {
     return framer_.supported_versions();
   }
 
   // From QuicFramerVisitorInterface
   void OnError(QuicFramer* framer) override;
-  bool OnProtocolVersionMismatch(QuicVersion received_version) override;
+  bool OnProtocolVersionMismatch(
+      QuicTransportVersion received_version) override;
   void OnPacket() override;
   void OnPublicResetPacket(const QuicPublicResetPacket& packet) override;
   void OnVersionNegotiationPacket(
@@ -516,7 +526,7 @@
   bool goaway_received() const { return goaway_received_; }
 
   // Must only be called on client connections.
-  const QuicVersionVector& server_supported_versions() const {
+  const QuicTransportVersionVector& server_supported_versions() const {
     DCHECK_EQ(Perspective::IS_CLIENT, perspective_);
     return server_supported_versions_;
   }
@@ -719,7 +729,8 @@
   // Selects and updates the version of the protocol being used by selecting a
   // version from |available_versions| which is also supported. Returns true if
   // such a version exists, false otherwise.
-  bool SelectMutualVersion(const QuicVersionVector& available_versions);
+  bool SelectMutualVersion(
+      const QuicTransportVersionVector& available_versions);
 
   // Returns the current per-packet options for the connection.
   PerPacketOptions* per_packet_options() { return per_packet_options_; }
@@ -1066,7 +1077,7 @@
 
   // If non-empty this contains the set of versions received in a
   // version negotiation packet.
-  QuicVersionVector server_supported_versions_;
+  QuicTransportVersionVector server_supported_versions_;
 
   // The size of the packet we are targeting while doing path MTU discovery.
   QuicByteCount mtu_discovery_target_;
diff --git a/net/quic/core/quic_connection_test.cc b/net/quic/core/quic_connection_test.cc
index 77232f3..3f07f013 100644
--- a/net/quic/core/quic_connection_test.cc
+++ b/net/quic/core/quic_connection_test.cc
@@ -91,7 +91,9 @@
 
   bool SetNoncePrefix(QuicStringPiece nonce_prefix) override { return true; }
 
-  bool EncryptPacket(QuicVersion /*version*/,
+  bool SetIV(QuicStringPiece iv) override { return true; }
+
+  bool EncryptPacket(QuicTransportVersion /*version*/,
                      QuicPacketNumber packet_number,
                      QuicStringPiece associated_data,
                      QuicStringPiece plaintext,
@@ -146,6 +148,8 @@
 
   bool SetNoncePrefix(QuicStringPiece nonce_prefix) override { return true; }
 
+  bool SetIV(QuicStringPiece iv) override { return true; }
+
   bool SetPreliminaryKey(QuicStringPiece key) override {
     QUIC_BUG << "should not be called";
     return false;
@@ -155,7 +159,7 @@
     return true;
   }
 
-  bool DecryptPacket(QuicVersion /*version*/,
+  bool DecryptPacket(QuicTransportVersion /*version*/,
                      QuicPacketNumber packet_number,
                      QuicStringPiece associated_data,
                      QuicStringPiece ciphertext,
@@ -274,9 +278,9 @@
 
 class TestPacketWriter : public QuicPacketWriter {
  public:
-  TestPacketWriter(QuicVersion version, MockClock* clock)
+  TestPacketWriter(QuicTransportVersion version, MockClock* clock)
       : version_(version),
-        framer_(SupportedVersions(version_), Perspective::IS_SERVER),
+        framer_(SupportedTransportVersions(version_), Perspective::IS_SERVER),
         last_packet_size_(0),
         write_blocked_(false),
         write_should_fail_(false),
@@ -437,8 +441,9 @@
 
   void Reset() { framer_.Reset(); }
 
-  void SetSupportedVersions(const QuicVersionVector& versions) {
-    framer_.SetSupportedVersions(versions);
+  void SetSupportedTransportVersions(
+      const QuicTransportVersionVector& versions) {
+    framer_.SetSupportedTransportVersions(versions);
   }
 
   void set_max_packet_size(QuicByteCount max_packet_size) {
@@ -446,7 +451,7 @@
   }
 
  private:
-  QuicVersion version_;
+  QuicTransportVersion version_;
   SimpleQuicFramer framer_;
   size_t last_packet_size_;
   bool write_blocked_;
@@ -476,7 +481,7 @@
                  TestAlarmFactory* alarm_factory,
                  TestPacketWriter* writer,
                  Perspective perspective,
-                 QuicVersion version)
+                 QuicTransportVersion version)
       : QuicConnection(connection_id,
                        address,
                        helper,
@@ -484,7 +489,7 @@
                        writer,
                        /* owns_writer= */ false,
                        perspective,
-                       SupportedVersions(version)) {
+                       SupportedTransportVersions(version)) {
     writer->set_perspective(perspective);
     SetEncrypter(ENCRYPTION_FORWARD_SECURE, new NullEncrypter(perspective));
   }
@@ -561,13 +566,15 @@
                                     nullptr);
   }
 
-  void set_version(QuicVersion version) {
+  void set_version(QuicTransportVersion version) {
     QuicConnectionPeer::GetFramer(this)->set_version(version);
   }
 
-  void SetSupportedVersions(const QuicVersionVector& versions) {
-    QuicConnectionPeer::GetFramer(this)->SetSupportedVersions(versions);
-    writer()->SetSupportedVersions(versions);
+  void SetSupportedTransportVersions(
+      const QuicTransportVersionVector& versions) {
+    QuicConnectionPeer::GetFramer(this)->SetSupportedTransportVersions(
+        versions);
+    writer()->SetSupportedTransportVersions(versions);
   }
 
   void set_perspective(Perspective perspective) {
@@ -652,9 +659,9 @@
 
 enum class AckResponse { kDefer, kImmediate };
 
-// Run tests with combinations of {QuicVersion, AckResponse}.
+// Run tests with combinations of {QuicTransportVersion, AckResponse}.
 struct TestParams {
-  TestParams(QuicVersion version,
+  TestParams(QuicTransportVersion version,
              AckResponse ack_response,
              bool no_stop_waiting)
       : version(version),
@@ -669,7 +676,7 @@
     return os;
   }
 
-  QuicVersion version;
+  QuicTransportVersion version;
   AckResponse ack_response;
   bool no_stop_waiting;
 };
@@ -677,7 +684,8 @@
 // Constructs various test permutations.
 std::vector<TestParams> GetTestParams() {
   std::vector<TestParams> params;
-  QuicVersionVector all_supported_versions = AllSupportedVersions();
+  QuicTransportVersionVector all_supported_versions =
+      AllSupportedTransportVersions();
   for (size_t i = 0; i < all_supported_versions.size(); ++i) {
     for (AckResponse ack_response :
          {AckResponse::kDefer, AckResponse::kImmediate}) {
@@ -694,28 +702,28 @@
  protected:
   QuicConnectionTest()
       : connection_id_(42),
-        framer_(SupportedVersions(version()),
+        framer_(SupportedTransportVersions(transport_version()),
                 QuicTime::Zero(),
                 Perspective::IS_CLIENT),
         send_algorithm_(new StrictMock<MockSendAlgorithm>),
         loss_algorithm_(new MockLossAlgorithm()),
         helper_(new TestConnectionHelper(&clock_, &random_generator_)),
         alarm_factory_(new TestAlarmFactory()),
-        peer_framer_(SupportedVersions(version()),
+        peer_framer_(SupportedTransportVersions(transport_version()),
                      QuicTime::Zero(),
                      Perspective::IS_SERVER),
         peer_creator_(connection_id_,
                       &peer_framer_,
                       &buffer_allocator_,
                       /*delegate=*/nullptr),
-        writer_(new TestPacketWriter(version(), &clock_)),
+        writer_(new TestPacketWriter(transport_version(), &clock_)),
         connection_(connection_id_,
                     kPeerAddress,
                     helper_.get(),
                     alarm_factory_.get(),
                     writer_.get(),
                     Perspective::IS_CLIENT,
-                    version()),
+                    transport_version()),
         creator_(QuicConnectionPeer::GetPacketCreator(&connection_)),
         generator_(QuicConnectionPeer::GetPacketGenerator(&connection_)),
         manager_(QuicConnectionPeer::GetSentPacketManager(&connection_)),
@@ -730,8 +738,7 @@
     connection_.set_visitor(&visitor_);
     connection_.SetSendAlgorithm(send_algorithm_);
     connection_.SetLossAlgorithm(loss_algorithm_.get());
-    EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _))
-        .WillRepeatedly(Return(QuicTime::Delta::Zero()));
+    EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true));
     EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
         .Times(AnyNumber());
     EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
@@ -760,7 +767,7 @@
         .Times(AnyNumber());
   }
 
-  QuicVersion version() { return GetParam().version; }
+  QuicTransportVersion transport_version() { return GetParam().version; }
 
   QuicAckFrame* outgoing_ack() {
     QuicFrame ack_frame = QuicConnectionPeer::GetUpdatedAckFrame(&connection_);
@@ -831,8 +838,8 @@
 
     const size_t encrypted_length = peer_framer_.EncryptInPlace(
         ENCRYPTION_NONE, header.packet_number,
-        GetStartOfEncryptedData(peer_framer_.version(), header), length,
-        kMaxPacketSize, encrypted_buffer);
+        GetStartOfEncryptedData(peer_framer_.transport_version(), header),
+        length, kMaxPacketSize, encrypted_buffer);
     DCHECK_GT(encrypted_length, 0u);
 
     connection_.ProcessUdpPacket(
@@ -991,15 +998,6 @@
     return QuicTime::Delta::FromMilliseconds(kMaxDelayedAckTimeMs);
   }
 
-  // Initialize a frame acknowledging all packets up to largest_observed.
-  const QuicAckFrame InitAckFrame(QuicPacketNumber largest_observed) {
-    QuicAckFrame frame(MakeAckFrame(largest_observed));
-    if (largest_observed > 0) {
-      frame.packets.AddRange(1, largest_observed + 1);
-    }
-    return frame;
-  }
-
   const QuicStopWaitingFrame InitStopWaitingFrame(
       QuicPacketNumber least_unacked) {
     QuicStopWaitingFrame frame;
@@ -1007,21 +1005,15 @@
     return frame;
   }
 
-  // Construct ack_frame containing up to two ranges
-  // [1, missing) and (missing, end_range]
+  // Construct a ack_frame that acks all packet numbers between 1 and
+  // |largest_acked|, except |missing|.
+  // REQUIRES: 1 <= |missing| < |largest_acked|
   QuicAckFrame ConstructAckFrame(QuicPacketNumber largest_acked,
                                  QuicPacketNumber missing) {
-    QuicAckFrame ack_frame;
-    if (largest_acked > missing) {
-      ack_frame.packets.AddRange(1, missing);
-      ack_frame.packets.AddRange(missing + 1, largest_acked + 1);
-      ack_frame.largest_observed = largest_acked;
+    if (missing == 1) {
+      return InitAckFrame({{missing + 1, largest_acked + 1}});
     }
-    if (largest_acked == missing) {
-      ack_frame.packets.AddRange(1, missing);
-      ack_frame.largest_observed = largest_acked;
-    }
-    return ack_frame;
+    return InitAckFrame({{1, missing}, {missing + 1, largest_acked + 1}});
   }
 
   // Undo nacking a packet within the frame.
@@ -1060,13 +1052,13 @@
   }
 
   void CongestionBlockWrites() {
-    EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _))
-        .WillRepeatedly(testing::Return(QuicTime::Delta::FromSeconds(1)));
+    EXPECT_CALL(*send_algorithm_, CanSend(_))
+        .WillRepeatedly(testing::Return(false));
   }
 
   void CongestionUnblockWrites() {
-    EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _))
-        .WillRepeatedly(testing::Return(QuicTime::Delta::Zero()));
+    EXPECT_CALL(*send_algorithm_, CanSend(_))
+        .WillRepeatedly(testing::Return(true));
   }
 
   void set_perspective(Perspective perspective) {
@@ -1267,7 +1259,7 @@
   QuicConnectionId connection_id = 42;
   TestConnection connection(connection_id, kPeerAddress, helper_.get(),
                             alarm_factory_.get(), writer_.get(),
-                            Perspective::IS_SERVER, version());
+                            Perspective::IS_SERVER, transport_version());
   EXPECT_EQ(Perspective::IS_SERVER, connection.perspective());
   EXPECT_EQ(1000u, connection.max_packet_length());
 }
@@ -1293,7 +1285,7 @@
       ENCRYPTION_NONE, 12, *packet, buffer, kMaxPacketSize);
   EXPECT_EQ(kMaxPacketSize, encrypted_length);
 
-  framer_.set_version(version());
+  framer_.set_version(transport_version());
   EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
   connection_.ProcessUdpPacket(
       kSelfAddress, kPeerAddress,
@@ -1326,7 +1318,7 @@
       ENCRYPTION_NONE, 12, *packet, buffer, kMaxPacketSize);
   EXPECT_EQ(kMaxPacketSize, encrypted_length);
 
-  framer_.set_version(version());
+  framer_.set_version(transport_version());
   EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
   connection_.ProcessUdpPacket(
       kSelfAddress, kPeerAddress,
@@ -1354,7 +1346,7 @@
   writer_->set_max_packet_size(lower_max_packet_size);
   TestConnection connection(connection_id, kPeerAddress, helper_.get(),
                             alarm_factory_.get(), writer_.get(),
-                            Perspective::IS_CLIENT, version());
+                            Perspective::IS_CLIENT, transport_version());
   EXPECT_EQ(Perspective::IS_CLIENT, connection.perspective());
   EXPECT_EQ(lower_max_packet_size, connection.max_packet_length());
 }
@@ -1512,15 +1504,16 @@
 
 TEST_P(QuicConnectionTest, AckReceiptCausesAckSend) {
   EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
-  QuicPacketNumber original;
-  QuicByteCount packet_size;
-  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
-      .WillOnce(DoAll(SaveArg<2>(&original), SaveArg<3>(&packet_size)));
-  connection_.SendStreamDataWithString(3, "foo", 0, NO_FIN, nullptr);
-  QuicAckFrame frame = ConstructAckFrame(original, original);
+  QuicPacketNumber original, second;
+
+  QuicByteCount packet_size =
+      SendStreamDataToPeer(3, "foo", 0, NO_FIN, &original);  // 1st packet.
+  SendStreamDataToPeer(3, "bar", 0, NO_FIN, &second);        // 2nd packet.
+
+  QuicAckFrame frame = InitAckFrame({{second, second + 1}});
   // First nack triggers early retransmit.
-  SendAlgorithmInterface::CongestionVector lost_packets;
-  lost_packets.push_back(std::make_pair(1, kMaxPacketSize));
+  LostPacketVector lost_packets;
+  lost_packets.push_back(LostPacket(original, kMaxPacketSize));
   EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _, _))
       .WillOnce(SetArgPointee<4>(lost_packets));
   EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
@@ -1568,7 +1561,7 @@
 }
 
 TEST_P(QuicConnectionTest, 20AcksCausesAckSend) {
-  if (connection_.version() > QUIC_VERSION_38) {
+  if (connection_.transport_version() > QUIC_VERSION_38) {
     return;
   }
   EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
@@ -1590,7 +1583,7 @@
 }
 
 TEST_P(QuicConnectionTest, AckNeedsRetransmittableFrames) {
-  if (connection_.version() <= QUIC_VERSION_38) {
+  if (connection_.transport_version() <= QUIC_VERSION_38) {
     return;
   }
 
@@ -1726,7 +1719,7 @@
                                            ConnectionCloseSource::FROM_SELF));
   EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
   EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
-  QuicAckFrame frame(MakeAckFrame(1));
+  QuicAckFrame frame = InitAckFrame(1);
   EXPECT_CALL(visitor_, OnCanWrite()).Times(0);
   ProcessAckPacket(&frame);
 }
@@ -1736,7 +1729,7 @@
   ProcessPacket(1);
 
   QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_, 1);
-  QuicAckFrame frame1 = InitAckFrame(0);
+  QuicAckFrame frame1;
   ProcessAckPacket(&frame1);
 }
 
@@ -1940,7 +1933,7 @@
   EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
 
   // Process an ack to cause the visitor's OnCanWrite to be invoked.
-  QuicAckFrame ack_one = InitAckFrame(0);
+  QuicAckFrame ack_one;
   ProcessAckPacket(3, &ack_one);
 
   EXPECT_EQ(0u, connection_.NumQueuedPackets());
@@ -2082,8 +2075,8 @@
         .WillRepeatedly(Return(false));
   }
 
-  EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _))
-      .WillRepeatedly(testing::Return(QuicTime::Delta::Zero()));
+  EXPECT_CALL(*send_algorithm_, CanSend(_))
+      .WillRepeatedly(testing::Return(true));
 
   connection_.OnCanWrite();
 
@@ -2112,8 +2105,8 @@
 
   // Lose a packet and ensure it triggers retransmission.
   QuicAckFrame nack_two = ConstructAckFrame(3, 2);
-  SendAlgorithmInterface::CongestionVector lost_packets;
-  lost_packets.push_back(std::make_pair(2, kMaxPacketSize));
+  LostPacketVector lost_packets;
+  lost_packets.push_back(LostPacket(2, kMaxPacketSize));
   EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _, _))
       .WillOnce(SetArgPointee<4>(lost_packets));
   EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
@@ -2192,8 +2185,8 @@
   // Lose a packet, ensure it triggers retransmission.
   QuicAckFrame nack_two = ConstructAckFrame(last_packet, last_packet - 1);
   EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
-  SendAlgorithmInterface::CongestionVector lost_packets;
-  lost_packets.push_back(std::make_pair(last_packet - 1, kMaxPacketSize));
+  LostPacketVector lost_packets;
+  lost_packets.push_back(LostPacket(last_packet - 1, kMaxPacketSize));
   EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _, _))
       .WillOnce(SetArgPointee<4>(lost_packets));
   EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
@@ -2304,8 +2297,8 @@
   // Lose a packet which will trigger a pending retransmission.
   QuicAckFrame ack = ConstructAckFrame(last_packet, last_packet - 1);
   EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
-  SendAlgorithmInterface::CongestionVector lost_packets;
-  lost_packets.push_back(std::make_pair(last_packet - 1, kMaxPacketSize));
+  LostPacketVector lost_packets;
+  lost_packets.push_back(LostPacket(last_packet - 1, kMaxPacketSize));
   EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _, _))
       .WillOnce(SetArgPointee<4>(lost_packets));
   EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
@@ -2337,8 +2330,8 @@
   // write blocked, so the packet will be queued.
   BlockOnNextWrite();
 
-  SendAlgorithmInterface::CongestionVector lost_packets;
-  lost_packets.push_back(std::make_pair(2, kMaxPacketSize));
+  LostPacketVector lost_packets;
+  lost_packets.push_back(LostPacket(2, kMaxPacketSize));
   EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _, _))
       .WillOnce(SetArgPointee<4>(lost_packets));
   EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
@@ -2364,16 +2357,16 @@
 
 TEST_P(QuicConnectionTest, RetransmitNackedLargestObserved) {
   EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
-  QuicPacketNumber largest_observed;
-  QuicByteCount packet_size;
-  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
-      .WillOnce(DoAll(SaveArg<2>(&largest_observed), SaveArg<3>(&packet_size)));
-  connection_.SendStreamDataWithString(3, "foo", 0, NO_FIN, nullptr);
+  QuicPacketNumber original, second;
 
-  QuicAckFrame frame = ConstructAckFrame(1, largest_observed);
+  QuicByteCount packet_size =
+      SendStreamDataToPeer(3, "foo", 0, NO_FIN, &original);  // 1st packet.
+  SendStreamDataToPeer(3, "bar", 0, NO_FIN, &second);        // 2nd packet.
+
+  QuicAckFrame frame = InitAckFrame({{second, second + 1}});
   // The first nack should retransmit the largest observed packet.
-  SendAlgorithmInterface::CongestionVector lost_packets;
-  lost_packets.push_back(std::make_pair(1, kMaxPacketSize));
+  LostPacketVector lost_packets;
+  lost_packets.push_back(LostPacket(original, kMaxPacketSize));
   EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _, _))
       .WillOnce(SetArgPointee<4>(lost_packets));
   EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
@@ -2496,9 +2489,9 @@
   nack.largest_observed = 15;
 
   // 14 packets have been NACK'd and lost.
-  SendAlgorithmInterface::CongestionVector lost_packets;
+  LostPacketVector lost_packets;
   for (int i = 1; i < 15; ++i) {
-    lost_packets.push_back(std::make_pair(i, kMaxPacketSize));
+    lost_packets.push_back(LostPacket(i, kMaxPacketSize));
   }
   EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _, _))
       .WillOnce(SetArgPointee<4>(lost_packets));
@@ -2674,8 +2667,7 @@
   connection_.SetEncrypter(ENCRYPTION_NONE, new TaggingEncrypter(0x01));
 
   // Attempt to send a handshake message and have the socket block.
-  EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _))
-      .WillRepeatedly(testing::Return(QuicTime::Delta::Zero()));
+  EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true));
   BlockOnNextWrite();
   connection_.SendStreamDataWithString(1, "foo", 0, NO_FIN, nullptr);
   // The packet should be serialized, but not queued.
@@ -3740,13 +3732,13 @@
   // All packets carry version info till version is negotiated.
   size_t payload_length;
   size_t length = GetPacketLengthForOneStream(
-      connection_.version(), kIncludeVersion, !kIncludeDiversificationNonce,
-      PACKET_8BYTE_CONNECTION_ID, PACKET_1BYTE_PACKET_NUMBER, &payload_length);
+      connection_.transport_version(), kIncludeVersion,
+      !kIncludeDiversificationNonce, PACKET_8BYTE_CONNECTION_ID,
+      PACKET_1BYTE_PACKET_NUMBER, &payload_length);
   connection_.SetMaxPacketLength(length);
 
   // Queue the first packet.
-  EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _))
-      .WillOnce(testing::Return(QuicTime::Delta::FromMicroseconds(10)));
+  EXPECT_CALL(*send_algorithm_, CanSend(_)).WillOnce(testing::Return(false));
   const string payload(payload_length, 'a');
   EXPECT_EQ(0u,
             connection_.SendStreamDataWithString(3, payload, 0, NO_FIN, nullptr)
@@ -3764,7 +3756,7 @@
   // stream frames with non-zero offets will fit within the packet length.
   size_t length =
       2 + GetPacketLengthForOneStream(
-              connection_.version(), kIncludeVersion,
+              connection_.transport_version(), kIncludeVersion,
               !kIncludeDiversificationNonce, PACKET_8BYTE_CONNECTION_ID,
               PACKET_1BYTE_PACKET_NUMBER, &payload_length);
   connection_.SetMaxPacketLength(length);
@@ -4478,8 +4470,8 @@
                                        nullptr);
   // Ack the second packet, which will retransmit the first packet.
   QuicAckFrame ack = ConstructAckFrame(2, 1);
-  SendAlgorithmInterface::CongestionVector lost_packets;
-  lost_packets.push_back(std::make_pair(1, kMaxPacketSize));
+  LostPacketVector lost_packets;
+  lost_packets.push_back(LostPacket(1, kMaxPacketSize));
   EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _, _))
       .WillOnce(SetArgPointee<4>(lost_packets));
   EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
@@ -4610,7 +4602,7 @@
 }
 
 TEST_P(QuicConnectionTest, ServerSendsVersionNegotiationPacket) {
-  connection_.SetSupportedVersions(AllSupportedVersions());
+  connection_.SetSupportedTransportVersions(AllSupportedTransportVersions());
   set_perspective(Perspective::IS_SERVER);
   peer_framer_.set_version_for_tests(QUIC_VERSION_UNSUPPORTED);
 
@@ -4626,26 +4618,26 @@
   size_t encrypted_length = framer_.EncryptPayload(ENCRYPTION_NONE, 12, *packet,
                                                    buffer, kMaxPacketSize);
 
-  framer_.set_version(version());
+  framer_.set_version(transport_version());
   connection_.ProcessUdpPacket(
       kSelfAddress, kPeerAddress,
       QuicReceivedPacket(buffer, encrypted_length, QuicTime::Zero(), false));
   EXPECT_TRUE(writer_->version_negotiation_packet() != nullptr);
 
-  size_t num_versions = arraysize(kSupportedQuicVersions);
+  size_t num_versions = arraysize(kSupportedTransportVersions);
   ASSERT_EQ(num_versions,
             writer_->version_negotiation_packet()->versions.size());
 
-  // We expect all versions in kSupportedQuicVersions to be
+  // We expect all versions in kSupportedTransportVersions to be
   // included in the packet.
   for (size_t i = 0; i < num_versions; ++i) {
-    EXPECT_EQ(kSupportedQuicVersions[i],
+    EXPECT_EQ(kSupportedTransportVersions[i],
               writer_->version_negotiation_packet()->versions[i]);
   }
 }
 
 TEST_P(QuicConnectionTest, ServerSendsVersionNegotiationPacketSocketBlocked) {
-  connection_.SetSupportedVersions(AllSupportedVersions());
+  connection_.SetSupportedTransportVersions(AllSupportedTransportVersions());
   set_perspective(Perspective::IS_SERVER);
   peer_framer_.set_version_for_tests(QUIC_VERSION_UNSUPPORTED);
 
@@ -4661,7 +4653,7 @@
   size_t encrypted_length = framer_.EncryptPayload(ENCRYPTION_NONE, 12, *packet,
                                                    buffer, kMaxPacketSize);
 
-  framer_.set_version(version());
+  framer_.set_version(transport_version());
   BlockOnNextWrite();
   connection_.ProcessUdpPacket(
       kSelfAddress, kPeerAddress,
@@ -4673,21 +4665,21 @@
   connection_.OnCanWrite();
   EXPECT_TRUE(writer_->version_negotiation_packet() != nullptr);
 
-  size_t num_versions = arraysize(kSupportedQuicVersions);
+  size_t num_versions = arraysize(kSupportedTransportVersions);
   ASSERT_EQ(num_versions,
             writer_->version_negotiation_packet()->versions.size());
 
-  // We expect all versions in kSupportedQuicVersions to be
+  // We expect all versions in kSupportedTransportVersions to be
   // included in the packet.
   for (size_t i = 0; i < num_versions; ++i) {
-    EXPECT_EQ(kSupportedQuicVersions[i],
+    EXPECT_EQ(kSupportedTransportVersions[i],
               writer_->version_negotiation_packet()->versions[i]);
   }
 }
 
 TEST_P(QuicConnectionTest,
        ServerSendsVersionNegotiationPacketSocketBlockedDataBuffered) {
-  connection_.SetSupportedVersions(AllSupportedVersions());
+  connection_.SetSupportedTransportVersions(AllSupportedTransportVersions());
   set_perspective(Perspective::IS_SERVER);
   peer_framer_.set_version_for_tests(QUIC_VERSION_UNSUPPORTED);
 
@@ -4703,7 +4695,7 @@
   size_t encryped_length = framer_.EncryptPayload(ENCRYPTION_NONE, 12, *packet,
                                                   buffer, kMaxPacketSize);
 
-  framer_.set_version(version());
+  framer_.set_version(transport_version());
   set_perspective(Perspective::IS_SERVER);
   BlockOnNextWrite();
   writer_->set_is_write_blocked_data_buffered(true);
@@ -4721,8 +4713,8 @@
 
   // Send a version negotiation packet.
   std::unique_ptr<QuicEncryptedPacket> encrypted(
-      peer_framer_.BuildVersionNegotiationPacket(connection_id_,
-                                                 AllSupportedVersions()));
+      peer_framer_.BuildVersionNegotiationPacket(
+          connection_id_, AllSupportedTransportVersions()));
   std::unique_ptr<QuicReceivedPacket> received(
       ConstructReceivedPacket(*encrypted, QuicTime::Zero()));
   connection_.ProcessUdpPacket(kSelfAddress, kPeerAddress, *received);
@@ -4757,7 +4749,7 @@
                                  ConnectionCloseSource::FROM_SELF));
   std::unique_ptr<QuicEncryptedPacket> encrypted(
       framer_.BuildVersionNegotiationPacket(connection_id_,
-                                            AllSupportedVersions()));
+                                            AllSupportedTransportVersions()));
   std::unique_ptr<QuicReceivedPacket> received(
       ConstructReceivedPacket(*encrypted, QuicTime::Zero()));
   connection_.ProcessUdpPacket(kSelfAddress, kPeerAddress, *received);
@@ -4788,9 +4780,9 @@
   nack_three.packets.Add(4);
   nack_three.largest_observed = 4;
 
-  SendAlgorithmInterface::CongestionVector lost_packets;
-  lost_packets.push_back(std::make_pair(1, kMaxPacketSize));
-  lost_packets.push_back(std::make_pair(3, kMaxPacketSize));
+  LostPacketVector lost_packets;
+  lost_packets.push_back(LostPacket(1, kMaxPacketSize));
+  lost_packets.push_back(LostPacket(3, kMaxPacketSize));
   EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _, _))
       .WillOnce(SetArgPointee<4>(lost_packets));
   EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
@@ -4842,31 +4834,31 @@
 }
 
 TEST_P(QuicConnectionTest, SelectMutualVersion) {
-  connection_.SetSupportedVersions(AllSupportedVersions());
+  connection_.SetSupportedTransportVersions(AllSupportedTransportVersions());
   // Set the connection to speak the lowest quic version.
   connection_.set_version(QuicVersionMin());
-  EXPECT_EQ(QuicVersionMin(), connection_.version());
+  EXPECT_EQ(QuicVersionMin(), connection_.transport_version());
 
   // Pass in available versions which includes a higher mutually supported
   // version.  The higher mutually supported version should be selected.
-  QuicVersionVector supported_versions;
-  for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) {
-    supported_versions.push_back(kSupportedQuicVersions[i]);
+  QuicTransportVersionVector supported_versions;
+  for (size_t i = 0; i < arraysize(kSupportedTransportVersions); ++i) {
+    supported_versions.push_back(kSupportedTransportVersions[i]);
   }
   EXPECT_TRUE(connection_.SelectMutualVersion(supported_versions));
-  EXPECT_EQ(QuicVersionMax(), connection_.version());
+  EXPECT_EQ(QuicVersionMax(), connection_.transport_version());
 
   // Expect that the lowest version is selected.
   // Ensure the lowest supported version is less than the max, unless they're
   // the same.
   EXPECT_LE(QuicVersionMin(), QuicVersionMax());
-  QuicVersionVector lowest_version_vector;
+  QuicTransportVersionVector lowest_version_vector;
   lowest_version_vector.push_back(QuicVersionMin());
   EXPECT_TRUE(connection_.SelectMutualVersion(lowest_version_vector));
-  EXPECT_EQ(QuicVersionMin(), connection_.version());
+  EXPECT_EQ(QuicVersionMin(), connection_.transport_version());
 
   // Shouldn't be able to find a mutually supported version.
-  QuicVersionVector unsupported_version;
+  QuicTransportVersionVector unsupported_version;
   unsupported_version.push_back(QUIC_VERSION_UNSUPPORTED);
   EXPECT_FALSE(connection_.SelectMutualVersion(unsupported_version));
 }
@@ -4934,8 +4926,8 @@
   // Now we receive ACK for packets 2 and 3, but importantly missing packet 1
   // which we registered to be notified about.
   QuicAckFrame frame = ConstructAckFrame(3, 1);
-  SendAlgorithmInterface::CongestionVector lost_packets;
-  lost_packets.push_back(std::make_pair(1, kMaxPacketSize));
+  LostPacketVector lost_packets;
+  lost_packets.push_back(LostPacket(1, kMaxPacketSize));
   EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _, _))
       .WillOnce(SetArgPointee<4>(lost_packets));
   EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
@@ -4959,8 +4951,8 @@
 
   // Now we receive ACK for packets 1, 3, and 4 and lose 2.
   QuicAckFrame frame = ConstructAckFrame(4, 2);
-  SendAlgorithmInterface::CongestionVector lost_packets;
-  lost_packets.push_back(std::make_pair(2, kMaxPacketSize));
+  LostPacketVector lost_packets;
+  lost_packets.push_back(LostPacket(2, kMaxPacketSize));
   EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _, _))
       .WillOnce(SetArgPointee<4>(lost_packets));
   EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
@@ -5034,8 +5026,8 @@
   QuicAckFrame frame = ConstructAckFrame(4, 2);
   EXPECT_CALL(*listener, OnPacketRetransmitted(_));
   EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
-  SendAlgorithmInterface::CongestionVector lost_packets;
-  lost_packets.push_back(std::make_pair(2, kMaxPacketSize));
+  LostPacketVector lost_packets;
+  lost_packets.push_back(LostPacket(2, kMaxPacketSize));
   EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _, _))
       .WillOnce(SetArgPointee<4>(lost_packets));
   EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
@@ -5072,10 +5064,10 @@
 TEST_P(QuicConnectionTest, Pacing) {
   TestConnection server(connection_id_, kSelfAddress, helper_.get(),
                         alarm_factory_.get(), writer_.get(),
-                        Perspective::IS_SERVER, version());
+                        Perspective::IS_SERVER, transport_version());
   TestConnection client(connection_id_, kPeerAddress, helper_.get(),
                         alarm_factory_.get(), writer_.get(),
-                        Perspective::IS_CLIENT, version());
+                        Perspective::IS_CLIENT, transport_version());
   EXPECT_FALSE(QuicSentPacketManagerPeer::UsingPacing(
       static_cast<const QuicSentPacketManager*>(
           &client.sent_packet_manager())));
@@ -5133,30 +5125,45 @@
 }
 
 TEST_P(QuicConnectionTest, ReevaluateTimeUntilSendOnAck) {
+  // Enable pacing.
+  EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+  QuicConfig config;
+  connection_.SetFromConfig(config);
+
+  // Send two packets.  One packet is not sufficient because if it gets acked,
+  // there will be no packets in flight after that and the pacer will always
+  // allow the next packet in that situation.
   EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
+  EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true));
   connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 0, NO_FIN,
                                        nullptr);
-
-  // Evaluate CanWrite, and have it return a non-Zero value.
-  EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _))
-      .WillRepeatedly(Return(QuicTime::Delta::FromMilliseconds(1)));
+  connection_.SendStreamDataWithString(kClientDataStreamId1, "bar", 3, NO_FIN,
+                                       nullptr);
   connection_.OnCanWrite();
-  EXPECT_TRUE(connection_.GetSendAlarm()->IsSet());
-  EXPECT_EQ(clock_.Now() + QuicTime::Delta::FromMilliseconds(1),
-            connection_.GetSendAlarm()->deadline());
 
-  // Process an ack and the send alarm will be set to the  new 2ms delay.
+  // Schedule the next packet for a few milliseconds in future.
+  QuicSentPacketManagerPeer::DisablePacerBursts(manager_);
+  QuicTime scheduled_pacing_time =
+      clock_.Now() + QuicTime::Delta::FromMilliseconds(5);
+  QuicSentPacketManagerPeer::SetNextPacedPacketTime(manager_,
+                                                    scheduled_pacing_time);
+
+  // Send a packet and have it be blocked by congestion control.
+  EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(false));
+  connection_.SendStreamDataWithString(kClientDataStreamId1, "baz", 6, NO_FIN,
+                                       nullptr);
+  EXPECT_FALSE(connection_.GetSendAlarm()->IsSet());
+
+  // Process an ack and the send alarm will be set to the new 5ms delay.
   QuicAckFrame ack = InitAckFrame(1);
   EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _, _));
   EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
-  EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _))
-      .WillRepeatedly(Return(QuicTime::Delta::FromMilliseconds(2)));
+  EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true));
   ProcessAckPacket(&ack);
   EXPECT_EQ(1u, writer_->frame_count());
   EXPECT_EQ(1u, writer_->stream_frames().size());
   EXPECT_TRUE(connection_.GetSendAlarm()->IsSet());
-  EXPECT_EQ(clock_.Now() + QuicTime::Delta::FromMilliseconds(2),
-            connection_.GetSendAlarm()->deadline());
+  EXPECT_EQ(scheduled_pacing_time, connection_.GetSendAlarm()->deadline());
   writer_->Reset();
 }
 
diff --git a/net/quic/core/quic_crypto_client_handshaker.cc b/net/quic/core/quic_crypto_client_handshaker.cc
index 0b5d96e..418f9bd 100644
--- a/net/quic/core/quic_crypto_client_handshaker.cc
+++ b/net/quic/core/quic_crypto_client_handshaker.cc
@@ -191,7 +191,7 @@
       crypto_config_->LookupOrCreate(server_id_);
   QuicErrorCode error = crypto_config_->ProcessServerConfigUpdate(
       server_config_update, session()->connection()->clock()->WallNow(),
-      session()->connection()->version(), chlo_hash_, cached,
+      session()->connection()->transport_version(), chlo_hash_, cached,
       crypto_negotiated_params_, &error_details);
 
   if (error != QUIC_NO_ERROR) {
@@ -441,7 +441,7 @@
   string error_details;
   QuicErrorCode error = crypto_config_->ProcessRejection(
       *in, session()->connection()->clock()->WallNow(),
-      session()->connection()->version(), chlo_hash_, cached,
+      session()->connection()->transport_version(), chlo_hash_, cached,
       crypto_negotiated_params_, &error_details);
 
   if (error != QUIC_NO_ERROR) {
@@ -477,7 +477,7 @@
 
   QuicAsyncStatus status = verifier->VerifyProof(
       server_id_.host(), server_id_.port(), cached->server_config(),
-      session()->connection()->version(), chlo_hash_, cached->certs(),
+      session()->connection()->transport_version(), chlo_hash_, cached->certs(),
       cached->cert_sct(), cached->signature(), verify_context_.get(),
       &verify_error_details_, &verify_details_,
       std::unique_ptr<ProofVerifierCallback>(proof_verify_callback));
@@ -618,7 +618,7 @@
   string error_details;
   QuicErrorCode error = crypto_config_->ProcessServerHello(
       *in, session()->connection()->connection_id(),
-      session()->connection()->version(),
+      session()->connection()->transport_version(),
       session()->connection()->server_supported_versions(), cached,
       crypto_negotiated_params_, &error_details);
 
diff --git a/net/quic/core/quic_crypto_client_stream.h b/net/quic/core/quic_crypto_client_stream.h
index af47c9b3..c5c53ab 100644
--- a/net/quic/core/quic_crypto_client_stream.h
+++ b/net/quic/core/quic_crypto_client_stream.h
@@ -54,11 +54,12 @@
   static const int kMaxClientHellos = 3;
 
   // QuicCryptoClientStream creates a HandshakerDelegate at construction time
-  // based on the QuicVersion of the connection. Different HandshakerDelegates
-  // provide implementations of different crypto handshake protocols. Currently
-  // QUIC crypto is the only protocol implemented; a future HandshakerDelegate
-  // will use TLS as the handshake protocol. QuicCryptoClientStream delegates
-  // all of its public methods to its HandshakerDelegate.
+  // based on the QuicTransportVersion of the connection. Different
+  // HandshakerDelegates provide implementations of different crypto handshake
+  // protocols. Currently QUIC crypto is the only protocol implemented; a future
+  // HandshakerDelegate will use TLS as the handshake protocol.
+  // QuicCryptoClientStream delegates all of its public methods to its
+  // HandshakerDelegate.
   //
   // This setup of the crypto stream delegating its implementation to the
   // handshaker results in the handshaker reading and writing bytes on the
diff --git a/net/quic/core/quic_crypto_client_stream_test.cc b/net/quic/core/quic_crypto_client_stream_test.cc
index 0c04daa..e4be8dd 100644
--- a/net/quic/core/quic_crypto_client_stream_test.cc
+++ b/net/quic/core/quic_crypto_client_stream_test.cc
@@ -262,8 +262,8 @@
   // Note: relies on the callback being invoked synchronously
   bool ok = false;
   crypto_config.BuildServerConfigUpdateMessage(
-      session_->connection()->version(), stream()->chlo_hash(), tokens,
-      QuicSocketAddress(QuicIpAddress::Loopback6(), 1234),
+      session_->connection()->transport_version(), stream()->chlo_hash(),
+      tokens, QuicSocketAddress(QuicIpAddress::Loopback6(), 1234),
       QuicIpAddress::Loopback6(), connection_->clock(),
       QuicRandom::GetInstance(), &cache, stream()->crypto_negotiated_params(),
       &network_params, QuicTagVector(),
@@ -366,7 +366,7 @@
     CreateClientSessionForTest(server_id_,
                                /* supports_stateless_rejects= */ true,
                                QuicTime::Delta::FromSeconds(100000),
-                               AllSupportedVersions(), &helper_,
+                               AllSupportedTransportVersions(), &helper_,
                                &alarm_factory_, &client_crypto_config_,
                                &client_connection_, &client_session);
     CHECK(client_session);
@@ -392,7 +392,7 @@
   void InitializeFakeStatelessRejectServer() {
     TestQuicSpdyServerSession* server_session = nullptr;
     CreateServerSessionForTest(server_id_, QuicTime::Delta::FromSeconds(100000),
-                               AllSupportedVersions(), &helper_,
+                               AllSupportedTransportVersions(), &helper_,
                                &alarm_factory_, &server_crypto_config_,
                                &server_compressed_certs_cache_,
                                &server_connection_, &server_session);
diff --git a/net/quic/core/quic_crypto_server_handshaker.cc b/net/quic/core/quic_crypto_server_handshaker.cc
index d5102ce9..dcaf15d 100644
--- a/net/quic/core/quic_crypto_server_handshaker.cc
+++ b/net/quic/core/quic_crypto_server_handshaker.cc
@@ -134,7 +134,7 @@
   validate_client_hello_cb_ = cb.get();
   crypto_config_->ValidateClientHello(
       message, GetClientAddress().host(),
-      session()->connection()->self_address(), version(),
+      session()->connection()->self_address(), transport_version(),
       session()->connection()->clock(), signed_config_, std::move(cb));
 }
 
@@ -271,7 +271,7 @@
   send_server_config_update_cb_ = cb.get();
 
   crypto_config_->BuildServerConfigUpdateMessage(
-      session()->connection()->version(), chlo_hash_,
+      session()->connection()->transport_version(), chlo_hash_,
       previous_source_address_tokens_, session()->connection()->self_address(),
       GetClientAddress().host(), session()->connection()->clock(),
       session()->connection()->random_generator(), compressed_certs_cache_,
@@ -437,12 +437,12 @@
       GenerateConnectionIdForReject(use_stateless_rejects_in_crypto_config);
   crypto_config_->ProcessClientHello(
       result, /*reject_only=*/false, connection->connection_id(),
-      connection->self_address(), GetClientAddress(), version(),
+      connection->self_address(), GetClientAddress(), transport_version(),
       connection->supported_versions(), use_stateless_rejects_in_crypto_config,
       server_designated_connection_id, connection->clock(),
       connection->random_generator(), compressed_certs_cache_,
       crypto_negotiated_params_, signed_config_,
-      QuicCryptoStream::CryptoMessageFramingOverhead(version()),
+      QuicCryptoStream::CryptoMessageFramingOverhead(transport_version()),
       chlo_packet_size_, std::move(done_cb));
 }
 
diff --git a/net/quic/core/quic_crypto_server_handshaker.h b/net/quic/core/quic_crypto_server_handshaker.h
index 6fffb98..5b5d0f8 100644
--- a/net/quic/core/quic_crypto_server_handshaker.h
+++ b/net/quic/core/quic_crypto_server_handshaker.h
@@ -146,8 +146,10 @@
   // Returns the QuicSession that this stream belongs to.
   QuicSession* session() const { return session_; }
 
-  // Returns the QuicVersion of the connection.
-  QuicVersion version() const { return session_->connection()->version(); }
+  // Returns the QuicTransportVersion of the connection.
+  QuicTransportVersion transport_version() const {
+    return session_->connection()->transport_version();
+  }
 
   QuicCryptoServerStream* stream_;
 
diff --git a/net/quic/core/quic_crypto_server_stream.h b/net/quic/core/quic_crypto_server_stream.h
index d777293..625f2fed 100644
--- a/net/quic/core/quic_crypto_server_stream.h
+++ b/net/quic/core/quic_crypto_server_stream.h
@@ -72,11 +72,12 @@
     : public QuicCryptoServerStreamBase {
  public:
   // QuicCryptoServerStream creates a HandshakerDelegate at construction time
-  // based on the QuicVersion of the connection. Different HandshakerDelegates
-  // provide implementations of different crypto handshake protocols. Currently
-  // QUIC crypto is the only protocol implemented; a future HandshakerDelegate
-  // will use TLS as the handshake protocol. QuicCryptoServerStream delegates
-  // all of its public methods to its HandshakerDelegate.
+  // based on the QuicTransportVersion of the connection. Different
+  // HandshakerDelegates provide implementations of different crypto handshake
+  // protocols. Currently QUIC crypto is the only protocol implemented; a future
+  // HandshakerDelegate will use TLS as the handshake protocol.
+  // QuicCryptoServerStream delegates all of its public methods to its
+  // HandshakerDelegate.
   //
   // This setup of the crypto stream delegating its implementation to the
   // handshaker results in the handshaker reading and writing bytes on the
diff --git a/net/quic/core/quic_crypto_server_stream_test.cc b/net/quic/core/quic_crypto_server_stream_test.cc
index 4166a27..f49b5f6 100644
--- a/net/quic/core/quic_crypto_server_stream_test.cc
+++ b/net/quic/core/quic_crypto_server_stream_test.cc
@@ -37,8 +37,8 @@
 }  // namespace net
 
 using std::string;
-using testing::_;
 using testing::NiceMock;
+using testing::_;
 
 namespace net {
 namespace test {
@@ -180,7 +180,8 @@
   crypto_test_utils::FakeClientOptions client_options_;
 
   // Which QUIC versions the client and server support.
-  QuicVersionVector supported_versions_ = AllSupportedVersions();
+  QuicTransportVersionVector supported_versions_ =
+      AllSupportedTransportVersions();
 };
 
 INSTANTIATE_TEST_CASE_P(Tests, QuicCryptoServerStreamTest, testing::Bool());
@@ -552,7 +553,7 @@
 
   // Create a minimal CHLO
   MockClock clock;
-  QuicVersion version = AllSupportedVersions().front();
+  QuicTransportVersion version = AllSupportedTransportVersions().front();
   CryptoHandshakeMessage chlo = crypto_test_utils::GenerateDefaultInchoateCHLO(
       &clock, version, &server_crypto_config_);
 
diff --git a/net/quic/core/quic_crypto_stream.cc b/net/quic/core/quic_crypto_stream.cc
index 197a170..8a81e75 100644
--- a/net/quic/core/quic_crypto_stream.cc
+++ b/net/quic/core/quic_crypto_stream.cc
@@ -19,9 +19,10 @@
 
 namespace net {
 
-#define ENDPOINT                                                               \
-  (session()->perspective() == Perspective::IS_SERVER ? "Server: " : "Client:" \
-                                                                     " ")
+#define ENDPOINT                                                   \
+  (session()->perspective() == Perspective::IS_SERVER ? "Server: " \
+                                                      : "Client:"  \
+                                                        " ")
 
 QuicCryptoStream::QuicCryptoStream(QuicSession* session)
     : QuicStream(kCryptoStreamId, session) {
@@ -33,7 +34,7 @@
 
 // static
 QuicByteCount QuicCryptoStream::CryptoMessageFramingOverhead(
-    QuicVersion version) {
+    QuicTransportVersion version) {
   return QuicPacketCreator::StreamFramePacketOverhead(
       version, PACKET_8BYTE_CONNECTION_ID,
       /*include_version=*/true,
diff --git a/net/quic/core/quic_crypto_stream.h b/net/quic/core/quic_crypto_stream.h
index 8c3a548d..5ffaf45 100644
--- a/net/quic/core/quic_crypto_stream.h
+++ b/net/quic/core/quic_crypto_stream.h
@@ -38,7 +38,8 @@
 
   // Returns the per-packet framing overhead associated with sending a
   // handshake message for |version|.
-  static QuicByteCount CryptoMessageFramingOverhead(QuicVersion version);
+  static QuicByteCount CryptoMessageFramingOverhead(
+      QuicTransportVersion version);
 
   // QuicStream implementation
   void OnDataAvailable() override;
diff --git a/net/quic/core/quic_flags_list.h b/net/quic/core/quic_flags_list.h
index a109aaa..3ffa225d 100644
--- a/net/quic/core/quic_flags_list.h
+++ b/net/quic/core/quic_flags_list.h
@@ -90,7 +90,7 @@
 
 // If true, export a varz mapping QUIC non 0-rtt handshake with corresponding
 // frontend service.
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_account_handshake, false)
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_account_handshake, true)
 
 // Allows the 3RTO QUIC connection option to close a QUIC connection after
 // 3RTOs if there are no open streams.
@@ -99,10 +99,6 @@
 // If true, enable experiment for testing PCC congestion-control.
 QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_pcc, false)
 
-// In QUIC, QuicSession gets notified when stream frames are acked, discarded or
-// retransmitted.
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_use_stream_notifier2, true)
-
 // When true, defaults to BBR congestion control instead of Cubic.
 QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_default_to_bbr, false)
 
@@ -124,18 +120,10 @@
 // If true, enable QUIC v42.
 QUIC_FLAG(bool, FLAGS_quic_enable_version_42, false)
 
-// When true, respect configured limits on header list size.
-QUIC_FLAG(bool, FLAGS_quic_restart_flag_quic_header_list_size, true)
-
 // When true, allows the LRTT connection option to cause QUIC BBR to exit
 // STARTUP when in recovery and there has been no bandwidth increase for 1RTT.
 QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_bbr_exit_startup_on_loss, true)
 
-// If true, application data is saved before consumption in QUIC.
-QUIC_FLAG(bool,
-          FLAGS_quic_reloadable_flag_quic_save_data_before_consumption2,
-          true)
-
 // If buffered data in QUIC stream is less than this threshold, buffers all
 // provided data or asks upper layer for more data.
 QUIC_FLAG(uint32_t, FLAGS_quic_buffered_data_threshold, 8192u)
@@ -143,13 +131,14 @@
 // Max size of data slice in bytes for QUIC stream send buffer.
 QUIC_FLAG(uint32_t, FLAGS_quic_send_buffer_max_data_slice_size, 4096u)
 
+// If true, QUIC supports both QUIC Crypto and TLS 1.3 for the handshake
+// protocol.
+QUIC_FLAG(bool, FLAGS_quic_supports_tls_handshake, false)
+
 // Add 4 new ack decimation modes to QUIC that are entirely time based at 1/4
 // or 1/8 RTT.
 QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_ack_decimation, false)
 
-// Enables using the ConsumeDataFastPath more often for large transfers.
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_consuming_data_faster, true)
-
 // If true, in QUIC, set dispatcher framer\'s version to client packet's
 // version in QuicDispatcher::OnStatelessRejectorProcessDone.
 QUIC_FLAG(
@@ -181,3 +170,10 @@
 QUIC_FLAG(bool,
           FLAGS_quic_reloadable_flag_quic_use_net_byte_order_version_label,
           false)
+
+// If true, send stateless reset token in SHLO. This token is used in IETF
+// public reset packet.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_send_reset_token_in_shlo, false)
+
+// Default enable all cubic fixes in QUIC Cubic by default.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_cubic_fixes, false)
diff --git a/net/quic/core/quic_framer.cc b/net/quic/core/quic_framer.cc
index e8be85c..7408ec28 100644
--- a/net/quic/core/quic_framer.cc
+++ b/net/quic/core/quic_framer.cc
@@ -134,7 +134,7 @@
   }
 }
 
-QuicPacketNumberLength ReadAckPacketNumberLength(QuicVersion version,
+QuicPacketNumberLength ReadAckPacketNumberLength(QuicTransportVersion version,
                                                  uint8_t flags) {
   switch (flags & PACKET_FLAGS_8BYTE_PACKET) {
     case PACKET_FLAGS_8BYTE_PACKET:
@@ -154,7 +154,7 @@
 
 }  // namespace
 
-QuicFramer::QuicFramer(const QuicVersionVector& supported_versions,
+QuicFramer::QuicFramer(const QuicTransportVersionVector& supported_versions,
                        QuicTime creation_time,
                        Perspective perspective)
     : visitor_(nullptr),
@@ -173,7 +173,7 @@
       last_timestamp_(QuicTime::Delta::Zero()),
       data_producer_(nullptr) {
   DCHECK(!supported_versions.empty());
-  quic_version_ = supported_versions_[0];
+  transport_version_ = supported_versions_[0];
   decrypter_ = QuicMakeUnique<NullDecrypter>(perspective);
   encrypter_[ENCRYPTION_NONE] = QuicMakeUnique<NullEncrypter>(perspective);
 }
@@ -181,7 +181,7 @@
 QuicFramer::~QuicFramer() {}
 
 // static
-size_t QuicFramer::GetMinStreamFrameSize(QuicVersion version,
+size_t QuicFramer::GetMinStreamFrameSize(QuicTransportVersion version,
                                          QuicStreamId stream_id,
                                          QuicStreamOffset offset,
                                          bool last_frame_in_packet) {
@@ -192,7 +192,7 @@
 
 // static
 size_t QuicFramer::GetMinAckFrameSize(
-    QuicVersion version,
+    QuicTransportVersion version,
     QuicPacketNumberLength largest_observed_length) {
   size_t min_size = kQuicFrameTypeSize + largest_observed_length +
                     kQuicDeltaTimeLargestObservedSize;
@@ -201,7 +201,7 @@
 
 // static
 size_t QuicFramer::GetStopWaitingFrameSize(
-    QuicVersion version,
+    QuicTransportVersion version,
     QuicPacketNumberLength packet_number_length) {
   size_t min_size = kQuicFrameTypeSize + packet_number_length;
   return min_size;
@@ -248,7 +248,7 @@
 }
 
 // static
-size_t QuicFramer::GetStreamOffsetSize(QuicVersion version,
+size_t QuicFramer::GetStreamOffsetSize(QuicTransportVersion version,
                                        QuicStreamOffset offset) {
   if (version < QUIC_VERSION_41) {
     // 0 is a special case.
@@ -283,7 +283,7 @@
          number_versions * kQuicVersionSize;
 }
 
-bool QuicFramer::IsSupportedVersion(const QuicVersion version) const {
+bool QuicFramer::IsSupportedVersion(const QuicTransportVersion version) const {
   for (size_t i = 0; i < supported_versions_.size(); ++i) {
     if (version == supported_versions_[i]) {
       return true;
@@ -336,7 +336,7 @@
   bool can_truncate =
       frame.type == ACK_FRAME &&
       free_bytes >=
-          GetMinAckFrameSize(quic_version_, PACKET_6BYTE_PACKET_NUMBER);
+          GetMinAckFrameSize(transport_version_, PACKET_6BYTE_PACKET_NUMBER);
   if (can_truncate) {
     // Truncate the frame so the packet will not exceed kMaxPacketSize.
     // Note that we may not use every byte of the writer in this case.
@@ -498,7 +498,7 @@
 // static
 std::unique_ptr<QuicEncryptedPacket> QuicFramer::BuildVersionNegotiationPacket(
     QuicConnectionId connection_id,
-    const QuicVersionVector& versions) {
+    const QuicTransportVersionVector& versions) {
   DCHECK(!versions.empty());
   size_t len = GetVersionNegotiationPacketSize(versions.size());
   std::unique_ptr<char[]> buffer(new char[len]);
@@ -518,7 +518,7 @@
     return nullptr;
   }
 
-  for (QuicVersion version : versions) {
+  for (QuicTransportVersion version : versions) {
     if (FLAGS_quic_reloadable_flag_quic_use_net_byte_order_version_label) {
       QUIC_FLAG_COUNT_N(
           quic_reloadable_flag_quic_use_net_byte_order_version_label, 3, 10);
@@ -559,7 +559,7 @@
   }
 
   if (perspective_ == Perspective::IS_SERVER && public_header.version_flag &&
-      public_header.versions[0] != quic_version_) {
+      public_header.versions[0] != transport_version_) {
     if (!visitor_->OnProtocolVersionMismatch(public_header.versions[0])) {
       return true;
     }
@@ -746,7 +746,7 @@
   if (header.public_header.version_flag) {
     DCHECK_EQ(Perspective::IS_CLIENT, perspective_);
     QuicVersionLabel version_label =
-        QuicVersionToQuicVersionLabel(quic_version_);
+        QuicVersionToQuicVersionLabel(transport_version_);
     if (FLAGS_quic_reloadable_flag_quic_use_net_byte_order_version_label) {
       QUIC_FLAG_COUNT_N(
           quic_reloadable_flag_quic_use_net_byte_order_version_label, 5, 10);
@@ -761,8 +761,9 @@
       }
     }
 
-    QUIC_DVLOG(1) << ENDPOINT << "version = " << quic_version_ << ", label = '"
-                  << QuicVersionLabelToString(version_label) << "'";
+    QUIC_DVLOG(1) << ENDPOINT << "version = " << transport_version_
+                  << ", label = '" << QuicVersionLabelToString(version_label)
+                  << "'";
   }
 
   if (header.public_header.nonce != nullptr &&
@@ -892,8 +893,9 @@
     // framer, then the public flags should be set to something we understand.
     // If not, this raises an error.
     last_version_label_ = version_label;
-    QuicVersion version = QuicVersionLabelToQuicVersion(version_label);
-    if (version == quic_version_ && public_flags > PACKET_PUBLIC_FLAGS_MAX) {
+    QuicTransportVersion version = QuicVersionLabelToQuicVersion(version_label);
+    if (version == transport_version_ &&
+        public_flags > PACKET_PUBLIC_FLAGS_MAX) {
       set_detailed_error("Illegal public flags value.");
       return false;
     }
@@ -923,7 +925,7 @@
 
 // static
 QuicPacketNumberLength QuicFramer::GetMinPacketNumberLength(
-    QuicVersion version,
+    QuicTransportVersion version,
     QuicPacketNumber packet_number) {
   if (packet_number < 1 << (PACKET_1BYTE_PACKET_NUMBER * 8)) {
     return PACKET_1BYTE_PACKET_NUMBER;
@@ -1043,9 +1045,9 @@
 
     if (frame_type & kQuicFrameTypeSpecialMask) {
       // Stream Frame
-      if ((quic_version_ < QUIC_VERSION_41 &&
+      if ((transport_version_ < QUIC_VERSION_41 &&
            (frame_type & kQuicFrameTypeStreamMask_Pre40)) ||
-          (quic_version_ >= QUIC_VERSION_41 &&
+          (transport_version_ >= QUIC_VERSION_41 &&
            ((frame_type & kQuicFrameTypeStreamMask) ==
             kQuicFrameTypeStreamMask))) {
         QuicStreamFrame frame;
@@ -1062,9 +1064,9 @@
       }
 
       // Ack Frame
-      if ((quic_version_ < QUIC_VERSION_41 &&
+      if ((transport_version_ < QUIC_VERSION_41 &&
            (frame_type & kQuicFrameTypeAckMask_Pre40)) ||
-          (quic_version_ >= QUIC_VERSION_41 &&
+          (transport_version_ >= QUIC_VERSION_41 &&
            ((frame_type & kQuicFrameTypeSpecialMask) ==
             kQuicFrameTypeAckMask))) {
         QuicAckFrame frame;
@@ -1242,7 +1244,7 @@
   uint8_t stream_id_length = 0;
   uint8_t offset_length = 4;
   bool has_data_length = true;
-  if (quic_version_ < QUIC_VERSION_41) {
+  if (transport_version_ < QUIC_VERSION_41) {
     stream_flags &= ~kQuicFrameTypeStreamMask_Pre40;
 
     // Read from right to left: StreamID, Offset, Data Length, Fin.
@@ -1316,12 +1318,12 @@
                                  uint8_t frame_type,
                                  QuicAckFrame* ack_frame) {
   bool has_ack_blocks =
-      ExtractBit(frame_type, quic_version_ < QUIC_VERSION_41
+      ExtractBit(frame_type, transport_version_ < QUIC_VERSION_41
                                  ? kQuicHasMultipleAckBlocksOffset_Pre40
                                  : kQuicHasMultipleAckBlocksOffset);
   uint8_t num_ack_blocks = 0;
   uint8_t num_received_packets = 0;
-  if (quic_version_ > QUIC_VERSION_39) {
+  if (transport_version_ > QUIC_VERSION_39) {
     if (has_ack_blocks && !reader->ReadUInt8(&num_ack_blocks)) {
       set_detailed_error("Unable to read num of ack blocks.");
       return false;
@@ -1335,11 +1337,13 @@
   // Determine the two lengths from the frame type: largest acked length,
   // ack block length.
   const QuicPacketNumberLength ack_block_length = ReadAckPacketNumberLength(
-      quic_version_, ExtractBits(frame_type, kQuicSequenceNumberLengthNumBits,
-                                 kActBlockLengthOffset));
+      transport_version_,
+      ExtractBits(frame_type, kQuicSequenceNumberLengthNumBits,
+                  kActBlockLengthOffset));
   const QuicPacketNumberLength largest_acked_length = ReadAckPacketNumberLength(
-      quic_version_, ExtractBits(frame_type, kQuicSequenceNumberLengthNumBits,
-                                 kLargestAckedOffset));
+      transport_version_,
+      ExtractBits(frame_type, kQuicSequenceNumberLengthNumBits,
+                  kLargestAckedOffset));
 
   if (!reader->ReadBytesToUInt64(largest_acked_length,
                                  &ack_frame->largest_observed)) {
@@ -1361,7 +1365,7 @@
   }
 
   if (has_ack_blocks) {
-    if (quic_version_ <= QUIC_VERSION_39 &&
+    if (transport_version_ <= QUIC_VERSION_39 &&
         !reader->ReadUInt8(&num_ack_blocks)) {
       set_detailed_error("Unable to read num of ack blocks.");
       return false;
@@ -1419,7 +1423,7 @@
     }
   }
 
-  if (quic_version_ <= QUIC_VERSION_39 &&
+  if (transport_version_ <= QUIC_VERSION_39 &&
       !reader->ReadUInt8(&num_received_packets)) {
     set_detailed_error("Unable to read num received packets.");
     return false;
@@ -1507,7 +1511,7 @@
     return false;
   }
 
-  if (quic_version_ <= QUIC_VERSION_39) {
+  if (transport_version_ <= QUIC_VERSION_39) {
     if (!reader->ReadUInt64(&frame->byte_offset)) {
       set_detailed_error("Unable to read rst stream sent byte offset.");
       return false;
@@ -1527,7 +1531,7 @@
 
   frame->error_code = static_cast<QuicRstStreamErrorCode>(error_code);
 
-  if (quic_version_ > QUIC_VERSION_39) {
+  if (transport_version_ > QUIC_VERSION_39) {
     if (!reader->ReadUInt64(&frame->byte_offset)) {
       set_detailed_error("Unable to read rst stream sent byte offset.");
       return false;
@@ -1620,7 +1624,7 @@
 
 void QuicFramer::ProcessPaddingFrame(QuicDataReader* reader,
                                      QuicPaddingFrame* frame) {
-  if (quic_version_ <= QUIC_VERSION_37) {
+  if (transport_version_ <= QUIC_VERSION_37) {
     frame->num_padding_bytes = reader->BytesRemaining() + 1;
     reader->ReadRemainingPayload();
     return;
@@ -1637,7 +1641,7 @@
 
 // static
 QuicStringPiece QuicFramer::GetAssociatedDataFromEncryptedPacket(
-    QuicVersion version,
+    QuicTransportVersion version,
     const QuicEncryptedPacket& encrypted,
     QuicConnectionIdLength connection_id_length,
     bool includes_version,
@@ -1688,7 +1692,7 @@
                                   char* buffer) {
   size_t output_length = 0;
   if (!encrypter_[level]->EncryptPacket(
-          quic_version_, packet_number,
+          transport_version_, packet_number,
           QuicStringPiece(buffer, ad_len),  // Associated data
           QuicStringPiece(buffer + ad_len, total_len - ad_len),  // Plaintext
           buffer + ad_len,  // Destination buffer
@@ -1707,7 +1711,7 @@
                                   size_t buffer_len) {
   DCHECK(encrypter_[level] != nullptr);
 
-  QuicStringPiece associated_data = packet.AssociatedData(quic_version_);
+  QuicStringPiece associated_data = packet.AssociatedData(transport_version_);
   // Copy in the header, because the encrypter only populates the encrypted
   // plaintext content.
   const size_t ad_len = associated_data.length();
@@ -1715,8 +1719,8 @@
   // Encrypt the plaintext into the buffer.
   size_t output_length = 0;
   if (!encrypter_[level]->EncryptPacket(
-          quic_version_, packet_number, associated_data,
-          packet.Plaintext(quic_version_), buffer + ad_len, &output_length,
+          transport_version_, packet_number, associated_data,
+          packet.Plaintext(transport_version_), buffer + ad_len, &output_length,
           buffer_len - ad_len)) {
     RaiseError(QUIC_ENCRYPTION_FAILURE);
     return 0;
@@ -1751,12 +1755,12 @@
   QuicStringPiece encrypted = encrypted_reader->ReadRemainingPayload();
   DCHECK(decrypter_ != nullptr);
   QuicStringPiece associated_data = GetAssociatedDataFromEncryptedPacket(
-      quic_version_, packet, header.public_header.connection_id_length,
+      transport_version_, packet, header.public_header.connection_id_length,
       header.public_header.version_flag, header.public_header.nonce != nullptr,
       header.public_header.packet_number_length);
 
   bool success = decrypter_->DecryptPacket(
-      quic_version_, header.packet_number, associated_data, encrypted,
+      transport_version_, header.packet_number, associated_data, encrypted,
       decrypted_buffer, decrypted_length, buffer_length);
   if (success) {
     visitor_->OnDecryptedPacket(decrypter_level_);
@@ -1780,7 +1784,7 @@
 
     if (try_alternative_decryption) {
       success = alternative_decrypter_->DecryptPacket(
-          quic_version_, header.packet_number, associated_data, encrypted,
+          transport_version_, header.packet_number, associated_data, encrypted,
           decrypted_buffer, decrypted_length, buffer_length);
     }
     if (success) {
@@ -1825,11 +1829,11 @@
 
   AckFrameInfo ack_info = GetAckFrameInfo(ack);
   QuicPacketNumberLength largest_acked_length =
-      GetMinPacketNumberLength(quic_version_, ack.largest_observed);
+      GetMinPacketNumberLength(transport_version_, ack.largest_observed);
   QuicPacketNumberLength ack_block_length =
-      GetMinPacketNumberLength(quic_version_, ack_info.max_block_length);
+      GetMinPacketNumberLength(transport_version_, ack_info.max_block_length);
 
-  ack_size = GetMinAckFrameSize(quic_version_, largest_acked_length);
+  ack_size = GetMinAckFrameSize(transport_version_, largest_acked_length);
   // First ack block length.
   ack_size += ack_block_length;
   if (ack_info.num_ack_blocks != 0) {
@@ -1850,15 +1854,15 @@
     QuicPacketNumberLength packet_number_length) {
   switch (frame.type) {
     case STREAM_FRAME:
-      return GetMinStreamFrameSize(quic_version_, frame.stream_frame->stream_id,
-                                   frame.stream_frame->offset,
-                                   last_frame_in_packet) +
+      return GetMinStreamFrameSize(
+                 transport_version_, frame.stream_frame->stream_id,
+                 frame.stream_frame->offset, last_frame_in_packet) +
              frame.stream_frame->data_length;
     case ACK_FRAME: {
       return GetAckFrameSize(*frame.ack_frame, packet_number_length);
     }
     case STOP_WAITING_FRAME:
-      return GetStopWaitingFrameSize(quic_version_, packet_number_length);
+      return GetStopWaitingFrameSize(transport_version_, packet_number_length);
     case MTU_DISCOVERY_FRAME:
     // MTU discovery frames are serialized as ping frames.
     case PING_FRAME:
@@ -1897,7 +1901,7 @@
       if (frame.stream_frame == nullptr) {
         QUIC_BUG << "Failed to append STREAM frame with no stream_frame.";
       }
-      if (quic_version_ < QUIC_VERSION_41) {
+      if (transport_version_ < QUIC_VERSION_41) {
         // Fin bit.
         type_byte |= frame.stream_frame->fin ? kQuicStreamFinMask_Pre40 : 0;
 
@@ -1909,7 +1913,7 @@
         // Offset 3 bits.
         type_byte <<= kQuicStreamShift_Pre40;
         const size_t offset_len =
-            GetStreamOffsetSize(quic_version_, frame.stream_frame->offset);
+            GetStreamOffsetSize(transport_version_, frame.stream_frame->offset);
         if (offset_len > 0) {
           type_byte |= offset_len - 1;
         }
@@ -1928,8 +1932,8 @@
 
         // Offset 2 bits.
         uint8_t offset_len_encode = 3;
-        switch (
-            GetStreamOffsetSize(quic_version_, frame.stream_frame->offset)) {
+        switch (GetStreamOffsetSize(transport_version_,
+                                    frame.stream_frame->offset)) {
           case 0:
             offset_len_encode = 0;
             break;
@@ -2020,7 +2024,7 @@
     QUIC_BUG << "Writing stream id size failed.";
     return false;
   }
-  if (!AppendStreamOffset(GetStreamOffsetSize(quic_version_, frame.offset),
+  if (!AppendStreamOffset(GetStreamOffsetSize(transport_version_, frame.offset),
                           frame.offset, writer)) {
     QUIC_BUG << "Writing offset size failed.";
     return false;
@@ -2053,9 +2057,9 @@
   return true;
 }
 
-void QuicFramer::set_version(const QuicVersion version) {
+void QuicFramer::set_version(const QuicTransportVersion version) {
   DCHECK(IsSupportedVersion(version)) << QuicVersionToString(version);
-  quic_version_ = version;
+  transport_version_ = version;
 }
 
 bool QuicFramer::AppendAckFrameAndTypeByte(const QuicAckFrame& frame,
@@ -2063,13 +2067,13 @@
   const AckFrameInfo new_ack_info = GetAckFrameInfo(frame);
   QuicPacketNumber largest_acked = frame.largest_observed;
   QuicPacketNumberLength largest_acked_length =
-      GetMinPacketNumberLength(quic_version_, largest_acked);
-  QuicPacketNumberLength ack_block_length =
-      GetMinPacketNumberLength(quic_version_, new_ack_info.max_block_length);
+      GetMinPacketNumberLength(transport_version_, largest_acked);
+  QuicPacketNumberLength ack_block_length = GetMinPacketNumberLength(
+      transport_version_, new_ack_info.max_block_length);
   // Calculate available bytes for timestamps and ack blocks.
   int32_t available_timestamp_and_ack_block_bytes =
       writer->capacity() - writer->length() - ack_block_length -
-      GetMinAckFrameSize(quic_version_, largest_acked_length) -
+      GetMinAckFrameSize(transport_version_, largest_acked_length) -
       (new_ack_info.num_ack_blocks != 0 ? kNumberOfAckBlocksSize : 0);
   DCHECK_LE(0, available_timestamp_and_ack_block_bytes);
 
@@ -2078,8 +2082,9 @@
   // Whether there are multiple ack blocks.
   uint8_t type_byte = 0;
   SetBit(&type_byte, new_ack_info.num_ack_blocks != 0,
-         quic_version_ < QUIC_VERSION_41 ? kQuicHasMultipleAckBlocksOffset_Pre40
-                                         : kQuicHasMultipleAckBlocksOffset);
+         transport_version_ < QUIC_VERSION_41
+             ? kQuicHasMultipleAckBlocksOffset_Pre40
+             : kQuicHasMultipleAckBlocksOffset);
 
   SetBits(&type_byte, GetPacketNumberFlags(largest_acked_length),
           kQuicSequenceNumberLengthNumBits, kLargestAckedOffset);
@@ -2087,7 +2092,7 @@
   SetBits(&type_byte, GetPacketNumberFlags(ack_block_length),
           kQuicSequenceNumberLengthNumBits, kActBlockLengthOffset);
 
-  if (quic_version_ < QUIC_VERSION_41) {
+  if (transport_version_ < QUIC_VERSION_41) {
     type_byte |= kQuicFrameTypeAckMask_Pre40;
   } else {
     type_byte |= kQuicFrameTypeAckMask;
@@ -2108,7 +2113,7 @@
     num_ack_blocks = std::numeric_limits<uint8_t>::max();
   }
 
-  if (quic_version_ > QUIC_VERSION_39) {
+  if (transport_version_ > QUIC_VERSION_39) {
     if (num_ack_blocks > 0 && !writer->WriteBytes(&num_ack_blocks, 1)) {
       return false;
     }
@@ -2137,7 +2142,7 @@
     return false;
   }
 
-  if (quic_version_ <= QUIC_VERSION_39) {
+  if (transport_version_ <= QUIC_VERSION_39) {
     if (num_ack_blocks > 0) {
       if (!writer->WriteBytes(&num_ack_blocks, 1)) {
         return false;
@@ -2237,7 +2242,7 @@
   }
 
   uint8_t num_received_packets = frame.received_packet_times.size();
-  if (quic_version_ <= QUIC_VERSION_39) {
+  if (transport_version_ <= QUIC_VERSION_39) {
     if (!writer->WriteBytes(&num_received_packets, 1)) {
       return false;
     }
@@ -2312,7 +2317,7 @@
              << " is too small for least_unacked_delta: " << least_unacked_delta
              << " packet_number:" << header.packet_number
              << " least_unacked:" << frame.least_unacked
-             << " version:" << quic_version_;
+             << " version:" << transport_version_;
     return false;
   }
   if (!AppendPacketNumber(header.public_header.packet_number_length,
@@ -2330,7 +2335,7 @@
     return false;
   }
 
-  if (quic_version_ <= QUIC_VERSION_39) {
+  if (transport_version_ <= QUIC_VERSION_39) {
     if (!writer->WriteUInt64(frame.byte_offset)) {
       return false;
     }
@@ -2341,7 +2346,7 @@
     return false;
   }
 
-  if (quic_version_ > QUIC_VERSION_39) {
+  if (transport_version_ > QUIC_VERSION_39) {
     if (!writer->WriteUInt64(frame.byte_offset)) {
       return false;
     }
@@ -2402,7 +2407,7 @@
 
 bool QuicFramer::AppendPaddingFrame(const QuicPaddingFrame& frame,
                                     QuicDataWriter* writer) {
-  if (quic_version_ <= QUIC_VERSION_37) {
+  if (transport_version_ <= QUIC_VERSION_37) {
     writer->WritePadding();
     return true;
   }
@@ -2428,7 +2433,8 @@
 }
 
 Endianness QuicFramer::endianness() const {
-  return quic_version_ > QUIC_VERSION_38 ? NETWORK_BYTE_ORDER : HOST_BYTE_ORDER;
+  return transport_version_ > QUIC_VERSION_38 ? NETWORK_BYTE_ORDER
+                                              : HOST_BYTE_ORDER;
 }
 
 bool QuicFramer::StartsWithChlo(QuicStreamId id,
diff --git a/net/quic/core/quic_framer.h b/net/quic/core/quic_framer.h
index a814622..375e8d4 100644
--- a/net/quic/core/quic_framer.h
+++ b/net/quic/core/quic_framer.h
@@ -72,7 +72,8 @@
   // |quic_version_|. The visitor should return true after it updates the
   // version of the |framer_| to |received_version| or false to stop processing
   // this packet.
-  virtual bool OnProtocolVersionMismatch(QuicVersion received_version) = 0;
+  virtual bool OnProtocolVersionMismatch(
+      QuicTransportVersion received_version) = 0;
 
   // Called when a new packet has been received, before it
   // has been validated or processed.
@@ -149,14 +150,14 @@
   // QuicDecrypter for level ENCRYPTION_NONE. |supported_versions| specifies the
   // list of supported QUIC versions. |quic_version_| is set to the maximum
   // version in |supported_versions|.
-  QuicFramer(const QuicVersionVector& supported_versions,
+  QuicFramer(const QuicTransportVersionVector& supported_versions,
              QuicTime creation_time,
              Perspective perspective);
 
   virtual ~QuicFramer();
 
   // Returns true if |version| is a supported protocol version.
-  bool IsSupportedVersion(const QuicVersion version) const;
+  bool IsSupportedVersion(const QuicTransportVersion version) const;
 
   // Set callbacks to be called from the framer.  A visitor must be set, or
   // else the framer will likely crash.  It is acceptable for the visitor
@@ -164,18 +165,18 @@
   // will be used.
   void set_visitor(QuicFramerVisitorInterface* visitor) { visitor_ = visitor; }
 
-  const QuicVersionVector& supported_versions() const {
+  const QuicTransportVersionVector& supported_versions() const {
     return supported_versions_;
   }
 
-  QuicVersion version() const { return quic_version_; }
+  QuicTransportVersion transport_version() const { return transport_version_; }
 
-  void set_version(const QuicVersion version);
+  void set_version(const QuicTransportVersion version);
 
   // Does not DCHECK for supported version. Used by tests to set unsupported
   // version to trigger version negotiation.
-  void set_version_for_tests(const QuicVersion version) {
-    quic_version_ = version;
+  void set_version_for_tests(const QuicTransportVersion version) {
+    transport_version_ = version;
   }
 
   QuicErrorCode error() const { return error_; }
@@ -188,18 +189,18 @@
   bool ProcessPacket(const QuicEncryptedPacket& packet);
 
   // Largest size in bytes of all stream frame fields without the payload.
-  static size_t GetMinStreamFrameSize(QuicVersion version,
+  static size_t GetMinStreamFrameSize(QuicTransportVersion version,
                                       QuicStreamId stream_id,
                                       QuicStreamOffset offset,
                                       bool last_frame_in_packet);
   // Size in bytes of all ack frame fields without the missing packets or ack
   // blocks.
   static size_t GetMinAckFrameSize(
-      QuicVersion version,
+      QuicTransportVersion version,
       QuicPacketNumberLength largest_observed_length);
   // Size in bytes of a stop waiting frame.
   static size_t GetStopWaitingFrameSize(
-      QuicVersion version,
+      QuicTransportVersion version,
       QuicPacketNumberLength packet_number_length);
   // Size in bytes of all reset stream frame fields.
   static size_t GetRstStreamFrameSize();
@@ -215,7 +216,7 @@
   // Size in bytes required to serialize the stream id.
   static size_t GetStreamIdSize(QuicStreamId stream_id);
   // Size in bytes required to serialize the stream offset.
-  static size_t GetStreamOffsetSize(QuicVersion version,
+  static size_t GetStreamOffsetSize(QuicTransportVersion version,
                                     QuicStreamOffset offset);
   // Size in bytes required for a serialized version negotiation packet
   static size_t GetVersionNegotiationPacketSize(size_t number_versions);
@@ -232,7 +233,7 @@
   // Returns the associated data from the encrypted packet |encrypted| as a
   // stringpiece.
   static QuicStringPiece GetAssociatedDataFromEncryptedPacket(
-      QuicVersion version,
+      QuicTransportVersion version,
       const QuicEncryptedPacket& encrypted,
       QuicConnectionIdLength connection_id_length,
       bool includes_version,
@@ -254,10 +255,10 @@
   // Returns a new version negotiation packet.
   static std::unique_ptr<QuicEncryptedPacket> BuildVersionNegotiationPacket(
       QuicConnectionId connection_id,
-      const QuicVersionVector& versions);
+      const QuicTransportVersionVector& versions);
 
   // If header.public_header.version_flag is set, the version in the
-  // packet will be set -- but it will be set from quic_version_ not
+  // packet will be set -- but it will be set from transport_version_ not
   // header.public_header.versions.
   bool AppendPacketHeader(const QuicPacketHeader& header,
                           QuicDataWriter* writer);
@@ -326,12 +327,13 @@
 
   // The minimum packet number length required to represent |packet_number|.
   static QuicPacketNumberLength GetMinPacketNumberLength(
-      QuicVersion version,
+      QuicTransportVersion version,
       QuicPacketNumber packet_number);
 
-  void SetSupportedVersions(const QuicVersionVector& versions) {
+  void SetSupportedTransportVersions(
+      const QuicTransportVersionVector& versions) {
     supported_versions_ = versions;
-    quic_version_ = versions[0];
+    transport_version_ = versions[0];
   }
 
   // Returns true if data_producer_ is not null.
@@ -347,7 +349,7 @@
 
   Perspective perspective() const { return perspective_; }
 
-  QuicVersionLabel last_version_label() { return last_version_label_; }
+  QuicVersionLabel last_version_label() const { return last_version_label_; }
 
   void set_data_producer(QuicStreamFrameDataProducer* data_producer) {
     data_producer_ = data_producer;
@@ -521,12 +523,12 @@
   // The last QUIC version label received.
   QuicVersionLabel last_version_label_;
   // Version of the protocol being used.
-  QuicVersion quic_version_;
+  QuicTransportVersion transport_version_;
   // This vector contains QUIC versions which we currently support.
   // This should be ordered such that the highest supported version is the first
   // element, with subsequent elements in descending order (versions can be
   // skipped as necessary).
-  QuicVersionVector supported_versions_;
+  QuicTransportVersionVector supported_versions_;
   // Primary decrypter used to decrypt packets during parsing.
   std::unique_ptr<QuicDecrypter> decrypter_;
   // Alternative decrypter that can also be used to decrypt packets.
diff --git a/net/quic/core/quic_framer_test.cc b/net/quic/core/quic_framer_test.cc
index f7b53e1..c76105ff 100644
--- a/net/quic/core/quic_framer_test.cc
+++ b/net/quic/core/quic_framer_test.cc
@@ -53,7 +53,8 @@
   ~TestEncrypter() override {}
   bool SetKey(QuicStringPiece key) override { return true; }
   bool SetNoncePrefix(QuicStringPiece nonce_prefix) override { return true; }
-  bool EncryptPacket(QuicVersion version,
+  bool SetIV(QuicStringPiece iv) override { return true; }
+  bool EncryptPacket(QuicTransportVersion version,
                      QuicPacketNumber packet_number,
                      QuicStringPiece associated_data,
                      QuicStringPiece plaintext,
@@ -79,7 +80,7 @@
   QuicStringPiece GetKey() const override { return QuicStringPiece(); }
   QuicStringPiece GetNoncePrefix() const override { return QuicStringPiece(); }
 
-  QuicVersion version_;
+  QuicTransportVersion version_;
   QuicPacketNumber packet_number_;
   string associated_data_;
   string plaintext_;
@@ -90,6 +91,7 @@
   ~TestDecrypter() override {}
   bool SetKey(QuicStringPiece key) override { return true; }
   bool SetNoncePrefix(QuicStringPiece nonce_prefix) override { return true; }
+  bool SetIV(QuicStringPiece iv) override { return true; }
   bool SetPreliminaryKey(QuicStringPiece key) override {
     QUIC_BUG << "should not be called";
     return false;
@@ -97,7 +99,7 @@
   bool SetDiversificationNonce(const DiversificationNonce& key) override {
     return true;
   }
-  bool DecryptPacket(QuicVersion version,
+  bool DecryptPacket(QuicTransportVersion version,
                      QuicPacketNumber packet_number,
                      QuicStringPiece associated_data,
                      QuicStringPiece ciphertext,
@@ -116,7 +118,7 @@
   QuicStringPiece GetNoncePrefix() const override { return QuicStringPiece(); }
   // Use a distinct value starting with 0xFFFFFF, which is never used by TLS.
   uint32_t cipher_id() const override { return 0xFFFFFFF2; }
-  QuicVersion version_;
+  QuicTransportVersion version_;
   QuicPacketNumber packet_number_;
   string associated_data_;
   string ciphertext_;
@@ -152,7 +154,7 @@
     version_negotiation_packet_.reset(new QuicVersionNegotiationPacket(packet));
   }
 
-  bool OnProtocolVersionMismatch(QuicVersion version) override {
+  bool OnProtocolVersionMismatch(QuicTransportVersion version) override {
     QUIC_DLOG(INFO) << "QuicFramer Version Mismatch, version: " << version;
     ++version_mismatch_;
     return true;
@@ -271,13 +273,15 @@
 
 using PacketFragments = std::vector<struct PacketFragment>;
 
-class QuicFramerTest : public QuicTestWithParam<QuicVersion> {
+class QuicFramerTest : public QuicTestWithParam<QuicTransportVersion> {
  public:
   QuicFramerTest()
       : encrypter_(new test::TestEncrypter()),
         decrypter_(new test::TestDecrypter()),
         start_(QuicTime::Zero() + QuicTime::Delta::FromMicroseconds(0x10)),
-        framer_(AllSupportedVersions(), start_, Perspective::IS_SERVER) {
+        framer_(AllSupportedTransportVersions(),
+                start_,
+                Perspective::IS_SERVER) {
     version_ = GetParam();
     framer_.set_version(version_);
     framer_.SetDecrypter(ENCRYPTION_NONE, decrypter_);
@@ -305,16 +309,17 @@
                       << " actual: " << encrypter_->packet_number_;
       return false;
     }
-    if (packet->AssociatedData(framer_.version()) !=
+    if (packet->AssociatedData(framer_.transport_version()) !=
         encrypter_->associated_data_) {
       QUIC_LOG(ERROR) << "Encrypted incorrect associated data.  expected "
-                      << packet->AssociatedData(framer_.version())
+                      << packet->AssociatedData(framer_.transport_version())
                       << " actual: " << encrypter_->associated_data_;
       return false;
     }
-    if (packet->Plaintext(framer_.version()) != encrypter_->plaintext_) {
+    if (packet->Plaintext(framer_.transport_version()) !=
+        encrypter_->plaintext_) {
       QUIC_LOG(ERROR) << "Encrypted incorrect plaintext data.  expected "
-                      << packet->Plaintext(framer_.version())
+                      << packet->Plaintext(framer_.transport_version())
                       << " actual: " << encrypter_->plaintext_;
       return false;
     }
@@ -332,12 +337,12 @@
       return false;
     }
     if (QuicFramer::GetAssociatedDataFromEncryptedPacket(
-            framer_.version(), encrypted, PACKET_8BYTE_CONNECTION_ID,
+            framer_.transport_version(), encrypted, PACKET_8BYTE_CONNECTION_ID,
             includes_version, includes_diversification_nonce,
             PACKET_6BYTE_PACKET_NUMBER) != decrypter_->associated_data_) {
       QUIC_LOG(ERROR) << "Decrypted incorrect associated data.  expected "
                       << QuicFramer::GetAssociatedDataFromEncryptedPacket(
-                             framer_.version(), encrypted,
+                             framer_.transport_version(), encrypted,
                              PACKET_8BYTE_CONNECTION_ID, includes_version,
                              includes_diversification_nonce,
                              PACKET_6BYTE_PACKET_NUMBER)
@@ -346,8 +351,9 @@
     }
     QuicStringPiece ciphertext(
         encrypted.AsStringPiece().substr(GetStartOfEncryptedData(
-            framer_.version(), PACKET_8BYTE_CONNECTION_ID, includes_version,
-            includes_diversification_nonce, PACKET_6BYTE_PACKET_NUMBER)));
+            framer_.transport_version(), PACKET_8BYTE_CONNECTION_ID,
+            includes_version, includes_diversification_nonce,
+            PACKET_6BYTE_PACKET_NUMBER)));
     if (ciphertext != decrypter_->ciphertext_) {
       QUIC_LOG(ERROR) << "Decrypted incorrect ciphertext data.  expected "
                       << ciphertext << " actual: " << decrypter_->ciphertext_;
@@ -446,7 +452,7 @@
 
   test::TestEncrypter* encrypter_;
   test::TestDecrypter* decrypter_;
-  QuicVersion version_;
+  QuicTransportVersion version_;
   QuicTime start_;
   QuicFramer framer_;
   test::TestQuicVisitor visitor_;
@@ -455,7 +461,7 @@
 // Run all framer tests with all supported versions of QUIC.
 INSTANTIATE_TEST_CASE_P(QuicFramerTests,
                         QuicFramerTest,
-                        ::testing::ValuesIn(kSupportedQuicVersions));
+                        ::testing::ValuesIn(kSupportedTransportVersions));
 
 TEST_P(QuicFramerTest, CalculatePacketNumberFromWireNearEpochStart) {
   // A few quick manual sanity checks.
@@ -580,7 +586,7 @@
   // clang-format on
 
   const size_t header_size = GetPacketHeaderSize(
-      framer_.version(), PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
+      framer_.transport_version(), PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
       !kIncludeDiversificationNonce, PACKET_6BYTE_PACKET_NUMBER);
 
   memset(packet + header_size, 0, kMaxPacketSize - header_size);
@@ -623,7 +629,7 @@
   // clang-format on
 
   PacketFragments& fragments =
-      framer_.version() <= QUIC_VERSION_38 ? packet38 : packet39;
+      framer_.transport_version() <= QUIC_VERSION_38 ? packet38 : packet39;
 
   std::unique_ptr<QuicEncryptedPacket> encrypted(
       AssemblePacketFromFragments(fragments));
@@ -667,7 +673,7 @@
   // clang-format on
 
   PacketFragments& fragments =
-      framer_.version() <= QUIC_VERSION_38 ? packet : packet39;
+      framer_.transport_version() <= QUIC_VERSION_38 ? packet : packet39;
   std::unique_ptr<QuicEncryptedPacket> encrypted(
       AssemblePacketFromFragments(fragments));
   EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
@@ -715,7 +721,7 @@
   // clang-format on
 
   PacketFragments& fragments =
-      framer_.version() <= QUIC_VERSION_38 ? packet : packet39;
+      framer_.transport_version() <= QUIC_VERSION_38 ? packet : packet39;
   std::unique_ptr<QuicEncryptedPacket> encrypted(
       AssemblePacketFromFragments(fragments));
   EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
@@ -760,7 +766,7 @@
   // clang-format on
 
   PacketFragments& fragments =
-      framer_.version() <= QUIC_VERSION_38 ? packet : packet39;
+      framer_.transport_version() <= QUIC_VERSION_38 ? packet : packet39;
   std::unique_ptr<QuicEncryptedPacket> encrypted(
       AssemblePacketFromFragments(fragments));
   EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
@@ -804,7 +810,7 @@
   // clang-format on
 
   PacketFragments& fragments =
-      framer_.version() <= QUIC_VERSION_38 ? packet : packet39;
+      framer_.transport_version() <= QUIC_VERSION_38 ? packet : packet39;
   std::unique_ptr<QuicEncryptedPacket> encrypted(
       AssemblePacketFromFragments(fragments));
   EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
@@ -950,7 +956,8 @@
   // clang-format on
 
   QuicEncryptedPacket encrypted(
-      AsChars(framer_.version() <= QUIC_VERSION_38 ? packet : packet39),
+      AsChars(framer_.transport_version() <= QUIC_VERSION_38 ? packet
+                                                             : packet39),
       arraysize(packet), false);
   QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
   EXPECT_TRUE(framer_.ProcessPacket(encrypted));
@@ -998,7 +1005,8 @@
   // clang-format on
 
   QuicEncryptedPacket encrypted(
-      AsChars(framer_.version() <= QUIC_VERSION_38 ? packet : packet39),
+      AsChars(framer_.transport_version() <= QUIC_VERSION_38 ? packet
+                                                             : packet39),
       arraysize(packet), false);
   EXPECT_TRUE(framer_.ProcessPacket(encrypted));
   EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
@@ -1039,7 +1047,7 @@
   };
   // clang-format on
 
-  if (framer_.version() > QUIC_VERSION_37) {
+  if (framer_.transport_version() > QUIC_VERSION_37) {
     return;
   }
 
@@ -1057,8 +1065,9 @@
   // A packet with no frames is not acceptable.
   CheckProcessingFails(
       packet,
-      GetPacketHeaderSize(framer_.version(), PACKET_8BYTE_CONNECTION_ID,
-                          !kIncludeVersion, !kIncludeDiversificationNonce,
+      GetPacketHeaderSize(framer_.transport_version(),
+                          PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
+                          !kIncludeDiversificationNonce,
                           PACKET_6BYTE_PACKET_NUMBER),
       "Packet has no frames.", QUIC_MISSING_PAYLOAD);
 }
@@ -1150,13 +1159,13 @@
   };
   // clang-format on
 
-  if (framer_.version() <= QUIC_VERSION_37) {
+  if (framer_.transport_version() <= QUIC_VERSION_37) {
     return;
   }
   unsigned char* p = packet;
-  if (framer_.version() > QUIC_VERSION_39) {
+  if (framer_.transport_version() > QUIC_VERSION_39) {
     p = packet41;
-  } else if (framer_.version() > QUIC_VERSION_38) {
+  } else if (framer_.transport_version() > QUIC_VERSION_38) {
     p = packet39;
   }
 
@@ -1274,9 +1283,9 @@
   };
 
   PacketFragments& fragments =
-      framer_.version() > QUIC_VERSION_39
+      framer_.transport_version() > QUIC_VERSION_39
           ? packet41
-          : (framer_.version() > QUIC_VERSION_38 ? packet39 : packet);
+          : (framer_.transport_version() > QUIC_VERSION_38 ? packet39 : packet);
   std::unique_ptr<QuicEncryptedPacket> encrypted(
       AssemblePacketFromFragments(fragments));
   EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
@@ -1378,9 +1387,9 @@
   // clang-format on
 
   unsigned char* p = packet;
-  if (framer_.version() > QUIC_VERSION_39) {
+  if (framer_.transport_version() > QUIC_VERSION_39) {
     p = packet41;
-  } else if (framer_.version() > QUIC_VERSION_38) {
+  } else if (framer_.transport_version() > QUIC_VERSION_38) {
     p = packet39;
   }
   QuicEncryptedPacket encrypted(AsChars(p), arraysize(packet), false);
@@ -1484,9 +1493,9 @@
   };
 
   PacketFragments& fragments =
-      framer_.version() > QUIC_VERSION_39
+      framer_.transport_version() > QUIC_VERSION_39
           ? packet41
-          : (framer_.version() > QUIC_VERSION_38 ? packet39 : packet);
+          : (framer_.transport_version() > QUIC_VERSION_38 ? packet39 : packet);
   std::unique_ptr<QuicEncryptedPacket> encrypted(
       AssemblePacketFromFragments(fragments));
   EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
@@ -1603,9 +1612,9 @@
   };
 
   PacketFragments& fragments =
-      framer_.version() > QUIC_VERSION_39
+      framer_.transport_version() > QUIC_VERSION_39
           ? packet41
-          : (framer_.version() > QUIC_VERSION_38 ? packet39 : packet);
+          : (framer_.transport_version() > QUIC_VERSION_38 ? packet39 : packet);
   std::unique_ptr<QuicEncryptedPacket> encrypted(
       AssemblePacketFromFragments(fragments));
   EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
@@ -1722,9 +1731,9 @@
   };
 
   PacketFragments& fragments =
-      framer_.version() > QUIC_VERSION_39
+      framer_.transport_version() > QUIC_VERSION_39
           ? packet41
-          : (framer_.version() > QUIC_VERSION_38 ? packet39 : packet);
+          : (framer_.transport_version() > QUIC_VERSION_38 ? packet39 : packet);
   std::unique_ptr<QuicEncryptedPacket> encrypted(
       AssemblePacketFromFragments(fragments));
   EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
@@ -1850,9 +1859,9 @@
   };
 
   PacketFragments& fragments =
-      framer_.version() > QUIC_VERSION_39
+      framer_.transport_version() > QUIC_VERSION_39
           ? packet41
-          : (framer_.version() > QUIC_VERSION_38 ? packet39 : packet);
+          : (framer_.transport_version() > QUIC_VERSION_38 ? packet39 : packet);
   std::unique_ptr<QuicEncryptedPacket> encrypted(
       AssemblePacketFromFragments(fragments));
   EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
@@ -1951,9 +1960,9 @@
   // clang-format on
 
   unsigned char* p = packet;
-  if (framer_.version() > QUIC_VERSION_39) {
+  if (framer_.transport_version() > QUIC_VERSION_39) {
     p = packet41;
-  } else if (framer_.version() > QUIC_VERSION_38) {
+  } else if (framer_.transport_version() > QUIC_VERSION_38) {
     p = packet39;
   }
   QuicEncryptedPacket encrypted(AsChars(p), arraysize(packet), false);
@@ -2075,9 +2084,9 @@
   };
 
   PacketFragments& fragments =
-      framer_.version() > QUIC_VERSION_39
+      framer_.transport_version() > QUIC_VERSION_39
           ? packet41
-          : (framer_.version() > QUIC_VERSION_38 ? packet39 : packet);
+          : (framer_.transport_version() > QUIC_VERSION_38 ? packet39 : packet);
   std::unique_ptr<QuicEncryptedPacket> encrypted(
       AssemblePacketFromFragments(fragments));
   EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
@@ -2189,9 +2198,9 @@
   };
 
   PacketFragments& fragments =
-      framer_.version() > QUIC_VERSION_39
+      framer_.transport_version() > QUIC_VERSION_39
           ? packet41
-          : (framer_.version() > QUIC_VERSION_38 ? packet39 : packet);
+          : (framer_.transport_version() > QUIC_VERSION_38 ? packet39 : packet);
   std::unique_ptr<QuicEncryptedPacket> encrypted(
       AssemblePacketFromFragments(fragments));
   EXPECT_EQ(!FLAGS_quic_reloadable_flag_sanitize_framer_addrange_input,
@@ -2287,9 +2296,9 @@
   // clang-format on
 
   PacketFragments& fragments =
-      framer_.version() > QUIC_VERSION_39
+      framer_.transport_version() > QUIC_VERSION_39
           ? packet41
-          : (framer_.version() > QUIC_VERSION_38 ? packet39 : packet);
+          : (framer_.transport_version() > QUIC_VERSION_38 ? packet39 : packet);
   std::unique_ptr<QuicEncryptedPacket> encrypted(
       AssemblePacketFromFragments(fragments));
   EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
@@ -2516,9 +2525,9 @@
 
   // clang-format on
   PacketFragments& fragments =
-      framer_.version() > QUIC_VERSION_39
+      framer_.transport_version() > QUIC_VERSION_39
           ? packet41
-          : (framer_.version() > QUIC_VERSION_38 ? packet39 : packet);
+          : (framer_.transport_version() > QUIC_VERSION_38 ? packet39 : packet);
 
   std::unique_ptr<QuicEncryptedPacket> encrypted(
       AssemblePacketFromFragments(fragments));
@@ -2582,7 +2591,7 @@
   // clang-format on
 
   PacketFragments& fragments =
-      framer_.version() > QUIC_VERSION_38 ? packet39 : packet;
+      framer_.transport_version() > QUIC_VERSION_38 ? packet39 : packet;
   std::unique_ptr<QuicEncryptedPacket> encrypted(
       AssemblePacketFromFragments(fragments));
   EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
@@ -2634,7 +2643,8 @@
   // clang-format on
 
   QuicEncryptedPacket encrypted(
-      AsChars(framer_.version() <= QUIC_VERSION_38 ? packet : packet39),
+      AsChars(framer_.transport_version() <= QUIC_VERSION_38 ? packet
+                                                             : packet39),
       arraysize(packet), false);
   EXPECT_FALSE(framer_.ProcessPacket(encrypted));
   EXPECT_EQ(QUIC_INVALID_STOP_WAITING_DATA, framer_.error());
@@ -2719,9 +2729,9 @@
   };
 
   PacketFragments& fragments =
-      framer_.version() > QUIC_VERSION_39
+      framer_.transport_version() > QUIC_VERSION_39
           ? packet41
-          : (framer_.version() > QUIC_VERSION_38 ? packet39 : packet);
+          : (framer_.transport_version() > QUIC_VERSION_38 ? packet39 : packet);
   std::unique_ptr<QuicEncryptedPacket> encrypted(
       AssemblePacketFromFragments(fragments));
   EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
@@ -2798,7 +2808,7 @@
   // clang-format on
 
   PacketFragments& fragments =
-      framer_.version() > QUIC_VERSION_38 ? packet39 : packet;
+      framer_.transport_version() > QUIC_VERSION_38 ? packet39 : packet;
   std::unique_ptr<QuicEncryptedPacket> encrypted(
       AssemblePacketFromFragments(fragments));
   EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
@@ -2885,7 +2895,7 @@
   // clang-format on
 
   PacketFragments& fragments =
-      framer_.version() > QUIC_VERSION_38 ? packet39 : packet;
+      framer_.transport_version() > QUIC_VERSION_38 ? packet39 : packet;
   std::unique_ptr<QuicEncryptedPacket> encrypted(
       AssemblePacketFromFragments(fragments));
   EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
@@ -2950,7 +2960,7 @@
   // clang-format on
 
   PacketFragments& fragments =
-      framer_.version() > QUIC_VERSION_38 ? packet39 : packet;
+      framer_.transport_version() > QUIC_VERSION_38 ? packet39 : packet;
   std::unique_ptr<QuicEncryptedPacket> encrypted(
       AssemblePacketFromFragments(fragments));
   EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
@@ -3006,7 +3016,7 @@
   // clang-format on
 
   PacketFragments& fragments =
-      framer_.version() > QUIC_VERSION_38 ? packet39 : packet;
+      framer_.transport_version() > QUIC_VERSION_38 ? packet39 : packet;
   std::unique_ptr<QuicEncryptedPacket> encrypted(
       AssemblePacketFromFragments(fragments));
   EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
@@ -3051,7 +3061,8 @@
   // clang-format on
 
   QuicEncryptedPacket encrypted(
-      AsChars(framer_.version() <= QUIC_VERSION_38 ? packet : packet39),
+      AsChars(framer_.transport_version() <= QUIC_VERSION_38 ? packet
+                                                             : packet39),
       arraysize(packet), false);
   EXPECT_TRUE(framer_.ProcessPacket(encrypted));
 
@@ -3374,9 +3385,9 @@
   // clang-format on
 
   uint64_t header_size = GetPacketHeaderSize(
-      framer_.version(), PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
+      framer_.transport_version(), PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
       !kIncludeDiversificationNonce, PACKET_6BYTE_PACKET_NUMBER);
-  memset((framer_.version() <= QUIC_VERSION_38 ? packet : packet39) +
+  memset((framer_.transport_version() <= QUIC_VERSION_38 ? packet : packet39) +
              header_size + 1,
          0x00, kMaxPacketSize - header_size - 1);
 
@@ -3385,12 +3396,13 @@
 
   test::CompareCharArraysWithHexError(
       "constructed packet", data->data(), data->length(),
-      AsChars(framer_.version() <= QUIC_VERSION_38 ? packet : packet39),
+      AsChars(framer_.transport_version() <= QUIC_VERSION_38 ? packet
+                                                             : packet39),
       arraysize(packet));
 }
 
 TEST_P(QuicFramerTest, BuildStreamFramePacketWithNewPaddingFrame) {
-  if (framer_.version() <= QUIC_VERSION_37) {
+  if (framer_.transport_version() <= QUIC_VERSION_37) {
     return;
   }
   QuicPacketHeader header;
@@ -3495,9 +3507,9 @@
   ASSERT_TRUE(data != nullptr);
 
   unsigned char* p = packet;
-  if (framer_.version() > QUIC_VERSION_39) {
+  if (framer_.transport_version() > QUIC_VERSION_39) {
     p = packet41;
-  } else if (framer_.version() > QUIC_VERSION_38) {
+  } else if (framer_.transport_version() > QUIC_VERSION_38) {
     p = packet39;
   }
   QuicEncryptedPacket encrypted(AsChars(p), arraysize(packet), false);
@@ -3546,9 +3558,9 @@
   // clang-format on
 
   uint64_t header_size = GetPacketHeaderSize(
-      framer_.version(), PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
+      framer_.transport_version(), PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
       !kIncludeDiversificationNonce, PACKET_4BYTE_PACKET_NUMBER);
-  memset((framer_.version() <= QUIC_VERSION_38 ? packet : packet39) +
+  memset((framer_.transport_version() <= QUIC_VERSION_38 ? packet : packet39) +
              header_size + 1,
          0x00, kMaxPacketSize - header_size - 1);
 
@@ -3557,7 +3569,8 @@
 
   test::CompareCharArraysWithHexError(
       "constructed packet", data->data(), data->length(),
-      AsChars(framer_.version() <= QUIC_VERSION_38 ? packet : packet39),
+      AsChars(framer_.transport_version() <= QUIC_VERSION_38 ? packet
+                                                             : packet39),
       arraysize(packet));
 }
 
@@ -3600,9 +3613,9 @@
   // clang-format on
 
   uint64_t header_size = GetPacketHeaderSize(
-      framer_.version(), PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
+      framer_.transport_version(), PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
       !kIncludeDiversificationNonce, PACKET_2BYTE_PACKET_NUMBER);
-  memset((framer_.version() <= QUIC_VERSION_38 ? packet : packet39) +
+  memset((framer_.transport_version() <= QUIC_VERSION_38 ? packet : packet39) +
              header_size + 1,
          0x00, kMaxPacketSize - header_size - 1);
 
@@ -3611,7 +3624,8 @@
 
   test::CompareCharArraysWithHexError(
       "constructed packet", data->data(), data->length(),
-      AsChars(framer_.version() <= QUIC_VERSION_38 ? packet : packet39),
+      AsChars(framer_.transport_version() <= QUIC_VERSION_38 ? packet
+                                                             : packet39),
       arraysize(packet));
 }
 
@@ -3641,7 +3655,7 @@
   // clang-format on
 
   uint64_t header_size = GetPacketHeaderSize(
-      framer_.version(), PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
+      framer_.transport_version(), PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
       !kIncludeDiversificationNonce, PACKET_1BYTE_PACKET_NUMBER);
   memset(packet + header_size + 1, 0x00, kMaxPacketSize - header_size - 1);
 
@@ -3737,9 +3751,9 @@
   ASSERT_TRUE(data != nullptr);
 
   unsigned char* p = packet;
-  if (framer_.version() > QUIC_VERSION_39) {
+  if (framer_.transport_version() > QUIC_VERSION_39) {
     p = packet41;
-  } else if (framer_.version() > QUIC_VERSION_38) {
+  } else if (framer_.transport_version() > QUIC_VERSION_38) {
     p = packet39;
   }
   test::CompareCharArraysWithHexError("constructed packet", data->data(),
@@ -3825,9 +3839,9 @@
   ASSERT_TRUE(data != nullptr);
 
   unsigned char* p = packet;
-  if (framer_.version() > QUIC_VERSION_39) {
+  if (framer_.transport_version() > QUIC_VERSION_39) {
     p = packet41;
-  } else if (framer_.version() > QUIC_VERSION_38) {
+  } else if (framer_.transport_version() > QUIC_VERSION_38) {
     p = packet39;
   }
   test::CompareCharArraysWithHexError("constructed packet", data->data(),
@@ -3849,8 +3863,8 @@
 
   QuicConnectionId connection_id = kConnectionId;
   std::unique_ptr<QuicEncryptedPacket> data(
-      framer_.BuildVersionNegotiationPacket(connection_id,
-                                            SupportedVersions(GetParam())));
+      framer_.BuildVersionNegotiationPacket(
+          connection_id, SupportedTransportVersions(GetParam())));
   test::CompareCharArraysWithHexError("constructed packet", data->data(),
                                       data->length(), AsChars(packet),
                                       arraysize(packet));
@@ -3936,9 +3950,9 @@
   };
   // clang-format on
   unsigned char* p = packet;
-  if (framer_.version() > QUIC_VERSION_39) {
+  if (framer_.transport_version() > QUIC_VERSION_39) {
     p = packet41;
-  } else if (framer_.version() > QUIC_VERSION_38) {
+  } else if (framer_.transport_version() > QUIC_VERSION_38) {
     p = packet39;
   }
 
@@ -4030,10 +4044,10 @@
   // clang-format on
   unsigned char* p = packet;
   size_t packet_size = arraysize(packet);
-  if (framer_.version() > QUIC_VERSION_39) {
+  if (framer_.transport_version() > QUIC_VERSION_39) {
     p = packet41;
     packet_size = arraysize(packet41);
-  } else if (framer_.version() > QUIC_VERSION_38) {
+  } else if (framer_.transport_version() > QUIC_VERSION_38) {
     p = packet39;
     packet_size = arraysize(packet39);
   }
@@ -4182,9 +4196,9 @@
   };
   // clang-format on
   unsigned char* p = packet;
-  if (framer_.version() > QUIC_VERSION_39) {
+  if (framer_.transport_version() > QUIC_VERSION_39) {
     p = packet41;
-  } else if (framer_.version() > QUIC_VERSION_38) {
+  } else if (framer_.transport_version() > QUIC_VERSION_38) {
     p = packet39;
   }
 
@@ -4496,9 +4510,9 @@
   };
   // clang-format on
   unsigned char* p = packet;
-  if (framer_.version() > QUIC_VERSION_39) {
+  if (framer_.transport_version() > QUIC_VERSION_39) {
     p = packet41;
-  } else if (framer_.version() > QUIC_VERSION_38) {
+  } else if (framer_.transport_version() > QUIC_VERSION_38) {
     p = packet39;
   }
 
@@ -4559,7 +4573,8 @@
 
   test::CompareCharArraysWithHexError(
       "constructed packet", data->data(), data->length(),
-      AsChars(framer_.version() <= QUIC_VERSION_38 ? packet : packet39),
+      AsChars(framer_.transport_version() <= QUIC_VERSION_38 ? packet
+                                                             : packet39),
       arraysize(packet));
 }
 
@@ -4643,9 +4658,9 @@
   ASSERT_TRUE(data != nullptr);
 
   unsigned char* p = packet;
-  if (framer_.version() > QUIC_VERSION_39) {
+  if (framer_.transport_version() > QUIC_VERSION_39) {
     p = packet41;
-  } else if (framer_.version() > QUIC_VERSION_38) {
+  } else if (framer_.transport_version() > QUIC_VERSION_38) {
     p = packet39;
   }
   QuicEncryptedPacket encrypted(AsChars(p), arraysize(packet), false);
@@ -4719,7 +4734,8 @@
 
   test::CompareCharArraysWithHexError(
       "constructed packet", data->data(), data->length(),
-      AsChars(framer_.version() <= QUIC_VERSION_38 ? packet : packet39),
+      AsChars(framer_.transport_version() <= QUIC_VERSION_38 ? packet
+                                                             : packet39),
       arraysize(packet));
 }
 
@@ -4792,7 +4808,8 @@
 
   test::CompareCharArraysWithHexError(
       "constructed packet", data->data(), data->length(),
-      AsChars(framer_.version() <= QUIC_VERSION_38 ? packet : packet39),
+      AsChars(framer_.transport_version() <= QUIC_VERSION_38 ? packet
+                                                             : packet39),
       arraysize(packet));
 }
 
@@ -4852,7 +4869,8 @@
 
   test::CompareCharArraysWithHexError(
       "constructed packet", data->data(), data->length(),
-      AsChars(framer_.version() <= QUIC_VERSION_38 ? packet : packet39),
+      AsChars(framer_.transport_version() <= QUIC_VERSION_38 ? packet
+                                                             : packet39),
       arraysize(packet));
 }
 
@@ -4905,7 +4923,8 @@
 
   test::CompareCharArraysWithHexError(
       "constructed packet", data->data(), data->length(),
-      AsChars(framer_.version() <= QUIC_VERSION_38 ? packet : packet39),
+      AsChars(framer_.transport_version() <= QUIC_VERSION_38 ? packet
+                                                             : packet39),
       arraysize(packet));
 }
 
@@ -4951,7 +4970,8 @@
 
   test::CompareCharArraysWithHexError(
       "constructed packet", data->data(), data->length(),
-      AsChars(framer_.version() <= QUIC_VERSION_38 ? packet : packet39),
+      AsChars(framer_.transport_version() <= QUIC_VERSION_38 ? packet
+                                                             : packet39),
       arraysize(packet));
 }
 
@@ -4998,7 +5018,8 @@
 
   test::CompareCharArraysWithHexError(
       "constructed packet", data->data(), data->length(),
-      AsChars(framer_.version() <= QUIC_VERSION_38 ? packet : packet39),
+      AsChars(framer_.transport_version() <= QUIC_VERSION_38 ? packet
+                                                             : packet39),
       arraysize(packet));
 }
 
@@ -5121,7 +5142,8 @@
   // clang-format on
 
   std::unique_ptr<QuicPacket> raw(new QuicPacket(
-      AsChars(framer_.version() <= QUIC_VERSION_38 ? packet : packet39),
+      AsChars(framer_.transport_version() <= QUIC_VERSION_38 ? packet
+                                                             : packet39),
       arraysize(packet), false, PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
       !kIncludeDiversificationNonce, PACKET_6BYTE_PACKET_NUMBER));
   char buffer[kMaxPacketSize];
@@ -5173,7 +5195,8 @@
   // clang-format on
 
   std::unique_ptr<QuicPacket> raw(new QuicPacket(
-      AsChars(framer_.version() <= QUIC_VERSION_38 ? packet : packet39),
+      AsChars(framer_.transport_version() <= QUIC_VERSION_38 ? packet
+                                                             : packet39),
       arraysize(packet), false, PACKET_8BYTE_CONNECTION_ID, kIncludeVersion,
       !kIncludeDiversificationNonce, PACKET_6BYTE_PACKET_NUMBER));
   char buffer[kMaxPacketSize];
@@ -5416,9 +5439,9 @@
   EXPECT_CALL(visitor, OnDecryptedPacket(_));
 
   unsigned char* p = packet;
-  if (framer_.version() > QUIC_VERSION_39) {
+  if (framer_.transport_version() > QUIC_VERSION_39) {
     p = packet41;
-  } else if (framer_.version() > QUIC_VERSION_38) {
+  } else if (framer_.transport_version() > QUIC_VERSION_38) {
     p = packet39;
   }
   QuicEncryptedPacket encrypted(AsChars(p), arraysize(packet), false);
@@ -5445,8 +5468,8 @@
                        new NullDecrypter(framer_.perspective()));
   framer_.SetEncrypter(ENCRYPTION_NONE,
                        new NullEncrypter(framer_.perspective()));
-  QuicVersionVector versions;
-  versions.push_back(framer_.version());
+  QuicTransportVersionVector versions;
+  versions.push_back(framer_.transport_version());
   std::unique_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket(
       42, false, false, kTestQuicStreamId, kTestString,
       PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_PACKET_NUMBER, &versions));
@@ -5481,8 +5504,8 @@
                        new NullDecrypter(framer_.perspective()));
   framer_.SetEncrypter(ENCRYPTION_NONE,
                        new NullEncrypter(framer_.perspective()));
-  QuicVersionVector versions;
-  versions.push_back(framer_.version());
+  QuicTransportVersionVector versions;
+  versions.push_back(framer_.transport_version());
   std::unique_ptr<QuicEncryptedPacket> packet(ConstructMisFramedEncryptedPacket(
       42, false, false, kTestQuicStreamId, kTestString,
       PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_PACKET_NUMBER, &versions,
@@ -5516,7 +5539,7 @@
 
 // target function to be fuzzed by Dr. Fuzz
 void QuicFramerFuzzFunc(unsigned char* data, size_t size) {
-  QuicFramer framer(AllSupportedVersions(), QuicTime::Zero(),
+  QuicFramer framer(AllSupportedTransportVersions(), QuicTime::Zero(),
                     Perspective::IS_SERVER);
   const char* const packet_bytes = reinterpret_cast<const char*>(data);
 
@@ -5618,9 +5641,9 @@
   // clang-format on
 
   unsigned char* p = packet;
-  if (framer_.version() > QUIC_VERSION_39) {
+  if (framer_.transport_version() > QUIC_VERSION_39) {
     p = packet41;
-  } else if (framer_.version() > QUIC_VERSION_38) {
+  } else if (framer_.transport_version() > QUIC_VERSION_38) {
     p = packet39;
   }
   QuicFramerFuzzFunc(p, arraysize(packet));
diff --git a/net/quic/core/quic_header_list.cc b/net/quic/core/quic_header_list.cc
index 3a7fe39c..f9d02301 100644
--- a/net/quic/core/quic_header_list.cc
+++ b/net/quic/core/quic_header_list.cc
@@ -30,29 +30,18 @@
 QuicHeaderList::~QuicHeaderList() {}
 
 void QuicHeaderList::OnHeaderBlockStart() {
-  if (FLAGS_quic_restart_flag_quic_header_list_size) {
-    QUIC_BUG_IF(current_header_list_size_ != 0)
-        << "OnHeaderBlockStart called more than once!";
-  } else {
-    QUIC_BUG_IF(uncompressed_header_bytes_ != 0)
-        << "OnHeaderBlockStart called more than once!";
-  }
+  QUIC_BUG_IF(current_header_list_size_ != 0)
+      << "OnHeaderBlockStart called more than once!";
 }
 
 void QuicHeaderList::OnHeader(QuicStringPiece name, QuicStringPiece value) {
   // Avoid infinite buffering of headers. No longer store headers
   // once the current headers are over the limit.
-  if (FLAGS_quic_restart_flag_quic_header_list_size) {
-    if (current_header_list_size_ < max_header_list_size_) {
-      current_header_list_size_ += name.size();
-      current_header_list_size_ += value.size();
-      current_header_list_size_ += kPerHeaderOverhead;
-      header_list_.emplace_back(string(name), string(value));
-    }
-  } else {
-    if (uncompressed_header_bytes_ == 0 || !header_list_.empty()) {
-      header_list_.emplace_back(string(name), string(value));
-    }
+  if (current_header_list_size_ < max_header_list_size_) {
+    current_header_list_size_ += name.size();
+    current_header_list_size_ += value.size();
+    current_header_list_size_ += kPerHeaderOverhead;
+    header_list_.emplace_back(string(name), string(value));
   }
 }
 
@@ -60,14 +49,8 @@
                                       size_t compressed_header_bytes) {
   uncompressed_header_bytes_ = uncompressed_header_bytes;
   compressed_header_bytes_ = compressed_header_bytes;
-  if (FLAGS_quic_restart_flag_quic_header_list_size) {
-    if (current_header_list_size_ > max_header_list_size_) {
-      Clear();
-    }
-  } else {
-    if (uncompressed_header_bytes_ > max_header_list_size_) {
-      Clear();
-    }
+  if (current_header_list_size_ > max_header_list_size_) {
+    Clear();
   }
 }
 
diff --git a/net/quic/core/quic_header_list_test.cc b/net/quic/core/quic_header_list_test.cc
index 8e45463..789bb08b 100644
--- a/net/quic/core/quic_header_list_test.cc
+++ b/net/quic/core/quic_header_list_test.cc
@@ -32,13 +32,8 @@
   headers.OnHeader(key, value);
   // Send a second header exceeding max_header_list_size.
   headers.OnHeader(key + "2", value);
-  if (FLAGS_quic_restart_flag_quic_header_list_size) {
-    // We should not allocate more memory after exceeding max_header_list_size.
-    EXPECT_LT(headers.DebugString().size(), 2 * value.size());
-  } else {
-    // Demonstrates previous behavior.
-    EXPECT_GE(headers.DebugString().size(), 2 * value.size());
-  }
+  // We should not allocate more memory after exceeding max_header_list_size.
+  EXPECT_LT(headers.DebugString().size(), 2 * value.size());
   size_t total_bytes = 2 * (key.size() + value.size()) + 1;
   headers.OnHeaderBlockEnd(total_bytes, total_bytes);
   EXPECT_TRUE(headers.empty());
diff --git a/net/quic/core/quic_headers_stream.cc b/net/quic/core/quic_headers_stream.cc
index 97d72c90..2d0c584 100644
--- a/net/quic/core/quic_headers_stream.cc
+++ b/net/quic/core/quic_headers_stream.cc
@@ -57,40 +57,6 @@
   }
 }
 
-QuicConsumedData QuicHeadersStream::WritevDataInner(
-    QuicIOVector iov,
-    QuicStreamOffset offset,
-    bool fin,
-    QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
-  if (!session()->use_stream_notifier() ||
-      session()->save_data_before_consumption()) {
-    // If data is saved before consumption, unacked_headers has been populated.
-    return QuicStream::WritevDataInner(iov, offset, fin,
-                                       std::move(ack_listener));
-  }
-  QuicConsumedData consumed =
-      QuicStream::WritevDataInner(iov, offset, fin, nullptr);
-  if (consumed.bytes_consumed == 0 || ack_listener == nullptr) {
-    // No need to update unacked_headers_ if no byte is consumed or there is no
-    // ack listener.
-    return consumed;
-  }
-
-  if (!unacked_headers_.empty() &&
-      (offset == unacked_headers_.back().headers_stream_offset +
-                     unacked_headers_.back().full_length) &&
-      ack_listener == unacked_headers_.back().ack_listener) {
-    // Try to combine with latest inserted entry if they belong to the same
-    // header (i.e., having contiguous offset and the same ack listener).
-    unacked_headers_.back().full_length += consumed.bytes_consumed;
-    unacked_headers_.back().unacked_length += consumed.bytes_consumed;
-  } else {
-    unacked_headers_.push_back(CompressedHeaderInfo(
-        offset, consumed.bytes_consumed, std::move(ack_listener)));
-  }
-  return consumed;
-}
-
 void QuicHeadersStream::OnStreamFrameAcked(const QuicStreamFrame& frame,
                                            QuicTime::Delta ack_delay_time) {
   QuicStreamOffset offset = frame.offset;
diff --git a/net/quic/core/quic_headers_stream.h b/net/quic/core/quic_headers_stream.h
index 3493987..5fc4f2e 100644
--- a/net/quic/core/quic_headers_stream.h
+++ b/net/quic/core/quic_headers_stream.h
@@ -46,16 +46,6 @@
  private:
   friend class test::QuicHeadersStreamPeer;
 
-  // Override to store mapping from offset, length to ack_listener. This
-  // ack_listener is notified once data within [offset, offset + length] is
-  // acked or retransmitted.
-  QuicConsumedData WritevDataInner(
-      QuicIOVector iov,
-      QuicStreamOffset offset,
-      bool fin,
-      QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener)
-      override;
-
   // CompressedHeaderInfo includes simple information of a header, including
   // offset in headers stream, unacked length and ack listener of this header.
   struct QUIC_EXPORT_PRIVATE CompressedHeaderInfo {
diff --git a/net/quic/core/quic_headers_stream_test.cc b/net/quic/core/quic_headers_stream_test.cc
index 8a22e872..b67c26f 100644
--- a/net/quic/core/quic_headers_stream_test.cc
+++ b/net/quic/core/quic_headers_stream_test.cc
@@ -31,13 +31,13 @@
 #include "net/test/gtest_util.h"
 
 using std::string;
-using testing::_;
 using testing::AtLeast;
 using testing::InSequence;
 using testing::Invoke;
 using testing::Return;
 using testing::StrictMock;
 using testing::WithArgs;
+using testing::_;
 
 namespace net {
 namespace test {
@@ -133,7 +133,7 @@
   DISALLOW_COPY_AND_ASSIGN(ForceHolAckListener);
 };
 
-typedef testing::tuple<QuicVersion, Perspective> TestParamsTuple;
+typedef testing::tuple<QuicTransportVersion, Perspective> TestParamsTuple;
 
 struct TestParams {
   explicit TestParams(TestParamsTuple params)
@@ -142,7 +142,7 @@
                    << ", perspective: " << perspective;
   }
 
-  QuicVersion version;
+  QuicTransportVersion version;
   Perspective perspective;
 };
 
@@ -170,7 +170,7 @@
         new SpdyFramer(SpdyFramer::ENABLE_COMPRESSION));
     deframer_ = std::unique_ptr<Http2DecoderAdapter>(new Http2DecoderAdapter());
     deframer_->set_visitor(&visitor_);
-    EXPECT_EQ(version(), session_.connection()->version());
+    EXPECT_EQ(transport_version(), session_.connection()->transport_version());
     EXPECT_TRUE(headers_stream_ != nullptr);
     connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
     client_id_1_ =
@@ -329,11 +329,13 @@
 
   Perspective perspective() const { return test_params_.perspective; }
 
-  QuicVersion version() const { return test_params_.version; }
+  QuicTransportVersion transport_version() const {
+    return test_params_.version;
+  }
 
-  QuicVersionVector GetVersion() {
-    QuicVersionVector versions;
-    versions.push_back(version());
+  QuicTransportVersionVector GetVersion() {
+    QuicTransportVersionVector versions;
+    versions.push_back(transport_version());
     return versions;
   }
 
@@ -375,7 +377,7 @@
 INSTANTIATE_TEST_CASE_P(
     Tests,
     QuicHeadersStreamTest,
-    ::testing::Combine(::testing::ValuesIn(AllSupportedVersions()),
+    ::testing::Combine(::testing::ValuesIn(AllSupportedTransportVersions()),
                        ::testing::Values(Perspective::IS_CLIENT,
                                          Perspective::IS_SERVER)));
 
@@ -869,9 +871,6 @@
 }
 
 TEST_P(QuicHeadersStreamTest, AckSentData) {
-  if (!session_.use_stream_notifier()) {
-    return;
-  }
   EXPECT_CALL(session_,
               WritevData(headers_stream_, kHeadersStreamId, _, _, NO_FIN, _))
       .WillRepeatedly(Invoke(MockQuicSession::ConsumeAllData));
@@ -931,9 +930,6 @@
 
 TEST_P(QuicHeadersStreamTest, FrameContainsMultipleHeaders) {
   // In this test, a stream frame can contain multiple headers.
-  if (!session_.save_data_before_consumption()) {
-    return;
-  }
   EXPECT_CALL(session_,
               WritevData(headers_stream_, kHeadersStreamId, _, _, NO_FIN, _))
       .WillRepeatedly(Invoke(MockQuicSession::ConsumeAllData));
diff --git a/net/quic/core/quic_packet_creator.cc b/net/quic/core/quic_packet_creator.cc
index 3aa951e..79534f1 100644
--- a/net/quic/core/quic_packet_creator.cc
+++ b/net/quic/core/quic_packet_creator.cc
@@ -112,8 +112,8 @@
   const QuicPacketNumber current_delta =
       packet_.packet_number + 1 - least_packet_awaited_by_peer;
   const uint64_t delta = std::max(current_delta, max_packets_in_flight);
-  packet_.packet_number_length =
-      QuicFramer::GetMinPacketNumberLength(framer_->version(), delta * 4);
+  packet_.packet_number_length = QuicFramer::GetMinPacketNumberLength(
+      framer_->transport_version(), delta * 4);
 }
 
 bool QuicPacketCreator::ConsumeData(QuicStreamId id,
@@ -154,13 +154,13 @@
 
 bool QuicPacketCreator::HasRoomForStreamFrame(QuicStreamId id,
                                               QuicStreamOffset offset) {
-  return BytesFree() > QuicFramer::GetMinStreamFrameSize(framer_->version(), id,
-                                                         offset, true);
+  return BytesFree() > QuicFramer::GetMinStreamFrameSize(
+                           framer_->transport_version(), id, offset, true);
 }
 
 // static
 size_t QuicPacketCreator::StreamFramePacketOverhead(
-    QuicVersion version,
+    QuicTransportVersion version,
     QuicConnectionIdLength connection_id_length,
     bool include_version,
     bool include_diversification_nonce,
@@ -179,17 +179,17 @@
                                           QuicStreamOffset offset,
                                           bool fin,
                                           QuicFrame* frame) {
-  DCHECK_GT(
-      max_packet_length_,
-      StreamFramePacketOverhead(framer_->version(), connection_id_length_,
-                                kIncludeVersion, IncludeNonceInPublicHeader(),
-                                PACKET_6BYTE_PACKET_NUMBER, offset));
+  DCHECK_GT(max_packet_length_,
+            StreamFramePacketOverhead(framer_->transport_version(),
+                                      connection_id_length_, kIncludeVersion,
+                                      IncludeNonceInPublicHeader(),
+                                      PACKET_6BYTE_PACKET_NUMBER, offset));
 
   QUIC_BUG_IF(!HasRoomForStreamFrame(id, offset))
       << "No room for Stream frame, BytesFree: " << BytesFree()
       << " MinStreamFrameSize: "
-      << QuicFramer::GetMinStreamFrameSize(framer_->version(), id, offset,
-                                           true);
+      << QuicFramer::GetMinStreamFrameSize(framer_->transport_version(), id,
+                                           offset, true);
 
   if (iov_offset == iov.total_length) {
     QUIC_BUG_IF(!fin) << "Creating a stream frame with no data or fin.";
@@ -201,7 +201,8 @@
 
   const size_t data_size = iov.total_length - iov_offset;
   size_t min_frame_size = QuicFramer::GetMinStreamFrameSize(
-      framer_->version(), id, offset, /* last_frame_in_packet= */ true);
+      framer_->transport_version(), id, offset,
+      /* last_frame_in_packet= */ true);
   size_t bytes_consumed =
       std::min<size_t>(BytesFree() - min_frame_size, data_size);
 
@@ -326,7 +327,8 @@
       << "Creating a stream frame with no data or fin.";
   const size_t remaining_data_size = iov.total_length - iov_offset;
   const size_t min_frame_size = QuicFramer::GetMinStreamFrameSize(
-      framer_->version(), id, stream_offset, /* last_frame_in_packet= */ true);
+      framer_->transport_version(), id, stream_offset,
+      /* last_frame_in_packet= */ true);
   const size_t available_size =
       max_plaintext_size_ - writer.length() - min_frame_size;
   const size_t bytes_consumed =
@@ -362,8 +364,8 @@
 
   size_t encrypted_length = framer_->EncryptInPlace(
       packet_.encryption_level, packet_.packet_number,
-      GetStartOfEncryptedData(framer_->version(), header), writer.length(),
-      arraysize(encrypted_buffer), encrypted_buffer);
+      GetStartOfEncryptedData(framer_->transport_version(), header),
+      writer.length(), arraysize(encrypted_buffer), encrypted_buffer);
   if (encrypted_length == 0) {
     QUIC_BUG << "Failed to encrypt packet number " << header.packet_number;
     return;
@@ -407,9 +409,10 @@
   if (!queued_frames_.empty()) {
     return packet_size_;
   }
-  packet_size_ = GetPacketHeaderSize(
-      framer_->version(), connection_id_length_, send_version_in_packet_,
-      IncludeNonceInPublicHeader(), packet_.packet_number_length);
+  packet_size_ =
+      GetPacketHeaderSize(framer_->transport_version(), connection_id_length_,
+                          send_version_in_packet_, IncludeNonceInPublicHeader(),
+                          packet_.packet_number_length);
   return packet_size_;
 }
 
@@ -467,7 +470,7 @@
   }
   const size_t encrypted_length = framer_->EncryptInPlace(
       packet_.encryption_level, packet_.packet_number,
-      GetStartOfEncryptedData(framer_->version(), header), length,
+      GetStartOfEncryptedData(framer_->transport_version(), header), length,
       encrypted_buffer_len, encrypted_buffer);
   if (encrypted_length == 0) {
     QUIC_BUG << "Failed to encrypt packet number " << packet_.packet_number;
@@ -482,7 +485,7 @@
 
 std::unique_ptr<QuicEncryptedPacket>
 QuicPacketCreator::SerializeVersionNegotiationPacket(
-    const QuicVersionVector& supported_versions) {
+    const QuicTransportVersionVector& supported_versions) {
   DCHECK_EQ(Perspective::IS_SERVER, framer_->perspective());
   std::unique_ptr<QuicEncryptedPacket> encrypted =
       QuicFramer::BuildVersionNegotiationPacket(connection_id_,
diff --git a/net/quic/core/quic_packet_creator.h b/net/quic/core/quic_packet_creator.h
index 61e8af50..84e5a7f 100644
--- a/net/quic/core/quic_packet_creator.h
+++ b/net/quic/core/quic_packet_creator.h
@@ -75,7 +75,7 @@
 
   // The overhead the framing will add for a packet with one frame.
   static size_t StreamFramePacketOverhead(
-      QuicVersion version,
+      QuicTransportVersion version,
       QuicConnectionIdLength connection_id_length,
       bool include_version,
       bool include_diversification_nonce,
@@ -162,7 +162,7 @@
 
   // Creates a version negotiation packet which supports |supported_versions|.
   std::unique_ptr<QuicEncryptedPacket> SerializeVersionNegotiationPacket(
-      const QuicVersionVector& supported_versions);
+      const QuicTransportVersionVector& supported_versions);
 
   // Returns a dummy packet that is valid but contains no useful information.
   static SerializedPacket NoPacket();
diff --git a/net/quic/core/quic_packet_creator_test.cc b/net/quic/core/quic_packet_creator_test.cc
index 3fda43c..29eb8c7 100644
--- a/net/quic/core/quic_packet_creator_test.cc
+++ b/net/quic/core/quic_packet_creator_test.cc
@@ -39,9 +39,10 @@
 
 const QuicStreamId kGetNthClientInitiatedStreamId1 = kHeadersStreamId + 2;
 
-// Run tests with combinations of {QuicVersion, ToggleVersionSerialization}.
+// Run tests with combinations of {QuicTransportVersion,
+// ToggleVersionSerialization}.
 struct TestParams {
-  TestParams(QuicVersion version,
+  TestParams(QuicTransportVersion version,
              bool version_serialization,
              QuicConnectionIdLength length,
              bool framer_has_data_producer)
@@ -58,7 +59,7 @@
     return os;
   }
 
-  QuicVersion version;
+  QuicTransportVersion version;
   QuicConnectionIdLength connection_id_length;
   bool version_serialization;
   bool framer_has_data_producer;
@@ -68,7 +69,8 @@
 std::vector<TestParams> GetTestParams() {
   std::vector<TestParams> params;
   constexpr QuicConnectionIdLength kMax = PACKET_8BYTE_CONNECTION_ID;
-  QuicVersionVector all_supported_versions = AllSupportedVersions();
+  QuicTransportVersionVector all_supported_versions =
+      AllSupportedTransportVersions();
   for (bool framer_has_data_producer : {true, false}) {
     for (size_t i = 0; i < all_supported_versions.size(); ++i) {
       params.push_back(TestParams(all_supported_versions[i], true, kMax,
@@ -143,10 +145,10 @@
 
  protected:
   QuicPacketCreatorTest()
-      : server_framer_(SupportedVersions(GetParam().version),
+      : server_framer_(SupportedTransportVersions(GetParam().version),
                        QuicTime::Zero(),
                        Perspective::IS_SERVER),
-        client_framer_(SupportedVersions(GetParam().version),
+        client_framer_(SupportedTransportVersions(GetParam().version),
                        QuicTime::Zero(),
                        Perspective::IS_CLIENT),
         connection_id_(2),
@@ -215,7 +217,7 @@
 
   // Returns the number of bytes consumed by the header of packet, including
   // the version.
-  size_t GetPacketHeaderOverhead(QuicVersion version) {
+  size_t GetPacketHeaderOverhead(QuicTransportVersion version) {
     return GetPacketHeaderSize(
         version, creator_.connection_id_length(), kIncludeVersion,
         !kIncludeDiversificationNonce,
@@ -231,7 +233,7 @@
 
   // Returns the number of bytes consumed by the non-data fields of a stream
   // frame, assuming it is the last frame in the packet
-  size_t GetStreamFrameOverhead(QuicVersion version) {
+  size_t GetStreamFrameOverhead(QuicTransportVersion version) {
     return QuicFramer::GetMinStreamFrameSize(
         version, kGetNthClientInitiatedStreamId1, kOffset, true);
   }
@@ -279,7 +281,7 @@
   for (int i = ENCRYPTION_NONE; i < NUM_ENCRYPTION_LEVELS; ++i) {
     EncryptionLevel level = static_cast<EncryptionLevel>(i);
     creator_.set_encryption_level(level);
-    frames_.push_back(QuicFrame(new QuicAckFrame(MakeAckFrame(0u))));
+    frames_.push_back(QuicFrame(new QuicAckFrame()));
     frames_.push_back(QuicFrame(
         new QuicStreamFrame(kCryptoStreamId, false, 0u, QuicStringPiece())));
     frames_.push_back(QuicFrame(
@@ -463,9 +465,10 @@
 }
 
 TEST_P(QuicPacketCreatorTest, ReserializeFramesWithFullPacketAndPadding) {
-  const size_t overhead = GetPacketHeaderOverhead(client_framer_.version()) +
-                          GetEncryptionOverhead() +
-                          GetStreamFrameOverhead(client_framer_.version());
+  const size_t overhead =
+      GetPacketHeaderOverhead(client_framer_.transport_version()) +
+      GetEncryptionOverhead() +
+      GetStreamFrameOverhead(client_framer_.transport_version());
   size_t capacity = kDefaultMaxPacketSize - overhead;
   for (int delta = -5; delta <= 0; ++delta) {
     string data(capacity + delta, 'A');
@@ -569,12 +572,14 @@
 
 TEST_P(QuicPacketCreatorTest, CreateAllFreeBytesForStreamFrames) {
   creator_.set_encryption_level(ENCRYPTION_FORWARD_SECURE);
-  const size_t overhead = GetPacketHeaderOverhead(client_framer_.version()) +
-                          GetEncryptionOverhead();
+  const size_t overhead =
+      GetPacketHeaderOverhead(client_framer_.transport_version()) +
+      GetEncryptionOverhead();
   for (size_t i = overhead; i < overhead + 100; ++i) {
     creator_.SetMaxPacketLength(i);
     const bool should_have_room =
-        i > overhead + GetStreamFrameOverhead(client_framer_.version());
+        i >
+        overhead + GetStreamFrameOverhead(client_framer_.transport_version());
     ASSERT_EQ(should_have_room, creator_.HasRoomForStreamFrame(
                                     kGetNthClientInitiatedStreamId1, kOffset));
     if (should_have_room) {
@@ -597,9 +602,10 @@
 TEST_P(QuicPacketCreatorTest, StreamFrameConsumption) {
   creator_.set_encryption_level(ENCRYPTION_FORWARD_SECURE);
   // Compute the total overhead for a single frame in packet.
-  const size_t overhead = GetPacketHeaderOverhead(client_framer_.version()) +
-                          GetEncryptionOverhead() +
-                          GetStreamFrameOverhead(client_framer_.version());
+  const size_t overhead =
+      GetPacketHeaderOverhead(client_framer_.transport_version()) +
+      GetEncryptionOverhead() +
+      GetStreamFrameOverhead(client_framer_.transport_version());
   size_t capacity = kDefaultMaxPacketSize - overhead;
   // Now, test various sizes around this size.
   for (int delta = -5; delta <= 5; ++delta) {
@@ -626,9 +632,10 @@
 
 TEST_P(QuicPacketCreatorTest, CryptoStreamFramePacketPadding) {
   // Compute the total overhead for a single frame in packet.
-  const size_t overhead = GetPacketHeaderOverhead(client_framer_.version()) +
-                          GetEncryptionOverhead() +
-                          GetStreamFrameOverhead(client_framer_.version());
+  const size_t overhead =
+      GetPacketHeaderOverhead(client_framer_.transport_version()) +
+      GetEncryptionOverhead() +
+      GetStreamFrameOverhead(client_framer_.transport_version());
   ASSERT_GT(kMaxPacketSize, overhead);
   size_t capacity = kDefaultMaxPacketSize - overhead;
   // Now, test various sizes around this size.
@@ -664,9 +671,10 @@
 TEST_P(QuicPacketCreatorTest, NonCryptoStreamFramePacketNonPadding) {
   creator_.set_encryption_level(ENCRYPTION_FORWARD_SECURE);
   // Compute the total overhead for a single frame in packet.
-  const size_t overhead = GetPacketHeaderOverhead(client_framer_.version()) +
-                          GetEncryptionOverhead() +
-                          GetStreamFrameOverhead(client_framer_.version());
+  const size_t overhead =
+      GetPacketHeaderOverhead(client_framer_.transport_version()) +
+      GetEncryptionOverhead() +
+      GetStreamFrameOverhead(client_framer_.transport_version());
   ASSERT_GT(kDefaultMaxPacketSize, overhead);
   size_t capacity = kDefaultMaxPacketSize - overhead;
   // Now, test various sizes around this size.
@@ -697,7 +705,7 @@
 
 TEST_P(QuicPacketCreatorTest, SerializeVersionNegotiationPacket) {
   QuicFramerPeer::SetPerspective(&client_framer_, Perspective::IS_SERVER);
-  QuicVersionVector versions;
+  QuicTransportVersionVector versions;
   versions.push_back(test::QuicVersionMax());
   std::unique_ptr<QuicEncryptedPacket> encrypted(
       creator_.SerializeVersionNegotiationPacket(versions));
@@ -804,7 +812,7 @@
   // A string larger than fits into a frame.
   size_t payload_length;
   creator_.SetMaxPacketLength(GetPacketLengthForOneStream(
-      client_framer_.version(),
+      client_framer_.transport_version(),
       QuicPacketCreatorPeer::SendVersionInPacket(&creator_),
       !kIncludeDiversificationNonce, creator_.connection_id_length(),
       PACKET_1BYTE_PACKET_NUMBER, &payload_length));
@@ -833,13 +841,14 @@
   EXPECT_FALSE(creator_.HasPendingFrames());
   EXPECT_EQ(max_plaintext_size -
                 GetPacketHeaderSize(
-                    client_framer_.version(), creator_.connection_id_length(),
+                    client_framer_.transport_version(),
+                    creator_.connection_id_length(),
                     QuicPacketCreatorPeer::SendVersionInPacket(&creator_),
                     !kIncludeDiversificationNonce, PACKET_1BYTE_PACKET_NUMBER),
             creator_.BytesFree());
 
   // Add a variety of frame types and then a padding frame.
-  QuicAckFrame ack_frame(MakeAckFrame(10u));
+  QuicAckFrame ack_frame(InitAckFrame(10u));
   EXPECT_TRUE(creator_.AddSavedFrame(QuicFrame(&ack_frame)));
   EXPECT_TRUE(creator_.HasPendingFrames());
 
@@ -876,7 +885,8 @@
   EXPECT_FALSE(creator_.HasPendingFrames());
   EXPECT_EQ(max_plaintext_size -
                 GetPacketHeaderSize(
-                    client_framer_.version(), creator_.connection_id_length(),
+                    client_framer_.transport_version(),
+                    creator_.connection_id_length(),
                     QuicPacketCreatorPeer::SendVersionInPacket(&creator_),
                     !kIncludeDiversificationNonce, PACKET_1BYTE_PACKET_NUMBER),
             creator_.BytesFree());
@@ -1069,10 +1079,10 @@
   const QuicByteCount kStreamFramePayloadSize = 100u;
   // Set the packet size be enough for one stream frame with 0 stream offset +
   // 1.
-  size_t length = GetPacketHeaderOverhead(client_framer_.version()) +
+  size_t length = GetPacketHeaderOverhead(client_framer_.transport_version()) +
                   GetEncryptionOverhead() +
                   QuicFramer::GetMinStreamFrameSize(
-                      client_framer_.version(), kCryptoStreamId, 0,
+                      client_framer_.transport_version(), kCryptoStreamId, 0,
                       /*last_frame_in_packet=*/false) +
                   kStreamFramePayloadSize + 1;
   creator_.SetMaxPacketLength(length);
diff --git a/net/quic/core/quic_packet_generator.cc b/net/quic/core/quic_packet_generator.cc
index 337cdd99..b36ce0e9 100644
--- a/net/quic/core/quic_packet_generator.cc
+++ b/net/quic/core/quic_packet_generator.cc
@@ -57,8 +57,7 @@
     QuicIOVector iov,
     QuicStreamOffset offset,
     StreamSendingState state,
-    QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener,
-    bool flag_run_fast_path) {
+    QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
   bool has_handshake = (id == kCryptoStreamId);
   bool fin = state != NO_FIN;
   QUIC_BUG_IF(has_handshake && fin)
@@ -82,10 +81,9 @@
   }
   // We determine if we can enter the fast path before executing
   // the slow path loop.
-  bool run_fast_path =
-      flag_run_fast_path &&
-      (!has_handshake && state != FIN_AND_PADDING && !HasQueuedFrames() &&
-       iov.total_length - total_bytes_consumed > kMaxPacketSize);
+  bool run_fast_path = !has_handshake && state != FIN_AND_PADDING &&
+                       !HasQueuedFrames() &&
+                       iov.total_length - total_bytes_consumed > kMaxPacketSize;
 
   while (!run_fast_path && delegate_->ShouldGeneratePacket(
                                HAS_RETRANSMITTABLE_DATA,
@@ -126,14 +124,12 @@
     // TODO(ianswett): Move to having the creator flush itself when it's full.
     packet_creator_.Flush();
 
-    run_fast_path =
-        flag_run_fast_path &&
-        (!has_handshake && state != FIN_AND_PADDING && !HasQueuedFrames() &&
-         iov.total_length - total_bytes_consumed > kMaxPacketSize);
+    run_fast_path = !has_handshake && state != FIN_AND_PADDING &&
+                    !HasQueuedFrames() &&
+                    iov.total_length - total_bytes_consumed > kMaxPacketSize;
   }
 
   if (run_fast_path) {
-    QUIC_FLAG_COUNT(quic_reloadable_flag_quic_consuming_data_faster);
     return ConsumeDataFastPath(id, iov, offset, state != NO_FIN,
                                total_bytes_consumed, ack_listener);
   }
@@ -323,7 +319,7 @@
 
 std::unique_ptr<QuicEncryptedPacket>
 QuicPacketGenerator::SerializeVersionNegotiationPacket(
-    const QuicVersionVector& supported_versions) {
+    const QuicTransportVersionVector& supported_versions) {
   return packet_creator_.SerializeVersionNegotiationPacket(supported_versions);
 }
 
diff --git a/net/quic/core/quic_packet_generator.h b/net/quic/core/quic_packet_generator.h
index 3c192c3c..19f92c7 100644
--- a/net/quic/core/quic_packet_generator.h
+++ b/net/quic/core/quic_packet_generator.h
@@ -101,8 +101,7 @@
       QuicIOVector iov,
       QuicStreamOffset offset,
       StreamSendingState state,
-      QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener,
-      bool flag_run_fast_path);
+      QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
 
   // Sends as many data only packets as allowed by the send algorithm and the
   // available iov.
@@ -148,7 +147,7 @@
 
   // Creates a version negotiation packet which supports |supported_versions|.
   std::unique_ptr<QuicEncryptedPacket> SerializeVersionNegotiationPacket(
-      const QuicVersionVector& supported_versions);
+      const QuicTransportVersionVector& supported_versions);
 
   // Re-serializes frames with the original packet's packet number length.
   // Used for retransmitting packets to ensure they aren't too long.
diff --git a/net/quic/core/quic_packet_generator_test.cc b/net/quic/core/quic_packet_generator_test.cc
index 0beb7cc..90ef7ac 100644
--- a/net/quic/core/quic_packet_generator_test.cc
+++ b/net/quic/core/quic_packet_generator_test.cc
@@ -149,9 +149,8 @@
         producer_->SaveStreamData(id, iov, 0, offset, iov.total_length);
       }
     }
-    return QuicPacketGenerator::ConsumeData(
-        id, iov, offset, state, std::move(ack_listener),
-        FLAGS_quic_reloadable_flag_quic_consuming_data_faster);
+    return QuicPacketGenerator::ConsumeData(id, iov, offset, state,
+                                            std::move(ack_listener));
   }
 
   SimpleDataProducer* producer_;
@@ -160,7 +159,7 @@
 class QuicPacketGeneratorTest : public QuicTest {
  public:
   QuicPacketGeneratorTest()
-      : framer_(AllSupportedVersions(),
+      : framer_(AllSupportedTransportVersions(),
                 QuicTime::Zero(),
                 Perspective::IS_CLIENT),
         generator_(42,
@@ -173,9 +172,7 @@
     creator_->SetEncrypter(ENCRYPTION_FORWARD_SECURE,
                            new NullEncrypter(Perspective::IS_CLIENT));
     creator_->set_encryption_level(ENCRYPTION_FORWARD_SECURE);
-    if (FLAGS_quic_reloadable_flag_quic_save_data_before_consumption2) {
-      framer_.set_data_producer(&producer_);
-    }
+    framer_.set_data_producer(&producer_);
   }
 
   ~QuicPacketGeneratorTest() override {
@@ -537,13 +534,17 @@
   size_t length =
       NullEncrypter(Perspective::IS_CLIENT).GetCiphertextSize(0) +
       GetPacketHeaderSize(
-          framer_.version(), creator_->connection_id_length(), kIncludeVersion,
-          !kIncludeDiversificationNonce,
+          framer_.transport_version(), creator_->connection_id_length(),
+          kIncludeVersion, !kIncludeDiversificationNonce,
           QuicPacketCreatorPeer::GetPacketNumberLength(creator_)) +
       // Add an extra 3 bytes for the payload and 1 byte so BytesFree is larger
       // than the GetMinStreamFrameSize.
-      QuicFramer::GetMinStreamFrameSize(framer_.version(), 1, 0, false) + 3 +
-      QuicFramer::GetMinStreamFrameSize(framer_.version(), 1, 0, true) + 1;
+      QuicFramer::GetMinStreamFrameSize(framer_.transport_version(), 1, 0,
+                                        false) +
+      3 +
+      QuicFramer::GetMinStreamFrameSize(framer_.transport_version(), 1, 0,
+                                        true) +
+      1;
   generator_.SetMaxPacketLength(length);
   delegate_.SetCanWriteAnything();
   {
@@ -1082,10 +1083,11 @@
   size_t length =
       NullEncrypter(Perspective::IS_CLIENT).GetCiphertextSize(0) +
       GetPacketHeaderSize(
-          framer_.version(), creator_->connection_id_length(), kIncludeVersion,
-          !kIncludeDiversificationNonce,
+          framer_.transport_version(), creator_->connection_id_length(),
+          kIncludeVersion, !kIncludeDiversificationNonce,
           QuicPacketCreatorPeer::GetPacketNumberLength(creator_)) +
-      QuicFramer::GetMinStreamFrameSize(framer_.version(), kDataStreamId, 0,
+      QuicFramer::GetMinStreamFrameSize(framer_.transport_version(),
+                                        kDataStreamId, 0,
                                         /*last_frame_in_packet=*/false) +
       kStreamFramePayloadSize + kMaxNumRandomPaddingBytes;
   generator_.SetMaxPacketLength(length);
@@ -1121,10 +1123,11 @@
   size_t length =
       NullEncrypter(Perspective::IS_CLIENT).GetCiphertextSize(0) +
       GetPacketHeaderSize(
-          framer_.version(), creator_->connection_id_length(), kIncludeVersion,
-          !kIncludeDiversificationNonce,
+          framer_.transport_version(), creator_->connection_id_length(),
+          kIncludeVersion, !kIncludeDiversificationNonce,
           QuicPacketCreatorPeer::GetPacketNumberLength(creator_)) +
-      QuicFramer::GetMinStreamFrameSize(framer_.version(), kDataStreamId, 0,
+      QuicFramer::GetMinStreamFrameSize(framer_.transport_version(),
+                                        kDataStreamId, 0,
                                         /*last_frame_in_packet=*/false) +
       kStreamFramePayloadSize + 1;
   generator_.SetMaxPacketLength(length);
@@ -1168,13 +1171,15 @@
   size_t length =
       NullEncrypter(Perspective::IS_CLIENT).GetCiphertextSize(0) +
       GetPacketHeaderSize(
-          framer_.version(), creator_->connection_id_length(), kIncludeVersion,
-          !kIncludeDiversificationNonce,
+          framer_.transport_version(), creator_->connection_id_length(),
+          kIncludeVersion, !kIncludeDiversificationNonce,
           QuicPacketCreatorPeer::GetPacketNumberLength(creator_)) +
-      QuicFramer::GetMinStreamFrameSize(framer_.version(), kDataStreamId1, 0,
+      QuicFramer::GetMinStreamFrameSize(framer_.transport_version(),
+                                        kDataStreamId1, 0,
                                         /*last_frame_in_packet=*/false) +
       kStreamFramePayloadSize +
-      QuicFramer::GetMinStreamFrameSize(framer_.version(), kDataStreamId1, 0,
+      QuicFramer::GetMinStreamFrameSize(framer_.transport_version(),
+                                        kDataStreamId1, 0,
                                         /*last_frame_in_packet=*/false) +
       1;
   generator_.SetMaxPacketLength(length);
diff --git a/net/quic/core/quic_packets.cc b/net/quic/core/quic_packets.cc
index 16720b7..2d5b824 100644
--- a/net/quic/core/quic_packets.cc
+++ b/net/quic/core/quic_packets.cc
@@ -15,7 +15,7 @@
 
 namespace net {
 
-size_t GetPacketHeaderSize(QuicVersion version,
+size_t GetPacketHeaderSize(QuicTransportVersion version,
                            const QuicPacketHeader& header) {
   return GetPacketHeaderSize(version, header.public_header.connection_id_length,
                              header.public_header.version_flag,
@@ -23,7 +23,7 @@
                              header.public_header.packet_number_length);
 }
 
-size_t GetPacketHeaderSize(QuicVersion version,
+size_t GetPacketHeaderSize(QuicTransportVersion version,
                            QuicConnectionIdLength connection_id_length,
                            bool include_version,
                            bool include_diversification_nonce,
@@ -33,12 +33,12 @@
          (include_diversification_nonce ? kDiversificationNonceSize : 0);
 }
 
-size_t GetStartOfEncryptedData(QuicVersion version,
+size_t GetStartOfEncryptedData(QuicTransportVersion version,
                                const QuicPacketHeader& header) {
   return GetPacketHeaderSize(version, header);
 }
 
-size_t GetStartOfEncryptedData(QuicVersion version,
+size_t GetStartOfEncryptedData(QuicTransportVersion version,
                                QuicConnectionIdLength connection_id_length,
                                bool include_version,
                                bool include_diversification_nonce,
@@ -180,14 +180,14 @@
   return os;
 }
 
-QuicStringPiece QuicPacket::AssociatedData(QuicVersion version) const {
+QuicStringPiece QuicPacket::AssociatedData(QuicTransportVersion version) const {
   return QuicStringPiece(
       data(), GetStartOfEncryptedData(
                   version, connection_id_length_, includes_version_,
                   includes_diversification_nonce_, packet_number_length_));
 }
 
-QuicStringPiece QuicPacket::Plaintext(QuicVersion version) const {
+QuicStringPiece QuicPacket::Plaintext(QuicTransportVersion version) const {
   const size_t start_of_encrypted_data = GetStartOfEncryptedData(
       version, connection_id_length_, includes_version_,
       includes_diversification_nonce_, packet_number_length_);
diff --git a/net/quic/core/quic_packets.h b/net/quic/core/quic_packets.h
index f552f0d..513e3bf 100644
--- a/net/quic/core/quic_packets.h
+++ b/net/quic/core/quic_packets.h
@@ -34,11 +34,11 @@
 struct QuicPacketHeader;
 
 // Size in bytes of the data packet header.
-QUIC_EXPORT_PRIVATE size_t GetPacketHeaderSize(QuicVersion version,
+QUIC_EXPORT_PRIVATE size_t GetPacketHeaderSize(QuicTransportVersion version,
                                                const QuicPacketHeader& header);
 
 QUIC_EXPORT_PRIVATE size_t
-GetPacketHeaderSize(QuicVersion version,
+GetPacketHeaderSize(QuicTransportVersion version,
                     QuicConnectionIdLength connection_id_length,
                     bool include_version,
                     bool include_diversification_nonce,
@@ -46,10 +46,11 @@
 
 // Index of the first byte in a QUIC packet of encrypted data.
 QUIC_EXPORT_PRIVATE size_t
-GetStartOfEncryptedData(QuicVersion version, const QuicPacketHeader& header);
+GetStartOfEncryptedData(QuicTransportVersion version,
+                        const QuicPacketHeader& header);
 
 QUIC_EXPORT_PRIVATE size_t
-GetStartOfEncryptedData(QuicVersion version,
+GetStartOfEncryptedData(QuicTransportVersion version,
                         QuicConnectionIdLength connection_id_length,
                         bool include_version,
                         bool include_diversification_nonce,
@@ -67,7 +68,7 @@
   bool reset_flag;
   bool version_flag;
   QuicPacketNumberLength packet_number_length;
-  QuicVersionVector versions;
+  QuicTransportVersionVector versions;
   // nonce contains an optional, 32-byte nonce value. If not included in the
   // packet, |nonce| will be empty.
   DiversificationNonce* nonce;
@@ -132,8 +133,8 @@
              bool includes_diversification_nonce,
              QuicPacketNumberLength packet_number_length);
 
-  QuicStringPiece AssociatedData(QuicVersion version) const;
-  QuicStringPiece Plaintext(QuicVersion version) const;
+  QuicStringPiece AssociatedData(QuicTransportVersion version) const;
+  QuicStringPiece Plaintext(QuicTransportVersion version) const;
 
   char* mutable_data() { return buffer_; }
 
diff --git a/net/quic/core/quic_received_packet_manager_test.cc b/net/quic/core/quic_received_packet_manager_test.cc
index 2b0f24a..7df845d 100644
--- a/net/quic/core/quic_received_packet_manager_test.cc
+++ b/net/quic/core/quic_received_packet_manager_test.cc
@@ -16,19 +16,20 @@
 namespace {
 
 struct TestParams {
-  explicit TestParams(QuicVersion version) : version(version) {}
+  explicit TestParams(QuicTransportVersion version) : version(version) {}
 
   friend std::ostream& operator<<(std::ostream& os, const TestParams& p) {
     os << "{ version: " << QuicVersionToString(p.version) << " }";
     return os;
   }
 
-  QuicVersion version;
+  QuicTransportVersion version;
 };
 
 std::vector<TestParams> GetTestParams() {
   std::vector<TestParams> params;
-  QuicVersionVector all_supported_versions = AllSupportedVersions();
+  QuicTransportVersionVector all_supported_versions =
+      AllSupportedTransportVersions();
   for (size_t i = 0; i < all_supported_versions.size(); ++i) {
     params.push_back(TestParams(all_supported_versions[i]));
   }
diff --git a/net/quic/core/quic_sent_packet_manager.cc b/net/quic/core/quic_sent_packet_manager.cc
index 8477aa21..fbc041b 100644
--- a/net/quic/core/quic_sent_packet_manager.cc
+++ b/net/quic/core/quic_sent_packet_manager.cc
@@ -307,8 +307,8 @@
     // If data is associated with the most recent transmission of this
     // packet, then inform the caller.
     if (it->in_flight) {
-      packets_acked_.push_back(SendAlgorithmInterface::AckedPacket(
-          packet_number, it->bytes_sent, QuicTime::Zero()));
+      packets_acked_.push_back(
+          AckedPacket(packet_number, it->bytes_sent, QuicTime::Zero()));
     } else {
       // Unackable packets are skipped earlier.
       largest_newly_acked_ = packet_number;
@@ -671,21 +671,22 @@
   }
   loss_algorithm_->DetectLosses(unacked_packets_, time, rtt_stats_,
                                 largest_newly_acked_, &packets_lost_);
-  for (const auto& pair : packets_lost_) {
+  for (const LostPacket& packet : packets_lost_) {
     ++stats_->packets_lost;
     if (debug_delegate_ != nullptr) {
-      debug_delegate_->OnPacketLoss(pair.first, LOSS_RETRANSMISSION, time);
+      debug_delegate_->OnPacketLoss(packet.packet_number, LOSS_RETRANSMISSION,
+                                    time);
     }
 
     // TODO(ianswett): This could be optimized.
-    if (unacked_packets_.HasRetransmittableFrames(pair.first)) {
-      MarkForRetransmission(pair.first, LOSS_RETRANSMISSION);
+    if (unacked_packets_.HasRetransmittableFrames(packet.packet_number)) {
+      MarkForRetransmission(packet.packet_number, LOSS_RETRANSMISSION);
     } else {
       // Since we will not retransmit this, we need to remove it from
       // unacked_packets_.   This is either the current transmission of
       // a packet whose previous transmission has been acked or a packet that
       // has been TLP retransmitted.
-      unacked_packets_.RemoveFromInFlight(pair.first);
+      unacked_packets_.RemoveFromInFlight(packet.packet_number);
     }
   }
 }
@@ -717,19 +718,20 @@
 }
 
 QuicTime::Delta QuicSentPacketManager::TimeUntilSend(QuicTime now) {
-  QuicTime::Delta delay = QuicTime::Delta::Infinite();
   // The TLP logic is entirely contained within QuicSentPacketManager, so the
   // send algorithm does not need to be consulted.
   if (pending_timer_transmission_count_ > 0) {
-    delay = QuicTime::Delta::Zero();
-  } else if (using_pacing_) {
-    delay =
-        pacing_sender_.TimeUntilSend(now, unacked_packets_.bytes_in_flight());
-  } else {
-    delay =
-        send_algorithm_->TimeUntilSend(now, unacked_packets_.bytes_in_flight());
+    return QuicTime::Delta::Zero();
   }
-  return delay;
+
+  if (using_pacing_) {
+    return pacing_sender_.TimeUntilSend(now,
+                                        unacked_packets_.bytes_in_flight());
+  }
+
+  return send_algorithm_->CanSend(unacked_packets_.bytes_in_flight())
+             ? QuicTime::Delta::Zero()
+             : QuicTime::Delta::Infinite();
 }
 
 const QuicTime QuicSentPacketManager::GetRetransmissionTime() const {
diff --git a/net/quic/core/quic_sent_packet_manager.h b/net/quic/core/quic_sent_packet_manager.h
index 14d2647..efbd220 100644
--- a/net/quic/core/quic_sent_packet_manager.h
+++ b/net/quic/core/quic_sent_packet_manager.h
@@ -22,6 +22,8 @@
 #include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_pending_retransmission.h"
 #include "net/quic/core/quic_sustained_bandwidth_recorder.h"
+#include "net/quic/core/quic_transmission_info.h"
+#include "net/quic/core/quic_types.h"
 #include "net/quic/core/quic_unacked_packet_map.h"
 #include "net/quic/platform/api/quic_containers.h"
 #include "net/quic/platform/api/quic_export.h"
@@ -384,8 +386,8 @@
   bool conservative_handshake_retransmits_;
 
   // Vectors packets acked and lost as a result of the last congestion event.
-  SendAlgorithmInterface::AckedPacketVector packets_acked_;
-  SendAlgorithmInterface::CongestionVector packets_lost_;
+  AckedPacketVector packets_acked_;
+  LostPacketVector packets_lost_;
   // Largest newly acknowledged packet.
   QuicPacketNumber largest_newly_acked_;
   // Largest packet in bytes ever acknowledged.
diff --git a/net/quic/core/quic_sent_packet_manager_test.cc b/net/quic/core/quic_sent_packet_manager_test.cc
index 4b7dc7c7..a80a694 100644
--- a/net/quic/core/quic_sent_packet_manager_test.cc
+++ b/net/quic/core/quic_sent_packet_manager_test.cc
@@ -37,11 +37,6 @@
 // Minimum number of consecutive RTOs before path is considered to be degrading.
 const size_t kMinTimeoutsBeforePathDegrading = 2;
 
-// Matcher to check the key of the key-value pair it receives as first argument
-// equals its second argument.
-MATCHER(KeyEq, "") {
-  return std::tr1::get<0>(arg).first == std::tr1::get<1>(arg);
-}
 // Matcher to check that the packet number matches the second argument.
 MATCHER(PacketNumberEq, "") {
   return std::tr1::get<0>(arg).packet_number == std::tr1::get<1>(arg);
@@ -138,7 +133,7 @@
         *send_algorithm_,
         OnCongestionEvent(rtt_updated, _, _,
                           Pointwise(PacketNumberEq(), {largest_observed}),
-                          ElementsAre(Pair(lost_packet, _))));
+                          Pointwise(PacketNumberEq(), {lost_packet})));
     EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
   }
 
@@ -159,7 +154,7 @@
     EXPECT_CALL(*send_algorithm_,
                 OnCongestionEvent(rtt_updated, _, _,
                                   Pointwise(PacketNumberEq(), ack_vector),
-                                  Pointwise(KeyEq(), lost_vector)));
+                                  Pointwise(PacketNumberEq(), lost_vector)));
     EXPECT_CALL(*network_change_visitor_, OnCongestionChange())
         .Times(AnyNumber());
   }
@@ -250,31 +245,6 @@
                           pending.transmission_type, HAS_RETRANSMITTABLE_DATA);
   }
 
-  // Initialize a frame acknowledging all packets up to largest_observed.
-  const QuicAckFrame InitAckFrame(QuicPacketNumber largest_observed) {
-    QuicAckFrame frame(MakeAckFrame(largest_observed));
-    if (largest_observed > 0) {
-      frame.packets.AddRange(1, largest_observed + 1);
-    }
-    return frame;
-  }
-
-  // Creates an ackframe that contains up to two ranges of packets
-  QuicAckFrame ConstructAckFrame(QuicPacketNumber range1_start,
-                                 QuicPacketNumber range1_end,
-                                 QuicPacketNumber range2_start,
-                                 QuicPacketNumber range2_end) {
-    QuicAckFrame ack_frame;
-    if (range1_start < range1_end) {
-      ack_frame.packets.AddRange(range1_start, range1_end);
-    }
-    if (range2_start <= range2_end) {
-      ack_frame.packets.AddRange(range2_start, range2_end + 1);
-    }
-    ack_frame.largest_observed = range2_end;
-    return ack_frame;
-  }
-
   QuicSentPacketManager manager_;
   MockClock clock_;
   QuicConnectionStats stats_;
@@ -308,7 +278,7 @@
   RetransmitAndSendPacket(1, 2);
 
   // Ack 2 but not 1.
-  QuicAckFrame ack_frame = ConstructAckFrame(1, 1, 2, 2);
+  QuicAckFrame ack_frame = InitAckFrame({{2, 3}});
 
   ExpectAck(2);
   manager_.OnIncomingAck(ack_frame, clock_.Now());
@@ -394,16 +364,16 @@
   clock_.AdvanceTime(rtt);
 
   // Next, NACK packet 2 three times.
-  ack_frame = ConstructAckFrame(1, 2, 3, 3);
+  ack_frame = InitAckFrame({{1, 2}, {3, 4}});
 
   ExpectAck(3);
   manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow());
 
-  ack_frame = ConstructAckFrame(1, 2, 3, 4);
+  ack_frame = InitAckFrame({{1, 2}, {3, 5}});
   ExpectAck(4);
   manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow());
 
-  ack_frame = ConstructAckFrame(1, 2, 3, 5);
+  ack_frame = InitAckFrame({{1, 2}, {3, 6}});
   ExpectAckAndLoss(true, 5, 2);
   manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow());
 
@@ -473,7 +443,7 @@
 
   // Ensure packet 2 is lost when 4 is sent and 3 and 4 are acked.
   SendDataPacket(4);
-  ack_frame = ConstructAckFrame(1, 2, 3, 4);
+  ack_frame = InitAckFrame({{1, 2}, {3, 5}});
   QuicPacketNumber acked[] = {3, 4};
   ExpectAcksAndLosses(true, acked, arraysize(acked), nullptr, 0);
   manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow());
@@ -483,7 +453,7 @@
   EXPECT_TRUE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_));
 
   SendDataPacket(5);
-  ack_frame = ConstructAckFrame(1, 2, 3, 5);
+  ack_frame = InitAckFrame({{1, 2}, {3, 6}});
   ExpectAckAndLoss(true, 5, 2);
   EXPECT_CALL(debug_delegate, OnPacketLoss(2, LOSS_RETRANSMISSION, _));
   manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow());
@@ -513,7 +483,7 @@
   SendDataPacket(4);
   // Ack 4, which causes 3 to be retransmitted.
   {
-    QuicAckFrame ack_frame = ConstructAckFrame(1, 2, 4, 4);
+    QuicAckFrame ack_frame = InitAckFrame({{1, 2}, {4, 5}});
     ExpectAck(4);
     EXPECT_CALL(*loss_algorithm, DetectLosses(_, _, _, _, _));
     manager_.OnIncomingAck(ack_frame, clock_.Now());
@@ -521,7 +491,12 @@
   }
 
   // Ack 3, which causes SpuriousRetransmitDetected to be called.
-  { QuicAckFrame ack_frame = ConstructAckFrame(1, 2, 3, 4); }
+  {
+    QuicAckFrame ack_frame = InitAckFrame({{1, 2}, {3, 5}});
+    EXPECT_CALL(*loss_algorithm, DetectLosses(_, _, _, _, _));
+    EXPECT_CALL(*loss_algorithm, SpuriousRetransmitDetected(_, _, _, 5));
+    manager_.OnIncomingAck(ack_frame, clock_.Now());
+  }
 }
 
 TEST_F(QuicSentPacketManagerTest, GetLeastUnacked) {
@@ -637,15 +612,14 @@
   manager_.MaybeRetransmitTailLossProbe();
   EXPECT_TRUE(manager_.HasPendingRetransmissions());
   RetransmitNextPacket(3);
-  EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _))
-      .WillOnce(Return(QuicTime::Delta::Infinite()));
+  EXPECT_CALL(*send_algorithm_, CanSend(_)).WillOnce(Return(false));
   EXPECT_EQ(QuicTime::Delta::Infinite(), manager_.TimeUntilSend(clock_.Now()));
   EXPECT_FALSE(manager_.HasPendingRetransmissions());
 
   // Ack the third and ensure the first two are still pending.
   ExpectAck(3);
 
-  QuicAckFrame ack_frame = ConstructAckFrame(1, 1, 3, 3);
+  QuicAckFrame ack_frame = InitAckFrame({{3, 4}});
   manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow());
 
   EXPECT_TRUE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_));
@@ -653,7 +627,7 @@
   // Acking two more packets will lose both of them due to nacks.
   SendDataPacket(4);
   SendDataPacket(5);
-  ack_frame = ConstructAckFrame(1, 1, 3, 5);
+  ack_frame = InitAckFrame({{3, 6}});
   QuicPacketNumber acked[] = {4, 5};
   QuicPacketNumber lost[] = {1, 2};
   ExpectAcksAndLosses(true, acked, arraysize(acked), lost, arraysize(lost));
@@ -684,8 +658,7 @@
   manager_.MaybeRetransmitTailLossProbe();
   EXPECT_TRUE(manager_.HasPendingRetransmissions());
   RetransmitNextPacket(101);
-  EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _))
-      .WillOnce(Return(QuicTime::Delta::Infinite()));
+  EXPECT_CALL(*send_algorithm_, CanSend(_)).WillOnce(Return(false));
   EXPECT_EQ(QuicTime::Delta::Infinite(), manager_.TimeUntilSend(clock_.Now()));
   EXPECT_FALSE(manager_.HasPendingRetransmissions());
   clock_.AdvanceTime(manager_.GetRetransmissionTime() - clock_.Now());
@@ -697,8 +670,7 @@
   EXPECT_TRUE(manager_.MaybeRetransmitTailLossProbe());
   EXPECT_TRUE(manager_.HasPendingRetransmissions());
   RetransmitNextPacket(102);
-  EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _))
-      .WillOnce(Return(QuicTime::Delta::Infinite()));
+  EXPECT_CALL(*send_algorithm_, CanSend(_)).WillOnce(Return(false));
   EXPECT_EQ(QuicTime::Delta::Infinite(), manager_.TimeUntilSend(clock_.Now()));
 
   // Ensure the RTO is set based on the correct packet.
@@ -719,7 +691,7 @@
             QuicSentPacketManagerPeer::GetBytesInFlight(&manager_));
 
   RetransmitNextPacket(103);
-  QuicAckFrame ack_frame = ConstructAckFrame(1, 0, 103, 103);
+  QuicAckFrame ack_frame = InitAckFrame({{103, 104}});
   QuicPacketNumber largest_acked = 103;
   EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout(true));
   EXPECT_CALL(*send_algorithm_,
@@ -763,10 +735,7 @@
   // and ensure the first four crypto packets get abandoned, but not lost.
   QuicPacketNumber acked[] = {3, 4, 5, 8, 9};
   ExpectAcksAndLosses(true, acked, arraysize(acked), nullptr, 0);
-  QuicAckFrame ack_frame;
-  ack_frame.packets.AddRange(3, 6);
-  ack_frame.packets.AddRange(8, 10);
-  ack_frame.largest_observed = 9;
+  QuicAckFrame ack_frame = InitAckFrame({{3, 6}, {8, 10}});
   manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow());
 
   EXPECT_FALSE(QuicSentPacketManagerPeer::HasUnackedCryptoPackets(&manager_));
@@ -814,7 +783,7 @@
   // crypto packets.
   QuicPacketNumber acked[] = {8, 9};
   ExpectAcksAndLosses(true, acked, arraysize(acked), nullptr, 0);
-  QuicAckFrame ack_frame = ConstructAckFrame(1, 1, 8, 9);
+  QuicAckFrame ack_frame = InitAckFrame({{8, 10}});
   manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow());
   EXPECT_EQ(10u, manager_.GetLeastUnacked());
 }
@@ -835,7 +804,7 @@
   // Now ack the second crypto packet, and ensure the first gets removed, but
   // the third does not.
   ExpectUpdatedRtt(2);
-  QuicAckFrame ack_frame = ConstructAckFrame(1, 1, 2, 2);
+  QuicAckFrame ack_frame = InitAckFrame({{2, 3}});
   manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow());
 
   EXPECT_FALSE(QuicSentPacketManagerPeer::HasUnackedCryptoPackets(&manager_));
@@ -908,7 +877,7 @@
   EXPECT_FALSE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_));
 
   // Ensure both packets get discarded when packet 2 is acked.
-  QuicAckFrame ack_frame = ConstructAckFrame(1, 1, 3, 3);
+  QuicAckFrame ack_frame = InitAckFrame({{3, 4}});
   ExpectUpdatedRtt(3);
   manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow());
   VerifyUnackedPackets(nullptr, 0);
@@ -935,7 +904,7 @@
   EXPECT_FALSE(manager_.HasPendingRetransmissions());
 
   // Ack a retransmission.
-  QuicAckFrame ack_frame = ConstructAckFrame(1, 0, 102, 102);
+  QuicAckFrame ack_frame = InitAckFrame({{102, 103}});
   ack_frame.ack_delay_time = QuicTime::Delta::Zero();
   // Ensure no packets are lost.
   QuicPacketNumber largest_acked = 102;
@@ -984,7 +953,7 @@
   EXPECT_FALSE(manager_.HasPendingRetransmissions());
 
   // Ack a retransmission and expect no call to OnRetransmissionTimeout.
-  QuicAckFrame ack_frame = ConstructAckFrame(1, 0, 102, 102);
+  QuicAckFrame ack_frame = InitAckFrame({{102, 103}});
   ack_frame.ack_delay_time = QuicTime::Delta::Zero();
   // This will include packets in the lost packet map.
   QuicPacketNumber largest_acked = 102;
@@ -1018,7 +987,7 @@
 
   // Ack a retransmission and ensure OnRetransmissionTimeout is called.
   EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout(true));
-  QuicAckFrame ack_frame = ConstructAckFrame(1, 1, 2, 2);
+  QuicAckFrame ack_frame = InitAckFrame({{2, 3}});
   ack_frame.ack_delay_time = QuicTime::Delta::Zero();
   ExpectAck(2);
   manager_.OnIncomingAck(ack_frame, clock_.Now());
@@ -1050,7 +1019,7 @@
 
   // Ack a retransmission and ensure OnRetransmissionTimeout is called.
   EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout(true));
-  QuicAckFrame ack_frame = ConstructAckFrame(1, 1, 3, 3);
+  QuicAckFrame ack_frame = InitAckFrame({{3, 4}});
   ack_frame.ack_delay_time = QuicTime::Delta::Zero();
   ExpectAck(3);
   manager_.OnIncomingAck(ack_frame, clock_.Now());
@@ -1171,8 +1140,7 @@
   EXPECT_TRUE(manager_.MaybeRetransmitTailLossProbe());
   EXPECT_TRUE(manager_.HasPendingRetransmissions());
   RetransmitNextPacket(3);
-  EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _))
-      .WillOnce(Return(QuicTime::Delta::Infinite()));
+  EXPECT_CALL(*send_algorithm_, CanSend(_)).WillOnce(Return(false));
   EXPECT_EQ(QuicTime::Delta::Infinite(), manager_.TimeUntilSend(clock_.Now()));
   EXPECT_FALSE(manager_.HasPendingRetransmissions());
 
@@ -1216,7 +1184,7 @@
 
   // Ack a packet before the first RTO and ensure the RTO timeout returns to the
   // original value and OnRetransmissionTimeout is not called or reverted.
-  QuicAckFrame ack_frame = ConstructAckFrame(1, 1, 2, 2);
+  QuicAckFrame ack_frame = InitAckFrame({{2, 3}});
   ExpectAck(2);
   manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow());
   EXPECT_FALSE(manager_.HasPendingRetransmissions());
@@ -1326,7 +1294,7 @@
   // set the loss timeout.
   ExpectAck(2);
   EXPECT_CALL(*loss_algorithm, DetectLosses(_, _, _, _, _));
-  QuicAckFrame ack_frame = ConstructAckFrame(1, 1, 2, 2);
+  QuicAckFrame ack_frame = InitAckFrame({{2, 3}});
   manager_.OnIncomingAck(ack_frame, clock_.Now());
 
   QuicTime timeout(clock_.Now() + QuicTime::Delta::FromMilliseconds(10));
diff --git a/net/quic/core/quic_server_session_base.cc b/net/quic/core/quic_server_session_base.cc
index fef219e..98f12ab 100644
--- a/net/quic/core/quic_server_session_base.cc
+++ b/net/quic/core/quic_server_session_base.cc
@@ -55,7 +55,7 @@
   bandwidth_resumption_enabled_ =
       last_bandwidth_resumption || max_bandwidth_resumption;
 
-  if (connection()->version() < QUIC_VERSION_35) {
+  if (connection()->transport_version() < QUIC_VERSION_35) {
     set_server_push_enabled(
         ContainsQuicTag(config()->ReceivedConnectionOptions(), kSPSH));
   }
diff --git a/net/quic/core/quic_server_session_base_test.cc b/net/quic/core/quic_server_session_base_test.cc
index 475dfde..9496394d 100644
--- a/net/quic/core/quic_server_session_base_test.cc
+++ b/net/quic/core/quic_server_session_base_test.cc
@@ -116,7 +116,8 @@
 
 const size_t kMaxStreamsForTest = 10;
 
-class QuicServerSessionBaseTest : public QuicTestWithParam<QuicVersion> {
+class QuicServerSessionBaseTest
+    : public QuicTestWithParam<QuicTransportVersion> {
  protected:
   QuicServerSessionBaseTest()
       : QuicServerSessionBaseTest(crypto_test_utils::ProofSourceForTesting()) {}
@@ -138,7 +139,7 @@
 
     connection_ = new StrictMock<MockQuicConnection>(
         &helper_, &alarm_factory_, Perspective::IS_SERVER,
-        SupportedVersions(GetParam()));
+        SupportedTransportVersions(GetParam()));
     session_.reset(new TestServerSession(
         config_, connection_, &owner_, &stream_helper_, &crypto_config_,
         &compressed_certs_cache_, &response_cache_));
@@ -190,7 +191,7 @@
 
 INSTANTIATE_TEST_CASE_P(Tests,
                         QuicServerSessionBaseTest,
-                        ::testing::ValuesIn(AllSupportedVersions()));
+                        ::testing::ValuesIn(AllSupportedTransportVersions()));
 TEST_P(QuicServerSessionBaseTest, CloseStreamDueToReset) {
   // Open a stream, then reset it.
   // Send two bytes of payload to open it.
@@ -569,7 +570,7 @@
 
 INSTANTIATE_TEST_CASE_P(StreamMemberLifetimeTests,
                         StreamMemberLifetimeTest,
-                        ::testing::ValuesIn(AllSupportedVersions()));
+                        ::testing::ValuesIn(AllSupportedTransportVersions()));
 
 // Trigger an operation which causes an async invocation of
 // ProofSource::GetProof.  Delay the completion of the operation until after the
@@ -579,11 +580,11 @@
   FLAGS_quic_reloadable_flag_quic_use_cheap_stateless_rejects = true;
 
   const QuicClock* clock = helper_.GetClock();
-  QuicVersion version = AllSupportedVersions().front();
+  QuicTransportVersion version = AllSupportedTransportVersions().front();
   CryptoHandshakeMessage chlo = crypto_test_utils::GenerateDefaultInchoateCHLO(
       clock, version, &crypto_config_);
   chlo.SetVector(kCOPT, QuicTagVector{kSREJ});
-  std::vector<QuicVersion> packet_version_list = {version};
+  std::vector<QuicTransportVersion> packet_version_list = {version};
   std::unique_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket(
       1, true, false, 1,
       string(chlo.GetSerialized(Perspective::IS_CLIENT)
diff --git a/net/quic/core/quic_session.cc b/net/quic/core/quic_session.cc
index 6fdab1b..aa3bdad 100644
--- a/net/quic/core/quic_session.cc
+++ b/net/quic/core/quic_session.cc
@@ -20,6 +20,14 @@
 
 namespace net {
 
+namespace {
+
+// Stateless reset token used in IETF public reset packet.
+// TODO(fayang): use a real stateless reset token instead of a hard code one.
+const uint128 kStatelessResetToken = 1010101;
+
+}  // namespace
+
 #define ENDPOINT \
   (perspective() == Perspective::IS_SERVER ? "Server: " : "Client: ")
 
@@ -46,22 +54,12 @@
                        perspective() == Perspective::IS_SERVER,
                        nullptr),
       currently_writing_stream_id_(0),
-      use_stream_notifier_(
-          FLAGS_quic_reloadable_flag_quic_use_stream_notifier2),
-      save_data_before_consumption_(
-          use_stream_notifier_ &&
-          FLAGS_quic_reloadable_flag_quic_save_data_before_consumption2),
-      can_use_slices_(save_data_before_consumption_ &&
-                      FLAGS_quic_reloadable_flag_quic_use_mem_slices) {}
+      can_use_slices_(FLAGS_quic_reloadable_flag_quic_use_mem_slices) {}
 
 void QuicSession::Initialize() {
   connection_->set_visitor(this);
-  if (use_stream_notifier_) {
-    connection_->SetStreamNotifier(this);
-  }
-  if (save_data_before_consumption_) {
-    connection_->SetDataProducer(this);
-  }
+  connection_->SetStreamNotifier(this);
+  connection_->SetDataProducer(this);
   connection_->SetFromConfig(config_);
 
   DCHECK_EQ(kCryptoStreamId, GetMutableCryptoStream()->id());
@@ -163,7 +161,7 @@
 }
 
 void QuicSession::OnSuccessfulVersionNegotiation(
-    const QuicVersion& /*version*/) {}
+    const QuicTransportVersion& /*version*/) {}
 
 void QuicSession::OnPathDegrading() {}
 
@@ -390,7 +388,7 @@
     stream->set_rst_sent(true);
   }
 
-  if (use_stream_notifier_ && stream->IsWaitingForAcks()) {
+  if (stream->IsWaitingForAcks()) {
     zombie_streams_[stream->id()] = std::move(it->second);
   } else {
     closed_streams_.push_back(std::move(it->second));
@@ -489,6 +487,11 @@
         AdjustInitialFlowControlWindows(1024 * 1024);
       }
     }
+
+    if (FLAGS_quic_reloadable_flag_quic_send_reset_token_in_shlo) {
+      QUIC_FLAG_COUNT(quic_reloadable_flag_quic_send_reset_token_in_shlo);
+      config_.SetStatelessResetTokenToSend(GetStatelessResetToken());
+    }
   }
 
   // A small number of additional incoming streams beyond the limit should be
@@ -950,7 +953,6 @@
         ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
     return;
   }
-  QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_use_stream_notifier2, 3, 3);
   stream->OnStreamFrameDiscarded(frame);
 }
 
@@ -968,4 +970,8 @@
   return stream->WriteStreamData(offset, data_length, writer);
 }
 
+uint128 QuicSession::GetStatelessResetToken() const {
+  return kStatelessResetToken;
+}
+
 }  // namespace net
diff --git a/net/quic/core/quic_session.h b/net/quic/core/quic_session.h
index 7aac5bb..725d078 100644
--- a/net/quic/core/quic_session.h
+++ b/net/quic/core/quic_session.h
@@ -15,6 +15,7 @@
 
 #include "base/compiler_specific.h"
 #include "base/macros.h"
+#include "net/base/int128.h"
 #include "net/quic/core/quic_connection.h"
 #include "net/quic/core/quic_crypto_stream.h"
 #include "net/quic/core/quic_packet_creator.h"
@@ -96,7 +97,8 @@
                           const std::string& error_details,
                           ConnectionCloseSource source) override;
   void OnWriteBlocked() override;
-  void OnSuccessfulVersionNegotiation(const QuicVersion& version) override;
+  void OnSuccessfulVersionNegotiation(
+      const QuicTransportVersion& version) override;
   void OnCanWrite() override;
   void OnCongestionWindowChange(QuicTime /*now*/) override {}
   void OnConnectionMigration(PeerAddressChangeType type) override {}
@@ -273,12 +275,6 @@
   // Returns true if this stream should yield writes to another blocked stream.
   bool ShouldYield(QuicStreamId stream_id);
 
-  bool use_stream_notifier() const { return use_stream_notifier_; }
-
-  bool save_data_before_consumption() const {
-    return save_data_before_consumption_;
-  }
-
   bool can_use_slices() const { return can_use_slices_; }
 
  protected:
@@ -395,6 +391,10 @@
   virtual void HandleRstOnValidNonexistentStream(
       const QuicRstStreamFrame& frame);
 
+  // Returns a stateless reset token which will be included in the public reset
+  // packet.
+  virtual uint128 GetStatelessResetToken() const;
+
  private:
   friend class test::QuicSessionPeer;
 
@@ -488,12 +488,6 @@
   // call stack of OnCanWrite.
   QuicStreamId currently_writing_stream_id_;
 
-  // This session is notified on every ack or loss.
-  const bool use_stream_notifier_;
-
-  // Application data is saved before it is actually consumed.
-  const bool save_data_before_consumption_;
-
   // QUIC stream can take ownership of application data provided in reference
   // counted memory to avoid data copy.
   const bool can_use_slices_;
diff --git a/net/quic/core/quic_session_test.cc b/net/quic/core/quic_session_test.cc
index df53dd7..15f53b37 100644
--- a/net/quic/core/quic_session_test.cc
+++ b/net/quic/core/quic_session_test.cc
@@ -222,10 +222,8 @@
     if (stream->id() != kCryptoStreamId) {
       this->connection()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
     }
-    if (save_data_before_consumption()) {
-      QuicStreamPeer::SendBuffer(stream).SaveStreamData(
-          MakeIOVector("not empty", &iov), 0, 9);
-    }
+    QuicStreamPeer::SendBuffer(stream).SaveStreamData(
+        MakeIOVector("not empty", &iov), 0, 9);
     QuicConsumedData consumed = WritevData(
         stream, stream->id(), MakeIOVector("not empty", &iov), 0, FIN, nullptr);
     return consumed;
@@ -250,14 +248,14 @@
   bool writev_consumes_all_data_;
 };
 
-class QuicSessionTestBase : public QuicTestWithParam<QuicVersion> {
+class QuicSessionTestBase : public QuicTestWithParam<QuicTransportVersion> {
  protected:
   explicit QuicSessionTestBase(Perspective perspective)
-      : connection_(
-            new StrictMock<MockQuicConnection>(&helper_,
-                                               &alarm_factory_,
-                                               perspective,
-                                               SupportedVersions(GetParam()))),
+      : connection_(new StrictMock<MockQuicConnection>(
+            &helper_,
+            &alarm_factory_,
+            perspective,
+            SupportedTransportVersions(GetParam()))),
         session_(connection_) {
     session_.config()->SetInitialStreamFlowControlWindowToSend(
         kInitialStreamFlowControlWindowForTest);
@@ -309,7 +307,9 @@
     closed_streams_.insert(id);
   }
 
-  QuicVersion version() const { return connection_->version(); }
+  QuicTransportVersion transport_version() const {
+    return connection_->transport_version();
+  }
 
   QuicStreamId GetNthClientInitiatedId(int n) {
     return QuicSpdySessionPeer::GetNthClientInitiatedStreamId(session_, n);
@@ -336,7 +336,7 @@
 
 INSTANTIATE_TEST_CASE_P(Tests,
                         QuicSessionTestServer,
-                        ::testing::ValuesIn(AllSupportedVersions()));
+                        ::testing::ValuesIn(AllSupportedTransportVersions()));
 
 TEST_P(QuicSessionTestServer, PeerAddress) {
   EXPECT_EQ(QuicSocketAddress(QuicIpAddress::Loopback4(), kTestPort),
@@ -587,8 +587,7 @@
   session_.MarkConnectionLevelWriteBlocked(stream6->id());
   session_.MarkConnectionLevelWriteBlocked(stream4->id());
 
-  EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _))
-      .WillRepeatedly(Return(QuicTime::Delta::Zero()));
+  EXPECT_CALL(*send_algorithm, CanSend(_)).WillRepeatedly(Return(true));
   EXPECT_CALL(*send_algorithm, GetCongestionWindow())
       .WillRepeatedly(Return(kMaxPacketSize * 10));
   EXPECT_CALL(*send_algorithm, InRecovery()).WillRepeatedly(Return(false));
@@ -632,35 +631,30 @@
   session_.MarkConnectionLevelWriteBlocked(stream4->id());
 
   StreamBlocker stream2_blocker(&session_, stream2->id());
-  EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _))
-      .WillOnce(Return(QuicTime::Delta::Zero()));
+  EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
   EXPECT_CALL(*stream2, OnCanWrite())
       .WillOnce(testing::IgnoreResult(
           Invoke(CreateFunctor(&TestSession::SendStreamData,
                                base::Unretained(&session_), stream2))));
-  EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _))
-      .WillOnce(Return(QuicTime::Delta::Zero()));
+  EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
   EXPECT_CALL(*stream6, OnCanWrite())
       .WillOnce(testing::IgnoreResult(
           Invoke(CreateFunctor(&TestSession::SendStreamData,
                                base::Unretained(&session_), stream6))));
-  EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _))
-      .WillOnce(Return(QuicTime::Delta::Infinite()));
+  EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(false));
   // stream4->OnCanWrite is not called.
 
   session_.OnCanWrite();
   EXPECT_TRUE(session_.WillingAndAbleToWrite());
 
   // Still congestion-control blocked.
-  EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _))
-      .WillOnce(Return(QuicTime::Delta::Infinite()));
+  EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(false));
   session_.OnCanWrite();
   EXPECT_TRUE(session_.WillingAndAbleToWrite());
 
   // stream4->OnCanWrite is called once the connection stops being
   // congestion-control blocked.
-  EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _))
-      .WillOnce(Return(QuicTime::Delta::Zero()));
+  EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
   EXPECT_CALL(*stream4, OnCanWrite())
       .WillOnce(testing::IgnoreResult(
           Invoke(CreateFunctor(&TestSession::SendStreamData,
@@ -675,8 +669,7 @@
   // application-limited signaling is handled correctly.
   MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
   QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
-  EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _))
-      .WillRepeatedly(Return(QuicTime::Delta::Zero()));
+  EXPECT_CALL(*send_algorithm, CanSend(_)).WillRepeatedly(Return(true));
 
   // Drive packet writer manually.
   MockPacketWriter* writer = static_cast<MockPacketWriter*>(
@@ -780,8 +773,7 @@
   // application-limited signaling is handled correctly.
   MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
   QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
-  EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _))
-      .WillRepeatedly(Return(QuicTime::Delta::Zero()));
+  EXPECT_CALL(*send_algorithm, CanSend(_)).WillRepeatedly(Return(true));
 
   // Ensure connection level flow control blockage.
   QuicFlowControllerPeer::SetSendWindowOffset(session_.flow_controller(), 0);
@@ -1273,7 +1265,7 @@
 
 INSTANTIATE_TEST_CASE_P(Tests,
                         QuicSessionTestClient,
-                        ::testing::ValuesIn(AllSupportedVersions()));
+                        ::testing::ValuesIn(AllSupportedTransportVersions()));
 
 TEST_P(QuicSessionTestClient, AvailableStreamsClient) {
   ASSERT_TRUE(session_.GetOrCreateDynamicStream(6) != nullptr);
@@ -1348,11 +1340,6 @@
 
   EXPECT_CALL(*connection_, SendRstStream(2, _, _));
   session_.CloseStream(2);
-  if (!session_.use_stream_notifier()) {
-    EXPECT_TRUE(session_.zombie_streams().empty());
-    EXPECT_FALSE(session_.closed_streams()->empty());
-    return;
-  }
   EXPECT_TRUE(QuicContainsKey(session_.zombie_streams(), 2));
   EXPECT_TRUE(session_.closed_streams()->empty());
   session_.OnStreamDoneWaitingForAcks(2);
diff --git a/net/quic/core/quic_spdy_session.cc b/net/quic/core/quic_spdy_session.cc
index 10c44c7..5fd6af6 100644
--- a/net/quic/core/quic_spdy_session.cc
+++ b/net/quic/core/quic_spdy_session.cc
@@ -372,13 +372,10 @@
   DCHECK_EQ(kHeadersStreamId, headers_stream_->id());
   static_streams()[kHeadersStreamId] = headers_stream_.get();
 
-  if (FLAGS_quic_restart_flag_quic_header_list_size) {
-    QUIC_FLAG_COUNT_N(quic_restart_flag_quic_header_list_size, 1, 2);
-    set_max_uncompressed_header_bytes(max_inbound_header_list_size_);
+  set_max_uncompressed_header_bytes(max_inbound_header_list_size_);
 
-    // Limit HPACK buffering to 2x header list size limit.
-    set_max_decode_buffer_size_bytes(2 * max_inbound_header_list_size_);
-  }
+  // Limit HPACK buffering to 2x header list size limit.
+  set_max_decode_buffer_size_bytes(2 * max_inbound_header_list_size_);
 }
 
 void QuicSpdySession::OnStreamHeadersPriority(QuicStreamId stream_id,
@@ -519,11 +516,7 @@
   QuicSession::OnCryptoHandshakeEvent(event);
   if (FLAGS_quic_reloadable_flag_quic_send_max_header_list_size &&
       event == HANDSHAKE_CONFIRMED && config()->SupportMaxHeaderListSize()) {
-    if (FLAGS_quic_restart_flag_quic_header_list_size) {
-      SendMaxHeaderListSize(max_inbound_header_list_size_);
-    } else {
-      SendMaxHeaderListSize(kDefaultMaxUncompressedHeaderSize);
-    }
+    SendMaxHeaderListSize(max_inbound_header_list_size_);
   }
 }
 
diff --git a/net/quic/core/quic_spdy_session.h b/net/quic/core/quic_spdy_session.h
index df28c47..bbcca3a 100644
--- a/net/quic/core/quic_spdy_session.h
+++ b/net/quic/core/quic_spdy_session.h
@@ -135,18 +135,6 @@
   void CloseConnectionWithDetails(QuicErrorCode error,
                                   const std::string& details);
 
-  // Sets how much encoded data the hpack decoder of spdy_framer_ is willing to
-  // buffer.
-  void set_max_decode_buffer_size_bytes(size_t max_decode_buffer_size_bytes) {
-    h2_deframer_.GetHpackDecoder()->set_max_decode_buffer_size_bytes(
-        max_decode_buffer_size_bytes);
-  }
-
-  // TODO(dahollings): Move to private upon deprecation of
-  // --quic_restart_flag_quic_header_list_size.
-  void set_max_uncompressed_header_bytes(
-      size_t set_max_uncompressed_header_bytes);
-
   void set_max_inbound_header_list_size(size_t max_inbound_header_list_size) {
     max_inbound_header_list_size_ = max_inbound_header_list_size;
   }
@@ -190,6 +178,16 @@
 
   bool IsConnected() { return connection()->connected(); }
 
+  // Sets how much encoded data the hpack decoder of h2_deframer_ is willing to
+  // buffer.
+  void set_max_decode_buffer_size_bytes(size_t max_decode_buffer_size_bytes) {
+    h2_deframer_.GetHpackDecoder()->set_max_decode_buffer_size_bytes(
+        max_decode_buffer_size_bytes);
+  }
+
+  void set_max_uncompressed_header_bytes(
+      size_t set_max_uncompressed_header_bytes);
+
  private:
   friend class test::QuicSpdySessionPeer;
 
diff --git a/net/quic/core/quic_spdy_stream.cc b/net/quic/core/quic_spdy_stream.cc
index 9e590f09..72902297 100644
--- a/net/quic/core/quic_spdy_stream.cc
+++ b/net/quic/core/quic_spdy_stream.cc
@@ -77,11 +77,11 @@
   // The header block must contain the final offset for this stream, as the
   // trailers may be processed out of order at the peer.
   QUIC_DLOG(INFO) << "Inserting trailer: (" << kFinalOffsetHeaderKey << ", "
-                  << stream_bytes_written() + queued_data_bytes() << ")";
+                  << stream_bytes_written() + BufferedDataBytes() << ")";
   trailer_block.insert(
       std::make_pair(kFinalOffsetHeaderKey,
                      QuicTextUtils::Uint64ToString(stream_bytes_written() +
-                                                   queued_data_bytes())));
+                                                   BufferedDataBytes())));
 
   // Write the trailing headers with a FIN, and close stream for writing:
   // trailers are the last thing to be sent on a stream.
@@ -92,7 +92,7 @@
 
   // Trailers are the last thing to be sent on a stream, but if there is still
   // queued data then CloseWriteSide() will cause it never to be sent.
-  if (queued_data_bytes() == 0) {
+  if (BufferedDataBytes() == 0) {
     CloseWriteSide();
   }
 
diff --git a/net/quic/core/quic_spdy_stream_test.cc b/net/quic/core/quic_spdy_stream_test.cc
index 9ada186..1f4107c 100644
--- a/net/quic/core/quic_spdy_stream_test.cc
+++ b/net/quic/core/quic_spdy_stream_test.cc
@@ -55,9 +55,9 @@
     data_ += string(buffer, bytes_read);
   }
 
-  using QuicStream::WriteOrBufferData;
-  using QuicStream::CloseWriteSide;
   using QuicSpdyStream::set_ack_listener;
+  using QuicStream::CloseWriteSide;
+  using QuicStream::WriteOrBufferData;
 
   const string& data() const { return data_; }
 
@@ -66,7 +66,7 @@
   string data_;
 };
 
-class QuicSpdyStreamTest : public QuicTestWithParam<QuicVersion> {
+class QuicSpdyStreamTest : public QuicTestWithParam<QuicTransportVersion> {
  public:
   QuicSpdyStreamTest() {
     headers_[":host"] = "www.google.com";
@@ -101,7 +101,7 @@
   void Initialize(bool stream_should_process_data) {
     connection_ = new testing::StrictMock<MockQuicConnection>(
         &helper_, &alarm_factory_, Perspective::IS_SERVER,
-        SupportedVersions(GetParam()));
+        SupportedTransportVersions(GetParam()));
     session_.reset(new testing::StrictMock<MockQuicSpdySession>(connection_));
     stream_ = new TestStream(GetNthClientInitiatedId(0), session_.get(),
                              stream_should_process_data);
@@ -136,7 +136,7 @@
 
 INSTANTIATE_TEST_CASE_P(Tests,
                         QuicSpdyStreamTest,
-                        ::testing::ValuesIn(AllSupportedVersions()));
+                        ::testing::ValuesIn(AllSupportedTransportVersions()));
 
 TEST_P(QuicSpdyStreamTest, ProcessHeaderList) {
   Initialize(kShouldProcessData);
@@ -901,7 +901,7 @@
   // Write non-zero body data.
   const int kBodySize = 1 * 1024;  // 1 MB
   stream_->WriteOrBufferData(string(kBodySize, 'x'), false, nullptr);
-  EXPECT_EQ(0u, stream_->queued_data_bytes());
+  EXPECT_EQ(0u, stream_->BufferedDataBytes());
 
   // Headers and body have been fully written, there is no queued data. Writing
   // trailers marks the end of this stream, and thus the write side is closed.
@@ -927,7 +927,7 @@
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
       .WillOnce(Return(QuicConsumedData(kBodySize - 1, false)));
   stream_->WriteOrBufferData(string(kBodySize, 'x'), false, nullptr);
-  EXPECT_EQ(1u, stream_->queued_data_bytes());
+  EXPECT_EQ(1u, stream_->BufferedDataBytes());
 
   // Writing trailers will send a FIN, but not close the write side of the
   // stream as there are queued bytes.
@@ -963,9 +963,6 @@
 
 TEST_P(QuicSpdyStreamTest, HeaderStreamNotiferCorrespondingSpdyStream) {
   Initialize(kShouldProcessData);
-  if (!session_->use_stream_notifier()) {
-    return;
-  }
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
       .Times(AnyNumber())
       .WillRepeatedly(Invoke(MockQuicSession::ConsumeAllData));
@@ -1011,15 +1008,10 @@
   QuicStreamPeer::CloseReadSide(stream_);
   // This write causes stream to be closed.
   stream_->WriteOrBufferData("Test1", true, nullptr);
-  if (!session_->use_stream_notifier()) {
-    EXPECT_TRUE(QuicSessionPeer::zombie_streams(session_.get()).empty());
-    EXPECT_FALSE(QuicSessionPeer::closed_streams(session_.get()).empty());
-  } else {
-    // stream_ has unacked data and should become zombie.
-    EXPECT_TRUE(QuicContainsKey(QuicSessionPeer::zombie_streams(session_.get()),
-                                stream_->id()));
-    EXPECT_TRUE(QuicSessionPeer::closed_streams(session_.get()).empty());
-  }
+  // stream_ has unacked data and should become zombie.
+  EXPECT_TRUE(QuicContainsKey(QuicSessionPeer::zombie_streams(session_.get()),
+                              stream_->id()));
+  EXPECT_TRUE(QuicSessionPeer::closed_streams(session_.get()).empty());
 }
 
 }  // namespace
diff --git a/net/quic/core/quic_stream.cc b/net/quic/core/quic_stream.cc
index 8980690..80afb520 100644
--- a/net/quic/core/quic_stream.cc
+++ b/net/quic/core/quic_stream.cc
@@ -50,8 +50,7 @@
 QuicStream::PendingData::~PendingData() {}
 
 QuicStream::QuicStream(QuicStreamId id, QuicSession* session)
-    : queued_data_bytes_(0),
-      sequencer_(this, session->connection()->clock()),
+    : sequencer_(this, session->connection()->clock()),
       id_(id),
       session_(session),
       stream_bytes_read_(0),
@@ -88,8 +87,7 @@
 }
 
 QuicStream::~QuicStream() {
-  if (session_ != nullptr && session_->use_stream_notifier() &&
-      IsWaitingForAcks()) {
+  if (session_ != nullptr && IsWaitingForAcks()) {
     QUIC_DVLOG(1)
         << ENDPOINT << "Stream " << id_
         << " gets destroyed while waiting for acks. stream_bytes_outstanding = "
@@ -219,93 +217,35 @@
   QuicConsumedData consumed_data(0, false);
   fin_buffered_ = fin;
 
-  if (session_->save_data_before_consumption()) {
-    bool had_buffered_data = HasBufferedData();
-    // Do not respect buffered data upper limit as WriteOrBufferData guarantees
-    // all data to be consumed.
-    if (data.length() > 0) {
-      struct iovec iov(MakeIovec(data));
-      QuicIOVector quic_iov(&iov, 1, data.length());
-      QuicStreamOffset offset = send_buffer_.stream_offset();
-      send_buffer_.SaveStreamData(quic_iov, 0, data.length());
-      OnDataBuffered(offset, data.length(), ack_listener);
-    }
-    if (!had_buffered_data && (HasBufferedData() || fin_buffered_)) {
-      // Write data if there is no buffered data before.
-      QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_save_data_before_consumption2,
-                        2, 4);
-      WriteBufferedData();
-    }
-    return;
-  }
-
-  if (queued_data_.empty()) {
+  bool had_buffered_data = HasBufferedData();
+  // Do not respect buffered data upper limit as WriteOrBufferData guarantees
+  // all data to be consumed.
+  if (data.length() > 0) {
     struct iovec iov(MakeIovec(data));
-    consumed_data = WritevData(&iov, 1, fin, ack_listener);
-    DCHECK_LE(consumed_data.bytes_consumed, data.length());
+    QuicIOVector quic_iov(&iov, 1, data.length());
+    QuicStreamOffset offset = send_buffer_.stream_offset();
+    send_buffer_.SaveStreamData(quic_iov, 0, data.length());
+    OnDataBuffered(offset, data.length(), ack_listener);
   }
-
-  // If there's unconsumed data or an unconsumed fin, queue it.
-  if (consumed_data.bytes_consumed < data.length() ||
-      (fin && !consumed_data.fin_consumed)) {
-    QuicStringPiece remainder(data.substr(consumed_data.bytes_consumed));
-    queued_data_bytes_ += remainder.size();
-    queued_data_.emplace_back(remainder.as_string(), ack_listener);
+  if (!had_buffered_data && (HasBufferedData() || fin_buffered_)) {
+    // Write data if there is no buffered data before.
+    WriteBufferedData();
   }
 }
 
 void QuicStream::OnCanWrite() {
-  if (session_->save_data_before_consumption()) {
-    DCHECK(queued_data_.empty());
-    if (write_side_closed_) {
-      QUIC_DLOG(ERROR) << ENDPOINT << "Stream " << id()
-                       << "attempting to write when the write side is closed";
-      return;
-    }
-    if (HasBufferedData() || (fin_buffered_ && !fin_sent_)) {
-      QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_save_data_before_consumption2,
-                        3, 4);
-      WriteBufferedData();
-    }
-    if (!fin_buffered_ && !fin_sent_ && CanWriteNewData()) {
-      // Notify upper layer to write new data when buffered data size is below
-      // low water mark.
-      OnCanWriteNewData();
-    }
+  if (write_side_closed_) {
+    QUIC_DLOG(ERROR) << ENDPOINT << "Stream " << id()
+                     << "attempting to write when the write side is closed";
     return;
   }
-
-  bool fin = false;
-  while (!queued_data_.empty()) {
-    PendingData* pending_data = &queued_data_.front();
-    QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener =
-        pending_data->ack_listener;
-    if (queued_data_.size() == 1 && fin_buffered_) {
-      fin = true;
-    }
-    if (pending_data->offset > 0 &&
-        pending_data->offset >= pending_data->data.size()) {
-      // This should be impossible because offset tracks the amount of
-      // pending_data written thus far.
-      QUIC_BUG << "Pending offset is beyond available data. offset: "
-               << pending_data->offset << " vs: " << pending_data->data.size();
-      return;
-    }
-    size_t remaining_len = pending_data->data.size() - pending_data->offset;
-    struct iovec iov = {
-        const_cast<char*>(pending_data->data.data()) + pending_data->offset,
-        remaining_len};
-    QuicConsumedData consumed_data = WritevData(&iov, 1, fin, ack_listener);
-    queued_data_bytes_ -= consumed_data.bytes_consumed;
-    if (consumed_data.bytes_consumed == remaining_len &&
-        fin == consumed_data.fin_consumed) {
-      queued_data_.pop_front();
-    } else {
-      if (consumed_data.bytes_consumed > 0) {
-        pending_data->offset += consumed_data.bytes_consumed;
-      }
-      break;
-    }
+  if (HasBufferedData() || (fin_buffered_ && !fin_sent_)) {
+    WriteBufferedData();
+  }
+  if (!fin_buffered_ && !fin_sent_ && CanWriteNewData()) {
+    // Notify upper layer to write new data when buffered data size is below
+    // low water mark.
+    OnCanWriteNewData();
   }
 }
 
@@ -344,103 +284,32 @@
     }
   }
 
-  if (session_->save_data_before_consumption()) {
-    QuicConsumedData consumed_data(0, false);
-    if (fin_buffered_) {
-      QUIC_BUG << "Fin already buffered";
-      return consumed_data;
-    }
-
-    bool had_buffered_data = HasBufferedData();
-    if (CanWriteNewData()) {
-      // Save all data if buffered data size is below low water mark.
-      QuicIOVector quic_iovec(iov, iov_count, write_length);
-      consumed_data.bytes_consumed = write_length;
-      if (consumed_data.bytes_consumed > 0) {
-        QuicStreamOffset offset = send_buffer_.stream_offset();
-        send_buffer_.SaveStreamData(quic_iovec, 0, write_length);
-        OnDataBuffered(offset, write_length, ack_listener);
-      }
-    }
-    consumed_data.fin_consumed =
-        consumed_data.bytes_consumed == write_length && fin;
-    fin_buffered_ = consumed_data.fin_consumed;
-
-    if (!had_buffered_data && (HasBufferedData() || fin_buffered_)) {
-      // Write data if there is no buffered data before.
-      QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_save_data_before_consumption2,
-                        1, 4);
-      WriteBufferedData();
-    }
-
+  QuicConsumedData consumed_data(0, false);
+  if (fin_buffered_) {
+    QUIC_BUG << "Fin already buffered";
     return consumed_data;
   }
 
-  // A FIN with zero data payload should not be flow control blocked.
-  bool fin_with_zero_data = (fin && write_length == 0);
-
-  // How much data flow control permits to be written.
-  QuicByteCount send_window = flow_controller_.SendWindowSize();
-  if (stream_contributes_to_connection_flow_control_) {
-    send_window =
-        std::min(send_window, connection_flow_controller_->SendWindowSize());
-  }
-
-  if (session_->ShouldYield(id())) {
-    session_->MarkConnectionLevelWriteBlocked(id());
-    return QuicConsumedData(0, false);
-  }
-
-  if (send_window == 0 && !fin_with_zero_data) {
-    // Quick return if nothing can be sent.
-    MaybeSendBlocked();
-    return QuicConsumedData(0, false);
-  }
-
-  if (write_length > send_window) {
-    // Don't send the FIN unless all the data will be sent.
-    fin = false;
-
-    // Writing more data would be a violation of flow control.
-    write_length = static_cast<size_t>(send_window);
-    QUIC_DVLOG(1) << "stream " << id() << " shortens write length to "
-                  << write_length << " due to flow control";
-  }
-
-  QuicConsumedData consumed_data =
-      WritevDataInner(QuicIOVector(iov, iov_count, write_length),
-                      stream_bytes_written_, fin, std::move(ack_listener));
-  stream_bytes_written_ += consumed_data.bytes_consumed;
-  stream_bytes_outstanding_ += consumed_data.bytes_consumed;
-
-  AddBytesSent(consumed_data.bytes_consumed);
-
-  // The write may have generated a write error causing this stream to be
-  // closed. If so, simply return without marking the stream write blocked.
-  if (write_side_closed_) {
-    return consumed_data;
-  }
-
-  if (consumed_data.bytes_consumed == write_length) {
-    if (!fin_with_zero_data) {
-      MaybeSendBlocked();
+  bool had_buffered_data = HasBufferedData();
+  if (CanWriteNewData()) {
+    // Save all data if buffered data size is below low water mark.
+    QuicIOVector quic_iovec(iov, iov_count, write_length);
+    consumed_data.bytes_consumed = write_length;
+    if (consumed_data.bytes_consumed > 0) {
+      QuicStreamOffset offset = send_buffer_.stream_offset();
+      send_buffer_.SaveStreamData(quic_iovec, 0, write_length);
+      OnDataBuffered(offset, write_length, ack_listener);
     }
-    if (fin && consumed_data.fin_consumed) {
-      fin_sent_ = true;
-      fin_outstanding_ = true;
-      if (fin_received_) {
-        session_->StreamDraining(id_);
-      }
-      CloseWriteSide();
-    } else if (fin && !consumed_data.fin_consumed) {
-      session_->MarkConnectionLevelWriteBlocked(id());
-    }
-  } else {
-    session_->MarkConnectionLevelWriteBlocked(id());
   }
-  if (consumed_data.bytes_consumed > 0 || consumed_data.fin_consumed) {
-    busy_counter_ = 0;
+  consumed_data.fin_consumed =
+      consumed_data.bytes_consumed == write_length && fin;
+  fin_buffered_ = consumed_data.fin_consumed;
+
+  if (!had_buffered_data && (HasBufferedData() || fin_buffered_)) {
+    // Write data if there is no buffered data before.
+    WriteBufferedData();
   }
+
   return consumed_data;
 }
 
@@ -526,16 +395,12 @@
 }
 
 bool QuicStream::HasBufferedData() const {
-  if (session_->save_data_before_consumption()) {
-    DCHECK(queued_data_.empty());
-    DCHECK_GE(send_buffer_.stream_offset(), stream_bytes_written_);
-    return send_buffer_.stream_offset() > stream_bytes_written_;
-  }
-  return !queued_data_.empty();
+  DCHECK_GE(send_buffer_.stream_offset(), stream_bytes_written_);
+  return send_buffer_.stream_offset() > stream_bytes_written_;
 }
 
-QuicVersion QuicStream::version() const {
-  return session_->connection()->version();
+QuicTransportVersion QuicStream::transport_version() const {
+  return session_->connection()->transport_version();
 }
 
 void QuicStream::StopReading() {
@@ -633,14 +498,12 @@
                                     QuicTime::Delta ack_delay_time) {
   OnStreamFrameDiscarded(frame);
   if (ack_listener_ != nullptr) {
-    QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_use_stream_notifier2, 1, 3);
     ack_listener_->OnPacketAcked(frame.data_length, ack_delay_time);
   }
 }
 
 void QuicStream::OnStreamFrameRetransmitted(const QuicStreamFrame& frame) {
   if (ack_listener_ != nullptr) {
-    QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_use_stream_notifier2, 2, 3);
     ack_listener_->OnPacketRetransmitted(frame.data_length);
   }
 }
@@ -657,7 +520,7 @@
   if (frame.fin) {
     fin_outstanding_ = false;
   }
-  if (session_->save_data_before_consumption() && frame.data_length > 0) {
+  if (frame.data_length > 0) {
     send_buffer_.RemoveStreamFrame(frame.offset, frame.data_length);
   }
   if (!IsWaitingForAcks()) {
@@ -677,8 +540,7 @@
 }
 
 void QuicStream::WriteBufferedData() {
-  DCHECK(!write_side_closed_ && queued_data_.empty() &&
-         (HasBufferedData() || fin_buffered_));
+  DCHECK(!write_side_closed_ && (HasBufferedData() || fin_buffered_));
 
   if (session_->ShouldYield(id())) {
     session_->MarkConnectionLevelWriteBlocked(id());
@@ -686,7 +548,7 @@
   }
 
   // Size of buffered data.
-  size_t write_length = queued_data_bytes();
+  size_t write_length = BufferedDataBytes();
 
   // A FIN with zero data payload should not be flow control blocked.
   bool fin_with_zero_data = (fin_buffered_ && write_length == 0);
@@ -726,7 +588,7 @@
   AddBytesSent(consumed_data.bytes_consumed);
   QUIC_DVLOG(1) << ENDPOINT << "stream " << id_ << " sends "
                 << stream_bytes_written_ << " bytes "
-                << " and has buffered data " << queued_data_bytes() << " bytes."
+                << " and has buffered data " << BufferedDataBytes() << " bytes."
                 << " fin is sent: " << consumed_data.fin_consumed
                 << " fin is buffered: " << fin_buffered_;
 
@@ -758,17 +620,13 @@
   }
 }
 
-uint64_t QuicStream::queued_data_bytes() const {
-  if (session_->save_data_before_consumption()) {
-    DCHECK_EQ(0u, queued_data_bytes_);
-    DCHECK_GE(send_buffer_.stream_offset(), stream_bytes_written_);
-    return send_buffer_.stream_offset() - stream_bytes_written_;
-  }
-  return queued_data_bytes_;
+uint64_t QuicStream::BufferedDataBytes() const {
+  DCHECK_GE(send_buffer_.stream_offset(), stream_bytes_written_);
+  return send_buffer_.stream_offset() - stream_bytes_written_;
 }
 
 bool QuicStream::CanWriteNewData() const {
-  return queued_data_bytes() < buffered_data_threshold_;
+  return BufferedDataBytes() < buffered_data_threshold_;
 }
 
 }  // namespace net
diff --git a/net/quic/core/quic_stream.h b/net/quic/core/quic_stream.h
index e36e1f4e..144d9177 100644
--- a/net/quic/core/quic_stream.h
+++ b/net/quic/core/quic_stream.h
@@ -115,9 +115,7 @@
   bool fin_received() { return fin_received_; }
   bool fin_sent() { return fin_sent_; }
 
-  // TODO(fayang): Rename this function to BufferedDataBytes() when
-  // deprecating quic_reloadable_flag_quic_save_data_before_consumption2.
-  uint64_t queued_data_bytes() const;
+  uint64_t BufferedDataBytes() const;
 
   uint64_t stream_bytes_read() const { return stream_bytes_read_; }
   uint64_t stream_bytes_written() const { return stream_bytes_written_; }
@@ -169,7 +167,7 @@
   bool HasBufferedData() const;
 
   // Returns the version of QUIC being used for this stream.
-  QuicVersion version() const;
+  QuicTransportVersion transport_version() const;
 
   bool fin_received() const { return fin_received_; }
 
@@ -214,12 +212,10 @@
   // If |ack_listener| is provided, then it will be notified once all
   // the ACKs for this write have been received.
   // Returns the number of bytes consumed by the connection.
-  // Please note: when quic_reloadable_flag_quic_save_data_before_consumption2
-  // is true, returned consumed data is the amount of data saved in send buffer.
-  // The data is not necessarily consumed by the connection. So write side is
-  // closed when FIN is sent.
-  // TODO(fayang): Let WritevData return boolean when deprecating
-  // quic_reloadable_flag_quic_save_data_before_consumption2.
+  // Please note: Returned consumed data is the amount of data saved in send
+  // buffer. The data is not necessarily consumed by the connection. So write
+  // side is closed when FIN is sent.
+  // TODO(fayang): Let WritevData return boolean.
   QuicConsumedData WritevData(
       const struct iovec* iov,
       int iov_count,
@@ -309,16 +305,9 @@
   void MaybeSendBlocked();
 
   // Write buffered data in send buffer. TODO(fayang): Consider combine
-  // WriteOrBufferData, Writev and WriteBufferedData when deprecating
-  // quic_reloadable_flag_quic_save_data_before_consumption2.
+  // WriteOrBufferData, Writev and WriteBufferedData.
   void WriteBufferedData();
 
-  std::list<PendingData> queued_data_;
-  // How many bytes are queued?
-  // TODO(fayang): Remove this variable when deprecating
-  // quic_reloadable_flag_quic_save_data_before_consumption2.
-  uint64_t queued_data_bytes_;
-
   QuicStreamSequencer sequencer_;
   QuicStreamId id_;
   // Pointer to the owning QuicSession object.
diff --git a/net/quic/core/quic_stream_test.cc b/net/quic/core/quic_stream_test.cc
index d4d6645..ab0d2d6 100644
--- a/net/quic/core/quic_stream_test.cc
+++ b/net/quic/core/quic_stream_test.cc
@@ -28,9 +28,9 @@
 using testing::AnyNumber;
 using testing::AtLeast;
 using testing::CreateFunctor;
+using testing::DoAll;
 using testing::InSequence;
 using testing::Invoke;
-using testing::DoAll;
 using testing::Return;
 using testing::StrictMock;
 using testing::WithArgs;
@@ -56,11 +56,11 @@
   MOCK_METHOD0(OnCanWriteNewData, void());
 
   using QuicStream::CanWriteNewData;
-  using QuicStream::WriteOrBufferData;
-  using QuicStream::WriteMemSlices;
-  using QuicStream::WritevData;
   using QuicStream::CloseWriteSide;
   using QuicStream::OnClose;
+  using QuicStream::WriteMemSlices;
+  using QuicStream::WriteOrBufferData;
+  using QuicStream::WritevData;
   using QuicStream::fin_buffered;
 
  private:
@@ -72,7 +72,7 @@
   QuicStreamTest()
       : initial_flow_control_window_bytes_(kMaxPacketSize),
         zero_(QuicTime::Delta::Zero()),
-        supported_versions_(AllSupportedVersions()) {
+        supported_versions_(AllSupportedTransportVersions()) {
     headers_[":host"] = "www.google.com";
     headers_[":path"] = "/index.hml";
     headers_[":scheme"] = "https";
@@ -158,17 +158,18 @@
   QuicWriteBlockedList* write_blocked_list_;
   uint32_t initial_flow_control_window_bytes_;
   QuicTime::Delta zero_;
-  QuicVersionVector supported_versions_;
+  QuicTransportVersionVector supported_versions_;
   const QuicStreamId kTestStreamId = 5u;
 };
 
 TEST_F(QuicStreamTest, WriteAllData) {
   Initialize(kShouldProcessData);
 
-  size_t length = 1 + QuicPacketCreator::StreamFramePacketOverhead(
-                          connection_->version(), PACKET_8BYTE_CONNECTION_ID,
-                          !kIncludeVersion, !kIncludeDiversificationNonce,
-                          PACKET_6BYTE_PACKET_NUMBER, 0u);
+  size_t length =
+      1 + QuicPacketCreator::StreamFramePacketOverhead(
+              connection_->transport_version(), PACKET_8BYTE_CONNECTION_ID,
+              !kIncludeVersion, !kIncludeDiversificationNonce,
+              PACKET_6BYTE_PACKET_NUMBER, 0u);
   connection_->SetMaxPacketLength(length);
 
   EXPECT_CALL(*session_, WritevData(stream_, kTestStreamId, _, _, _, _))
@@ -196,7 +197,7 @@
       .WillOnce(Return(QuicConsumedData(1, false)));
   stream_->WriteOrBufferData(QuicStringPiece(kData1, 2), false, nullptr);
   ASSERT_EQ(1u, write_blocked_list_->NumBlockedStreams());
-  EXPECT_EQ(1u, stream_->queued_data_bytes());
+  EXPECT_EQ(1u, stream_->BufferedDataBytes());
 }
 
 TEST_F(QuicStreamTest, BlockIfFinNotConsumedWithData) {
@@ -239,32 +240,26 @@
   Initialize(kShouldProcessData);
 
   EXPECT_FALSE(HasWriteBlockedStreams());
-  size_t length = 1 + QuicPacketCreator::StreamFramePacketOverhead(
-                          connection_->version(), PACKET_8BYTE_CONNECTION_ID,
-                          !kIncludeVersion, !kIncludeDiversificationNonce,
-                          PACKET_6BYTE_PACKET_NUMBER, 0u);
+  size_t length =
+      1 + QuicPacketCreator::StreamFramePacketOverhead(
+              connection_->transport_version(), PACKET_8BYTE_CONNECTION_ID,
+              !kIncludeVersion, !kIncludeDiversificationNonce,
+              PACKET_6BYTE_PACKET_NUMBER, 0u);
   connection_->SetMaxPacketLength(length);
 
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
       .WillOnce(Return(QuicConsumedData(kDataLen - 1, false)));
   stream_->WriteOrBufferData(kData1, false, nullptr);
-  EXPECT_EQ(1u, stream_->queued_data_bytes());
+  EXPECT_EQ(1u, stream_->BufferedDataBytes());
   EXPECT_TRUE(HasWriteBlockedStreams());
 
   // Queue a bytes_consumed write.
   stream_->WriteOrBufferData(kData2, false, nullptr);
-  EXPECT_EQ(10u, stream_->queued_data_bytes());
+  EXPECT_EQ(10u, stream_->BufferedDataBytes());
   // Make sure we get the tail of the first write followed by the bytes_consumed
   InSequence s;
-  if (session_->save_data_before_consumption()) {
-    EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
-        .WillOnce(Return(QuicConsumedData(kDataLen - 1, false)));
-  } else {
-    EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
-        .WillOnce(Return(QuicConsumedData(1, false)));
-    EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
-        .WillOnce(Return(QuicConsumedData(kDataLen - 2, false)));
-  }
+  EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
+      .WillOnce(Return(QuicConsumedData(kDataLen - 1, false)));
   stream_->OnCanWrite();
 
   // And finally the end of the bytes_consumed.
@@ -729,11 +724,7 @@
 
   // Send kData1.
   stream_->WriteOrBufferData(kData1, false, nullptr);
-  if (session_->save_data_before_consumption()) {
-    EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
-  } else {
-    EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
-  }
+  EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
   EXPECT_TRUE(stream_->IsWaitingForAcks());
   QuicStreamFrame frame1(stream_->id(), false, 0, kData1);
   stream_->OnStreamFrameAcked(frame1, QuicTime::Delta::Zero());
@@ -744,19 +735,11 @@
   // Send kData2.
   stream_->WriteOrBufferData(kData2, false, nullptr);
   EXPECT_TRUE(stream_->IsWaitingForAcks());
-  if (session_->save_data_before_consumption()) {
-    EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
-  } else {
-    EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
-  }
+  EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
   // Send FIN.
   stream_->WriteOrBufferData("", true, nullptr);
-  if (session_->save_data_before_consumption()) {
-    // Fin only frame is not stored in send buffer.
-    EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
-  } else {
-    EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
-  }
+  // Fin only frame is not stored in send buffer.
+  EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
 
   // kData2 is acked.
   QuicStreamFrame frame2(stream_->id(), false, 9, kData2);
@@ -781,11 +764,7 @@
   stream_->WriteOrBufferData(kData1, false, nullptr);
   stream_->WriteOrBufferData(kData1, false, nullptr);
   stream_->WriteOrBufferData("", true, nullptr);
-  if (session_->save_data_before_consumption()) {
-    EXPECT_EQ(3u, QuicStreamPeer::SendBuffer(stream_).size());
-  } else {
-    EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
-  }
+  EXPECT_EQ(3u, QuicStreamPeer::SendBuffer(stream_).size());
   EXPECT_TRUE(stream_->IsWaitingForAcks());
 
   QuicStreamFrame frame1(stream_->id(), false, 0, kData1);
@@ -793,13 +772,9 @@
   QuicStreamFrame frame3(stream_->id(), false, 18, kData1);
   QuicStreamFrame frame4(stream_->id(), true, 27, "");
   stream_->OnStreamFrameAcked(frame2, QuicTime::Delta::Zero());
-  if (session_->save_data_before_consumption()) {
-    EXPECT_EQ(3u, QuicStreamPeer::SendBuffer(stream_).size());
-  }
+  EXPECT_EQ(3u, QuicStreamPeer::SendBuffer(stream_).size());
   stream_->OnStreamFrameAcked(frame3, QuicTime::Delta::Zero());
-  if (session_->save_data_before_consumption()) {
-    EXPECT_EQ(3u, QuicStreamPeer::SendBuffer(stream_).size());
-  }
+  EXPECT_EQ(3u, QuicStreamPeer::SendBuffer(stream_).size());
   stream_->OnStreamFrameDiscarded(frame1);
   EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
   // FIN is not acked yet.
@@ -818,11 +793,7 @@
   stream_->WriteOrBufferData(kData1, false, nullptr);
   QuicStreamFrame frame(stream_->id(), 0, false, kData1);
   EXPECT_TRUE(stream_->IsWaitingForAcks());
-  if (session_->save_data_before_consumption()) {
-    EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
-  } else {
-    EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
-  }
+  EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
   // Cancel stream.
   stream_->Reset(QUIC_STREAM_NO_ERROR);
   // stream still waits for acks as the error code is QUIC_STREAM_NO_ERROR, and
@@ -831,12 +802,10 @@
   EXPECT_CALL(*session_,
               SendRstStream(stream_->id(), QUIC_STREAM_CANCELLED, 9));
   stream_->Reset(QUIC_STREAM_CANCELLED);
-  if (session_->use_stream_notifier()) {
-    stream_->OnStreamFrameDiscarded(frame);
-    // Stream stops waiting for acks as data is not going to be retransmitted.
-    EXPECT_FALSE(stream_->IsWaitingForAcks());
-    EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
-  }
+  stream_->OnStreamFrameDiscarded(frame);
+  // Stream stops waiting for acks as data is not going to be retransmitted.
+  EXPECT_FALSE(stream_->IsWaitingForAcks());
+  EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
 }
 
 TEST_F(QuicStreamTest, RstFrameReceivedStreamNotFinishSending) {
@@ -849,24 +818,18 @@
   stream_->WriteOrBufferData(kData1, false, nullptr);
   QuicStreamFrame frame(stream_->id(), 0, false, kData1);
   EXPECT_TRUE(stream_->IsWaitingForAcks());
-  if (session_->save_data_before_consumption()) {
-    EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
-  } else {
-    EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
-  }
+  EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
 
   // RST_STREAM received.
   QuicRstStreamFrame rst_frame(stream_->id(), QUIC_STREAM_CANCELLED, 9);
   EXPECT_CALL(*session_,
               SendRstStream(stream_->id(), QUIC_RST_ACKNOWLEDGEMENT, 9));
   stream_->OnStreamReset(rst_frame);
-  if (session_->use_stream_notifier()) {
-    stream_->OnStreamFrameDiscarded(frame);
-    // Stream stops waiting for acks as it does not finish sending and rst is
-    // sent.
-    EXPECT_FALSE(stream_->IsWaitingForAcks());
-    EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
-  }
+  stream_->OnStreamFrameDiscarded(frame);
+  // Stream stops waiting for acks as it does not finish sending and rst is
+  // sent.
+  EXPECT_FALSE(stream_->IsWaitingForAcks());
+  EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
 }
 
 TEST_F(QuicStreamTest, RstFrameReceivedStreamFinishSending) {
@@ -885,11 +848,7 @@
   stream_->OnStreamReset(rst_frame);
   // Stream stops waiting for acks as it has unacked data.
   EXPECT_TRUE(stream_->IsWaitingForAcks());
-  if (session_->save_data_before_consumption()) {
-    EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
-  } else {
-    EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
-  }
+  EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
 }
 
 TEST_F(QuicStreamTest, ConnectionClosed) {
@@ -907,12 +866,10 @@
               SendRstStream(stream_->id(), QUIC_RST_ACKNOWLEDGEMENT, 9));
   stream_->OnConnectionClosed(QUIC_INTERNAL_ERROR,
                               ConnectionCloseSource::FROM_SELF);
-  if (session_->use_stream_notifier()) {
-    stream_->OnStreamFrameDiscarded(frame);
-    // Stream stops waiting for acks as connection is going to close.
-    EXPECT_FALSE(stream_->IsWaitingForAcks());
-    EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
-  }
+  stream_->OnStreamFrameDiscarded(frame);
+  // Stream stops waiting for acks as connection is going to close.
+  EXPECT_FALSE(stream_->IsWaitingForAcks());
+  EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
 }
 
 TEST_F(QuicStreamTest, WriteBufferedData) {
@@ -922,9 +879,6 @@
   set_initial_flow_control_window_bytes(500000);
 
   Initialize(kShouldProcessData);
-  if (!session_->save_data_before_consumption()) {
-    return;
-  }
   string data(1024, 'a');
   EXPECT_TRUE(stream_->CanWriteNewData());
 
@@ -935,14 +889,14 @@
   stream_->WriteOrBufferData(data, false, nullptr);
   stream_->WriteOrBufferData(data, false, nullptr);
   // Verify all data is saved.
-  EXPECT_EQ(3 * data.length() - 100, stream_->queued_data_bytes());
+  EXPECT_EQ(3 * data.length() - 100, stream_->BufferedDataBytes());
 
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
       .WillOnce(Return(QuicConsumedData(100, false)));
   // Buffered data size > threshold, do not ask upper layer for more data.
   EXPECT_CALL(*stream_, OnCanWriteNewData()).Times(0);
   stream_->OnCanWrite();
-  EXPECT_EQ(3 * data.length() - 200, stream_->queued_data_bytes());
+  EXPECT_EQ(3 * data.length() - 200, stream_->BufferedDataBytes());
   EXPECT_FALSE(stream_->CanWriteNewData());
 
   // Send buffered data to make buffered data size < threshold.
@@ -955,7 +909,7 @@
   EXPECT_CALL(*stream_, OnCanWriteNewData()).Times(1);
   stream_->OnCanWrite();
   EXPECT_EQ(GetQuicFlag(FLAGS_quic_buffered_data_threshold) - 1u,
-            stream_->queued_data_bytes());
+            stream_->BufferedDataBytes());
   EXPECT_TRUE(stream_->CanWriteNewData());
 
   // Flush all buffered data.
@@ -963,7 +917,7 @@
       .WillOnce(Invoke(MockQuicSession::ConsumeAllData));
   EXPECT_CALL(*stream_, OnCanWriteNewData()).Times(1);
   stream_->OnCanWrite();
-  EXPECT_EQ(0u, stream_->queued_data_bytes());
+  EXPECT_EQ(0u, stream_->BufferedDataBytes());
   EXPECT_FALSE(stream_->HasBufferedData());
   EXPECT_TRUE(stream_->CanWriteNewData());
 
@@ -976,7 +930,7 @@
   // respecting buffered data upper limit.
   EXPECT_EQ(data.length(), consumed.bytes_consumed);
   EXPECT_FALSE(consumed.fin_consumed);
-  EXPECT_EQ(data.length(), stream_->queued_data_bytes());
+  EXPECT_EQ(data.length(), stream_->BufferedDataBytes());
   EXPECT_FALSE(stream_->CanWriteNewData());
 
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(0);
@@ -984,7 +938,7 @@
   // No Data can be consumed as buffered data is beyond upper limit.
   EXPECT_EQ(0u, consumed.bytes_consumed);
   EXPECT_FALSE(consumed.fin_consumed);
-  EXPECT_EQ(data.length(), stream_->queued_data_bytes());
+  EXPECT_EQ(data.length(), stream_->BufferedDataBytes());
 
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
       .WillOnce(Return(QuicConsumedData(
@@ -992,7 +946,7 @@
   EXPECT_CALL(*stream_, OnCanWriteNewData()).Times(1);
   stream_->OnCanWrite();
   EXPECT_EQ(GetQuicFlag(FLAGS_quic_buffered_data_threshold) - 1,
-            stream_->queued_data_bytes());
+            stream_->BufferedDataBytes());
   EXPECT_TRUE(stream_->CanWriteNewData());
 
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(0);
@@ -1001,7 +955,7 @@
   EXPECT_EQ(data.length(), consumed.bytes_consumed);
   EXPECT_FALSE(consumed.fin_consumed);
   EXPECT_EQ(data.length() + GetQuicFlag(FLAGS_quic_buffered_data_threshold) - 1,
-            stream_->queued_data_bytes());
+            stream_->BufferedDataBytes());
   EXPECT_FALSE(stream_->CanWriteNewData());
 }
 
@@ -1030,7 +984,7 @@
   QuicConsumedData consumed = stream_->WriteMemSlices(span1, false);
   EXPECT_EQ(2048u, consumed.bytes_consumed);
   EXPECT_FALSE(consumed.fin_consumed);
-  EXPECT_EQ(2 * arraysize(data) - 100, stream_->queued_data_bytes());
+  EXPECT_EQ(2 * arraysize(data) - 100, stream_->BufferedDataBytes());
   EXPECT_FALSE(stream_->fin_buffered());
 
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(0);
@@ -1038,7 +992,7 @@
   consumed = stream_->WriteMemSlices(span2, true);
   EXPECT_EQ(0u, consumed.bytes_consumed);
   EXPECT_FALSE(consumed.fin_consumed);
-  EXPECT_EQ(2 * arraysize(data) - 100, stream_->queued_data_bytes());
+  EXPECT_EQ(2 * arraysize(data) - 100, stream_->BufferedDataBytes());
   EXPECT_FALSE(stream_->fin_buffered());
 
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
@@ -1049,7 +1003,7 @@
   EXPECT_CALL(*stream_, OnCanWriteNewData()).Times(1);
   stream_->OnCanWrite();
   EXPECT_EQ(GetQuicFlag(FLAGS_quic_buffered_data_threshold) - 1,
-            stream_->queued_data_bytes());
+            stream_->BufferedDataBytes());
   // Try to write slices2 again.
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(0);
   consumed = stream_->WriteMemSlices(span2, true);
@@ -1057,7 +1011,7 @@
   EXPECT_TRUE(consumed.fin_consumed);
   EXPECT_EQ(
       2 * arraysize(data) + GetQuicFlag(FLAGS_quic_buffered_data_threshold) - 1,
-      stream_->queued_data_bytes());
+      stream_->BufferedDataBytes());
   EXPECT_TRUE(stream_->fin_buffered());
 
   // Flush all buffered data.
diff --git a/net/quic/core/quic_types.h b/net/quic/core/quic_types.h
index f7e9f9a..df9bb13 100644
--- a/net/quic/core/quic_types.h
+++ b/net/quic/core/quic_types.h
@@ -263,6 +263,40 @@
   FIN_AND_PADDING,
 };
 
+// Information about a newly acknowledged packet.
+struct AckedPacket {
+  AckedPacket(QuicPacketNumber packet_number,
+              QuicPacketLength bytes_acked,
+              QuicTime receive_timestamp)
+      : packet_number(packet_number),
+        bytes_acked(bytes_acked),
+        receive_timestamp(receive_timestamp) {}
+
+  QuicPacketNumber packet_number;
+  // Number of bytes sent in the packet that was acknowledged.
+  QuicPacketLength bytes_acked;
+  // The time |packet_number| was received by the peer, according to the
+  // optional timestamp the peer included in the ACK frame which acknowledged
+  // |packet_number|. Zero if no timestamp was available for this packet.
+  QuicTime receive_timestamp;
+};
+
+// A vector of acked packets.
+typedef std::vector<AckedPacket> AckedPacketVector;
+
+// Information about a newly lost packet.
+struct LostPacket {
+  LostPacket(QuicPacketNumber packet_number, QuicPacketLength bytes_lost)
+      : packet_number(packet_number), bytes_lost(bytes_lost) {}
+
+  QuicPacketNumber packet_number;
+  // Number of bytes sent in the packet that was lost.
+  QuicPacketLength bytes_lost;
+};
+
+// A vector of lost packets.
+typedef std::vector<LostPacket> LostPacketVector;
+
 }  // namespace net
 
 #endif  // NET_QUIC_CORE_QUIC_TYPES_H_
diff --git a/net/quic/core/quic_version_manager.cc b/net/quic/core/quic_version_manager.cc
index e504b680..8cecc822 100644
--- a/net/quic/core/quic_version_manager.cc
+++ b/net/quic/core/quic_version_manager.cc
@@ -9,23 +9,25 @@
 
 namespace net {
 
-QuicVersionManager::QuicVersionManager(QuicVersionVector supported_versions)
+QuicVersionManager::QuicVersionManager(
+    QuicTransportVersionVector supported_versions)
     : enable_version_42_(GetQuicFlag(FLAGS_quic_enable_version_42)),
       enable_version_41_(FLAGS_quic_reloadable_flag_quic_enable_version_41),
       enable_version_39_(FLAGS_quic_reloadable_flag_quic_enable_version_39),
       enable_version_38_(FLAGS_quic_reloadable_flag_quic_enable_version_38),
       allowed_supported_versions_(supported_versions),
       filtered_supported_versions_(
-          FilterSupportedVersions(supported_versions)) {}
+          FilterSupportedTransportVersions(supported_versions)) {}
 
 QuicVersionManager::~QuicVersionManager() {}
 
-const QuicVersionVector& QuicVersionManager::GetSupportedVersions() {
-  MaybeRefilterSupportedVersions();
+const QuicTransportVersionVector&
+QuicVersionManager::GetSupportedTransportVersions() {
+  MaybeRefilterSupportedTransportVersions();
   return filtered_supported_versions_;
 }
 
-void QuicVersionManager::MaybeRefilterSupportedVersions() {
+void QuicVersionManager::MaybeRefilterSupportedTransportVersions() {
   if (enable_version_42_ != GetQuicFlag(FLAGS_quic_enable_version_42) ||
       enable_version_41_ != FLAGS_quic_reloadable_flag_quic_enable_version_41 ||
       enable_version_39_ != FLAGS_quic_reloadable_flag_quic_enable_version_39 ||
@@ -34,13 +36,13 @@
     enable_version_41_ = FLAGS_quic_reloadable_flag_quic_enable_version_41;
     enable_version_39_ = FLAGS_quic_reloadable_flag_quic_enable_version_39;
     enable_version_38_ = FLAGS_quic_reloadable_flag_quic_enable_version_38;
-    RefilterSupportedVersions();
+    RefilterSupportedTransportVersions();
   }
 }
 
-void QuicVersionManager::RefilterSupportedVersions() {
+void QuicVersionManager::RefilterSupportedTransportVersions() {
   filtered_supported_versions_ =
-      FilterSupportedVersions(allowed_supported_versions_);
+      FilterSupportedTransportVersions(allowed_supported_versions_);
 }
 
 }  // namespace net
diff --git a/net/quic/core/quic_version_manager.h b/net/quic/core/quic_version_manager.h
index 289bf3f0..6e2a444 100644
--- a/net/quic/core/quic_version_manager.h
+++ b/net/quic/core/quic_version_manager.h
@@ -13,20 +13,20 @@
 // Used to generate filtered supported versions based on flags.
 class QUIC_EXPORT_PRIVATE QuicVersionManager {
  public:
-  explicit QuicVersionManager(QuicVersionVector supported_versions);
+  explicit QuicVersionManager(QuicTransportVersionVector supported_versions);
   virtual ~QuicVersionManager();
 
   // Returns currently supported QUIC versions.
-  const QuicVersionVector& GetSupportedVersions();
+  const QuicTransportVersionVector& GetSupportedTransportVersions();
 
  protected:
   // Maybe refilter filtered_supported_versions_ based on flags.
-  void MaybeRefilterSupportedVersions();
+  void MaybeRefilterSupportedTransportVersions();
 
   // Refilters filtered_supported_versions_.
-  virtual void RefilterSupportedVersions();
+  virtual void RefilterSupportedTransportVersions();
 
-  const QuicVersionVector& filtered_supported_versions() const {
+  const QuicTransportVersionVector& filtered_supported_versions() const {
     return filtered_supported_versions_;
   }
 
@@ -40,10 +40,10 @@
   // FLAGS_quic_reloadable_flag_quic_enable_version_38
   bool enable_version_38_;
   // The list of versions that may be supported.
-  QuicVersionVector allowed_supported_versions_;
+  QuicTransportVersionVector allowed_supported_versions_;
   // This vector contains QUIC versions which are currently supported based on
   // flags.
-  QuicVersionVector filtered_supported_versions_;
+  QuicTransportVersionVector filtered_supported_versions_;
 };
 
 }  // namespace net
diff --git a/net/quic/core/quic_version_manager_test.cc b/net/quic/core/quic_version_manager_test.cc
index 6d824971..870bef71 100644
--- a/net/quic/core/quic_version_manager_test.cc
+++ b/net/quic/core/quic_version_manager_test.cc
@@ -20,59 +20,59 @@
   FLAGS_quic_reloadable_flag_quic_enable_version_41 = false;
   FLAGS_quic_reloadable_flag_quic_enable_version_39 = false;
   FLAGS_quic_reloadable_flag_quic_enable_version_38 = false;
-  QuicVersionManager manager(AllSupportedVersions());
-  EXPECT_EQ(FilterSupportedVersions(AllSupportedVersions()),
-            manager.GetSupportedVersions());
+  QuicVersionManager manager(AllSupportedTransportVersions());
+  EXPECT_EQ(FilterSupportedTransportVersions(AllSupportedTransportVersions()),
+            manager.GetSupportedTransportVersions());
 
-  EXPECT_EQ(FilterSupportedVersions(AllSupportedVersions()),
-            manager.GetSupportedVersions());
-  ASSERT_EQ(2u, manager.GetSupportedVersions().size());
-  EXPECT_EQ(QUIC_VERSION_37, manager.GetSupportedVersions()[0]);
-  EXPECT_EQ(QUIC_VERSION_35, manager.GetSupportedVersions()[1]);
+  EXPECT_EQ(FilterSupportedTransportVersions(AllSupportedTransportVersions()),
+            manager.GetSupportedTransportVersions());
+  ASSERT_EQ(2u, manager.GetSupportedTransportVersions().size());
+  EXPECT_EQ(QUIC_VERSION_37, manager.GetSupportedTransportVersions()[0]);
+  EXPECT_EQ(QUIC_VERSION_35, manager.GetSupportedTransportVersions()[1]);
 
   FLAGS_quic_reloadable_flag_quic_enable_version_38 = true;
-  EXPECT_EQ(FilterSupportedVersions(AllSupportedVersions()),
-            manager.GetSupportedVersions());
-  ASSERT_EQ(3u, manager.GetSupportedVersions().size());
-  EXPECT_EQ(QUIC_VERSION_38, manager.GetSupportedVersions()[0]);
-  EXPECT_EQ(QUIC_VERSION_37, manager.GetSupportedVersions()[1]);
-  EXPECT_EQ(QUIC_VERSION_35, manager.GetSupportedVersions()[2]);
+  EXPECT_EQ(FilterSupportedTransportVersions(AllSupportedTransportVersions()),
+            manager.GetSupportedTransportVersions());
+  ASSERT_EQ(3u, manager.GetSupportedTransportVersions().size());
+  EXPECT_EQ(QUIC_VERSION_38, manager.GetSupportedTransportVersions()[0]);
+  EXPECT_EQ(QUIC_VERSION_37, manager.GetSupportedTransportVersions()[1]);
+  EXPECT_EQ(QUIC_VERSION_35, manager.GetSupportedTransportVersions()[2]);
 
   FLAGS_quic_reloadable_flag_quic_enable_version_39 = true;
-  EXPECT_EQ(FilterSupportedVersions(AllSupportedVersions()),
-            manager.GetSupportedVersions());
-  ASSERT_EQ(4u, manager.GetSupportedVersions().size());
-  EXPECT_EQ(QUIC_VERSION_39, manager.GetSupportedVersions()[0]);
-  EXPECT_EQ(QUIC_VERSION_38, manager.GetSupportedVersions()[1]);
-  EXPECT_EQ(QUIC_VERSION_37, manager.GetSupportedVersions()[2]);
-  EXPECT_EQ(QUIC_VERSION_35, manager.GetSupportedVersions()[3]);
+  EXPECT_EQ(FilterSupportedTransportVersions(AllSupportedTransportVersions()),
+            manager.GetSupportedTransportVersions());
+  ASSERT_EQ(4u, manager.GetSupportedTransportVersions().size());
+  EXPECT_EQ(QUIC_VERSION_39, manager.GetSupportedTransportVersions()[0]);
+  EXPECT_EQ(QUIC_VERSION_38, manager.GetSupportedTransportVersions()[1]);
+  EXPECT_EQ(QUIC_VERSION_37, manager.GetSupportedTransportVersions()[2]);
+  EXPECT_EQ(QUIC_VERSION_35, manager.GetSupportedTransportVersions()[3]);
 
   FLAGS_quic_reloadable_flag_quic_enable_version_41 = true;
-  ASSERT_EQ(5u, manager.GetSupportedVersions().size());
-  EXPECT_EQ(QUIC_VERSION_41, manager.GetSupportedVersions()[0]);
-  EXPECT_EQ(QUIC_VERSION_39, manager.GetSupportedVersions()[1]);
-  EXPECT_EQ(QUIC_VERSION_38, manager.GetSupportedVersions()[2]);
-  EXPECT_EQ(QUIC_VERSION_37, manager.GetSupportedVersions()[3]);
-  EXPECT_EQ(QUIC_VERSION_35, manager.GetSupportedVersions()[4]);
+  ASSERT_EQ(5u, manager.GetSupportedTransportVersions().size());
+  EXPECT_EQ(QUIC_VERSION_41, manager.GetSupportedTransportVersions()[0]);
+  EXPECT_EQ(QUIC_VERSION_39, manager.GetSupportedTransportVersions()[1]);
+  EXPECT_EQ(QUIC_VERSION_38, manager.GetSupportedTransportVersions()[2]);
+  EXPECT_EQ(QUIC_VERSION_37, manager.GetSupportedTransportVersions()[3]);
+  EXPECT_EQ(QUIC_VERSION_35, manager.GetSupportedTransportVersions()[4]);
 
   SetQuicFlag(&FLAGS_quic_enable_version_42, true);
-  ASSERT_EQ(6u, manager.GetSupportedVersions().size());
-  EXPECT_EQ(QUIC_VERSION_42, manager.GetSupportedVersions()[0]);
-  EXPECT_EQ(QUIC_VERSION_41, manager.GetSupportedVersions()[1]);
-  EXPECT_EQ(QUIC_VERSION_39, manager.GetSupportedVersions()[2]);
-  EXPECT_EQ(QUIC_VERSION_38, manager.GetSupportedVersions()[3]);
-  EXPECT_EQ(QUIC_VERSION_37, manager.GetSupportedVersions()[4]);
-  EXPECT_EQ(QUIC_VERSION_35, manager.GetSupportedVersions()[5]);
+  ASSERT_EQ(6u, manager.GetSupportedTransportVersions().size());
+  EXPECT_EQ(QUIC_VERSION_42, manager.GetSupportedTransportVersions()[0]);
+  EXPECT_EQ(QUIC_VERSION_41, manager.GetSupportedTransportVersions()[1]);
+  EXPECT_EQ(QUIC_VERSION_39, manager.GetSupportedTransportVersions()[2]);
+  EXPECT_EQ(QUIC_VERSION_38, manager.GetSupportedTransportVersions()[3]);
+  EXPECT_EQ(QUIC_VERSION_37, manager.GetSupportedTransportVersions()[4]);
+  EXPECT_EQ(QUIC_VERSION_35, manager.GetSupportedTransportVersions()[5]);
 
-  EXPECT_EQ(FilterSupportedVersions(AllSupportedVersions()),
-            manager.GetSupportedVersions());
-  ASSERT_EQ(6u, manager.GetSupportedVersions().size());
-  EXPECT_EQ(QUIC_VERSION_42, manager.GetSupportedVersions()[0]);
-  EXPECT_EQ(QUIC_VERSION_41, manager.GetSupportedVersions()[1]);
-  EXPECT_EQ(QUIC_VERSION_39, manager.GetSupportedVersions()[2]);
-  EXPECT_EQ(QUIC_VERSION_38, manager.GetSupportedVersions()[3]);
-  EXPECT_EQ(QUIC_VERSION_37, manager.GetSupportedVersions()[4]);
-  EXPECT_EQ(QUIC_VERSION_35, manager.GetSupportedVersions()[5]);
+  EXPECT_EQ(FilterSupportedTransportVersions(AllSupportedTransportVersions()),
+            manager.GetSupportedTransportVersions());
+  ASSERT_EQ(6u, manager.GetSupportedTransportVersions().size());
+  EXPECT_EQ(QUIC_VERSION_42, manager.GetSupportedTransportVersions()[0]);
+  EXPECT_EQ(QUIC_VERSION_41, manager.GetSupportedTransportVersions()[1]);
+  EXPECT_EQ(QUIC_VERSION_39, manager.GetSupportedTransportVersions()[2]);
+  EXPECT_EQ(QUIC_VERSION_38, manager.GetSupportedTransportVersions()[3]);
+  EXPECT_EQ(QUIC_VERSION_37, manager.GetSupportedTransportVersions()[4]);
+  EXPECT_EQ(QUIC_VERSION_35, manager.GetSupportedTransportVersions()[5]);
 }
 
 }  // namespace
diff --git a/net/quic/core/quic_versions.cc b/net/quic/core/quic_versions.cc
index a1988c6..c234c605 100644
--- a/net/quic/core/quic_versions.cc
+++ b/net/quic/core/quic_versions.cc
@@ -7,6 +7,7 @@
 #include "net/quic/core/quic_error_codes.h"
 #include "net/quic/core/quic_tag.h"
 #include "net/quic/core/quic_types.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
 #include "net/quic/platform/api/quic_endian.h"
 #include "net/quic/platform/api/quic_flag_utils.h"
 #include "net/quic/platform/api/quic_flags.h"
@@ -30,22 +31,81 @@
 
 }  // namespace
 
-QuicVersionVector AllSupportedVersions() {
-  QuicVersionVector supported_versions;
-  for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) {
-    supported_versions.push_back(kSupportedQuicVersions[i]);
+QuicVersionLabel CreateQuicVersionLabel(ParsedQuicVersion parsed_version) {
+  char proto = 0;
+  switch (parsed_version.handshake_protocol) {
+    case PROTOCOL_QUIC_CRYPTO:
+      proto = 'Q';
+      break;
+    case PROTOCOL_TLS1_3:
+      if (!FLAGS_quic_supports_tls_handshake) {
+        QUIC_BUG << "TLS use attempted when not enabled";
+      }
+      proto = 'T';
+      break;
+    default:
+      QUIC_LOG(ERROR) << "Invalid HandshakeProtocol: "
+                      << parsed_version.handshake_protocol;
+      return 0;
+  }
+  switch (parsed_version.transport_version) {
+    case QUIC_VERSION_35:
+      return MakeVersionLabel(proto, '0', '3', '5');
+    case QUIC_VERSION_37:
+      return MakeVersionLabel(proto, '0', '3', '7');
+    case QUIC_VERSION_38:
+      return MakeVersionLabel(proto, '0', '3', '8');
+    case QUIC_VERSION_39:
+      return MakeVersionLabel(proto, '0', '3', '9');
+    case QUIC_VERSION_41:
+      return MakeVersionLabel(proto, '0', '4', '1');
+    case QUIC_VERSION_42:
+      return MakeVersionLabel(proto, '0', '4', '2');
+    default:
+      // This shold be an ERROR because we should never attempt to convert an
+      // invalid QuicTransportVersion to be written to the wire.
+      QUIC_LOG(ERROR) << "Unsupported QuicTransportVersion: "
+                      << parsed_version.transport_version;
+      return 0;
+  }
+}
+
+ParsedQuicVersion ParseQuicVersionLabel(QuicVersionLabel version_label) {
+  std::vector<HandshakeProtocol> protocols = {PROTOCOL_QUIC_CRYPTO};
+  if (FLAGS_quic_supports_tls_handshake) {
+    protocols.push_back(PROTOCOL_TLS1_3);
+  }
+  for (QuicTransportVersion version : kSupportedTransportVersions) {
+    for (HandshakeProtocol handshake : protocols) {
+      if (version_label ==
+          CreateQuicVersionLabel(ParsedQuicVersion(handshake, version))) {
+        return ParsedQuicVersion(handshake, version);
+      }
+    }
+  }
+  // Reading from the client so this should not be considered an ERROR.
+  QUIC_DLOG(INFO) << "Unsupported QuicVersionLabel version: "
+                  << QuicVersionLabelToString(version_label);
+  return ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED);
+}
+
+QuicTransportVersionVector AllSupportedTransportVersions() {
+  QuicTransportVersionVector supported_versions;
+  for (size_t i = 0; i < arraysize(kSupportedTransportVersions); ++i) {
+    supported_versions.push_back(kSupportedTransportVersions[i]);
   }
   return supported_versions;
 }
 
-QuicVersionVector CurrentSupportedVersions() {
-  return FilterSupportedVersions(AllSupportedVersions());
+QuicTransportVersionVector CurrentSupportedTransportVersions() {
+  return FilterSupportedTransportVersions(AllSupportedTransportVersions());
 }
 
-QuicVersionVector FilterSupportedVersions(QuicVersionVector versions) {
-  QuicVersionVector filtered_versions(versions.size());
+QuicTransportVersionVector FilterSupportedTransportVersions(
+    QuicTransportVersionVector versions) {
+  QuicTransportVersionVector filtered_versions(versions.size());
   filtered_versions.clear();  // Guaranteed by spec not to change capacity.
-  for (QuicVersion version : versions) {
+  for (QuicTransportVersion version : versions) {
     if (version == QUIC_VERSION_42) {
       if (GetQuicFlag(FLAGS_quic_enable_version_42) &&
           FLAGS_quic_reloadable_flag_quic_enable_version_41 &&
@@ -75,8 +135,10 @@
   return filtered_versions;
 }
 
-QuicVersionVector VersionOfIndex(const QuicVersionVector& versions, int index) {
-  QuicVersionVector version;
+QuicTransportVersionVector VersionOfIndex(
+    const QuicTransportVersionVector& versions,
+    int index) {
+  QuicTransportVersionVector version;
   int version_count = versions.size();
   if (index >= 0 && index < version_count) {
     version.push_back(versions[index]);
@@ -86,26 +148,10 @@
   return version;
 }
 
-QuicVersionLabel QuicVersionToQuicVersionLabel(const QuicVersion version) {
-  switch (version) {
-    case QUIC_VERSION_35:
-      return MakeVersionLabel('Q', '0', '3', '5');
-    case QUIC_VERSION_37:
-      return MakeVersionLabel('Q', '0', '3', '7');
-    case QUIC_VERSION_38:
-      return MakeVersionLabel('Q', '0', '3', '8');
-    case QUIC_VERSION_39:
-      return MakeVersionLabel('Q', '0', '3', '9');
-    case QUIC_VERSION_41:
-      return MakeVersionLabel('Q', '0', '4', '1');
-    case QUIC_VERSION_42:
-      return MakeVersionLabel('Q', '0', '4', '2');
-    default:
-      // This shold be an ERROR because we should never attempt to convert an
-      // invalid QuicVersion to be written to the wire.
-      QUIC_LOG(ERROR) << "Unsupported QuicVersion: " << version;
-      return 0;
-  }
+QuicVersionLabel QuicVersionToQuicVersionLabel(
+    QuicTransportVersion transport_version) {
+  return CreateQuicVersionLabel(
+      ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, transport_version));
 }
 
 string QuicVersionLabelToString(QuicVersionLabel version_label) {
@@ -117,25 +163,22 @@
   return QuicTagToString(QuicEndian::HostToNet32(version_label));
 }
 
-QuicVersion QuicVersionLabelToQuicVersion(QuicVersionLabel version_label) {
-  for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) {
-    if (version_label ==
-        QuicVersionToQuicVersionLabel(kSupportedQuicVersions[i])) {
-      return kSupportedQuicVersions[i];
-    }
-  }
-  // Reading from the client so this should not be considered an ERROR.
-  QUIC_DLOG(INFO) << "Unsupported QuicVersionLabel version: "
-                  << QuicVersionLabelToString(version_label);
-  return QUIC_VERSION_UNSUPPORTED;
+QuicTransportVersion QuicVersionLabelToQuicVersion(
+    QuicVersionLabel version_label) {
+  return ParseQuicVersionLabel(version_label).transport_version;
+}
+
+HandshakeProtocol QuicVersionLabelToHandshakeProtocol(
+    QuicVersionLabel version_label) {
+  return ParseQuicVersionLabel(version_label).handshake_protocol;
 }
 
 #define RETURN_STRING_LITERAL(x) \
   case x:                        \
     return #x
 
-string QuicVersionToString(const QuicVersion version) {
-  switch (version) {
+string QuicVersionToString(QuicTransportVersion transport_version) {
+  switch (transport_version) {
     RETURN_STRING_LITERAL(QUIC_VERSION_35);
     RETURN_STRING_LITERAL(QUIC_VERSION_37);
     RETURN_STRING_LITERAL(QUIC_VERSION_38);
@@ -147,7 +190,8 @@
   }
 }
 
-string QuicVersionVectorToString(const QuicVersionVector& versions) {
+string QuicTransportVersionVectorToString(
+    const QuicTransportVersionVector& versions) {
   string result = "";
   for (size_t i = 0; i < versions.size(); ++i) {
     if (i != 0) {
diff --git a/net/quic/core/quic_versions.h b/net/quic/core/quic_versions.h
index 0c35eef..8ec84c41 100644
--- a/net/quic/core/quic_versions.h
+++ b/net/quic/core/quic_versions.h
@@ -17,10 +17,10 @@
 // The available versions of QUIC. Guaranteed that the integer value of the enum
 // will match the version number.
 // When adding a new version to this enum you should add it to
-// kSupportedQuicVersions (if appropriate), and also add a new case to the
-// helper methods QuicVersionToQuicTag, QuicTagToQuicVersion, and
-// QuicVersionToString.
-enum QuicVersion {
+// kSupportedTransportVersions (if appropriate), and also add a new case to the
+// helper methods QuicVersionToQuicVersionLabel, QuicVersionLabelToQuicVersion,
+// and QuicVersionToString.
+enum QuicTransportVersion {
   // Special case to indicate unknown/unsupported QUIC version.
   QUIC_VERSION_UNSUPPORTED = 0,
 
@@ -39,6 +39,30 @@
   // http://sites/quic/adding-and-removing-versions
 };
 
+// The crypto handshake protocols that can be used with QUIC.
+enum HandshakeProtocol {
+  PROTOCOL_UNSUPPORTED,
+  PROTOCOL_QUIC_CRYPTO,
+  PROTOCOL_TLS1_3,
+};
+
+// A parsed QUIC version label which determines that handshake protocol
+// and the transport version.
+struct ParsedQuicVersion {
+  HandshakeProtocol handshake_protocol;
+  QuicTransportVersion transport_version;
+
+  ParsedQuicVersion(HandshakeProtocol handshake_protocol,
+                    QuicTransportVersion transport_version)
+      : handshake_protocol(handshake_protocol),
+        transport_version(transport_version) {}
+
+  bool operator==(const ParsedQuicVersion& other) const {
+    return handshake_protocol == other.handshake_protocol &&
+           transport_version == other.transport_version;
+  }
+};
+
 // Representation of the on-the-wire QUIC version number. Will be written/read
 // to the wire in network-byte-order.
 using QuicVersionLabel = uint32_t;
@@ -51,53 +75,71 @@
 //
 // IMPORTANT: if you are adding to this list, follow the instructions at
 // http://sites/quic/adding-and-removing-versions
-static const QuicVersion kSupportedQuicVersions[] = {
+static const QuicTransportVersion kSupportedTransportVersions[] = {
     QUIC_VERSION_42, QUIC_VERSION_41, QUIC_VERSION_39,
     QUIC_VERSION_38, QUIC_VERSION_37, QUIC_VERSION_35};
 
-typedef std::vector<QuicVersion> QuicVersionVector;
+typedef std::vector<QuicTransportVersion> QuicTransportVersionVector;
 
-// Returns a vector of QUIC versions in kSupportedQuicVersions.
-QUIC_EXPORT_PRIVATE QuicVersionVector AllSupportedVersions();
+// Returns a vector of QUIC versions in kSupportedTransportVersions.
+QUIC_EXPORT_PRIVATE QuicTransportVersionVector AllSupportedTransportVersions();
 
-// Returns a vector of QUIC versions from kSupportedQuicVersions which exclude
-// any versions which are disabled by flags.
-QUIC_EXPORT_PRIVATE QuicVersionVector CurrentSupportedVersions();
+// Returns a vector of QUIC versions from kSupportedTransportVersions which
+// exclude any versions which are disabled by flags.
+QUIC_EXPORT_PRIVATE QuicTransportVersionVector
+CurrentSupportedTransportVersions();
 
 // Returns a vector of QUIC versions from |versions| which exclude any versions
 // which are disabled by flags.
-QUIC_EXPORT_PRIVATE QuicVersionVector
-FilterSupportedVersions(QuicVersionVector versions);
+QUIC_EXPORT_PRIVATE QuicTransportVersionVector
+FilterSupportedTransportVersions(QuicTransportVersionVector versions);
 
 // Returns QUIC version of |index| in result of |versions|. Returns
 // QUIC_VERSION_UNSUPPORTED if |index| is out of bounds.
-QUIC_EXPORT_PRIVATE QuicVersionVector
-VersionOfIndex(const QuicVersionVector& versions, int index);
+QUIC_EXPORT_PRIVATE QuicTransportVersionVector
+VersionOfIndex(const QuicTransportVersionVector& versions, int index);
 
 // QuicVersionLabel is written to and read from the wire, but we prefer to use
-// the more readable QuicVersion at other levels.
-// Helper function which translates from a QuicVersion to a QuicVersionLabel.
-// Returns 0 if |version| is unsupported.
+// the more readable ParsedQuicVersion at other levels.
+// Helper function which translates from a QuicVersionLabel to a
+// ParsedQuicVersion.
+QUIC_EXPORT_PRIVATE ParsedQuicVersion
+ParseQuicVersionLabel(QuicVersionLabel version_label);
+
+// Constructs a QuicVersionLabel from the provided ParsedQuicVersion.
 QUIC_EXPORT_PRIVATE QuicVersionLabel
-QuicVersionToQuicVersionLabel(const QuicVersion version);
+CreateQuicVersionLabel(ParsedQuicVersion parsed_version);
+
+// QuicVersionLabel is written to and read from the wire, but we prefer to use
+// the more readable QuicTransportVersion at other levels.
+// Helper function which translates from a QuicTransportVersion to a
+// QuicVersionLabel. Returns 0 if |version| is unsupported.
+QUIC_EXPORT_PRIVATE QuicVersionLabel
+QuicVersionToQuicVersionLabel(QuicTransportVersion transport_version);
 
 // Helper function which translates from a QuicVersionLabel to a std::string.
 QUIC_EXPORT_PRIVATE std::string QuicVersionLabelToString(
     QuicVersionLabel version_label);
 
-// Returns appropriate QuicVersion from a QuicVersionLabel.
-// Returns QUIC_VERSION_UNSUPPORTED if version_tag cannot be understood.
-QUIC_EXPORT_PRIVATE QuicVersion
+// Returns appropriate QuicTransportVersion from a QuicVersionLabel.
+// Returns QUIC_VERSION_UNSUPPORTED if |version_label| cannot be understood.
+QUIC_EXPORT_PRIVATE QuicTransportVersion
 QuicVersionLabelToQuicVersion(QuicVersionLabel version_label);
 
-// Helper function which translates from a QuicVersion to a string.
+// Returns the HandshakeProtocol used with the given |version_label|, returning
+// PROTOCOL_UNSUPPORTED if it is unknown.
+QUIC_EXPORT_PRIVATE HandshakeProtocol
+QuicVersionLabelToHandshakeProtocol(QuicVersionLabel version_label);
+
+// Helper function which translates from a QuicTransportVersion to a string.
 // Returns strings corresponding to enum names (e.g. QUIC_VERSION_6).
-QUIC_EXPORT_PRIVATE std::string QuicVersionToString(const QuicVersion version);
+QUIC_EXPORT_PRIVATE std::string QuicVersionToString(
+    QuicTransportVersion transport_version);
 
 // Returns comma separated list of string representations of QuicVersion enum
 // values in the supplied |versions| vector.
-QUIC_EXPORT_PRIVATE std::string QuicVersionVectorToString(
-    const QuicVersionVector& versions);
+QUIC_EXPORT_PRIVATE std::string QuicTransportVersionVectorToString(
+    const QuicTransportVersionVector& versions);
 
 }  // namespace net
 
diff --git a/net/quic/core/quic_versions_test.cc b/net/quic/core/quic_versions_test.cc
index 9b985806..e8def57 100644
--- a/net/quic/core/quic_versions_test.cc
+++ b/net/quic/core/quic_versions_test.cc
@@ -12,11 +12,20 @@
 namespace test {
 namespace {
 
-class QuicVersionsTest : public QuicTest {};
+class QuicVersionsTest : public QuicTest {
+ protected:
+  QuicVersionLabel MakeVersionLabel(char a, char b, char c, char d) {
+    if (!FLAGS_quic_reloadable_flag_quic_use_net_byte_order_version_label) {
+      return MakeQuicTag(a, b, c, d);
+    }
+    return MakeQuicTag(d, c, b, a);
+  }
+};
 
 TEST_F(QuicVersionsTest, QuicVersionToQuicVersionLabel) {
-// If you add a new version to the QuicVersion enum you will need to add a new
-// case to QuicVersionToQuicVersionLabel, otherwise this test will fail.
+// If you add a new version to the QuicTransportVersion enum you will need to
+// add a new case to QuicVersionToQuicVersionLabel, otherwise this test will
+// fail.
 
 // TODO(rtenneti): Enable checking of Log(ERROR) messages.
 #if 0
@@ -38,8 +47,8 @@
   // Loop over all supported versions and make sure that we never hit the
   // default case (i.e. all supported versions should be successfully converted
   // to valid QuicVersionLabels).
-  for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) {
-    QuicVersion version = kSupportedQuicVersions[i];
+  for (size_t i = 0; i < arraysize(kSupportedTransportVersions); ++i) {
+    QuicTransportVersion version = kSupportedTransportVersions[i];
     EXPECT_LT(0u, QuicVersionToQuicVersionLabel(version));
   }
 }
@@ -51,7 +60,8 @@
   // and QuicConnectionTest::SendVersionNegotiationPacket can be changed to use
   // mis-matched versions rather than relying on QUIC_VERSION_UNSUPPORTED.
   ScopedMockLog log(kDoNotCaptureLogsYet);
-  EXPECT_CALL(log, Log(base_logging::ERROR, _, "Unsupported QuicVersion: 0"))
+  EXPECT_CALL(
+      log, Log(base_logging::ERROR, _, "Unsupported QuicTransportVersion: 0"))
       .Times(1);
   log.StartCapturingLogs();
 #endif
@@ -59,9 +69,10 @@
   EXPECT_EQ(0u, QuicVersionToQuicVersionLabel(QUIC_VERSION_UNSUPPORTED));
 }
 
-TEST_F(QuicVersionsTest, QuicVersionLabelToQuicVersion) {
-// If you add a new version to the QuicVersion enum you will need to add a new
-// case to QuicVersionLabelToQuicVersion, otherwise this test will fail.
+TEST_F(QuicVersionsTest, QuicVersionLabelToQuicTransportVersion) {
+// If you add a new version to the QuicTransportVersion enum you will need to
+// add a new case to QuicVersionLabelToQuicTransportVersion, otherwise this
+// test will fail.
 
 // TODO(rtenneti): Enable checking of Log(ERROR) messages.
 #if 0
@@ -80,18 +91,18 @@
               QuicVersionLabelToQuicVersion(MakeQuicTag('5', '3', '0', 'Q')));
   }
 
-  for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) {
-    QuicVersion version = kSupportedQuicVersions[i];
+  for (size_t i = 0; i < arraysize(kSupportedTransportVersions); ++i) {
+    QuicTransportVersion version = kSupportedTransportVersions[i];
 
     // Get the label from the version (we can loop over QuicVersions easily).
     QuicVersionLabel version_label = QuicVersionToQuicVersionLabel(version);
     EXPECT_LT(0u, version_label);
 
     // Now try converting back.
-    QuicVersion label_to_quic_version =
+    QuicTransportVersion label_to_transport_version =
         QuicVersionLabelToQuicVersion(version_label);
-    EXPECT_EQ(version, label_to_quic_version);
-    EXPECT_NE(QUIC_VERSION_UNSUPPORTED, label_to_quic_version);
+    EXPECT_EQ(version, label_to_transport_version);
+    EXPECT_NE(QUIC_VERSION_UNSUPPORTED, label_to_transport_version);
   }
 }
 
@@ -117,73 +128,214 @@
             QuicVersionLabelToQuicVersion(MakeQuicTag('F', 'A', 'K', 'E')));
 }
 
+TEST_F(QuicVersionsTest, QuicVersionLabelToHandshakeProtocol) {
+// TODO(rtenneti): Enable checking of Log(ERROR) messages.
+#if 0
+  ScopedMockLog log(kDoNotCaptureLogsYet);
+  EXPECT_CALL(log, Log(_, _, _)).Times(0);
+  log.StartCapturingLogs();
+#endif
+
+  for (size_t i = 0; i < arraysize(kSupportedTransportVersions); ++i) {
+    QuicVersionLabel version_label =
+        QuicVersionToQuicVersionLabel(kSupportedTransportVersions[i]);
+    EXPECT_EQ(PROTOCOL_QUIC_CRYPTO,
+              QuicVersionLabelToHandshakeProtocol(version_label));
+  }
+
+  // Test a TLS version:
+  FLAGS_quic_supports_tls_handshake = true;
+  QuicTag tls_tag;
+  if (!FLAGS_quic_reloadable_flag_quic_use_net_byte_order_version_label) {
+    tls_tag = MakeQuicTag('T', '0', '4', '1');
+  } else {
+    tls_tag = MakeQuicTag('1', '4', '0', 'T');
+  }
+  EXPECT_EQ(PROTOCOL_TLS1_3, QuicVersionLabelToHandshakeProtocol(tls_tag));
+
+  FLAGS_quic_supports_tls_handshake = false;
+#if 0
+#ifndef NDEBUG
+  EXPECT_CALL(log, Log(base_logging::INFO, _,
+                       "Unsupported QuicVersionLabel version: T041"))
+      .Times(1);
+#endif
+#endif
+  EXPECT_EQ(PROTOCOL_UNSUPPORTED, QuicVersionLabelToHandshakeProtocol(tls_tag));
+}
+
+TEST_F(QuicVersionsTest, ParseQuicVersionLabel) {
+  EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_35),
+            ParseQuicVersionLabel(MakeVersionLabel('Q', '0', '3', '5')));
+  EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_37),
+            ParseQuicVersionLabel(MakeVersionLabel('Q', '0', '3', '7')));
+  EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_38),
+            ParseQuicVersionLabel(MakeVersionLabel('Q', '0', '3', '8')));
+  EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_39),
+            ParseQuicVersionLabel(MakeVersionLabel('Q', '0', '3', '9')));
+  EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_41),
+            ParseQuicVersionLabel(MakeVersionLabel('Q', '0', '4', '1')));
+  EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_42),
+            ParseQuicVersionLabel(MakeVersionLabel('Q', '0', '4', '2')));
+
+  // Test a TLS version:
+  FLAGS_quic_supports_tls_handshake = true;
+  EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_35),
+            ParseQuicVersionLabel(MakeVersionLabel('T', '0', '3', '5')));
+  EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_37),
+            ParseQuicVersionLabel(MakeVersionLabel('T', '0', '3', '7')));
+  EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_38),
+            ParseQuicVersionLabel(MakeVersionLabel('T', '0', '3', '8')));
+  EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_39),
+            ParseQuicVersionLabel(MakeVersionLabel('T', '0', '3', '9')));
+  EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_41),
+            ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '1')));
+  EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_42),
+            ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '2')));
+
+  FLAGS_quic_supports_tls_handshake = false;
+  EXPECT_EQ(ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED),
+            ParseQuicVersionLabel(MakeVersionLabel('T', '0', '3', '5')));
+  EXPECT_EQ(ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED),
+            ParseQuicVersionLabel(MakeVersionLabel('T', '0', '3', '7')));
+  EXPECT_EQ(ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED),
+            ParseQuicVersionLabel(MakeVersionLabel('T', '0', '3', '8')));
+  EXPECT_EQ(ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED),
+            ParseQuicVersionLabel(MakeVersionLabel('T', '0', '3', '9')));
+  EXPECT_EQ(ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED),
+            ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '1')));
+  EXPECT_EQ(ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED),
+            ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '2')));
+}
+
+TEST_F(QuicVersionsTest, CreateQuicVersionLabel) {
+  EXPECT_EQ(MakeVersionLabel('Q', '0', '3', '5'),
+            CreateQuicVersionLabel(
+                ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_35)));
+  EXPECT_EQ(MakeVersionLabel('Q', '0', '3', '7'),
+            CreateQuicVersionLabel(
+                ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_37)));
+  EXPECT_EQ(MakeVersionLabel('Q', '0', '3', '8'),
+            CreateQuicVersionLabel(
+                ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_38)));
+  EXPECT_EQ(MakeVersionLabel('Q', '0', '3', '9'),
+            CreateQuicVersionLabel(
+                ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_39)));
+  EXPECT_EQ(MakeVersionLabel('Q', '0', '4', '1'),
+            CreateQuicVersionLabel(
+                ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_41)));
+  EXPECT_EQ(MakeVersionLabel('Q', '0', '4', '2'),
+            CreateQuicVersionLabel(
+                ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_42)));
+
+  // Test a TLS version:
+  FLAGS_quic_supports_tls_handshake = true;
+  EXPECT_EQ(MakeVersionLabel('T', '0', '3', '5'),
+            CreateQuicVersionLabel(
+                ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_35)));
+  EXPECT_EQ(MakeVersionLabel('T', '0', '3', '7'),
+            CreateQuicVersionLabel(
+                ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_37)));
+  EXPECT_EQ(MakeVersionLabel('T', '0', '3', '8'),
+            CreateQuicVersionLabel(
+                ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_38)));
+  EXPECT_EQ(MakeVersionLabel('T', '0', '3', '9'),
+            CreateQuicVersionLabel(
+                ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_39)));
+  EXPECT_EQ(MakeVersionLabel('T', '0', '4', '1'),
+            CreateQuicVersionLabel(
+                ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_41)));
+  EXPECT_EQ(MakeVersionLabel('T', '0', '4', '2'),
+            CreateQuicVersionLabel(
+                ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_42)));
+
+  FLAGS_quic_supports_tls_handshake = false;
+  EXPECT_EQ(ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED),
+            ParseQuicVersionLabel(MakeVersionLabel('T', '0', '3', '5')));
+  EXPECT_EQ(ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED),
+            ParseQuicVersionLabel(MakeVersionLabel('T', '0', '3', '7')));
+  EXPECT_EQ(ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED),
+            ParseQuicVersionLabel(MakeVersionLabel('T', '0', '3', '8')));
+  EXPECT_EQ(ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED),
+            ParseQuicVersionLabel(MakeVersionLabel('T', '0', '3', '9')));
+  EXPECT_EQ(ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED),
+            ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '1')));
+  EXPECT_EQ(ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED),
+            ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '2')));
+}
+
 TEST_F(QuicVersionsTest, QuicVersionToString) {
   EXPECT_EQ("QUIC_VERSION_35", QuicVersionToString(QUIC_VERSION_35));
   EXPECT_EQ("QUIC_VERSION_UNSUPPORTED",
             QuicVersionToString(QUIC_VERSION_UNSUPPORTED));
 
-  QuicVersion single_version[] = {QUIC_VERSION_35};
-  QuicVersionVector versions_vector;
+  QuicTransportVersion single_version[] = {QUIC_VERSION_35};
+  QuicTransportVersionVector versions_vector;
   for (size_t i = 0; i < arraysize(single_version); ++i) {
     versions_vector.push_back(single_version[i]);
   }
-  EXPECT_EQ("QUIC_VERSION_35", QuicVersionVectorToString(versions_vector));
+  EXPECT_EQ("QUIC_VERSION_35",
+            QuicTransportVersionVectorToString(versions_vector));
 
-  QuicVersion multiple_versions[] = {QUIC_VERSION_UNSUPPORTED, QUIC_VERSION_35};
+  QuicTransportVersion multiple_versions[] = {QUIC_VERSION_UNSUPPORTED,
+                                              QUIC_VERSION_35};
   versions_vector.clear();
   for (size_t i = 0; i < arraysize(multiple_versions); ++i) {
     versions_vector.push_back(multiple_versions[i]);
   }
   EXPECT_EQ("QUIC_VERSION_UNSUPPORTED,QUIC_VERSION_35",
-            QuicVersionVectorToString(versions_vector));
+            QuicTransportVersionVectorToString(versions_vector));
 
   // Make sure that all supported versions are present in QuicVersionToString.
-  for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) {
-    QuicVersion version = kSupportedQuicVersions[i];
+  for (size_t i = 0; i < arraysize(kSupportedTransportVersions); ++i) {
+    QuicTransportVersion version = kSupportedTransportVersions[i];
     EXPECT_NE("QUIC_VERSION_UNSUPPORTED", QuicVersionToString(version));
   }
 }
 
-TEST_F(QuicVersionsTest, FilterSupportedVersionsNo38) {
-  QuicVersionVector all_versions = {QUIC_VERSION_35, QUIC_VERSION_37,
-                                    QUIC_VERSION_38, QUIC_VERSION_39};
+TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsNo38) {
+  QuicTransportVersionVector all_versions = {QUIC_VERSION_35, QUIC_VERSION_37,
+                                             QUIC_VERSION_38, QUIC_VERSION_39};
 
   FLAGS_quic_reloadable_flag_quic_enable_version_38 = false;
 
-  QuicVersionVector filtered_versions = FilterSupportedVersions(all_versions);
+  QuicTransportVersionVector filtered_versions =
+      FilterSupportedTransportVersions(all_versions);
   ASSERT_EQ(2u, filtered_versions.size());
   EXPECT_EQ(QUIC_VERSION_35, filtered_versions[0]);
   EXPECT_EQ(QUIC_VERSION_37, filtered_versions[1]);
 }
 
-TEST_F(QuicVersionsTest, FilterSupportedVersionsNo39) {
-  QuicVersionVector all_versions = {QUIC_VERSION_35, QUIC_VERSION_37,
-                                    QUIC_VERSION_38, QUIC_VERSION_39};
+TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsNo39) {
+  QuicTransportVersionVector all_versions = {QUIC_VERSION_35, QUIC_VERSION_37,
+                                             QUIC_VERSION_38, QUIC_VERSION_39};
 
   FLAGS_quic_reloadable_flag_quic_enable_version_38 = true;
   FLAGS_quic_reloadable_flag_quic_enable_version_39 = false;
 
-  QuicVersionVector filtered_versions = FilterSupportedVersions(all_versions);
+  QuicTransportVersionVector filtered_versions =
+      FilterSupportedTransportVersions(all_versions);
   ASSERT_EQ(3u, filtered_versions.size());
   EXPECT_EQ(QUIC_VERSION_35, filtered_versions[0]);
   EXPECT_EQ(QUIC_VERSION_37, filtered_versions[1]);
   EXPECT_EQ(QUIC_VERSION_38, filtered_versions[2]);
 }
 
-TEST_F(QuicVersionsTest, FilterSupportedVersionsAllVersions) {
-  QuicVersionVector all_versions = {QUIC_VERSION_35, QUIC_VERSION_37,
-                                    QUIC_VERSION_38, QUIC_VERSION_39};
+TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsAllVersions) {
+  QuicTransportVersionVector all_versions = {QUIC_VERSION_35, QUIC_VERSION_37,
+                                             QUIC_VERSION_38, QUIC_VERSION_39};
 
   FLAGS_quic_reloadable_flag_quic_enable_version_38 = true;
   FLAGS_quic_reloadable_flag_quic_enable_version_39 = true;
 
-  QuicVersionVector filtered_versions = FilterSupportedVersions(all_versions);
+  QuicTransportVersionVector filtered_versions =
+      FilterSupportedTransportVersions(all_versions);
   ASSERT_EQ(all_versions, filtered_versions);
 }
 
 TEST_F(QuicVersionsTest, LookUpVersionByIndex) {
-  QuicVersionVector all_versions = {QUIC_VERSION_35, QUIC_VERSION_37,
-                                    QUIC_VERSION_38, QUIC_VERSION_39};
+  QuicTransportVersionVector all_versions = {QUIC_VERSION_35, QUIC_VERSION_37,
+                                             QUIC_VERSION_38, QUIC_VERSION_39};
   int version_count = all_versions.size();
   for (int i = -5; i <= version_count + 1; ++i) {
     if (i >= 0 && i < version_count) {
diff --git a/net/quic/quartc/quartc_factory.cc b/net/quic/quartc/quartc_factory.cc
index c81cc4a..e84e477 100644
--- a/net/quic/quartc/quartc_factory.cc
+++ b/net/quic/quartc/quartc_factory.cc
@@ -140,7 +140,7 @@
   return std::unique_ptr<QuicConnection>(new QuicConnection(
       dummy_id, dummy_address, this, /*QuicConnectionHelperInterface*/
       this /*QuicAlarmFactory*/, writer.release(), true /*own the writer*/,
-      perspective, AllSupportedVersions()));
+      perspective, AllSupportedTransportVersions()));
 }
 
 QuicAlarm* QuartcFactory::CreateAlarm(QuicAlarm::Delegate* delegate) {
diff --git a/net/quic/quartc/quartc_session.cc b/net/quic/quartc/quartc_session.cc
index 30d2d2b..62bdf36 100644
--- a/net/quic/quartc/quartc_session.cc
+++ b/net/quic/quartc/quartc_session.cc
@@ -35,7 +35,7 @@
   void GetProof(const QuicSocketAddress& server_addr,
                 const string& hostname,
                 const string& server_config,
-                QuicVersion quic_version,
+                QuicTransportVersion transport_version,
                 QuicStringPiece chlo_hash,
                 const QuicTagVector& connection_options,
                 std::unique_ptr<Callback> callback) override {
@@ -78,7 +78,7 @@
       const string& hostname,
       const uint16_t port,
       const string& server_config,
-      QuicVersion quic_version,
+      QuicTransportVersion transport_version,
       QuicStringPiece chlo_hash,
       const std::vector<string>& certs,
       const string& cert_sct,
@@ -203,6 +203,10 @@
   }
 }
 
+bool QuartcSession::IsOpenStream(QuicStreamId stream_id) {
+  return QuicSession::IsOpenStream(stream_id);
+}
+
 QuartcSessionStats QuartcSession::GetStats() {
   QuartcSessionStats stats;
   const QuicConnectionStats& connection_stats = connection_->GetStats();
diff --git a/net/quic/quartc/quartc_session.h b/net/quic/quartc/quartc_session.h
index 4250101..735c0c2 100644
--- a/net/quic/quartc/quartc_session.h
+++ b/net/quic/quartc/quartc_session.h
@@ -72,6 +72,8 @@
 
   void CancelStream(QuicStreamId stream_id) override;
 
+  bool IsOpenStream(QuicStreamId stream_id) override;
+
   QuartcSessionStats GetStats() override;
 
   void SetDelegate(QuartcSessionInterface::Delegate* session_delegate) override;
diff --git a/net/quic/quartc/quartc_session_interface.h b/net/quic/quartc/quartc_session_interface.h
index 8af6343..37c8fea 100644
--- a/net/quic/quartc/quartc_session_interface.h
+++ b/net/quic/quartc/quartc_session_interface.h
@@ -64,6 +64,12 @@
   // caller tries to cancel them, rendering the caller's pointers invalid.
   virtual void CancelStream(QuicStreamId stream_id) = 0;
 
+  // This method verifies if a stream is still open and stream pointer can be
+  // used. When true is returned, the interface pointer is good for making a
+  // call immediately on the same thread, but may be rendered invalid by ANY
+  // other QUIC activity.
+  virtual bool IsOpenStream(QuicStreamId stream_id) = 0;
+
   // Gets stats associated with this Quartc session.
   virtual QuartcSessionStats GetStats() = 0;
 
diff --git a/net/quic/quartc/quartc_session_test.cc b/net/quic/quartc/quartc_session_test.cc
index 1c4f12c..0773dd7 100644
--- a/net/quic/quartc/quartc_session_test.cc
+++ b/net/quic/quartc/quartc_session_test.cc
@@ -155,7 +155,7 @@
   void GetProof(const QuicSocketAddress& server_ip,
                 const string& hostname,
                 const string& server_config,
-                QuicVersion quic_version,
+                QuicTransportVersion transport_version,
                 QuicStringPiece chlo_hash,
                 const QuicTagVector& connection_options,
                 std::unique_ptr<Callback> callback) override {
@@ -202,7 +202,7 @@
       const string& hostname,
       const uint16_t port,
       const string& server_config,
-      QuicVersion quic_version,
+      QuicTransportVersion transport_version,
       QuicStringPiece chlo_hash,
       const std::vector<string>& certs,
       const string& cert_sct,
@@ -482,7 +482,7 @@
     return std::unique_ptr<QuicConnection>(new QuicConnection(
         0, QuicSocketAddress(ip, 0), this /*QuicConnectionHelperInterface*/,
         alarm_factory_.get(), writer, owns_writer, perspective,
-        AllSupportedVersions()));
+        AllSupportedTransportVersions()));
   }
 
   // Runs all tasks scheduled in the next 200 ms.
diff --git a/net/quic/quartc/quartc_stream_test.cc b/net/quic/quartc/quartc_stream_test.cc
index b4aceb3..9e53860 100644
--- a/net/quic/quartc/quartc_stream_test.cc
+++ b/net/quic/quartc/quartc_stream_test.cc
@@ -178,7 +178,7 @@
     connection_.reset(new QuicConnection(
         0, QuicSocketAddress(ip, 0), this /*QuicConnectionHelperInterface*/,
         alarm_factory_.get(), new DummyPacketWriter(), owns_writer, perspective,
-        AllSupportedVersions()));
+        AllSupportedTransportVersions()));
 
     session_.reset(
         new MockQuicSession(connection_.get(), QuicConfig(), &write_buffer_));
@@ -244,33 +244,18 @@
   stream_->Write("Foo bar", 7, kDefaultParam);
   // The data will not be buffered.
   EXPECT_EQ(0ul, write_buffer_.size());
-  if (session_->save_data_before_consumption()) {
-    EXPECT_TRUE(stream_->HasBufferedData());
-  } else {
-    EXPECT_FALSE(stream_->HasBufferedData());
-  }
+  EXPECT_TRUE(stream_->HasBufferedData());
   EXPECT_EQ(0u, stream_->bytes_written());
   // The stream is writable, but there's nothing to send.
   session_->set_writable(true);
   stream_->OnCanWrite();
-  if (session_->save_data_before_consumption()) {
-    EXPECT_EQ(7u, stream_->bytes_written());
-    EXPECT_EQ(7ul, write_buffer_.size());
-  } else {
-    EXPECT_EQ(0u, stream_->bytes_written());
-    EXPECT_EQ(0ul, write_buffer_.size());
-  }
+  EXPECT_EQ(7u, stream_->bytes_written());
+  EXPECT_EQ(7ul, write_buffer_.size());
   EXPECT_FALSE(stream_->HasBufferedData());
 
   stream_->Write("xyzzy", 5, kDefaultParam);
-  if (session_->save_data_before_consumption()) {
-    EXPECT_EQ("Foo barxyzzy", write_buffer_);
-    EXPECT_EQ(12u, stream_->bytes_written());
-  } else {
-    // The stream threw away the previous data.  It only sends this.
-    EXPECT_EQ("xyzzy", write_buffer_);
-    EXPECT_EQ(5u, stream_->bytes_written());
-  }
+  EXPECT_EQ("Foo barxyzzy", write_buffer_);
+  EXPECT_EQ(12u, stream_->bytes_written());
 }
 
 // Finish writing to a stream.
diff --git a/net/quic/test_tools/crypto_test_utils.cc b/net/quic/test_tools/crypto_test_utils.cc
index bd2ada0..b1ad1df6 100644
--- a/net/quic/test_tools/crypto_test_utils.cc
+++ b/net/quic/test_tools/crypto_test_utils.cc
@@ -309,7 +309,8 @@
     result_ = result;
     crypto_config_->ProcessClientHello(
         result_, /*reject_only=*/false, /*connection_id=*/1, server_addr_,
-        client_addr_, AllSupportedVersions().front(), AllSupportedVersions(),
+        client_addr_, AllSupportedTransportVersions().front(),
+        AllSupportedTransportVersions(),
         /*use_stateless_rejects=*/true, /*server_designated_connection_id=*/0,
         clock_, QuicRandom::GetInstance(), compressed_certs_cache_, params_,
         signed_config_, /*total_framing_overhead=*/50, kDefaultMaxPacketSize,
@@ -596,7 +597,7 @@
   // Note: relies on the callback being invoked synchronously
   bool ok = false;
   proof_source->GetProof(
-      server_address, "", "", AllSupportedVersions().front(), "",
+      server_address, "", "", AllSupportedTransportVersions().front(), "",
       QuicTagVector(),
       std::unique_ptr<ProofSource::Callback>(new Callback(&ok, &chain)));
   if (!ok || chain->certs.empty()) {
@@ -949,7 +950,7 @@
 
 CryptoHandshakeMessage GenerateDefaultInchoateCHLO(
     const QuicClock* clock,
-    QuicVersion version,
+    QuicTransportVersion version,
     QuicCryptoServerConfig* crypto_config) {
   // clang-format off
   return CreateCHLO(
@@ -998,7 +999,7 @@
                       QuicCryptoServerConfig* crypto_config,
                       QuicSocketAddress server_addr,
                       QuicSocketAddress client_addr,
-                      QuicVersion version,
+                      QuicTransportVersion version,
                       const QuicClock* clock,
                       QuicReferenceCountedPointer<QuicSignedServerConfig> proof,
                       QuicCompressedCertsCache* compressed_certs_cache,
diff --git a/net/quic/test_tools/crypto_test_utils.h b/net/quic/test_tools/crypto_test_utils.h
index 0767135..38dc33e 100644
--- a/net/quic/test_tools/crypto_test_utils.h
+++ b/net/quic/test_tools/crypto_test_utils.h
@@ -238,7 +238,7 @@
 // Return an inchoate CHLO with some basic tag value pairs.
 CryptoHandshakeMessage GenerateDefaultInchoateCHLO(
     const QuicClock* clock,
-    QuicVersion version,
+    QuicTransportVersion version,
     QuicCryptoServerConfig* crypto_config);
 
 // Takes a inchoate CHLO, returns a full CHLO in |out| which can pass
@@ -248,7 +248,7 @@
     QuicCryptoServerConfig* crypto_config,
     QuicSocketAddress server_addr,
     QuicSocketAddress client_addr,
-    QuicVersion version,
+    QuicTransportVersion version,
     const QuicClock* clock,
     QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
     QuicCompressedCertsCache* compressed_certs_cache,
diff --git a/net/quic/test_tools/crypto_test_utils_test.cc b/net/quic/test_tools/crypto_test_utils_test.cc
index 86968096..b3fcf55 100644
--- a/net/quic/test_tools/crypto_test_utils_test.cc
+++ b/net/quic/test_tools/crypto_test_utils_test.cc
@@ -60,7 +60,8 @@
     result_ = result;
     crypto_config_->ProcessClientHello(
         result_, /*reject_only=*/false, /*connection_id=*/1, server_addr_,
-        client_addr_, AllSupportedVersions().front(), AllSupportedVersions(),
+        client_addr_, AllSupportedTransportVersions().front(),
+        AllSupportedTransportVersions(),
         /*use_stateless_rejects=*/true, /*server_designated_connection_id=*/0,
         clock_, QuicRandom::GetInstance(), compressed_certs_cache_, params_,
         signed_config_, /*total_framing_overhead=*/50, kDefaultMaxPacketSize,
@@ -149,7 +150,7 @@
   string pub_hex =
       "#" + QuicTextUtils::HexEncode(public_value, sizeof(public_value));
 
-  QuicVersion version(AllSupportedVersions().front());
+  QuicTransportVersion version(AllSupportedTransportVersions().front());
   CryptoHandshakeMessage inchoate_chlo = crypto_test_utils::CreateCHLO(
       {{"PDMD", "X509"},
        {"AEAD", "AESG"},
diff --git a/net/quic/test_tools/failing_proof_source.cc b/net/quic/test_tools/failing_proof_source.cc
index 142e87c..89684c6 100644
--- a/net/quic/test_tools/failing_proof_source.cc
+++ b/net/quic/test_tools/failing_proof_source.cc
@@ -10,7 +10,7 @@
 void FailingProofSource::GetProof(const QuicSocketAddress& server_address,
                                   const std::string& hostname,
                                   const std::string& server_config,
-                                  QuicVersion quic_version,
+                                  QuicTransportVersion transport_version,
                                   QuicStringPiece chlo_hash,
                                   const QuicTagVector& connection_options,
                                   std::unique_ptr<Callback> callback) {
diff --git a/net/quic/test_tools/failing_proof_source.h b/net/quic/test_tools/failing_proof_source.h
index e370efa..1ef18b43 100644
--- a/net/quic/test_tools/failing_proof_source.h
+++ b/net/quic/test_tools/failing_proof_source.h
@@ -16,7 +16,7 @@
   void GetProof(const QuicSocketAddress& server_address,
                 const std::string& hostname,
                 const std::string& server_config,
-                QuicVersion quic_version,
+                QuicTransportVersion transport_version,
                 QuicStringPiece chlo_hash,
                 const QuicTagVector& connection_options,
                 std::unique_ptr<Callback> callback) override;
diff --git a/net/quic/test_tools/fake_proof_source.cc b/net/quic/test_tools/fake_proof_source.cc
index 7a27028..e876316 100644
--- a/net/quic/test_tools/fake_proof_source.cc
+++ b/net/quic/test_tools/fake_proof_source.cc
@@ -23,7 +23,7 @@
     const QuicSocketAddress& server_addr,
     string hostname,
     string server_config,
-    QuicVersion quic_version,
+    QuicTransportVersion transport_version,
     string chlo_hash,
     const QuicTagVector& connection_options,
     std::unique_ptr<ProofSource::Callback> callback,
@@ -31,7 +31,7 @@
     : server_address_(server_addr),
       hostname_(std::move(hostname)),
       server_config_(std::move(server_config)),
-      quic_version_(quic_version),
+      transport_version_(transport_version),
       chlo_hash_(std::move(chlo_hash)),
       connection_options_(connection_options),
       callback_(std::move(callback)),
@@ -41,8 +41,9 @@
 
 void FakeProofSource::GetProofOp::Run() {
   // Note: relies on the callback being invoked synchronously
-  delegate_->GetProof(server_address_, hostname_, server_config_, quic_version_,
-                      chlo_hash_, connection_options_, std::move(callback_));
+  delegate_->GetProof(server_address_, hostname_, server_config_,
+                      transport_version_, chlo_hash_, connection_options_,
+                      std::move(callback_));
 }
 
 FakeProofSource::ComputeSignatureOp::ComputeSignatureOp(
@@ -74,19 +75,21 @@
     const QuicSocketAddress& server_address,
     const string& hostname,
     const string& server_config,
-    QuicVersion quic_version,
+    QuicTransportVersion transport_version,
     QuicStringPiece chlo_hash,
     const QuicTagVector& connection_options,
     std::unique_ptr<ProofSource::Callback> callback) {
   if (!active_) {
-    delegate_->GetProof(server_address, hostname, server_config, quic_version,
-                        chlo_hash, connection_options, std::move(callback));
+    delegate_->GetProof(server_address, hostname, server_config,
+                        transport_version, chlo_hash, connection_options,
+                        std::move(callback));
     return;
   }
 
   pending_ops_.push_back(QuicMakeUnique<GetProofOp>(
-      server_address, hostname, server_config, quic_version, string(chlo_hash),
-      connection_options, std::move(callback), delegate_.get()));
+      server_address, hostname, server_config, transport_version,
+      string(chlo_hash), connection_options, std::move(callback),
+      delegate_.get()));
 }
 
 QuicReferenceCountedPointer<ProofSource::Chain> FakeProofSource::GetCertChain(
diff --git a/net/quic/test_tools/fake_proof_source.h b/net/quic/test_tools/fake_proof_source.h
index 62a182d8..a871031 100644
--- a/net/quic/test_tools/fake_proof_source.h
+++ b/net/quic/test_tools/fake_proof_source.h
@@ -34,7 +34,7 @@
   void GetProof(const QuicSocketAddress& server_address,
                 const std::string& hostname,
                 const std::string& server_config,
-                QuicVersion quic_version,
+                QuicTransportVersion transport_version,
                 QuicStringPiece chlo_hash,
                 const QuicTagVector& connection_options,
                 std::unique_ptr<ProofSource::Callback> callback) override;
@@ -70,7 +70,7 @@
     GetProofOp(const QuicSocketAddress& server_addr,
                std::string hostname,
                std::string server_config,
-               QuicVersion quic_version,
+               QuicTransportVersion transport_version,
                std::string chlo_hash,
                const QuicTagVector& connection_options,
                std::unique_ptr<ProofSource::Callback> callback,
@@ -83,7 +83,7 @@
     QuicSocketAddress server_address_;
     std::string hostname_;
     std::string server_config_;
-    QuicVersion quic_version_;
+    QuicTransportVersion transport_version_;
     std::string chlo_hash_;
     QuicTagVector connection_options_;
     std::unique_ptr<ProofSource::Callback> callback_;
diff --git a/net/quic/test_tools/quic_sent_packet_manager_peer.cc b/net/quic/test_tools/quic_sent_packet_manager_peer.cc
index 0c876c3..c706543 100644
--- a/net/quic/test_tools/quic_sent_packet_manager_peer.cc
+++ b/net/quic/test_tools/quic_sent_packet_manager_peer.cc
@@ -186,5 +186,19 @@
   return &sent_packet_manager->unacked_packets_;
 }
 
+// static
+void QuicSentPacketManagerPeer::DisablePacerBursts(
+    QuicSentPacketManager* sent_packet_manager) {
+  sent_packet_manager->pacing_sender_.burst_tokens_ = 0;
+  sent_packet_manager->pacing_sender_.initial_burst_size_ = 0;
+}
+
+// static
+void QuicSentPacketManagerPeer::SetNextPacedPacketTime(
+    QuicSentPacketManager* sent_packet_manager,
+    QuicTime time) {
+  sent_packet_manager->pacing_sender_.ideal_next_packet_send_time_ = time;
+}
+
 }  // namespace test
 }  // namespace net
diff --git a/net/quic/test_tools/quic_sent_packet_manager_peer.h b/net/quic/test_tools/quic_sent_packet_manager_peer.h
index 3f95030..7da7040f 100644
--- a/net/quic/test_tools/quic_sent_packet_manager_peer.h
+++ b/net/quic/test_tools/quic_sent_packet_manager_peer.h
@@ -90,6 +90,11 @@
   static QuicUnackedPacketMap* GetUnackedPacketMap(
       QuicSentPacketManager* sent_packet_manager);
 
+  static void DisablePacerBursts(QuicSentPacketManager* sent_packet_manager);
+
+  static void SetNextPacedPacketTime(QuicSentPacketManager* sent_packet_manager,
+                                     QuicTime time);
+
  private:
   DISALLOW_COPY_AND_ASSIGN(QuicSentPacketManagerPeer);
 };
diff --git a/net/quic/test_tools/quic_stream_peer.cc b/net/quic/test_tools/quic_stream_peer.cc
index cee9acb..e9bbc33 100644
--- a/net/quic/test_tools/quic_stream_peer.cc
+++ b/net/quic/test_tools/quic_stream_peer.cc
@@ -49,7 +49,7 @@
 
 // static
 uint32_t QuicStreamPeer::SizeOfQueuedData(QuicStream* stream) {
-  return stream->queued_data_bytes();
+  return stream->BufferedDataBytes();
 }
 
 // static
diff --git a/net/quic/test_tools/quic_test_utils.cc b/net/quic/test_tools/quic_test_utils.cc
index 9f22b2f..9e1933c9 100644
--- a/net/quic/test_tools/quic_test_utils.cc
+++ b/net/quic/test_tools/quic_test_utils.cc
@@ -33,15 +33,31 @@
 namespace net {
 namespace test {
 
-QuicAckFrame MakeAckFrame(QuicPacketNumber largest_observed) {
+QuicAckFrame InitAckFrame(const std::vector<QuicAckBlock>& ack_blocks) {
+  DCHECK_GT(ack_blocks.size(), 0u);
+
   QuicAckFrame ack;
-  ack.largest_observed = largest_observed;
+  QuicPacketNumber end_of_previous_block = 1;
+  for (const QuicAckBlock& block : ack_blocks) {
+    DCHECK_GE(block.start, end_of_previous_block);
+    DCHECK_GT(block.limit, block.start);
+    ack.packets.AddRange(block.start, block.limit);
+    end_of_previous_block = block.limit;
+  }
+
+  ack.largest_observed = ack.packets.Max();
+
   return ack;
 }
 
+QuicAckFrame InitAckFrame(QuicPacketNumber largest_acked) {
+  return InitAckFrame({{1, largest_acked + 1}});
+}
+
 QuicAckFrame MakeAckFrameWithAckBlocks(size_t num_ack_blocks,
                                        QuicPacketNumber least_unacked) {
-  QuicAckFrame ack = MakeAckFrame(2 * num_ack_blocks + least_unacked);
+  QuicAckFrame ack;
+  ack.largest_observed = 2 * num_ack_blocks + least_unacked;
   // Add enough received packets to get num_ack_blocks ack blocks.
   for (QuicPacketNumber i = 2; i < 2 * num_ack_blocks + 1; i += 2) {
     ack.packets.Add(least_unacked + i);
@@ -53,7 +69,7 @@
                                    const QuicPacketHeader& header,
                                    const QuicFrames& frames) {
   const size_t max_plaintext_size = framer->GetMaxPlaintextSize(kMaxPacketSize);
-  size_t packet_size = GetPacketHeaderSize(framer->version(), header);
+  size_t packet_size = GetPacketHeaderSize(framer->transport_version(), header);
   for (size_t i = 0; i < frames.size(); ++i) {
     DCHECK_LE(packet_size, max_plaintext_size);
     bool first_frame = i == 0;
@@ -147,7 +163,8 @@
 
 MockFramerVisitor::~MockFramerVisitor() {}
 
-bool NoOpFramerVisitor::OnProtocolVersionMismatch(QuicVersion version) {
+bool NoOpFramerVisitor::OnProtocolVersionMismatch(
+    QuicTransportVersion version) {
   return false;
 }
 
@@ -258,7 +275,7 @@
                          helper,
                          alarm_factory,
                          perspective,
-                         AllSupportedVersions()) {}
+                         AllSupportedTransportVersions()) {}
 
 MockQuicConnection::MockQuicConnection(QuicSocketAddress address,
                                        MockQuicConnectionHelper* helper,
@@ -269,7 +286,7 @@
                          helper,
                          alarm_factory,
                          perspective,
-                         AllSupportedVersions()) {}
+                         AllSupportedTransportVersions()) {}
 
 MockQuicConnection::MockQuicConnection(QuicConnectionId connection_id,
                                        MockQuicConnectionHelper* helper,
@@ -280,13 +297,13 @@
                          helper,
                          alarm_factory,
                          perspective,
-                         CurrentSupportedVersions()) {}
+                         CurrentSupportedTransportVersions()) {}
 
 MockQuicConnection::MockQuicConnection(
     MockQuicConnectionHelper* helper,
     MockAlarmFactory* alarm_factory,
     Perspective perspective,
-    const QuicVersionVector& supported_versions)
+    const QuicTransportVersionVector& supported_versions)
     : MockQuicConnection(QuicEndian::NetToHost64(kTestConnectionId),
                          QuicSocketAddress(TestPeerIPAddress(), kTestPort),
                          helper,
@@ -300,7 +317,7 @@
     MockQuicConnectionHelper* helper,
     MockAlarmFactory* alarm_factory,
     Perspective perspective,
-    const QuicVersionVector& supported_versions)
+    const QuicTransportVersionVector& supported_versions)
     : QuicConnection(connection_id,
                      address,
                      helper,
@@ -320,7 +337,8 @@
   static_cast<MockQuicConnectionHelper*>(helper())->AdvanceTime(delta);
 }
 
-bool MockQuicConnection::OnProtocolVersionMismatch(QuicVersion version) {
+bool MockQuicConnection::OnProtocolVersionMismatch(
+    QuicTransportVersion version) {
   return false;
 }
 
@@ -333,7 +351,7 @@
     MockQuicConnectionHelper* helper,
     MockAlarmFactory* alarm_factory,
     Perspective perspective,
-    const QuicVersionVector& supported_versions)
+    const QuicTransportVersionVector& supported_versions)
     : MockQuicConnection(helper,
                          alarm_factory,
                          perspective,
@@ -593,12 +611,12 @@
   return QuicIpAddress::Loopback4();
 }
 
-QuicVersion QuicVersionMax() {
-  return AllSupportedVersions().front();
+QuicTransportVersion QuicVersionMax() {
+  return AllSupportedTransportVersions().front();
 }
 
-QuicVersion QuicVersionMin() {
-  return AllSupportedVersions().back();
+QuicTransportVersion QuicVersionMin() {
+  return AllSupportedTransportVersions().back();
 }
 
 QuicEncryptedPacket* ConstructEncryptedPacket(QuicConnectionId connection_id,
@@ -632,7 +650,7 @@
     const string& data,
     QuicConnectionIdLength connection_id_length,
     QuicPacketNumberLength packet_number_length,
-    QuicVersionVector* versions) {
+    QuicTransportVersionVector* versions) {
   return ConstructEncryptedPacket(connection_id, version_flag, reset_flag,
                                   packet_number, data, connection_id_length,
                                   packet_number_length, versions,
@@ -646,7 +664,7 @@
     const string& data,
     QuicConnectionIdLength connection_id_length,
     QuicPacketNumberLength packet_number_length,
-    QuicVersionVector* versions,
+    QuicTransportVersionVector* versions,
     Perspective perspective) {
   QuicPacketHeader header;
   header.public_header.connection_id = connection_id;
@@ -660,7 +678,7 @@
   QuicFrames frames;
   frames.push_back(frame);
   QuicFramer framer(
-      versions != nullptr ? *versions : CurrentSupportedVersions(),
+      versions != nullptr ? *versions : CurrentSupportedTransportVersions(),
       QuicTime::Zero(), perspective);
 
   std::unique_ptr<QuicPacket> packet(
@@ -690,7 +708,7 @@
     const string& data,
     QuicConnectionIdLength connection_id_length,
     QuicPacketNumberLength packet_number_length,
-    QuicVersionVector* versions,
+    QuicTransportVersionVector* versions,
     Perspective perspective) {
   QuicPacketHeader header;
   header.public_header.connection_id = connection_id;
@@ -703,8 +721,9 @@
   QuicFrame frame(&stream_frame);
   QuicFrames frames;
   frames.push_back(frame);
-  QuicFramer framer(versions != nullptr ? *versions : AllSupportedVersions(),
-                    QuicTime::Zero(), perspective);
+  QuicFramer framer(
+      versions != nullptr ? *versions : AllSupportedTransportVersions(),
+      QuicTime::Zero(), perspective);
 
   std::unique_ptr<QuicPacket> packet(
       BuildUnsizedDataPacket(&framer, header, frames));
@@ -713,7 +732,7 @@
   // Now set the frame type to 0x1F, which is an invalid frame type.
   reinterpret_cast<unsigned char*>(
       packet->mutable_data())[GetStartOfEncryptedData(
-      framer.version(), connection_id_length, version_flag,
+      framer.transport_version(), connection_id_length, version_flag,
       false /* no diversification nonce */, packet_number_length)] = 0x1F;
 
   char* buffer = new char[kMaxPacketSize];
@@ -754,7 +773,7 @@
                 << HexDumpWithMarks(actual, actual_len, marks.get(), max_len);
 }
 
-size_t GetPacketLengthForOneStream(QuicVersion version,
+size_t GetPacketLengthForOneStream(QuicTransportVersion version,
                                    bool include_version,
                                    bool include_diversification_nonce,
                                    QuicConnectionIdLength connection_id_length,
@@ -800,8 +819,9 @@
   return config;
 }
 
-QuicVersionVector SupportedVersions(QuicVersion version) {
-  QuicVersionVector versions;
+QuicTransportVersionVector SupportedTransportVersions(
+    QuicTransportVersion version) {
+  QuicTransportVersionVector versions;
   versions.push_back(version);
   return versions;
 }
@@ -825,7 +845,7 @@
 void CreateClientSessionForTest(QuicServerId server_id,
                                 bool supports_stateless_rejects,
                                 QuicTime::Delta connection_start_time,
-                                QuicVersionVector supported_versions,
+                                QuicTransportVersionVector supported_versions,
                                 MockQuicConnectionHelper* helper,
                                 MockAlarmFactory* alarm_factory,
                                 QuicCryptoClientConfig* crypto_client_config,
@@ -851,7 +871,7 @@
 void CreateServerSessionForTest(
     QuicServerId server_id,
     QuicTime::Delta connection_start_time,
-    QuicVersionVector supported_versions,
+    QuicTransportVersionVector supported_versions,
     MockQuicConnectionHelper* helper,
     MockAlarmFactory* alarm_factory,
     QuicCryptoServerConfig* server_crypto_config,
@@ -876,17 +896,19 @@
   (*server_connection)->AdvanceTime(connection_start_time);
 }
 
-QuicStreamId NextStreamId(QuicVersion version) {
+QuicStreamId NextStreamId(QuicTransportVersion version) {
   // TODO(ckrasic) - when version for http stream pairs re-lands, this
   // will be conditional.
   return 2;
 }
 
-QuicStreamId GetNthClientInitiatedStreamId(QuicVersion version, int n) {
+QuicStreamId GetNthClientInitiatedStreamId(QuicTransportVersion version,
+                                           int n) {
   return 5 + NextStreamId(version) * n;
 }
 
-QuicStreamId GetNthServerInitiatedStreamId(QuicVersion version, int n) {
+QuicStreamId GetNthServerInitiatedStreamId(QuicTransportVersion version,
+                                           int n) {
   return 2 + NextStreamId(version) * n;
 }
 
diff --git a/net/quic/test_tools/quic_test_utils.h b/net/quic/test_tools/quic_test_utils.h
index ec3aa67..9a1f864 100644
--- a/net/quic/test_tools/quic_test_utils.h
+++ b/net/quic/test_tools/quic_test_utils.h
@@ -54,13 +54,13 @@
 QuicIpAddress TestPeerIPAddress();
 
 // Upper limit on versions we support.
-QuicVersion QuicVersionMax();
+QuicTransportVersion QuicVersionMax();
 
 // Lower limit on versions we support.
-QuicVersion QuicVersionMin();
+QuicTransportVersion QuicVersionMin();
 
 // Create an encrypted packet for testing.
-// If versions == nullptr, uses &AllSupportedVersions().
+// If versions == nullptr, uses &AllSupportedTransportVersions().
 // Note that the packet is encrypted with NullEncrypter, so to decrypt the
 // constructed packet, the framer must be set to use NullDecrypter.
 QuicEncryptedPacket* ConstructEncryptedPacket(
@@ -71,11 +71,11 @@
     const std::string& data,
     QuicConnectionIdLength connection_id_length,
     QuicPacketNumberLength packet_number_length,
-    QuicVersionVector* versions,
+    QuicTransportVersionVector* versions,
     Perspective perspective);
 
 // Create an encrypted packet for testing.
-// If versions == nullptr, uses &AllSupportedVersions().
+// If versions == nullptr, uses &AllSupportedTransportVersions().
 // Note that the packet is encrypted with NullEncrypter, so to decrypt the
 // constructed packet, the framer must be set to use NullDecrypter.
 QuicEncryptedPacket* ConstructEncryptedPacket(
@@ -86,7 +86,7 @@
     const std::string& data,
     QuicConnectionIdLength connection_id_length,
     QuicPacketNumberLength packet_number_length,
-    QuicVersionVector* versions);
+    QuicTransportVersionVector* versions);
 
 // This form assumes |versions| == nullptr.
 QuicEncryptedPacket* ConstructEncryptedPacket(
@@ -126,7 +126,7 @@
     const std::string& data,
     QuicConnectionIdLength connection_id_length,
     QuicPacketNumberLength packet_number_length,
-    QuicVersionVector* versions,
+    QuicTransportVersionVector* versions,
     Perspective perspective);
 
 void CompareCharArraysWithHexError(const std::string& description,
@@ -138,7 +138,7 @@
 // Returns the length of a QuicPacket that is capable of holding either a
 // stream frame or a minimal ack frame.  Sets |*payload_length| to the number
 // of bytes of stream data that will fit in such a packet.
-size_t GetPacketLengthForOneStream(QuicVersion version,
+size_t GetPacketLengthForOneStream(QuicTransportVersion version,
                                    bool include_version,
                                    bool include_diversification_nonce,
                                    QuicConnectionIdLength connection_id_length,
@@ -152,11 +152,27 @@
 QuicConfig DefaultQuicConfigStatelessRejects();
 
 // Returns a version vector consisting of |version|.
-QuicVersionVector SupportedVersions(QuicVersion version);
+QuicTransportVersionVector SupportedTransportVersions(
+    QuicTransportVersion version);
 
-// Testing convenience method to construct a QuicAckFrame with largest_observed
-// from peer set to |largest_observed|.
-QuicAckFrame MakeAckFrame(QuicPacketNumber largest_observed);
+struct QuicAckBlock {
+  QuicPacketNumber start;  // Included
+  QuicPacketNumber limit;  // Excluded
+};
+
+// Testing convenience method to construct a QuicAckFrame with arbitrary ack
+// blocks. Each block is given by a (closed-open) range of packet numbers. e.g.:
+// InitAckFrame({{1, 10}})
+//   => 1 ack block acking packet numbers 1 to 9.
+//
+// InitAckFrame({{1, 2}, {3, 4}})
+//   => 2 ack blocks acking packet 1 and 3. Packet 2 is missing.
+QuicAckFrame InitAckFrame(const std::vector<QuicAckBlock>& ack_blocks);
+
+// Testing convenience method to construct a QuicAckFrame with 1 ack block which
+// covers packet number range [1, |largest_acked| + 1).
+// Equivalent to InitAckFrame({{1, largest_acked + 1}})
+QuicAckFrame InitAckFrame(QuicPacketNumber largest_acked);
 
 // Testing convenience method to construct a QuicAckFrame with |num_ack_blocks|
 // ack blocks of width 1 packet, starting from |least_unacked| + 2.
@@ -208,7 +224,7 @@
 
   MOCK_METHOD1(OnError, void(QuicFramer* framer));
   // The constructor sets this up to return false by default.
-  MOCK_METHOD1(OnProtocolVersionMismatch, bool(QuicVersion version));
+  MOCK_METHOD1(OnProtocolVersionMismatch, bool(QuicTransportVersion version));
   MOCK_METHOD0(OnPacket, void());
   MOCK_METHOD1(OnPublicResetPacket, void(const QuicPublicResetPacket& header));
   MOCK_METHOD1(OnVersionNegotiationPacket,
@@ -246,7 +262,7 @@
   void OnPublicResetPacket(const QuicPublicResetPacket& packet) override {}
   void OnVersionNegotiationPacket(
       const QuicVersionNegotiationPacket& packet) override {}
-  bool OnProtocolVersionMismatch(QuicVersion version) override;
+  bool OnProtocolVersionMismatch(QuicTransportVersion version) override;
   bool OnUnauthenticatedHeader(const QuicPacketHeader& header) override;
   bool OnUnauthenticatedPublicHeader(
       const QuicPacketPublicHeader& header) override;
@@ -291,7 +307,7 @@
   MOCK_CONST_METHOD0(HasPendingHandshake, bool());
   MOCK_CONST_METHOD0(HasOpenDynamicStreams, bool());
   MOCK_METHOD1(OnSuccessfulVersionNegotiation,
-               void(const QuicVersion& version));
+               void(const QuicTransportVersion& version));
   MOCK_METHOD0(OnConfigNegotiated, void());
   MOCK_METHOD0(PostProcessAfterData, void());
   MOCK_METHOD0(OnAckNeedsRetransmittableFrame, void());
@@ -365,14 +381,14 @@
   MockQuicConnection(MockQuicConnectionHelper* helper,
                      MockAlarmFactory* alarm_factory,
                      Perspective perspective,
-                     const QuicVersionVector& supported_versions);
+                     const QuicTransportVersionVector& supported_versions);
 
   MockQuicConnection(QuicConnectionId connection_id,
                      QuicSocketAddress address,
                      MockQuicConnectionHelper* helper,
                      MockAlarmFactory* alarm_factory,
                      Perspective perspective,
-                     const QuicVersionVector& supported_versions);
+                     const QuicTransportVersionVector& supported_versions);
 
   ~MockQuicConnection() override;
 
@@ -423,7 +439,7 @@
     QuicConnection::ProcessUdpPacket(self_address, peer_address, packet);
   }
 
-  bool OnProtocolVersionMismatch(QuicVersion version) override;
+  bool OnProtocolVersionMismatch(QuicTransportVersion version) override;
 
   void ReallySendGoAway(QuicErrorCode error,
                         QuicStreamId last_good_stream_id,
@@ -444,7 +460,7 @@
   PacketSavingConnection(MockQuicConnectionHelper* helper,
                          MockAlarmFactory* alarm_factory,
                          Perspective perspective,
-                         const QuicVersionVector& supported_versions);
+                         const QuicTransportVersionVector& supported_versions);
 
   ~PacketSavingConnection() override;
 
@@ -736,7 +752,7 @@
                     QuicByteCount bytes_in_flight,
                     QuicTime event_time,
                     const AckedPacketVector& acked_packets,
-                    const CongestionVector& lost_packets));
+                    const LostPacketVector& lost_packets));
   MOCK_METHOD5(OnPacketSent,
                void(QuicTime,
                     QuicByteCount,
@@ -746,8 +762,7 @@
   MOCK_METHOD1(OnRetransmissionTimeout, void(bool));
   MOCK_METHOD0(OnConnectionMigration, void());
   MOCK_METHOD0(RevertRetransmissionTimeout, void());
-  MOCK_METHOD2(TimeUntilSend,
-               QuicTime::Delta(QuicTime now, QuicByteCount bytes_in_flight));
+  MOCK_METHOD1(CanSend, bool(QuicByteCount));
   MOCK_CONST_METHOD1(PacingRate, QuicBandwidth(QuicByteCount));
   MOCK_CONST_METHOD0(BandwidthEstimate, QuicBandwidth(void));
   MOCK_CONST_METHOD0(HasReliableBandwidthEstimate, bool());
@@ -777,7 +792,7 @@
                     QuicTime time,
                     const RttStats& rtt_stats,
                     QuicPacketNumber largest_recently_acked,
-                    SendAlgorithmInterface::CongestionVector* packets_lost));
+                    LostPacketVector* packets_lost));
   MOCK_CONST_METHOD0(GetLossTimeout, QuicTime());
   MOCK_METHOD4(SpuriousRetransmitDetected,
                void(const QuicUnackedPacketMap&,
@@ -842,11 +857,12 @@
 
   MOCK_METHOD1(OnIncorrectConnectionId, void(QuicConnectionId));
 
-  MOCK_METHOD1(OnProtocolVersionMismatch, void(QuicVersion));
+  MOCK_METHOD1(OnProtocolVersionMismatch, void(QuicTransportVersion));
 
   MOCK_METHOD1(OnPacketHeader, void(const QuicPacketHeader& header));
 
-  MOCK_METHOD1(OnSuccessfulVersionNegotiation, void(const QuicVersion&));
+  MOCK_METHOD1(OnSuccessfulVersionNegotiation,
+               void(const QuicTransportVersion&));
 
   MOCK_METHOD1(OnStreamFrame, void(const QuicStreamFrame&));
 
@@ -925,7 +941,7 @@
 void CreateClientSessionForTest(QuicServerId server_id,
                                 bool supports_stateless_rejects,
                                 QuicTime::Delta connection_start_time,
-                                QuicVersionVector supported_versions,
+                                QuicTransportVersionVector supported_versions,
                                 MockQuicConnectionHelper* helper,
                                 MockAlarmFactory* alarm_factory,
                                 QuicCryptoClientConfig* crypto_client_config,
@@ -950,7 +966,7 @@
 void CreateServerSessionForTest(
     QuicServerId server_id,
     QuicTime::Delta connection_start_time,
-    QuicVersionVector supported_versions,
+    QuicTransportVersionVector supported_versions,
     MockQuicConnectionHelper* helper,
     MockAlarmFactory* alarm_factory,
     QuicCryptoServerConfig* crypto_server_config,
@@ -1000,9 +1016,9 @@
 
 // Utilities that will adapt stream ids when http stream pairs are
 // enabled.
-QuicStreamId NextStreamId(QuicVersion version);
-QuicStreamId GetNthClientInitiatedStreamId(QuicVersion version, int n);
-QuicStreamId GetNthServerInitiatedStreamId(QuicVersion version, int n);
+QuicStreamId NextStreamId(QuicTransportVersion version);
+QuicStreamId GetNthClientInitiatedStreamId(QuicTransportVersion version, int n);
+QuicStreamId GetNthServerInitiatedStreamId(QuicTransportVersion version, int n);
 
 }  // namespace test
 }  // namespace net
diff --git a/net/quic/test_tools/quic_time_wait_list_manager_peer.cc b/net/quic/test_tools/quic_time_wait_list_manager_peer.cc
index 630f64e6..ba47d8b 100644
--- a/net/quic/test_tools/quic_time_wait_list_manager_peer.cc
+++ b/net/quic/test_tools/quic_time_wait_list_manager_peer.cc
@@ -18,7 +18,8 @@
   return manager->time_wait_period_;
 }
 
-QuicVersion QuicTimeWaitListManagerPeer::GetQuicVersionFromConnectionId(
+QuicTransportVersion
+QuicTimeWaitListManagerPeer::GetQuicVersionFromConnectionId(
     QuicTimeWaitListManager* manager,
     QuicConnectionId connection_id) {
   return manager->GetQuicVersionFromConnectionId(connection_id);
diff --git a/net/quic/test_tools/quic_time_wait_list_manager_peer.h b/net/quic/test_tools/quic_time_wait_list_manager_peer.h
index c2635962..bb7d4c7 100644
--- a/net/quic/test_tools/quic_time_wait_list_manager_peer.h
+++ b/net/quic/test_tools/quic_time_wait_list_manager_peer.h
@@ -17,7 +17,7 @@
 
   static QuicTime::Delta time_wait_period(QuicTimeWaitListManager* manager);
 
-  static QuicVersion GetQuicVersionFromConnectionId(
+  static QuicTransportVersion GetQuicVersionFromConnectionId(
       QuicTimeWaitListManager* manager,
       QuicConnectionId connection_id);
 
diff --git a/net/quic/test_tools/simple_quic_framer.cc b/net/quic/test_tools/simple_quic_framer.cc
index f216b8c8..2ae486b 100644
--- a/net/quic/test_tools/simple_quic_framer.cc
+++ b/net/quic/test_tools/simple_quic_framer.cc
@@ -25,7 +25,9 @@
 
   void OnError(QuicFramer* framer) override { error_ = framer->error(); }
 
-  bool OnProtocolVersionMismatch(QuicVersion version) override { return false; }
+  bool OnProtocolVersionMismatch(QuicTransportVersion version) override {
+    return false;
+  }
 
   void OnPacket() override {}
   void OnPublicResetPacket(const QuicPublicResetPacket& packet) override {
@@ -158,15 +160,17 @@
 };
 
 SimpleQuicFramer::SimpleQuicFramer()
-    : framer_(AllSupportedVersions(),
+    : framer_(AllSupportedTransportVersions(),
               QuicTime::Zero(),
               Perspective::IS_SERVER) {}
 
-SimpleQuicFramer::SimpleQuicFramer(const QuicVersionVector& supported_versions)
+SimpleQuicFramer::SimpleQuicFramer(
+    const QuicTransportVersionVector& supported_versions)
     : framer_(supported_versions, QuicTime::Zero(), Perspective::IS_SERVER) {}
 
-SimpleQuicFramer::SimpleQuicFramer(const QuicVersionVector& supported_versions,
-                                   Perspective perspective)
+SimpleQuicFramer::SimpleQuicFramer(
+    const QuicTransportVersionVector& supported_versions,
+    Perspective perspective)
     : framer_(supported_versions, QuicTime::Zero(), perspective) {}
 
 SimpleQuicFramer::~SimpleQuicFramer() {}
diff --git a/net/quic/test_tools/simple_quic_framer.h b/net/quic/test_tools/simple_quic_framer.h
index 9e87523..5e0ebb0 100644
--- a/net/quic/test_tools/simple_quic_framer.h
+++ b/net/quic/test_tools/simple_quic_framer.h
@@ -24,8 +24,9 @@
 class SimpleQuicFramer {
  public:
   SimpleQuicFramer();
-  explicit SimpleQuicFramer(const QuicVersionVector& supported_versions);
-  SimpleQuicFramer(const QuicVersionVector& supported_versions,
+  explicit SimpleQuicFramer(
+      const QuicTransportVersionVector& supported_versions);
+  SimpleQuicFramer(const QuicTransportVersionVector& supported_versions,
                    Perspective perspective);
   ~SimpleQuicFramer();
 
@@ -47,8 +48,9 @@
 
   QuicFramer* framer();
 
-  void SetSupportedVersions(const QuicVersionVector& versions) {
-    framer_.SetSupportedVersions(versions);
+  void SetSupportedTransportVersions(
+      const QuicTransportVersionVector& versions) {
+    framer_.SetSupportedTransportVersions(versions);
   }
 
  private:
diff --git a/net/quic/test_tools/simulator/quic_endpoint.cc b/net/quic/test_tools/simulator/quic_endpoint.cc
index 6e810d43..683f6ab 100644
--- a/net/quic/test_tools/simulator/quic_endpoint.cc
+++ b/net/quic/test_tools/simulator/quic_endpoint.cc
@@ -72,7 +72,7 @@
                   &writer_,
                   false,
                   perspective,
-                  CurrentSupportedVersions()),
+                  CurrentSupportedTransportVersions()),
       bytes_to_transfer_(0),
       bytes_transferred_(0),
       write_blocked_count_(0),
diff --git a/net/quic/test_tools/simulator/quic_endpoint.h b/net/quic/test_tools/simulator/quic_endpoint.h
index faf2459..c4dd7d7 100644
--- a/net/quic/test_tools/simulator/quic_endpoint.h
+++ b/net/quic/test_tools/simulator/quic_endpoint.h
@@ -85,7 +85,8 @@
                           const std::string& error_details,
                           ConnectionCloseSource source) override {}
   void OnWriteBlocked() override {}
-  void OnSuccessfulVersionNegotiation(const QuicVersion& version) override {}
+  void OnSuccessfulVersionNegotiation(
+      const QuicTransportVersion& version) override {}
   void OnCongestionWindowChange(QuicTime now) override {}
   void OnConnectionMigration(PeerAddressChangeType type) override {}
   void OnPathDegrading() override {}
diff --git a/net/quic/test_tools/simulator/quic_endpoint_test.cc b/net/quic/test_tools/simulator/quic_endpoint_test.cc
index d739bfb..2d8c87e 100644
--- a/net/quic/test_tools/simulator/quic_endpoint_test.cc
+++ b/net/quic/test_tools/simulator/quic_endpoint_test.cc
@@ -96,8 +96,7 @@
 
   // Will be owned by the sent packet manager.
   auto* sender = new NiceMock<test::MockSendAlgorithm>();
-  EXPECT_CALL(*sender, TimeUntilSend(_, _))
-      .WillRepeatedly(Return(QuicTime::Delta::Zero()));
+  EXPECT_CALL(*sender, CanSend(_)).WillRepeatedly(Return(true));
   EXPECT_CALL(*sender, PacingRate(_))
       .WillRepeatedly(Return(10 * kDefaultBandwidth));
   EXPECT_CALL(*sender, BandwidthEstimate())
diff --git a/net/spdy/chromium/spdy_session.cc b/net/spdy/chromium/spdy_session.cc
index 0018b9b..f764faf 100644
--- a/net/spdy/chromium/spdy_session.cc
+++ b/net/spdy/chromium/spdy_session.cc
@@ -717,18 +717,19 @@
   return true;
 }
 
-SpdySession::SpdySession(const SpdySessionKey& spdy_session_key,
-                         HttpServerProperties* http_server_properties,
-                         TransportSecurityState* transport_security_state,
-                         const QuicVersionVector& quic_supported_versions,
-                         bool enable_sending_initial_data,
-                         bool enable_ping_based_connection_checking,
-                         size_t session_max_recv_window_size,
-                         const SettingsMap& initial_settings,
-                         TimeFunc time_func,
-                         ServerPushDelegate* push_delegate,
-                         ProxyDelegate* proxy_delegate,
-                         NetLog* net_log)
+SpdySession::SpdySession(
+    const SpdySessionKey& spdy_session_key,
+    HttpServerProperties* http_server_properties,
+    TransportSecurityState* transport_security_state,
+    const QuicTransportVersionVector& quic_supported_versions,
+    bool enable_sending_initial_data,
+    bool enable_ping_based_connection_checking,
+    size_t session_max_recv_window_size,
+    const SettingsMap& initial_settings,
+    TimeFunc time_func,
+    ServerPushDelegate* push_delegate,
+    ProxyDelegate* proxy_delegate,
+    NetLog* net_log)
     : in_io_loop_(false),
       spdy_session_key_(spdy_session_key),
       pool_(NULL),
@@ -2985,10 +2986,10 @@
     // HttpStreamFactory::ProcessAlternativeServices
     // could use the the same function.
     // Check if QUIC version is supported. Filter supported QUIC versions.
-    QuicVersionVector advertised_versions;
+    QuicTransportVersionVector advertised_versions;
     if (protocol == kProtoQUIC && !altsvc.version.empty()) {
       bool match_found = false;
-      for (const QuicVersion& supported : quic_supported_versions_) {
+      for (const QuicTransportVersion& supported : quic_supported_versions_) {
         for (const uint16_t& advertised : altsvc.version) {
           if (supported == advertised) {
             match_found = true;
diff --git a/net/spdy/chromium/spdy_session.h b/net/spdy/chromium/spdy_session.h
index 48f89b4..fb7063b 100644
--- a/net/spdy/chromium/spdy_session.h
+++ b/net/spdy/chromium/spdy_session.h
@@ -305,7 +305,7 @@
   SpdySession(const SpdySessionKey& spdy_session_key,
               HttpServerProperties* http_server_properties,
               TransportSecurityState* transport_security_state,
-              const QuicVersionVector& quic_supported_versions,
+              const QuicTransportVersionVector& quic_supported_versions,
               bool enable_sending_initial_data,
               bool enable_ping_based_connection_checking,
               size_t session_max_recv_window_size,
@@ -1158,7 +1158,7 @@
   NetLogWithSource net_log_;
 
   // Versions of QUIC which may be used.
-  const QuicVersionVector quic_supported_versions_;
+  const QuicTransportVersionVector quic_supported_versions_;
 
   // Outside of tests, these should always be true.
   bool enable_sending_initial_data_;
diff --git a/net/spdy/chromium/spdy_session_pool.cc b/net/spdy/chromium/spdy_session_pool.cc
index 50dc011e..b20e97a 100644
--- a/net/spdy/chromium/spdy_session_pool.cc
+++ b/net/spdy/chromium/spdy_session_pool.cc
@@ -49,7 +49,7 @@
     SSLConfigService* ssl_config_service,
     HttpServerProperties* http_server_properties,
     TransportSecurityState* transport_security_state,
-    const QuicVersionVector& quic_supported_versions,
+    const QuicTransportVersionVector& quic_supported_versions,
     bool enable_ping_based_connection_checking,
     size_t session_max_recv_window_size,
     const SettingsMap& initial_settings,
diff --git a/net/spdy/chromium/spdy_session_pool.h b/net/spdy/chromium/spdy_session_pool.h
index 56e78fa..251a0245 100644
--- a/net/spdy/chromium/spdy_session_pool.h
+++ b/net/spdy/chromium/spdy_session_pool.h
@@ -60,7 +60,7 @@
                   SSLConfigService* ssl_config_service,
                   HttpServerProperties* http_server_properties,
                   TransportSecurityState* transport_security_state,
-                  const QuicVersionVector& quic_supported_versions,
+                  const QuicTransportVersionVector& quic_supported_versions,
                   bool enable_ping_based_connection_checking,
                   size_t session_max_recv_window_size,
                   const SettingsMap& initial_settings,
@@ -255,7 +255,7 @@
   HostResolver* const resolver_;
 
   // Versions of QUIC which may be used.
-  const QuicVersionVector quic_supported_versions_;
+  const QuicTransportVersionVector quic_supported_versions_;
 
   // Defaults to true. May be controlled via SpdySessionPoolPeer for tests.
   bool enable_sending_initial_data_;
diff --git a/net/tools/quic/chlo_extractor.cc b/net/tools/quic/chlo_extractor.cc
index 28e08162..60429ef 100644
--- a/net/tools/quic/chlo_extractor.cc
+++ b/net/tools/quic/chlo_extractor.cc
@@ -26,7 +26,7 @@
 
   // QuicFramerVisitorInterface implementation
   void OnError(QuicFramer* framer) override {}
-  bool OnProtocolVersionMismatch(QuicVersion version) override;
+  bool OnProtocolVersionMismatch(QuicTransportVersion version) override;
   void OnPacket() override {}
   void OnPublicResetPacket(const QuicPublicResetPacket& packet) override {}
   void OnVersionNegotiationPacket(
@@ -68,7 +68,8 @@
       found_chlo_(false),
       connection_id_(0) {}
 
-bool ChloFramerVisitor::OnProtocolVersionMismatch(QuicVersion version) {
+bool ChloFramerVisitor::OnProtocolVersionMismatch(
+    QuicTransportVersion version) {
   if (!framer_->IsSupportedVersion(version)) {
     return false;
   }
@@ -144,7 +145,7 @@
 void ChloFramerVisitor::OnHandshakeMessage(
     const CryptoHandshakeMessage& message) {
   if (delegate_ != nullptr) {
-    delegate_->OnChlo(framer_->version(), connection_id_, message);
+    delegate_->OnChlo(framer_->transport_version(), connection_id_, message);
   }
   found_chlo_ = true;
 }
@@ -153,7 +154,7 @@
 
 // static
 bool ChloExtractor::Extract(const QuicEncryptedPacket& packet,
-                            const QuicVersionVector& versions,
+                            const QuicTransportVersionVector& versions,
                             Delegate* delegate) {
   QuicFramer framer(versions, QuicTime::Zero(), Perspective::IS_SERVER);
   ChloFramerVisitor visitor(&framer, delegate);
diff --git a/net/tools/quic/chlo_extractor.h b/net/tools/quic/chlo_extractor.h
index 176ad047..6ad12c5 100644
--- a/net/tools/quic/chlo_extractor.h
+++ b/net/tools/quic/chlo_extractor.h
@@ -19,7 +19,7 @@
     virtual ~Delegate() {}
 
     // Called when a CHLO message is found in the packets.
-    virtual void OnChlo(QuicVersion version,
+    virtual void OnChlo(QuicTransportVersion version,
                         QuicConnectionId connection_id,
                         const CryptoHandshakeMessage& chlo) = 0;
   };
@@ -28,7 +28,7 @@
   // of |delegate|. Return true if a CHLO message was found, and false
   // otherwise.
   static bool Extract(const QuicEncryptedPacket& packet,
-                      const QuicVersionVector& versions,
+                      const QuicTransportVersionVector& versions,
                       Delegate* delegate);
 
   ChloExtractor(const ChloExtractor&) = delete;
diff --git a/net/tools/quic/chlo_extractor_test.cc b/net/tools/quic/chlo_extractor_test.cc
index cd62225..e0470810 100644
--- a/net/tools/quic/chlo_extractor_test.cc
+++ b/net/tools/quic/chlo_extractor_test.cc
@@ -22,7 +22,7 @@
   ~TestDelegate() override {}
 
   // ChloExtractor::Delegate implementation
-  void OnChlo(QuicVersion version,
+  void OnChlo(QuicTransportVersion version,
               QuicConnectionId connection_id,
               const CryptoHandshakeMessage& chlo) override {
     version_ = version;
@@ -31,12 +31,12 @@
   }
 
   QuicConnectionId connection_id() const { return connection_id_; }
-  QuicVersion version() const { return version_; }
+  QuicTransportVersion transport_version() const { return version_; }
   const string& chlo() const { return chlo_; }
 
  private:
   QuicConnectionId connection_id_;
-  QuicVersion version_;
+  QuicTransportVersion version_;
   string chlo_;
 };
 
@@ -47,7 +47,7 @@
     header_.public_header.connection_id_length = PACKET_8BYTE_CONNECTION_ID;
     header_.public_header.version_flag = true;
     header_.public_header.versions =
-        SupportedVersions(AllSupportedVersions().front());
+        SupportedTransportVersions(AllSupportedTransportVersions().front());
     header_.public_header.reset_flag = false;
     header_.public_header.packet_number_length = PACKET_6BYTE_PACKET_NUMBER;
     header_.packet_number = 1;
@@ -57,8 +57,9 @@
     QuicFrame frame(stream_frame);
     QuicFrames frames;
     frames.push_back(frame);
-    QuicFramer framer(SupportedVersions(header_.public_header.versions.front()),
-                      QuicTime::Zero(), Perspective::IS_CLIENT);
+    QuicFramer framer(
+        SupportedTransportVersions(header_.public_header.versions.front()),
+        QuicTime::Zero(), Perspective::IS_CLIENT);
     std::unique_ptr<QuicPacket> packet(
         BuildUnsizedDataPacket(&framer, header_, frames));
     EXPECT_TRUE(packet != nullptr);
@@ -86,14 +87,14 @@
                               .AsStringPiece()
                               .as_string());
   // Construct a CHLO with each supported version
-  for (QuicVersion version : AllSupportedVersions()) {
-    QuicVersionVector versions(SupportedVersions(version));
+  for (QuicTransportVersion version : AllSupportedTransportVersions()) {
+    QuicTransportVersionVector versions(SupportedTransportVersions(version));
     header_.public_header.versions = versions;
     MakePacket(
         new QuicStreamFrame(kCryptoStreamId, false, 0, client_hello_str));
     EXPECT_TRUE(ChloExtractor::Extract(*packet_, versions, &delegate_))
         << QuicVersionToString(version);
-    EXPECT_EQ(version, delegate_.version());
+    EXPECT_EQ(version, delegate_.transport_version());
     EXPECT_EQ(header_.public_header.connection_id, delegate_.connection_id());
     EXPECT_EQ(client_hello.DebugString(Perspective::IS_SERVER),
               delegate_.chlo())
@@ -110,8 +111,8 @@
                               .as_string());
   MakePacket(
       new QuicStreamFrame(kCryptoStreamId + 1, false, 0, client_hello_str));
-  EXPECT_FALSE(
-      ChloExtractor::Extract(*packet_, AllSupportedVersions(), &delegate_));
+  EXPECT_FALSE(ChloExtractor::Extract(*packet_, AllSupportedTransportVersions(),
+                                      &delegate_));
 }
 
 TEST_F(ChloExtractorTest, DoesNotFindValidChloOnWrongOffset) {
@@ -122,14 +123,14 @@
                               .AsStringPiece()
                               .as_string());
   MakePacket(new QuicStreamFrame(kCryptoStreamId, false, 1, client_hello_str));
-  EXPECT_FALSE(
-      ChloExtractor::Extract(*packet_, AllSupportedVersions(), &delegate_));
+  EXPECT_FALSE(ChloExtractor::Extract(*packet_, AllSupportedTransportVersions(),
+                                      &delegate_));
 }
 
 TEST_F(ChloExtractorTest, DoesNotFindInvalidChlo) {
   MakePacket(new QuicStreamFrame(kCryptoStreamId, false, 0, "foo"));
-  EXPECT_FALSE(
-      ChloExtractor::Extract(*packet_, AllSupportedVersions(), &delegate_));
+  EXPECT_FALSE(ChloExtractor::Extract(*packet_, AllSupportedTransportVersions(),
+                                      &delegate_));
 }
 
 }  // namespace
diff --git a/net/tools/quic/end_to_end_test.cc b/net/tools/quic/end_to_end_test.cc
index cbf6964..d199c9ea1 100644
--- a/net/tools/quic/end_to_end_test.cc
+++ b/net/tools/quic/end_to_end_test.cc
@@ -80,9 +80,9 @@
 
 // Run all tests with the cross products of all versions.
 struct TestParams {
-  TestParams(const QuicVersionVector& client_supported_versions,
-             const QuicVersionVector& server_supported_versions,
-             QuicVersion negotiated_version,
+  TestParams(const QuicTransportVersionVector& client_supported_versions,
+             const QuicTransportVersionVector& server_supported_versions,
+             QuicTransportVersion negotiated_version,
              bool client_supports_stateless_rejects,
              bool server_uses_stateless_rejects_if_peer_supported,
              QuicTag congestion_control_tag,
@@ -100,9 +100,9 @@
 
   friend std::ostream& operator<<(std::ostream& os, const TestParams& p) {
     os << "{ server_supported_versions: "
-       << QuicVersionVectorToString(p.server_supported_versions);
+       << QuicTransportVersionVectorToString(p.server_supported_versions);
     os << " client_supported_versions: "
-       << QuicVersionVectorToString(p.client_supported_versions);
+       << QuicTransportVersionVectorToString(p.client_supported_versions);
     os << " negotiated_version: " << QuicVersionToString(p.negotiated_version);
     os << " client_supports_stateless_rejects: "
        << p.client_supports_stateless_rejects;
@@ -116,9 +116,9 @@
     return os;
   }
 
-  QuicVersionVector client_supported_versions;
-  QuicVersionVector server_supported_versions;
-  QuicVersion negotiated_version;
+  QuicTransportVersionVector client_supported_versions;
+  QuicTransportVersionVector server_supported_versions;
+  QuicTransportVersion negotiated_version;
   bool client_supports_stateless_rejects;
   bool server_uses_stateless_rejects_if_peer_supported;
   QuicTag congestion_control_tag;
@@ -136,12 +136,13 @@
   // these tests need to ensure that clients are never attempting
   // to do 0-RTT across incompatible versions. Chromium only supports
   // a single version at a time anyway. :)
-  QuicVersionVector all_supported_versions = AllSupportedVersions();
+  QuicTransportVersionVector all_supported_versions =
+      AllSupportedTransportVersions();
   // Even though this currently has one element, it may well get another
   // with future versions of QUIC, so don't remove it.
-  QuicVersionVector version_buckets[1];
+  QuicTransportVersionVector version_buckets[1];
 
-  for (const QuicVersion version : all_supported_versions) {
+  for (const QuicTransportVersion version : all_supported_versions) {
     // Versions: 35+
     // QUIC_VERSION_35 allows endpoints to independently set stream limit.
     version_buckets[0].push_back(version);
@@ -185,9 +186,10 @@
               continue;
             }
 
-            for (const QuicVersionVector& client_versions : version_buckets) {
+            for (const QuicTransportVersionVector& client_versions :
+                 version_buckets) {
               CHECK(!client_versions.empty());
-              if (FilterSupportedVersions(client_versions).empty()) {
+              if (FilterSupportedTransportVersions(client_versions).empty()) {
                 continue;
               }
               // Add an entry for server and client supporting all
@@ -212,9 +214,9 @@
               // occur.  Skip the i = 0 case because it is essentially the
               // same as the default case.
               for (size_t i = 1; i < client_versions.size(); ++i) {
-                QuicVersionVector server_supported_versions;
+                QuicTransportVersionVector server_supported_versions;
                 server_supported_versions.push_back(client_versions[i]);
-                if (FilterSupportedVersions(server_supported_versions)
+                if (FilterSupportedTransportVersions(server_supported_versions)
                         .empty()) {
                   continue;
                 }
@@ -585,10 +587,10 @@
   bool server_started_;
   QuicConfig client_config_;
   QuicConfig server_config_;
-  QuicVersionVector client_supported_versions_;
-  QuicVersionVector server_supported_versions_;
+  QuicTransportVersionVector client_supported_versions_;
+  QuicTransportVersionVector server_supported_versions_;
   QuicTagVector client_extra_copts_;
-  QuicVersion negotiated_version_;
+  QuicTransportVersion negotiated_version_;
   size_t chlo_multiplier_;
   QuicTestServer::StreamFactory* stream_factory_;
   bool support_server_push_;
@@ -2407,11 +2409,12 @@
 
 class MockableQuicClientThatDropsBody : public MockableQuicClient {
  public:
-  MockableQuicClientThatDropsBody(QuicSocketAddress server_address,
-                                  const QuicServerId& server_id,
-                                  const QuicConfig& config,
-                                  const QuicVersionVector& supported_versions,
-                                  EpollServer* epoll_server)
+  MockableQuicClientThatDropsBody(
+      QuicSocketAddress server_address,
+      const QuicServerId& server_id,
+      const QuicConfig& config,
+      const QuicTransportVersionVector& supported_versions,
+      EpollServer* epoll_server)
       : MockableQuicClient(server_address,
                            server_id,
                            config,
@@ -2429,10 +2432,11 @@
 
 class QuicTestClientThatDropsBody : public QuicTestClient {
  public:
-  QuicTestClientThatDropsBody(QuicSocketAddress server_address,
-                              const string& server_hostname,
-                              const QuicConfig& config,
-                              const QuicVersionVector& supported_versions)
+  QuicTestClientThatDropsBody(
+      QuicSocketAddress server_address,
+      const string& server_hostname,
+      const QuicConfig& config,
+      const QuicTransportVersionVector& supported_versions)
       : QuicTestClient(server_address,
                        server_hostname,
                        config,
@@ -2951,7 +2955,7 @@
   QuicConnection* client_connection =
       client_->client()->client_session()->connection();
   client_connection->set_debug_visitor(&observer);
-  QuicVersion version = client_connection->version();
+  QuicTransportVersion version = client_connection->transport_version();
   // 100KB body.
   string body(100 * 1024, 'a');
   SpdyHeaderBlock headers;
@@ -2970,6 +2974,17 @@
   }
 }
 
+TEST_P(EndToEndTest, SendStatelessResetTokenInShlo) {
+  ASSERT_TRUE(Initialize());
+  EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
+  QuicConfig* config = client_->client()->session()->config();
+  if (FLAGS_quic_reloadable_flag_quic_send_reset_token_in_shlo) {
+    EXPECT_TRUE(config->HasReceivedStatelessResetToken());
+    EXPECT_EQ(1010101u, config->ReceivedStatelessResetToken());
+  }
+  client_->Disconnect();
+}
+
 class EndToEndBufferedPacketsTest : public EndToEndTest {
  public:
   void CreateClientWithWriter() override {
diff --git a/net/tools/quic/quic_client.cc b/net/tools/quic/quic_client.cc
index f68df5a..aacb3f0ab 100644
--- a/net/tools/quic/quic_client.cc
+++ b/net/tools/quic/quic_client.cc
@@ -37,7 +37,7 @@
 
 QuicClient::QuicClient(QuicSocketAddress server_address,
                        const QuicServerId& server_id,
-                       const QuicVersionVector& supported_versions,
+                       const QuicTransportVersionVector& supported_versions,
                        EpollServer* epoll_server,
                        std::unique_ptr<ProofVerifier> proof_verifier)
     : QuicClient(
@@ -52,7 +52,7 @@
 QuicClient::QuicClient(
     QuicSocketAddress server_address,
     const QuicServerId& server_id,
-    const QuicVersionVector& supported_versions,
+    const QuicTransportVersionVector& supported_versions,
     EpollServer* epoll_server,
     std::unique_ptr<QuicClientEpollNetworkHelper> network_helper,
     std::unique_ptr<ProofVerifier> proof_verifier)
@@ -67,7 +67,7 @@
 QuicClient::QuicClient(
     QuicSocketAddress server_address,
     const QuicServerId& server_id,
-    const QuicVersionVector& supported_versions,
+    const QuicTransportVersionVector& supported_versions,
     const QuicConfig& config,
     EpollServer* epoll_server,
     std::unique_ptr<QuicClientEpollNetworkHelper> network_helper,
diff --git a/net/tools/quic/quic_client.h b/net/tools/quic/quic_client.h
index a236d4b..278d3b7 100644
--- a/net/tools/quic/quic_client.h
+++ b/net/tools/quic/quic_client.h
@@ -39,19 +39,19 @@
   // This will create its own QuicClientEpollNetworkHelper.
   QuicClient(QuicSocketAddress server_address,
              const QuicServerId& server_id,
-             const QuicVersionVector& supported_versions,
+             const QuicTransportVersionVector& supported_versions,
              EpollServer* epoll_server,
              std::unique_ptr<ProofVerifier> proof_verifier);
   // This will take ownership of a passed in network primitive.
   QuicClient(QuicSocketAddress server_address,
              const QuicServerId& server_id,
-             const QuicVersionVector& supported_versions,
+             const QuicTransportVersionVector& supported_versions,
              EpollServer* epoll_server,
              std::unique_ptr<QuicClientEpollNetworkHelper> network_helper,
              std::unique_ptr<ProofVerifier> proof_verifier);
   QuicClient(QuicSocketAddress server_address,
              const QuicServerId& server_id,
-             const QuicVersionVector& supported_versions,
+             const QuicTransportVersionVector& supported_versions,
              const QuicConfig& config,
              EpollServer* epoll_server,
              std::unique_ptr<QuicClientEpollNetworkHelper> network_helper,
diff --git a/net/tools/quic/quic_client_base.cc b/net/tools/quic/quic_client_base.cc
index 408aae63..f664ef9d 100644
--- a/net/tools/quic/quic_client_base.cc
+++ b/net/tools/quic/quic_client_base.cc
@@ -18,13 +18,14 @@
 
 QuicClientBase::NetworkHelper::~NetworkHelper() {}
 
-QuicClientBase::QuicClientBase(const QuicServerId& server_id,
-                               const QuicVersionVector& supported_versions,
-                               const QuicConfig& config,
-                               QuicConnectionHelperInterface* helper,
-                               QuicAlarmFactory* alarm_factory,
-                               std::unique_ptr<NetworkHelper> network_helper,
-                               std::unique_ptr<ProofVerifier> proof_verifier)
+QuicClientBase::QuicClientBase(
+    const QuicServerId& server_id,
+    const QuicTransportVersionVector& supported_versions,
+    const QuicConfig& config,
+    QuicConnectionHelperInterface* helper,
+    QuicAlarmFactory* alarm_factory,
+    std::unique_ptr<NetworkHelper> network_helper,
+    std::unique_ptr<ProofVerifier> proof_verifier)
     : server_id_(server_id),
       initialized_(false),
       local_port_(0),
diff --git a/net/tools/quic/quic_client_base.h b/net/tools/quic/quic_client_base.h
index 8252e1a5..db02189 100644
--- a/net/tools/quic/quic_client_base.h
+++ b/net/tools/quic/quic_client_base.h
@@ -59,7 +59,7 @@
   };
 
   QuicClientBase(const QuicServerId& server_id,
-                 const QuicVersionVector& supported_versions,
+                 const QuicTransportVersionVector& supported_versions,
                  const QuicConfig& config,
                  QuicConnectionHelperInterface* helper,
                  QuicAlarmFactory* alarm_factory,
@@ -142,11 +142,12 @@
     crypto_config_.tb_key_params = QuicTagVector{kTB10};
   }
 
-  const QuicVersionVector& supported_versions() const {
+  const QuicTransportVersionVector& supported_versions() const {
     return supported_versions_;
   }
 
-  void SetSupportedVersions(const QuicVersionVector& versions) {
+  void SetSupportedTransportVersions(
+      const QuicTransportVersionVector& versions) {
     supported_versions_ = versions;
   }
 
@@ -328,7 +329,7 @@
   // element, with subsequent elements in descending order (versions can be
   // skipped as necessary). We will always pick supported_versions_[0] as the
   // initial version to use.
-  QuicVersionVector supported_versions_;
+  QuicTransportVersionVector supported_versions_;
 
   // The initial value of maximum packet size of the connection.  If set to
   // zero, the default is used.
diff --git a/net/tools/quic/quic_client_bin.cc b/net/tools/quic/quic_client_bin.cc
index 33783c2..1a1cae4 100644
--- a/net/tools/quic/quic_client_bin.cc
+++ b/net/tools/quic/quic_client_bin.cc
@@ -111,7 +111,7 @@
       const string& /*hostname*/,
       const uint16_t /*port*/,
       const string& /*server_config*/,
-      net::QuicVersion /*quic_version*/,
+      net::QuicTransportVersion /*quic_version*/,
       QuicStringPiece /*chlo_hash*/,
       const std::vector<string>& /*certs*/,
       const string& /*cert_sct*/,
@@ -253,10 +253,12 @@
   net::EpollServer epoll_server;
   net::QuicServerId server_id(url.host(), url.port(),
                               net::PRIVACY_MODE_DISABLED);
-  net::QuicVersionVector versions = net::AllSupportedVersions();
+  net::QuicTransportVersionVector versions =
+      net::AllSupportedTransportVersions();
   if (FLAGS_quic_version != -1) {
     versions.clear();
-    versions.push_back(static_cast<net::QuicVersion>(FLAGS_quic_version));
+    versions.push_back(
+        static_cast<net::QuicTransportVersion>(FLAGS_quic_version));
   }
   // For secure QUIC we need to verify the cert chain.
   std::unique_ptr<CertVerifier> cert_verifier(CertVerifier::CreateDefault());
@@ -285,7 +287,8 @@
     net::QuicErrorCode error = client.session()->error();
     if (FLAGS_version_mismatch_ok && error == net::QUIC_INVALID_VERSION) {
       cout << "Server talks QUIC, but none of the versions supported by "
-           << "this client: " << QuicVersionVectorToString(versions) << endl;
+           << "this client: " << QuicTransportVersionVectorToString(versions)
+           << endl;
       // Version mismatch is not deemed a failure.
       return 0;
     }
diff --git a/net/tools/quic/quic_client_test.cc b/net/tools/quic/quic_client_test.cc
index 973826d0..941996c 100644
--- a/net/tools/quic/quic_client_test.cc
+++ b/net/tools/quic/quic_client_test.cc
@@ -53,7 +53,7 @@
   QuicSocketAddress server_address(QuicSocketAddress(TestLoopback(), port));
   QuicServerId server_id("hostname", server_address.port(),
                          PRIVACY_MODE_DISABLED);
-  QuicVersionVector versions = AllSupportedVersions();
+  QuicTransportVersionVector versions = AllSupportedTransportVersions();
   QuicClient* client =
       new QuicClient(server_address, server_id, versions, eps,
                      crypto_test_utils::ProofVerifierForTesting());
diff --git a/net/tools/quic/quic_dispatcher.cc b/net/tools/quic/quic_dispatcher.cc
index a52ba6f..aa959c57 100644
--- a/net/tools/quic/quic_dispatcher.cc
+++ b/net/tools/quic/quic_dispatcher.cc
@@ -115,9 +115,7 @@
                  helper->GetStreamFrameBufferAllocator(),
                  &collector_),
         time_wait_list_manager_(time_wait_list_manager) {
-    if (FLAGS_quic_reloadable_flag_quic_save_data_before_consumption2) {
-      framer_->set_data_producer(&collector_);
-    }
+    framer_->set_data_producer(&collector_);
   }
 
   ~StatelessConnectionTerminator() {
@@ -142,7 +140,7 @@
     creator_.Flush();
     DCHECK_EQ(1u, collector_.packets()->size());
     time_wait_list_manager_->AddConnectionIdToTimeWait(
-        connection_id_, framer_->version(),
+        connection_id_, framer_->transport_version(),
         /*connection_rejected_statelessly=*/false, collector_.packets());
   }
 
@@ -156,8 +154,6 @@
     QuicIOVector iov(&iovec, 1, iovec.iov_len);
     QuicStreamOffset offset = 0;
     if (framer_->HasDataProducer()) {
-      QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_save_data_before_consumption2,
-                        4, 4);
       collector_.SaveStatelessRejectFrameData(iov, 0, reject.length());
     }
     while (offset < iovec.iov_len) {
@@ -176,7 +172,7 @@
       creator_.Flush();
     }
     time_wait_list_manager_->AddConnectionIdToTimeWait(
-        connection_id_, framer_->version(),
+        connection_id_, framer_->transport_version(),
         /*connection_rejected_statelessly=*/true, collector_.packets());
     DCHECK(time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id_));
   }
@@ -193,7 +189,7 @@
 // Class which extracts the ALPN from a CHLO packet.
 class ChloAlpnExtractor : public ChloExtractor::Delegate {
  public:
-  void OnChlo(QuicVersion version,
+  void OnChlo(QuicTransportVersion version,
               QuicConnectionId connection_id,
               const CryptoHandshakeMessage& chlo) override {
     QuicStringPiece alpn_value;
@@ -221,7 +217,7 @@
         can_accept_(false) {}
 
   // ChloExtractor::Delegate implementation.
-  void OnChlo(QuicVersion version,
+  void OnChlo(QuicTransportVersion version,
               QuicConnectionId connection_id,
               const CryptoHandshakeMessage& chlo) override {
     // Extract the ALPN
@@ -267,7 +263,7 @@
       buffered_packets_(this, helper_->GetClock(), alarm_factory_.get()),
       current_packet_(nullptr),
       version_manager_(version_manager),
-      framer_(GetSupportedVersions(),
+      framer_(GetSupportedTransportVersions(),
               /*unused*/ QuicTime::Zero(),
               Perspective::IS_SERVER),
       last_error_(QUIC_NO_ERROR),
@@ -365,12 +361,12 @@
 
   // Unless the packet provides a version, assume that we can continue
   // processing using our preferred version.
-  QuicVersion version = GetSupportedVersions().front();
+  QuicTransportVersion version = GetSupportedTransportVersions().front();
   if (header.version_flag) {
-    QuicVersion packet_version = header.versions.front();
-    if (framer_.supported_versions() != GetSupportedVersions()) {
+    QuicTransportVersion packet_version = header.versions.front();
+    if (framer_.supported_versions() != GetSupportedTransportVersions()) {
       // Reset framer's version if version flags change in flight.
-      framer_.SetSupportedVersions(GetSupportedVersions());
+      framer_.SetSupportedTransportVersions(GetSupportedTransportVersions());
     }
     if (!framer_.IsSupportedVersion(packet_version)) {
       if (ShouldCreateSessionForUnknownVersion(framer_.last_version_label())) {
@@ -379,8 +375,8 @@
       // Since the version is not supported, send a version negotiation
       // packet and stop processing the current packet.
       time_wait_list_manager()->SendVersionNegotiationPacket(
-          connection_id, GetSupportedVersions(), current_server_address_,
-          current_client_address_);
+          connection_id, GetSupportedTransportVersions(),
+          current_server_address_, current_client_address_);
       return false;
     }
     version = packet_version;
@@ -436,7 +432,7 @@
         QUIC_DLOG(INFO) << "Adding connection ID " << connection_id
                         << "to time-wait list.";
         time_wait_list_manager_->AddConnectionIdToTimeWait(
-            connection_id, framer_.version(),
+            connection_id, framer_.transport_version(),
             /*connection_rejected_statelessly=*/false, nullptr);
       }
       DCHECK(time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id));
@@ -521,7 +517,7 @@
            !connection->termination_packets()->empty());
   }
   time_wait_list_manager_->AddConnectionIdToTimeWait(
-      it->first, connection->version(), should_close_statelessly,
+      it->first, connection->transport_version(), should_close_statelessly,
       connection->termination_packets());
   session_map_.erase(it);
 }
@@ -631,7 +627,7 @@
 }
 
 bool QuicDispatcher::OnProtocolVersionMismatch(
-    QuicVersion /*received_version*/) {
+    QuicTransportVersion /*received_version*/) {
   QUIC_BUG_IF(
       !time_wait_list_manager_->IsConnectionIdInTimeWait(
           current_connection_id_) &&
@@ -723,7 +719,7 @@
     QuicConnectionId connection_id,
     BufferedPacketList early_arrived_packets) {
   time_wait_list_manager_->AddConnectionIdToTimeWait(
-      connection_id, framer_.version(), false, nullptr);
+      connection_id, framer_.transport_version(), false, nullptr);
 }
 
 void QuicDispatcher::ProcessBufferedChlos(size_t max_connections_to_create) {
@@ -798,7 +794,7 @@
   if (!accept_new_connections_) {
     // Don't any create new connection.
     time_wait_list_manager()->AddConnectionIdToTimeWait(
-        current_connection_id(), framer()->version(),
+        current_connection_id(), framer()->transport_version(),
         /*connection_rejected_statelessly=*/false,
         /*termination_packets=*/nullptr);
     // This will trigger sending Public Reset packet.
@@ -880,7 +876,7 @@
     : public StatelessRejector::ProcessDoneCallback {
  public:
   StatelessRejectorProcessDoneCallback(QuicDispatcher* dispatcher,
-                                       QuicVersion first_version)
+                                       QuicTransportVersion first_version)
       : dispatcher_(dispatcher),
         current_client_address_(dispatcher->current_client_address_),
         current_server_address_(dispatcher->current_server_address_),
@@ -899,11 +895,11 @@
   QuicSocketAddress current_client_address_;
   QuicSocketAddress current_server_address_;
   std::unique_ptr<QuicReceivedPacket> current_packet_;
-  QuicVersion first_version_;
+  QuicTransportVersion first_version_;
 };
 
 void QuicDispatcher::MaybeRejectStatelessly(QuicConnectionId connection_id,
-                                            QuicVersion version) {
+                                            QuicTransportVersion version) {
   // TODO(rch): This logic should probably live completely inside the rejector.
   if (!FLAGS_quic_allow_chlo_buffering ||
       !FLAGS_quic_reloadable_flag_quic_use_cheap_stateless_rejects ||
@@ -912,7 +908,8 @@
     // Not use cheap stateless reject.
     ChloAlpnExtractor alpn_extractor;
     if (FLAGS_quic_allow_chlo_buffering &&
-        !ChloExtractor::Extract(*current_packet_, GetSupportedVersions(),
+        !ChloExtractor::Extract(*current_packet_,
+                                GetSupportedTransportVersions(),
                                 &alpn_extractor)) {
       // Buffer non-CHLO packets.
       ProcessUnauthenticatedHeaderFate(kFateBuffer, connection_id);
@@ -924,12 +921,13 @@
   }
 
   std::unique_ptr<StatelessRejector> rejector(new StatelessRejector(
-      version, GetSupportedVersions(), crypto_config_, &compressed_certs_cache_,
-      helper()->GetClock(), helper()->GetRandomGenerator(),
-      current_packet_->length(), GetClientAddress(), current_server_address_));
+      version, GetSupportedTransportVersions(), crypto_config_,
+      &compressed_certs_cache_, helper()->GetClock(),
+      helper()->GetRandomGenerator(), current_packet_->length(),
+      GetClientAddress(), current_server_address_));
   ChloValidator validator(session_helper_.get(), current_server_address_,
                           rejector.get());
-  if (!ChloExtractor::Extract(*current_packet_, GetSupportedVersions(),
+  if (!ChloExtractor::Extract(*current_packet_, GetSupportedTransportVersions(),
                               &validator)) {
     ProcessUnauthenticatedHeaderFate(kFateBuffer, connection_id);
     return;
@@ -972,7 +970,7 @@
     const QuicSocketAddress& current_client_address,
     const QuicSocketAddress& current_server_address,
     std::unique_ptr<QuicReceivedPacket> current_packet,
-    QuicVersion first_version) {
+    QuicTransportVersion first_version) {
   // Stop buffering packets on this connection
   const auto num_erased =
       temporarily_buffered_connections_.erase(rejector->connection_id());
@@ -1007,7 +1005,7 @@
 
 void QuicDispatcher::ProcessStatelessRejectorState(
     std::unique_ptr<StatelessRejector> rejector,
-    QuicVersion first_version) {
+    QuicTransportVersion first_version) {
   QuicPacketFate fate;
   switch (rejector->state()) {
     case StatelessRejector::FAILED: {
@@ -1031,10 +1029,10 @@
       break;
 
     case StatelessRejector::REJECTED: {
-      QUIC_BUG_IF(first_version != framer_.version())
+      QUIC_BUG_IF(first_version != framer_.transport_version())
           << "SREJ: Client's version: " << QuicVersionToString(first_version)
           << " is different from current dispatcher framer's version: "
-          << QuicVersionToString(framer_.version());
+          << QuicVersionToString(framer_.transport_version());
       StatelessConnectionTerminator terminator(rejector->connection_id(),
                                                &framer_, helper(),
                                                time_wait_list_manager_.get());
@@ -1054,8 +1052,9 @@
   ProcessUnauthenticatedHeaderFate(fate, rejector->connection_id());
 }
 
-const QuicVersionVector& QuicDispatcher::GetSupportedVersions() {
-  return version_manager_->GetSupportedVersions();
+const QuicTransportVersionVector&
+QuicDispatcher::GetSupportedTransportVersions() {
+  return version_manager_->GetSupportedTransportVersions();
 }
 
 void QuicDispatcher::DeliverPacketsToSession(
diff --git a/net/tools/quic/quic_dispatcher.h b/net/tools/quic/quic_dispatcher.h
index 27204ab..132f2da0 100644
--- a/net/tools/quic/quic_dispatcher.h
+++ b/net/tools/quic/quic_dispatcher.h
@@ -122,7 +122,8 @@
   // destined for the time wait manager.
   bool OnUnauthenticatedHeader(const QuicPacketHeader& header) override;
   void OnError(QuicFramer* framer) override;
-  bool OnProtocolVersionMismatch(QuicVersion received_version) override;
+  bool OnProtocolVersionMismatch(
+      QuicTransportVersion received_version) override;
 
   // The following methods should never get called because
   // OnUnauthenticatedPublicHeader() or OnUnauthenticatedHeader() (whichever
@@ -213,7 +214,7 @@
     return time_wait_list_manager_.get();
   }
 
-  const QuicVersionVector& GetSupportedVersions();
+  const QuicTransportVersionVector& GetSupportedTransportVersions();
 
   QuicConnectionId current_connection_id() { return current_connection_id_; }
   const QuicSocketAddress& current_server_address() {
@@ -303,7 +304,7 @@
   // fate which describes what subsequent processing should be performed on the
   // packets, like ValidityChecks, and invokes ProcessUnauthenticatedHeaderFate.
   void MaybeRejectStatelessly(QuicConnectionId connection_id,
-                              QuicVersion version);
+                              QuicTransportVersion version);
 
   // Deliver |packets| to |session| for further processing.
   void DeliverPacketsToSession(
@@ -322,13 +323,13 @@
       const QuicSocketAddress& current_client_address,
       const QuicSocketAddress& current_server_address,
       std::unique_ptr<QuicReceivedPacket> current_packet,
-      QuicVersion first_version);
+      QuicTransportVersion first_version);
 
   // Examine the state of the rejector and decide what to do with the current
   // packet.
   void ProcessStatelessRejectorState(
       std::unique_ptr<StatelessRejector> rejector,
-      QuicVersion first_version);
+      QuicTransportVersion first_version);
 
   void set_new_sessions_allowed_per_event_loop(
       int16_t new_sessions_allowed_per_event_loop) {
diff --git a/net/tools/quic/quic_dispatcher_test.cc b/net/tools/quic/quic_dispatcher_test.cc
index b1543217..221c359 100644
--- a/net/tools/quic/quic_dispatcher_test.cc
+++ b/net/tools/quic/quic_dispatcher_test.cc
@@ -176,7 +176,7 @@
   explicit QuicDispatcherTest(std::unique_ptr<ProofSource> proof_source)
       : helper_(&eps_, QuicAllocator::BUFFER_POOL),
         alarm_factory_(&eps_),
-        version_manager_(AllSupportedVersions()),
+        version_manager_(AllSupportedTransportVersions()),
         crypto_config_(QuicCryptoServerConfig::TESTING,
                        QuicRandom::GetInstance(),
                        std::move(proof_source)),
@@ -240,7 +240,7 @@
                      QuicPacketNumberLength packet_number_length,
                      QuicPacketNumber packet_number) {
     ProcessPacket(client_address, connection_id, has_version_flag,
-                  CurrentSupportedVersions().front(), data,
+                  CurrentSupportedTransportVersions().front(), data,
                   connection_id_length, packet_number_length, packet_number);
   }
 
@@ -248,12 +248,12 @@
   void ProcessPacket(QuicSocketAddress client_address,
                      QuicConnectionId connection_id,
                      bool has_version_flag,
-                     QuicVersion version,
+                     QuicTransportVersion version,
                      const string& data,
                      QuicConnectionIdLength connection_id_length,
                      QuicPacketNumberLength packet_number_length,
                      QuicPacketNumber packet_number) {
-    QuicVersionVector versions(SupportedVersions(version));
+    QuicTransportVersionVector versions(SupportedTransportVersions(version));
     std::unique_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket(
         connection_id, has_version_flag, false, packet_number, data,
         connection_id_length, packet_number_length, &versions));
@@ -386,7 +386,8 @@
   EXPECT_CALL(*dispatcher_,
               CreateQuicSession(1, client_address, QuicStringPiece("hq")))
       .Times(0);
-  QuicVersion version = static_cast<QuicVersion>(QuicVersionMin() - 1);
+  QuicTransportVersion version =
+      static_cast<QuicTransportVersion>(QuicVersionMin() - 1);
   ProcessPacket(client_address, 1, true, version, SerializeCHLO(),
                 PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_PACKET_NUMBER, 1);
 }
@@ -552,8 +553,8 @@
                     QuicDispatcher::kMaxReasonableInitialPacketNumber + 1);
 }
 
-TEST_F(QuicDispatcherTest, SupportedVersionsChangeInFlight) {
-  static_assert(arraysize(kSupportedQuicVersions) == 6u,
+TEST_F(QuicDispatcherTest, SupportedTransportVersionsChangeInFlight) {
+  static_assert(arraysize(kSupportedTransportVersions) == 6u,
                 "Supported versions out of sync");
   FLAGS_quic_reloadable_flag_quic_enable_version_38 = true;
   FLAGS_quic_reloadable_flag_quic_enable_version_39 = true;
@@ -567,8 +568,9 @@
                                               QuicStringPiece("hq")))
       .Times(0);
   ProcessPacket(client_address, connection_id, true,
-                static_cast<QuicVersion>(QuicVersionMin() - 1), SerializeCHLO(),
-                PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_PACKET_NUMBER, 1);
+                static_cast<QuicTransportVersion>(QuicVersionMin() - 1),
+                SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
+                PACKET_6BYTE_PACKET_NUMBER, 1);
   ++connection_id;
   EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
                                               QuicStringPiece("hq")))
@@ -1258,7 +1260,7 @@
     QuicDispatcherTest::SetUp();
     clock_ = QuicDispatcherPeer::GetHelper(dispatcher_.get())->GetClock();
 
-    QuicVersion version = AllSupportedVersions().front();
+    QuicTransportVersion version = AllSupportedTransportVersions().front();
     CryptoHandshakeMessage chlo =
         crypto_test_utils::GenerateDefaultInchoateCHLO(clock_, version,
                                                        &crypto_config_);
@@ -1667,7 +1669,7 @@
     QuicDispatcherTest::SetUp();
 
     clock_ = QuicDispatcherPeer::GetHelper(dispatcher_.get())->GetClock();
-    QuicVersion version = AllSupportedVersions().front();
+    QuicTransportVersion version = AllSupportedTransportVersions().front();
     chlo_ = crypto_test_utils::GenerateDefaultInchoateCHLO(clock_, version,
                                                            &crypto_config_);
     chlo_.SetVector(net::kCOPT, net::QuicTagVector{net::kSREJ});
diff --git a/net/tools/quic/quic_packet_printer_bin.cc b/net/tools/quic/quic_packet_printer_bin.cc
index aa26b479..b58a689 100644
--- a/net/tools/quic/quic_packet_printer_bin.cc
+++ b/net/tools/quic/quic_packet_printer_bin.cc
@@ -67,7 +67,8 @@
     std::cerr << "OnError: " << QuicErrorCodeToString(framer->error())
               << " detail: " << framer->detailed_error() << "\n";
   }
-  bool OnProtocolVersionMismatch(QuicVersion received_version) override {
+  bool OnProtocolVersionMismatch(
+      QuicTransportVersion received_version) override {
     framer_->set_version(received_version);
     std::cerr << "OnProtocolVersionMismatch: "
               << QuicVersionToString(received_version) << "\n";
@@ -177,12 +178,13 @@
     return 1;
   }
   string hex = net::QuicTextUtils::HexDecode(argv[2]);
-  net::QuicVersionVector versions = net::AllSupportedVersions();
+  net::QuicTransportVersionVector versions =
+      net::AllSupportedTransportVersions();
   // Fake a time since we're not actually generating acks.
   net::QuicTime start(net::QuicTime::Zero());
   net::QuicFramer framer(versions, start, perspective);
   if (!FLAGS_quic_version.empty()) {
-    for (net::QuicVersion version : versions) {
+    for (net::QuicTransportVersion version : versions) {
       if (net::QuicVersionToString(version) == FLAGS_quic_version) {
         framer.set_version(version);
       }
diff --git a/net/tools/quic/quic_server.cc b/net/tools/quic/quic_server.cc
index aef56cd..b3d7414 100644
--- a/net/tools/quic/quic_server.cc
+++ b/net/tools/quic/quic_server.cc
@@ -56,14 +56,14 @@
     : QuicServer(std::move(proof_source),
                  QuicConfig(),
                  QuicCryptoServerConfig::ConfigOptions(),
-                 AllSupportedVersions(),
+                 AllSupportedTransportVersions(),
                  response_cache) {}
 
 QuicServer::QuicServer(
     std::unique_ptr<ProofSource> proof_source,
     const QuicConfig& config,
     const QuicCryptoServerConfig::ConfigOptions& crypto_config_options,
-    const QuicVersionVector& supported_versions,
+    const QuicTransportVersionVector& supported_versions,
     QuicHttpResponseCache* response_cache)
     : port_(0),
       fd_(-1),
diff --git a/net/tools/quic/quic_server.h b/net/tools/quic/quic_server.h
index 2a3aca040..9e404973 100644
--- a/net/tools/quic/quic_server.h
+++ b/net/tools/quic/quic_server.h
@@ -40,7 +40,7 @@
   QuicServer(std::unique_ptr<ProofSource> proof_source,
              const QuicConfig& config,
              const QuicCryptoServerConfig::ConfigOptions& server_config_options,
-             const QuicVersionVector& supported_versions,
+             const QuicTransportVersionVector& supported_versions,
              QuicHttpResponseCache* response_cache);
 
   ~QuicServer() override;
diff --git a/net/tools/quic/quic_server_bin.cc b/net/tools/quic/quic_server_bin.cc
index 45621a8..1c062c49 100644
--- a/net/tools/quic/quic_server_bin.cc
+++ b/net/tools/quic/quic_server_bin.cc
@@ -85,7 +85,7 @@
       CreateProofSource(line->GetSwitchValuePath("certificate_file"),
                         line->GetSwitchValuePath("key_file")),
       config, net::QuicCryptoServerConfig::ConfigOptions(),
-      net::AllSupportedVersions(), &response_cache);
+      net::AllSupportedTransportVersions(), &response_cache);
 
   int rc = server.CreateUDPSocketAndListen(
       net::QuicSocketAddress(net::QuicIpAddress::Any6(), FLAGS_port));
diff --git a/net/tools/quic/quic_server_test.cc b/net/tools/quic/quic_server_test.cc
index af0eeaa..e0da550 100644
--- a/net/tools/quic/quic_server_test.cc
+++ b/net/tools/quic/quic_server_test.cc
@@ -149,7 +149,7 @@
       : crypto_config_("blah",
                        QuicRandom::GetInstance(),
                        crypto_test_utils::ProofSourceForTesting()),
-        version_manager_(AllSupportedVersions()),
+        version_manager_(AllSupportedTransportVersions()),
         dispatcher_(
             config_,
             &crypto_config_,
diff --git a/net/tools/quic/quic_simple_client.cc b/net/tools/quic/quic_simple_client.cc
index 12b511f6..b394ae1 100644
--- a/net/tools/quic/quic_simple_client.cc
+++ b/net/tools/quic/quic_simple_client.cc
@@ -36,7 +36,7 @@
 QuicSimpleClient::QuicSimpleClient(
     QuicSocketAddress server_address,
     const QuicServerId& server_id,
-    const QuicVersionVector& supported_versions,
+    const QuicTransportVersionVector& supported_versions,
     std::unique_ptr<ProofVerifier> proof_verifier)
     : QuicSpdyClientBase(
           server_id,
diff --git a/net/tools/quic/quic_simple_client.h b/net/tools/quic/quic_simple_client.h
index 1aecc2a2..5f79e049 100644
--- a/net/tools/quic/quic_simple_client.h
+++ b/net/tools/quic/quic_simple_client.h
@@ -40,7 +40,7 @@
   // Create a quic client, which will have events managed by the message loop.
   QuicSimpleClient(QuicSocketAddress server_address,
                    const QuicServerId& server_id,
-                   const QuicVersionVector& supported_versions,
+                   const QuicTransportVersionVector& supported_versions,
                    std::unique_ptr<ProofVerifier> proof_verifier);
 
   ~QuicSimpleClient() override;
diff --git a/net/tools/quic/quic_simple_client_bin.cc b/net/tools/quic/quic_simple_client_bin.cc
index 0a5a35b..6ce004a 100644
--- a/net/tools/quic/quic_simple_client_bin.cc
+++ b/net/tools/quic/quic_simple_client_bin.cc
@@ -111,7 +111,7 @@
       const string& hostname,
       const uint16_t port,
       const string& server_config,
-      net::QuicVersion quic_version,
+      net::QuicTransportVersion quic_version,
       QuicStringPiece chlo_hash,
       const std::vector<string>& certs,
       const string& cert_sct,
@@ -252,10 +252,12 @@
   // Build the client, and try to connect.
   net::QuicServerId server_id(url.host(), url.EffectiveIntPort(),
                               net::PRIVACY_MODE_DISABLED);
-  net::QuicVersionVector versions = net::AllSupportedVersions();
+  net::QuicTransportVersionVector versions =
+      net::AllSupportedTransportVersions();
   if (FLAGS_quic_version != -1) {
     versions.clear();
-    versions.push_back(static_cast<net::QuicVersion>(FLAGS_quic_version));
+    versions.push_back(
+        static_cast<net::QuicTransportVersion>(FLAGS_quic_version));
   }
   // For secure QUIC we need to verify the cert chain.
   std::unique_ptr<CertVerifier> cert_verifier(CertVerifier::CreateDefault());
@@ -284,7 +286,8 @@
     net::QuicErrorCode error = client.session()->error();
     if (FLAGS_version_mismatch_ok && error == net::QUIC_INVALID_VERSION) {
       cout << "Server talks QUIC, but none of the versions supported by "
-           << "this client: " << QuicVersionVectorToString(versions) << endl;
+           << "this client: " << QuicTransportVersionVectorToString(versions)
+           << endl;
       // Version mismatch is not deemed a failure.
       return 0;
     }
diff --git a/net/tools/quic/quic_simple_client_test.cc b/net/tools/quic/quic_simple_client_test.cc
index 997890e0..2c6baef 100644
--- a/net/tools/quic/quic_simple_client_test.cc
+++ b/net/tools/quic/quic_simple_client_test.cc
@@ -16,7 +16,7 @@
   QuicSocketAddress server_address(QuicIpAddress::Loopback4(), 80);
   QuicServerId server_id("hostname", server_address.port(),
                          PRIVACY_MODE_DISABLED);
-  QuicVersionVector versions = AllSupportedVersions();
+  QuicTransportVersionVector versions = AllSupportedTransportVersions();
   QuicSimpleClient client(server_address, server_id, versions,
                           crypto_test_utils::ProofVerifierForTesting());
   EXPECT_TRUE(client.Initialize());
diff --git a/net/tools/quic/quic_simple_dispatcher.cc b/net/tools/quic/quic_simple_dispatcher.cc
index 8b8e59c8..663783ad 100644
--- a/net/tools/quic/quic_simple_dispatcher.cc
+++ b/net/tools/quic/quic_simple_dispatcher.cc
@@ -51,10 +51,11 @@
     const QuicSocketAddress& client_address,
     QuicStringPiece /*alpn*/) {
   // The QuicServerSessionBase takes ownership of |connection| below.
-  QuicConnection* connection = new QuicConnection(
-      connection_id, client_address, helper(), alarm_factory(),
-      CreatePerConnectionWriter(),
-      /* owns_writer= */ true, Perspective::IS_SERVER, GetSupportedVersions());
+  QuicConnection* connection =
+      new QuicConnection(connection_id, client_address, helper(),
+                         alarm_factory(), CreatePerConnectionWriter(),
+                         /* owns_writer= */ true, Perspective::IS_SERVER,
+                         GetSupportedTransportVersions());
 
   QuicServerSessionBase* session = new QuicSimpleServerSession(
       config(), connection, this, session_helper(), crypto_config(),
diff --git a/net/tools/quic/quic_simple_server.cc b/net/tools/quic/quic_simple_server.cc
index a9714c2a..9f0f9d15 100644
--- a/net/tools/quic/quic_simple_server.cc
+++ b/net/tools/quic/quic_simple_server.cc
@@ -40,7 +40,7 @@
     std::unique_ptr<ProofSource> proof_source,
     const QuicConfig& config,
     const QuicCryptoServerConfig::ConfigOptions& crypto_config_options,
-    const QuicVersionVector& supported_versions,
+    const QuicTransportVersionVector& supported_versions,
     QuicHttpResponseCache* response_cache)
     : version_manager_(supported_versions),
       helper_(
diff --git a/net/tools/quic/quic_simple_server.h b/net/tools/quic/quic_simple_server.h
index f97b9b65..938a713 100644
--- a/net/tools/quic/quic_simple_server.h
+++ b/net/tools/quic/quic_simple_server.h
@@ -39,7 +39,7 @@
       std::unique_ptr<ProofSource> proof_source,
       const QuicConfig& config,
       const QuicCryptoServerConfig::ConfigOptions& crypto_config_options,
-      const QuicVersionVector& supported_versions,
+      const QuicTransportVersionVector& supported_versions,
       QuicHttpResponseCache* response_cache);
 
   virtual ~QuicSimpleServer();
diff --git a/net/tools/quic/quic_simple_server_bin.cc b/net/tools/quic/quic_simple_server_bin.cc
index aa57912..cbce5344 100644
--- a/net/tools/quic/quic_simple_server_bin.cc
+++ b/net/tools/quic/quic_simple_server_bin.cc
@@ -88,7 +88,7 @@
       CreateProofSource(line->GetSwitchValuePath("certificate_file"),
                         line->GetSwitchValuePath("key_file")),
       config, net::QuicCryptoServerConfig::ConfigOptions(),
-      net::AllSupportedVersions(), &response_cache);
+      net::AllSupportedTransportVersions(), &response_cache);
 
   int rc = server.Listen(net::IPEndPoint(ip, FLAGS_port));
   if (rc < 0) {
diff --git a/net/tools/quic/quic_simple_server_session_test.cc b/net/tools/quic/quic_simple_server_session_test.cc
index 1a4e0d2..2054146 100644
--- a/net/tools/quic/quic_simple_server_session_test.cc
+++ b/net/tools/quic/quic_simple_server_session_test.cc
@@ -118,7 +118,7 @@
       MockQuicConnectionHelper* helper,
       MockAlarmFactory* alarm_factory,
       Perspective perspective,
-      const QuicVersionVector& supported_versions)
+      const QuicTransportVersionVector& supported_versions)
       : MockQuicConnection(helper,
                            alarm_factory,
                            perspective,
@@ -181,7 +181,8 @@
                  ack_listener));
 };
 
-class QuicSimpleServerSessionTest : public QuicTestWithParam<QuicVersion> {
+class QuicSimpleServerSessionTest
+    : public QuicTestWithParam<QuicTransportVersion> {
  protected:
   QuicSimpleServerSessionTest()
       : crypto_config_(QuicCryptoServerConfig::TESTING,
@@ -200,7 +201,7 @@
 
     connection_ = new StrictMock<MockQuicConnectionWithSendStreamData>(
         &helper_, &alarm_factory_, Perspective::IS_SERVER,
-        SupportedVersions(GetParam()));
+        SupportedTransportVersions(GetParam()));
     session_.reset(new MockQuicSimpleServerSession(
         config_, connection_, &owner_, &stream_helper_, &crypto_config_,
         &compressed_certs_cache_, &response_cache_));
@@ -238,7 +239,7 @@
 
 INSTANTIATE_TEST_CASE_P(Tests,
                         QuicSimpleServerSessionTest,
-                        ::testing::ValuesIn(AllSupportedVersions()));
+                        ::testing::ValuesIn(AllSupportedTransportVersions()));
 
 TEST_P(QuicSimpleServerSessionTest, CloseStreamDueToReset) {
   // Open a stream, then reset it.
@@ -455,7 +456,7 @@
 
     connection_ = new StrictMock<MockQuicConnectionWithSendStreamData>(
         &helper_, &alarm_factory_, Perspective::IS_SERVER,
-        SupportedVersions(GetParam()));
+        SupportedTransportVersions(GetParam()));
     session_.reset(new MockQuicSimpleServerSession(
         config_, connection_, &owner_, &stream_helper_, &crypto_config_,
         &compressed_certs_cache_, &response_cache_));
@@ -523,7 +524,7 @@
 
 INSTANTIATE_TEST_CASE_P(Tests,
                         QuicSimpleServerSessionServerPushTest,
-                        ::testing::ValuesIn(AllSupportedVersions()));
+                        ::testing::ValuesIn(AllSupportedTransportVersions()));
 
 TEST_P(QuicSimpleServerSessionServerPushTest, TestPromisePushResources) {
   // Tests that given more than kMaxOpenStreamForTest resources, all their
diff --git a/net/tools/quic/quic_simple_server_stream_test.cc b/net/tools/quic/quic_simple_server_stream_test.cc
index 052c8cf..c7383e6 100644
--- a/net/tools/quic/quic_simple_server_stream_test.cc
+++ b/net/tools/quic/quic_simple_server_stream_test.cc
@@ -24,12 +24,12 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 using std::string;
-using testing::_;
 using testing::AnyNumber;
-using testing::Invoke;
 using testing::InSequence;
+using testing::Invoke;
 using testing::Return;
 using testing::StrictMock;
+using testing::_;
 
 namespace net {
 namespace test {
@@ -45,8 +45,8 @@
 
   ~QuicSimpleServerStreamPeer() override {}
 
-  using QuicSimpleServerStream::SendResponse;
   using QuicSimpleServerStream::SendErrorResponse;
+  using QuicSimpleServerStream::SendResponse;
 
   SpdyHeaderBlock* mutable_headers() { return &request_headers_; }
 
@@ -166,14 +166,15 @@
   DISALLOW_COPY_AND_ASSIGN(MockQuicSimpleServerSession);
 };
 
-class QuicSimpleServerStreamTest : public QuicTestWithParam<QuicVersion> {
+class QuicSimpleServerStreamTest
+    : public QuicTestWithParam<QuicTransportVersion> {
  public:
   QuicSimpleServerStreamTest()
-      : connection_(
-            new StrictMock<MockQuicConnection>(&helper_,
-                                               &alarm_factory_,
-                                               Perspective::IS_SERVER,
-                                               SupportedVersions(GetParam()))),
+      : connection_(new StrictMock<MockQuicConnection>(
+            &helper_,
+            &alarm_factory_,
+            Perspective::IS_SERVER,
+            SupportedTransportVersions(GetParam()))),
         crypto_config_(new QuicCryptoServerConfig(
             QuicCryptoServerConfig::TESTING,
             QuicRandom::GetInstance(),
@@ -233,7 +234,7 @@
 
 INSTANTIATE_TEST_CASE_P(Tests,
                         QuicSimpleServerStreamTest,
-                        ::testing::ValuesIn(AllSupportedVersions()));
+                        ::testing::ValuesIn(AllSupportedTransportVersions()));
 
 TEST_P(QuicSimpleServerStreamTest, TestFraming) {
   EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
diff --git a/net/tools/quic/quic_simple_server_test.cc b/net/tools/quic/quic_simple_server_test.cc
index 72e82828..3b5000ca 100644
--- a/net/tools/quic/quic_simple_server_test.cc
+++ b/net/tools/quic/quic_simple_server_test.cc
@@ -26,7 +26,7 @@
       : crypto_config_("blah",
                        QuicRandom::GetInstance(),
                        crypto_test_utils::ProofSourceForTesting()),
-        version_manager_(AllSupportedVersions()),
+        version_manager_(AllSupportedTransportVersions()),
         dispatcher_(
             config_,
             &crypto_config_,
diff --git a/net/tools/quic/quic_spdy_client_base.cc b/net/tools/quic/quic_spdy_client_base.cc
index 2ece82d..7eca30d 100644
--- a/net/tools/quic/quic_spdy_client_base.cc
+++ b/net/tools/quic/quic_spdy_client_base.cc
@@ -32,7 +32,7 @@
 
 QuicSpdyClientBase::QuicSpdyClientBase(
     const QuicServerId& server_id,
-    const QuicVersionVector& supported_versions,
+    const QuicTransportVersionVector& supported_versions,
     const QuicConfig& config,
     QuicConnectionHelperInterface* helper,
     QuicAlarmFactory* alarm_factory,
diff --git a/net/tools/quic/quic_spdy_client_base.h b/net/tools/quic/quic_spdy_client_base.h
index 76a2e92..a79a5ef 100644
--- a/net/tools/quic/quic_spdy_client_base.h
+++ b/net/tools/quic/quic_spdy_client_base.h
@@ -69,7 +69,7 @@
   };
 
   QuicSpdyClientBase(const QuicServerId& server_id,
-                     const QuicVersionVector& supported_versions,
+                     const QuicTransportVersionVector& supported_versions,
                      const QuicConfig& config,
                      QuicConnectionHelperInterface* helper,
                      QuicAlarmFactory* alarm_factory,
diff --git a/net/tools/quic/quic_spdy_client_session_test.cc b/net/tools/quic/quic_spdy_client_session_test.cc
index af8e4fc..f03910e 100644
--- a/net/tools/quic/quic_spdy_client_session_test.cc
+++ b/net/tools/quic/quic_spdy_client_session_test.cc
@@ -63,7 +63,8 @@
   }
 };
 
-class QuicSpdyClientSessionTest : public QuicTestWithParam<QuicVersion> {
+class QuicSpdyClientSessionTest
+    : public QuicTestWithParam<QuicTransportVersion> {
  protected:
   QuicSpdyClientSessionTest()
       : crypto_config_(crypto_test_utils::ProofVerifierForTesting()),
@@ -81,9 +82,9 @@
 
   void Initialize() {
     session_.reset();
-    connection_ = new PacketSavingConnection(&helper_, &alarm_factory_,
-                                             Perspective::IS_CLIENT,
-                                             SupportedVersions(GetParam()));
+    connection_ = new PacketSavingConnection(
+        &helper_, &alarm_factory_, Perspective::IS_CLIENT,
+        SupportedTransportVersions(GetParam()));
     session_.reset(new TestQuicSpdyClientSession(
         DefaultQuicConfig(), connection_,
         QuicServerId(kServerHostname, kPort, PRIVACY_MODE_DISABLED),
@@ -130,7 +131,7 @@
 
 INSTANTIATE_TEST_CASE_P(Tests,
                         QuicSpdyClientSessionTest,
-                        ::testing::ValuesIn(AllSupportedVersions()));
+                        ::testing::ValuesIn(AllSupportedTransportVersions()));
 
 TEST_P(QuicSpdyClientSessionTest, CryptoConnect) {
   CompleteCryptoHandshake();
@@ -343,7 +344,7 @@
 
   // Verify that a decryptable packet with bad frames does close the connection.
   QuicConnectionId connection_id = session_->connection()->connection_id();
-  QuicVersionVector versions = {GetParam()};
+  QuicTransportVersionVector versions = {GetParam()};
   std::unique_ptr<QuicEncryptedPacket> packet(ConstructMisFramedEncryptedPacket(
       connection_id, false, false, 100, "data", PACKET_8BYTE_CONNECTION_ID,
       PACKET_6BYTE_PACKET_NUMBER, &versions, Perspective::IS_SERVER));
diff --git a/net/tools/quic/quic_time_wait_list_manager.cc b/net/tools/quic/quic_time_wait_list_manager.cc
index beedf3a..1021a03 100644
--- a/net/tools/quic/quic_time_wait_list_manager.cc
+++ b/net/tools/quic/quic_time_wait_list_manager.cc
@@ -93,7 +93,7 @@
 
 void QuicTimeWaitListManager::AddConnectionIdToTimeWait(
     QuicConnectionId connection_id,
-    QuicVersion version,
+    QuicTransportVersion version,
     bool connection_rejected_statelessly,
     std::vector<std::unique_ptr<QuicEncryptedPacket>>* termination_packets) {
   if (connection_rejected_statelessly) {
@@ -127,7 +127,7 @@
   return QuicContainsKey(connection_id_map_, connection_id);
 }
 
-QuicVersion QuicTimeWaitListManager::GetQuicVersionFromConnectionId(
+QuicTransportVersion QuicTimeWaitListManager::GetQuicVersionFromConnectionId(
     QuicConnectionId connection_id) {
   ConnectionIdMap::iterator it = connection_id_map_.find(connection_id);
   DCHECK(it != connection_id_map_.end());
@@ -180,12 +180,13 @@
 
 void QuicTimeWaitListManager::SendVersionNegotiationPacket(
     QuicConnectionId connection_id,
-    const QuicVersionVector& supported_versions,
+    const QuicTransportVersionVector& supported_versions,
     const QuicSocketAddress& server_address,
     const QuicSocketAddress& client_address) {
-  SendOrQueuePacket(QuicMakeUnique<QueuedPacket>(
-      server_address, client_address, QuicFramer::BuildVersionNegotiationPacket(
-                                          connection_id, supported_versions)));
+  SendOrQueuePacket(
+      QuicMakeUnique<QueuedPacket>(server_address, client_address,
+                                   QuicFramer::BuildVersionNegotiationPacket(
+                                       connection_id, supported_versions)));
 }
 
 // Returns true if the number of packets received for this connection_id is a
@@ -309,7 +310,7 @@
 
 QuicTimeWaitListManager::ConnectionIdData::ConnectionIdData(
     int num_packets_,
-    QuicVersion version_,
+    QuicTransportVersion version_,
     QuicTime time_added_,
     bool connection_rejected_statelessly)
     : num_packets(num_packets_),
diff --git a/net/tools/quic/quic_time_wait_list_manager.h b/net/tools/quic/quic_time_wait_list_manager.h
index ff88c6a..ed0b545 100644
--- a/net/tools/quic/quic_time_wait_list_manager.h
+++ b/net/tools/quic/quic_time_wait_list_manager.h
@@ -68,7 +68,7 @@
   // and termination packets are expected.
   virtual void AddConnectionIdToTimeWait(
       QuicConnectionId connection_id,
-      QuicVersion version,
+      QuicTransportVersion version,
       bool connection_rejected_statelessly,
       std::vector<std::unique_ptr<QuicEncryptedPacket>>* termination_packets);
 
@@ -100,8 +100,9 @@
   void TrimTimeWaitListIfNeeded();
 
   // Given a ConnectionId that exists in the time wait list, returns the
-  // QuicVersion associated with it.
-  QuicVersion GetQuicVersionFromConnectionId(QuicConnectionId connection_id);
+  // QuicTransportVersion associated with it.
+  QuicTransportVersion GetQuicVersionFromConnectionId(
+      QuicConnectionId connection_id);
 
   // The number of connections on the time-wait list.
   size_t num_connections() const { return connection_id_map_.size(); }
@@ -110,7 +111,7 @@
   // for |supported_versions| to |client_address| from |server_address|.
   virtual void SendVersionNegotiationPacket(
       QuicConnectionId connection_id,
-      const QuicVersionVector& supported_versions,
+      const QuicTransportVersionVector& supported_versions,
       const QuicSocketAddress& server_address,
       const QuicSocketAddress& client_address);
 
@@ -161,7 +162,7 @@
   // connection_id.
   struct ConnectionIdData {
     ConnectionIdData(int num_packets_,
-                     QuicVersion version_,
+                     QuicTransportVersion version_,
                      QuicTime time_added_,
                      bool connection_rejected_statelessly);
 
@@ -171,7 +172,7 @@
     ~ConnectionIdData();
 
     int num_packets;
-    QuicVersion version;
+    QuicTransportVersion version;
     QuicTime time_added;
     // These packets may contain CONNECTION_CLOSE frames, or SREJ messages.
     std::vector<std::unique_ptr<QuicEncryptedPacket>> termination_packets;
diff --git a/net/tools/quic/quic_time_wait_list_manager_test.cc b/net/tools/quic/quic_time_wait_list_manager_test.cc
index 34e70874..1a1c1b8 100644
--- a/net/tools/quic/quic_time_wait_list_manager_test.cc
+++ b/net/tools/quic/quic_time_wait_list_manager_test.cc
@@ -102,7 +102,7 @@
 
   void AddConnectionId(
       QuicConnectionId connection_id,
-      QuicVersion version,
+      QuicTransportVersion version,
       bool connection_rejected_statelessly,
       std::vector<std::unique_ptr<QuicEncryptedPacket>>* packets) {
     time_wait_list_manager_.AddConnectionIdToTimeWait(
@@ -147,7 +147,7 @@
       const std::tr1::tuple<const char*, int> packet_buffer,
       testing::MatchResultListener* /* listener */) const override {
     FramerVisitorCapturingPublicReset visitor;
-    QuicFramer framer(AllSupportedVersions(), QuicTime::Zero(),
+    QuicFramer framer(AllSupportedTransportVersions(), QuicTime::Zero(),
                       Perspective::IS_CLIENT);
     framer.set_visitor(&visitor);
     QuicEncryptedPacket encrypted(std::tr1::get<0>(packet_buffer),
@@ -192,14 +192,15 @@
 
 TEST_F(QuicTimeWaitListManagerTest, SendVersionNegotiationPacket) {
   std::unique_ptr<QuicEncryptedPacket> packet(
-      QuicFramer::BuildVersionNegotiationPacket(connection_id_,
-                                                AllSupportedVersions()));
+      QuicFramer::BuildVersionNegotiationPacket(
+          connection_id_, AllSupportedTransportVersions()));
   EXPECT_CALL(writer_, WritePacket(_, packet->length(), server_address_.host(),
                                    client_address_, _))
       .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1)));
 
   time_wait_list_manager_.SendVersionNegotiationPacket(
-      connection_id_, AllSupportedVersions(), server_address_, client_address_);
+      connection_id_, AllSupportedTransportVersions(), server_address_,
+      client_address_);
   EXPECT_EQ(0u, time_wait_list_manager_.num_connections());
 }
 
diff --git a/net/tools/quic/stateless_rejector.cc b/net/tools/quic/stateless_rejector.cc
index a0fc1c56..c2ded3b 100644
--- a/net/tools/quic/stateless_rejector.cc
+++ b/net/tools/quic/stateless_rejector.cc
@@ -34,8 +34,8 @@
 };
 
 StatelessRejector::StatelessRejector(
-    QuicVersion version,
-    const QuicVersionVector& versions,
+    QuicTransportVersion version,
+    const QuicTransportVersionVector& versions,
     const QuicCryptoServerConfig* crypto_config,
     QuicCompressedCertsCache* compressed_certs_cache,
     const QuicClock* clock,
@@ -60,7 +60,7 @@
 
 StatelessRejector::~StatelessRejector() {}
 
-void StatelessRejector::OnChlo(QuicVersion version,
+void StatelessRejector::OnChlo(QuicTransportVersion version,
                                QuicConnectionId connection_id,
                                QuicConnectionId server_designated_connection_id,
                                const CryptoHandshakeMessage& message) {
diff --git a/net/tools/quic/stateless_rejector.h b/net/tools/quic/stateless_rejector.h
index adaf7cef..6152d1e 100644
--- a/net/tools/quic/stateless_rejector.h
+++ b/net/tools/quic/stateless_rejector.h
@@ -23,8 +23,8 @@
     REJECTED,     // The CHLO was rejected.
   };
 
-  StatelessRejector(QuicVersion version,
-                    const QuicVersionVector& versions,
+  StatelessRejector(QuicTransportVersion version,
+                    const QuicTransportVersionVector& versions,
                     const QuicCryptoServerConfig* crypto_config,
                     QuicCompressedCertsCache* compressed_certs_cache,
                     const QuicClock* clock,
@@ -36,7 +36,7 @@
   ~StatelessRejector();
 
   // Called when |chlo| is received for |connection_id|.
-  void OnChlo(QuicVersion version,
+  void OnChlo(QuicTransportVersion version,
               QuicConnectionId connection_id,
               QuicConnectionId server_designated_connection_id,
               const CryptoHandshakeMessage& chlo);
@@ -93,8 +93,8 @@
   State state_;
   QuicErrorCode error_;
   std::string error_details_;
-  QuicVersion version_;
-  QuicVersionVector versions_;
+  QuicTransportVersion version_;
+  QuicTransportVersionVector versions_;
   QuicConnectionId connection_id_;
   QuicConnectionId server_designated_connection_id_;
   QuicByteCount chlo_packet_size_;
diff --git a/net/tools/quic/stateless_rejector_test.cc b/net/tools/quic/stateless_rejector_test.cc
index 4e6074b4..67a630b 100644
--- a/net/tools/quic/stateless_rejector_test.cc
+++ b/net/tools/quic/stateless_rejector_test.cc
@@ -51,7 +51,7 @@
 
 // Test various combinations of QUIC version and flag state.
 struct TestParams {
-  QuicVersion version;
+  QuicTransportVersion version;
   FlagsMode flags;
 };
 
@@ -64,7 +64,7 @@
   std::vector<TestParams> params;
   for (FlagsMode flags :
        {ENABLED, STATELESS_DISABLED, CHEAP_DISABLED, BOTH_DISABLED}) {
-    for (QuicVersion version : AllSupportedVersions()) {
+    for (QuicTransportVersion version : AllSupportedTransportVersions()) {
       TestParams param;
       param.version = version;
       param.flags = flags;
@@ -86,7 +86,7 @@
             QuicCompressedCertsCache::kQuicCompressedCertsCacheSize),
         rejector_(QuicMakeUnique<StatelessRejector>(
             GetParam().version,
-            AllSupportedVersions(),
+            AllSupportedTransportVersions(),
             &config_,
             &compressed_certs_cache_,
             &clock_,
diff --git a/net/tools/quic/test_tools/mock_quic_time_wait_list_manager.h b/net/tools/quic/test_tools/mock_quic_time_wait_list_manager.h
index 5e1f5cf..a7e72efd 100644
--- a/net/tools/quic/test_tools/mock_quic_time_wait_list_manager.h
+++ b/net/tools/quic/test_tools/mock_quic_time_wait_list_manager.h
@@ -21,14 +21,14 @@
 
   MOCK_METHOD4(AddConnectionIdToTimeWait,
                void(QuicConnectionId connection_id,
-                    QuicVersion version,
+                    QuicTransportVersion version,
                     bool connection_rejected_statelessly,
                     std::vector<std::unique_ptr<QuicEncryptedPacket>>*
                         termination_packets));
 
   void QuicTimeWaitListManager_AddConnectionIdToTimeWait(
       QuicConnectionId connection_id,
-      QuicVersion version,
+      QuicTransportVersion version,
       bool connection_rejected_statelessly,
       std::vector<std::unique_ptr<QuicEncryptedPacket>>* termination_packets) {
     QuicTimeWaitListManager::AddConnectionIdToTimeWait(
@@ -43,7 +43,7 @@
 
   MOCK_METHOD4(SendVersionNegotiationPacket,
                void(QuicConnectionId connection_id,
-                    const QuicVersionVector& supported_versions,
+                    const QuicTransportVersionVector& supported_versions,
                     const QuicSocketAddress& server_address,
                     const QuicSocketAddress& client_address));
 };
diff --git a/net/tools/quic/test_tools/quic_test_client.cc b/net/tools/quic/test_tools/quic_test_client.cc
index fa81d1f..c6320242 100644
--- a/net/tools/quic/test_tools/quic_test_client.cc
+++ b/net/tools/quic/test_tools/quic_test_client.cc
@@ -49,7 +49,7 @@
       const string& hostname,
       const uint16_t port,
       const string& server_config,
-      QuicVersion quic_version,
+      QuicTransportVersion transport_version,
       QuicStringPiece chlo_hash,
       const std::vector<string>& certs,
       const string& cert_sct,
@@ -83,9 +83,10 @@
       return QUIC_SUCCESS;
     }
 
-    return verifier_->VerifyProof(
-        hostname, port, server_config, quic_version, chlo_hash, certs, cert_sct,
-        signature, context, error_details, details, std::move(callback));
+    return verifier_->VerifyProof(hostname, port, server_config,
+                                  transport_version, chlo_hash, certs, cert_sct,
+                                  signature, context, error_details, details,
+                                  std::move(callback));
   }
 
   QuicAsyncStatus VerifyCertChain(
@@ -164,7 +165,7 @@
 MockableQuicClient::MockableQuicClient(
     QuicSocketAddress server_address,
     const QuicServerId& server_id,
-    const QuicVersionVector& supported_versions,
+    const QuicTransportVersionVector& supported_versions,
     EpollServer* epoll_server)
     : MockableQuicClient(server_address,
                          server_id,
@@ -176,7 +177,7 @@
     QuicSocketAddress server_address,
     const QuicServerId& server_id,
     const QuicConfig& config,
-    const QuicVersionVector& supported_versions,
+    const QuicTransportVersionVector& supported_versions,
     EpollServer* epoll_server)
     : MockableQuicClient(server_address,
                          server_id,
@@ -189,7 +190,7 @@
     QuicSocketAddress server_address,
     const QuicServerId& server_id,
     const QuicConfig& config,
-    const QuicVersionVector& supported_versions,
+    const QuicTransportVersionVector& supported_versions,
     EpollServer* epoll_server,
     std::unique_ptr<ProofVerifier> proof_verifier)
     : QuicClient(
@@ -247,18 +248,20 @@
   mockable_network_helper()->set_track_last_incoming_packet(track);
 }
 
-QuicTestClient::QuicTestClient(QuicSocketAddress server_address,
-                               const string& server_hostname,
-                               const QuicVersionVector& supported_versions)
+QuicTestClient::QuicTestClient(
+    QuicSocketAddress server_address,
+    const string& server_hostname,
+    const QuicTransportVersionVector& supported_versions)
     : QuicTestClient(server_address,
                      server_hostname,
                      QuicConfig(),
                      supported_versions) {}
 
-QuicTestClient::QuicTestClient(QuicSocketAddress server_address,
-                               const string& server_hostname,
-                               const QuicConfig& config,
-                               const QuicVersionVector& supported_versions)
+QuicTestClient::QuicTestClient(
+    QuicSocketAddress server_address,
+    const string& server_hostname,
+    const QuicConfig& config,
+    const QuicTransportVersionVector& supported_versions)
     : client_(new MockableQuicClient(server_address,
                                      QuicServerId(server_hostname,
                                                   server_address.port(),
@@ -269,11 +272,12 @@
   Initialize();
 }
 
-QuicTestClient::QuicTestClient(QuicSocketAddress server_address,
-                               const string& server_hostname,
-                               const QuicConfig& config,
-                               const QuicVersionVector& supported_versions,
-                               std::unique_ptr<ProofVerifier> proof_verifier)
+QuicTestClient::QuicTestClient(
+    QuicSocketAddress server_address,
+    const string& server_hostname,
+    const QuicConfig& config,
+    const QuicTransportVersionVector& supported_versions,
+    std::unique_ptr<ProofVerifier> proof_verifier)
     : client_(new MockableQuicClient(server_address,
                                      QuicServerId(server_hostname,
                                                   server_address.port(),
@@ -358,9 +362,7 @@
   if (stream == nullptr) {
     return 0;
   }
-  if (client()->session()->save_data_before_consumption()) {
-    QuicStreamPeer::set_ack_listener(stream, ack_listener);
-  }
+  QuicStreamPeer::set_ack_listener(stream, ack_listener);
 
   ssize_t ret = 0;
   if (headers != nullptr) {
diff --git a/net/tools/quic/test_tools/quic_test_client.h b/net/tools/quic/test_tools/quic_test_client.h
index cd9fa84..4c76a76 100644
--- a/net/tools/quic/test_tools/quic_test_client.h
+++ b/net/tools/quic/test_tools/quic_test_client.h
@@ -34,19 +34,19 @@
  public:
   MockableQuicClient(QuicSocketAddress server_address,
                      const QuicServerId& server_id,
-                     const QuicVersionVector& supported_versions,
+                     const QuicTransportVersionVector& supported_versions,
                      EpollServer* epoll_server);
 
   MockableQuicClient(QuicSocketAddress server_address,
                      const QuicServerId& server_id,
                      const QuicConfig& config,
-                     const QuicVersionVector& supported_versions,
+                     const QuicTransportVersionVector& supported_versions,
                      EpollServer* epoll_server);
 
   MockableQuicClient(QuicSocketAddress server_address,
                      const QuicServerId& server_id,
                      const QuicConfig& config,
-                     const QuicVersionVector& supported_versions,
+                     const QuicTransportVersionVector& supported_versions,
                      EpollServer* epoll_server,
                      std::unique_ptr<ProofVerifier> proof_verifier);
 
@@ -79,15 +79,15 @@
  public:
   QuicTestClient(QuicSocketAddress server_address,
                  const std::string& server_hostname,
-                 const QuicVersionVector& supported_versions);
+                 const QuicTransportVersionVector& supported_versions);
   QuicTestClient(QuicSocketAddress server_address,
                  const std::string& server_hostname,
                  const QuicConfig& config,
-                 const QuicVersionVector& supported_versions);
+                 const QuicTransportVersionVector& supported_versions);
   QuicTestClient(QuicSocketAddress server_address,
                  const std::string& server_hostname,
                  const QuicConfig& config,
-                 const QuicVersionVector& supported_versions,
+                 const QuicTransportVersionVector& supported_versions,
                  std::unique_ptr<ProofVerifier> proof_verifier);
 
   ~QuicTestClient() override;
diff --git a/net/tools/quic/test_tools/quic_test_server.cc b/net/tools/quic/test_tools/quic_test_server.cc
index c7d7caa6..39d0926 100644
--- a/net/tools/quic/test_tools/quic_test_server.cc
+++ b/net/tools/quic/test_tools/quic_test_server.cc
@@ -97,7 +97,7 @@
     QuicConnection* connection = new QuicConnection(
         id, client, helper(), alarm_factory(), CreatePerConnectionWriter(),
         /* owns_writer= */ true, Perspective::IS_SERVER,
-        GetSupportedVersions());
+        GetSupportedTransportVersions());
 
     QuicServerSessionBase* session = nullptr;
     if (stream_factory_ != nullptr || crypto_stream_factory_ != nullptr) {
@@ -147,10 +147,11 @@
                                QuicHttpResponseCache* response_cache)
     : QuicServer(std::move(proof_source), response_cache) {}
 
-QuicTestServer::QuicTestServer(std::unique_ptr<ProofSource> proof_source,
-                               const QuicConfig& config,
-                               const QuicVersionVector& supported_versions,
-                               QuicHttpResponseCache* response_cache)
+QuicTestServer::QuicTestServer(
+    std::unique_ptr<ProofSource> proof_source,
+    const QuicConfig& config,
+    const QuicTransportVersionVector& supported_versions,
+    QuicHttpResponseCache* response_cache)
     : QuicServer(std::move(proof_source),
                  config,
                  QuicCryptoServerConfig::ConfigOptions(),
diff --git a/net/tools/quic/test_tools/quic_test_server.h b/net/tools/quic/test_tools/quic_test_server.h
index 4679f61..cf22311 100644
--- a/net/tools/quic/test_tools/quic_test_server.h
+++ b/net/tools/quic/test_tools/quic_test_server.h
@@ -62,7 +62,7 @@
                  QuicHttpResponseCache* response_cache);
   QuicTestServer(std::unique_ptr<ProofSource> proof_source,
                  const QuicConfig& config,
-                 const QuicVersionVector& supported_versions,
+                 const QuicTransportVersionVector& supported_versions,
                  QuicHttpResponseCache* response_cache);
 
   // Create a custom dispatcher which creates custom sessions.
diff --git a/net/url_request/url_request_quic_perftest.cc b/net/url_request/url_request_quic_perftest.cc
index 5ca643ef..b5189e4a 100644
--- a/net/url_request/url_request_quic_perftest.cc
+++ b/net/url_request/url_request_quic_perftest.cc
@@ -149,8 +149,8 @@
                                       kHelloAltSvcResponse);
     quic_server_.reset(new QuicSimpleServer(
         test::crypto_test_utils::ProofSourceForTesting(), config,
-        net::QuicCryptoServerConfig::ConfigOptions(), AllSupportedVersions(),
-        &response_cache_));
+        net::QuicCryptoServerConfig::ConfigOptions(),
+        AllSupportedTransportVersions(), &response_cache_));
     int rv = quic_server_->Listen(
         net::IPEndPoint(net::IPAddress::IPv4AllZeros(), kAltSvcPort));
     ASSERT_GE(rv, 0) << "Quic server fails to start";
diff --git a/net/url_request/url_request_quic_unittest.cc b/net/url_request/url_request_quic_unittest.cc
index 7c64304..f8d9bb8 100644
--- a/net/url_request/url_request_quic_unittest.cc
+++ b/net/url_request/url_request_quic_unittest.cc
@@ -134,8 +134,8 @@
         directory.Append(FILE_PATH_LITERAL("quic_test.example.com.key.sct"))));
     server_.reset(new QuicSimpleServer(
         test::crypto_test_utils::ProofSourceForTesting(), config,
-        net::QuicCryptoServerConfig::ConfigOptions(), AllSupportedVersions(),
-        &response_cache_));
+        net::QuicCryptoServerConfig::ConfigOptions(),
+        AllSupportedTransportVersions(), &response_cache_));
     int rv = server_->Listen(
         net::IPEndPoint(net::IPAddress::IPv4AllZeros(), kTestServerPort));
     EXPECT_GE(rv, 0) << "Quic server fails to start";
diff --git a/remoting/host/it2me/BUILD.gn b/remoting/host/it2me/BUILD.gn
index e732fe144..69e9583 100644
--- a/remoting/host/it2me/BUILD.gn
+++ b/remoting/host/it2me/BUILD.gn
@@ -55,10 +55,10 @@
     deps += [
       "//build/config/linux/gtk",
 
-      # GTK pulls pangoft2, which requires HarfBuzz symbols. Since we
-      # link our own HarfBuzz, avoid mixing symbols from system HarfBuzz
-      # and own ones, hence the dependency to harfbuzz-ng here.
-      "//third_party/harfbuzz-ng",
+      # GTK pulls pangoft2, which requires HarfBuzz symbols. When linking
+      # our own HarfBuzz avoid mixing symbols from system HarfBuzz and
+      # our own through the indirect dependency to harfbuzz-ng here.
+      "//third_party:freetype_harfbuzz",
     ]
   }
 }
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h b/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h
index 9dba77cf..1f9b0f3 100644
--- a/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h
+++ b/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h
@@ -68,11 +68,6 @@
   // The callback will be posted on the same thread of the caller.
   void GetVmRegionsForHeapProfiler(RequestGlobalDumpCallback);
 
-  // TODO(hjd): Add a RequestGlobalDump() helper, not bound to tracing.
-  // here. The mojom interface is about to change soon and right now there is
-  // only one client of this API (process_memory_metrics_emitter.cc). Delay this
-  // API and change that only once the cleaned up interface is ready.
-
  private:
   MemoryInstrumentation(service_manager::Connector* connector,
                         const std::string& service_name);
diff --git a/third_party/BUILD.gn b/third_party/BUILD.gn
index 1fa7ac4..7fccf382 100644
--- a/third_party/BUILD.gn
+++ b/third_party/BUILD.gn
@@ -2,9 +2,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-if (is_android) {
-  import("//build/config/android/config.gni")
-}
+import("//build/config/freetype/freetype.gni")
+import("//third_party/harfbuzz-ng/harfbuzz.gni")
 
 assert(!is_ios, "This is not used on iOS, don't drag it in unintentionally")
 
@@ -57,3 +56,21 @@
     public_configs = [ "//third_party/libjpeg:libjpeg_config" ]
   }
 }
+
+# FreeType and HarfBuzz libraries are dependent on each other. This component
+# will depend on the appropriate source sets or export the system packages
+# for both FreeType and HarfBuzz.
+component("freetype_harfbuzz") {
+  public_configs = []
+  public_deps = []
+  if (use_system_freetype) {
+    public_configs += [ "//build/linux:freetype_from_pkgconfig" ]
+  } else {
+    public_deps += [ "//third_party/freetype:freetype_source" ]
+  }
+  if (use_system_harfbuzz) {
+    public_configs += [ "//third_party/harfbuzz-ng:harfbuzz_from_pkgconfig" ]
+  } else {
+    public_deps += [ "//third_party/harfbuzz-ng:harfbuzz_source" ]
+  }
+}
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 9931295..a3e0ad8 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -1736,6 +1736,7 @@
 crbug.com/771729 [ Win Debug ] external/wpt/html/semantics/scripting-1/the-script-element/execution-timing/039.html [ Pass Failure ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 external/wpt/payment-method-basic-card/empty-data-manual.https.html [ Skip ]
 crbug.com/626703 external/wpt/html/semantics/embedded-content/the-iframe-element/sandbox_003-manual.htm [ Skip ]
 crbug.com/626703 external/wpt/html/semantics/embedded-content/the-iframe-element/sandbox_004-manual.htm [ Skip ]
 crbug.com/626703 external/wpt/html/semantics/embedded-content/the-iframe-element/sandbox_006-manual.htm [ Skip ]
diff --git a/third_party/WebKit/LayoutTests/editing/inserting/insertparagraph-seperator-on-non-selectable-node.html b/third_party/WebKit/LayoutTests/editing/inserting/insertparagraph-seperator-on-non-selectable-node.html
new file mode 100644
index 0000000..e882533
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/editing/inserting/insertparagraph-seperator-on-non-selectable-node.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../assert_selection.js"></script>
+<script>
+selection_test(
+    [
+        '<div style="user-select:none">',
+            '<table contenteditable>',
+            '</table>',
+        '</div>'
+    ],
+    selection => {
+       const document = selection.document;
+       // We should set HTML content for this test using innerHTML,
+       // else HTML parser moves '<h1>' outside '<table>'.
+       document.querySelector('table').innerHTML = '<h1>foo</h1><img>bar';
+       const bar = document.querySelector('img').nextSibling;
+       selection.collapse(bar, 3);
+       document.execCommand('insertParagraph');
+    },
+    [
+        '<div style="user-select:none">',
+            '<table contenteditable>',
+            '<h1>foo</h1><img>bar|',
+            '</table>',
+        '</div>'
+    ],
+    'Should not crash when insertParagraph on nonselectable node boundary');
+</script>
+
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
index 1b680648d..cd4af0d 100644
--- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
+++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
@@ -3961,6 +3961,12 @@
      {}
     ]
    ],
+   "payment-method-basic-card/empty-data-manual.https.html": [
+    [
+     "/payment-method-basic-card/empty-data-manual.https.html",
+     {}
+    ]
+   ],
    "payment-request/PaymentAddress/attributes-and-toJSON-method-manual.https.html": [
     [
      "/payment-request/PaymentAddress/attributes-and-toJSON-method-manual.https.html",
@@ -101300,6 +101306,16 @@
      {}
     ]
    ],
+   "html/browsers/browsing-the-web/history-traversal/support/window-name-navigation.sub.html": [
+    [
+     {}
+    ]
+   ],
+   "html/browsers/browsing-the-web/history-traversal/support/window-name-test.sub.html": [
+    [
+     {}
+    ]
+   ],
    "html/browsers/browsing-the-web/history-traversal/unset_context_name.html": [
     [
      {}
@@ -115650,6 +115666,11 @@
      {}
     ]
    ],
+   "payment-method-basic-card/payment-request-canmakepayment-method.https-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "payment-method-id/OWNERS": [
     [
      {}
@@ -118980,16 +119001,6 @@
      {}
     ]
    ],
-   "security/support/window-name-navigation.sub.html": [
-    [
-     {}
-    ]
-   ],
-   "security/support/window-name-test.sub.html": [
-    [
-     {}
-    ]
-   ],
    "selection/OWNERS": [
     [
      {}
@@ -147882,6 +147893,42 @@
      {}
     ]
    ],
+   "html/browsers/browsing-the-web/history-traversal/window-name-after-cross-origin-aux-frame-navigation.sub.html": [
+    [
+     "/html/browsers/browsing-the-web/history-traversal/window-name-after-cross-origin-aux-frame-navigation.sub.html",
+     {}
+    ]
+   ],
+   "html/browsers/browsing-the-web/history-traversal/window-name-after-cross-origin-main-frame-navigation.sub.html": [
+    [
+     "/html/browsers/browsing-the-web/history-traversal/window-name-after-cross-origin-main-frame-navigation.sub.html",
+     {}
+    ]
+   ],
+   "html/browsers/browsing-the-web/history-traversal/window-name-after-cross-origin-sub-frame-navigation.sub.html": [
+    [
+     "/html/browsers/browsing-the-web/history-traversal/window-name-after-cross-origin-sub-frame-navigation.sub.html",
+     {}
+    ]
+   ],
+   "html/browsers/browsing-the-web/history-traversal/window-name-after-same-origin-aux-frame-navigation.sub.html": [
+    [
+     "/html/browsers/browsing-the-web/history-traversal/window-name-after-same-origin-aux-frame-navigation.sub.html",
+     {}
+    ]
+   ],
+   "html/browsers/browsing-the-web/history-traversal/window-name-after-same-origin-main-frame-navigation.sub.html": [
+    [
+     "/html/browsers/browsing-the-web/history-traversal/window-name-after-same-origin-main-frame-navigation.sub.html",
+     {}
+    ]
+   ],
+   "html/browsers/browsing-the-web/history-traversal/window-name-after-same-origin-sub-frame-navigation.sub.html": [
+    [
+     "/html/browsers/browsing-the-web/history-traversal/window-name-after-same-origin-sub-frame-navigation.sub.html",
+     {}
+    ]
+   ],
    "html/browsers/browsing-the-web/navigating-across-documents/001.html": [
     [
      "/html/browsers/browsing-the-web/navigating-across-documents/001.html",
@@ -170392,6 +170439,12 @@
      {}
     ]
    ],
+   "payment-method-basic-card/payment-request-canmakepayment-method.https.html": [
+    [
+     "/payment-method-basic-card/payment-request-canmakepayment-method.https.html",
+     {}
+    ]
+   ],
    "payment-request/PaymentRequestUpdateEvent/constructor.http.html": [
     [
      "/payment-request/PaymentRequestUpdateEvent/constructor.http.html",
@@ -179462,42 +179515,6 @@
      {}
     ]
    ],
-   "security/window-name-after-cross-origin-aux-frame-navigation.sub.html": [
-    [
-     "/security/window-name-after-cross-origin-aux-frame-navigation.sub.html",
-     {}
-    ]
-   ],
-   "security/window-name-after-cross-origin-main-frame-navigation.sub.html": [
-    [
-     "/security/window-name-after-cross-origin-main-frame-navigation.sub.html",
-     {}
-    ]
-   ],
-   "security/window-name-after-cross-origin-sub-frame-navigation.sub.html": [
-    [
-     "/security/window-name-after-cross-origin-sub-frame-navigation.sub.html",
-     {}
-    ]
-   ],
-   "security/window-name-after-same-origin-aux-frame-navigation.sub.html": [
-    [
-     "/security/window-name-after-same-origin-aux-frame-navigation.sub.html",
-     {}
-    ]
-   ],
-   "security/window-name-after-same-origin-main-frame-navigation.sub.html": [
-    [
-     "/security/window-name-after-same-origin-main-frame-navigation.sub.html",
-     {}
-    ]
-   ],
-   "security/window-name-after-same-origin-sub-frame-navigation.sub.html": [
-    [
-     "/security/window-name-after-same-origin-sub-frame-navigation.sub.html",
-     {}
-    ]
-   ],
    "selection/Document-open.html": [
     [
      "/selection/Document-open.html",
@@ -257471,6 +257488,14 @@
    "d049bc03734690b94017819ed70b1104378cc9b4",
    "testharness"
   ],
+  "html/browsers/browsing-the-web/history-traversal/support/window-name-navigation.sub.html": [
+   "79ba1608590fae1fae8aacdf809b00741e101066",
+   "support"
+  ],
+  "html/browsers/browsing-the-web/history-traversal/support/window-name-test.sub.html": [
+   "841e6ebed7f83a59b4942be07452ad5c9b8f6519",
+   "support"
+  ],
   "html/browsers/browsing-the-web/history-traversal/unset_context_name-1.html": [
    "b3aba3e8d9c277aaf30f8cc6860431ba793ab283",
    "testharness"
@@ -257479,6 +257504,30 @@
    "d6a35d1de53be20dd8171b06349edafa4ae32a87",
    "support"
   ],
+  "html/browsers/browsing-the-web/history-traversal/window-name-after-cross-origin-aux-frame-navigation.sub.html": [
+   "16dfcc1f1628c9dab89470a421138ffde85e866a",
+   "testharness"
+  ],
+  "html/browsers/browsing-the-web/history-traversal/window-name-after-cross-origin-main-frame-navigation.sub.html": [
+   "74c59d584d8523ce523a26452767d6212d010234",
+   "testharness"
+  ],
+  "html/browsers/browsing-the-web/history-traversal/window-name-after-cross-origin-sub-frame-navigation.sub.html": [
+   "498803de18a2ac26f3d5bb19a470ad058cefa9ac",
+   "testharness"
+  ],
+  "html/browsers/browsing-the-web/history-traversal/window-name-after-same-origin-aux-frame-navigation.sub.html": [
+   "2b0496b919110cc5996c79afdd420905e1d48ea6",
+   "testharness"
+  ],
+  "html/browsers/browsing-the-web/history-traversal/window-name-after-same-origin-main-frame-navigation.sub.html": [
+   "74ec6353b0b0afa070c745125c09b91d870f38c7",
+   "testharness"
+  ],
+  "html/browsers/browsing-the-web/history-traversal/window-name-after-same-origin-sub-frame-navigation.sub.html": [
+   "8865745d26bee3955927f4c9d35a5174578238ce",
+   "testharness"
+  ],
   "html/browsers/browsing-the-web/navigating-across-documents/.gitkeep": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
@@ -284915,6 +284964,18 @@
    "461dae406c7cdbfcbd2a1a5dc8857e110ed3063e",
    "support"
   ],
+  "payment-method-basic-card/empty-data-manual.https.html": [
+   "f58fecb7d70aac64befe54f403208da14e479b1b",
+   "manual"
+  ],
+  "payment-method-basic-card/payment-request-canmakepayment-method.https-expected.txt": [
+   "da4907d81ce5375d90c80196b63aca3b44748627",
+   "support"
+  ],
+  "payment-method-basic-card/payment-request-canmakepayment-method.https.html": [
+   "70f2de7b94ca8e22fdbfed6d39f6f1627b5bf3b0",
+   "testharness"
+  ],
   "payment-method-id/OWNERS": [
    "fe5d51777dc0535512489f19477962766fec6d08",
    "support"
@@ -294071,38 +294132,6 @@
    "c9b3ac77b8c62131dbe0f7228071fc6bf5e5e838",
    "support"
   ],
-  "security/support/window-name-navigation.sub.html": [
-   "f5e1ec7b0626f7f007bc75b66504bcc4ec47d4f2",
-   "support"
-  ],
-  "security/support/window-name-test.sub.html": [
-   "841e6ebed7f83a59b4942be07452ad5c9b8f6519",
-   "support"
-  ],
-  "security/window-name-after-cross-origin-aux-frame-navigation.sub.html": [
-   "16dfcc1f1628c9dab89470a421138ffde85e866a",
-   "testharness"
-  ],
-  "security/window-name-after-cross-origin-main-frame-navigation.sub.html": [
-   "74c59d584d8523ce523a26452767d6212d010234",
-   "testharness"
-  ],
-  "security/window-name-after-cross-origin-sub-frame-navigation.sub.html": [
-   "498803de18a2ac26f3d5bb19a470ad058cefa9ac",
-   "testharness"
-  ],
-  "security/window-name-after-same-origin-aux-frame-navigation.sub.html": [
-   "2b0496b919110cc5996c79afdd420905e1d48ea6",
-   "testharness"
-  ],
-  "security/window-name-after-same-origin-main-frame-navigation.sub.html": [
-   "74ec6353b0b0afa070c745125c09b91d870f38c7",
-   "testharness"
-  ],
-  "security/window-name-after-same-origin-sub-frame-navigation.sub.html": [
-   "8865745d26bee3955927f4c9d35a5174578238ce",
-   "testharness"
-  ],
   "selection/Document-open.html": [
    "31a5ee7a3619c62dbd35eafb66725bf4192639a0",
    "testharness"
@@ -298492,7 +298521,7 @@
    "testharness"
   ],
   "trusted-types/block-string-assignment-to-location-href.tentative.html": [
-   "63a9b411400a2b7c93d36e2e7a293cbf8d341a91",
+   "b4da566f7eab26c9156e7976714618c74fd405b0",
    "testharness"
   ],
   "trusted-types/block-string-assignment-to-outerHTML.tentative.html": [
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-method-basic-card/empty-data-manual.https.html b/third_party/WebKit/LayoutTests/external/wpt/payment-method-basic-card/empty-data-manual.https.html
new file mode 100644
index 0000000..692f31e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/payment-method-basic-card/empty-data-manual.https.html
@@ -0,0 +1,139 @@
+<!doctype html>
+<meta charset="utf8">
+<title>Payment Method Basic Card - test passing empty BasicCardRequest members</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+setup({ explicit_done: true, explicit_timeout: true });
+
+const amount = { value: "1.0", currency: "USD" };
+const details = {
+  total: {
+    label: "Total",
+    amount,
+  },
+};
+const method = {
+  supportedMethods: "basic-card",
+};
+
+const defaultBillingAddress = {
+  country: 'AF',
+  addressLine: '1 wpt street',
+  region: '',
+  city: 'Kabul',
+  dependentLocality: '',
+  postalCode: '1001',
+  sortingCode: '',
+  languageCode: 'fa',
+  organization: 'w3c',
+  recipient: 'web platform test',
+  phone: '+93555555555',
+};
+
+const visaCredit = {
+  cardNumber: "4111111111111111",
+  cardSecurityCode: "123",
+  cardholderName: "web platform test",
+  expiryMonth: "01",
+  expiryYear: "2026",
+};
+
+async function getCardResponse(data) {
+  const method = Object.assign({ data }, methodCard);
+  const response = await new PaymentRequest([method], defaultDetails).show();
+  await response.complete("success");
+  return response.details;
+}
+
+/**
+ * All tests expect the same return data, so we can just check the
+ * same result over and over again.
+ */
+function runPromiseTest(button, data, expectedCard = visaCredit, expectedAddress = defaultBillingAddress ) {
+  button.disabled = true;
+  promise_test(async () => {
+    const card = await getCardResponse(data);
+    for (const [member, expectedValue] of Object.entries(expectedCard)) {
+      const msg = `Expected card.${member} to equal ${expectedValue}.`;
+      assert_equals(card[member], expectedValue, msg);
+    }
+    const { billingAddress } = card;
+    for (const [member, expectedValue] of Object.entries(expectedAddress)) {
+      const msg = `billingAddress.${member} to equal ${expectedValue}.`;
+      assert_equals(billingAddress[member], expectedValue);
+    }
+  }, button.textContent.trim());
+}
+</script>
+<h2>
+  Payment Method Basic Card - test passing empty BasicCardRequest values
+</h2>
+<p>
+  This test checks that the Basic Card payment handler can accept any card.
+</p>
+<p>
+  Click on each button in sequence from top to bottom without refreshing the page.
+  Each button will bring up the Payment Request UI window.
+  The test expects the following credit card.
+</p>
+<ol>
+  <li>Add credit card:
+    <dl>
+      <dt>Cardholder name:</dt>
+      <dd>web platform test</dd>
+      <dt>Card number:</dt>
+      <dd>4111111111111111</dd>
+      <dt>Security code (CVV):</dt>
+      <dd>123</dd>
+      <dt>Expiry month:</dt>
+      <dd>01</dd>
+      <dt>Expiry year:</dt>
+      <dd>2026</dd>
+    </dl>
+  </li>
+  <li>Add billing address:
+    <dl>
+      <dt>Recipient:</dt>
+      <dd>web platform test</dd>
+      <dt>Address:</dt>
+      <dd>1 web st</dd>
+      <dt>Post code:</dt>
+      <dd>1234</dd>
+      <dt>Country:</dt>
+      <dd>Afghanistan</dd>
+      <dt>City:</dt>
+      <dd>w3c</dd>
+      <dt>Phone</dt>
+      <dd>+12345678910</dd>
+    </dl>
+  </li>
+</ol>
+<hr>
+<ol>
+  <li>
+    <button onclick="runPromiseTest(this, {});">
+      When passed BasicCardRequest without members, allow the user to input of any credit card type.
+    </button>
+  </li>
+  <li>
+    <button onclick="runPromiseTest(this, { supportedNetworks: [], supportedTypes: [] });">
+      Returns any card type on any network, because zero length supportedNetworks and supportedTypes.
+    </button>
+  </li>
+  <li>
+    <button onclick="runPromiseTest(this, { supportedNetworks: [] });">
+      Returns any card type on any network, because supportedNetworks is missing and supportedTypes is empty.
+    </button>
+  </li>
+  <li>
+    <button onclick="runPromiseTest(this, { supportedTypes: [] });">
+      Returns any card type on any network missing supportedTypes, and empty supportedNetwork.
+    </button>
+  </li>
+</ol>
+
+<small>
+  If you find a buggy test, please <a href="https://github.com/w3c/web-platform-tests/issues">file a bug</a>
+  and tag one of the <a href="https://github.com/w3c/web-platform-tests/blob/master/payment-request/OWNERS">owners</a>.
+</small>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-method-basic-card/payment-request-canmakepayment-method.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/payment-method-basic-card/payment-request-canmakepayment-method.https-expected.txt
new file mode 100644
index 0000000..d5d09362
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/payment-method-basic-card/payment-request-canmakepayment-method.https-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+FAIL Must return false when the PMI is not supported at by the user agent. promise_test: Unhandled rejection with value: object "UnknownError: Request failed"
+FAIL Must return true when basic-card is amongst unsupported PMIs. promise_test: Unhandled rejection with value: object "UnknownError: Request failed"
+FAIL If basic-card is supported, then return a promise that resolves to true. assert_equals: if it throws, then it must be a NotAllowedError. expected "NotAllowedError" but got "UnknownError"
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-method-basic-card/payment-request-canmakepayment-method.https.html b/third_party/WebKit/LayoutTests/external/wpt/payment-method-basic-card/payment-request-canmakepayment-method.https.html
new file mode 100644
index 0000000..a89c63b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/payment-method-basic-card/payment-request-canmakepayment-method.https.html
@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<!-- Copyright © 2017 World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
+<meta charset="utf-8">
+<title>Payment Method Basic Card: Tests that basic card is a supported method</title>
+<link rel="help" href="https://w3c.github.io/browser-payment-api/#show-method">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+const basicCard = Object.freeze({ supportedMethods: "basic-card", data: {} });
+const defaultMethods = Object.freeze([basicCard]);
+const defaultDetails = Object.freeze({
+  total: {
+    label: "Total",
+    amount: {
+      currency: "USD",
+      value: "1.00",
+    },
+  },
+});
+
+const notSupportedMethod = Object.freeze({
+  supportedMethods: "this-is-not-supported",
+});
+
+promise_test(async t => {
+  const request = new PaymentRequest([notSupportedMethod], defaultDetails);
+  assert_false(
+    await request.canMakePayment(),
+    `canMakePaymentPromise should be false`
+  );
+}, `Must return false when the PMI is not supported at by the user agent.`);
+
+function* pmiGenerator(howMany = 256) {
+  for (i = 0; i < howMany; i++) {
+    yield {
+      supportedMethods: `this-is-not-supported-${i}`,
+      data: { key: "value" },
+    };
+  }
+}
+
+promise_test(async t => {
+  //Smoke test
+  const canMakePaymentPromise = new PaymentRequest(
+    [notSupportedMethod],
+    defaultDetails
+  ).canMakePayment();
+  assert_false(
+    await canMakePaymentPromise,
+    "Expected canMakePaymentPromise smoke test to resolve with false"
+  );
+  // Actual test - Make a big array with random PMIs,
+  // put basic-card in the middle of it!
+  const pmis = []
+    .concat(Array.from(pmiGenerator(250)))
+    .concat(basicCard)
+    .concat(Array.from(pmiGenerator(250)));
+  const request = new PaymentRequest(pmis, defaultDetails);
+  assert_true(
+    await request.canMakePayment(),
+    `canMakePaymentPromise should be true, because basic-card is present`
+  );
+}, `Must return true when basic-card is amongst unsupported PMIs.`);
+
+promise_test(async t => {
+  const request = new PaymentRequest(defaultMethods, defaultDetails);
+  try {
+    assert_true(
+      await request.canMakePayment(),
+      `canMakePaymentPromise must resolve to true`
+    );
+    assert_true(
+      await request.canMakePayment(),
+      `canMakePaymentPromise must resolve to true`
+    );
+    // try to trigger optional behavior
+    for (let i = 0; i < 1024; i++) {
+      const temp = new PaymentRequest(defaultMethods, defaultDetails);
+      await Promise.all([temp.canMakePayment(), request.canMakePayment()]);
+    }
+  } catch (err) {
+    assert_equals(
+      err.name,
+      "NotAllowedError",
+      "if it throws, then it must be a NotAllowedError."
+    );
+  }
+}, `If basic-card is supported, then return a promise that resolves to true.`);
+</script>
diff --git a/third_party/WebKit/Source/core/editing/commands/InsertParagraphSeparatorCommand.cpp b/third_party/WebKit/Source/core/editing/commands/InsertParagraphSeparatorCommand.cpp
index fc19695..53a7c1ba 100644
--- a/third_party/WebKit/Source/core/editing/commands/InsertParagraphSeparatorCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/InsertParagraphSeparatorCommand.cpp
@@ -463,9 +463,12 @@
   // want to make sure we include all of the correct nodes when building the
   // ancestor list. So this needs to be the deepest representation of the
   // position before we walk the DOM tree.
-  insertion_position = PositionOutsideTabSpan(
-      CreateVisiblePosition(insertion_position).DeepEquivalent());
+  VisiblePosition visible_insertion_position =
+      CreateVisiblePosition(insertion_position);
+  ABORT_EDITING_COMMAND_IF(visible_insertion_position.IsNull());
 
+  insertion_position =
+      PositionOutsideTabSpan(visible_insertion_position.DeepEquivalent());
   // If the returned position lies either at the end or at the start of an
   // element that is ignored by editing we should move to its upstream or
   // downstream position.
diff --git a/third_party/WebKit/Source/platform/BUILD.gn b/third_party/WebKit/Source/platform/BUILD.gn
index 6796efe..1a1e1d57 100644
--- a/third_party/WebKit/Source/platform/BUILD.gn
+++ b/third_party/WebKit/Source/platform/BUILD.gn
@@ -1521,6 +1521,7 @@
     "//mojo/public/cpp/bindings",
     "//mojo/public/cpp/bindings:wtf_support",
     "//services/service_manager/public/cpp",
+    "//third_party:freetype_harfbuzz",
     "//third_party/WebKit/Source/platform/heap",
     "//third_party/WebKit/Source/platform/instrumentation",
     "//third_party/WebKit/Source/platform/loader",
@@ -1529,7 +1530,6 @@
     "//third_party/WebKit/public:mojo_bindings_blink",
     "//third_party/WebKit/public:offscreen_canvas_mojo_bindings_blink",
     "//third_party/ced",
-    "//third_party/harfbuzz-ng",
     "//third_party/icu",
     "//ui/gfx",
     "//ui/gfx/geometry",
@@ -1945,11 +1945,11 @@
     "//skia",
     "//testing/gmock",
     "//testing/gtest",
+    "//third_party:freetype_harfbuzz",
     "//third_party/WebKit/Source/platform/instrumentation:unit_tests",
     "//third_party/WebKit/Source/platform/loader:unit_tests",
     "//third_party/WebKit/Source/platform/scheduler:unit_tests",
     "//third_party/WebKit/Source/platform/wtf",
-    "//third_party/harfbuzz-ng",
     "//ui/gfx",
     "//ui/gfx/geometry",
     "//ui/gfx/geometry/mojo:test_interfaces_blink",
diff --git a/third_party/WebKit/Source/platform/fonts/WebFontDecoder.cpp b/third_party/WebKit/Source/platform/fonts/WebFontDecoder.cpp
index db44ba1..8679d3e 100644
--- a/third_party/WebKit/Source/platform/fonts/WebFontDecoder.cpp
+++ b/third_party/WebKit/Source/platform/fonts/WebFontDecoder.cpp
@@ -38,10 +38,10 @@
 #include "platform/instrumentation/tracing/TraceEvent.h"
 #include "platform/wtf/CurrentTime.h"
 #include "public/platform/Platform.h"
-#include "third_party/harfbuzz-ng/src/hb.h"
 #include "third_party/ots/include/ots-memory-stream.h"
 #include "third_party/skia/include/core/SkStream.h"
 
+#include <hb.h>
 #include <stdarg.h>
 
 namespace blink {
diff --git a/third_party/freetype/BUILD.gn b/third_party/freetype/BUILD.gn
index 0dbb1c6..4d84fbf1 100644
--- a/third_party/freetype/BUILD.gn
+++ b/third_party/freetype/BUILD.gn
@@ -6,6 +6,8 @@
 import("//build/config/freetype/freetype.gni")
 import("//third_party/harfbuzz-ng/harfbuzz.gni")
 
+assert(!use_system_freetype, "Not used when using system freetype.")
+
 config("freetype_config") {
   include_dirs = [
     "include",
@@ -23,32 +25,39 @@
   }
 }
 
-# This component is used to resolve a cyclic dependency between HarfBuzz and
-# FreeType. HarfBuzz needs basic FreeType glyph information symbols for its
-# hb-ft.* functions, FreeType needs HarfBuzz' OpenType parsing functionality in
-# the autohinting code. We start by building a minimum FreeType here - enough to
-# satisfy harfbuzz-ng-ft symbol requirements. Then we can build harfbuzz-ng-ft
-# based on the minimal FreeType and harfbuzz-ng which does not depend on
-# FreeType itself. Then we build FreeType depending on harfbuzz-ng-ft and
-# harfbuzz-ng.
-static_library("bootstrap_freetype_for_harfbuzz") {
-  visibility = [
-    "//third_party/harfbuzz-ng:harfbuzz-ng-ft",
-    ":freetype",
-  ]
+source_set("freetype_source") {
+  visibility = [ "//third_party:freetype_harfbuzz" ]
 
   defines = []
+  include_dirs = []
 
   sources = [
     "include/freetype-custom-config/ftconfig.h",
     "include/freetype-custom-config/ftmodule.h",
     "include/freetype-custom-config/ftoption.h",
+    "src/src/autofit/autofit.c",
     "src/src/base/ftbase.c",
+    "src/src/base/ftbbox.c",
     "src/src/base/ftbitmap.c",
+    "src/src/base/ftfntfmt.c",
+    "src/src/base/ftfstype.c",
+    "src/src/base/ftgasp.c",
+    "src/src/base/ftglyph.c",
+    "src/src/base/ftinit.c",
+    "src/src/base/ftlcdfil.c",
+    "src/src/base/ftmm.c",
+    "src/src/base/ftstroke.c",
+    "src/src/base/fttype1.c",
+    "src/src/cff/cff.c",
+    "src/src/gzip/ftgzip.c",
+    "src/src/pshinter/pshinter.c",
+    "src/src/psnames/psnames.c",
+    "src/src/raster/raster.c",
+    "src/src/sfnt/sfnt.c",
+    "src/src/smooth/smooth.c",
+    "src/src/truetype/truetype.c",
   ]
 
-  include_dirs = []
-
   # ftsystem.c provides implementations of FT_Memory and FT_Stream_Open.
   # While Chromium itself avoids using this code, any build of Chromium which
   # depends on //third_party/fontconfig:fontconfig with use_bundled_fontconfig
@@ -71,68 +80,6 @@
     sources += [ "src/src/base/ftsystem.c" ]
   }
 
-  if (is_mac && !is_component_build) {
-    defines += [ "MAC_RESTRICT_VISIBILITY" ]
-  }
-
-  defines += [
-    "FT2_BUILD_LIBRARY",
-    "DARWIN_NO_CARBON",
-
-    # Long directory name to avoid accidentally using wrong headers.
-    # GN currently does not escape '<' and '>' when generating xml based Visual
-    # Studio project files. As a result, use quotes instead of pointy brackets
-    # in these defines.
-    "FT_CONFIG_CONFIG_H=\"freetype-custom-config/ftconfig.h\"",
-    "FT_CONFIG_MODULES_H=\"freetype-custom-config/ftmodule.h\"",
-    "FT_CONFIG_OPTIONS_H=\"freetype-custom-config/ftoption.h\"",
-  ]
-
-  if (is_win && is_component_build) {
-    # Used for managing declspec(dllimport/export) visibility.
-    defines += [ "FT2_BUILD_DLL" ]
-  }
-
-  public_configs = [ ":freetype_config" ]
-  configs -= [ "//build/config/compiler:chromium_code" ]
-  configs += [ "//build/config/compiler:no_chromium_code" ]
-
-  configs += [ ":freetype-warnings" ]
-}
-
-component("freetype") {
-  if (is_linux) {
-    output_name = "freetype"
-    output_extension = "so.6"
-  }
-
-  defines = []
-
-  sources = [
-    "include/freetype-custom-config/ftconfig.h",
-    "include/freetype-custom-config/ftmodule.h",
-    "include/freetype-custom-config/ftoption.h",
-    "src/src/autofit/autofit.c",
-    "src/src/base/ftbbox.c",
-    "src/src/base/ftfntfmt.c",
-    "src/src/base/ftfstype.c",
-    "src/src/base/ftgasp.c",
-    "src/src/base/ftglyph.c",
-    "src/src/base/ftinit.c",
-    "src/src/base/ftlcdfil.c",
-    "src/src/base/ftmm.c",
-    "src/src/base/ftstroke.c",
-    "src/src/base/fttype1.c",
-    "src/src/cff/cff.c",
-    "src/src/gzip/ftgzip.c",
-    "src/src/pshinter/pshinter.c",
-    "src/src/psnames/psnames.c",
-    "src/src/raster/raster.c",
-    "src/src/sfnt/sfnt.c",
-    "src/src/smooth/smooth.c",
-    "src/src/truetype/truetype.c",
-  ]
-
   if (!is_android) {
     sources += [
       "src/src/cid/type1cid.c",
@@ -183,29 +130,19 @@
     defines += [ "FT2_BUILD_DLL" ]
   }
 
-  public_configs = [ ":freetype_config" ]
+  if (use_system_harfbuzz) {
+    configs += [ "//third_party/harfbuzz-ng:harfbuzz_from_pkgconfig" ]
+  } else {
+    configs += [ "//third_party/harfbuzz-ng:harfbuzz_config" ]
+  }
   configs -= [ "//build/config/compiler:chromium_code" ]
   configs += [ "//build/config/compiler:no_chromium_code" ]
-
   configs += [ ":freetype-warnings" ]
 
+  public_configs = [ ":freetype_config" ]
+
   deps = [
     "//third_party/libpng",
     "//third_party/zlib",
   ]
-
-  if (!use_system_freetype) {
-    deps += [ ":bootstrap_freetype_for_harfbuzz" ]
-  }
-
-  if (!use_system_harfbuzz) {
-    if (!is_android) {
-      # See "WITHOUT_HARFBUZZ" above, harfbuzz-ng-ft is only needed if we build
-      # FreeType with HarfBuzz support.
-      deps += [ "//third_party/harfbuzz-ng:harfbuzz-ng-ft" ]
-    }
-    deps += [ "//third_party/harfbuzz-ng:harfbuzz-ng-without-freetype" ]
-  } else {
-    deps += [ "//third_party/harfbuzz-ng:harfbuzz-ng" ]
-  }
 }
diff --git a/third_party/harfbuzz-ng/BUILD.gn b/third_party/harfbuzz-ng/BUILD.gn
index 174bf239..d2ff8749 100644
--- a/third_party/harfbuzz-ng/BUILD.gn
+++ b/third_party/harfbuzz-ng/BUILD.gn
@@ -5,31 +5,21 @@
 import("//build/config/chrome_build.gni")
 import("//build/config/features.gni")
 import("//build/config/freetype/freetype.gni")
-import("//build/config/linux/pkg_config.gni")
 import("//build/config/ui.gni")
 import("//testing/libfuzzer/fuzzer_test.gni")
 import("//third_party/harfbuzz-ng/harfbuzz.gni")
 
 if (use_system_harfbuzz) {
   import("//build/config/linux/pkg_config.gni")
-  pkg_config("harfbuzz_pkgconfig") {
+  pkg_config("harfbuzz_from_pkgconfig") {
+    visibility = [
+      "//third_party:freetype_harfbuzz",
+      "//third_party/freetype:freetype_source",
+    ]
     packages = [ "harfbuzz" ]
   }
-  group("harfbuzz-ng") {
-    public_configs = [ ":harfbuzz_pkgconfig" ]
-  }
 } else {
-  # The :harfbuzz-ng target combines the staged build steps required to resolve
-  # the cyclic dependency between parts of FreeType and HarfBuzz.
-  group("harfbuzz-ng") {
-    public_deps = [
-      ":harfbuzz-ng-ft",
-      ":harfbuzz-ng-without-freetype",
-      "//build/config/freetype",
-    ]
-  }
-
-  config("harfbuzz-ng_config") {
+  config("harfbuzz_config") {
     include_dirs = [ "src" ]
   }
 
@@ -51,7 +41,9 @@
     }
   }
 
-  static_library("harfbuzz-ng-without-freetype") {
+  source_set("harfbuzz_source") {
+    visibility = [ "//third_party:freetype_harfbuzz" ]
+
     sources = [
       "src/hb-atomic-private.hh",
       "src/hb-blob.cc",
@@ -72,6 +64,8 @@
       "src/hb-font-private.hh",
       "src/hb-font.cc",
       "src/hb-font.h",
+      "src/hb-ft.cc",
+      "src/hb-ft.h",
       "src/hb-icu.cc",
       "src/hb-icu.h",
       "src/hb-mutex-private.hh",
@@ -156,11 +150,6 @@
       "src/hb.h",
     ]
 
-    if (is_component_build && !is_win) {
-      configs -= [ "//build/config/gcc:symbol_visibility_hidden" ]
-      configs += [ "//build/config/gcc:symbol_visibility_default" ]
-    }
-
     defines = [
       "HAVE_OT",
       "HAVE_ICU",
@@ -168,6 +157,20 @@
       "HAVE_INTEL_ATOMIC_PRIMITIVES",
     ]
 
+    if (is_component_build) {
+      if (is_win) {
+        defines += [ "HB_EXTERN=__declspec (dllexport) extern" ]
+      } else {
+        configs -= [ "//build/config/gcc:symbol_visibility_hidden" ]
+        configs += [ "//build/config/gcc:symbol_visibility_default" ]
+      }
+    }
+
+    if (use_system_freetype) {
+      configs += [ "//build/linux:freetype_from_pkgconfig" ]
+    } else {
+      configs += [ "//third_party/freetype:freetype_config" ]
+    }
     configs -= [ "//build/config/compiler:chromium_code" ]
     configs += [
       "//build/config/compiler:no_chromium_code",
@@ -176,7 +179,7 @@
       # correctly.
       ":harfbuzz_warnings",
     ]
-    public_configs = [ ":harfbuzz-ng_config" ]
+    public_configs = [ ":harfbuzz_config" ]
 
     deps = [
       "//third_party/icu:icuuc",
@@ -203,45 +206,6 @@
       ]
     }
   }
-
-  static_library("harfbuzz-ng-ft") {
-    sources = [
-      "src/hb-ft.cc",
-      "src/hb-ft.h",
-    ]
-
-    if (is_component_build && !is_win) {
-      configs -= [ "//build/config/gcc:symbol_visibility_hidden" ]
-      configs += [ "//build/config/gcc:symbol_visibility_default" ]
-    }
-
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [
-      "//build/config/compiler:no_chromium_code",
-
-      # Must be after no_chromium_code for warning flags to be ordered
-      # correctly.
-      ":harfbuzz_warnings",
-    ]
-    public_configs = [ ":harfbuzz-ng_config" ]
-
-    defines = [
-      "HAVE_OT",
-      "HAVE_ICU",
-      "HAVE_ICU_BUILTIN",
-      "HAVE_INTEL_ATOMIC_PRIMITIVES",
-    ]
-
-    if (use_system_freetype) {
-      deps = [
-        "//build/config/freetype:freetype",
-      ]
-    } else {
-      deps = [
-        "//third_party/freetype:bootstrap_freetype_for_harfbuzz",
-      ]
-    }
-  }
 }
 
 fuzzer_test("harfbuzz_fuzzer") {
@@ -249,7 +213,7 @@
     "fuzz/harfbuzz_fuzzer.cc",
   ]
   deps = [
-    ":harfbuzz-ng",
+    "//third_party:freetype_harfbuzz",
   ]
   libfuzzer_options = [ "max_len=16800" ]
   seed_corpus = "fuzz/seed_corpus"
diff --git a/ui/gfx/BUILD.gn b/ui/gfx/BUILD.gn
index 4dfc958..862de17 100644
--- a/ui/gfx/BUILD.gn
+++ b/ui/gfx/BUILD.gn
@@ -302,7 +302,7 @@
   } else {
     deps += [
       "//cc/paint",
-      "//third_party/harfbuzz-ng",
+      "//third_party:freetype_harfbuzz",
     ]
   }
 
@@ -712,10 +712,6 @@
     sources += [ "paint_vector_icon_unittest.cc" ]
   }
 
-  if (!is_android && !is_ios) {
-    sources += [ "render_text_unittest.cc" ]
-  }
-
   # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
   configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
 
@@ -736,6 +732,11 @@
     "//ui/resources:ui_test_pak",
   ]
 
+  if (!is_android && !is_ios) {
+    sources += [ "render_text_unittest.cc" ]
+    deps += [ "//third_party:freetype_harfbuzz" ]
+  }
+
   data_deps = [
     "//ui/resources:ui_test_pak",
   ]
diff --git a/ui/gfx/harfbuzz_font_skia.h b/ui/gfx/harfbuzz_font_skia.h
index bdf6dc12..abc6c79 100644
--- a/ui/gfx/harfbuzz_font_skia.h
+++ b/ui/gfx/harfbuzz_font_skia.h
@@ -5,11 +5,12 @@
 #ifndef UI_GFX_HARFBUZZ_FONT_SKIA_H_
 #define UI_GFX_HARFBUZZ_FONT_SKIA_H_
 
-#include "third_party/harfbuzz-ng/src/hb.h"
 #include "third_party/skia/include/core/SkRefCnt.h"
 #include "third_party/skia/include/core/SkScalar.h"
 #include "ui/gfx/font_render_params.h"
 
+#include <hb.h>
+
 class SkTypeface;
 
 namespace gfx {
diff --git a/ui/gfx/render_text_harfbuzz.cc b/ui/gfx/render_text_harfbuzz.cc
index 89ef8e8..108b3b3 100644
--- a/ui/gfx/render_text_harfbuzz.cc
+++ b/ui/gfx/render_text_harfbuzz.cc
@@ -20,7 +20,6 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/trace_event/trace_event.h"
 #include "build/build_config.h"
-#include "third_party/harfbuzz-ng/src/hb.h"
 #include "third_party/icu/source/common/unicode/ubidi.h"
 #include "third_party/icu/source/common/unicode/utf16.h"
 #include "third_party/skia/include/core/SkColor.h"
@@ -38,6 +37,8 @@
 #include "ui/gfx/text_utils.h"
 #include "ui/gfx/utf16_indexing.h"
 
+#include <hb.h>
+
 namespace gfx {
 
 namespace {
diff --git a/ui/gfx/render_text_harfbuzz.h b/ui/gfx/render_text_harfbuzz.h
index f0b190f..40d0ab4 100644
--- a/ui/gfx/render_text_harfbuzz.h
+++ b/ui/gfx/render_text_harfbuzz.h
@@ -12,11 +12,12 @@
 #include <vector>
 
 #include "base/macros.h"
-#include "third_party/harfbuzz-ng/src/hb.h"
 #include "third_party/icu/source/common/unicode/ubidi.h"
 #include "third_party/icu/source/common/unicode/uscript.h"
 #include "ui/gfx/render_text.h"
 
+#include <hb.h>
+
 namespace base {
 namespace i18n {
 class BreakIterator;