diff --git a/.gn b/.gn
index 3a7b224f..b2b3f3b 100644
--- a/.gn
+++ b/.gn
@@ -344,8 +344,7 @@
   "//third_party/android_swipe_refresh/*",
   "//third_party/android_system_sdk/*",
   "//third_party/android_testrunner/*",
-
-  # "//third_party/angle/*",  # 30ish errors
+  "//third_party/angle/*",
   "//third_party/apache-portable-runtime/*",
   "//third_party/apache_velocity/*",
   "//third_party/apache-win32/*",
diff --git a/DEPS b/DEPS
index 2908ff67d..916e697 100644
--- a/DEPS
+++ b/DEPS
@@ -162,11 +162,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '8ef18d359b2666828957c4c6f03f2ddfa8ce266c',
+  'skia_revision': '6e637472ebf3735e217df25c12d54930485a6e2d',
   # 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': 'a7cf9c5c1f51db3b7e9efda13edee844686dc6e2',
+  'v8_revision': '69d20d247f62a3378d15ce0956ed8bf9665e6a44',
   # 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.
@@ -174,11 +174,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': '2c5d48a6f0e43c5a688ad85716f318ca1a9e957e',
+  'angle_revision': '791ad7b8774a06c996467eb9e6e5137b1e4ef452',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
-  'swiftshader_revision': '18c9ac4971176658d2f9f13a043fe93c183556d8',
+  'swiftshader_revision': '39a9f1bdcd0eb45cb8813993ae0221b672afaa1c',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
@@ -225,7 +225,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '9e1c92c073c95229717afb53a96ef3dfbdfc2400',
+  'catapult_revision': '9f64c5cb4902fa548e2b52aba1c44951f9fdc071',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -297,11 +297,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': 'adbecedad5e09a829fcc43fc42cc9ff457d1a1ad',
+  'dawn_revision': '824424fa351be2b2eccd78b2f31de1d5d1ad4183',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'quiche_revision': '28315b77c94c06e419bc8e6cddedce71884cbf4d',
+  'quiche_revision': '45f8f861073d321294d735c077b67fddb5ba2cee',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ios_webkit
   # and whatever else without interference from each other.
@@ -867,7 +867,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '17016be940adee622232217f60df423ad555e82c',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '355e97e300e8baceae8353287ad59b915dbb8196',
 
   'src/third_party/devtools-node-modules':
     Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'),
@@ -1414,7 +1414,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'abaae129d9a0c6e1e092067e0b105475df43352e',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '8b14b0dea605d22c0886a02b1c78b9d01f0946cc',
+    Var('webrtc_git') + '/src.git' + '@' + 'ce6a0c8fb3f3a19caa797d5913b7e7c8ecf3ca9b',
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
@@ -1455,7 +1455,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@408dc11ec29e2f55dd1d072097f07cc943684adf',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@0b598b6e8d5bdac89f62b6108f29c6de5e94ffc8',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/ash/wm/desks/desks_controller.cc b/ash/wm/desks/desks_controller.cc
index e648d80..01177a4 100644
--- a/ash/wm/desks/desks_controller.cc
+++ b/ash/wm/desks/desks_controller.cc
@@ -8,6 +8,7 @@
 
 #include "ash/accessibility/accessibility_controller_impl.h"
 #include "ash/public/cpp/shell_window_ids.h"
+#include "ash/session/session_controller_impl.h"
 #include "ash/shell.h"
 #include "ash/strings/grit/ash_strings.h"
 #include "ash/wm/desks/desk.h"
@@ -24,6 +25,7 @@
 #include "base/containers/unique_ptr_adapters.h"
 #include "base/logging.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/numerics/ranges.h"
 #include "base/stl_util.h"
 #include "ui/aura/window_tree_host.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -171,7 +173,8 @@
   }
 
  protected:
-  DeskAnimationBase(DesksController* controller) : controller_(controller) {}
+  explicit DeskAnimationBase(DesksController* controller)
+      : controller_(controller) {}
 
   // Abstract functions that can be overridden by child classes to do different
   // things when phase (1), and phase (3) completes. Note that
@@ -313,6 +316,7 @@
 
 DesksController::DesksController() {
   Shell::Get()->activation_client()->AddObserver(this);
+  Shell::Get()->session_controller()->AddObserver(this);
 
   for (int id : desks_util::GetDesksContainersIds())
     available_container_ids_.push(id);
@@ -324,6 +328,7 @@
 }
 
 DesksController::~DesksController() {
+  Shell::Get()->session_controller()->RemoveObserver(this);
   Shell::Get()->activation_client()->RemoveObserver(this);
 }
 
@@ -422,8 +427,6 @@
 void DesksController::ActivateDesk(const Desk* desk, DesksSwitchSource source) {
   DCHECK(HasDesk(desk));
 
-  UMA_HISTOGRAM_ENUMERATION(kDeskSwitchHistogramName, source);
-
   OverviewController* overview_controller = Shell::Get()->overview_controller();
   const bool in_overview = overview_controller->InOverviewSession();
   if (desk == active_desk_) {
@@ -435,21 +438,30 @@
     return;
   }
 
-  if (source == DesksSwitchSource::kDeskRemoved) {
+  UMA_HISTOGRAM_ENUMERATION(kDeskSwitchHistogramName, source);
+
+  const int target_desk_index = GetDeskIndex(desk);
+  if (source != DesksSwitchSource::kDeskRemoved) {
+    // Desk removal has its own a11y alert.
+    Shell::Get()
+        ->accessibility_controller()
+        ->TriggerAccessibilityAlertWithMessage(l10n_util::GetStringFUTF8(
+            IDS_ASH_VIRTUAL_DESKS_ALERT_DESK_ACTIVATED,
+            base::NumberToString16(target_desk_index + 1)));
+  }
+
+  if (source == DesksSwitchSource::kDeskRemoved ||
+      source == DesksSwitchSource::kUserSwitch) {
+    // Desk switches due to desks removal or user switches in a multi-profile
+    // session result in immediate desk activation without animation.
     ActivateDeskInternal(desk, /*update_window_activation=*/!in_overview);
     return;
   }
 
-  Shell::Get()
-      ->accessibility_controller()
-      ->TriggerAccessibilityAlertWithMessage(l10n_util::GetStringFUTF8(
-          IDS_ASH_VIRTUAL_DESKS_ALERT_DESK_ACTIVATED,
-          base::NumberToString16(GetDeskIndex(desk) + 1)));
-
   // New desks are always added at the end of the list to the right of existing
   // desks. Therefore, desks at lower indices are located on the left of desks
   // with higher indices.
-  const bool move_left = GetDeskIndex(active_desk_) < GetDeskIndex(desk);
+  const bool move_left = GetDeskIndex(active_desk_) < target_desk_index;
   animations_.emplace_back(
       std::make_unique<DeskActivationAnimation>(this, desk, move_left));
   animations_.back()->Launch();
@@ -555,6 +567,39 @@
                                         aura::Window* gained_active,
                                         aura::Window* lost_active) {}
 
+void DesksController::OnActiveUserSessionChanged(const AccountId& account_id) {
+  // TODO(afakhry): Remove this when multi-profile support goes away.
+  if (!current_account_id_.is_valid()) {
+    // This is the login of the first primary user. No need to switch any desks.
+    current_account_id_ = account_id;
+    return;
+  }
+
+  user_to_active_desk_index_[current_account_id_] = GetDeskIndex(active_desk_);
+  current_account_id_ = account_id;
+
+  // Note the following constraints:
+  // - Simultaneously logged-in users share the same number of desks.
+  // - We don't sync and restore the number of desks nor the active desk
+  //   position from previous login sessions.
+  //
+  // Given the above, we do the following for simplicity:
+  // - If this user has never been seen before, we activate their first desk.
+  // - If one of the simultaneously logged-in users remove desks, that other
+  //   users' active-desk indices may become invalid. We won't create extra
+  //   desks for this user, but rather we will simply activate their last desk
+  //   on the right. Future user switches will update the pref for this user to
+  //   the correct value.
+  int new_user_active_desk_index =
+      /* This is a default initialized index to 0 if the id doesn't exist. */
+      user_to_active_desk_index_[current_account_id_];
+  new_user_active_desk_index = base::ClampToRange(
+      new_user_active_desk_index, 0, static_cast<int>(desks_.size()) - 1);
+
+  ActivateDesk(desks_[new_user_active_desk_index].get(),
+               DesksSwitchSource::kUserSwitch);
+}
+
 void DesksController::OnAnimationFinished(DeskAnimationBase* animation) {
   base::EraseIf(animations_, base::MatchesUniquePtr(animation));
 }
diff --git a/ash/wm/desks/desks_controller.h b/ash/wm/desks/desks_controller.h
index ff2a2028..e4cb1a9 100644
--- a/ash/wm/desks/desks_controller.h
+++ b/ash/wm/desks/desks_controller.h
@@ -10,10 +10,13 @@
 #include <vector>
 
 #include "ash/ash_export.h"
+#include "ash/session/session_observer.h"
 #include "ash/wm/desks/desks_histogram_enums.h"
 #include "ash/wm/desks/root_window_desk_switch_animator.h"
+#include "base/containers/flat_map.h"
 #include "base/macros.h"
 #include "base/observer_list.h"
+#include "components/account_id/account_id.h"
 #include "ui/wm/public/activation_change_observer.h"
 
 namespace aura {
@@ -26,7 +29,8 @@
 
 // Defines a controller for creating, destroying and managing virtual desks and
 // their windows.
-class ASH_EXPORT DesksController : public wm::ActivationChangeObserver {
+class ASH_EXPORT DesksController : public wm::ActivationChangeObserver,
+                                   public SessionObserver {
  public:
   class Observer {
    public:
@@ -131,6 +135,9 @@
                          aura::Window* gained_active,
                          aura::Window* lost_active) override;
 
+  // SessionObserver:
+  void OnActiveUserSessionChanged(const AccountId& account_id) override;
+
  private:
   class DeskAnimationBase;
   class DeskActivationAnimation;
@@ -170,6 +177,12 @@
 
   Desk* active_desk_ = nullptr;
 
+  // The account ID of the current active user.
+  AccountId current_account_id_;
+
+  // Stores the per-user last active desk index.
+  base::flat_map<AccountId, int> user_to_active_desk_index_;
+
   // True when desks addition, removal, or activation change are in progress.
   // This can be checked when overview mode is active to avoid exiting overview
   // mode as a result of desks modifications.
diff --git a/ash/wm/desks/desks_histogram_enums.h b/ash/wm/desks/desks_histogram_enums.h
index b92bb88..4bdfe96b 100644
--- a/ash/wm/desks/desks_histogram_enums.h
+++ b/ash/wm/desks/desks_histogram_enums.h
@@ -36,7 +36,8 @@
   kMiniViewButton = 3,
   kWindowActivated = 4,
   kDeskSwitchTouchpad = 5,
-  kMaxValue = kDeskSwitchTouchpad,
+  kUserSwitch = 6,
+  kMaxValue = kUserSwitch,
 };
 
 }  // namespace ash
diff --git a/ash/wm/desks/desks_unittests.cc b/ash/wm/desks/desks_unittests.cc
index 59f9926..173ac35f 100644
--- a/ash/wm/desks/desks_unittests.cc
+++ b/ash/wm/desks/desks_unittests.cc
@@ -1964,13 +1964,13 @@
 };
 
 TEST_F(DesksMultiUserTest, SwitchUsersBackAndForth) {
-  // Create two desks with two windows on each, one window that belongs to the
-  // first user, and the other belongs to the second.
   auto* controller = DesksController::Get();
   NewDesk();
-  ASSERT_EQ(2u, controller->desks().size());
+  NewDesk();
+  ASSERT_EQ(3u, controller->desks().size());
   Desk* desk_1 = controller->desks()[0].get();
   Desk* desk_2 = controller->desks()[1].get();
+  Desk* desk_3 = controller->desks()[2].get();
   auto win0 = CreateAppWindow(gfx::Rect(0, 0, 250, 100));
   multi_user_window_manager()->SetWindowOwner(win0.get(), GetUser1AccountId());
   EXPECT_TRUE(win0->IsVisible());
@@ -1986,10 +1986,14 @@
   EXPECT_FALSE(win0->IsVisible());
   EXPECT_FALSE(win1->IsVisible());
 
+  // Since this is the first time this user logs in, desk_1 will be activated
+  // for this user.
+  EXPECT_TRUE(desk_1->is_active());
+
   auto win2 = CreateAppWindow(gfx::Rect(0, 0, 250, 200));
   multi_user_window_manager()->SetWindowOwner(win2.get(), GetUser2AccountId());
   EXPECT_TRUE(win2->IsVisible());
-  ActivateDesk(desk_1);
+  ActivateDesk(desk_3);
   auto win3 = CreateAppWindow(gfx::Rect(0, 0, 250, 200));
   multi_user_window_manager()->SetWindowOwner(win3.get(), GetUser2AccountId());
   EXPECT_FALSE(win0->IsVisible());
@@ -1997,22 +2001,27 @@
   EXPECT_FALSE(win2->IsVisible());
   EXPECT_TRUE(win3->IsVisible());
 
-  // Similarly when switching back to user_1.
+  // When switching back to user_1, the active desk should be restored to
+  // desk_2.
   SwitchActiveUser(GetUser1AccountId());
-  EXPECT_TRUE(win0->IsVisible());
-  EXPECT_FALSE(win1->IsVisible());
-  EXPECT_FALSE(win2->IsVisible());
-  EXPECT_FALSE(win3->IsVisible());
-  ActivateDesk(desk_2);
+  EXPECT_TRUE(desk_2->is_active());
   EXPECT_FALSE(win0->IsVisible());
   EXPECT_TRUE(win1->IsVisible());
   EXPECT_FALSE(win2->IsVisible());
   EXPECT_FALSE(win3->IsVisible());
+
+  // When switching to user_2, the active desk should be restored to desk_3.
+  SwitchActiveUser(GetUser2AccountId());
+  EXPECT_TRUE(desk_3->is_active());
+  EXPECT_FALSE(win0->IsVisible());
+  EXPECT_FALSE(win1->IsVisible());
+  EXPECT_FALSE(win2->IsVisible());
+  EXPECT_TRUE(win3->IsVisible());
 }
 
 TEST_F(DesksMultiUserTest, RemoveDesks) {
-  // Create two desks with several windows with different app types that belong
-  // to different users.
+  // Create two desks with several windows with different app types that
+  // belong to different users.
   auto* controller = DesksController::Get();
   NewDesk();
   ASSERT_EQ(2u, controller->desks().size());
@@ -2037,6 +2046,7 @@
   // Switch to user_2 and expect no windows from user_1 is visible regardless of
   // the desk.
   SwitchActiveUser(GetUser2AccountId());
+  EXPECT_TRUE(desk_1->is_active());
   EXPECT_FALSE(win0->IsVisible());
   EXPECT_FALSE(win1->IsVisible());
   EXPECT_FALSE(win2->IsVisible());
@@ -2045,7 +2055,7 @@
   auto win4 = CreateAppWindow(gfx::Rect(0, 0, 250, 200));
   multi_user_window_manager()->SetWindowOwner(win4.get(), GetUser2AccountId());
   EXPECT_TRUE(win4->IsVisible());
-  ActivateDesk(desk_1);
+  ActivateDesk(desk_2);
   auto win5 = CreateAppWindow(gfx::Rect(0, 0, 250, 200));
   multi_user_window_manager()->SetWindowOwner(win5.get(), GetUser2AccountId());
   EXPECT_FALSE(win0->IsVisible());
@@ -2057,6 +2067,7 @@
 
   // Delete desk_2, and expect all app windows move to desk_1.
   RemoveDesk(desk_2);
+  EXPECT_TRUE(desk_1->is_active());
   auto* desk_1_container =
       desk_1->GetDeskContainerForRoot(Shell::GetPrimaryRootWindow());
   EXPECT_EQ(desk_1_container, win0->parent());
@@ -2076,10 +2087,32 @@
 
   // Switch to user_1 and expect the correct windows' visibility.
   SwitchActiveUser(GetUser1AccountId());
+  EXPECT_TRUE(desk_1->is_active());
   EXPECT_TRUE(win0->IsVisible());
   EXPECT_TRUE(win1->IsVisible());
   EXPECT_TRUE(win2->IsVisible());
   EXPECT_FALSE(win3->IsVisible());
+
+  // Create two more desks, switch to user_2, and activate the third desk.
+  NewDesk();
+  NewDesk();
+  ASSERT_EQ(3u, controller->desks().size());
+  desk_2 = controller->desks()[1].get();
+  Desk* desk_3 = controller->desks()[2].get();
+  SwitchActiveUser(GetUser2AccountId());
+  ActivateDesk(desk_3);
+  auto win6 = CreateAppWindow(gfx::Rect(0, 0, 250, 200));
+  multi_user_window_manager()->SetWindowOwner(win5.get(), GetUser2AccountId());
+
+  // Switch back to user_1, and remove the first desk. When switching back to
+  // user_2 after that, we should see that what used to be the third desk is now
+  // active.
+  SwitchActiveUser(GetUser1AccountId());
+  EXPECT_TRUE(desk_1->is_active());
+  RemoveDesk(desk_1);
+  SwitchActiveUser(GetUser2AccountId());
+  EXPECT_TRUE(desk_3->is_active());
+  EXPECT_TRUE(win6->IsVisible());
 }
 
 }  // namespace
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index 41d8562..bd57cad 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -1511,6 +1511,21 @@
           # TODO(https://crbug.com/995993): Clean up and enable.
           "-Wno-implicit-fallthrough",
         ]
+
+        if (llvm_force_head_revision) {
+          cflags += [
+            # TODO(thakis): Check how often this fires, then decide if we want
+            # to clean up the codebase or just disable this. Doesn't seem super
+            # useful, likely just want to disable.
+            # https://crbug.com/999871
+            "-Wno-error=c99-designator",
+
+            # TODO(https://crbug.com/999886): Clean up, enable.
+            # If roling this in, use -Wno-final-dtor-non-final-class instead
+            # of the -Wno-error form.
+            "-Wno-error=final-dtor-non-final-class",
+          ]
+        }
       }
     }
   }
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index 8d62563..ffd6ddcb 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-8903684974005062112
\ No newline at end of file
+8903492066113915536
\ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index d0d7a4ad..e9fe6869 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-8903686332382558560
\ No newline at end of file
+8903489678245509728
\ No newline at end of file
diff --git a/cc/benchmarks/micro_benchmark_controller_unittest.cc b/cc/benchmarks/micro_benchmark_controller_unittest.cc
index f4a528d..e0ba122 100644
--- a/cc/benchmarks/micro_benchmark_controller_unittest.cc
+++ b/cc/benchmarks/micro_benchmark_controller_unittest.cc
@@ -67,7 +67,7 @@
 }
 
 TEST_F(MicroBenchmarkControllerTest, CommitScheduled) {
-  EXPECT_FALSE(layer_tree_host_->needs_commit());
+  layer_tree_host_->reset_needs_commit();
   int id = layer_tree_host_->ScheduleMicroBenchmark("unittest_only_benchmark",
                                                     nullptr, base::DoNothing());
   EXPECT_GT(id, 0);
diff --git a/cc/test/fake_layer_tree_host.h b/cc/test/fake_layer_tree_host.h
index 4ca1a50..5e789ac 100644
--- a/cc/test/fake_layer_tree_host.h
+++ b/cc/test/fake_layer_tree_host.h
@@ -46,7 +46,6 @@
 
   void SetNeedsCommit() override;
   void SetNeedsUpdateLayers() override {}
-  void SetNeedsFullTreeSync() override {}
 
   LayerImpl* CommitAndCreateLayerImplTree();
   LayerImpl* CommitAndCreatePendingTree();
diff --git a/cc/test/geometry_test_utils.cc b/cc/test/geometry_test_utils.cc
index df61c53..b60eeca 100644
--- a/cc/test/geometry_test_utils.cc
+++ b/cc/test/geometry_test_utils.cc
@@ -5,6 +5,7 @@
 #include "cc/test/geometry_test_utils.h"
 
 #include "base/logging.h"
+#include "base/strings/stringprintf.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/gfx/transform.h"
 
@@ -19,7 +20,8 @@
   for (int row = 0; row < 4; ++row) {
     for (int col = 0; col < 4; ++col) {
       EXPECT_FLOAT_EQ(expected.matrix().get(row, col),
-                      actual.matrix().get(row, col));
+                      actual.matrix().get(row, col))
+          << "row: " << row << " col: " << col;
     }
   }
 }
@@ -30,7 +32,8 @@
   for (int row = 0; row < 4; ++row) {
     for (int col = 0; col < 4; ++col) {
       EXPECT_NEAR(expected.matrix().get(row, col),
-                  actual.matrix().get(row, col), abs_error);
+                  actual.matrix().get(row, col), abs_error)
+          << "row: " << row << " col: " << col;
     }
   }
 }
diff --git a/cc/test/geometry_test_utils.h b/cc/test/geometry_test_utils.h
index 0e72e58a..48a58e76 100644
--- a/cc/test/geometry_test_utils.h
+++ b/cc/test/geometry_test_utils.h
@@ -108,7 +108,6 @@
 
 #define EXPECT_TRANSFORMATION_MATRIX_EQ(expected, actual) \
   do {                                                    \
-    SCOPED_TRACE("");                                     \
     ExpectTransformationMatrixEq(expected, actual);       \
   } while (false)
 
@@ -118,7 +117,6 @@
 
 #define EXPECT_TRANSFORMATION_MATRIX_NEAR(expected, actual, abs_error) \
   do {                                                                 \
-    SCOPED_TRACE("");                                                  \
     ExpectTransformationMatrixNear(expected, actual, abs_error);       \
   } while (false)
 
diff --git a/cc/test/layer_test_common.cc b/cc/test/layer_test_common.cc
index 8d65d11d..8dcb93a 100644
--- a/cc/test/layer_test_common.cc
+++ b/cc/test/layer_test_common.cc
@@ -32,18 +32,6 @@
 // Align with expected and actual output.
 const char* LayerTestCommon::quad_string = "    Quad: ";
 
-RenderSurfaceImpl* GetRenderSurface(LayerImpl* layer_impl) {
-  EffectTree& effect_tree =
-      layer_impl->layer_tree_impl()->property_trees()->effect_tree;
-
-  if (RenderSurfaceImpl* surface =
-          effect_tree.GetRenderSurface(layer_impl->effect_tree_index()))
-    return surface;
-
-  return effect_tree.GetRenderSurface(
-      effect_tree.Node(layer_impl->effect_tree_index())->target_id);
-}
-
 static bool CanRectFBeSafelyRoundedToRect(const gfx::RectF& r) {
   // Ensure that range of float values is not beyond integer range.
   if (!r.IsExpressibleAsRect())
@@ -151,25 +139,23 @@
       render_pass_(viz::RenderPass::Create()),
       layer_impl_id_(2) {
   std::unique_ptr<LayerImpl> root =
-      LayerImpl::Create(host_->host_impl()->active_tree(), 1);
-  host_->host_impl()->active_tree()->SetRootLayerForTesting(std::move(root));
-  host_->host_impl()->SetVisible(true);
-  EXPECT_TRUE(
-      host_->host_impl()->InitializeFrameSink(layer_tree_frame_sink_.get()));
+      LayerImpl::Create(host_impl()->active_tree(), 1);
+  host_impl()->active_tree()->SetRootLayerForTesting(std::move(root));
+  host_impl()->SetVisible(true);
+  EXPECT_TRUE(host_impl()->InitializeFrameSink(layer_tree_frame_sink_.get()));
 
   const int timeline_id = AnimationIdProvider::NextTimelineId();
   timeline_ = AnimationTimeline::Create(timeline_id);
   animation_host_->AddAnimationTimeline(timeline_);
   // Create impl-side instance.
-  animation_host_->PushPropertiesTo(host_->host_impl()->animation_host());
-  timeline_impl_ =
-      host_->host_impl()->animation_host()->GetTimelineById(timeline_id);
+  animation_host_->PushPropertiesTo(host_impl()->animation_host());
+  timeline_impl_ = host_impl()->animation_host()->GetTimelineById(timeline_id);
 }
 
 LayerTestCommon::LayerImplTest::~LayerImplTest() {
   animation_host_->RemoveAnimationTimeline(timeline_);
   timeline_ = nullptr;
-  host_->host_impl()->ReleaseLayerTreeFrameSink();
+  host_impl()->ReleaseLayerTreeFrameSink();
 }
 
 LayerImpl* LayerTestCommon::LayerImplTest::EnsureRootLayerInPendingTree() {
@@ -185,6 +171,7 @@
   RenderSurfaceList render_surface_list;
   LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs(
       root_layer_for_testing(), gfx::Rect(viewport_size), &render_surface_list);
+  inputs.update_layer_list = &update_layer_impl_list_;
   LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs);
 }
 
@@ -244,47 +231,11 @@
 }
 
 void LayerTestCommon::LayerImplTest::ExecuteCalculateDrawProperties(
-    Layer* root_layer,
-    float device_scale_factor,
-    float page_scale_factor,
-    Layer* page_scale_layer,
-    Layer* inner_viewport_scroll_layer,
-    Layer* outer_viewport_scroll_layer) {
-  EXPECT_TRUE(page_scale_layer || (page_scale_factor == 1.f));
-  gfx::Rect device_viewport_rect =
-      gfx::Rect(root_layer->bounds().width() * device_scale_factor,
-                root_layer->bounds().height() * device_scale_factor);
-
-  root_layer->layer_tree_host()->SetViewportRectAndScale(
-      device_viewport_rect, device_scale_factor,
-      viz::LocalSurfaceIdAllocation());
-
-  // We are probably not testing what is intended if the root_layer bounds are
-  // empty.
-  DCHECK(!root_layer->bounds().IsEmpty());
-  LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
-      root_layer, device_viewport_rect);
-  inputs.device_scale_factor = device_scale_factor;
-  inputs.page_scale_factor = page_scale_factor;
-  inputs.page_scale_layer = page_scale_layer;
-  inputs.inner_viewport_scroll_layer = inner_viewport_scroll_layer;
-  inputs.outer_viewport_scroll_layer = outer_viewport_scroll_layer;
-  if (page_scale_layer) {
-    PropertyTrees* property_trees =
-        root_layer->layer_tree_host()->property_trees();
-    inputs.page_scale_transform_node = property_trees->transform_tree.Node(
-        page_scale_layer->transform_tree_index());
-  }
-  LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs);
-}
-
-void LayerTestCommon::LayerImplTest::ExecuteCalculateDrawProperties(
     LayerImpl* root_layer,
     float device_scale_factor,
+    const gfx::Transform& device_transform,
     float page_scale_factor,
-    LayerImpl* page_scale_layer,
-    LayerImpl* inner_viewport_scroll_layer,
-    LayerImpl* outer_viewport_scroll_layer) {
+    LayerImpl* page_scale_layer) {
   if (device_scale_factor !=
           root_layer->layer_tree_impl()->device_scale_factor() &&
       !root_layer->layer_tree_impl()->settings().use_layer_lists)
@@ -308,8 +259,9 @@
   inputs.device_scale_factor = device_scale_factor;
   inputs.page_scale_factor = page_scale_factor;
   inputs.page_scale_layer = page_scale_layer;
-  inputs.inner_viewport_scroll_layer = inner_viewport_scroll_layer;
-  inputs.outer_viewport_scroll_layer = outer_viewport_scroll_layer;
+  inputs.device_transform = device_transform;
+  inputs.update_layer_list = &update_layer_impl_list_;
+
   if (page_scale_layer) {
     PropertyTrees* property_trees =
         root_layer->layer_tree_impl()->property_trees();
diff --git a/cc/test/layer_test_common.h b/cc/test/layer_test_common.h
index 61bbb53..0a3f6b6 100644
--- a/cc/test/layer_test_common.h
+++ b/cc/test/layer_test_common.h
@@ -50,9 +50,6 @@
   LayerListSettings() { use_layer_lists = true; }
 };
 
-// Returns the RenderSurfaceImpl into which the given layer draws.
-RenderSurfaceImpl* GetRenderSurface(LayerImpl* layer_impl);
-
 class LayerTestCommon {
  public:
   static const char* quad_string;
@@ -136,10 +133,10 @@
     void RequestCopyOfOutput();
 
     LayerTreeFrameSink* layer_tree_frame_sink() const {
-      return host_->host_impl()->layer_tree_frame_sink();
+      return host_impl()->layer_tree_frame_sink();
     }
     viz::ClientResourceProvider* resource_provider() const {
-      return host_->host_impl()->resource_provider();
+      return host_impl()->resource_provider();
     }
     LayerImpl* root_layer_for_testing() const {
       return host_impl()->active_tree()->root_layer_for_testing();
@@ -147,7 +144,7 @@
     FakeLayerTreeHost* host() { return host_.get(); }
     FakeLayerTreeHostImpl* host_impl() const { return host_->host_impl(); }
     TaskRunnerProvider* task_runner_provider() const {
-      return host_->host_impl()->task_runner_provider();
+      return host_impl()->task_runner_provider();
     }
     const viz::QuadList& quad_list() const { return render_pass_->quad_list; }
     scoped_refptr<AnimationTimeline> timeline() { return timeline_; }
@@ -156,43 +153,17 @@
     void BuildPropertyTreesForTesting() {
       host_impl()->active_tree()->BuildPropertyTreesForTesting();
     }
+
     void SetElementIdsForTesting() {
       host_impl()->active_tree()->SetElementIdsForTesting();
     }
 
-    void ExecuteCalculateDrawProperties(Layer* root_layer,
-                                        float device_scale_factor,
-                                        float page_scale_factor,
-                                        Layer* page_scale_layer,
-                                        Layer* inner_viewport_scroll_layer,
-                                        Layer* outer_viewport_scroll_layer);
-    void ExecuteCalculateDrawProperties(LayerImpl* root_layer,
-                                        float device_scale_factor,
-                                        float page_scale_factor,
-                                        LayerImpl* page_scale_layer,
-                                        LayerImpl* inner_viewport_scroll_layer,
-                                        LayerImpl* outer_viewport_scroll_layer);
-
-    template <class LayerType>
-    void ExecuteCalculateDrawProperties(LayerType* root_layer) {
-      LayerType* page_scale_application_layer = nullptr;
-      LayerType* inner_viewport_scroll_layer = nullptr;
-      LayerType* outer_viewport_scroll_layer = nullptr;
-      ExecuteCalculateDrawProperties(
-          root_layer, 1.f, 1.f, page_scale_application_layer,
-          inner_viewport_scroll_layer, outer_viewport_scroll_layer);
-    }
-
-    template <class LayerType>
-    void ExecuteCalculateDrawProperties(LayerType* root_layer,
-                                        float device_scale_factor) {
-      LayerType* page_scale_application_layer = nullptr;
-      LayerType* inner_viewport_scroll_layer = nullptr;
-      LayerType* outer_viewport_scroll_layer = nullptr;
-      ExecuteCalculateDrawProperties(
-          root_layer, device_scale_factor, 1.f, page_scale_application_layer,
-          inner_viewport_scroll_layer, outer_viewport_scroll_layer);
-    }
+    void ExecuteCalculateDrawProperties(
+        LayerImpl* root_layer,
+        float device_scale_factor = 1.0f,
+        const gfx::Transform& device_transform = gfx::Transform(),
+        float page_scale_factor = 1.0f,
+        LayerImpl* page_scale_layer = nullptr);
 
     void ExecuteCalculateDrawPropertiesWithoutAdjustingRasterScales(
         LayerImpl* root_layer);
@@ -201,6 +172,18 @@
       return render_surface_list_impl_.get();
     }
 
+    bool UpdateLayerImplListContains(int id) const {
+      for (const auto* layer : update_layer_impl_list_) {
+        if (layer->id() == id)
+          return true;
+      }
+      return false;
+    }
+
+    const LayerImplList& update_layer_impl_list() const {
+      return update_layer_impl_list_;
+    }
+
    private:
     template <typename T, typename... Args>
     T* AddLayerInternal(LayerTreeImpl* tree, Args&&... args) {
@@ -222,6 +205,7 @@
     scoped_refptr<AnimationTimeline> timeline_impl_;
     int layer_impl_id_;
     std::unique_ptr<RenderSurfaceList> render_surface_list_impl_;
+    LayerImplList update_layer_impl_list_;
   };
 };
 
diff --git a/cc/test/property_tree_test_utils.h b/cc/test/property_tree_test_utils.h
index 391b936..3a4abe92 100644
--- a/cc/test/property_tree_test_utils.h
+++ b/cc/test/property_tree_test_utils.h
@@ -130,6 +130,14 @@
                    scoped_refptr<Layer> outer_scroll_layer,
                    const gfx::Size& outer_bounds);
 
+// Returns the RenderSurfaceImpl into which the given layer draws.
+inline RenderSurfaceImpl* GetRenderSurface(const LayerImpl* layer) {
+  auto& effect_tree = GetPropertyTrees(layer)->effect_tree;
+  if (auto* surface = effect_tree.GetRenderSurface(layer->effect_tree_index()))
+    return surface;
+  return effect_tree.GetRenderSurface(GetEffectNode(layer)->target_id);
+}
+
 // TODO(wangxianzhu): Add functions to create property nodes not based on
 // layers when needed.
 
diff --git a/cc/trees/layer_tree_host_common.cc b/cc/trees/layer_tree_host_common.cc
index a3a10669..2081bf9 100644
--- a/cc/trees/layer_tree_host_common.cc
+++ b/cc/trees/layer_tree_host_common.cc
@@ -36,8 +36,7 @@
                                       float page_scale_factor,
                                       const Layer* page_scale_layer,
                                       const Layer* inner_viewport_scroll_layer,
-                                      const Layer* outer_viewport_scroll_layer,
-                                      TransformNode* page_scale_transform_node)
+                                      const Layer* outer_viewport_scroll_layer)
     : root_layer(root_layer),
       device_viewport_rect(device_viewport_rect),
       device_transform(device_transform),
@@ -45,8 +44,7 @@
       page_scale_factor(page_scale_factor),
       page_scale_layer(page_scale_layer),
       inner_viewport_scroll_layer(inner_viewport_scroll_layer),
-      outer_viewport_scroll_layer(outer_viewport_scroll_layer),
-      page_scale_transform_node(page_scale_transform_node) {}
+      outer_viewport_scroll_layer(outer_viewport_scroll_layer) {}
 
 LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting::
     CalcDrawPropsMainInputsForTesting(Layer* root_layer,
@@ -59,7 +57,6 @@
                                         1.f,
                                         nullptr,
                                         nullptr,
-                                        nullptr,
                                         nullptr) {}
 
 LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting::
@@ -517,9 +514,10 @@
   }
 }
 
-void CalculateDrawPropertiesInternal(
+static void CalculateDrawPropertiesInternal(
     LayerTreeHostCommon::CalcDrawPropsImplInputs* inputs,
-    PropertyTreeOption property_tree_option) {
+    PropertyTreeOption property_tree_option,
+    LayerImplList* output_update_layer_list) {
   inputs->render_surface_list->clear();
 
   LayerImplList visible_layer_list;
@@ -611,6 +609,9 @@
   // CalculateDrawProperties.
   DCHECK(inputs->property_trees->effect_tree.GetRenderSurface(
       EffectTree::kContentsRootNodeId));
+
+  if (output_update_layer_list)
+    *output_update_layer_list = std::move(visible_layer_list);
 }
 
 void LayerTreeHostCommon::CalculateDrawPropertiesForTesting(
@@ -636,11 +637,14 @@
   draw_property_utils::FindLayersThatNeedUpdates(
       inputs->root_layer->layer_tree_host(), property_trees,
       &update_layer_list);
+
+  if (inputs->update_layer_list)
+    *inputs->update_layer_list = std::move(update_layer_list);
 }
 
 void LayerTreeHostCommon::CalculateDrawProperties(
     CalcDrawPropsImplInputs* inputs) {
-  CalculateDrawPropertiesInternal(inputs, DONT_BUILD_PROPERTY_TREES);
+  CalculateDrawPropertiesInternal(inputs, DONT_BUILD_PROPERTY_TREES, nullptr);
 }
 
 void LayerTreeHostCommon::CalculateDrawPropertiesForTesting(
@@ -659,9 +663,11 @@
         &old_render_surfaces, inputs->root_layer->layer_tree_impl());
     inputs->property_trees->ResetCachedData();
   }
-  CalculateDrawPropertiesInternal(inputs, inputs->property_trees->needs_rebuild
-                                              ? BUILD_PROPERTY_TREES
-                                              : DONT_BUILD_PROPERTY_TREES);
+  CalculateDrawPropertiesInternal(inputs,
+                                  inputs->property_trees->needs_rebuild
+                                      ? BUILD_PROPERTY_TREES
+                                      : DONT_BUILD_PROPERTY_TREES,
+                                  inputs->update_layer_list);
 }
 
 PropertyTrees* GetPropertyTrees(const Layer* layer) {
diff --git a/cc/trees/layer_tree_host_common.h b/cc/trees/layer_tree_host_common.h
index 1915ad4..37aad4c 100644
--- a/cc/trees/layer_tree_host_common.h
+++ b/cc/trees/layer_tree_host_common.h
@@ -43,8 +43,7 @@
                                       float page_scale_factor,
                                       const Layer* page_scale_layer,
                                       const Layer* inner_viewport_scroll_layer,
-                                      const Layer* outer_viewport_scroll_layer,
-                                      TransformNode* page_scale_transform_node);
+                                      const Layer* outer_viewport_scroll_layer);
     CalcDrawPropsMainInputsForTesting(Layer* root_layer,
                                       const gfx::Rect& device_viewport_rect,
                                       const gfx::Transform& device_transform);
@@ -58,7 +57,8 @@
     const Layer* page_scale_layer;
     const Layer* inner_viewport_scroll_layer;
     const Layer* outer_viewport_scroll_layer;
-    TransformNode* page_scale_transform_node;
+    // If not null, accepts layers output from FindLayersThatNeedUpdates().
+    LayerList* update_layer_list = nullptr;
   };
 
   struct CC_EXPORT CalcDrawPropsImplInputs {
@@ -112,6 +112,9 @@
                                       const gfx::Rect& device_viewport_rect,
                                       float device_scale_factor,
                                       RenderSurfaceList* render_surface_list);
+
+    // If not null, accepts layers output from FindLayersThatNeedUpdates().
+    LayerImplList* update_layer_list = nullptr;
   };
 
   static int CalculateLayerJitter(LayerImpl* scrolling_layer);
diff --git a/cc/trees/layer_tree_host_common_unittest.cc b/cc/trees/layer_tree_host_common_unittest.cc
index 0499c30..6a511ff0 100644
--- a/cc/trees/layer_tree_host_common_unittest.cc
+++ b/cc/trees/layer_tree_host_common_unittest.cc
@@ -27,7 +27,8 @@
 #include "cc/layers/layer_client.h"
 #include "cc/layers/layer_impl.h"
 #include "cc/layers/render_surface_impl.h"
-#include "cc/layers/texture_layer_impl.h"
+#include "cc/layers/texture_layer.h"
+#include "cc/layers/texture_layer_client.h"
 #include "cc/test/animation_test_common.h"
 #include "cc/test/fake_content_layer_client.h"
 #include "cc/test/fake_impl_task_runner_provider.h"
@@ -96,82 +97,83 @@
         .starting_animation_scale;
   }
 
-  const LayerList* GetUpdateLayerList() { return &update_layer_list_; }
+  // Inherits the impl version from LayerImplTest.
+  using LayerImplTest::ExecuteCalculateDrawProperties;
 
-  void ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(Layer* root_layer) {
-    DCHECK(root_layer->layer_tree_host());
-    const Layer* page_scale_layer =
-        root_layer->layer_tree_host()->page_scale_layer();
-    Layer* inner_viewport_scroll_layer =
-        root_layer->layer_tree_host()->inner_viewport_scroll_layer();
-    Layer* outer_viewport_scroll_layer =
-        root_layer->layer_tree_host()->outer_viewport_scroll_layer();
-    const ElementId overscroll_elasticity_element_id =
-        root_layer->layer_tree_host()->overscroll_elasticity_element_id();
-    gfx::Vector2dF elastic_overscroll =
-        root_layer->layer_tree_host()->elastic_overscroll();
-    float page_scale_factor = 1.f;
-    float device_scale_factor = 1.f;
-    gfx::Rect device_viewport_rect =
-        gfx::Rect(root_layer->bounds().width() * device_scale_factor,
-                  root_layer->bounds().height() * device_scale_factor);
-    PropertyTrees* property_trees =
-        root_layer->layer_tree_host()->property_trees();
-    update_layer_list_.clear();
-    PropertyTreeBuilder::BuildPropertyTrees(
-        root_layer, page_scale_layer, inner_viewport_scroll_layer,
-        outer_viewport_scroll_layer, overscroll_elasticity_element_id,
-        elastic_overscroll, page_scale_factor, device_scale_factor,
-        device_viewport_rect, gfx::Transform(), property_trees);
-    draw_property_utils::UpdatePropertyTrees(root_layer->layer_tree_host(),
-                                             property_trees);
-    draw_property_utils::FindLayersThatNeedUpdates(
-        root_layer->layer_tree_host(), property_trees, &update_layer_list_);
-  }
-
-  void ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(
-      LayerImpl* root_layer) {
-    DCHECK(root_layer->layer_tree_impl());
-
-    const LayerImpl* page_scale_layer = nullptr;
-    LayerImpl* inner_viewport_scroll_layer =
-        root_layer->layer_tree_impl()->InnerViewportScrollLayer();
-    LayerImpl* outer_viewport_scroll_layer =
-        root_layer->layer_tree_impl()->OuterViewportScrollLayer();
-    const ElementId overscroll_elasticity_element_id =
-        root_layer->layer_tree_impl()->OverscrollElasticityElementId();
-    gfx::Vector2dF elastic_overscroll =
-        root_layer->layer_tree_impl()->elastic_overscroll()->Current(
-            root_layer->layer_tree_impl()->IsActiveTree());
-    float page_scale_factor = 1.f;
-    float device_scale_factor = 1.f;
-    gfx::Rect device_viewport_rect =
-        gfx::Rect(root_layer->bounds().width() * device_scale_factor,
-                  root_layer->bounds().height() * device_scale_factor);
-    update_layer_impl_list_.reset(new LayerImplList);
-    root_layer->layer_tree_impl()->BuildLayerListForTesting();
-    PropertyTrees* property_trees =
-        root_layer->layer_tree_impl()->property_trees();
-    PropertyTreeBuilder::BuildPropertyTrees(
-        root_layer, page_scale_layer, inner_viewport_scroll_layer,
-        outer_viewport_scroll_layer, overscroll_elasticity_element_id,
-        elastic_overscroll, page_scale_factor, device_scale_factor,
-        device_viewport_rect, gfx::Transform(), property_trees);
-    draw_property_utils::UpdatePropertyTreesAndRenderSurfaces(root_layer,
-                                                              property_trees);
-    draw_property_utils::FindLayersThatNeedUpdates(
-        root_layer->layer_tree_impl(), property_trees,
-        update_layer_impl_list_.get());
-    draw_property_utils::ComputeDrawPropertiesOfVisibleLayers(
-        update_layer_impl_list(), property_trees);
-  }
-
-  bool UpdateLayerImplListContains(int id) const {
-    for (auto* layer : *update_layer_impl_list_) {
-      if (layer->id() == id)
-        return true;
+  // This is the main version.
+  void ExecuteCalculateDrawProperties(Layer* root_layer,
+                                      float device_scale_factor = 1.0f,
+                                      float page_scale_factor = 1.0f,
+                                      Layer* page_scale_layer = nullptr) {
+    if (!host()->IsUsingLayerLists()) {
+      if (device_scale_factor != host()->device_scale_factor() ||
+          page_scale_factor != host()->page_scale_factor()) {
+        host()->property_trees()->needs_rebuild = true;
+      }
     }
-    return false;
+
+    EXPECT_TRUE(page_scale_layer || (page_scale_factor == 1.f));
+    gfx::Rect device_viewport_rect =
+        gfx::Rect(root_layer->bounds().width() * device_scale_factor,
+                  root_layer->bounds().height() * device_scale_factor);
+
+    root_layer->layer_tree_host()->SetViewportRectAndScale(
+        device_viewport_rect, device_scale_factor,
+        viz::LocalSurfaceIdAllocation());
+
+    // We are probably not testing what is intended if the root_layer bounds are
+    // empty.
+    DCHECK(!root_layer->bounds().IsEmpty());
+    LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
+        root_layer, device_viewport_rect);
+    inputs.device_scale_factor = device_scale_factor;
+    inputs.page_scale_factor = page_scale_factor;
+    inputs.page_scale_layer = page_scale_layer;
+    inputs.update_layer_list = &update_layer_list_;
+    LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs);
+  }
+
+  LayerImpl* ImplOf(const scoped_refptr<Layer>& layer) {
+    return layer ? host_impl()->active_tree()->LayerById(layer->id()) : nullptr;
+  }
+  LayerImpl* PendingImplOf(const scoped_refptr<Layer>& layer) {
+    return layer ? host_impl()->pending_tree()->LayerById(layer->id())
+                 : nullptr;
+  }
+  RenderSurfaceImpl* GetRenderSurfaceImpl(const scoped_refptr<Layer>& layer) {
+    return GetRenderSurface(ImplOf(layer));
+  }
+
+  // Updates main thread draw properties, commits main thread tree to
+  // impl-side pending tree, and updates pending tree draw properties.
+  void Commit(float device_scale_factor = 1.0f,
+              float page_scale_factor = 1.0f,
+              Layer* page_scale_layer = nullptr) {
+    ExecuteCalculateDrawProperties(host()->root_layer(), device_scale_factor,
+                                   page_scale_factor, page_scale_layer);
+    if (!host_impl()->pending_tree())
+      host_impl()->CreatePendingTree();
+    host()->CommitAndCreatePendingTree();
+    // TODO(https://crbug.com/939968) This call should be handled by
+    // FakeLayerTreeHost instead of manually pushing the properties from the
+    // layer tree host to the pending tree.
+    host()->PushLayerTreePropertiesTo(host_impl()->pending_tree());
+    ExecuteCalculateDrawProperties(
+        host_impl()->pending_tree()->root_layer_for_testing(),
+        device_scale_factor, gfx::Transform(), page_scale_factor,
+        PendingImplOf(page_scale_layer));
+  }
+
+  // Calls Commit(), then activates the pending tree, and updates active tree
+  // draw properties.
+  void CommitAndActivate(float device_scale_factor = 1.0f,
+                         float page_scale_factor = 1.0f,
+                         Layer* page_scale_layer = nullptr) {
+    Commit(device_scale_factor, page_scale_factor, page_scale_layer);
+    host_impl()->ActivateSyncTree();
+    ExecuteCalculateDrawProperties(root_layer_for_testing(),
+                                   device_scale_factor, gfx::Transform(),
+                                   page_scale_factor, ImplOf(page_scale_layer));
   }
 
   bool UpdateLayerListContains(int id) const {
@@ -182,19 +184,10 @@
     return false;
   }
 
-  const LayerImplList* update_layer_impl_list() const {
-    return update_layer_impl_list_.get();
-  }
   const LayerList& update_layer_list() const { return update_layer_list_; }
 
-  bool VerifyLayerInList(scoped_refptr<Layer> layer,
-                         const LayerList* layer_list) {
-    return base::Contains(*layer_list, layer);
-  }
-
  private:
   LayerList update_layer_list_;
-  std::unique_ptr<LayerImplList> update_layer_impl_list_;
 };
 
 class LayerTreeHostCommonTest : public LayerTreeHostCommonTestBase,
@@ -281,18 +274,20 @@
 TEST_F(LayerTreeHostCommonTestWithLayerTree, EffectTreeTransformIdTest) {
   // Tests that effect tree node gets a valid transform id when a layer
   // has opacity but doesn't create a render surface.
-  LayerImpl* parent = root_layer_for_testing();
-  LayerImpl* child = AddChild<LayerImpl>(parent);
-  child->SetDrawsContent(true);
+  auto parent = Layer::Create();
+  host()->SetRootLayer(parent);
+  auto child = Layer::Create();
+  parent->AddChild(child);
+  child->SetIsDrawable(true);
 
   parent->SetBounds(gfx::Size(100, 100));
-  child->test_properties()->position = gfx::PointF(10, 10);
+  child->SetPosition(gfx::PointF(10, 10));
   child->SetBounds(gfx::Size(100, 100));
-  child->test_properties()->opacity = 0.f;
-  ExecuteCalculateDrawProperties(parent);
-  EffectNode* node = GetEffectNode(child);
+  child->SetOpacity(0.f);
+  ExecuteCalculateDrawProperties(parent.get());
+  EffectNode* node = GetEffectNode(child.get());
   const int transform_tree_size =
-      GetPropertyTrees(parent)->transform_tree.next_available_id();
+      GetPropertyTrees(parent.get())->transform_tree.next_available_id();
   EXPECT_LT(node->transform_id, transform_tree_size);
 }
 
@@ -430,8 +425,9 @@
                                                kScrollOffset);
   SetScrollOffsetDelta(scroll_layer, kScrollDelta);
 
-  ExecuteCalculateDrawProperties(root_layer, kDeviceScale, page_scale,
-                                 page_scale_layer, nullptr, nullptr);
+  const gfx::Transform kDeviceTransform;
+  ExecuteCalculateDrawProperties(root_layer, kDeviceScale, kDeviceTransform,
+                                 page_scale, page_scale_layer);
   gfx::Transform expected_transform;
   gfx::PointF sub_layer_screen_position = kScrollLayerPosition - kScrollDelta;
   expected_transform.Translate(
@@ -449,8 +445,8 @@
   const float kTranslateY = 20.6f;
   arbitrary_translate.Translate(kTranslateX, kTranslateY);
   SetTransform(scroll_layer, arbitrary_translate);
-  ExecuteCalculateDrawProperties(root_layer, kDeviceScale, page_scale,
-                                 page_scale_layer, nullptr, nullptr);
+  ExecuteCalculateDrawProperties(root_layer, kDeviceScale, kDeviceTransform,
+                                 page_scale, page_scale_layer);
   expected_transform.MakeIdentity();
   expected_transform.Translate(
       std::round(kTranslateX * page_scale * kDeviceScale +
@@ -470,8 +466,8 @@
   root_layer->layer_tree_impl()->SetViewportLayersFromIds(viewport_ids);
   root_layer->layer_tree_impl()->SetPageScaleOnActiveTree(page_scale);
   EXPECT_FALSE(root_layer->layer_tree_impl()->property_trees()->needs_rebuild);
-  ExecuteCalculateDrawProperties(root_layer, kDeviceScale, page_scale,
-                                 page_scale_layer, nullptr, nullptr);
+  ExecuteCalculateDrawProperties(root_layer, kDeviceScale, kDeviceTransform,
+                                 page_scale, page_scale_layer);
 
   expected_transform.MakeIdentity();
   expected_transform.Translate(
@@ -880,30 +876,34 @@
   // Note that the way the code is currently implemented, it is not expected to
   // use a canonical orthographic projection.
 
-  LayerImpl* root = root_layer_for_testing();
-  LayerImpl* child = AddChildToRoot<LayerImpl>();
-  child->SetDrawsContent(true);
-  LayerImpl* grand_child = AddChild<LayerImpl>(child);
-  grand_child->SetDrawsContent(true);
-  LayerImpl* great_grand_child = AddChild<LayerImpl>(grand_child);
-  great_grand_child->SetDrawsContent(true);
+  auto root = Layer::Create();
+  host()->SetRootLayer(root);
+  auto child = Layer::Create();
+  root->AddChild(child);
+  child->SetIsDrawable(true);
+  auto grand_child = Layer::Create();
+  child->AddChild(grand_child);
+  grand_child->SetIsDrawable(true);
+  auto great_grand_child = Layer::Create();
+  grand_child->AddChild(great_grand_child);
+  great_grand_child->SetIsDrawable(true);
 
   gfx::Transform rotation_about_y_axis;
   rotation_about_y_axis.RotateAboutYAxis(30.0);
 
   root->SetBounds(gfx::Size(100, 100));
-  child->test_properties()->transform = rotation_about_y_axis;
+  child->SetTransform(rotation_about_y_axis);
   child->SetBounds(gfx::Size(10, 10));
-  child->test_properties()->force_render_surface = true;
-  grand_child->test_properties()->transform = rotation_about_y_axis;
+  child->SetForceRenderSurfaceForTesting(true);
+  grand_child->SetTransform(rotation_about_y_axis);
   grand_child->SetBounds(gfx::Size(10, 10));
   great_grand_child->SetBounds(gfx::Size(10, 10));
 
   // No layers in this test should preserve 3d.
-  ASSERT_TRUE(root->test_properties()->should_flatten_transform);
-  ASSERT_TRUE(child->test_properties()->should_flatten_transform);
-  ASSERT_TRUE(grand_child->test_properties()->should_flatten_transform);
-  ASSERT_TRUE(great_grand_child->test_properties()->should_flatten_transform);
+  ASSERT_TRUE(root->should_flatten_transform());
+  ASSERT_TRUE(child->should_flatten_transform());
+  ASSERT_TRUE(grand_child->should_flatten_transform());
+  ASSERT_TRUE(great_grand_child->should_flatten_transform());
 
   gfx::Transform expected_child_draw_transform = rotation_about_y_axis;
   gfx::Transform expected_child_screen_space_transform = rotation_about_y_axis;
@@ -918,27 +918,29 @@
   gfx::Transform expected_great_grand_child_screen_space_transform =
       flattened_rotation_about_y * flattened_rotation_about_y;
 
-  ExecuteCalculateDrawProperties(root);
+  CommitAndActivate();
 
   // The child's draw transform should have been taken by its surface.
-  ASSERT_TRUE(GetRenderSurface(child));
-  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_draw_transform,
-                                  GetRenderSurface(child)->draw_transform());
+  ASSERT_TRUE(GetRenderSurfaceImpl(child));
+  EXPECT_TRANSFORMATION_MATRIX_EQ(
+      expected_child_draw_transform,
+      GetRenderSurfaceImpl(child)->draw_transform());
   EXPECT_TRANSFORMATION_MATRIX_EQ(
       expected_child_screen_space_transform,
-      GetRenderSurface(child)->screen_space_transform());
-  EXPECT_TRANSFORMATION_MATRIX_EQ(gfx::Transform(), child->DrawTransform());
+      GetRenderSurfaceImpl(child)->screen_space_transform());
+  EXPECT_TRANSFORMATION_MATRIX_EQ(gfx::Transform(),
+                                  ImplOf(child)->DrawTransform());
   EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_screen_space_transform,
-                                  child->ScreenSpaceTransform());
+                                  ImplOf(child)->ScreenSpaceTransform());
   EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_draw_transform,
-                                  grand_child->DrawTransform());
+                                  ImplOf(grand_child)->DrawTransform());
   EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_screen_space_transform,
-                                  grand_child->ScreenSpaceTransform());
+                                  ImplOf(grand_child)->ScreenSpaceTransform());
   EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_draw_transform,
-                                  great_grand_child->DrawTransform());
+                                  ImplOf(great_grand_child)->DrawTransform());
   EXPECT_TRANSFORMATION_MATRIX_EQ(
       expected_great_grand_child_screen_space_transform,
-      great_grand_child->ScreenSpaceTransform());
+      ImplOf(great_grand_child)->ScreenSpaceTransform());
 }
 
 TEST_F(LayerTreeHostCommonTest, LayerFullyContainedWithinClipInTargetSpace) {
@@ -957,11 +959,6 @@
   child->SetBounds(gfx::Size(10, 10));
   grand_child->SetBounds(gfx::Size(100, 100));
   grand_child->SetDrawsContent(true);
-  float device_scale_factor = 1.f;
-  float page_scale_factor = 1.f;
-  LayerImpl* page_scale_layer = nullptr;
-  LayerImpl* inner_viewport_scroll_layer = nullptr;
-  LayerImpl* outer_viewport_scroll_layer = nullptr;
 
   SetupRootProperties(root);
   CopyProperties(root, child);
@@ -971,9 +968,7 @@
   grand_child_transform_node.flattens_inherited_transform = false;
   grand_child_transform_node.local = grand_child_transform;
 
-  ExecuteCalculateDrawProperties(root, device_scale_factor, page_scale_factor,
-                                 page_scale_layer, inner_viewport_scroll_layer,
-                                 outer_viewport_scroll_layer);
+  ExecuteCalculateDrawProperties(root);
 
   // Mapping grand_child's bounds to screen space produces an empty rect, but
   // only because it is turned sideways.  The entire rect is contained inside
@@ -1074,13 +1069,11 @@
   CopyProperties(root, child);
   CreateClipNode(child);
 
+  float device_scale_factor = 1.0f;
   gfx::Transform translate;
   translate.Translate(50, 50);
   {
-    RenderSurfaceList render_surface_list_impl;
-    LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs(
-        root, gfx::Rect(root->bounds()), translate, &render_surface_list_impl);
-    LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs);
+    ExecuteCalculateDrawProperties(root, device_scale_factor, translate);
     EXPECT_TRANSFORMATION_MATRIX_EQ(
         translate, root->draw_properties().target_space_transform);
     EXPECT_TRANSFORMATION_MATRIX_EQ(
@@ -1094,10 +1087,7 @@
   gfx::Transform scale;
   scale.Scale(2, 2);
   {
-    RenderSurfaceList render_surface_list_impl;
-    LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs(
-        root, gfx::Rect(root->bounds()), scale, &render_surface_list_impl);
-    LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs);
+    ExecuteCalculateDrawProperties(root, device_scale_factor, scale);
     EXPECT_TRANSFORMATION_MATRIX_EQ(
         scale, root->draw_properties().target_space_transform);
     EXPECT_TRANSFORMATION_MATRIX_EQ(
@@ -1111,10 +1101,7 @@
   gfx::Transform rotate;
   rotate.Rotate(2);
   {
-    RenderSurfaceList render_surface_list_impl;
-    LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs(
-        root, gfx::Rect(root->bounds()), rotate, &render_surface_list_impl);
-    LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs);
+    ExecuteCalculateDrawProperties(root, device_scale_factor, rotate);
     EXPECT_TRANSFORMATION_MATRIX_EQ(
         rotate, root->draw_properties().target_space_transform);
     EXPECT_TRANSFORMATION_MATRIX_EQ(
@@ -1130,10 +1117,7 @@
   composite.ConcatTransform(scale);
   composite.ConcatTransform(rotate);
   {
-    RenderSurfaceList render_surface_list_impl;
-    LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs(
-        root, gfx::Rect(root->bounds()), composite, &render_surface_list_impl);
-    LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs);
+    ExecuteCalculateDrawProperties(root, device_scale_factor, composite);
     EXPECT_TRANSFORMATION_MATRIX_EQ(
         composite, root->draw_properties().target_space_transform);
     EXPECT_TRANSFORMATION_MATRIX_EQ(
@@ -1145,14 +1129,10 @@
   }
 
   // Verify it composes correctly with device scale.
-  float device_scale_factor = 1.5f;
+  device_scale_factor = 1.5f;
 
   {
-    RenderSurfaceList render_surface_list_impl;
-    LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs(
-        root, gfx::Rect(root->bounds()), translate, &render_surface_list_impl);
-    inputs.device_scale_factor = device_scale_factor;
-    LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs);
+    ExecuteCalculateDrawProperties(root, device_scale_factor, translate);
     gfx::Transform device_scaled_translate = translate;
     device_scaled_translate.Scale(device_scale_factor, device_scale_factor);
     EXPECT_TRANSFORMATION_MATRIX_EQ(
@@ -1172,47 +1152,55 @@
 // Needs layer tree mode: testing PropertyTreeBuilder.
 TEST_F(LayerTreeHostCommonTestWithLayerTree,
        RenderSurfaceForNonAxisAlignedClipping) {
-  LayerImpl* root = root_layer_for_testing();
-  LayerImpl* rotated_and_transparent = AddChildToRoot<LayerImpl>();
-  LayerImpl* clips_subtree = AddChild<LayerImpl>(rotated_and_transparent);
-  LayerImpl* draws_content = AddChild<LayerImpl>(clips_subtree);
+  auto root = Layer::Create();
+  host()->SetRootLayer(root);
+  auto rotated_and_transparent = Layer::Create();
+  root->AddChild(rotated_and_transparent);
+  auto clips_subtree = Layer::Create();
+  rotated_and_transparent->AddChild(clips_subtree);
+  auto draws_content = Layer::Create();
+  clips_subtree->AddChild(draws_content);
 
   root->SetBounds(gfx::Size(10, 10));
   rotated_and_transparent->SetBounds(gfx::Size(10, 10));
-  rotated_and_transparent->test_properties()->opacity = 0.5f;
+  rotated_and_transparent->SetOpacity(0.5f);
   gfx::Transform rotate;
   rotate.Rotate(2);
-  rotated_and_transparent->test_properties()->transform = rotate;
+  rotated_and_transparent->SetTransform(rotate);
   clips_subtree->SetBounds(gfx::Size(10, 10));
   clips_subtree->SetMasksToBounds(true);
   draws_content->SetBounds(gfx::Size(10, 10));
-  draws_content->SetDrawsContent(true);
+  draws_content->SetIsDrawable(true);
 
-  ExecuteCalculateDrawProperties(root);
-  EXPECT_TRUE(GetEffectNode(clips_subtree)->HasRenderSurface());
+  ExecuteCalculateDrawProperties(root.get());
+  EXPECT_TRUE(GetEffectNode(clips_subtree.get())->HasRenderSurface());
 }
 
 // Needs layer tree mode: testing PropertyTreeBuilder.
 TEST_F(LayerTreeHostCommonTestWithLayerTree,
        EffectNodesForNonAxisAlignedClips) {
-  LayerImpl* root = root_layer_for_testing();
-  LayerImpl* rotate_and_clip = AddChildToRoot<LayerImpl>();
-  LayerImpl* only_clip = AddChild<LayerImpl>(rotate_and_clip);
-  LayerImpl* rotate_and_clip2 = AddChild<LayerImpl>(only_clip);
+  auto root = Layer::Create();
+  host()->SetRootLayer(root);
+  auto rotate_and_clip = Layer::Create();
+  root->AddChild(rotate_and_clip);
+  auto only_clip = Layer::Create();
+  rotate_and_clip->AddChild(only_clip);
+  auto rotate_and_clip2 = Layer::Create();
+  only_clip->AddChild(rotate_and_clip2);
 
   gfx::Transform rotate;
   rotate.Rotate(2);
   root->SetBounds(gfx::Size(10, 10));
   rotate_and_clip->SetBounds(gfx::Size(10, 10));
-  rotate_and_clip->test_properties()->transform = rotate;
+  rotate_and_clip->SetTransform(rotate);
   rotate_and_clip->SetMasksToBounds(true);
   only_clip->SetBounds(gfx::Size(10, 10));
   only_clip->SetMasksToBounds(true);
   rotate_and_clip2->SetBounds(gfx::Size(10, 10));
-  rotate_and_clip2->test_properties()->transform = rotate;
+  rotate_and_clip2->SetTransform(rotate);
   rotate_and_clip2->SetMasksToBounds(true);
 
-  ExecuteCalculateDrawProperties(root);
+  ExecuteCalculateDrawProperties(root.get());
   // non-axis aligned clip should create an effect node
   EXPECT_NE(root->effect_tree_index(), rotate_and_clip->effect_tree_index());
   // Since only_clip's clip is in the same non-axis aligned space as
@@ -1228,131 +1216,145 @@
 // Needs layer tree mode: testing PropertyTreeBuilder.
 TEST_F(LayerTreeHostCommonTestWithLayerTree,
        RenderSurfaceListForRenderSurfaceWithClippedLayer) {
-  LayerImpl* root = root_layer_for_testing();
-  LayerImpl* render_surface1 = AddChildToRoot<LayerImpl>();
-  LayerImpl* child = AddChild<LayerImpl>(render_surface1);
+  auto root = Layer::Create();
+  host()->SetRootLayer(root);
+  auto render_surface1 = Layer::Create();
+  root->AddChild(render_surface1);
+  auto child = Layer::Create();
+  render_surface1->AddChild(child);
 
   root->SetBounds(gfx::Size(10, 10));
   root->SetMasksToBounds(true);
   render_surface1->SetBounds(gfx::Size(10, 10));
-  render_surface1->test_properties()->force_render_surface = true;
-  child->SetDrawsContent(true);
-  child->test_properties()->position = gfx::PointF(30.f, 30.f);
+  render_surface1->SetForceRenderSurfaceForTesting(true);
+  child->SetIsDrawable(true);
+  child->SetPosition(gfx::PointF(30.f, 30.f));
   child->SetBounds(gfx::Size(10, 10));
-  ExecuteCalculateDrawProperties(root);
+
+  CommitAndActivate();
 
   // The child layer's content is entirely outside the root's clip rect, so
   // the intermediate render surface should not be listed here, even if it was
   // forced to be created. Render surfaces without children or visible content
   // are unexpected at draw time (e.g. we might try to create a content texture
   // of size 0).
-  ASSERT_TRUE(GetRenderSurface(root));
+  ASSERT_TRUE(GetRenderSurfaceImpl(root));
   EXPECT_EQ(1U, render_surface_list_impl()->size());
 }
 
 // Needs layer tree mode: testing PropertyTreeBuilder.
 TEST_F(LayerTreeHostCommonTestWithLayerTree,
        RenderSurfaceListForTransparentChild) {
-  LayerImpl* root = root_layer_for_testing();
-  LayerImpl* render_surface1 = AddChild<LayerImpl>(root);
-  LayerImpl* child = AddChild<LayerImpl>(render_surface1);
+  auto root = Layer::Create();
+  host()->SetRootLayer(root);
+  auto render_surface1 = Layer::Create();
+  root->AddChild(render_surface1);
+  auto child = Layer::Create();
+  render_surface1->AddChild(child);
 
   root->SetBounds(gfx::Size(10, 10));
   render_surface1->SetBounds(gfx::Size(10, 10));
-  render_surface1->test_properties()->force_render_surface = true;
-  render_surface1->test_properties()->opacity = 0.f;
+  render_surface1->SetForceRenderSurfaceForTesting(true);
+  render_surface1->SetOpacity(0.f);
   child->SetBounds(gfx::Size(10, 10));
-  child->SetDrawsContent(true);
+  child->SetIsDrawable(true);
 
-  ExecuteCalculateDrawProperties(root);
+  CommitAndActivate();
 
-  // Since the layer is transparent, render_surface1->GetRenderSurface() should
-  // not have gotten added anywhere.  Also, the drawable content rect should not
-  // have been extended by the children.
-  ASSERT_TRUE(GetRenderSurface(root));
-  EXPECT_EQ(0, GetRenderSurface(root)->num_contributors());
+  // Since the layer is transparent, render_surface1_impl->GetRenderSurface()
+  // should not have gotten added anywhere.  Also, the drawable content rect
+  // should not have been extended by the children.
+  ASSERT_TRUE(GetRenderSurfaceImpl(root));
+  EXPECT_EQ(0, GetRenderSurfaceImpl(root)->num_contributors());
   EXPECT_EQ(1U, render_surface_list_impl()->size());
   EXPECT_EQ(static_cast<viz::RenderPassId>(root->id()),
             render_surface_list_impl()->at(0)->id());
-  EXPECT_EQ(gfx::Rect(), root->drawable_content_rect());
+  EXPECT_EQ(gfx::Rect(), ImplOf(root)->drawable_content_rect());
 }
 
 // Needs layer tree mode: testing PropertyTreeBuilder.
 TEST_F(LayerTreeHostCommonTestWithLayerTree,
        RenderSurfaceListForTransparentChildWithBackdropFilter) {
-  LayerImpl* root = root_layer_for_testing();
-  LayerImpl* render_surface1 = AddChild<LayerImpl>(root);
-  LayerImpl* child = AddChild<LayerImpl>(render_surface1);
+  auto root = Layer::Create();
+  host()->SetRootLayer(root);
+  auto render_surface1 = Layer::Create();
+  root->AddChild(render_surface1);
+  auto child = Layer::Create();
+  render_surface1->AddChild(child);
 
   root->SetBounds(gfx::Size(10, 10));
   render_surface1->SetBounds(gfx::Size(10, 10));
-  render_surface1->test_properties()->force_render_surface = true;
-  render_surface1->test_properties()->opacity = 0.f;
-  render_surface1->SetDrawsContent(true);
+  render_surface1->SetForceRenderSurfaceForTesting(true);
+  render_surface1->SetOpacity(0.f);
+  render_surface1->SetIsDrawable(true);
   FilterOperations filters;
   filters.Append(FilterOperation::CreateBlurFilter(1.5f));
-  render_surface1->test_properties()->backdrop_filters = filters;
+  render_surface1->SetBackdropFilters(filters);
   child->SetBounds(gfx::Size(10, 10));
-  child->SetDrawsContent(true);
-  root->layer_tree_impl()->SetElementIdsForTesting();
+  child->SetIsDrawable(true);
+  host()->SetElementIdsForTesting();
 
-  ExecuteCalculateDrawProperties(root);
+  CommitAndActivate();
   EXPECT_EQ(2U, render_surface_list_impl()->size());
 
   // The layer is fully transparent, but has a backdrop filter, so it
   // shouldn't be skipped and should be drawn.
-  ASSERT_TRUE(GetRenderSurface(root));
-  EXPECT_EQ(1, GetRenderSurface(root)->num_contributors());
+  ASSERT_TRUE(GetRenderSurfaceImpl(root));
+  EXPECT_EQ(1, GetRenderSurfaceImpl(root)->num_contributors());
   EXPECT_EQ(gfx::RectF(0, 0, 10, 10),
-            GetRenderSurface(root)->DrawableContentRect());
-  EXPECT_TRUE(GetEffectNode(render_surface1)->is_drawn);
+            GetRenderSurfaceImpl(root)->DrawableContentRect());
+  EXPECT_TRUE(GetEffectNode(ImplOf(render_surface1))->is_drawn);
 
   // When root is transparent, the layer should not be drawn.
-  root->layer_tree_impl()->SetOpacityMutated(root->element_id(), 0.f);
-  root->layer_tree_impl()->SetOpacityMutated(render_surface1->element_id(),
-                                             1.f);
-  render_surface1->set_visible_layer_rect(gfx::Rect());
-  ExecuteCalculateDrawProperties(root);
+  host_impl()->active_tree()->SetOpacityMutated(root->element_id(), 0.f);
+  host_impl()->active_tree()->SetOpacityMutated(render_surface1->element_id(),
+                                                1.f);
+  ImplOf(render_surface1)->set_visible_layer_rect(gfx::Rect());
+  ExecuteCalculateDrawProperties(ImplOf(root));
 
-  EXPECT_FALSE(GetEffectNode(render_surface1)->is_drawn);
-  EXPECT_EQ(gfx::Rect(), render_surface1->visible_layer_rect());
+  EXPECT_FALSE(GetEffectNode(ImplOf(render_surface1))->is_drawn);
+  EXPECT_EQ(gfx::Rect(), ImplOf(render_surface1)->visible_layer_rect());
 }
 
 // Needs layer tree mode: testing PropertyTreeBuilder.
 TEST_F(LayerTreeHostCommonTestWithLayerTree, RenderSurfaceListForFilter) {
-  LayerImpl* root = root_layer_for_testing();
-  LayerImpl* parent = AddChild<LayerImpl>(root);
-  LayerImpl* child1 = AddChild<LayerImpl>(parent);
-  LayerImpl* child2 = AddChild<LayerImpl>(parent);
+  auto root = Layer::Create();
+  host()->SetRootLayer(root);
+  auto parent = Layer::Create();
+  root->AddChild(parent);
+  auto child1 = Layer::Create();
+  parent->AddChild(child1);
+  auto child2 = Layer::Create();
+  parent->AddChild(child2);
 
   gfx::Transform scale_matrix;
   scale_matrix.Scale(2.0f, 2.0f);
 
   root->SetBounds(gfx::Size(100, 100));
-  parent->test_properties()->transform = scale_matrix;
+  parent->SetTransform(scale_matrix);
   FilterOperations filters;
   filters.Append(FilterOperation::CreateBlurFilter(10.0f));
-  parent->test_properties()->filters = filters;
-  parent->test_properties()->force_render_surface = true;
+  parent->SetFilters(filters);
+  parent->SetForceRenderSurfaceForTesting(true);
   child1->SetBounds(gfx::Size(25, 25));
-  child1->SetDrawsContent(true);
-  child1->test_properties()->force_render_surface = true;
-  child2->test_properties()->position = gfx::PointF(25, 25);
+  child1->SetIsDrawable(true);
+  child1->SetForceRenderSurfaceForTesting(true);
+  child2->SetPosition(gfx::PointF(25, 25));
   child2->SetBounds(gfx::Size(25, 25));
-  child2->SetDrawsContent(true);
-  child2->test_properties()->force_render_surface = true;
+  child2->SetIsDrawable(true);
+  child2->SetForceRenderSurfaceForTesting(true);
 
-  ExecuteCalculateDrawProperties(root);
+  CommitAndActivate();
 
-  ASSERT_TRUE(GetRenderSurface(parent));
-  EXPECT_EQ(2, GetRenderSurface(parent)->num_contributors());
+  ASSERT_TRUE(GetRenderSurfaceImpl(parent));
+  EXPECT_EQ(2, GetRenderSurfaceImpl(parent)->num_contributors());
   EXPECT_EQ(4U, render_surface_list_impl()->size());
 
   // The rectangle enclosing child1 and child2 (0,0 50x50), expanded for the
   // blur (-30,-30 110x110), and then scaled by the scale matrix
   // (-60,-60 220x220).
   EXPECT_EQ(gfx::RectF(-60, -60, 220, 220),
-            GetRenderSurface(parent)->DrawableContentRect());
+            GetRenderSurfaceImpl(parent)->DrawableContentRect());
 }
 
 TEST_F(LayerTreeHostCommonTest, DrawableContentRectForReferenceFilter) {
@@ -1476,31 +1478,30 @@
 
 // Needs layer tree mode: testing PropertyTreeBuilder.
 TEST_F(LayerTreeHostCommonTestWithLayerTree, ForceRenderSurface) {
-  LayerImpl* root = root_layer_for_testing();
-  LayerImpl* render_surface1 = AddChildToRoot<LayerImpl>();
-  LayerImpl* child = AddChild<LayerImpl>(render_surface1);
+  auto root = Layer::Create();
+  host()->SetRootLayer(root);
+  auto render_surface1 = Layer::Create();
+  root->AddChild(render_surface1);
+  auto child = Layer::Create();
+  render_surface1->AddChild(child);
 
   root->SetBounds(gfx::Size(10, 10));
   render_surface1->SetBounds(gfx::Size(10, 10));
-  render_surface1->test_properties()->force_render_surface = true;
+  render_surface1->SetForceRenderSurfaceForTesting(true);
   child->SetBounds(gfx::Size(10, 10));
-  child->SetDrawsContent(true);
+  child->SetIsDrawable(true);
 
-  {
-    ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root);
+  CommitAndActivate();
 
-    // The root layer always creates a render surface
-    EXPECT_TRUE(GetRenderSurface(root));
-    EXPECT_NE(GetRenderSurface(render_surface1), GetRenderSurface(root));
-  }
+  // The root layer always creates a render surface
+  EXPECT_TRUE(GetRenderSurfaceImpl(root));
+  EXPECT_NE(GetRenderSurfaceImpl(render_surface1), GetRenderSurfaceImpl(root));
 
-  {
-    render_surface1->test_properties()->force_render_surface = false;
-    render_surface1->layer_tree_impl()->property_trees()->needs_rebuild = true;
-    ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root);
-    EXPECT_TRUE(GetRenderSurface(root));
-    EXPECT_EQ(GetRenderSurface(render_surface1), GetRenderSurface(root));
-  }
+  render_surface1->SetForceRenderSurfaceForTesting(false);
+  CommitAndActivate();
+
+  EXPECT_TRUE(GetRenderSurfaceImpl(root));
+  EXPECT_EQ(GetRenderSurfaceImpl(render_surface1), GetRenderSurfaceImpl(root));
 }
 
 // Needs layer tree mode: testing PropertyTreeBuilder (force flattening on
@@ -1509,42 +1510,49 @@
        RenderSurfacesFlattenScreenSpaceTransform) {
   // Render surfaces act as a flattening point for their subtree, so should
   // always flatten the target-to-screen space transform seen by descendants.
-  LayerImpl* root = root_layer_for_testing();
-  LayerImpl* parent = AddChild<LayerImpl>(root);
-  LayerImpl* child = AddChild<LayerImpl>(parent);
-  LayerImpl* grand_child = AddChild<LayerImpl>(child);
+  auto root = Layer::Create();
+  host()->SetRootLayer(root);
+  auto parent = Layer::Create();
+  root->AddChild(parent);
+  auto child = Layer::Create();
+  parent->AddChild(child);
+  auto grand_child = Layer::Create();
+  child->AddChild(grand_child);
 
   gfx::Transform rotation_about_y_axis;
   rotation_about_y_axis.RotateAboutYAxis(30.0);
 
   root->SetBounds(gfx::Size(100, 100));
-  parent->test_properties()->transform = rotation_about_y_axis;
+  parent->SetTransform(rotation_about_y_axis);
   parent->SetBounds(gfx::Size(10, 10));
-  parent->test_properties()->force_render_surface = true;
+  parent->SetForceRenderSurfaceForTesting(true);
   child->SetBounds(gfx::Size(10, 10));
-  child->SetDrawsContent(true);
+  child->SetIsDrawable(true);
   grand_child->SetBounds(gfx::Size(10, 10));
-  grand_child->SetDrawsContent(true);
-  grand_child->test_properties()->should_flatten_transform = false;
-  ExecuteCalculateDrawProperties(root);
+  grand_child->SetIsDrawable(true);
+  grand_child->SetShouldFlattenTransform(false);
 
-  EXPECT_TRUE(GetRenderSurface(parent));
-  EXPECT_EQ(GetRenderSurface(child), GetRenderSurface(parent));
-  EXPECT_EQ(GetRenderSurface(grand_child), GetRenderSurface(parent));
+  CommitAndActivate();
 
-  EXPECT_TRANSFORMATION_MATRIX_EQ(gfx::Transform(), child->DrawTransform());
+  EXPECT_TRUE(GetRenderSurfaceImpl(parent));
+  EXPECT_EQ(GetRenderSurfaceImpl(child), GetRenderSurfaceImpl(parent));
+  EXPECT_EQ(GetRenderSurfaceImpl(grand_child), GetRenderSurfaceImpl(parent));
+
   EXPECT_TRANSFORMATION_MATRIX_EQ(gfx::Transform(),
-                                  grand_child->DrawTransform());
+                                  ImplOf(child)->DrawTransform());
+  EXPECT_TRANSFORMATION_MATRIX_EQ(gfx::Transform(),
+                                  ImplOf(grand_child)->DrawTransform());
 
-  // The screen-space transform inherited by |child| and |grand_child| should
-  // have been flattened at their render target. In particular, the fact that
-  // |grand_child| happens to preserve 3d shouldn't affect this flattening.
+  // The screen-space transform inherited by |child| and |grand_child|
+  // should have been flattened at their render target. In particular, the fact
+  // that |grand_child| happens to preserve 3d shouldn't affect this
+  // flattening.
   gfx::Transform flattened_rotation_about_y = rotation_about_y_axis;
   flattened_rotation_about_y.FlattenTo2d();
   EXPECT_TRANSFORMATION_MATRIX_EQ(flattened_rotation_about_y,
-                                  child->ScreenSpaceTransform());
+                                  ImplOf(child)->ScreenSpaceTransform());
   EXPECT_TRANSFORMATION_MATRIX_EQ(flattened_rotation_about_y,
-                                  grand_child->ScreenSpaceTransform());
+                                  ImplOf(grand_child)->ScreenSpaceTransform());
 }
 
 TEST_F(LayerTreeHostCommonTest, ClipRectCullsRenderSurfaces) {
@@ -1968,7 +1976,7 @@
   LayerImpl* grand_child_of_rs2 = AddLayer<LayerImpl>();
   LayerImpl* child_of_top = AddLayer<LayerImpl>();
   LayerImpl* grand_child_of_top = AddLayer<LayerImpl>();
-  root->layer_tree_impl()->SetElementIdsForTesting();
+  SetElementIdsForTesting();
 
   top->SetDrawsContent(true);
   render_surface1->SetDrawsContent(true);
@@ -2653,34 +2661,40 @@
 // node for pixel-moving filter).
 TEST_F(LayerTreeHostCommonTestWithLayerTree,
        VisibleRectWithClippingAndFilters) {
-  LayerImpl* root = root_layer_for_testing();
-  LayerImpl* clip = AddChild<LayerImpl>(root);
-  LayerImpl* filter = AddChild<LayerImpl>(clip);
-  LayerImpl* filter_child = AddChild<LayerImpl>(filter);
+  auto root = Layer::Create();
+  host()->SetRootLayer(root);
+  auto clip = Layer::Create();
+  root->AddChild(clip);
+  auto filter = Layer::Create();
+  clip->AddChild(filter);
+  auto filter_child = Layer::Create();
+  filter->AddChild(filter_child);
 
   root->SetBounds(gfx::Size(100, 100));
   clip->SetBounds(gfx::Size(10, 10));
-  filter->test_properties()->force_render_surface = true;
+  filter->SetForceRenderSurfaceForTesting(true);
   filter_child->SetBounds(gfx::Size(2000, 2000));
-  filter_child->test_properties()->position = gfx::PointF(-50, -50);
-  filter_child->SetDrawsContent(true);
+  filter_child->SetPosition(gfx::PointF(-50, -50));
+  filter_child->SetIsDrawable(true);
 
   clip->SetMasksToBounds(true);
 
-  ExecuteCalculateDrawProperties(root);
-  EXPECT_EQ(gfx::Rect(50, 50, 10, 10), filter_child->visible_layer_rect());
-  EXPECT_EQ(gfx::Rect(10, 10), GetRenderSurface(filter)->content_rect());
+  CommitAndActivate();
+
+  EXPECT_EQ(gfx::Rect(50, 50, 10, 10),
+            ImplOf(filter_child)->visible_layer_rect());
+  EXPECT_EQ(gfx::Rect(10, 10), GetRenderSurfaceImpl(filter)->content_rect());
 
   FilterOperations blur_filter;
   blur_filter.Append(FilterOperation::CreateBlurFilter(4.0f));
-  filter->test_properties()->filters = blur_filter;
-  host_impl()->active_tree()->property_trees()->needs_rebuild = true;
+  filter->SetFilters(blur_filter);
 
-  ExecuteCalculateDrawProperties(root);
+  CommitAndActivate();
 
-  EXPECT_EQ(gfx::Rect(38, 38, 34, 34), filter_child->visible_layer_rect());
+  EXPECT_EQ(gfx::Rect(38, 38, 34, 34),
+            ImplOf(filter_child)->visible_layer_rect());
   EXPECT_EQ(gfx::Rect(-12, -12, 34, 34),
-            GetRenderSurface(filter)->content_rect());
+            GetRenderSurfaceImpl(filter)->content_rect());
 
   gfx::Transform vertical_flip;
   vertical_flip.Scale(1, -1);
@@ -2690,53 +2704,60 @@
   reflection_filter.Append(
       FilterOperation::CreateReferenceFilter(sk_make_sp<XfermodePaintFilter>(
           SkBlendMode::kSrcOver, std::move(flip_filter), nullptr)));
-  filter->test_properties()->filters = reflection_filter;
-  host_impl()->active_tree()->property_trees()->needs_rebuild = true;
+  filter->SetFilters(reflection_filter);
 
-  ExecuteCalculateDrawProperties(root);
+  CommitAndActivate();
 
-  EXPECT_EQ(gfx::Rect(49, 39, 12, 21), filter_child->visible_layer_rect());
+  EXPECT_EQ(gfx::Rect(49, 39, 12, 21),
+            ImplOf(filter_child)->visible_layer_rect());
   EXPECT_EQ(gfx::Rect(-1, -11, 12, 21),
-            GetRenderSurface(filter)->content_rect());
+            GetRenderSurfaceImpl(filter)->content_rect());
 }
 
 // Needs layer tree mode: testing PropertyTreeBuilder (creating expanding clip
 // node for pixel-moving filter).
 TEST_F(LayerTreeHostCommonTestWithLayerTree,
        VisibleRectWithScalingClippingAndFilters) {
-  LayerImpl* root = root_layer_for_testing();
-  LayerImpl* scale = AddChild<LayerImpl>(root);
-  LayerImpl* clip = AddChild<LayerImpl>(scale);
-  LayerImpl* filter = AddChild<LayerImpl>(clip);
-  LayerImpl* filter_child = AddChild<LayerImpl>(filter);
+  auto root = Layer::Create();
+  host()->SetRootLayer(root);
+  auto scale = Layer::Create();
+  root->AddChild(scale);
+  auto clip = Layer::Create();
+  scale->AddChild(clip);
+  auto filter = Layer::Create();
+  clip->AddChild(filter);
+  auto filter_child = Layer::Create();
+  filter->AddChild(filter_child);
 
   root->SetBounds(gfx::Size(100, 100));
   clip->SetBounds(gfx::Size(10, 10));
-  filter->test_properties()->force_render_surface = true;
+  filter->SetForceRenderSurfaceForTesting(true);
   filter_child->SetBounds(gfx::Size(2000, 2000));
-  filter_child->test_properties()->position = gfx::PointF(-50, -50);
-  filter_child->SetDrawsContent(true);
+  filter_child->SetPosition(gfx::PointF(-50, -50));
+  filter_child->SetIsDrawable(true);
 
   clip->SetMasksToBounds(true);
 
   gfx::Transform scale_transform;
   scale_transform.Scale(3, 3);
-  scale->test_properties()->transform = scale_transform;
+  scale->SetTransform(scale_transform);
 
-  ExecuteCalculateDrawProperties(root);
-  EXPECT_EQ(gfx::Rect(50, 50, 10, 10), filter_child->visible_layer_rect());
-  EXPECT_EQ(gfx::Rect(30, 30), GetRenderSurface(filter)->content_rect());
+  CommitAndActivate();
+
+  EXPECT_EQ(gfx::Rect(50, 50, 10, 10),
+            ImplOf(filter_child)->visible_layer_rect());
+  EXPECT_EQ(gfx::Rect(30, 30), GetRenderSurfaceImpl(filter)->content_rect());
 
   FilterOperations blur_filter;
   blur_filter.Append(FilterOperation::CreateBlurFilter(4.0f));
-  filter->test_properties()->filters = blur_filter;
-  host_impl()->active_tree()->property_trees()->needs_rebuild = true;
+  filter->SetFilters(blur_filter);
 
-  ExecuteCalculateDrawProperties(root);
+  CommitAndActivate();
 
-  EXPECT_EQ(gfx::Rect(38, 38, 34, 34), filter_child->visible_layer_rect());
+  EXPECT_EQ(gfx::Rect(38, 38, 34, 34),
+            ImplOf(filter_child)->visible_layer_rect());
   EXPECT_EQ(gfx::Rect(-36, -36, 102, 102),
-            GetRenderSurface(filter)->content_rect());
+            GetRenderSurfaceImpl(filter)->content_rect());
 
   gfx::Transform vertical_flip;
   vertical_flip.Scale(1, -1);
@@ -2746,14 +2767,14 @@
   reflection_filter.Append(
       FilterOperation::CreateReferenceFilter(sk_make_sp<XfermodePaintFilter>(
           SkBlendMode::kSrcOver, std::move(flip_filter), nullptr)));
-  filter->test_properties()->filters = reflection_filter;
-  host_impl()->active_tree()->property_trees()->needs_rebuild = true;
+  filter->SetFilters(reflection_filter);
 
-  ExecuteCalculateDrawProperties(root);
+  CommitAndActivate();
 
-  EXPECT_EQ(gfx::Rect(49, 39, 12, 21), filter_child->visible_layer_rect());
+  EXPECT_EQ(gfx::Rect(49, 39, 12, 21),
+            ImplOf(filter_child)->visible_layer_rect());
   EXPECT_EQ(gfx::Rect(-1, -31, 32, 61),
-            GetRenderSurface(filter)->content_rect());
+            GetRenderSurfaceImpl(filter)->content_rect());
 }
 
 TEST_F(LayerTreeHostCommonTest, ClipRectWithClipParent) {
@@ -3010,29 +3031,18 @@
 
 // Needs layer tree mode: mask layer.
 TEST_F(LayerTreeHostCommonTestWithLayerTree, OcclusionBySiblingOfTarget) {
-  FakeImplTaskRunnerProvider task_runner_provider;
-  TestTaskGraphRunner task_graph_runner;
-  std::unique_ptr<LayerTreeFrameSink> layer_tree_frame_sink =
-      FakeLayerTreeFrameSink::Create3d();
-  FakeLayerTreeHostImpl host_impl(&task_runner_provider, &task_graph_runner);
+  auto root = Layer::Create();
+  auto child = Layer::Create();
+  FakeContentLayerClient client;
+  auto surface = PictureLayer::Create(&client);
+  auto surface_child = PictureLayer::Create(&client);
+  auto surface_sibling = PictureLayer::Create(&client);
+  auto surface_child_mask = PictureLayer::Create(&client);
 
-  std::unique_ptr<LayerImpl> root =
-      LayerImpl::Create(host_impl.active_tree(), 1);
-  std::unique_ptr<LayerImpl> child =
-      LayerImpl::Create(host_impl.active_tree(), 2);
-  std::unique_ptr<TextureLayerImpl> surface =
-      TextureLayerImpl::Create(host_impl.active_tree(), 3);
-  std::unique_ptr<TextureLayerImpl> surface_child =
-      TextureLayerImpl::Create(host_impl.active_tree(), 4);
-  std::unique_ptr<TextureLayerImpl> surface_sibling =
-      TextureLayerImpl::Create(host_impl.active_tree(), 5);
-  std::unique_ptr<TextureLayerImpl> surface_child_mask =
-      TextureLayerImpl::Create(host_impl.active_tree(), 6);
-
-  surface->SetDrawsContent(true);
-  surface_child->SetDrawsContent(true);
-  surface_sibling->SetDrawsContent(true);
-  surface_child_mask->SetDrawsContent(true);
+  surface->SetIsDrawable(true);
+  surface_child->SetIsDrawable(true);
+  surface_sibling->SetIsDrawable(true);
+  surface_child_mask->SetIsDrawable(true);
   surface->SetContentsOpaque(true);
   surface_child->SetContentsOpaque(true);
   surface_sibling->SetContentsOpaque(true);
@@ -3043,67 +3053,64 @@
 
   root->SetBounds(gfx::Size(1000, 1000));
   child->SetBounds(gfx::Size(300, 300));
-  surface->test_properties()->transform = translate;
+  surface->SetTransform(translate);
   surface->SetBounds(gfx::Size(300, 300));
-  surface->test_properties()->force_render_surface = true;
+  surface->SetForceRenderSurfaceForTesting(true);
   surface_child->SetBounds(gfx::Size(300, 300));
-  surface_child->test_properties()->force_render_surface = true;
+  surface_child->SetForceRenderSurfaceForTesting(true);
   surface_sibling->SetBounds(gfx::Size(200, 200));
+  surface_child_mask->SetBounds(gfx::Size(300, 300));
 
-  LayerImpl* surface_ptr = surface.get();
-  LayerImpl* surface_child_ptr = surface_child.get();
-  LayerImpl* surface_child_mask_ptr = surface_child_mask.get();
+  surface_child->SetMaskLayer(surface_child_mask);
+  surface->AddChild(surface_child);
+  child->AddChild(surface);
+  child->AddChild(surface_sibling);
+  root->AddChild(child);
+  host()->SetRootLayer(root);
 
-  host_impl.active_tree()->SetDeviceViewportRect(gfx::Rect(root->bounds()));
-
-  surface_child->test_properties()->SetMaskLayer(std::move(surface_child_mask));
-  surface->test_properties()->AddChild(std::move(surface_child));
-  child->test_properties()->AddChild(std::move(surface));
-  child->test_properties()->AddChild(std::move(surface_sibling));
-  root->test_properties()->AddChild(std::move(child));
-  host_impl.active_tree()->SetRootLayerForTesting(std::move(root));
-  host_impl.SetVisible(true);
-  host_impl.InitializeFrameSink(layer_tree_frame_sink.get());
-  host_impl.active_tree()->BuildLayerListAndPropertyTreesForTesting();
-  host_impl.active_tree()->UpdateDrawProperties();
+  CommitAndActivate();
+  host_impl()->active_tree()->UpdateDrawProperties();
 
   EXPECT_TRANSFORMATION_MATRIX_EQ(
-      GetRenderSurface(surface_ptr)->draw_transform(), translate);
+      GetRenderSurfaceImpl(surface)->draw_transform(), translate);
   // surface_sibling draws into the root render surface and occludes
   // surface_child's contents.
   Occlusion actual_occlusion =
-      GetRenderSurface(surface_child_ptr)->occlusion_in_content_space();
+      GetRenderSurfaceImpl(surface_child)->occlusion_in_content_space();
   Occlusion expected_occlusion(translate, SimpleEnclosedRegion(gfx::Rect()),
                                SimpleEnclosedRegion(gfx::Rect(200, 200)));
   EXPECT_TRUE(expected_occlusion.IsEqual(actual_occlusion));
 
   // Mask layer should have the same occlusion.
   actual_occlusion =
-      surface_child_mask_ptr->draw_properties().occlusion_in_content_space;
+      ImplOf(surface_child_mask)->draw_properties().occlusion_in_content_space;
   EXPECT_TRUE(expected_occlusion.IsEqual(actual_occlusion));
 }
 
 // Needs layer tree mode: testing PropertyTreeBuilder (snapping transform for
 // texture layer).
 TEST_F(LayerTreeHostCommonTestWithLayerTree, TextureLayerSnapping) {
-  LayerImpl* root = root_layer_for_testing();
-  TextureLayerImpl* child = AddChildToRoot<TextureLayerImpl>();
+  auto root = Layer::Create();
+  host()->SetRootLayer(root);
+  auto child = TextureLayer::CreateForMailbox(nullptr);
+  root->AddChild(child);
 
   root->SetBounds(gfx::Size(100, 100));
   child->SetBounds(gfx::Size(100, 100));
-  child->SetDrawsContent(true);
+  child->SetIsDrawable(true);
   gfx::Transform fractional_translate;
   fractional_translate.Translate(10.5f, 20.3f);
-  child->test_properties()->transform = fractional_translate;
+  child->SetTransform(fractional_translate);
 
-  ExecuteCalculateDrawProperties(root);
+  CommitAndActivate();
 
-  EXPECT_NE(child->ScreenSpaceTransform(), fractional_translate);
+  auto child_screen_space_transform = ImplOf(child)->ScreenSpaceTransform();
+  EXPECT_NE(child_screen_space_transform, fractional_translate);
   fractional_translate.RoundTranslationComponents();
-  EXPECT_TRANSFORMATION_MATRIX_EQ(child->ScreenSpaceTransform(),
+  EXPECT_TRANSFORMATION_MATRIX_EQ(child_screen_space_transform,
                                   fractional_translate);
   gfx::RectF layer_bounds_in_screen_space = MathUtil::MapClippedRect(
-      child->ScreenSpaceTransform(), gfx::RectF(gfx::SizeF(child->bounds())));
+      child_screen_space_transform, gfx::RectF(gfx::SizeF(child->bounds())));
   EXPECT_EQ(layer_bounds_in_screen_space, gfx::RectF(11.f, 20.f, 100.f, 100.f));
 }
 
@@ -3715,43 +3722,44 @@
 // Needs layer tree mode: testing PropertyTreeBuilder.
 TEST_F(LayerTreeHostCommonTestWithLayerTree,
        BackFaceCullingWithoutPreserves3d) {
-  LayerImpl* root = root_layer_for_testing();
-  LayerImpl* front_facing_child = AddChildToRoot<LayerImpl>();
-  LayerImpl* back_facing_child = AddChildToRoot<LayerImpl>();
-  LayerImpl* front_facing_surface = AddChildToRoot<LayerImpl>();
-  LayerImpl* back_facing_surface = AddChildToRoot<LayerImpl>();
-  LayerImpl* front_facing_child_of_front_facing_surface =
-      AddChild<LayerImpl>(front_facing_surface);
-  LayerImpl* back_facing_child_of_front_facing_surface =
-      AddChild<LayerImpl>(front_facing_surface);
-  LayerImpl* front_facing_child_of_back_facing_surface =
-      AddChild<LayerImpl>(back_facing_surface);
-  LayerImpl* back_facing_child_of_back_facing_surface =
-      AddChild<LayerImpl>(back_facing_surface);
+  auto root = Layer::Create();
+  host()->SetRootLayer(root);
+  auto front_facing_child = Layer::Create();
+  root->AddChild(front_facing_child);
+  auto back_facing_child = Layer::Create();
+  root->AddChild(back_facing_child);
+  auto front_facing_surface = Layer::Create();
+  root->AddChild(front_facing_surface);
+  auto back_facing_surface = Layer::Create();
+  root->AddChild(back_facing_surface);
+  auto front_facing_child_of_front_facing_surface = Layer::Create();
+  front_facing_surface->AddChild(front_facing_child_of_front_facing_surface);
+  auto back_facing_child_of_front_facing_surface = Layer::Create();
+  front_facing_surface->AddChild(back_facing_child_of_front_facing_surface);
+  auto front_facing_child_of_back_facing_surface = Layer::Create();
+  back_facing_surface->AddChild(front_facing_child_of_back_facing_surface);
+  auto back_facing_child_of_back_facing_surface = Layer::Create();
+  back_facing_surface->AddChild(back_facing_child_of_back_facing_surface);
 
   // Nothing is double-sided
-  front_facing_child->test_properties()->double_sided = false;
-  back_facing_child->test_properties()->double_sided = false;
-  front_facing_surface->test_properties()->double_sided = false;
-  back_facing_surface->test_properties()->double_sided = false;
-  front_facing_child_of_front_facing_surface->test_properties()->double_sided =
-      false;
-  back_facing_child_of_front_facing_surface->test_properties()->double_sided =
-      false;
-  front_facing_child_of_back_facing_surface->test_properties()->double_sided =
-      false;
-  back_facing_child_of_back_facing_surface->test_properties()->double_sided =
-      false;
+  front_facing_child->SetDoubleSided(false);
+  back_facing_child->SetDoubleSided(false);
+  front_facing_surface->SetDoubleSided(false);
+  back_facing_surface->SetDoubleSided(false);
+  front_facing_child_of_front_facing_surface->SetDoubleSided(false);
+  back_facing_child_of_front_facing_surface->SetDoubleSided(false);
+  front_facing_child_of_back_facing_surface->SetDoubleSided(false);
+  back_facing_child_of_back_facing_surface->SetDoubleSided(false);
 
   // Everything draws content.
-  front_facing_child->SetDrawsContent(true);
-  back_facing_child->SetDrawsContent(true);
-  front_facing_surface->SetDrawsContent(true);
-  back_facing_surface->SetDrawsContent(true);
-  front_facing_child_of_front_facing_surface->SetDrawsContent(true);
-  back_facing_child_of_front_facing_surface->SetDrawsContent(true);
-  front_facing_child_of_back_facing_surface->SetDrawsContent(true);
-  back_facing_child_of_back_facing_surface->SetDrawsContent(true);
+  front_facing_child->SetIsDrawable(true);
+  back_facing_child->SetIsDrawable(true);
+  front_facing_surface->SetIsDrawable(true);
+  back_facing_surface->SetIsDrawable(true);
+  front_facing_child_of_front_facing_surface->SetIsDrawable(true);
+  back_facing_child_of_front_facing_surface->SetIsDrawable(true);
+  front_facing_child_of_back_facing_surface->SetIsDrawable(true);
+  back_facing_child_of_back_facing_surface->SetIsDrawable(true);
 
   gfx::Transform backface_matrix;
   backface_matrix.Translate(50.0, 50.0);
@@ -3768,38 +3776,40 @@
   front_facing_child_of_back_facing_surface->SetBounds(gfx::Size(100, 100));
   back_facing_child_of_back_facing_surface->SetBounds(gfx::Size(100, 100));
 
-  front_facing_surface->test_properties()->force_render_surface = true;
-  back_facing_surface->test_properties()->force_render_surface = true;
+  front_facing_surface->SetForceRenderSurfaceForTesting(true);
+  back_facing_surface->SetForceRenderSurfaceForTesting(true);
 
-  back_facing_child->test_properties()->transform = backface_matrix;
-  back_facing_surface->test_properties()->transform = backface_matrix;
-  back_facing_child_of_front_facing_surface->test_properties()->transform =
-      backface_matrix;
-  back_facing_child_of_back_facing_surface->test_properties()->transform =
-      backface_matrix;
+  back_facing_child->SetTransform(backface_matrix);
+  back_facing_surface->SetTransform(backface_matrix);
+  back_facing_child_of_front_facing_surface->SetTransform(backface_matrix);
+  back_facing_child_of_back_facing_surface->SetTransform(backface_matrix);
 
   // Note: No layers preserve 3d. According to current W3C CSS gfx::Transforms
   // spec, these layers should blindly use their own local transforms to
   // determine back-face culling.
-  ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root);
+  CommitAndActivate();
 
   // Verify which render surfaces were created.
-  EXPECT_EQ(GetRenderSurface(front_facing_child), GetRenderSurface(root));
-  EXPECT_EQ(GetRenderSurface(back_facing_child), GetRenderSurface(root));
-  EXPECT_NE(GetRenderSurface(front_facing_surface), GetRenderSurface(root));
-  EXPECT_NE(GetRenderSurface(back_facing_surface), GetRenderSurface(root));
-  EXPECT_NE(GetRenderSurface(back_facing_surface),
-            GetRenderSurface(front_facing_surface));
-  EXPECT_EQ(GetRenderSurface(front_facing_child_of_front_facing_surface),
-            GetRenderSurface(front_facing_surface));
-  EXPECT_EQ(GetRenderSurface(back_facing_child_of_front_facing_surface),
-            GetRenderSurface(front_facing_surface));
-  EXPECT_EQ(GetRenderSurface(front_facing_child_of_back_facing_surface),
-            GetRenderSurface(back_facing_surface));
-  EXPECT_EQ(GetRenderSurface(back_facing_child_of_back_facing_surface),
-            GetRenderSurface(back_facing_surface));
+  EXPECT_EQ(GetRenderSurfaceImpl(front_facing_child),
+            GetRenderSurfaceImpl(root));
+  EXPECT_EQ(GetRenderSurfaceImpl(back_facing_child),
+            GetRenderSurfaceImpl(root));
+  EXPECT_NE(GetRenderSurfaceImpl(front_facing_surface),
+            GetRenderSurfaceImpl(root));
+  EXPECT_NE(GetRenderSurfaceImpl(back_facing_surface),
+            GetRenderSurfaceImpl(root));
+  EXPECT_NE(GetRenderSurfaceImpl(back_facing_surface),
+            GetRenderSurfaceImpl(front_facing_surface));
+  EXPECT_EQ(GetRenderSurfaceImpl(front_facing_child_of_front_facing_surface),
+            GetRenderSurfaceImpl(front_facing_surface));
+  EXPECT_EQ(GetRenderSurfaceImpl(back_facing_child_of_front_facing_surface),
+            GetRenderSurfaceImpl(front_facing_surface));
+  EXPECT_EQ(GetRenderSurfaceImpl(front_facing_child_of_back_facing_surface),
+            GetRenderSurfaceImpl(back_facing_surface));
+  EXPECT_EQ(GetRenderSurfaceImpl(back_facing_child_of_back_facing_surface),
+            GetRenderSurfaceImpl(back_facing_surface));
 
-  EXPECT_EQ(3u, update_layer_impl_list()->size());
+  EXPECT_EQ(3u, update_layer_impl_list().size());
   EXPECT_TRUE(UpdateLayerImplListContains(front_facing_child->id()));
   EXPECT_TRUE(UpdateLayerImplListContains(front_facing_surface->id()));
   EXPECT_TRUE(UpdateLayerImplListContains(
@@ -3810,50 +3820,54 @@
 // is used.
 // Needs layer tree mode: testing PropertyTreeBuilder.
 TEST_F(LayerTreeHostCommonTestWithLayerTree, BackFaceCullingWithPreserves3d) {
-  LayerImpl* root = root_layer_for_testing();
-  LayerImpl* front_facing_child = AddChildToRoot<LayerImpl>();
-  LayerImpl* back_facing_child = AddChildToRoot<LayerImpl>();
-  LayerImpl* front_facing_surface = AddChildToRoot<LayerImpl>();
-  LayerImpl* back_facing_surface = AddChildToRoot<LayerImpl>();
-  LayerImpl* front_facing_child_of_front_facing_surface =
-      AddChild<LayerImpl>(front_facing_surface);
-  LayerImpl* back_facing_child_of_front_facing_surface =
-      AddChild<LayerImpl>(front_facing_surface);
-  LayerImpl* front_facing_child_of_back_facing_surface =
-      AddChild<LayerImpl>(back_facing_surface);
-  LayerImpl* back_facing_child_of_back_facing_surface =
-      AddChild<LayerImpl>(back_facing_surface);
+  auto root = Layer::Create();
+  host()->SetRootLayer(root);
+  auto front_facing_child = Layer::Create();
+  root->AddChild(front_facing_child);
+  auto back_facing_child = Layer::Create();
+  root->AddChild(back_facing_child);
+  auto front_facing_surface = Layer::Create();
+  root->AddChild(front_facing_surface);
+  auto back_facing_surface = Layer::Create();
+  root->AddChild(back_facing_surface);
+  auto front_facing_child_of_front_facing_surface = Layer::Create();
+  front_facing_surface->AddChild(front_facing_child_of_front_facing_surface);
+  auto back_facing_child_of_front_facing_surface = Layer::Create();
+  front_facing_surface->AddChild(back_facing_child_of_front_facing_surface);
+  auto front_facing_child_of_back_facing_surface = Layer::Create();
+  back_facing_surface->AddChild(front_facing_child_of_back_facing_surface);
+  auto back_facing_child_of_back_facing_surface = Layer::Create();
+  back_facing_surface->AddChild(back_facing_child_of_back_facing_surface);
   // Opacity will not force creation of render surfaces in this case because of
   // the preserve-3d transform style. Instead, an example of when a surface
   // would be created with preserve-3d is when there is a mask layer.
-  LayerImpl* dummy_mask_layer1 = AddMaskLayer<LayerImpl>(front_facing_surface);
-  LayerImpl* dummy_mask_layer2 = AddMaskLayer<LayerImpl>(back_facing_surface);
+  FakeContentLayerClient client;
+  auto dummy_mask_layer1 = PictureLayer::Create(&client);
+  front_facing_surface->SetMaskLayer(dummy_mask_layer1);
+  auto dummy_mask_layer2 = PictureLayer::Create(&client);
+  back_facing_surface->SetMaskLayer(dummy_mask_layer2);
 
   // Nothing is double-sided
-  front_facing_child->test_properties()->double_sided = false;
-  back_facing_child->test_properties()->double_sided = false;
-  front_facing_surface->test_properties()->double_sided = false;
-  back_facing_surface->test_properties()->double_sided = false;
-  front_facing_child_of_front_facing_surface->test_properties()->double_sided =
-      false;
-  back_facing_child_of_front_facing_surface->test_properties()->double_sided =
-      false;
-  front_facing_child_of_back_facing_surface->test_properties()->double_sided =
-      false;
-  back_facing_child_of_back_facing_surface->test_properties()->double_sided =
-      false;
+  front_facing_child->SetDoubleSided(false);
+  back_facing_child->SetDoubleSided(false);
+  front_facing_surface->SetDoubleSided(false);
+  back_facing_surface->SetDoubleSided(false);
+  front_facing_child_of_front_facing_surface->SetDoubleSided(false);
+  back_facing_child_of_front_facing_surface->SetDoubleSided(false);
+  front_facing_child_of_back_facing_surface->SetDoubleSided(false);
+  back_facing_child_of_back_facing_surface->SetDoubleSided(false);
 
   // Everything draws content.
-  front_facing_child->SetDrawsContent(true);
-  back_facing_child->SetDrawsContent(true);
-  front_facing_surface->SetDrawsContent(true);
-  back_facing_surface->SetDrawsContent(true);
-  front_facing_child_of_front_facing_surface->SetDrawsContent(true);
-  back_facing_child_of_front_facing_surface->SetDrawsContent(true);
-  front_facing_child_of_back_facing_surface->SetDrawsContent(true);
-  back_facing_child_of_back_facing_surface->SetDrawsContent(true);
-  dummy_mask_layer1->SetDrawsContent(true);
-  dummy_mask_layer2->SetDrawsContent(true);
+  front_facing_child->SetIsDrawable(true);
+  back_facing_child->SetIsDrawable(true);
+  front_facing_surface->SetIsDrawable(true);
+  back_facing_surface->SetIsDrawable(true);
+  front_facing_child_of_front_facing_surface->SetIsDrawable(true);
+  back_facing_child_of_front_facing_surface->SetIsDrawable(true);
+  front_facing_child_of_back_facing_surface->SetIsDrawable(true);
+  back_facing_child_of_back_facing_surface->SetIsDrawable(true);
+  dummy_mask_layer1->SetIsDrawable(true);
+  dummy_mask_layer2->SetIsDrawable(true);
 
   gfx::Transform backface_matrix;
   backface_matrix.Translate(50.0, 50.0);
@@ -3869,52 +3883,52 @@
   back_facing_child_of_front_facing_surface->SetBounds(gfx::Size(100, 100));
   front_facing_child_of_back_facing_surface->SetBounds(gfx::Size(100, 100));
   back_facing_child_of_back_facing_surface->SetBounds(gfx::Size(100, 100));
+  dummy_mask_layer1->SetBounds(gfx::Size(100, 100));
+  dummy_mask_layer2->SetBounds(gfx::Size(100, 100));
 
-  back_facing_child->test_properties()->transform = backface_matrix;
-  back_facing_surface->test_properties()->transform = backface_matrix;
-  back_facing_child_of_front_facing_surface->test_properties()->transform =
-      backface_matrix;
-  back_facing_child_of_back_facing_surface->test_properties()->transform =
-      backface_matrix;
+  back_facing_child->SetTransform(backface_matrix);
+  back_facing_surface->SetTransform(backface_matrix);
+  back_facing_child_of_front_facing_surface->SetTransform(backface_matrix);
+  back_facing_child_of_back_facing_surface->SetTransform(backface_matrix);
 
   // Each surface creates its own new 3d rendering context (as defined by W3C
   // spec).  According to current W3C CSS gfx::Transforms spec, layers in a 3d
   // rendering context should use the transform with respect to that context.
   // This 3d rendering context occurs when (a) parent's transform style is flat
   // and (b) the layer's transform style is preserve-3d.
-  front_facing_surface->test_properties()->should_flatten_transform = false;
-  front_facing_surface->test_properties()->sorting_context_id = 1;
-  back_facing_surface->test_properties()->should_flatten_transform = false;
-  back_facing_surface->test_properties()->sorting_context_id = 1;
-  front_facing_child_of_front_facing_surface->test_properties()
-      ->sorting_context_id = 1;
-  back_facing_child_of_front_facing_surface->test_properties()
-      ->sorting_context_id = 1;
-  front_facing_child_of_back_facing_surface->test_properties()
-      ->sorting_context_id = 1;
-  back_facing_child_of_back_facing_surface->test_properties()
-      ->sorting_context_id = 1;
+  front_facing_surface->SetShouldFlattenTransform(false);
+  front_facing_surface->Set3dSortingContextId(1);
+  back_facing_surface->SetShouldFlattenTransform(false);
+  back_facing_surface->Set3dSortingContextId(1);
+  front_facing_child_of_front_facing_surface->Set3dSortingContextId(1);
+  back_facing_child_of_front_facing_surface->Set3dSortingContextId(1);
+  front_facing_child_of_back_facing_surface->Set3dSortingContextId(1);
+  back_facing_child_of_back_facing_surface->Set3dSortingContextId(1);
 
-  ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root);
+  CommitAndActivate();
 
   // Verify which render surfaces were created and used.
-  EXPECT_EQ(GetRenderSurface(front_facing_child), GetRenderSurface(root));
-  EXPECT_EQ(GetRenderSurface(back_facing_child), GetRenderSurface(root));
-  EXPECT_NE(GetRenderSurface(front_facing_surface), GetRenderSurface(root));
+  EXPECT_EQ(GetRenderSurfaceImpl(front_facing_child),
+            GetRenderSurfaceImpl(root));
+  EXPECT_EQ(GetRenderSurfaceImpl(back_facing_child),
+            GetRenderSurfaceImpl(root));
+  EXPECT_NE(GetRenderSurfaceImpl(front_facing_surface),
+            GetRenderSurfaceImpl(root));
   // We expect that a render surface was created but not used.
-  EXPECT_NE(GetRenderSurface(back_facing_surface), GetRenderSurface(root));
-  EXPECT_NE(GetRenderSurface(back_facing_surface),
-            GetRenderSurface(front_facing_surface));
-  EXPECT_EQ(GetRenderSurface(front_facing_child_of_front_facing_surface),
-            GetRenderSurface(front_facing_surface));
-  EXPECT_EQ(GetRenderSurface(back_facing_child_of_front_facing_surface),
-            GetRenderSurface(front_facing_surface));
-  EXPECT_EQ(GetRenderSurface(front_facing_child_of_back_facing_surface),
-            GetRenderSurface(back_facing_surface));
-  EXPECT_EQ(GetRenderSurface(back_facing_child_of_back_facing_surface),
-            GetRenderSurface(back_facing_surface));
+  EXPECT_NE(GetRenderSurfaceImpl(back_facing_surface),
+            GetRenderSurfaceImpl(root));
+  EXPECT_NE(GetRenderSurfaceImpl(back_facing_surface),
+            GetRenderSurfaceImpl(front_facing_surface));
+  EXPECT_EQ(GetRenderSurfaceImpl(front_facing_child_of_front_facing_surface),
+            GetRenderSurfaceImpl(front_facing_surface));
+  EXPECT_EQ(GetRenderSurfaceImpl(back_facing_child_of_front_facing_surface),
+            GetRenderSurfaceImpl(front_facing_surface));
+  EXPECT_EQ(GetRenderSurfaceImpl(front_facing_child_of_back_facing_surface),
+            GetRenderSurfaceImpl(back_facing_surface));
+  EXPECT_EQ(GetRenderSurfaceImpl(back_facing_child_of_back_facing_surface),
+            GetRenderSurfaceImpl(back_facing_surface));
 
-  EXPECT_EQ(3u, update_layer_impl_list()->size());
+  EXPECT_EQ(3u, update_layer_impl_list().size());
 
   EXPECT_TRUE(UpdateLayerImplListContains(front_facing_child->id()));
   EXPECT_TRUE(UpdateLayerImplListContains(front_facing_surface->id()));
@@ -3929,74 +3943,80 @@
 // Needs layer tree mode: testing PropertyTreeBuilder.
 TEST_F(LayerTreeHostCommonTestWithLayerTree,
        BackFaceCullingWithAnimatingTransforms) {
-  LayerImpl* root = root_layer_for_testing();
-  LayerImpl* child = AddLayer<LayerImpl>();
-  LayerImpl* animating_surface = AddLayer<LayerImpl>();
-  LayerImpl* child_of_animating_surface =
-      AddChild<LayerImpl>(animating_surface);
-  LayerImpl* animating_child = AddLayer<LayerImpl>();
-  LayerImpl* child2 = AddLayer<LayerImpl>();
+  auto root = Layer::Create();
+  host()->SetRootLayer(root);
+  auto child = Layer::Create();
+  root->AddChild(child);
+  auto animating_surface = Layer::Create();
+  root->AddChild(animating_surface);
+  auto child_of_animating_surface = Layer::Create();
+  animating_surface->AddChild(child_of_animating_surface);
+  auto animating_child = Layer::Create();
+  root->AddChild(animating_child);
+  auto child2 = Layer::Create();
+  root->AddChild(child2);
 
   // Nothing is double-sided
-  child->test_properties()->double_sided = false;
-  child2->test_properties()->double_sided = false;
-  animating_surface->test_properties()->double_sided = false;
-  child_of_animating_surface->test_properties()->double_sided = false;
-  animating_child->test_properties()->double_sided = false;
+  child->SetDoubleSided(false);
+  child2->SetDoubleSided(false);
+  animating_surface->SetDoubleSided(false);
+  child_of_animating_surface->SetDoubleSided(false);
+  animating_child->SetDoubleSided(false);
 
   // Everything draws content.
-  child->SetDrawsContent(true);
-  child2->SetDrawsContent(true);
-  animating_surface->SetDrawsContent(true);
-  child_of_animating_surface->SetDrawsContent(true);
-  animating_child->SetDrawsContent(true);
+  child->SetIsDrawable(true);
+  child2->SetIsDrawable(true);
+  animating_surface->SetIsDrawable(true);
+  child_of_animating_surface->SetIsDrawable(true);
+  animating_child->SetIsDrawable(true);
 
   gfx::Transform backface_matrix;
   backface_matrix.Translate(50.0, 50.0);
   backface_matrix.RotateAboutYAxis(180.0);
   backface_matrix.Translate(-50.0, -50.0);
 
-  SetElementIdsForTesting();
+  host()->SetElementIdsForTesting();
 
   // Animate the transform on the render surface.
   AddAnimatedTransformToElementWithAnimation(animating_surface->element_id(),
-                                             timeline_impl(), 10.0, 30, 0);
+                                             timeline(), 10.0, 30, 0);
   // This is just an animating layer, not a surface.
   AddAnimatedTransformToElementWithAnimation(animating_child->element_id(),
-                                             timeline_impl(), 10.0, 30, 0);
+                                             timeline(), 10.0, 30, 0);
 
   root->SetBounds(gfx::Size(100, 100));
   child->SetBounds(gfx::Size(100, 100));
-  child->test_properties()->transform = backface_matrix;
+  child->SetTransform(backface_matrix);
   animating_surface->SetBounds(gfx::Size(100, 100));
-  animating_surface->test_properties()->transform = backface_matrix;
-  animating_surface->test_properties()->force_render_surface = true;
+  animating_surface->SetTransform(backface_matrix);
+  animating_surface->SetForceRenderSurfaceForTesting(true);
   child_of_animating_surface->SetBounds(gfx::Size(100, 100));
-  child_of_animating_surface->test_properties()->transform = backface_matrix;
+  child_of_animating_surface->SetTransform(backface_matrix);
   animating_child->SetBounds(gfx::Size(100, 100));
-  animating_child->test_properties()->transform = backface_matrix;
+  animating_child->SetTransform(backface_matrix);
   child2->SetBounds(gfx::Size(100, 100));
 
-  ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root);
+  CommitAndActivate();
 
-  EXPECT_EQ(GetRenderSurface(child), GetRenderSurface(root));
-  EXPECT_TRUE(GetRenderSurface(animating_surface));
-  EXPECT_EQ(GetRenderSurface(child_of_animating_surface),
-            GetRenderSurface(animating_surface));
-  EXPECT_EQ(GetRenderSurface(animating_child), GetRenderSurface(root));
-  EXPECT_EQ(GetRenderSurface(child2), GetRenderSurface(root));
+  EXPECT_EQ(GetRenderSurfaceImpl(child), GetRenderSurfaceImpl(root));
+  EXPECT_TRUE(GetRenderSurfaceImpl(animating_surface));
+  EXPECT_EQ(GetRenderSurfaceImpl(child_of_animating_surface),
+            GetRenderSurfaceImpl(animating_surface));
+  EXPECT_EQ(GetRenderSurfaceImpl(animating_child), GetRenderSurfaceImpl(root));
+  EXPECT_EQ(GetRenderSurfaceImpl(child2), GetRenderSurfaceImpl(root));
 
-  EXPECT_EQ(1u, update_layer_impl_list()->size());
+  EXPECT_EQ(1u, update_layer_impl_list().size());
 
   // The back facing layers are culled from the layer list, and have an empty
   // visible rect.
   EXPECT_TRUE(UpdateLayerImplListContains(child2->id()));
-  EXPECT_TRUE(child->visible_layer_rect().IsEmpty());
-  EXPECT_TRUE(animating_surface->visible_layer_rect().IsEmpty());
-  EXPECT_TRUE(child_of_animating_surface->visible_layer_rect().IsEmpty());
-  EXPECT_TRUE(animating_child->visible_layer_rect().IsEmpty());
+  EXPECT_TRUE(ImplOf(child)->visible_layer_rect().IsEmpty());
+  EXPECT_TRUE(ImplOf(animating_surface)->visible_layer_rect().IsEmpty());
+  EXPECT_TRUE(
+      ImplOf(child_of_animating_surface)->visible_layer_rect().IsEmpty());
+  EXPECT_TRUE(ImplOf(animating_child)->visible_layer_rect().IsEmpty());
 
-  EXPECT_EQ(gfx::Rect(100, 100), child2->visible_layer_rect());
+  EXPECT_EQ(gfx::Rect(100, 100), ImplOf(child2)->visible_layer_rect());
 }
 
 // Verify the behavior of back-face culling for a render surface that is
@@ -4004,21 +4024,26 @@
 // Needs layer tree mode: testing PropertyTreeBuilder.
 TEST_F(LayerTreeHostCommonTestWithLayerTree,
        BackFaceCullingWithPreserves3dForFlatteningSurface) {
-  LayerImpl* root = root_layer_for_testing();
-  LayerImpl* front_facing_surface = AddChildToRoot<LayerImpl>();
-  LayerImpl* back_facing_surface = AddChildToRoot<LayerImpl>();
-  LayerImpl* child1 = AddChild<LayerImpl>(front_facing_surface);
-  LayerImpl* child2 = AddChild<LayerImpl>(back_facing_surface);
+  auto root = Layer::Create();
+  host()->SetRootLayer(root);
+  auto front_facing_surface = Layer::Create();
+  root->AddChild(front_facing_surface);
+  auto back_facing_surface = Layer::Create();
+  root->AddChild(back_facing_surface);
+  auto child1 = Layer::Create();
+  front_facing_surface->AddChild(child1);
+  auto child2 = Layer::Create();
+  back_facing_surface->AddChild(child2);
 
   // RenderSurfaces are not double-sided
-  front_facing_surface->test_properties()->double_sided = false;
-  back_facing_surface->test_properties()->double_sided = false;
+  front_facing_surface->SetDoubleSided(false);
+  back_facing_surface->SetDoubleSided(false);
 
   // Everything draws content.
-  front_facing_surface->SetDrawsContent(true);
-  back_facing_surface->SetDrawsContent(true);
-  child1->SetDrawsContent(true);
-  child2->SetDrawsContent(true);
+  front_facing_surface->SetIsDrawable(true);
+  back_facing_surface->SetIsDrawable(true);
+  child1->SetIsDrawable(true);
+  child2->SetIsDrawable(true);
 
   gfx::Transform backface_matrix;
   backface_matrix.Translate(50.0, 50.0);
@@ -4027,27 +4052,30 @@
 
   root->SetBounds(gfx::Size(100, 100));
   front_facing_surface->SetBounds(gfx::Size(100, 100));
-  front_facing_surface->test_properties()->force_render_surface = true;
+  front_facing_surface->SetForceRenderSurfaceForTesting(true);
   back_facing_surface->SetBounds(gfx::Size(100, 100));
-  back_facing_surface->test_properties()->transform = backface_matrix;
-  back_facing_surface->test_properties()->force_render_surface = true;
+  back_facing_surface->SetTransform(backface_matrix);
+  back_facing_surface->SetForceRenderSurfaceForTesting(true);
   child1->SetBounds(gfx::Size(100, 100));
   child2->SetBounds(gfx::Size(100, 100));
 
-  front_facing_surface->test_properties()->sorting_context_id = 1;
-  back_facing_surface->test_properties()->sorting_context_id = 1;
+  front_facing_surface->Set3dSortingContextId(1);
+  back_facing_surface->Set3dSortingContextId(1);
 
-  ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root);
+  CommitAndActivate();
 
   // Verify which render surfaces were created and used.
-  EXPECT_TRUE(GetRenderSurface(front_facing_surface));
+  EXPECT_TRUE(GetRenderSurfaceImpl(front_facing_surface));
 
   // We expect the render surface to have been created, but remain unused.
-  EXPECT_NE(GetRenderSurface(back_facing_surface), GetRenderSurface(root));
-  EXPECT_EQ(GetRenderSurface(child1), GetRenderSurface(front_facing_surface));
-  EXPECT_EQ(GetRenderSurface(child2), GetRenderSurface(back_facing_surface));
+  EXPECT_NE(GetRenderSurfaceImpl(back_facing_surface),
+            GetRenderSurfaceImpl(root));
+  EXPECT_EQ(GetRenderSurfaceImpl(child1),
+            GetRenderSurfaceImpl(front_facing_surface));
+  EXPECT_EQ(GetRenderSurfaceImpl(child2),
+            GetRenderSurfaceImpl(back_facing_surface));
 
-  EXPECT_EQ(2u, update_layer_impl_list()->size());
+  EXPECT_EQ(2u, update_layer_impl_list().size());
   EXPECT_TRUE(UpdateLayerImplListContains(front_facing_surface->id()));
   EXPECT_TRUE(UpdateLayerImplListContains(child1->id()));
 }
@@ -4190,14 +4218,15 @@
 
   float device_scale_factor = 2.5f;
   float page_scale_factor = 3.f;
+  const gfx::Transform kDeviceTransform;
 
   LayerTreeImpl::ViewportLayerIds viewport_ids;
   viewport_ids.page_scale = page_scale->id();
   root->layer_tree_impl()->SetViewportLayersFromIds(viewport_ids);
   root->layer_tree_impl()->SetPageScaleOnActiveTree(page_scale_factor);
 
-  ExecuteCalculateDrawProperties(root, device_scale_factor, page_scale_factor,
-                                 page_scale, nullptr, nullptr);
+  ExecuteCalculateDrawProperties(root, device_scale_factor, kDeviceTransform,
+                                 page_scale_factor, page_scale);
 
   EXPECT_FLOAT_EQ(device_scale_factor * page_scale_factor,
                   parent->GetIdealContentsScale());
@@ -4278,6 +4307,7 @@
 
   float device_scale_factor = 2.5f;
   float page_scale_factor = 0.01f;
+  const gfx::Transform kDeviceTransform;
 
   SetupRootProperties(root);
   CopyProperties(root, page_scale);
@@ -4287,8 +4317,8 @@
   CopyProperties(parent, child_scale);
   CreateTransformNode(child_scale).local = child_scale_matrix;
 
-  ExecuteCalculateDrawProperties(root, device_scale_factor, page_scale_factor,
-                                 page_scale, nullptr, nullptr);
+  ExecuteCalculateDrawProperties(root, device_scale_factor, kDeviceTransform,
+                                 page_scale_factor, page_scale);
 
   // The ideal scale is able to go below 1.
   float expected_ideal_scale =
@@ -4459,7 +4489,7 @@
   scoped_refptr<PictureLayer> mask_layer = PictureLayer::Create(&client);
 
   child->AddChild(grand_child.get());
-  child->SetMaskLayer(mask_layer.get());
+  child->SetMaskLayer(mask_layer);
   root->AddChild(child.get());
 
   host()->SetRootLayer(root);
@@ -4743,391 +4773,351 @@
 
 // Needs layer tree mode: hide_layer_and_subtree.
 TEST_F(LayerTreeHostCommonTestWithLayerTree, SubtreeHidden_SingleLayerImpl) {
-  FakeImplTaskRunnerProvider task_runner_provider;
-  TestTaskGraphRunner task_graph_runner;
-  FakeLayerTreeHostImpl host_impl(&task_runner_provider, &task_graph_runner);
-  host_impl.CreatePendingTree();
-
-  std::unique_ptr<LayerImpl> root =
-      LayerImpl::Create(host_impl.pending_tree(), 1);
+  auto root = Layer::Create();
   root->SetBounds(gfx::Size(50, 50));
-  root->SetDrawsContent(true);
-  LayerImpl* root_layer = root.get();
+  root->SetIsDrawable(true);
 
-  std::unique_ptr<LayerImpl> child =
-      LayerImpl::Create(host_impl.pending_tree(), 2);
+  auto child = Layer::Create();
+  root->AddChild(child);
   child->SetBounds(gfx::Size(40, 40));
-  child->SetDrawsContent(true);
-  LayerImpl* child_layer = child.get();
+  child->SetIsDrawable(true);
 
-  std::unique_ptr<LayerImpl> grand_child =
-      LayerImpl::Create(host_impl.pending_tree(), 3);
+  auto grand_child = Layer::Create();
+  child->AddChild(grand_child);
   grand_child->SetBounds(gfx::Size(30, 30));
-  grand_child->SetDrawsContent(true);
-  grand_child->test_properties()->hide_layer_and_subtree = true;
-  LayerImpl* grand_child_layer = grand_child.get();
+  grand_child->SetIsDrawable(true);
+  grand_child->SetHideLayerAndSubtree(true);
 
-  child->test_properties()->AddChild(std::move(grand_child));
-  root->test_properties()->AddChild(std::move(child));
-  host_impl.pending_tree()->SetRootLayerForTesting(std::move(root));
+  child->AddChild(grand_child);
+  root->AddChild(child);
+  host()->SetRootLayer(root);
 
-  ExecuteCalculateDrawProperties(root_layer);
+  CommitAndActivate();
 
   // We should have one render surface and two layers. The grand child has
   // hidden itself.
   ASSERT_EQ(1u, render_surface_list_impl()->size());
-  ASSERT_EQ(2, GetRenderSurface(root_layer)->num_contributors());
-  EXPECT_TRUE(root_layer->contributes_to_drawn_render_surface());
-  EXPECT_TRUE(child_layer->contributes_to_drawn_render_surface());
-  EXPECT_FALSE(grand_child_layer->contributes_to_drawn_render_surface());
+  ASSERT_EQ(2, GetRenderSurfaceImpl(root)->num_contributors());
+  EXPECT_TRUE(ImplOf(root)->contributes_to_drawn_render_surface());
+  EXPECT_TRUE(ImplOf(child)->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(grand_child)->contributes_to_drawn_render_surface());
 }
 
 // Needs layer tree mode: hide_layer_and_subtree.
 TEST_F(LayerTreeHostCommonTestWithLayerTree, SubtreeHidden_TwoLayersImpl) {
-  FakeImplTaskRunnerProvider task_runner_provider;
-  TestTaskGraphRunner task_graph_runner;
-  FakeLayerTreeHostImpl host_impl(&task_runner_provider, &task_graph_runner);
-  host_impl.CreatePendingTree();
-
-  std::unique_ptr<LayerImpl> root =
-      LayerImpl::Create(host_impl.pending_tree(), 1);
+  auto root = Layer::Create();
   root->SetBounds(gfx::Size(50, 50));
-  root->SetDrawsContent(true);
-  LayerImpl* root_layer = root.get();
+  root->SetIsDrawable(true);
 
-  std::unique_ptr<LayerImpl> child =
-      LayerImpl::Create(host_impl.pending_tree(), 2);
+  auto child = Layer::Create();
   child->SetBounds(gfx::Size(40, 40));
-  child->SetDrawsContent(true);
-  child->test_properties()->hide_layer_and_subtree = true;
-  LayerImpl* child_layer = child.get();
+  child->SetIsDrawable(true);
+  child->SetHideLayerAndSubtree(true);
 
-  std::unique_ptr<LayerImpl> grand_child =
-      LayerImpl::Create(host_impl.pending_tree(), 3);
+  auto grand_child = Layer::Create();
   grand_child->SetBounds(gfx::Size(30, 30));
-  grand_child->SetDrawsContent(true);
-  LayerImpl* grand_child_layer = grand_child.get();
+  grand_child->SetIsDrawable(true);
 
-  child->test_properties()->AddChild(std::move(grand_child));
-  root->test_properties()->AddChild(std::move(child));
-  host_impl.pending_tree()->SetRootLayerForTesting(std::move(root));
+  child->AddChild(grand_child);
+  root->AddChild(child);
+  host()->SetRootLayer(root);
 
-  ExecuteCalculateDrawProperties(root_layer);
+  CommitAndActivate();
 
   // We should have one render surface and one layer. The child has
   // hidden itself and the grand child.
   ASSERT_EQ(1u, render_surface_list_impl()->size());
-  ASSERT_EQ(1, GetRenderSurface(root_layer)->num_contributors());
-  EXPECT_TRUE(root_layer->contributes_to_drawn_render_surface());
-  EXPECT_FALSE(child_layer->contributes_to_drawn_render_surface());
-  EXPECT_FALSE(grand_child_layer->contributes_to_drawn_render_surface());
+  ASSERT_EQ(1, GetRenderSurfaceImpl(root)->num_contributors());
+  EXPECT_TRUE(ImplOf(root)->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(child)->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(grand_child)->contributes_to_drawn_render_surface());
 }
 
 // Needs layer tree mode: mask layer, hide_layer_and_subtree and copy request.
 TEST_F(LayerTreeHostCommonTestWithLayerTree, SubtreeHiddenWithCopyRequest) {
-  FakeImplTaskRunnerProvider task_runner_provider;
-  TestTaskGraphRunner task_graph_runner;
-  FakeLayerTreeHostImpl host_impl(&task_runner_provider, &task_graph_runner);
-  host_impl.CreatePendingTree();
-
-  std::unique_ptr<LayerImpl> root =
-      LayerImpl::Create(host_impl.pending_tree(), 1);
+  auto root = Layer::Create();
   root->SetBounds(gfx::Size(50, 50));
-  root->SetDrawsContent(true);
-  LayerImpl* root_layer = root.get();
+  root->SetIsDrawable(true);
 
-  std::unique_ptr<LayerImpl> copy_grand_parent =
-      LayerImpl::Create(host_impl.pending_tree(), 2);
+  auto copy_grand_parent = Layer::Create();
   copy_grand_parent->SetBounds(gfx::Size(40, 40));
-  copy_grand_parent->SetDrawsContent(true);
-  LayerImpl* copy_grand_parent_layer = copy_grand_parent.get();
+  copy_grand_parent->SetIsDrawable(true);
 
-  std::unique_ptr<LayerImpl> copy_parent =
-      LayerImpl::Create(host_impl.pending_tree(), 3);
+  auto copy_parent = Layer::Create();
   copy_parent->SetBounds(gfx::Size(30, 30));
-  copy_parent->SetDrawsContent(true);
-  copy_parent->test_properties()->force_render_surface = true;
-  LayerImpl* copy_parent_layer = copy_parent.get();
+  copy_parent->SetIsDrawable(true);
+  copy_parent->SetForceRenderSurfaceForTesting(true);
 
-  std::unique_ptr<LayerImpl> copy_request =
-      LayerImpl::Create(host_impl.pending_tree(), 4);
-  copy_request->SetBounds(gfx::Size(20, 20));
-  copy_request->SetDrawsContent(true);
-  copy_request->test_properties()->force_render_surface = true;
-  LayerImpl* copy_layer = copy_request.get();
+  auto copy_layer = Layer::Create();
+  copy_layer->SetBounds(gfx::Size(20, 20));
+  copy_layer->SetIsDrawable(true);
+  copy_layer->SetForceRenderSurfaceForTesting(true);
 
-  std::unique_ptr<LayerImpl> copy_child =
-      LayerImpl::Create(host_impl.pending_tree(), 5);
+  auto copy_child = Layer::Create();
   copy_child->SetBounds(gfx::Size(20, 20));
-  copy_child->SetDrawsContent(true);
-  LayerImpl* copy_child_layer = copy_child.get();
+  copy_child->SetIsDrawable(true);
 
-  std::unique_ptr<LayerImpl> copy_grand_child =
-      LayerImpl::Create(host_impl.pending_tree(), 6);
+  auto copy_grand_child = Layer::Create();
   copy_grand_child->SetBounds(gfx::Size(20, 20));
-  copy_grand_child->SetDrawsContent(true);
-  LayerImpl* copy_grand_child_layer = copy_grand_child.get();
+  copy_grand_child->SetIsDrawable(true);
 
-  std::unique_ptr<LayerImpl> copy_grand_parent_sibling_before =
-      LayerImpl::Create(host_impl.pending_tree(), 7);
+  auto copy_grand_parent_sibling_before = Layer::Create();
   copy_grand_parent_sibling_before->SetBounds(gfx::Size(40, 40));
-  copy_grand_parent_sibling_before->SetDrawsContent(true);
-  LayerImpl* copy_grand_parent_sibling_before_layer =
-      copy_grand_parent_sibling_before.get();
+  copy_grand_parent_sibling_before->SetIsDrawable(true);
 
-  std::unique_ptr<LayerImpl> copy_grand_parent_sibling_after =
-      LayerImpl::Create(host_impl.pending_tree(), 8);
+  auto copy_grand_parent_sibling_after = Layer::Create();
   copy_grand_parent_sibling_after->SetBounds(gfx::Size(40, 40));
-  copy_grand_parent_sibling_after->SetDrawsContent(true);
-  LayerImpl* copy_grand_parent_sibling_after_layer =
-      copy_grand_parent_sibling_after.get();
+  copy_grand_parent_sibling_after->SetIsDrawable(true);
 
-  copy_child->test_properties()->AddChild(std::move(copy_grand_child));
-  copy_request->test_properties()->AddChild(std::move(copy_child));
-  copy_parent->test_properties()->AddChild(std::move(copy_request));
-  copy_grand_parent->test_properties()->AddChild(std::move(copy_parent));
-  root->test_properties()->AddChild(
-      std::move(copy_grand_parent_sibling_before));
-  root->test_properties()->AddChild(std::move(copy_grand_parent));
-  root->test_properties()->AddChild(std::move(copy_grand_parent_sibling_after));
-  host_impl.pending_tree()->SetRootLayerForTesting(std::move(root));
+  copy_child->AddChild(copy_grand_child);
+  copy_layer->AddChild(copy_child);
+  copy_parent->AddChild(copy_layer);
+  copy_grand_parent->AddChild(copy_parent);
+  root->AddChild(copy_grand_parent_sibling_before);
+  root->AddChild(copy_grand_parent);
+  root->AddChild(copy_grand_parent_sibling_after);
+  host()->SetRootLayer(root);
 
   // Hide the copy_grand_parent and its subtree. But make a copy request in that
   // hidden subtree on copy_layer. Also hide the copy grand child and its
   // subtree.
-  copy_grand_parent_layer->test_properties()->hide_layer_and_subtree = true;
-  copy_grand_parent_sibling_before_layer->test_properties()
-      ->hide_layer_and_subtree = true;
-  copy_grand_parent_sibling_after_layer->test_properties()
-      ->hide_layer_and_subtree = true;
-  copy_grand_child_layer->test_properties()->hide_layer_and_subtree = true;
+  copy_grand_parent->SetHideLayerAndSubtree(true);
+  copy_grand_parent_sibling_before->SetHideLayerAndSubtree(true);
+  copy_grand_parent_sibling_after->SetHideLayerAndSubtree(true);
+  copy_grand_child->SetHideLayerAndSubtree(true);
 
-  copy_layer->test_properties()->copy_requests.push_back(
+  copy_layer->RequestCopyOfOutput(
       viz::CopyOutputRequest::CreateStubForTesting());
 
-  ExecuteCalculateDrawProperties(root_layer);
+  CommitAndActivate();
 
-  EXPECT_TRUE(GetEffectNode(root_layer)->subtree_has_copy_request);
-  EXPECT_TRUE(GetEffectNode(copy_grand_parent_layer)->subtree_has_copy_request);
-  EXPECT_TRUE(GetEffectNode(copy_parent_layer)->subtree_has_copy_request);
-  EXPECT_TRUE(GetEffectNode(copy_layer)->subtree_has_copy_request);
+  EXPECT_TRUE(GetEffectNode(ImplOf(root))->subtree_has_copy_request);
+  EXPECT_TRUE(
+      GetEffectNode(ImplOf(copy_grand_parent))->subtree_has_copy_request);
+  EXPECT_TRUE(GetEffectNode(ImplOf(copy_parent))->subtree_has_copy_request);
+  EXPECT_TRUE(GetEffectNode(ImplOf(copy_layer))->subtree_has_copy_request);
 
   // We should have four render surfaces, one for the root, one for the grand
   // parent since it has opacity and two drawing descendants, one for the parent
   // since it owns a surface, and one for the copy_layer.
   ASSERT_EQ(4u, render_surface_list_impl()->size());
-  EXPECT_EQ(static_cast<uint64_t>(root_layer->id()),
+  EXPECT_EQ(static_cast<uint64_t>(root->id()),
             render_surface_list_impl()->at(0)->id());
-  EXPECT_EQ(static_cast<uint64_t>(copy_grand_parent_layer->id()),
+  EXPECT_EQ(static_cast<uint64_t>(copy_grand_parent->id()),
             render_surface_list_impl()->at(1)->id());
-  EXPECT_EQ(static_cast<uint64_t>(copy_parent_layer->id()),
+  EXPECT_EQ(static_cast<uint64_t>(copy_parent->id()),
             render_surface_list_impl()->at(2)->id());
   EXPECT_EQ(static_cast<uint64_t>(copy_layer->id()),
             render_surface_list_impl()->at(3)->id());
 
   // The root render surface should have 2 contributing layers.
-  EXPECT_EQ(2, GetRenderSurface(root_layer)->num_contributors());
-  EXPECT_TRUE(root_layer->contributes_to_drawn_render_surface());
-  EXPECT_FALSE(copy_grand_parent_layer->contributes_to_drawn_render_surface());
-  EXPECT_FALSE(copy_grand_parent_sibling_before_layer
+  EXPECT_EQ(2, GetRenderSurfaceImpl(root)->num_contributors());
+  EXPECT_TRUE(ImplOf(root)->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(
+      ImplOf(copy_grand_parent)->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(copy_grand_parent_sibling_before)
                    ->contributes_to_drawn_render_surface());
-  EXPECT_FALSE(copy_grand_parent_sibling_after_layer
+  EXPECT_FALSE(ImplOf(copy_grand_parent_sibling_after)
                    ->contributes_to_drawn_render_surface());
 
   // Nothing actually draws into the copy parent, so only the copy_layer will
   // appear in its list, since it needs to be drawn for the copy request.
-  ASSERT_EQ(1, GetRenderSurface(copy_parent_layer)->num_contributors());
-  EXPECT_FALSE(copy_parent_layer->contributes_to_drawn_render_surface());
+  ASSERT_EQ(1, GetRenderSurfaceImpl(copy_parent)->num_contributors());
+  EXPECT_FALSE(ImplOf(copy_parent)->contributes_to_drawn_render_surface());
 
   // The copy layer's render surface should have 2 contributing layers.
-  ASSERT_EQ(2, GetRenderSurface(copy_layer)->num_contributors());
-  EXPECT_TRUE(copy_layer->contributes_to_drawn_render_surface());
-  EXPECT_TRUE(copy_child_layer->contributes_to_drawn_render_surface());
-  EXPECT_FALSE(copy_grand_child_layer->contributes_to_drawn_render_surface());
+  ASSERT_EQ(2, GetRenderSurfaceImpl(copy_layer)->num_contributors());
+  EXPECT_TRUE(ImplOf(copy_layer)->contributes_to_drawn_render_surface());
+  EXPECT_TRUE(ImplOf(copy_child)->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(copy_grand_child)->contributes_to_drawn_render_surface());
 
   // copy_grand_parent, copy_parent shouldn't be drawn because they are hidden,
   // but the copy_layer and copy_child should be drawn for the copy request.
   // copy grand child should not be drawn as its hidden even in the copy
   // request.
-  EXPECT_FALSE(GetEffectNode(copy_grand_parent_layer)->is_drawn);
-  EXPECT_FALSE(GetEffectNode(copy_parent_layer)->is_drawn);
-  EXPECT_TRUE(GetEffectNode(copy_layer)->is_drawn);
-  EXPECT_TRUE(GetEffectNode(copy_child_layer)->is_drawn);
-  EXPECT_FALSE(GetEffectNode(copy_grand_child_layer)->is_drawn);
+  EXPECT_FALSE(GetEffectNode(ImplOf(copy_grand_parent))->is_drawn);
+  EXPECT_FALSE(GetEffectNode(ImplOf(copy_parent))->is_drawn);
+  EXPECT_TRUE(GetEffectNode(ImplOf(copy_layer))->is_drawn);
+  EXPECT_TRUE(GetEffectNode(ImplOf(copy_child))->is_drawn);
+  EXPECT_FALSE(GetEffectNode(ImplOf(copy_grand_child))->is_drawn);
 
   // Though copy_layer is drawn, it shouldn't contribute to drawn surface as its
   // actually hidden.
-  EXPECT_FALSE(GetRenderSurface(copy_layer)->contributes_to_drawn_surface());
+  EXPECT_FALSE(
+      GetRenderSurfaceImpl(copy_layer)->contributes_to_drawn_surface());
 }
 
 // Needs layer tree mode: copy request.
 TEST_F(LayerTreeHostCommonTestWithLayerTree, ClippedOutCopyRequest) {
-  FakeImplTaskRunnerProvider task_runner_provider;
-  TestTaskGraphRunner task_graph_runner;
-  FakeLayerTreeHostImpl host_impl(&task_runner_provider, &task_graph_runner);
-  host_impl.CreatePendingTree();
-
-  std::unique_ptr<LayerImpl> root =
-      LayerImpl::Create(host_impl.pending_tree(), 1);
+  auto root = Layer::Create();
   root->SetBounds(gfx::Size(50, 50));
-  root->SetDrawsContent(true);
+  root->SetIsDrawable(true);
 
-  std::unique_ptr<LayerImpl> copy_parent =
-      LayerImpl::Create(host_impl.pending_tree(), 2);
-  copy_parent->SetDrawsContent(true);
+  auto copy_parent = Layer::Create();
+  copy_parent->SetIsDrawable(true);
   copy_parent->SetMasksToBounds(true);
 
-  std::unique_ptr<LayerImpl> copy_layer =
-      LayerImpl::Create(host_impl.pending_tree(), 3);
+  auto copy_layer = Layer::Create();
   copy_layer->SetBounds(gfx::Size(30, 30));
-  copy_layer->SetDrawsContent(true);
-  copy_layer->test_properties()->force_render_surface = true;
+  copy_layer->SetIsDrawable(true);
+  copy_layer->SetForceRenderSurfaceForTesting(true);
 
-  std::unique_ptr<LayerImpl> copy_child =
-      LayerImpl::Create(host_impl.pending_tree(), 4);
+  auto copy_child = Layer::Create();
   copy_child->SetBounds(gfx::Size(20, 20));
-  copy_child->SetDrawsContent(true);
+  copy_child->SetIsDrawable(true);
 
-  copy_layer->test_properties()->copy_requests.push_back(
+  copy_layer->RequestCopyOfOutput(
       viz::CopyOutputRequest::CreateStubForTesting());
 
-  copy_layer->test_properties()->AddChild(std::move(copy_child));
-  copy_parent->test_properties()->AddChild(std::move(copy_layer));
-  root->test_properties()->AddChild(std::move(copy_parent));
+  copy_layer->AddChild(copy_child);
+  copy_parent->AddChild(copy_layer);
+  root->AddChild(copy_parent);
 
-  LayerImpl* root_layer = root.get();
-  root_layer->layer_tree_impl()->SetRootLayerForTesting(std::move(root));
-  ExecuteCalculateDrawProperties(root_layer);
+  host()->SetRootLayer(root);
+
+  CommitAndActivate();
 
   // We should have two render surface, as the others are clipped out.
   ASSERT_EQ(2u, render_surface_list_impl()->size());
-  EXPECT_EQ(static_cast<uint64_t>(root_layer->id()),
+  EXPECT_EQ(static_cast<uint64_t>(root->id()),
             render_surface_list_impl()->at(0)->id());
 
   // The root render surface should have only 2 contributing layer, since the
   // other layers are clipped away.
-  ASSERT_EQ(2, GetRenderSurface(root_layer)->num_contributors());
-  EXPECT_TRUE(root_layer->contributes_to_drawn_render_surface());
+  ASSERT_EQ(2, GetRenderSurfaceImpl(root)->num_contributors());
+  EXPECT_TRUE(ImplOf(root)->contributes_to_drawn_render_surface());
 }
 
 // Needs layer tree mode: copy request.
 TEST_F(LayerTreeHostCommonTestWithLayerTree, SingularTransformAndCopyRequests) {
-  LayerImpl* root = root_layer_for_testing();
+  auto root = Layer::Create();
+  host()->SetRootLayer(root);
   root->SetBounds(gfx::Size(50, 50));
-  root->SetDrawsContent(true);
+  root->SetIsDrawable(true);
 
-  LayerImpl* singular_transform_layer = AddChild<LayerImpl>(root);
+  auto singular_transform_layer = Layer::Create();
+  root->AddChild(singular_transform_layer);
   singular_transform_layer->SetBounds(gfx::Size(100, 100));
-  singular_transform_layer->SetDrawsContent(true);
+  singular_transform_layer->SetIsDrawable(true);
   gfx::Transform singular;
   singular.Scale3d(6.f, 6.f, 0.f);
-  singular_transform_layer->test_properties()->transform = singular;
+  singular_transform_layer->SetTransform(singular);
 
-  LayerImpl* copy_layer = AddChild<LayerImpl>(singular_transform_layer);
+  auto copy_layer = Layer::Create();
+  singular_transform_layer->AddChild(copy_layer);
   copy_layer->SetBounds(gfx::Size(100, 100));
-  copy_layer->SetDrawsContent(true);
-  copy_layer->test_properties()->copy_requests.push_back(
+  copy_layer->SetIsDrawable(true);
+  copy_layer->RequestCopyOfOutput(
       viz::CopyOutputRequest::CreateStubForTesting());
 
-  LayerImpl* copy_child = AddChild<LayerImpl>(copy_layer);
+  auto copy_child = Layer::Create();
+  copy_layer->AddChild(copy_child);
   copy_child->SetBounds(gfx::Size(100, 100));
-  copy_child->SetDrawsContent(true);
+  copy_child->SetIsDrawable(true);
 
-  LayerImpl* copy_grand_child = AddChild<LayerImpl>(copy_child);
+  auto copy_grand_child = Layer::Create();
+  copy_child->AddChild(copy_grand_child);
   copy_grand_child->SetBounds(gfx::Size(100, 100));
-  copy_grand_child->SetDrawsContent(true);
-  copy_grand_child->test_properties()->transform = singular;
+  copy_grand_child->SetIsDrawable(true);
+  copy_grand_child->SetTransform(singular);
 
-  DCHECK(!copy_layer->test_properties()->copy_requests.empty());
-  ExecuteCalculateDrawProperties(root);
-  DCHECK(copy_layer->test_properties()->copy_requests.empty());
+  ASSERT_TRUE(copy_layer->HasCopyRequest());
+  CommitAndActivate();
+  ASSERT_FALSE(copy_layer->HasCopyRequest());
 
   // A layer with singular transform should not contribute to drawn render
   // surface.
-  EXPECT_FALSE(singular_transform_layer->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(
+      ImplOf(singular_transform_layer)->contributes_to_drawn_render_surface());
   // Even though copy_layer and copy_child have singular screen space transform,
   // they still contribute to drawn render surface as their transform to the
   // closest ancestor with copy request is not singular.
-  EXPECT_TRUE(copy_layer->contributes_to_drawn_render_surface());
-  EXPECT_TRUE(copy_child->contributes_to_drawn_render_surface());
+  EXPECT_TRUE(ImplOf(copy_layer)->contributes_to_drawn_render_surface());
+  EXPECT_TRUE(ImplOf(copy_child)->contributes_to_drawn_render_surface());
   // copy_grand_child's transform to its closest ancestor with copy request is
   // also singular. So, it doesn't contribute to drawn render surface.
-  EXPECT_FALSE(copy_grand_child->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(copy_grand_child)->contributes_to_drawn_render_surface());
 }
 
 // Needs layer tree mode: copy request.
 TEST_F(LayerTreeHostCommonTestWithLayerTree, VisibleRectInNonRootCopyRequest) {
-  LayerImpl* root = root_layer_for_testing();
+  auto root = Layer::Create();
+  host()->SetRootLayer(root);
   root->SetBounds(gfx::Size(50, 50));
-  root->SetDrawsContent(true);
+  root->SetIsDrawable(true);
   root->SetMasksToBounds(true);
 
-  LayerImpl* copy_layer = AddChild<LayerImpl>(root);
+  auto copy_layer = Layer::Create();
+  root->AddChild(copy_layer);
   copy_layer->SetBounds(gfx::Size(100, 100));
-  copy_layer->SetDrawsContent(true);
-  copy_layer->test_properties()->force_render_surface = true;
+  copy_layer->SetIsDrawable(true);
+  copy_layer->SetForceRenderSurfaceForTesting(true);
 
-  LayerImpl* copy_child = AddChild<LayerImpl>(copy_layer);
-  copy_child->test_properties()->position = gfx::PointF(40.f, 40.f);
+  auto copy_child = Layer::Create();
+  copy_layer->AddChild(copy_child);
+  copy_child->SetPosition(gfx::PointF(40.f, 40.f));
   copy_child->SetBounds(gfx::Size(20, 20));
-  copy_child->SetDrawsContent(true);
+  copy_child->SetIsDrawable(true);
 
-  LayerImpl* copy_clip = AddChild<LayerImpl>(copy_layer);
+  auto copy_clip = Layer::Create();
+  copy_layer->AddChild(copy_clip);
   copy_clip->SetBounds(gfx::Size(55, 55));
   copy_clip->SetMasksToBounds(true);
 
-  LayerImpl* copy_clipped_child = AddChild<LayerImpl>(copy_clip);
-  copy_clipped_child->test_properties()->position = gfx::PointF(40.f, 40.f);
+  auto copy_clipped_child = Layer::Create();
+  copy_clip->AddChild(copy_clipped_child);
+  copy_clipped_child->SetPosition(gfx::PointF(40.f, 40.f));
   copy_clipped_child->SetBounds(gfx::Size(20, 20));
-  copy_clipped_child->SetDrawsContent(true);
+  copy_clipped_child->SetIsDrawable(true);
 
-  LayerImpl* copy_surface = AddChild<LayerImpl>(copy_clip);
-  copy_surface->test_properties()->position = gfx::PointF(45.f, 45.f);
+  auto copy_surface = Layer::Create();
+  copy_clip->AddChild(copy_surface);
+  copy_surface->SetPosition(gfx::PointF(45.f, 45.f));
   copy_surface->SetBounds(gfx::Size(20, 20));
-  copy_surface->SetDrawsContent(true);
-  copy_surface->test_properties()->force_render_surface = true;
+  copy_surface->SetIsDrawable(true);
+  copy_surface->SetForceRenderSurfaceForTesting(true);
 
-  copy_layer->test_properties()->copy_requests.push_back(
+  copy_layer->RequestCopyOfOutput(
       viz::CopyOutputRequest::CreateStubForTesting());
+  ASSERT_TRUE(copy_layer->HasCopyRequest());
+  CommitAndActivate();
+  ASSERT_FALSE(copy_layer->HasCopyRequest());
 
-  DCHECK(!copy_layer->test_properties()->copy_requests.empty());
-  ExecuteCalculateDrawProperties(root);
-  DCHECK(copy_layer->test_properties()->copy_requests.empty());
-
-  EXPECT_EQ(gfx::Rect(100, 100), copy_layer->visible_layer_rect());
-  EXPECT_EQ(gfx::Rect(20, 20), copy_child->visible_layer_rect());
-  EXPECT_EQ(gfx::Rect(15, 15), copy_clipped_child->visible_layer_rect());
-  EXPECT_EQ(gfx::Rect(10, 10), copy_surface->visible_layer_rect());
+  EXPECT_EQ(gfx::Rect(100, 100), ImplOf(copy_layer)->visible_layer_rect());
+  EXPECT_EQ(gfx::Rect(20, 20), ImplOf(copy_child)->visible_layer_rect());
+  EXPECT_EQ(gfx::Rect(15, 15),
+            ImplOf(copy_clipped_child)->visible_layer_rect());
+  EXPECT_EQ(gfx::Rect(10, 10), ImplOf(copy_surface)->visible_layer_rect());
 
   // Case 2: When the non root copy request layer is clipped.
   copy_layer->SetBounds(gfx::Size(50, 50));
   copy_layer->SetMasksToBounds(true);
-  copy_layer->test_properties()->copy_requests.push_back(
+  copy_layer->RequestCopyOfOutput(
       viz::CopyOutputRequest::CreateStubForTesting());
-  root->layer_tree_impl()->property_trees()->needs_rebuild = true;
+  ASSERT_TRUE(copy_layer->HasCopyRequest());
+  CommitAndActivate();
+  ASSERT_FALSE(copy_layer->HasCopyRequest());
 
-  DCHECK(!copy_layer->test_properties()->copy_requests.empty());
-  ExecuteCalculateDrawProperties(root);
-  DCHECK(copy_layer->test_properties()->copy_requests.empty());
-
-  EXPECT_EQ(gfx::Rect(50, 50), copy_layer->visible_layer_rect());
-  EXPECT_EQ(gfx::Rect(10, 10), copy_child->visible_layer_rect());
-  EXPECT_EQ(gfx::Rect(10, 10), copy_clipped_child->visible_layer_rect());
-  EXPECT_EQ(gfx::Rect(5, 5), copy_surface->visible_layer_rect());
+  EXPECT_EQ(gfx::Rect(50, 50), ImplOf(copy_layer)->visible_layer_rect());
+  EXPECT_EQ(gfx::Rect(10, 10), ImplOf(copy_child)->visible_layer_rect());
+  EXPECT_EQ(gfx::Rect(10, 10),
+            ImplOf(copy_clipped_child)->visible_layer_rect());
+  EXPECT_EQ(gfx::Rect(5, 5), ImplOf(copy_surface)->visible_layer_rect());
 
   // Case 3: When there is device scale factor.
   float device_scale_factor = 2.f;
-  copy_layer->test_properties()->copy_requests.push_back(
+  copy_layer->RequestCopyOfOutput(
       viz::CopyOutputRequest::CreateStubForTesting());
 
-  DCHECK(!copy_layer->test_properties()->copy_requests.empty());
-  ExecuteCalculateDrawProperties(root, device_scale_factor);
-  DCHECK(copy_layer->test_properties()->copy_requests.empty());
+  ASSERT_TRUE(copy_layer->HasCopyRequest());
+  CommitAndActivate(device_scale_factor);
+  ASSERT_FALSE(copy_layer->HasCopyRequest());
 
-  EXPECT_EQ(gfx::Rect(50, 50), copy_layer->visible_layer_rect());
-  EXPECT_EQ(gfx::Rect(10, 10), copy_child->visible_layer_rect());
-  EXPECT_EQ(gfx::Rect(10, 10), copy_clipped_child->visible_layer_rect());
-  EXPECT_EQ(gfx::Rect(5, 5), copy_surface->visible_layer_rect());
+  EXPECT_EQ(gfx::Rect(50, 50), ImplOf(copy_layer)->visible_layer_rect());
+  EXPECT_EQ(gfx::Rect(10, 10), ImplOf(copy_child)->visible_layer_rect());
+  EXPECT_EQ(gfx::Rect(10, 10),
+            ImplOf(copy_clipped_child)->visible_layer_rect());
+  EXPECT_EQ(gfx::Rect(5, 5), ImplOf(copy_surface)->visible_layer_rect());
 }
 
 TEST_F(LayerTreeHostCommonTest, TransformedClipParent) {
@@ -5530,68 +5520,80 @@
        CreateRenderSurfaceWhenFlattenInsideRenderingContext) {
   // Verifies that Render Surfaces are created at the edge of rendering context.
 
-  LayerImpl* root = root_layer_for_testing();
-  LayerImpl* child1 = AddChildToRoot<LayerImpl>();
-  LayerImpl* child2 = AddChild<LayerImpl>(child1);
-  LayerImpl* child3 = AddChild<LayerImpl>(child2);
-  root->SetDrawsContent(true);
+  auto root = Layer::Create();
+  host()->SetRootLayer(root);
+  auto child1 = Layer::Create();
+  root->AddChild(child1);
+  auto child2 = Layer::Create();
+  child1->AddChild(child2);
+  auto child3 = Layer::Create();
+  child2->AddChild(child3);
+  root->SetIsDrawable(true);
 
   gfx::Size bounds(100, 100);
 
   root->SetBounds(bounds);
   child1->SetBounds(bounds);
-  child1->SetDrawsContent(true);
-  child1->test_properties()->should_flatten_transform = false;
-  child1->test_properties()->sorting_context_id = 1;
+  child1->SetIsDrawable(true);
+  child1->SetShouldFlattenTransform(false);
+  child1->Set3dSortingContextId(1);
   child2->SetBounds(bounds);
-  child2->SetDrawsContent(true);
-  child2->test_properties()->sorting_context_id = 1;
+  child2->SetIsDrawable(true);
+  child2->Set3dSortingContextId(1);
   child3->SetBounds(bounds);
-  child3->SetDrawsContent(true);
-  child3->test_properties()->sorting_context_id = 1;
-  ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root);
+  child3->SetIsDrawable(true);
+  child3->Set3dSortingContextId(1);
+
+  CommitAndActivate();
 
   // Verify which render surfaces were created.
-  EXPECT_TRUE(GetRenderSurface(root));
-  EXPECT_EQ(GetRenderSurface(child1), GetRenderSurface(root));
-  EXPECT_NE(GetRenderSurface(child2), GetRenderSurface(root));
-  EXPECT_EQ(GetRenderSurface(child3), GetRenderSurface(child2));
+  EXPECT_TRUE(GetRenderSurfaceImpl(root));
+  EXPECT_EQ(GetRenderSurfaceImpl(child1), GetRenderSurfaceImpl(root));
+  EXPECT_NE(GetRenderSurfaceImpl(child2), GetRenderSurfaceImpl(root));
+  EXPECT_EQ(GetRenderSurfaceImpl(child3), GetRenderSurfaceImpl(child2));
 }
 
 // Needs layer tree mode: testing PropertyTreeBuilder.
 TEST_F(LayerTreeHostCommonTestWithLayerTree,
        DoNotIncludeBackfaceInvisibleSurfaces) {
-  LayerImpl* root = root_layer_for_testing();
-  LayerImpl* back_facing = AddChild<LayerImpl>(root);
+  auto root = Layer::Create();
+  host()->SetRootLayer(root);
+  auto back_facing = Layer::Create();
+  root->AddChild(back_facing);
 
-  LayerImpl* render_surface1 = AddChild<LayerImpl>(back_facing);
-  LayerImpl* child1 = AddChild<LayerImpl>(render_surface1);
+  auto render_surface1 = Layer::Create();
+  back_facing->AddChild(render_surface1);
+  auto child1 = Layer::Create();
+  render_surface1->AddChild(child1);
 
-  LayerImpl* flattener = AddChild<LayerImpl>(back_facing);
-  LayerImpl* render_surface2 = AddChild<LayerImpl>(flattener);
-  LayerImpl* child2 = AddChild<LayerImpl>(render_surface2);
+  auto flattener = Layer::Create();
+  back_facing->AddChild(flattener);
+  auto render_surface2 = Layer::Create();
+  flattener->AddChild(render_surface2);
+  auto child2 = Layer::Create();
+  render_surface2->AddChild(child2);
 
-  child1->SetDrawsContent(true);
-  child2->SetDrawsContent(true);
+  child1->SetIsDrawable(true);
+  child2->SetIsDrawable(true);
 
   root->SetBounds(gfx::Size(50, 50));
   back_facing->SetBounds(gfx::Size(50, 50));
-  back_facing->test_properties()->should_flatten_transform = false;
+  back_facing->SetShouldFlattenTransform(false);
 
   render_surface1->SetBounds(gfx::Size(30, 30));
-  render_surface1->test_properties()->should_flatten_transform = false;
-  render_surface1->test_properties()->force_render_surface = true;
-  render_surface1->test_properties()->double_sided = false;
+  render_surface1->SetShouldFlattenTransform(false);
+  render_surface1->SetForceRenderSurfaceForTesting(true);
+  render_surface1->SetDoubleSided(false);
   child1->SetBounds(gfx::Size(20, 20));
 
   flattener->SetBounds(gfx::Size(30, 30));
   render_surface2->SetBounds(gfx::Size(30, 30));
-  render_surface2->test_properties()->should_flatten_transform = false;
-  render_surface2->test_properties()->force_render_surface = true;
-  render_surface2->test_properties()->double_sided = false;
+  render_surface2->SetShouldFlattenTransform(false);
+  render_surface2->SetForceRenderSurfaceForTesting(true);
+  render_surface2->SetDoubleSided(false);
   child2->SetBounds(gfx::Size(20, 20));
 
-  ExecuteCalculateDrawProperties(root);
+  CommitAndActivate();
 
   EXPECT_EQ(3u, render_surface_list_impl()->size());
   EXPECT_EQ(2, render_surface_list_impl()->at(0)->num_contributors());
@@ -5599,11 +5601,9 @@
 
   gfx::Transform rotation_transform;
   rotation_transform.RotateAboutXAxis(180.0);
+  back_facing->SetTransform(rotation_transform);
 
-  back_facing->test_properties()->transform = rotation_transform;
-  root->layer_tree_impl()->property_trees()->needs_rebuild = true;
-
-  ExecuteCalculateDrawProperties(root);
+  CommitAndActivate();
 
   // render_surface1 is in the same 3d rendering context as back_facing and is
   // not double sided, so it should not be in RSLL. render_surface2 is also not
@@ -5616,62 +5616,66 @@
 // Needs layer tree mode: testing PropertyTreeBuilder.
 TEST_F(LayerTreeHostCommonTestWithLayerTree,
        DoNotIncludeBackfaceInvisibleLayers) {
-  LayerImpl* root = root_layer_for_testing();
-  LayerImpl* child = AddChild<LayerImpl>(root);
-  LayerImpl* grand_child = AddChild<LayerImpl>(child);
+  auto root = Layer::Create();
+  host()->SetRootLayer(root);
+  auto child = Layer::Create();
+  root->AddChild(child);
+  auto grand_child = Layer::Create();
+  child->AddChild(grand_child);
 
   root->SetBounds(gfx::Size(50, 50));
-  root->test_properties()->should_flatten_transform = false;
+  root->SetShouldFlattenTransform(false);
   child->SetBounds(gfx::Size(30, 30));
-  child->test_properties()->double_sided = false;
-  child->test_properties()->should_flatten_transform = false;
+  child->SetDoubleSided(false);
+  child->SetShouldFlattenTransform(false);
   grand_child->SetBounds(gfx::Size(20, 20));
-  grand_child->SetDrawsContent(true);
+  grand_child->SetIsDrawable(true);
   grand_child->SetUseParentBackfaceVisibility(true);
-  grand_child->test_properties()->should_flatten_transform = false;
-  ExecuteCalculateDrawProperties(root);
+  grand_child->SetShouldFlattenTransform(false);
+
+  CommitAndActivate();
 
   EXPECT_EQ(1u, render_surface_list_impl()->size());
-  EXPECT_TRUE(grand_child->contributes_to_drawn_render_surface());
+  EXPECT_TRUE(ImplOf(grand_child)->contributes_to_drawn_render_surface());
 
   // A ll layers with invisible backfgaces should be checked.
-  EXPECT_FALSE(root->should_check_backface_visibility());
-  EXPECT_TRUE(child->should_check_backface_visibility());
-  EXPECT_TRUE(grand_child->should_check_backface_visibility());
+  EXPECT_FALSE(ImplOf(root)->should_check_backface_visibility());
+  EXPECT_TRUE(ImplOf(child)->should_check_backface_visibility());
+  EXPECT_TRUE(ImplOf(grand_child)->should_check_backface_visibility());
 
   gfx::Transform rotation_transform;
   rotation_transform.RotateAboutXAxis(180.0);
 
-  child->test_properties()->transform = rotation_transform;
-  child->test_properties()->sorting_context_id = 1;
-  grand_child->test_properties()->sorting_context_id = 1;
-  child->layer_tree_impl()->property_trees()->needs_rebuild = true;
+  child->SetTransform(rotation_transform);
+  child->Set3dSortingContextId(1);
+  grand_child->Set3dSortingContextId(1);
 
-  ExecuteCalculateDrawProperties(root);
+  CommitAndActivate();
+
   EXPECT_EQ(1u, render_surface_list_impl()->size());
   EXPECT_EQ(0, render_surface_list_impl()->at(0)->num_contributors());
 
   // We should check for backface visibilty of child as it has a rotation
   // transform. We should also check for grand_child as it uses the backface
   // visibility of its parent.
-  EXPECT_FALSE(root->should_check_backface_visibility());
-  EXPECT_TRUE(child->should_check_backface_visibility());
-  EXPECT_TRUE(grand_child->should_check_backface_visibility());
+  EXPECT_FALSE(ImplOf(root)->should_check_backface_visibility());
+  EXPECT_TRUE(ImplOf(child)->should_check_backface_visibility());
+  EXPECT_TRUE(ImplOf(grand_child)->should_check_backface_visibility());
 
   grand_child->SetUseParentBackfaceVisibility(false);
-  grand_child->test_properties()->double_sided = false;
-  grand_child->layer_tree_impl()->property_trees()->needs_rebuild = true;
+  grand_child->SetDoubleSided(false);
 
-  ExecuteCalculateDrawProperties(root);
+  CommitAndActivate();
+
   EXPECT_EQ(1u, render_surface_list_impl()->size());
   EXPECT_EQ(0, render_surface_list_impl()->at(0)->num_contributors());
 
   // We should check the backface visibility of child as it has a rotation
   // transform and for grand_child as it is in a 3d rendering context and not
   // the root of it.
-  EXPECT_FALSE(root->should_check_backface_visibility());
-  EXPECT_TRUE(child->should_check_backface_visibility());
-  EXPECT_TRUE(grand_child->should_check_backface_visibility());
+  EXPECT_FALSE(ImplOf(root)->should_check_backface_visibility());
+  EXPECT_TRUE(ImplOf(child)->should_check_backface_visibility());
+  EXPECT_TRUE(ImplOf(grand_child)->should_check_backface_visibility());
 }
 
 TEST_F(LayerTreeHostCommonTest, TransformAnimationUpdatesBackfaceVisibility) {
@@ -6694,32 +6698,28 @@
   TransformOperations translation;
   translation.AppendTranslate(1.f, 2.f, 3.f);
 
-  scoped_refptr<AnimationTimeline> timeline;
-  timeline = AnimationTimeline::Create(AnimationIdProvider::NextTimelineId());
-  host_impl()->animation_host()->AddAnimationTimeline(timeline);
-
   scoped_refptr<SingleKeyframeEffectAnimation> grand_parent_animation =
       SingleKeyframeEffectAnimation::Create(
           AnimationIdProvider::NextAnimationId());
-  timeline->AttachAnimation(grand_parent_animation);
+  timeline_impl()->AttachAnimation(grand_parent_animation);
   grand_parent_animation->AttachElement(grand_parent->element_id());
 
   scoped_refptr<SingleKeyframeEffectAnimation> parent_animation =
       SingleKeyframeEffectAnimation::Create(
           AnimationIdProvider::NextAnimationId());
-  timeline->AttachAnimation(parent_animation);
+  timeline_impl()->AttachAnimation(parent_animation);
   parent_animation->AttachElement(parent->element_id());
 
   scoped_refptr<SingleKeyframeEffectAnimation> child_animation =
       SingleKeyframeEffectAnimation::Create(
           AnimationIdProvider::NextAnimationId());
-  timeline->AttachAnimation(child_animation);
+  timeline_impl()->AttachAnimation(child_animation);
   child_animation->AttachElement(child->element_id());
 
   scoped_refptr<SingleKeyframeEffectAnimation> grand_child_animation =
       SingleKeyframeEffectAnimation::Create(
           AnimationIdProvider::NextAnimationId());
-  timeline->AttachAnimation(grand_child_animation);
+  timeline_impl()->AttachAnimation(grand_child_animation);
   grand_child_animation->AttachElement(grand_child->element_id());
 
   AddAnimatedTransformToAnimation(parent_animation.get(), 1.0,
@@ -6902,29 +6902,12 @@
 
 // Needs layer tree mode: mask layer.
 TEST_F(LayerTreeHostCommonTestWithLayerTree, RenderSurfaceLayerListMembership) {
-  FakeImplTaskRunnerProvider task_runner_provider;
-  TestTaskGraphRunner task_graph_runner;
-  FakeLayerTreeHostImpl host_impl(&task_runner_provider, &task_graph_runner);
-
-  std::unique_ptr<LayerImpl> root =
-      LayerImpl::Create(host_impl.active_tree(), 1);
-  std::unique_ptr<LayerImpl> grand_parent =
-      LayerImpl::Create(host_impl.active_tree(), 2);
-  std::unique_ptr<LayerImpl> parent =
-      LayerImpl::Create(host_impl.active_tree(), 4);
-  std::unique_ptr<LayerImpl> child =
-      LayerImpl::Create(host_impl.active_tree(), 6);
-  std::unique_ptr<LayerImpl> grand_child1 =
-      LayerImpl::Create(host_impl.active_tree(), 8);
-  std::unique_ptr<LayerImpl> grand_child2 =
-      LayerImpl::Create(host_impl.active_tree(), 10);
-
-  LayerImpl* root_raw = root.get();
-  LayerImpl* grand_parent_raw = grand_parent.get();
-  LayerImpl* parent_raw = parent.get();
-  LayerImpl* child_raw = child.get();
-  LayerImpl* grand_child1_raw = grand_child1.get();
-  LayerImpl* grand_child2_raw = grand_child2.get();
+  auto root = Layer::Create();
+  auto grand_parent = Layer::Create();
+  auto parent = Layer::Create();
+  auto child = Layer::Create();
+  auto grand_child1 = Layer::Create();
+  auto grand_child2 = Layer::Create();
 
   root->SetBounds(gfx::Size(1, 2));
   grand_parent->SetBounds(gfx::Size(1, 2));
@@ -6933,326 +6916,277 @@
   grand_child1->SetBounds(gfx::Size(1, 2));
   grand_child2->SetBounds(gfx::Size(1, 2));
 
-  child->test_properties()->AddChild(std::move(grand_child1));
-  child->test_properties()->AddChild(std::move(grand_child2));
-  parent->test_properties()->AddChild(std::move(child));
-  grand_parent->test_properties()->AddChild(std::move(parent));
-  root->test_properties()->AddChild(std::move(grand_parent));
-  host_impl.active_tree()->SetRootLayerForTesting(std::move(root));
+  child->AddChild(grand_child1);
+  child->AddChild(grand_child2);
+  parent->AddChild(child);
+  grand_parent->AddChild(parent);
+  root->AddChild(grand_parent);
+  host()->SetRootLayer(root);
 
   // Start with nothing being drawn.
-  ExecuteCalculateDrawProperties(root_raw);
+  CommitAndActivate();
 
-  EXPECT_FALSE(grand_parent_raw->contributes_to_drawn_render_surface());
-  EXPECT_FALSE(parent_raw->contributes_to_drawn_render_surface());
-  EXPECT_FALSE(child_raw->contributes_to_drawn_render_surface());
-  EXPECT_FALSE(grand_child1_raw->contributes_to_drawn_render_surface());
-  EXPECT_FALSE(grand_child2_raw->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(grand_parent)->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(parent)->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(child)->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(grand_child1)->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(grand_child2)->contributes_to_drawn_render_surface());
 
   std::set<LayerImpl*> expected;
   std::set<LayerImpl*> actual;
-  GatherDrawnLayers(host_impl.active_tree(), &actual);
+  GatherDrawnLayers(host_impl()->active_tree(), &actual);
   EXPECT_EQ(expected, actual);
 
   // If we force render surface, but none of the layers are in the layer list,
   // then this layer should not appear in RSLL.
-  grand_child1_raw->test_properties()->force_render_surface = true;
-  grand_child1_raw->layer_tree_impl()->property_trees()->needs_rebuild = true;
+  grand_child1->SetForceRenderSurfaceForTesting(true);
 
-  ExecuteCalculateDrawProperties(root_raw);
+  CommitAndActivate();
 
-  EXPECT_FALSE(grand_parent_raw->contributes_to_drawn_render_surface());
-  EXPECT_FALSE(parent_raw->contributes_to_drawn_render_surface());
-  EXPECT_FALSE(child_raw->contributes_to_drawn_render_surface());
-  EXPECT_FALSE(grand_child1_raw->contributes_to_drawn_render_surface());
-  EXPECT_FALSE(grand_child2_raw->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(grand_parent)->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(parent)->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(child)->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(grand_child1)->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(grand_child2)->contributes_to_drawn_render_surface());
 
   expected.clear();
   actual.clear();
-  GatherDrawnLayers(host_impl.active_tree(), &actual);
+  GatherDrawnLayers(host_impl()->active_tree(), &actual);
   EXPECT_EQ(expected, actual);
 
   // However, if we say that this layer also draws content, it will appear in
   // RSLL.
-  grand_child1_raw->SetDrawsContent(true);
+  grand_child1->SetIsDrawable(true);
 
-  ExecuteCalculateDrawProperties(root_raw);
+  CommitAndActivate();
 
-  EXPECT_FALSE(grand_parent_raw->contributes_to_drawn_render_surface());
-  EXPECT_FALSE(parent_raw->contributes_to_drawn_render_surface());
-  EXPECT_FALSE(child_raw->contributes_to_drawn_render_surface());
-  EXPECT_TRUE(grand_child1_raw->contributes_to_drawn_render_surface());
-  EXPECT_FALSE(grand_child2_raw->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(grand_parent)->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(parent)->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(child)->contributes_to_drawn_render_surface());
+  EXPECT_TRUE(ImplOf(grand_child1)->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(grand_child2)->contributes_to_drawn_render_surface());
 
   expected.clear();
-  expected.insert(grand_child1_raw);
+  expected.insert(ImplOf(grand_child1));
 
   actual.clear();
-  GatherDrawnLayers(host_impl.active_tree(), &actual);
+  GatherDrawnLayers(host_impl()->active_tree(), &actual);
   EXPECT_EQ(expected, actual);
 
   // Now child is forced to have a render surface, and one if its children draws
   // content.
-  grand_child1_raw->SetDrawsContent(false);
-  grand_child1_raw->test_properties()->force_render_surface = false;
-  grand_child1_raw->layer_tree_impl()->property_trees()->needs_rebuild = true;
-  child_raw->test_properties()->force_render_surface = true;
-  grand_child2_raw->SetDrawsContent(true);
+  grand_child1->SetIsDrawable(false);
+  grand_child1->SetForceRenderSurfaceForTesting(false);
+  child->SetForceRenderSurfaceForTesting(true);
+  grand_child2->SetIsDrawable(true);
 
-  ExecuteCalculateDrawProperties(root_raw);
+  CommitAndActivate();
 
-  EXPECT_FALSE(grand_parent_raw->contributes_to_drawn_render_surface());
-  EXPECT_FALSE(parent_raw->contributes_to_drawn_render_surface());
-  EXPECT_FALSE(child_raw->contributes_to_drawn_render_surface());
-  EXPECT_FALSE(grand_child1_raw->contributes_to_drawn_render_surface());
-  EXPECT_TRUE(grand_child2_raw->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(grand_parent)->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(parent)->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(child)->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(grand_child1)->contributes_to_drawn_render_surface());
+  EXPECT_TRUE(ImplOf(grand_child2)->contributes_to_drawn_render_surface());
 
   expected.clear();
-  expected.insert(grand_child2_raw);
+  expected.insert(ImplOf(grand_child2));
 
   actual.clear();
-  GatherDrawnLayers(host_impl.active_tree(), &actual);
+  GatherDrawnLayers(host_impl()->active_tree(), &actual);
   EXPECT_EQ(expected, actual);
 
   // Add a mask layer to child.
-  child_raw->test_properties()->SetMaskLayer(
-      LayerImpl::Create(host_impl.active_tree(), 7));
-  child_raw->layer_tree_impl()->property_trees()->needs_rebuild = true;
+  FakeContentLayerClient client;
+  auto mask = PictureLayer::Create(&client);
+  mask->SetBounds(child->bounds());
+  child->SetMaskLayer(mask);
 
-  ExecuteCalculateDrawProperties(root_raw);
+  CommitAndActivate();
 
-  EXPECT_FALSE(grand_parent_raw->contributes_to_drawn_render_surface());
-  EXPECT_FALSE(parent_raw->contributes_to_drawn_render_surface());
-  EXPECT_FALSE(child_raw->contributes_to_drawn_render_surface());
-  EXPECT_TRUE(child_raw->test_properties()
-                  ->mask_layer->contributes_to_drawn_render_surface());
-  EXPECT_FALSE(grand_child1_raw->contributes_to_drawn_render_surface());
-  EXPECT_TRUE(grand_child2_raw->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(grand_parent)->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(parent)->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(child)->contributes_to_drawn_render_surface());
+  EXPECT_TRUE(ImplOf(mask)->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(grand_child1)->contributes_to_drawn_render_surface());
+  EXPECT_TRUE(ImplOf(grand_child2)->contributes_to_drawn_render_surface());
 
   expected.clear();
-  expected.insert(grand_child2_raw);
-  expected.insert(child_raw->test_properties()->mask_layer);
-
-  expected.clear();
-  expected.insert(grand_child2_raw);
-  expected.insert(child_raw->test_properties()->mask_layer);
+  expected.insert(ImplOf(grand_child2));
+  expected.insert(ImplOf(mask));
 
   actual.clear();
-  GatherDrawnLayers(host_impl.active_tree(), &actual);
+  GatherDrawnLayers(host_impl()->active_tree(), &actual);
   EXPECT_EQ(expected, actual);
 
-  ExecuteCalculateDrawProperties(root_raw);
+  CommitAndActivate();
 
-  EXPECT_FALSE(grand_parent_raw->contributes_to_drawn_render_surface());
-  EXPECT_FALSE(parent_raw->contributes_to_drawn_render_surface());
-  EXPECT_FALSE(child_raw->contributes_to_drawn_render_surface());
-  EXPECT_TRUE(child_raw->test_properties()
-                  ->mask_layer->contributes_to_drawn_render_surface());
-  EXPECT_FALSE(grand_child1_raw->contributes_to_drawn_render_surface());
-  EXPECT_TRUE(grand_child2_raw->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(grand_parent)->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(parent)->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(child)->contributes_to_drawn_render_surface());
+  EXPECT_TRUE(ImplOf(mask)->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(grand_child1)->contributes_to_drawn_render_surface());
+  EXPECT_TRUE(ImplOf(grand_child2)->contributes_to_drawn_render_surface());
 
   expected.clear();
-  expected.insert(grand_child2_raw);
-  expected.insert(child_raw->test_properties()->mask_layer);
+  expected.insert(ImplOf(grand_child2));
+  expected.insert(ImplOf(mask));
 
   actual.clear();
-  GatherDrawnLayers(host_impl.active_tree(), &actual);
+  GatherDrawnLayers(host_impl()->active_tree(), &actual);
   EXPECT_EQ(expected, actual);
 
-  child_raw->layer_tree_impl()->property_trees()->needs_rebuild = true;
-
   // With nothing drawing, we should have no layers.
-  grand_child2_raw->SetDrawsContent(false);
+  grand_child2->SetIsDrawable(false);
 
-  ExecuteCalculateDrawProperties(root_raw);
+  CommitAndActivate();
 
-  EXPECT_FALSE(grand_parent_raw->contributes_to_drawn_render_surface());
-  EXPECT_FALSE(parent_raw->contributes_to_drawn_render_surface());
-  EXPECT_FALSE(child_raw->contributes_to_drawn_render_surface());
-  EXPECT_FALSE(child_raw->test_properties()
-                   ->mask_layer->contributes_to_drawn_render_surface());
-  EXPECT_FALSE(grand_child1_raw->contributes_to_drawn_render_surface());
-  EXPECT_FALSE(grand_child2_raw->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(grand_parent)->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(parent)->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(child)->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(mask)->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(grand_child1)->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(grand_child2)->contributes_to_drawn_render_surface());
 
   expected.clear();
   actual.clear();
-  GatherDrawnLayers(host_impl.active_tree(), &actual);
+  GatherDrawnLayers(host_impl()->active_tree(), &actual);
   EXPECT_EQ(expected, actual);
 
-  // Child itself draws means that we should have the child and the mask in the
-  // list.
-  child_raw->SetDrawsContent(true);
+  // When the child is drawable, both the child and the mask should be in the
+  // render surface list.
+  child->SetIsDrawable(true);
 
-  ExecuteCalculateDrawProperties(root_raw);
+  CommitAndActivate();
 
-  EXPECT_FALSE(grand_parent_raw->contributes_to_drawn_render_surface());
-  EXPECT_FALSE(parent_raw->contributes_to_drawn_render_surface());
-  EXPECT_TRUE(child_raw->contributes_to_drawn_render_surface());
-  EXPECT_TRUE(child_raw->test_properties()
-                  ->mask_layer->contributes_to_drawn_render_surface());
-  EXPECT_FALSE(grand_child1_raw->contributes_to_drawn_render_surface());
-  EXPECT_FALSE(grand_child2_raw->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(grand_parent)->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(parent)->contributes_to_drawn_render_surface());
+  EXPECT_TRUE(ImplOf(child)->contributes_to_drawn_render_surface());
+  EXPECT_TRUE(ImplOf(mask)->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(grand_child1)->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(grand_child2)->contributes_to_drawn_render_surface());
 
   expected.clear();
-  expected.insert(child_raw);
-  expected.insert(child_raw->test_properties()->mask_layer);
+  expected.insert(ImplOf(child));
+  expected.insert(ImplOf(mask));
   actual.clear();
-  GatherDrawnLayers(host_impl.active_tree(), &actual);
+  GatherDrawnLayers(host_impl()->active_tree(), &actual);
   EXPECT_EQ(expected, actual);
 
-  child_raw->test_properties()->SetMaskLayer(nullptr);
-  child_raw->layer_tree_impl()->property_trees()->needs_rebuild = true;
+  child->SetMaskLayer(nullptr);
 
   // Now everyone's a member!
-  grand_parent_raw->SetDrawsContent(true);
-  parent_raw->SetDrawsContent(true);
-  child_raw->SetDrawsContent(true);
-  grand_child1_raw->SetDrawsContent(true);
-  grand_child2_raw->SetDrawsContent(true);
+  grand_parent->SetIsDrawable(true);
+  parent->SetIsDrawable(true);
+  child->SetIsDrawable(true);
+  grand_child1->SetIsDrawable(true);
+  grand_child2->SetIsDrawable(true);
 
-  ExecuteCalculateDrawProperties(root_raw);
+  CommitAndActivate();
 
-  EXPECT_TRUE(grand_parent_raw->contributes_to_drawn_render_surface());
-  EXPECT_TRUE(parent_raw->contributes_to_drawn_render_surface());
-  EXPECT_TRUE(child_raw->contributes_to_drawn_render_surface());
-  EXPECT_TRUE(grand_child1_raw->contributes_to_drawn_render_surface());
-  EXPECT_TRUE(grand_child2_raw->contributes_to_drawn_render_surface());
+  EXPECT_TRUE(ImplOf(grand_parent)->contributes_to_drawn_render_surface());
+  EXPECT_TRUE(ImplOf(parent)->contributes_to_drawn_render_surface());
+  EXPECT_TRUE(ImplOf(child)->contributes_to_drawn_render_surface());
+  EXPECT_TRUE(ImplOf(grand_child1)->contributes_to_drawn_render_surface());
+  EXPECT_TRUE(ImplOf(grand_child2)->contributes_to_drawn_render_surface());
 
   expected.clear();
-  expected.insert(grand_parent_raw);
-  expected.insert(parent_raw);
-  expected.insert(child_raw);
-  expected.insert(grand_child1_raw);
-  expected.insert(grand_child2_raw);
+  expected.insert(ImplOf(grand_parent));
+  expected.insert(ImplOf(parent));
+  expected.insert(ImplOf(child));
+  expected.insert(ImplOf(grand_child1));
+  expected.insert(ImplOf(grand_child2));
 
   actual.clear();
-  GatherDrawnLayers(host_impl.active_tree(), &actual);
+  GatherDrawnLayers(host_impl()->active_tree(), &actual);
   EXPECT_EQ(expected, actual);
 }
 
 // Needs layer tree mode: mask layer.
 TEST_F(LayerTreeHostCommonTestWithLayerTree, DrawPropertyScales) {
-  FakeImplTaskRunnerProvider task_runner_provider;
-  TestTaskGraphRunner task_graph_runner;
-  LayerTreeSettings settings = host()->GetSettings();
-  FakeLayerTreeHostImpl host_impl(settings, &task_runner_provider,
-                                  &task_graph_runner);
-
-  std::unique_ptr<LayerImpl> root =
-      LayerImpl::Create(host_impl.active_tree(), 1);
-  LayerImpl* root_layer = root.get();
-  std::unique_ptr<LayerImpl> page_scale =
-      LayerImpl::Create(host_impl.active_tree(), 2);
-  LayerImpl* page_scale_layer = page_scale.get();
-  std::unique_ptr<LayerImpl> child1 =
-      LayerImpl::Create(host_impl.active_tree(), 3);
-  LayerImpl* child1_layer = child1.get();
-  std::unique_ptr<LayerImpl> child2 =
-      LayerImpl::Create(host_impl.active_tree(), 4);
-  LayerImpl* child2_layer = child2.get();
+  auto root = Layer::Create();
+  auto page_scale = Layer::Create();
+  auto child1 = Layer::Create();
+  auto child2 = Layer::Create();
 
   gfx::Transform scale_transform_child1, scale_transform_child2;
   scale_transform_child1.Scale(2, 3);
   scale_transform_child2.Scale(4, 5);
 
   root->SetBounds(gfx::Size(1, 1));
-  root->SetDrawsContent(true);
-  child1_layer->test_properties()->transform = scale_transform_child1;
-  child1_layer->SetBounds(gfx::Size(1, 1));
-  child1_layer->SetDrawsContent(true);
+  root->SetIsDrawable(true);
+  child1->SetTransform(scale_transform_child1);
+  child1->SetBounds(gfx::Size(1, 1));
+  child1->SetIsDrawable(true);
 
-  child1_layer->test_properties()->SetMaskLayer(
-      LayerImpl::Create(host_impl.active_tree(), 5));
+  FakeContentLayerClient client;
+  auto mask = PictureLayer::Create(&client);
+  mask->SetBounds(child1->bounds());
+  child1->SetMaskLayer(mask);
 
-  page_scale->test_properties()->AddChild(std::move(child1));
-  page_scale->test_properties()->AddChild(std::move(child2));
-  root->test_properties()->AddChild(std::move(page_scale));
-  host_impl.active_tree()->SetRootLayerForTesting(std::move(root));
-  host_impl.active_tree()->SetElementIdsForTesting();
+  page_scale->AddChild(child1);
+  page_scale->AddChild(child2);
+  root->AddChild(page_scale);
+  host()->SetRootLayer(root);
+  host()->SetElementIdsForTesting();
 
-  ExecuteCalculateDrawProperties(root_layer, 1.f, 1.f, page_scale_layer,
-                                 nullptr, nullptr);
+  CommitAndActivate();
 
   TransformOperations scale;
   scale.AppendScale(5.f, 8.f, 3.f);
 
-  scoped_refptr<AnimationTimeline> timeline =
-      AnimationTimeline::Create(AnimationIdProvider::NextTimelineId());
-  host_impl.animation_host()->AddAnimationTimeline(timeline);
+  child2->SetTransform(scale_transform_child2);
+  child2->SetBounds(gfx::Size(1, 1));
+  child2->SetIsDrawable(true);
+  AddAnimatedTransformToElementWithAnimation(child2->element_id(), timeline(),
+                                             1.0, TransformOperations(), scale);
 
-  child2_layer->test_properties()->transform = scale_transform_child2;
-  child2_layer->SetBounds(gfx::Size(1, 1));
-  child2_layer->SetDrawsContent(true);
-  AddAnimatedTransformToElementWithAnimation(
-      child2_layer->element_id(), timeline, 1.0, TransformOperations(), scale);
+  CommitAndActivate();
 
-  root_layer->layer_tree_impl()->property_trees()->needs_rebuild = true;
-  ExecuteCalculateDrawProperties(root_layer, 1.f, 1.f, page_scale_layer,
-                                 nullptr, nullptr);
+  EXPECT_FLOAT_EQ(1.f, ImplOf(root)->GetIdealContentsScale());
+  EXPECT_FLOAT_EQ(1.f, ImplOf(page_scale)->GetIdealContentsScale());
+  EXPECT_FLOAT_EQ(3.f, ImplOf(child1)->GetIdealContentsScale());
+  EXPECT_FLOAT_EQ(3.f, ImplOf(mask)->GetIdealContentsScale());
+  EXPECT_FLOAT_EQ(5.f, ImplOf(child2)->GetIdealContentsScale());
 
-  EXPECT_FLOAT_EQ(1.f, root_layer->GetIdealContentsScale());
-  EXPECT_FLOAT_EQ(1.f, page_scale_layer->GetIdealContentsScale());
-  EXPECT_FLOAT_EQ(3.f, child1_layer->GetIdealContentsScale());
-  EXPECT_FLOAT_EQ(
-      3.f,
-      child1_layer->test_properties()->mask_layer->GetIdealContentsScale());
-  EXPECT_FLOAT_EQ(5.f, child2_layer->GetIdealContentsScale());
-
-  EXPECT_FLOAT_EQ(kNotScaled, GetMaximumAnimationScale(root_layer));
-  EXPECT_FLOAT_EQ(kNotScaled, GetMaximumAnimationScale(page_scale_layer));
-  EXPECT_FLOAT_EQ(kNotScaled, GetMaximumAnimationScale(child1_layer));
-  EXPECT_FLOAT_EQ(8.f, GetMaximumAnimationScale(child2_layer));
+  EXPECT_FLOAT_EQ(kNotScaled, GetMaximumAnimationScale(ImplOf(root)));
+  EXPECT_FLOAT_EQ(kNotScaled, GetMaximumAnimationScale(ImplOf(page_scale)));
+  EXPECT_FLOAT_EQ(kNotScaled, GetMaximumAnimationScale(ImplOf(child1)));
+  EXPECT_FLOAT_EQ(8.f, GetMaximumAnimationScale(ImplOf(child2)));
 
   // Changing page-scale would affect ideal_contents_scale and
   // maximum_animation_contents_scale.
 
-  float page_scale_factor = 3.f;
   float device_scale_factor = 1.0f;
-  RenderSurfaceList render_surface_list;
-  gfx::Rect device_viewport_rect =
-      gfx::Rect(root_layer->bounds().width() * device_scale_factor,
-                root_layer->bounds().height() * device_scale_factor);
-  LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs(
-      root_layer, device_viewport_rect, &render_surface_list);
+  float page_scale_factor = 3.f;
+  CommitAndActivate(device_scale_factor, page_scale_factor, page_scale.get());
 
-  inputs.page_scale_factor = page_scale_factor;
-  inputs.page_scale_layer = page_scale_layer;
-  inputs.page_scale_transform_node = GetTransformNode(page_scale_layer);
-  LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs);
+  EXPECT_FLOAT_EQ(1.f, ImplOf(root)->GetIdealContentsScale());
+  EXPECT_FLOAT_EQ(3.f, ImplOf(page_scale)->GetIdealContentsScale());
+  EXPECT_FLOAT_EQ(9.f, ImplOf(child1)->GetIdealContentsScale());
+  EXPECT_FLOAT_EQ(9.f, ImplOf(mask)->GetIdealContentsScale());
+  EXPECT_FLOAT_EQ(15.f, ImplOf(child2)->GetIdealContentsScale());
 
-  EXPECT_FLOAT_EQ(1.f, root_layer->GetIdealContentsScale());
-  EXPECT_FLOAT_EQ(3.f, page_scale_layer->GetIdealContentsScale());
-  EXPECT_FLOAT_EQ(9.f, child1_layer->GetIdealContentsScale());
-  EXPECT_FLOAT_EQ(
-      9.f,
-      child1_layer->test_properties()->mask_layer->GetIdealContentsScale());
-  EXPECT_FLOAT_EQ(15.f, child2_layer->GetIdealContentsScale());
-
-  EXPECT_FLOAT_EQ(kNotScaled, GetMaximumAnimationScale(root_layer));
-  EXPECT_FLOAT_EQ(kNotScaled, GetMaximumAnimationScale(page_scale_layer));
-  EXPECT_FLOAT_EQ(kNotScaled, GetMaximumAnimationScale(child1_layer));
-  EXPECT_FLOAT_EQ(24.f, GetMaximumAnimationScale(child2_layer));
+  EXPECT_FLOAT_EQ(kNotScaled, GetMaximumAnimationScale(ImplOf(root)));
+  EXPECT_FLOAT_EQ(kNotScaled, GetMaximumAnimationScale(ImplOf(page_scale)));
+  EXPECT_FLOAT_EQ(kNotScaled, GetMaximumAnimationScale(ImplOf(child1)));
+  EXPECT_FLOAT_EQ(24.f, GetMaximumAnimationScale(ImplOf(child2)));
 
   // Changing device-scale would affect ideal_contents_scale and
   // maximum_animation_contents_scale.
 
   device_scale_factor = 4.0f;
-  inputs.device_scale_factor = device_scale_factor;
-  root_layer->layer_tree_impl()->property_trees()->needs_rebuild = true;
-  LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs);
+  CommitAndActivate(device_scale_factor, page_scale_factor, page_scale.get());
 
-  EXPECT_FLOAT_EQ(4.f, root_layer->GetIdealContentsScale());
-  EXPECT_FLOAT_EQ(12.f, page_scale_layer->GetIdealContentsScale());
-  EXPECT_FLOAT_EQ(36.f, child1_layer->GetIdealContentsScale());
-  EXPECT_FLOAT_EQ(
-      36.f,
-      child1_layer->test_properties()->mask_layer->GetIdealContentsScale());
-  EXPECT_FLOAT_EQ(60.f, child2_layer->GetIdealContentsScale());
+  EXPECT_FLOAT_EQ(4.f, ImplOf(root)->GetIdealContentsScale());
+  EXPECT_FLOAT_EQ(12.f, ImplOf(page_scale)->GetIdealContentsScale());
+  EXPECT_FLOAT_EQ(36.f, ImplOf(child1)->GetIdealContentsScale());
+  EXPECT_FLOAT_EQ(36.f, ImplOf(mask)->GetIdealContentsScale());
+  EXPECT_FLOAT_EQ(60.f, ImplOf(child2)->GetIdealContentsScale());
 
-  EXPECT_FLOAT_EQ(kNotScaled, GetMaximumAnimationScale(root_layer));
-  EXPECT_FLOAT_EQ(kNotScaled, GetMaximumAnimationScale(page_scale_layer));
-  EXPECT_FLOAT_EQ(kNotScaled, GetMaximumAnimationScale(child1_layer));
-  EXPECT_FLOAT_EQ(96.f, GetMaximumAnimationScale(child2_layer));
+  EXPECT_FLOAT_EQ(kNotScaled, GetMaximumAnimationScale(ImplOf(root)));
+  EXPECT_FLOAT_EQ(kNotScaled, GetMaximumAnimationScale(ImplOf(page_scale)));
+  EXPECT_FLOAT_EQ(kNotScaled, GetMaximumAnimationScale(ImplOf(child1)));
+  EXPECT_FLOAT_EQ(96.f, GetMaximumAnimationScale(ImplOf(child2)));
 }
 
 TEST_F(LayerTreeHostCommonTest, AnimationScales) {
@@ -7278,15 +7212,8 @@
   TransformOperations scale;
   scale.AppendScale(5.f, 8.f, 3.f);
 
-  scoped_refptr<AnimationTimeline> timeline =
-      AnimationTimeline::Create(AnimationIdProvider::NextTimelineId());
-  host_impl()->animation_host()->AddAnimationTimeline(timeline);
-
-  AddAnimatedTransformToElementWithAnimation(child2->element_id(), timeline,
-                                             1.0, TransformOperations(), scale);
-
-  // Correctly computes animation scale when rebuilding property trees.
-  root->layer_tree_impl()->property_trees()->needs_rebuild = true;
+  AddAnimatedTransformToElementWithAnimation(
+      child2->element_id(), timeline_impl(), 1.0, TransformOperations(), scale);
   ExecuteCalculateDrawProperties(root);
 
   EXPECT_FLOAT_EQ(kNotScaled, GetMaximumAnimationScale(root));
@@ -7380,15 +7307,11 @@
   CreateClipNode(root);
   CopyProperties(root, sublayer);
 
-  RenderSurfaceList render_surface_list;
-  LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs(
-      root, device_viewport_rect, &render_surface_list);
-
-  LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs);
+  ExecuteCalculateDrawProperties(root);
   EXPECT_EQ(gfx::Rect(root_size), sublayer->visible_layer_rect());
 
   root->SetViewportBoundsDelta(gfx::Vector2dF(0.0, 50.0));
-  LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs);
+  ExecuteCalculateDrawProperties(root);
 
   gfx::Rect affected_by_delta(0, 0, root_size.width(),
                               root_size.height() + 50);
@@ -7396,27 +7319,23 @@
 }
 
 TEST_F(LayerTreeHostCommonTest, VisibleContentRectForAnimatedLayer) {
-  LayerImpl* root = root_layer_for_testing();
-  LayerImpl* animated = AddLayer<LayerImpl>();
-  SetElementIdsForTesting();
+  host_impl()->CreatePendingTree();
+  LayerImpl* root = EnsureRootLayerInPendingTree();
+  LayerImpl* animated = AddLayerInPendingTree<LayerImpl>();
+
+  animated->SetDrawsContent(true);
+  host_impl()->pending_tree()->SetElementIdsForTesting();
 
   root->SetBounds(gfx::Size(100, 100));
-  root->SetMasksToBounds(true);
   animated->SetBounds(gfx::Size(20, 20));
-  animated->SetDrawsContent(true);
 
   SetupRootProperties(root);
-  CreateEffectNode(root).render_surface_reason = RenderSurfaceReason::kTest;
-  CreateClipNode(root);
   CopyProperties(root, animated);
-  auto& animated_effect_node = CreateEffectNode(animated);
-  animated_effect_node.render_surface_reason =
-      RenderSurfaceReason::kOpacityAnimation;
-  animated_effect_node.opacity = 0.f;
+  CreateEffectNode(animated).opacity = 0.f;
 
   AddOpacityTransitionToElementWithAnimation(
       animated->element_id(), timeline_impl(), 10.0, 0.f, 1.f, false);
-  ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root);
+  ExecuteCalculateDrawProperties(root);
 
   EXPECT_FALSE(animated->visible_layer_rect().IsEmpty());
 }
@@ -7518,25 +7437,28 @@
 // Needs layer tree mode: testing PropertyTreeBuilder.
 TEST_F(LayerTreeHostCommonTestWithLayerTree,
        AnimatedOpacityCreatesRenderSurface) {
-  LayerImpl* root = root_layer_for_testing();
-  LayerImpl* child = AddChild<LayerImpl>(root);
-  LayerImpl* grandchild = AddChild<LayerImpl>(child);
+  auto root = Layer::Create();
+  host()->SetRootLayer(root);
+  auto child = Layer::Create();
+  root->AddChild(child);
+  auto grandchild = Layer::Create();
+  child->AddChild(grandchild);
 
   root->SetBounds(gfx::Size(50, 50));
   child->SetBounds(gfx::Size(50, 50));
-  child->SetDrawsContent(true);
+  child->SetIsDrawable(true);
   grandchild->SetBounds(gfx::Size(50, 50));
-  grandchild->SetDrawsContent(true);
+  grandchild->SetIsDrawable(true);
 
-  SetElementIdsForTesting();
-  AddOpacityTransitionToElementWithAnimation(
-      child->element_id(), timeline_impl(), 10.0, 1.f, 0.2f, false);
-  ExecuteCalculateDrawProperties(root);
+  host()->SetElementIdsForTesting();
+  AddOpacityTransitionToElementWithAnimation(child->element_id(), timeline(),
+                                             10.0, 1.f, 0.2f, false);
+  CommitAndActivate();
 
-  EXPECT_EQ(1.f, child->Opacity());
-  EXPECT_TRUE(GetRenderSurface(root));
-  EXPECT_NE(GetRenderSurface(child), GetRenderSurface(root));
-  EXPECT_EQ(GetRenderSurface(grandchild), GetRenderSurface(child));
+  EXPECT_EQ(1.f, ImplOf(child)->Opacity());
+  EXPECT_TRUE(GetRenderSurfaceImpl(root));
+  EXPECT_NE(GetRenderSurfaceImpl(child), GetRenderSurfaceImpl(root));
+  EXPECT_EQ(GetRenderSurfaceImpl(grandchild), GetRenderSurfaceImpl(child));
 }
 
 static bool FilterIsAnimating(LayerImpl* layer) {
@@ -7550,29 +7472,32 @@
 // Needs layer tree mode: testing PropertyTreeBuilder.
 TEST_F(LayerTreeHostCommonTestWithLayerTree,
        AnimatedFilterCreatesRenderSurface) {
-  LayerImpl* root = root_layer_for_testing();
-  LayerImpl* child = AddChild<LayerImpl>(root);
-  LayerImpl* grandchild = AddChild<LayerImpl>(child);
+  auto root = Layer::Create();
+  host()->SetRootLayer(root);
+  auto child = Layer::Create();
+  root->AddChild(child);
+  auto grandchild = Layer::Create();
+  child->AddChild(grandchild);
 
   root->SetBounds(gfx::Size(50, 50));
   child->SetBounds(gfx::Size(50, 50));
   grandchild->SetBounds(gfx::Size(50, 50));
 
-  SetElementIdsForTesting();
-  AddAnimatedFilterToElementWithAnimation(child->element_id(), timeline_impl(),
-                                          10.0, 0.1f, 0.2f);
-  ExecuteCalculateDrawProperties(root);
+  host()->SetElementIdsForTesting();
+  AddAnimatedFilterToElementWithAnimation(child->element_id(), timeline(), 10.0,
+                                          0.1f, 0.2f);
+  CommitAndActivate();
 
-  EXPECT_TRUE(GetRenderSurface(root));
-  EXPECT_NE(GetRenderSurface(child), GetRenderSurface(root));
-  EXPECT_EQ(GetRenderSurface(grandchild), GetRenderSurface(child));
+  EXPECT_TRUE(GetRenderSurfaceImpl(root));
+  EXPECT_NE(GetRenderSurfaceImpl(child), GetRenderSurfaceImpl(root));
+  EXPECT_EQ(GetRenderSurfaceImpl(grandchild), GetRenderSurfaceImpl(child));
 
-  EXPECT_TRUE(GetRenderSurface(root)->Filters().IsEmpty());
-  EXPECT_TRUE(GetRenderSurface(child)->Filters().IsEmpty());
+  EXPECT_TRUE(GetRenderSurfaceImpl(root)->Filters().IsEmpty());
+  EXPECT_TRUE(GetRenderSurfaceImpl(child)->Filters().IsEmpty());
 
-  EXPECT_FALSE(FilterIsAnimating(root));
-  EXPECT_TRUE(FilterIsAnimating(child));
-  EXPECT_FALSE(FilterIsAnimating(grandchild));
+  EXPECT_FALSE(FilterIsAnimating(ImplOf(root)));
+  EXPECT_TRUE(FilterIsAnimating(ImplOf(child)));
+  EXPECT_FALSE(FilterIsAnimating(ImplOf(grandchild)));
 }
 
 bool HasPotentiallyRunningFilterAnimation(const LayerImpl& layer) {
@@ -7586,15 +7511,18 @@
 // Needs layer tree mode: testing PropertyTreeBuilder.
 TEST_F(LayerTreeHostCommonTestWithLayerTree,
        DelayedFilterAnimationCreatesRenderSurface) {
-  LayerImpl* root = root_layer_for_testing();
-  LayerImpl* child = AddChild<LayerImpl>(root);
-  LayerImpl* grandchild = AddChild<LayerImpl>(child);
+  auto root = Layer::Create();
+  host()->SetRootLayer(root);
+  auto child = Layer::Create();
+  root->AddChild(child);
+  auto grandchild = Layer::Create();
+  child->AddChild(grandchild);
 
   root->SetBounds(gfx::Size(50, 50));
   child->SetBounds(gfx::Size(50, 50));
   grandchild->SetBounds(gfx::Size(50, 50));
 
-  SetElementIdsForTesting();
+  host()->SetElementIdsForTesting();
 
   std::unique_ptr<KeyframedFilterAnimationCurve> curve(
       KeyframedFilterAnimationCurve::Create());
@@ -7611,23 +7539,23 @@
   keyframe_model->set_fill_mode(KeyframeModel::FillMode::NONE);
   keyframe_model->set_time_offset(base::TimeDelta::FromMilliseconds(-1000));
 
-  AddKeyframeModelToElementWithAnimation(child->element_id(), timeline_impl(),
+  AddKeyframeModelToElementWithAnimation(child->element_id(), timeline(),
                                          std::move(keyframe_model));
-  ExecuteCalculateDrawProperties(root);
+  CommitAndActivate();
 
-  EXPECT_TRUE(GetRenderSurface(root));
-  EXPECT_NE(GetRenderSurface(child), GetRenderSurface(root));
-  EXPECT_EQ(GetRenderSurface(grandchild), GetRenderSurface(child));
+  EXPECT_TRUE(GetRenderSurfaceImpl(root));
+  EXPECT_NE(GetRenderSurfaceImpl(child), GetRenderSurfaceImpl(root));
+  EXPECT_EQ(GetRenderSurfaceImpl(grandchild), GetRenderSurfaceImpl(child));
 
-  EXPECT_TRUE(GetRenderSurface(root)->Filters().IsEmpty());
-  EXPECT_TRUE(GetRenderSurface(child)->Filters().IsEmpty());
+  EXPECT_TRUE(GetRenderSurfaceImpl(root)->Filters().IsEmpty());
+  EXPECT_TRUE(GetRenderSurfaceImpl(child)->Filters().IsEmpty());
 
-  EXPECT_FALSE(FilterIsAnimating(root));
-  EXPECT_FALSE(HasPotentiallyRunningFilterAnimation(*root));
-  EXPECT_FALSE(FilterIsAnimating(child));
-  EXPECT_TRUE(HasPotentiallyRunningFilterAnimation(*child));
-  EXPECT_FALSE(FilterIsAnimating(grandchild));
-  EXPECT_FALSE(HasPotentiallyRunningFilterAnimation(*grandchild));
+  EXPECT_FALSE(FilterIsAnimating(ImplOf(root)));
+  EXPECT_FALSE(HasPotentiallyRunningFilterAnimation(*ImplOf(root)));
+  EXPECT_FALSE(FilterIsAnimating(ImplOf(child)));
+  EXPECT_TRUE(HasPotentiallyRunningFilterAnimation(*ImplOf(child)));
+  EXPECT_FALSE(FilterIsAnimating(ImplOf(grandchild)));
+  EXPECT_FALSE(HasPotentiallyRunningFilterAnimation(*ImplOf(grandchild)));
 }
 
 // Needs layer tree mode: needs_rebuild flag. Not using impl-side
@@ -7645,7 +7573,7 @@
 
   host()->SetRootLayer(root);
 
-  ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root.get());
+  ExecuteCalculateDrawProperties(root.get());
   EXPECT_FALSE(host()->property_trees()->needs_rebuild);
 
   root->SetTransform(translate);
@@ -7729,11 +7657,12 @@
   grandchild->AddChild(greatgrandchild);
   host()->SetRootLayer(root);
 
+  root->SetBounds(gfx::Size(1, 1));
   child1->RequestCopyOfOutput(viz::CopyOutputRequest::CreateStubForTesting());
   greatgrandchild->RequestCopyOfOutput(
       viz::CopyOutputRequest::CreateStubForTesting());
   child2->SetOpacity(0.f);
-  ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root.get());
+  ExecuteCalculateDrawProperties(root.get());
 
   EXPECT_TRUE(LayerSubtreeHasCopyRequest(root.get()));
   EXPECT_TRUE(LayerSubtreeHasCopyRequest(child1.get()));
@@ -7768,9 +7697,8 @@
   host()->SetElementIdsForTesting();
 
   // Check the non-skipped case.
-  ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root.get());
-  const LayerList* update_list = GetUpdateLayerList();
-  EXPECT_TRUE(VerifyLayerInList(grandchild, update_list));
+  ExecuteCalculateDrawProperties(root.get());
+  EXPECT_TRUE(UpdateLayerListContains(grandchild->id()));
 
   // Now we will reset the visible rect from property trees for the grandchild,
   // and we will configure |child| in several ways that should force the subtree
@@ -7780,15 +7708,13 @@
   singular.matrix().set(0, 0, 0);
 
   child->SetTransform(singular);
-  ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root.get());
-  update_list = GetUpdateLayerList();
-  EXPECT_FALSE(VerifyLayerInList(grandchild, update_list));
+  ExecuteCalculateDrawProperties(root.get());
+  EXPECT_FALSE(UpdateLayerListContains(grandchild->id()));
   child->SetTransform(gfx::Transform());
 
   child->SetHideLayerAndSubtree(true);
-  ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root.get());
-  update_list = GetUpdateLayerList();
-  EXPECT_FALSE(VerifyLayerInList(grandchild, update_list));
+  ExecuteCalculateDrawProperties(root.get());
+  EXPECT_FALSE(UpdateLayerListContains(grandchild->id()));
   child->SetHideLayerAndSubtree(false);
 
   gfx::Transform zero_z_scale;
@@ -7805,26 +7731,23 @@
   keyframe_model->set_time_offset(base::TimeDelta::FromMilliseconds(-1000));
   AddKeyframeModelToElementWithAnimation(child->element_id(), timeline(),
                                          std::move(keyframe_model));
-  ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root.get());
-  update_list = GetUpdateLayerList();
-  EXPECT_TRUE(VerifyLayerInList(grandchild, update_list));
+  ExecuteCalculateDrawProperties(root.get());
+  EXPECT_TRUE(UpdateLayerListContains(grandchild->id()));
 
   RemoveKeyframeModelFromElementWithExistingKeyframeEffect(
       child->element_id(), timeline(), keyframe_model_id);
   child->SetTransform(gfx::Transform());
   child->SetOpacity(0.f);
-  ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root.get());
-  update_list = GetUpdateLayerList();
-  EXPECT_FALSE(VerifyLayerInList(grandchild, update_list));
+  ExecuteCalculateDrawProperties(root.get());
+  EXPECT_FALSE(UpdateLayerListContains(grandchild->id()));
 
   // Now, even though child has zero opacity, we will configure |grandchild| and
   // |greatgrandchild| in several ways that should force the subtree to be
   // processed anyhow.
   grandchild->RequestCopyOfOutput(
       viz::CopyOutputRequest::CreateStubForTesting());
-  ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root.get());
-  update_list = GetUpdateLayerList();
-  EXPECT_TRUE(VerifyLayerInList(grandchild, update_list));
+  ExecuteCalculateDrawProperties(root.get());
+  EXPECT_TRUE(UpdateLayerListContains(grandchild->id()));
 
   // Add an opacity animation with a start delay.
   keyframe_model_id = 1;
@@ -7835,38 +7758,43 @@
   keyframe_model->set_time_offset(base::TimeDelta::FromMilliseconds(-1000));
   AddKeyframeModelToElementWithExistingKeyframeEffect(
       child->element_id(), timeline(), std::move(keyframe_model));
-  ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root.get());
-  update_list = GetUpdateLayerList();
-  EXPECT_TRUE(VerifyLayerInList(grandchild, update_list));
+  ExecuteCalculateDrawProperties(root.get());
+  EXPECT_TRUE(UpdateLayerListContains(grandchild->id()));
 }
 
 // Needs layer tree mode: hide_layer_and_subtree, etc.
 TEST_F(LayerTreeHostCommonTestWithLayerTree, SkippingLayerImpl) {
-  LayerImpl* root = root_layer_for_testing();
-  auto* parent = AddChildToRoot<LayerImpl>();
-  auto* child = AddChild<LayerImpl>(parent);
-  auto* grandchild = AddChild<LayerImpl>(child);
-  auto* greatgrandchild = AddChild<FakePictureLayerImpl>(grandchild);
+  auto root = Layer::Create();
+  host()->SetRootLayer(root);
+  auto parent = Layer::Create();
+  root->AddChild(parent);
+  auto child = Layer::Create();
+  parent->AddChild(child);
+  auto grandchild = Layer::Create();
+  child->AddChild(grandchild);
+  FakeContentLayerClient client;
+  auto greatgrandchild = PictureLayer::Create(&client);
+  grandchild->AddChild(greatgrandchild);
 
   root->SetBounds(gfx::Size(100, 100));
   parent->SetBounds(gfx::Size(100, 100));
   child->SetBounds(gfx::Size(10, 10));
-  child->SetDrawsContent(true);
+  child->SetIsDrawable(true);
   grandchild->SetBounds(gfx::Size(10, 10));
-  grandchild->SetDrawsContent(true);
-  greatgrandchild->SetDrawsContent(true);
+  grandchild->SetIsDrawable(true);
+  greatgrandchild->SetIsDrawable(true);
 
-  SetElementIdsForTesting();
+  host()->SetElementIdsForTesting();
 
   // Check the non-skipped case.
-  ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root);
-  EXPECT_EQ(gfx::Rect(10, 10), grandchild->visible_layer_rect());
+  CommitAndActivate();
+  EXPECT_EQ(gfx::Rect(10, 10), ImplOf(grandchild)->visible_layer_rect());
 
   // Now we will reset the visible rect from property trees for the grandchild,
   // and we will configure |child| in several ways that should force the subtree
   // to be skipped. The visible content rect for |grandchild| should, therefore,
   // remain empty.
-  grandchild->set_visible_layer_rect(gfx::Rect());
+  ImplOf(grandchild)->set_visible_layer_rect(gfx::Rect());
 
   gfx::Transform singular;
   singular.matrix().set(0, 0, 0);
@@ -7881,62 +7809,56 @@
   rotate_back_and_translate.RotateAboutYAxis(180);
   rotate_back_and_translate.Translate(-10, 0);
 
-  child->test_properties()->transform = singular;
-  GetPropertyTrees(root)->needs_rebuild = true;
-  ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root);
-  EXPECT_EQ(gfx::Rect(0, 0), grandchild->visible_layer_rect());
-  child->test_properties()->transform = gfx::Transform();
+  child->SetTransform(singular);
+  CommitAndActivate();
+  EXPECT_EQ(gfx::Rect(0, 0), ImplOf(grandchild)->visible_layer_rect());
+  child->SetTransform(gfx::Transform());
 
-  child->test_properties()->hide_layer_and_subtree = true;
-  ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root);
-  EXPECT_EQ(gfx::Rect(0, 0), grandchild->visible_layer_rect());
-  child->test_properties()->hide_layer_and_subtree = false;
+  child->SetHideLayerAndSubtree(true);
+  CommitAndActivate();
+  EXPECT_EQ(gfx::Rect(0, 0), ImplOf(grandchild)->visible_layer_rect());
+  child->SetHideLayerAndSubtree(false);
 
-  child->test_properties()->opacity = 0.f;
-  GetPropertyTrees(root)->needs_rebuild = true;
-  ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root);
-  EXPECT_EQ(gfx::Rect(0, 0), grandchild->visible_layer_rect());
-  child->test_properties()->opacity = 1.f;
+  child->SetOpacity(0.f);
+  CommitAndActivate();
+  EXPECT_EQ(gfx::Rect(0, 0), ImplOf(grandchild)->visible_layer_rect());
+  child->SetOpacity(1.f);
 
-  parent->test_properties()->transform = singular;
+  parent->SetTransform(singular);
   // Force transform tree to have a node for child, so that ancestor's
   // invertible transform can be tested.
-  child->test_properties()->transform = rotate;
-  GetPropertyTrees(root)->needs_rebuild = true;
-  ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root);
-  EXPECT_EQ(gfx::Rect(0, 0), grandchild->visible_layer_rect());
-  parent->test_properties()->transform = gfx::Transform();
-  child->test_properties()->transform = gfx::Transform();
+  child->SetTransform(rotate);
+  CommitAndActivate();
+  EXPECT_EQ(gfx::Rect(0, 0), ImplOf(grandchild)->visible_layer_rect());
+  parent->SetTransform(gfx::Transform());
+  child->SetTransform(gfx::Transform());
 
-  parent->test_properties()->opacity = 0.f;
-  child->test_properties()->opacity = 0.7f;
-  GetPropertyTrees(root)->needs_rebuild = true;
-  ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root);
-  EXPECT_EQ(gfx::Rect(0, 0), grandchild->visible_layer_rect());
-  parent->test_properties()->opacity = 1.f;
+  parent->SetOpacity(0.f);
+  child->SetOpacity(0.7f);
+  CommitAndActivate();
+  EXPECT_EQ(gfx::Rect(0, 0), ImplOf(grandchild)->visible_layer_rect());
+  parent->SetOpacity(1.f);
 
-  child->test_properties()->opacity = 0.f;
+  child->SetOpacity(0.f);
   // Now, even though child has zero opacity, we will configure |grandchild| and
   // |greatgrandchild| in several ways that should force the subtree to be
   // processed anyhow.
-  grandchild->test_properties()->copy_requests.push_back(
+  grandchild->RequestCopyOfOutput(
       viz::CopyOutputRequest::CreateStubForTesting());
-  GetPropertyTrees(root)->needs_rebuild = true;
-  ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root);
-  EXPECT_EQ(gfx::Rect(10, 10), grandchild->visible_layer_rect());
+  CommitAndActivate();
+  EXPECT_EQ(gfx::Rect(10, 10), ImplOf(grandchild)->visible_layer_rect());
 
-  GetPropertyTrees(root)->effect_tree.ClearCopyRequests();
-  child->test_properties()->opacity = 1.f;
+  GetPropertyTrees(root.get())->effect_tree.ClearCopyRequests();
+  child->SetOpacity(1.f);
 
   // A double sided render surface with backface visible should not be skipped
-  grandchild->set_visible_layer_rect(gfx::Rect());
-  child->test_properties()->force_render_surface = true;
-  child->test_properties()->double_sided = true;
-  child->test_properties()->transform = rotate_back_and_translate;
-  GetPropertyTrees(root)->needs_rebuild = true;
-  ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root);
-  EXPECT_EQ(gfx::Rect(10, 10), grandchild->visible_layer_rect());
-  child->test_properties()->transform = gfx::Transform();
+  ImplOf(grandchild)->set_visible_layer_rect(gfx::Rect());
+  child->SetForceRenderSurfaceForTesting(true);
+  child->SetDoubleSided(true);
+  child->SetTransform(rotate_back_and_translate);
+  CommitAndActivate();
+  EXPECT_EQ(gfx::Rect(10, 10), ImplOf(grandchild)->visible_layer_rect());
+  child->SetTransform(gfx::Transform());
 
   std::unique_ptr<KeyframedTransformAnimationCurve> curve(
       KeyframedTransformAnimationCurve::Create());
@@ -7954,19 +7876,15 @@
       KeyframeModel::Create(std::move(curve), 3, 3, TargetProperty::TRANSFORM));
   scoped_refptr<SingleKeyframeEffectAnimation> animation(
       SingleKeyframeEffectAnimation::Create(1));
-  scoped_refptr<AnimationTimeline> timeline =
-      AnimationTimeline::Create(AnimationIdProvider::NextTimelineId());
-  host_impl()->animation_host()->AddAnimationTimeline(timeline);
-  timeline->AttachAnimation(animation);
+  timeline()->AttachAnimation(animation);
   animation->AttachElementForKeyframeEffect(parent->element_id(),
                                             animation->keyframe_effect()->id());
   animation->AddKeyframeModel(std::move(transform_animation));
-  grandchild->set_visible_layer_rect(gfx::Rect());
-  parent->test_properties()->transform = singular;
-  child->test_properties()->transform = singular;
-  GetPropertyTrees(root)->needs_rebuild = true;
-  ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root);
-  EXPECT_EQ(gfx::Rect(0, 0), grandchild->visible_layer_rect());
+  ImplOf(grandchild)->set_visible_layer_rect(gfx::Rect());
+  parent->SetTransform(singular);
+  child->SetTransform(singular);
+  CommitAndActivate();
+  EXPECT_EQ(gfx::Rect(0, 0), ImplOf(grandchild)->visible_layer_rect());
 }
 
 // This tests for correctness of an optimization.  If a node in the tree
@@ -8063,50 +7981,34 @@
 // This tests that we skip computing the visible areas for the subtree
 // rooted at nodes with constant zero opacity.
 TEST_F(LayerTreeHostCommonTestWithLayerTree, SkippingPendingLayerImpl) {
-  FakeImplTaskRunnerProvider task_runner_provider;
-  TestTaskGraphRunner task_graph_runner;
-  FakeLayerTreeHostImpl host_impl(&task_runner_provider, &task_graph_runner);
-
-  host_impl.CreatePendingTree();
-  std::unique_ptr<LayerImpl> root =
-      LayerImpl::Create(host_impl.pending_tree(), 1);
-  std::unique_ptr<LayerImpl> child =
-      LayerImpl::Create(host_impl.pending_tree(), 2);
-  std::unique_ptr<LayerImpl> grandchild =
-      LayerImpl::Create(host_impl.pending_tree(), 3);
-
-  std::unique_ptr<FakePictureLayerImpl> greatgrandchild(
-      FakePictureLayerImpl::Create(host_impl.pending_tree(), 4));
+  auto root = Layer::Create();
+  auto child = Layer::Create();
+  auto grandchild = Layer::Create();
+  FakeContentLayerClient client;
+  auto greatgrandchild = PictureLayer::Create(&client);
 
   root->SetBounds(gfx::Size(100, 100));
   child->SetBounds(gfx::Size(10, 10));
-  child->SetDrawsContent(true);
+  child->SetIsDrawable(true);
   grandchild->SetBounds(gfx::Size(10, 10));
-  grandchild->SetDrawsContent(true);
-  greatgrandchild->SetDrawsContent(true);
+  grandchild->SetIsDrawable(true);
+  greatgrandchild->SetIsDrawable(true);
 
-  LayerImpl* root_ptr = root.get();
-  LayerImpl* grandchild_ptr = grandchild.get();
-
-  child->test_properties()->AddChild(std::move(grandchild));
-  root->test_properties()->AddChild(std::move(child));
-
-  host_impl.pending_tree()->SetRootLayerForTesting(std::move(root));
-  host_impl.pending_tree()->SetElementIdsForTesting();
+  child->AddChild(grandchild);
+  root->AddChild(child);
+  host()->SetRootLayer(root);
+  host()->SetElementIdsForTesting();
 
   // Check the non-skipped case.
-  root_ptr->test_properties()->opacity = 1.f;
-  grandchild_ptr->set_visible_layer_rect(gfx::Rect());
-  root_ptr->layer_tree_impl()->property_trees()->needs_rebuild = true;
-  ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root_ptr);
-  ASSERT_EQ(gfx::Rect(10, 10), grandchild_ptr->visible_layer_rect());
+  root->SetOpacity(1.f);
+  Commit();
+  ASSERT_EQ(gfx::Rect(10, 10), PendingImplOf(grandchild)->visible_layer_rect());
 
   // Check the skipped case.
-  root_ptr->test_properties()->opacity = 0.f;
-  grandchild_ptr->set_visible_layer_rect(gfx::Rect());
-  root_ptr->layer_tree_impl()->property_trees()->needs_rebuild = true;
-  ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root_ptr);
-  EXPECT_EQ(gfx::Rect(), grandchild_ptr->visible_layer_rect());
+  root->SetOpacity(0.f);
+  PendingImplOf(grandchild)->set_visible_layer_rect(gfx::Rect());
+  Commit();
+  EXPECT_EQ(gfx::Rect(), PendingImplOf(grandchild)->visible_layer_rect());
 
   // Check the animated case is not skipped.
   std::unique_ptr<KeyframedFloatAnimationCurve> curve(
@@ -8122,59 +8024,54 @@
       KeyframeModel::Create(std::move(curve), 3, 3, TargetProperty::OPACITY));
   scoped_refptr<SingleKeyframeEffectAnimation> animation(
       SingleKeyframeEffectAnimation::Create(1));
-  scoped_refptr<AnimationTimeline> timeline =
-      AnimationTimeline::Create(AnimationIdProvider::NextTimelineId());
-  host_impl.animation_host()->AddAnimationTimeline(timeline);
-  timeline->AttachAnimation(animation);
+  timeline()->AttachAnimation(animation);
   animation->AddKeyframeModel(std::move(keyframe_model));
-  animation->AttachElementForKeyframeEffect(root_ptr->element_id(),
+  animation->AttachElementForKeyframeEffect(root->element_id(),
                                             animation->keyframe_effect()->id());
   // Repeat the calculation invocation.
-  grandchild_ptr->set_visible_layer_rect(gfx::Rect());
-  root_ptr->layer_tree_impl()->property_trees()->needs_rebuild = true;
-  ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root_ptr);
-  EXPECT_EQ(gfx::Rect(10, 10), grandchild_ptr->visible_layer_rect());
+  PendingImplOf(grandchild)->set_visible_layer_rect(gfx::Rect());
+  Commit();
+  EXPECT_EQ(gfx::Rect(10, 10), PendingImplOf(grandchild)->visible_layer_rect());
 }
 
 // Needs layer tree mode: hide_layer_and_subtree.
 TEST_F(LayerTreeHostCommonTestWithLayerTree, SkippingLayer) {
-  LayerImpl* root = root_layer_for_testing();
-  LayerImpl* child = AddChild<LayerImpl>(root);
+  auto root = Layer::Create();
+  host()->SetRootLayer(root);
+  auto child = Layer::Create();
+  root->AddChild(child);
 
   root->SetBounds(gfx::Size(100, 100));
   child->SetBounds(gfx::Size(10, 10));
-  child->SetDrawsContent(true);
+  child->SetIsDrawable(true);
 
-  ExecuteCalculateDrawProperties(root);
-  EXPECT_EQ(gfx::Rect(10, 10), child->visible_layer_rect());
-  child->set_visible_layer_rect(gfx::Rect());
+  CommitAndActivate();
 
-  child->test_properties()->hide_layer_and_subtree = true;
-  root->layer_tree_impl()->property_trees()->needs_rebuild = true;
-  ExecuteCalculateDrawProperties(root);
-  EXPECT_EQ(gfx::Rect(0, 0), child->visible_layer_rect());
-  child->test_properties()->hide_layer_and_subtree = false;
+  EXPECT_EQ(gfx::Rect(10, 10), ImplOf(child)->visible_layer_rect());
+  ImplOf(child)->set_visible_layer_rect(gfx::Rect());
+
+  child->SetHideLayerAndSubtree(true);
+  CommitAndActivate();
+  EXPECT_EQ(gfx::Rect(0, 0), ImplOf(child)->visible_layer_rect());
+  child->SetHideLayerAndSubtree(false);
 
   child->SetBounds(gfx::Size());
-  root->layer_tree_impl()->property_trees()->needs_rebuild = true;
-  ExecuteCalculateDrawProperties(root);
-  EXPECT_EQ(gfx::Rect(0, 0), child->visible_layer_rect());
+  CommitAndActivate();
+  EXPECT_EQ(gfx::Rect(0, 0), ImplOf(child)->visible_layer_rect());
   child->SetBounds(gfx::Size(10, 10));
 
   gfx::Transform rotate;
-  child->test_properties()->double_sided = false;
+  child->SetDoubleSided(false);
   rotate.RotateAboutXAxis(180.f);
-  child->test_properties()->transform = rotate;
-  root->layer_tree_impl()->property_trees()->needs_rebuild = true;
-  ExecuteCalculateDrawProperties(root);
-  EXPECT_EQ(gfx::Rect(0, 0), child->visible_layer_rect());
-  child->test_properties()->double_sided = true;
-  child->test_properties()->transform = gfx::Transform();
+  child->SetTransform(rotate);
+  CommitAndActivate();
+  EXPECT_EQ(gfx::Rect(0, 0), ImplOf(child)->visible_layer_rect());
+  child->SetDoubleSided(true);
+  child->SetTransform(gfx::Transform());
 
-  child->test_properties()->opacity = 0.f;
-  root->layer_tree_impl()->property_trees()->needs_rebuild = true;
-  ExecuteCalculateDrawProperties(root);
-  EXPECT_EQ(gfx::Rect(0, 0), child->visible_layer_rect());
+  child->SetOpacity(0.f);
+  CommitAndActivate();
+  EXPECT_EQ(gfx::Rect(0, 0), ImplOf(child)->visible_layer_rect());
 }
 
 // Needs layer tree mode: testing PropertyTreeBuilder.
@@ -8194,23 +8091,28 @@
 
   host()->SetRootLayer(root);
 
-  ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root.get());
+  ExecuteCalculateDrawProperties(root.get());
   EXPECT_NE(-1, child->transform_tree_index());
 
   child->RemoveFromParent();
 
-  ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root.get());
+  ExecuteCalculateDrawProperties(root.get());
   EXPECT_EQ(-1, child->transform_tree_index());
 }
 
 // Needs layer tree mode: testing PropertyTreeBuilder.
 TEST_F(LayerTreeHostCommonTestWithLayerTree, RenderSurfaceClipsSubtree) {
   // Ensure that a Clip Node is added when a render surface applies clip.
-  LayerImpl* root = root_layer_for_testing();
-  LayerImpl* significant_transform = AddChildToRoot<LayerImpl>();
-  LayerImpl* layer_clips_subtree = AddChild<LayerImpl>(significant_transform);
-  LayerImpl* render_surface = AddChild<LayerImpl>(layer_clips_subtree);
-  LayerImpl* test_layer = AddChild<LayerImpl>(render_surface);
+  auto root = Layer::Create();
+  host()->SetRootLayer(root);
+  auto significant_transform = Layer::Create();
+  root->AddChild(significant_transform);
+  auto layer_clips_subtree = Layer::Create();
+  significant_transform->AddChild(layer_clips_subtree);
+  auto render_surface = Layer::Create();
+  layer_clips_subtree->AddChild(render_surface);
+  auto test_layer = Layer::Create();
+  render_surface->AddChild(test_layer);
 
   // This transform should be a significant one so that a transform node is
   // formed for it.
@@ -8223,33 +8125,28 @@
   transform2.Translate3d(10, 10, 10);
 
   root->SetBounds(gfx::Size(30, 30));
-  significant_transform->test_properties()->transform = transform1;
+  significant_transform->SetTransform(transform1);
   significant_transform->SetBounds(gfx::Size(30, 30));
   layer_clips_subtree->SetBounds(gfx::Size(30, 30));
   layer_clips_subtree->SetMasksToBounds(true);
-  layer_clips_subtree->test_properties()->force_render_surface = true;
-  render_surface->test_properties()->transform = transform2;
+  layer_clips_subtree->SetForceRenderSurfaceForTesting(true);
+  render_surface->SetTransform(transform2);
   render_surface->SetBounds(gfx::Size(30, 30));
-  render_surface->test_properties()->force_render_surface = true;
+  render_surface->SetForceRenderSurfaceForTesting(true);
   test_layer->SetBounds(gfx::Size(30, 30));
-  test_layer->SetDrawsContent(true);
+  test_layer->SetIsDrawable(true);
 
-  float device_scale_factor = 1.f;
-  float page_scale_factor = 1.f;
-  LayerImpl* page_scale_layer = nullptr;
-  LayerImpl* inner_viewport_scroll_layer = nullptr;
-  LayerImpl* outer_viewport_scroll_layer = nullptr;
-  ExecuteCalculateDrawProperties(root, device_scale_factor, page_scale_factor,
-                                 page_scale_layer, inner_viewport_scroll_layer,
-                                 outer_viewport_scroll_layer);
+  CommitAndActivate();
 
-  EXPECT_TRUE(GetRenderSurface(root));
-  EXPECT_EQ(GetRenderSurface(significant_transform), GetRenderSurface(root));
-  EXPECT_TRUE(GetRenderSurface(layer_clips_subtree));
-  EXPECT_NE(GetRenderSurface(render_surface), GetRenderSurface(root));
-  EXPECT_EQ(GetRenderSurface(test_layer), GetRenderSurface(render_surface));
+  EXPECT_TRUE(GetRenderSurfaceImpl(root));
+  EXPECT_EQ(GetRenderSurfaceImpl(significant_transform),
+            GetRenderSurfaceImpl(root));
+  EXPECT_TRUE(GetRenderSurfaceImpl(layer_clips_subtree));
+  EXPECT_NE(GetRenderSurfaceImpl(render_surface), GetRenderSurfaceImpl(root));
+  EXPECT_EQ(GetRenderSurfaceImpl(test_layer),
+            GetRenderSurfaceImpl(render_surface));
 
-  EXPECT_EQ(gfx::Rect(30, 20), test_layer->visible_layer_rect());
+  EXPECT_EQ(gfx::Rect(30, 20), ImplOf(test_layer)->visible_layer_rect());
 }
 
 TEST_F(LayerTreeHostCommonTest, TransformOfParentClipNodeAncestorOfTarget) {
@@ -8697,26 +8594,31 @@
 // Needs layer tree mode: hide_layer_and_subtree.
 TEST_F(LayerTreeHostCommonTestWithLayerTree, SubtreeIsHiddenTest) {
   // Tests that subtree is hidden is updated.
-  LayerImpl* root = root_layer_for_testing();
-  LayerImpl* hidden = AddChild<LayerImpl>(root);
-  LayerImpl* test = AddChild<LayerImpl>(hidden);
+  auto root = Layer::Create();
+  host()->SetRootLayer(root);
+  auto hidden = Layer::Create();
+  root->AddChild(hidden);
+  auto test = Layer::Create();
+  hidden->AddChild(test);
 
   root->SetBounds(gfx::Size(30, 30));
   hidden->SetBounds(gfx::Size(30, 30));
-  hidden->test_properties()->force_render_surface = true;
-  hidden->test_properties()->hide_layer_and_subtree = true;
+  hidden->SetForceRenderSurfaceForTesting(true);
+  hidden->SetHideLayerAndSubtree(true);
   test->SetBounds(gfx::Size(30, 30));
-  test->test_properties()->force_render_surface = true;
+  test->SetForceRenderSurfaceForTesting(true);
 
-  ExecuteCalculateDrawProperties(root);
-  EXPECT_EQ(0.f,
-            GetRenderSurface(test)->OwningEffectNode()->screen_space_opacity);
+  CommitAndActivate();
 
-  hidden->test_properties()->hide_layer_and_subtree = false;
-  root->layer_tree_impl()->property_trees()->needs_rebuild = true;
-  ExecuteCalculateDrawProperties(root);
-  EXPECT_EQ(1.f,
-            GetRenderSurface(test)->OwningEffectNode()->screen_space_opacity);
+  EXPECT_EQ(
+      0.f,
+      GetRenderSurfaceImpl(test)->OwningEffectNode()->screen_space_opacity);
+
+  hidden->SetHideLayerAndSubtree(false);
+  CommitAndActivate();
+  EXPECT_EQ(
+      1.f,
+      GetRenderSurfaceImpl(test)->OwningEffectNode()->screen_space_opacity);
 }
 
 TEST_F(LayerTreeHostCommonTest, TwoUnclippedRenderSurfaces) {
@@ -8758,45 +8660,49 @@
 // Needs layer tree mode: mask layer.
 TEST_F(LayerTreeHostCommonTestWithLayerTree, MaskLayerDrawProperties) {
   // Tests that a mask layer's draw properties are computed correctly.
-  LayerImpl* root = root_layer_for_testing();
-  LayerImpl* child = AddChild<LayerImpl>(root);
-  child->test_properties()->SetMaskLayer(
-      LayerImpl::Create(root->layer_tree_impl(), 100));
-  LayerImpl* mask = child->test_properties()->mask_layer;
+  auto root = Layer::Create();
+  host()->SetRootLayer(root);
+  auto child = Layer::Create();
+  root->AddChild(child);
+  FakeContentLayerClient client;
+  auto mask = PictureLayer::Create(&client);
+  child->SetMaskLayer(mask);
 
   gfx::Transform transform;
   transform.Translate(10, 10);
 
   root->SetBounds(gfx::Size(40, 40));
-  root->SetDrawsContent(true);
-  child->test_properties()->transform = transform;
+  root->SetIsDrawable(true);
+  child->SetTransform(transform);
   child->SetBounds(gfx::Size(30, 30));
-  child->SetDrawsContent(false);
-  mask->SetBounds(gfx::Size(20, 20));
-  ExecuteCalculateDrawProperties(root);
+  child->SetIsDrawable(false);
+  mask->SetBounds(gfx::Size(30, 30));
+
+  CommitAndActivate();
 
   // The render surface created for the mask has no contributing content, so the
   // mask doesn't contribute to a drawn render surface. This means it has an
   // empty visible rect, but its screen space transform can still be computed
   // correctly on-demand.
-  EXPECT_FALSE(mask->contributes_to_drawn_render_surface());
-  EXPECT_EQ(gfx::Rect(), mask->visible_layer_rect());
-  EXPECT_TRANSFORMATION_MATRIX_EQ(transform, mask->ScreenSpaceTransform());
+  EXPECT_FALSE(ImplOf(mask)->contributes_to_drawn_render_surface());
+  EXPECT_EQ(gfx::Rect(), ImplOf(mask)->visible_layer_rect());
+  EXPECT_TRANSFORMATION_MATRIX_EQ(transform,
+                                  ImplOf(mask)->ScreenSpaceTransform());
 
   // Make the child's render surface have contributing content.
-  child->SetDrawsContent(true);
-  root->layer_tree_impl()->property_trees()->needs_rebuild = true;
-  ExecuteCalculateDrawProperties(root);
-  EXPECT_TRUE(mask->contributes_to_drawn_render_surface());
-  EXPECT_EQ(gfx::Rect(20, 20), mask->visible_layer_rect());
-  EXPECT_TRANSFORMATION_MATRIX_EQ(transform, mask->ScreenSpaceTransform());
+  child->SetIsDrawable(true);
+  CommitAndActivate();
+  EXPECT_TRUE(ImplOf(mask)->contributes_to_drawn_render_surface());
+  EXPECT_EQ(gfx::Rect(30, 30), ImplOf(mask)->visible_layer_rect());
+  EXPECT_TRANSFORMATION_MATRIX_EQ(transform,
+                                  ImplOf(mask)->ScreenSpaceTransform());
 
   transform.Translate(10, 10);
-  child->test_properties()->transform = transform;
-  root->layer_tree_impl()->property_trees()->needs_rebuild = true;
-  ExecuteCalculateDrawProperties(root);
-  EXPECT_TRANSFORMATION_MATRIX_EQ(transform, mask->ScreenSpaceTransform());
-  EXPECT_EQ(gfx::Rect(20, 20), mask->visible_layer_rect());
+  child->SetTransform(transform);
+  CommitAndActivate();
+  EXPECT_TRANSFORMATION_MATRIX_EQ(transform,
+                                  ImplOf(mask)->ScreenSpaceTransform());
+  EXPECT_EQ(gfx::Rect(20, 20), ImplOf(mask)->visible_layer_rect());
 }
 
 TEST_F(LayerTreeHostCommonTest,
@@ -8945,7 +8851,7 @@
 
   root->SetBounds(gfx::Size(100, 100));
   child->SetBounds(gfx::Size(20, 20));
-  ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root.get());
+  ExecuteCalculateDrawProperties(root.get());
 
   // Changing the opacity from 1 to non-1 value should trigger rebuild of
   // property trees as a new effect node will be created.
@@ -8953,7 +8859,7 @@
   PropertyTrees* property_trees = host()->property_trees();
   EXPECT_TRUE(property_trees->needs_rebuild);
 
-  ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root.get());
+  ExecuteCalculateDrawProperties(root.get());
   EXPECT_NE(child->effect_tree_index(), root->effect_tree_index());
 
   // child already has an effect node. Changing its opacity shouldn't trigger
@@ -8962,7 +8868,7 @@
   property_trees = host()->property_trees();
   EXPECT_FALSE(property_trees->needs_rebuild);
 
-  ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root.get());
+  ExecuteCalculateDrawProperties(root.get());
   EXPECT_NE(child->effect_tree_index(), root->effect_tree_index());
 
   // Changing the opacity from non-1 value to 1 should trigger a rebuild of
@@ -8971,7 +8877,7 @@
   property_trees = host()->property_trees();
   EXPECT_TRUE(property_trees->needs_rebuild);
 
-  ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root.get());
+  ExecuteCalculateDrawProperties(root.get());
   EXPECT_EQ(child->effect_tree_index(), root->effect_tree_index());
 }
 
@@ -9006,7 +8912,7 @@
   AddKeyframeModelToElementWithExistingKeyframeEffect(
       animated->element_id(), timeline(), std::move(keyframe_model));
 
-  ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root.get());
+  ExecuteCalculateDrawProperties(root.get());
 
   EffectNode* node = GetEffectNode(animated.get());
   EXPECT_FALSE(node->is_currently_animating_opacity);
@@ -9064,7 +8970,7 @@
   AddKeyframeModelToElementWithExistingKeyframeEffect(
       animated->element_id(), timeline(), std::move(keyframe_model));
 
-  ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root.get());
+  ExecuteCalculateDrawProperties(root.get());
 
   TransformNode* node = GetTransformNode(animated.get());
   EXPECT_FALSE(node->is_currently_animating);
@@ -9085,99 +8991,112 @@
 
 // Needs layer tree mode: copy request.
 TEST_F(LayerTreeHostCommonTestWithLayerTree, CopyRequestScalingTest) {
-  LayerImpl* root = root_layer_for_testing();
-  LayerImpl* scale_layer = AddChild<LayerImpl>(root);
-  LayerImpl* copy_layer = AddChild<LayerImpl>(scale_layer);
-  LayerImpl* clip_layer = AddChild<LayerImpl>(copy_layer);
-  LayerImpl* test_layer = AddChild<LayerImpl>(clip_layer);
+  auto root = Layer::Create();
+  host()->SetRootLayer(root);
+  auto scale_layer = Layer::Create();
+  root->AddChild(scale_layer);
+  auto copy_layer = Layer::Create();
+  scale_layer->AddChild(copy_layer);
+  auto clip_layer = Layer::Create();
+  copy_layer->AddChild(clip_layer);
+  auto test_layer = Layer::Create();
+  clip_layer->AddChild(test_layer);
 
   root->SetBounds(gfx::Size(150, 150));
 
   scale_layer->SetBounds(gfx::Size(30, 30));
   gfx::Transform transform;
   transform.Scale(5.f, 5.f);
-  scale_layer->test_properties()->transform = transform;
+  scale_layer->SetTransform(transform);
 
   // Need to persist the render surface after copy request is cleared.
-  copy_layer->test_properties()->force_render_surface = true;
-  copy_layer->test_properties()->copy_requests.push_back(
+  copy_layer->SetForceRenderSurfaceForTesting(true);
+  copy_layer->RequestCopyOfOutput(
       viz::CopyOutputRequest::CreateStubForTesting());
 
-  clip_layer->SetDrawsContent(true);
+  clip_layer->SetIsDrawable(true);
   clip_layer->SetMasksToBounds(true);
   clip_layer->SetBounds(gfx::Size(10, 10));
 
-  test_layer->SetDrawsContent(true);
+  test_layer->SetIsDrawable(true);
   test_layer->SetMasksToBounds(true);
   test_layer->SetBounds(gfx::Size(20, 20));
 
-  ExecuteCalculateDrawProperties(root);
+  CommitAndActivate();
 
   // Check surface with copy request draw properties.
-  EXPECT_EQ(gfx::Rect(50, 50), GetRenderSurface(copy_layer)->content_rect());
-  EXPECT_EQ(gfx::Transform(), GetRenderSurface(copy_layer)->draw_transform());
+  EXPECT_EQ(gfx::Rect(50, 50),
+            GetRenderSurfaceImpl(copy_layer)->content_rect());
+  EXPECT_EQ(gfx::Transform(),
+            GetRenderSurfaceImpl(copy_layer)->draw_transform());
   EXPECT_EQ(gfx::RectF(50.0f, 50.0f),
-            GetRenderSurface(copy_layer)->DrawableContentRect());
+            GetRenderSurfaceImpl(copy_layer)->DrawableContentRect());
 
   // Check test layer draw properties.
-  EXPECT_EQ(gfx::Rect(10, 10), test_layer->visible_layer_rect());
-  EXPECT_EQ(transform, test_layer->DrawTransform());
-  EXPECT_EQ(gfx::Rect(50, 50), test_layer->clip_rect());
-  EXPECT_EQ(gfx::Rect(50, 50), test_layer->drawable_content_rect());
+  EXPECT_EQ(gfx::Rect(10, 10), ImplOf(test_layer)->visible_layer_rect());
+  EXPECT_EQ(transform, ImplOf(test_layer)->DrawTransform());
+  EXPECT_EQ(gfx::Rect(50, 50), ImplOf(test_layer)->clip_rect());
+  EXPECT_EQ(gfx::Rect(50, 50), ImplOf(test_layer)->drawable_content_rect());
 
   // Clear the copy request and call UpdateSurfaceContentsScale.
-  host_impl()->active_tree()->property_trees()->effect_tree.ClearCopyRequests();
-  ExecuteCalculateDrawProperties(root);
+  GetPropertyTrees(root.get())->effect_tree.ClearCopyRequests();
+  CommitAndActivate();
 }
 
 // Needs layer tree mode: hide_layer_and_subtree, etc.
 TEST_F(LayerTreeHostCommonTestWithLayerTree,
        SubtreeHiddenWithCacheRenderSurface) {
-  LayerImpl* root = root_layer_for_testing();
+  auto root = Layer::Create();
+  host()->SetRootLayer(root);
   root->SetBounds(gfx::Size(50, 50));
-  root->SetDrawsContent(true);
+  root->SetIsDrawable(true);
 
-  auto* cache_grand_parent_sibling_before = AddChildToRoot<LayerImpl>();
+  auto cache_grand_parent_sibling_before = Layer::Create();
+  root->AddChild(cache_grand_parent_sibling_before);
   cache_grand_parent_sibling_before->SetBounds(gfx::Size(40, 40));
-  cache_grand_parent_sibling_before->SetDrawsContent(true);
+  cache_grand_parent_sibling_before->SetIsDrawable(true);
 
-  auto* cache_grand_parent = AddChildToRoot<LayerImpl>();
+  auto cache_grand_parent = Layer::Create();
+  root->AddChild(cache_grand_parent);
   cache_grand_parent->SetBounds(gfx::Size(40, 40));
-  cache_grand_parent->SetDrawsContent(true);
+  cache_grand_parent->SetIsDrawable(true);
 
-  auto* cache_parent = AddChild<LayerImpl>(cache_grand_parent);
+  auto cache_parent = Layer::Create();
+  cache_grand_parent->AddChild(cache_parent);
   cache_parent->SetBounds(gfx::Size(30, 30));
-  cache_parent->SetDrawsContent(true);
-  cache_parent->test_properties()->force_render_surface = true;
+  cache_parent->SetIsDrawable(true);
+  cache_parent->SetForceRenderSurfaceForTesting(true);
 
-  auto* cache_render_surface = AddChild<LayerImpl>(cache_parent);
+  auto cache_render_surface = Layer::Create();
+  cache_parent->AddChild(cache_render_surface);
   cache_render_surface->SetBounds(gfx::Size(20, 20));
-  cache_render_surface->SetDrawsContent(true);
-  cache_render_surface->test_properties()->cache_render_surface = true;
+  cache_render_surface->SetIsDrawable(true);
+  cache_render_surface->SetCacheRenderSurface(true);
 
-  auto* cache_child = AddChild<LayerImpl>(cache_render_surface);
+  auto cache_child = Layer::Create();
+  cache_render_surface->AddChild(cache_child);
   cache_child->SetBounds(gfx::Size(20, 20));
-  cache_child->SetDrawsContent(true);
+  cache_child->SetIsDrawable(true);
 
-  auto* cache_grand_child = AddChild<LayerImpl>(cache_child);
+  auto cache_grand_child = Layer::Create();
+  cache_child->AddChild(cache_grand_child);
   cache_grand_child->SetBounds(gfx::Size(20, 20));
-  cache_grand_child->SetDrawsContent(true);
+  cache_grand_child->SetIsDrawable(true);
 
-  auto* cache_grand_parent_sibling_after = AddChildToRoot<LayerImpl>();
+  auto cache_grand_parent_sibling_after = Layer::Create();
+  root->AddChild(cache_grand_parent_sibling_after);
   cache_grand_parent_sibling_after->SetBounds(gfx::Size(40, 40));
-  cache_grand_parent_sibling_after->SetDrawsContent(true);
+  cache_grand_parent_sibling_after->SetIsDrawable(true);
 
   // Hide the cache_grand_parent and its subtree. But cache a render surface in
   // that hidden subtree on cache_layer. Also hide the cache grand child and its
   // subtree.
-  cache_grand_parent->test_properties()->hide_layer_and_subtree = true;
-  cache_grand_parent_sibling_before->test_properties()->hide_layer_and_subtree =
-      true;
-  cache_grand_parent_sibling_after->test_properties()->hide_layer_and_subtree =
-      true;
-  cache_grand_child->test_properties()->hide_layer_and_subtree = true;
+  cache_grand_parent->SetHideLayerAndSubtree(true);
+  cache_grand_parent_sibling_before->SetHideLayerAndSubtree(true);
+  cache_grand_parent_sibling_after->SetHideLayerAndSubtree(true);
+  cache_grand_child->SetHideLayerAndSubtree(true);
 
-  ExecuteCalculateDrawProperties(root);
+  CommitAndActivate();
 
   // We should have four render surfaces, one for the root, one for the grand
   // parent since it has opacity and two drawing descendants, one for the parent
@@ -9193,173 +9112,190 @@
             render_surface_list_impl()->at(3)->id());
 
   // The root render surface should have 2 contributing layers.
-  EXPECT_EQ(2, GetRenderSurface(root)->num_contributors());
-  EXPECT_TRUE(root->contributes_to_drawn_render_surface());
-  EXPECT_FALSE(cache_grand_parent->contributes_to_drawn_render_surface());
+  EXPECT_EQ(2, GetRenderSurfaceImpl(root)->num_contributors());
+  EXPECT_TRUE(ImplOf(root)->contributes_to_drawn_render_surface());
   EXPECT_FALSE(
-      cache_grand_parent_sibling_before->contributes_to_drawn_render_surface());
-  EXPECT_FALSE(
-      cache_grand_parent_sibling_after->contributes_to_drawn_render_surface());
+      ImplOf(cache_grand_parent)->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(cache_grand_parent_sibling_before)
+                   ->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(ImplOf(cache_grand_parent_sibling_after)
+                   ->contributes_to_drawn_render_surface());
 
   // Nothing actually draws into the cache parent, so only the cache will
   // appear in its list, since it needs to be drawn for the cache render
   // surface.
-  ASSERT_EQ(1, GetRenderSurface(cache_parent)->num_contributors());
-  EXPECT_FALSE(cache_parent->contributes_to_drawn_render_surface());
+  ASSERT_EQ(1, GetRenderSurfaceImpl(cache_parent)->num_contributors());
+  EXPECT_FALSE(ImplOf(cache_parent)->contributes_to_drawn_render_surface());
 
   // The cache layer's render surface should have 2 contributing layers.
-  ASSERT_EQ(2, GetRenderSurface(cache_render_surface)->num_contributors());
-  EXPECT_TRUE(cache_render_surface->contributes_to_drawn_render_surface());
-  EXPECT_TRUE(cache_child->contributes_to_drawn_render_surface());
-  EXPECT_FALSE(cache_grand_child->contributes_to_drawn_render_surface());
+  ASSERT_EQ(2, GetRenderSurfaceImpl(cache_render_surface)->num_contributors());
+  EXPECT_TRUE(
+      ImplOf(cache_render_surface)->contributes_to_drawn_render_surface());
+  EXPECT_TRUE(ImplOf(cache_child)->contributes_to_drawn_render_surface());
+  EXPECT_FALSE(
+      ImplOf(cache_grand_child)->contributes_to_drawn_render_surface());
 
   // cache_grand_parent, cache_parent shouldn't be drawn because they are
   // hidden, but the cache and cache_child should be drawn for the cache
   // render surface. cache grand child should not be drawn as its hidden even in
   // the cache render surface.
-  EXPECT_FALSE(GetEffectNode(cache_grand_parent)->is_drawn);
-  EXPECT_FALSE(GetEffectNode(cache_parent)->is_drawn);
-  EXPECT_TRUE(GetEffectNode(cache_render_surface)->is_drawn);
-  EXPECT_TRUE(GetEffectNode(cache_child)->is_drawn);
-  EXPECT_FALSE(GetEffectNode(cache_grand_child)->is_drawn);
+  EXPECT_FALSE(GetEffectNode(ImplOf(cache_grand_parent))->is_drawn);
+  EXPECT_FALSE(GetEffectNode(ImplOf(cache_parent))->is_drawn);
+  EXPECT_TRUE(GetEffectNode(ImplOf(cache_render_surface))->is_drawn);
+  EXPECT_TRUE(GetEffectNode(ImplOf(cache_child))->is_drawn);
+  EXPECT_FALSE(GetEffectNode(ImplOf(cache_grand_child))->is_drawn);
 
   // Though cache is drawn, it shouldn't contribute to drawn surface as
   // its actually hidden.
-  EXPECT_FALSE(
-      GetRenderSurface(cache_render_surface)->contributes_to_drawn_surface());
+  EXPECT_FALSE(GetRenderSurfaceImpl(cache_render_surface)
+                   ->contributes_to_drawn_surface());
 }
 
 // Needs layer tree mode: copy request.
 TEST_F(LayerTreeHostCommonTestWithLayerTree,
        VisibleRectInNonRootCacheRenderSurface) {
-  LayerImpl* root = root_layer_for_testing();
+  auto root = Layer::Create();
+  host()->SetRootLayer(root);
   root->SetBounds(gfx::Size(50, 50));
-  root->SetDrawsContent(true);
+  root->SetIsDrawable(true);
   root->SetMasksToBounds(true);
 
-  LayerImpl* cache_render_surface_layer = AddChild<LayerImpl>(root);
+  auto cache_render_surface_layer = Layer::Create();
+  root->AddChild(cache_render_surface_layer);
   cache_render_surface_layer->SetBounds(gfx::Size(120, 120));
-  cache_render_surface_layer->SetDrawsContent(true);
-  cache_render_surface_layer->test_properties()->cache_render_surface = true;
+  cache_render_surface_layer->SetIsDrawable(true);
+  cache_render_surface_layer->SetCacheRenderSurface(true);
 
-  LayerImpl* copy_layer = AddChild<LayerImpl>(cache_render_surface_layer);
+  auto copy_layer = Layer::Create();
+  cache_render_surface_layer->AddChild(copy_layer);
   copy_layer->SetBounds(gfx::Size(100, 100));
-  copy_layer->SetDrawsContent(true);
-  copy_layer->test_properties()->force_render_surface = true;
+  copy_layer->SetIsDrawable(true);
+  copy_layer->SetForceRenderSurfaceForTesting(true);
 
-  LayerImpl* copy_child = AddChild<LayerImpl>(copy_layer);
-  copy_child->test_properties()->position = gfx::PointF(40.f, 40.f);
+  auto copy_child = Layer::Create();
+  copy_layer->AddChild(copy_child);
+  copy_child->SetPosition(gfx::PointF(40.f, 40.f));
   copy_child->SetBounds(gfx::Size(20, 20));
-  copy_child->SetDrawsContent(true);
+  copy_child->SetIsDrawable(true);
 
-  LayerImpl* copy_clip = AddChild<LayerImpl>(copy_layer);
+  auto copy_clip = Layer::Create();
+  copy_layer->AddChild(copy_clip);
   copy_clip->SetBounds(gfx::Size(55, 55));
   copy_clip->SetMasksToBounds(true);
 
-  LayerImpl* copy_clipped_child = AddChild<LayerImpl>(copy_clip);
-  copy_clipped_child->test_properties()->position = gfx::PointF(40.f, 40.f);
+  auto copy_clipped_child = Layer::Create();
+  copy_clip->AddChild(copy_clipped_child);
+  copy_clipped_child->SetPosition(gfx::PointF(40.f, 40.f));
   copy_clipped_child->SetBounds(gfx::Size(20, 20));
-  copy_clipped_child->SetDrawsContent(true);
+  copy_clipped_child->SetIsDrawable(true);
 
-  LayerImpl* cache_surface = AddChild<LayerImpl>(copy_clip);
-  cache_surface->test_properties()->position = gfx::PointF(45.f, 45.f);
+  auto cache_surface = Layer::Create();
+  copy_clip->AddChild(cache_surface);
+  cache_surface->SetPosition(gfx::PointF(45.f, 45.f));
   cache_surface->SetBounds(gfx::Size(20, 20));
-  cache_surface->SetDrawsContent(true);
+  cache_surface->SetIsDrawable(true);
 
-  ExecuteCalculateDrawProperties(root);
+  CommitAndActivate();
+
   EXPECT_EQ(gfx::Rect(120, 120),
-            cache_render_surface_layer->visible_layer_rect());
-  EXPECT_EQ(gfx::Rect(100, 100), copy_layer->visible_layer_rect());
-  EXPECT_EQ(gfx::Rect(20, 20), copy_child->visible_layer_rect());
-  EXPECT_EQ(gfx::Rect(15, 15), copy_clipped_child->visible_layer_rect());
-  EXPECT_EQ(gfx::Rect(10, 10), cache_surface->visible_layer_rect());
+            ImplOf(cache_render_surface_layer)->visible_layer_rect());
+  EXPECT_EQ(gfx::Rect(100, 100), ImplOf(copy_layer)->visible_layer_rect());
+  EXPECT_EQ(gfx::Rect(20, 20), ImplOf(copy_child)->visible_layer_rect());
+  EXPECT_EQ(gfx::Rect(15, 15),
+            ImplOf(copy_clipped_child)->visible_layer_rect());
+  EXPECT_EQ(gfx::Rect(10, 10), ImplOf(cache_surface)->visible_layer_rect());
 
   // Case 2: When the non root cache render surface layer is clipped.
   cache_render_surface_layer->SetBounds(gfx::Size(50, 50));
   cache_render_surface_layer->SetMasksToBounds(true);
-  root->layer_tree_impl()->property_trees()->needs_rebuild = true;
-  ExecuteCalculateDrawProperties(root);
+  CommitAndActivate();
   EXPECT_EQ(gfx::Rect(50, 50),
-            cache_render_surface_layer->visible_layer_rect());
-  EXPECT_EQ(gfx::Rect(50, 50), copy_layer->visible_layer_rect());
-  EXPECT_EQ(gfx::Rect(10, 10), copy_child->visible_layer_rect());
-  EXPECT_EQ(gfx::Rect(10, 10), copy_clipped_child->visible_layer_rect());
-  EXPECT_EQ(gfx::Rect(5, 5), cache_surface->visible_layer_rect());
+            ImplOf(cache_render_surface_layer)->visible_layer_rect());
+  EXPECT_EQ(gfx::Rect(50, 50), ImplOf(copy_layer)->visible_layer_rect());
+  EXPECT_EQ(gfx::Rect(10, 10), ImplOf(copy_child)->visible_layer_rect());
+  EXPECT_EQ(gfx::Rect(10, 10),
+            ImplOf(copy_clipped_child)->visible_layer_rect());
+  EXPECT_EQ(gfx::Rect(5, 5), ImplOf(cache_surface)->visible_layer_rect());
 
   // Case 3: When there is device scale factor.
   float device_scale_factor = 2.f;
-  ExecuteCalculateDrawProperties(root, device_scale_factor);
+  CommitAndActivate(device_scale_factor);
   EXPECT_EQ(gfx::Rect(50, 50),
-            cache_render_surface_layer->visible_layer_rect());
-  EXPECT_EQ(gfx::Rect(50, 50), copy_layer->visible_layer_rect());
-  EXPECT_EQ(gfx::Rect(10, 10), copy_child->visible_layer_rect());
-  EXPECT_EQ(gfx::Rect(10, 10), copy_clipped_child->visible_layer_rect());
-  EXPECT_EQ(gfx::Rect(5, 5), cache_surface->visible_layer_rect());
+            ImplOf(cache_render_surface_layer)->visible_layer_rect());
+  EXPECT_EQ(gfx::Rect(50, 50), ImplOf(copy_layer)->visible_layer_rect());
+  EXPECT_EQ(gfx::Rect(10, 10), ImplOf(copy_child)->visible_layer_rect());
+  EXPECT_EQ(gfx::Rect(10, 10),
+            ImplOf(copy_clipped_child)->visible_layer_rect());
+  EXPECT_EQ(gfx::Rect(5, 5), ImplOf(cache_surface)->visible_layer_rect());
 
   // Case 4: When the non root cache render surface layer is clipped and there
   // is a copy request layer beneath it.
-  copy_layer->test_properties()->copy_requests.push_back(
+  copy_layer->RequestCopyOfOutput(
       viz::CopyOutputRequest::CreateStubForTesting());
-  root->layer_tree_impl()->property_trees()->needs_rebuild = true;
-  DCHECK(!copy_layer->test_properties()->copy_requests.empty());
-  ExecuteCalculateDrawProperties(root);
-  DCHECK(copy_layer->test_properties()->copy_requests.empty());
+  ASSERT_TRUE(copy_layer->HasCopyRequest());
+  CommitAndActivate();
+  ASSERT_FALSE(copy_layer->HasCopyRequest());
   EXPECT_EQ(gfx::Rect(50, 50),
-            cache_render_surface_layer->visible_layer_rect());
-  EXPECT_EQ(gfx::Rect(100, 100), copy_layer->visible_layer_rect());
-  EXPECT_EQ(gfx::Rect(20, 20), copy_child->visible_layer_rect());
-  EXPECT_EQ(gfx::Rect(15, 15), copy_clipped_child->visible_layer_rect());
-  EXPECT_EQ(gfx::Rect(10, 10), cache_surface->visible_layer_rect());
+            ImplOf(cache_render_surface_layer)->visible_layer_rect());
+  EXPECT_EQ(gfx::Rect(100, 100), ImplOf(copy_layer)->visible_layer_rect());
+  EXPECT_EQ(gfx::Rect(20, 20), ImplOf(copy_child)->visible_layer_rect());
+  EXPECT_EQ(gfx::Rect(15, 15),
+            ImplOf(copy_clipped_child)->visible_layer_rect());
+  EXPECT_EQ(gfx::Rect(10, 10), ImplOf(cache_surface)->visible_layer_rect());
 
   // Case 5: When there is another cache render surface layer under the copy
   // request layer.
-  cache_surface->test_properties()->cache_render_surface = true;
-  copy_layer->test_properties()->copy_requests.push_back(
+  cache_surface->SetCacheRenderSurface(true);
+  copy_layer->RequestCopyOfOutput(
       viz::CopyOutputRequest::CreateStubForTesting());
-  root->layer_tree_impl()->property_trees()->needs_rebuild = true;
-  DCHECK(!copy_layer->test_properties()->copy_requests.empty());
-  ExecuteCalculateDrawProperties(root);
-  DCHECK(copy_layer->test_properties()->copy_requests.empty());
+  ASSERT_TRUE(copy_layer->HasCopyRequest());
+  CommitAndActivate();
+  ASSERT_FALSE(copy_layer->HasCopyRequest());
   EXPECT_EQ(gfx::Rect(50, 50),
-            cache_render_surface_layer->visible_layer_rect());
-  EXPECT_EQ(gfx::Rect(100, 100), copy_layer->visible_layer_rect());
-  EXPECT_EQ(gfx::Rect(20, 20), copy_child->visible_layer_rect());
-  EXPECT_EQ(gfx::Rect(15, 15), copy_clipped_child->visible_layer_rect());
-  EXPECT_EQ(gfx::Rect(20, 20), cache_surface->visible_layer_rect());
+            ImplOf(cache_render_surface_layer)->visible_layer_rect());
+  EXPECT_EQ(gfx::Rect(100, 100), ImplOf(copy_layer)->visible_layer_rect());
+  EXPECT_EQ(gfx::Rect(20, 20), ImplOf(copy_child)->visible_layer_rect());
+  EXPECT_EQ(gfx::Rect(15, 15),
+            ImplOf(copy_clipped_child)->visible_layer_rect());
+  EXPECT_EQ(gfx::Rect(20, 20), ImplOf(cache_surface)->visible_layer_rect());
 }
 
 // Needs layer tree mode: testing PropertyTreeBuilder.
 TEST_F(LayerTreeHostCommonTestWithLayerTree,
        RenderSurfaceListForTrilinearFiltering) {
-  LayerImpl* root = root_layer_for_testing();
-  LayerImpl* parent = AddChild<LayerImpl>(root);
-  LayerImpl* child1 = AddChild<LayerImpl>(parent);
-  LayerImpl* child2 = AddChild<LayerImpl>(parent);
+  auto root = Layer::Create();
+  host()->SetRootLayer(root);
+  auto parent = Layer::Create();
+  root->AddChild(parent);
+  auto child1 = Layer::Create();
+  parent->AddChild(child1);
+  auto child2 = Layer::Create();
+  parent->AddChild(child2);
 
   gfx::Transform scale_matrix;
   scale_matrix.Scale(.25f, .25f);
 
   root->SetBounds(gfx::Size(200, 200));
-  parent->test_properties()->transform = scale_matrix;
-  parent->test_properties()->trilinear_filtering = true;
+  parent->SetTransform(scale_matrix);
+  parent->SetTrilinearFiltering(true);
   child1->SetBounds(gfx::Size(50, 50));
-  child1->SetDrawsContent(true);
-  child1->test_properties()->force_render_surface = true;
-  child2->test_properties()->position = gfx::PointF(50, 50);
+  child1->SetIsDrawable(true);
+  child1->SetForceRenderSurfaceForTesting(true);
+  child2->SetPosition(gfx::PointF(50, 50));
   child2->SetBounds(gfx::Size(50, 50));
-  child2->SetDrawsContent(true);
-  child2->test_properties()->force_render_surface = true;
+  child2->SetIsDrawable(true);
+  child2->SetForceRenderSurfaceForTesting(true);
 
-  ExecuteCalculateDrawProperties(root);
+  CommitAndActivate();
 
-  ASSERT_TRUE(GetRenderSurface(parent));
-  EXPECT_EQ(2, GetRenderSurface(parent)->num_contributors());
+  ASSERT_TRUE(GetRenderSurfaceImpl(parent));
+  EXPECT_EQ(2, GetRenderSurfaceImpl(parent)->num_contributors());
   EXPECT_EQ(4U, render_surface_list_impl()->size());
 
   // The rectangle enclosing child1 and child2 (0,0 100x100), scaled by the
   // scale matrix to (0,0 25x25).
   EXPECT_EQ(gfx::RectF(0, 0, 25, 25),
-            GetRenderSurface(parent)->DrawableContentRect());
+            GetRenderSurfaceImpl(parent)->DrawableContentRect());
 }
 
 // In layer tree mode, not using impl-side PropertyTreeBuilder.
diff --git a/chrome/VERSION b/chrome/VERSION
index 823a58d..8b250c179 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=78
 MINOR=0
-BUILD=3899
+BUILD=3901
 PATCH=0
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index c5139a474..5040865e 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -1717,6 +1717,7 @@
   "java/src/org/chromium/chrome/browser/webapps/WebApkActivity8.java",
   "java/src/org/chromium/chrome/browser/webapps/WebApkActivity9.java",
   "java/src/org/chromium/chrome/browser/webapps/WebApkInfo.java",
+  "java/src/org/chromium/chrome/browser/webapps/WebApkIntentDataProvider.java",
   "java/src/org/chromium/chrome/browser/webapps/WebApkHandlerDelegate.java",
   "java/src/org/chromium/chrome/browser/webapps/WebApkInstallService.java",
   "java/src/org/chromium/chrome/browser/webapps/WebApkInstaller.java",
@@ -1749,10 +1750,13 @@
   "java/src/org/chromium/chrome/browser/webapps/WebappDelegateFactory.java",
   "java/src/org/chromium/chrome/browser/webapps/WebappDirectoryManager.java",
   "java/src/org/chromium/chrome/browser/webapps/WebappDisclosureSnackbarController.java",
+  "java/src/org/chromium/chrome/browser/webapps/WebappExtras.java",
   "java/src/org/chromium/chrome/browser/webapps/WebappIcon.java",
   "java/src/org/chromium/chrome/browser/webapps/WebappInfo.java",
+  "java/src/org/chromium/chrome/browser/webapps/WebappIntentDataProvider.java",
   "java/src/org/chromium/chrome/browser/webapps/WebappLauncherActivity.java",
   "java/src/org/chromium/chrome/browser/webapps/WebappManagedActivity.java",
+  "java/src/org/chromium/chrome/browser/webapps/WebApkExtras.java",
   "java/src/org/chromium/chrome/browser/webapps/WebApkOfflineDialog.java",
   "java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java",
   "java/src/org/chromium/chrome/browser/webapps/WebappScopePolicy.java",
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/BrowserServicesIntentDataProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/BrowserServicesIntentDataProvider.java
index 24383af3..7bcf96dd 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/BrowserServicesIntentDataProvider.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/BrowserServicesIntentDataProvider.java
@@ -19,6 +19,8 @@
 import androidx.browser.trusted.sharing.ShareTarget;
 
 import org.chromium.chrome.browser.customtabs.CustomButtonParams;
+import org.chromium.chrome.browser.webapps.WebApkExtras;
+import org.chromium.chrome.browser.webapps.WebappExtras;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -46,19 +48,12 @@
         int OFFLINE_PAGE = 6;
     }
 
-    private final Intent mIntent;
-
-    public BrowserServicesIntentDataProvider(Intent intent) {
-        mIntent = intent;
-    }
-
     /**
      * @return the Intent this instance was created with.
-     *
-     * Not final so that it can be mocked in JUnit tests.
      */
+    @Nullable
     public Intent getIntent() {
-        return mIntent;
+        return null;
     }
 
     /**
@@ -385,6 +380,22 @@
     }
 
     /**
+     * Returns {@link WebappExtras} if the intent targets a webapp, and null otherwise.
+     */
+    @Nullable
+    public WebappExtras getWebappExtras() {
+        return null;
+    }
+
+    /**
+     * Returns {@link WebApkExtras} if the intent targets a WebAPK, and null otherwise.
+     */
+    @Nullable
+    public WebApkExtras getWebApkExtras() {
+        return null;
+    }
+
+    /**
      * @return Whether the bottom bar should be shown.
      */
     public final boolean shouldShowBottomBar() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java
index 75dd25f1..635db4f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java
@@ -187,6 +187,7 @@
             + "To make locally-built Chrome a first-party app, sign with release-test "
             + "signing keys and run on userdebug devices. See use_signing_keys GN arg.";
 
+    private final Intent mIntent;
     private final CustomTabsSessionToken mSession;
     private final boolean mIsTrustedIntent;
     private final Intent mKeepAliveServiceIntent;
@@ -270,8 +271,8 @@
      * CustomTabIntentDataProvider object must be created.
      */
     public CustomTabIntentDataProvider(Intent intent, Context context, int colorScheme) {
-        super(intent);
         if (intent == null) assert false;
+        mIntent = intent;
 
         mSession = CustomTabsSessionToken.getSessionTokenFromIntent(intent);
         mIsTrustedIntent = IntentHandler.notSecureIsIntentChromeOrFirstParty(intent);
@@ -630,6 +631,12 @@
 
     @Override
     @Nullable
+    public Intent getIntent() {
+        return mIntent;
+    }
+
+    @Override
+    @Nullable
     public CustomTabsSessionToken getSession() {
         return mSession;
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
index cb17132..9f0ac38 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
@@ -1155,7 +1155,6 @@
      */
     boolean notifySinglePageLoadMetric(CustomTabsSessionToken session, String metricName,
             long navigationStartTick, long offsetMs) {
-        if (!mClientManager.shouldGetPageLoadMetrics(session)) return false;
         if (!mNativeTickOffsetUsComputed) {
             // Compute offset from time ticks to uptimeMillis.
             mNativeTickOffsetUsComputed = true;
@@ -1186,6 +1185,7 @@
      *     should be a key specifying the metric name and the metric value as the value.
      */
     boolean notifyPageLoadMetrics(CustomTabsSessionToken session, Bundle args) {
+        if (!mClientManager.shouldGetPageLoadMetrics(session)) return false;
         if (safeExtraCallback(session, PAGE_LOAD_METRICS_CALLBACK, args)) {
             logPageLoadMetricsCallback(args);
             return true;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkExtras.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkExtras.java
new file mode 100644
index 0000000..f3a92c1
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkExtras.java
@@ -0,0 +1,113 @@
+// Copyright 2019 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.
+
+package org.chromium.chrome.browser.webapps;
+
+import org.chromium.chrome.browser.webapps.WebApkInfo.ShareData;
+import org.chromium.chrome.browser.webapps.WebApkInfo.ShareTarget;
+
+import java.util.Map;
+
+/**
+ * Stores WebAPK specific information on behalf of {@link BrowserServicesIntentDataProvider}.
+ */
+public class WebApkExtras {
+    /**
+     * The package of the WebAPK.
+     */
+    public final String webApkPackageName;
+
+    /**
+     * Badge icon to use for notifications.
+     */
+    public final WebappIcon badgeIcon;
+
+    /**
+     * Icon to use for the splash screen.
+     */
+    public final WebappIcon splashIcon;
+
+    /**
+     * Version of the code in //chrome/android/webapk/shell_apk.
+     */
+    public final int shellApkVersion;
+
+    /**
+     * URL of the Web Manifest.
+     */
+    public final String manifestUrl;
+
+    /**
+     * URL that the WebAPK should navigate to when launched from the homescreen.
+     */
+    public final String manifestStartUrl;
+
+    /** The source from where the WebAPK is installed. */
+    public final @WebApkDistributor int distributor;
+
+    /**
+     * Map of the WebAPK's icon URLs to Murmur2 hashes of the icon untransformed bytes.
+     */
+    public final Map<String, String> iconUrlToMurmur2HashMap;
+
+    /**
+     * ShareTarget data for {@link shareTargetActivityName}
+     * TODO(pkotwicz): Remove this property in favor of
+     * {@link BrowserServicesIntentDataProvider#shareTarget()}
+     */
+    public final ShareTarget shareTarget;
+
+    /**
+     * Name of activity or activity alias in WebAPK which handles share intents.
+     */
+    public final String shareTargetActivityName;
+
+    /**
+     * Whether the WebAPK
+     * (1) Launches an internal activity to display the splash screen
+     * AND
+     * (2) Has a content provider which provides a screenshot of the splash screen.
+     */
+    public final boolean isSplashProvidedByWebApk;
+
+    /**
+     * Shared information from the share intent.
+     * TODO(pkotwicz): Remove this property in favor of
+     * {@link BrowserServicesIntentDataProvider#shareData()}
+     */
+    public final ShareData shareData;
+
+    /**
+     * WebAPK's version code.
+     */
+    public final int webApkVersionCode;
+
+    public static WebApkExtras createEmpty() {
+        return new WebApkExtras(null /* webApkPackageName */, new WebappIcon(), new WebappIcon(),
+                0 /* shellApkVersion */, null /* manifestUrl */, null /* manifestStartUrl */,
+                WebApkDistributor.OTHER, null /* iconUrlToMurmur2HashMap */, new ShareTarget(),
+                null /* shareTargetActivityName */, false /* isSplashProvidedByWebApk */,
+                null /* shareData */, 0 /* webApkVersionCode */);
+    }
+
+    public WebApkExtras(String webApkPackageName, WebappIcon badgeIcon, WebappIcon splashIcon,
+            int shellApkVersion, String manifestUrl, String manifestStartUrl,
+            @WebApkDistributor int distributor, Map<String, String> iconUrlToMurmur2HashMap,
+            ShareTarget shareTarget, String shareTargetActivityName,
+            boolean isSplashProvidedByWebApk, ShareData shareData, int webApkVersionCode) {
+        this.webApkPackageName = webApkPackageName;
+        this.badgeIcon = badgeIcon;
+        this.splashIcon = splashIcon;
+        this.shellApkVersion = shellApkVersion;
+        this.manifestUrl = manifestUrl;
+        this.manifestStartUrl = manifestStartUrl;
+        this.distributor = distributor;
+        this.iconUrlToMurmur2HashMap = iconUrlToMurmur2HashMap;
+        this.shareTarget = shareTarget;
+        this.shareTargetActivityName = shareTargetActivityName;
+        this.isSplashProvidedByWebApk = isSplashProvidedByWebApk;
+        this.shareData = shareData;
+        this.webApkVersionCode = webApkVersionCode;
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInfo.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInfo.java
index 8603a85..fc42f90 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInfo.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInfo.java
@@ -4,39 +4,18 @@
 
 package org.chromium.chrome.browser.webapps;
 
-import android.content.Context;
 import android.content.Intent;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ProviderInfo;
-import android.content.pm.ResolveInfo;
-import android.content.res.Resources;
 import android.net.Uri;
-import android.os.Build;
-import android.os.Bundle;
-import android.text.TextUtils;
-import android.util.Pair;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
 
-import org.chromium.base.ApiCompatibilityUtils;
-import org.chromium.base.ContextUtils;
-import org.chromium.base.Log;
 import org.chromium.blink_public.platform.WebDisplayMode;
-import org.chromium.chrome.browser.IntentHandler;
 import org.chromium.chrome.browser.ShortcutHelper;
-import org.chromium.chrome.browser.ShortcutSource;
-import org.chromium.chrome.browser.util.IntentUtils;
-import org.chromium.content_public.common.ScreenOrientationValues;
-import org.chromium.webapk.lib.common.WebApkCommonUtils;
+import org.chromium.chrome.browser.browserservices.BrowserServicesIntentDataProvider;
 import org.chromium.webapk.lib.common.WebApkConstants;
-import org.chromium.webapk.lib.common.WebApkMetaDataKeys;
-import org.chromium.webapk.lib.common.WebApkMetaDataUtils;
-import org.chromium.webapk.lib.common.splash.SplashLayout;
 
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
 import java.util.Map;
 
 /**
@@ -129,29 +108,8 @@
         }
     }
 
-    public static final String RESOURCE_NAME = "name";
-    public static final String RESOURCE_SHORT_NAME = "short_name";
-    public static final String RESOURCE_STRING_TYPE = "string";
-
-    private static final String TAG = "WebApkInfo";
-
-    private WebappIcon mBadgeIcon;
-    private WebappIcon mSplashIcon;
-    private String mApkPackageName;
-    private int mShellApkVersion;
-    private String mManifestUrl;
-    private String mManifestStartUrl;
-    private @WebApkDistributor int mDistributor;
-    private ShareTarget mShareTarget;
-    private String mShareTargetActivityName;
-    private int mApkVersionCode;
-    private Map<String, String> mIconUrlToMurmur2HashMap;
-    private boolean mIsSplashProvidedByWebApk;
-
-    private ShareData mShareData;
-
     public static WebApkInfo createEmpty() {
-        return new WebApkInfo();
+        return create(WebApkIntentDataProvider.createEmpty());
     }
 
     /**
@@ -160,88 +118,7 @@
      * @param intent Intent containing info about the app.
      */
     public static WebApkInfo create(Intent intent) {
-        String webApkPackageName =
-                IntentUtils.safeGetStringExtra(intent, WebApkConstants.EXTRA_WEBAPK_PACKAGE_NAME);
-
-        if (TextUtils.isEmpty(webApkPackageName)) {
-            return null;
-        }
-
-        // Force navigation if the extra is not specified to avoid breaking deep linking for old
-        // WebAPKs which don't specify the {@link ShortcutHelper#EXTRA_FORCE_NAVIGATION} intent
-        // extra.
-        boolean forceNavigation = IntentUtils.safeGetBooleanExtra(
-                intent, ShortcutHelper.EXTRA_FORCE_NAVIGATION, true);
-
-        ShareData shareData = null;
-
-        String shareActivityClassName = IntentUtils.safeGetStringExtra(
-                intent, WebApkConstants.EXTRA_WEBAPK_SELECTED_SHARE_TARGET_ACTIVITY_CLASS_NAME);
-
-        // Share Target when shareActivityClassName is present.
-        if (!TextUtils.isEmpty(shareActivityClassName)) {
-            shareData = new ShareData();
-            shareData.shareActivityClassName = shareActivityClassName;
-            shareData.subject = IntentUtils.safeGetStringExtra(intent, Intent.EXTRA_SUBJECT);
-            shareData.text = IntentUtils.safeGetStringExtra(intent, Intent.EXTRA_TEXT);
-            shareData.files = IntentUtils.getParcelableArrayListExtra(intent, Intent.EXTRA_STREAM);
-            if (shareData.files == null) {
-                Uri file = IntentUtils.safeGetParcelableExtra(intent, Intent.EXTRA_STREAM);
-                if (file != null) {
-                    shareData.files = new ArrayList<>();
-                    shareData.files.add(file);
-                }
-            }
-        }
-
-        String url = urlFromIntent(intent);
-        int source = sourceFromIntent(intent);
-
-        if (source == ShortcutSource.EXTERNAL_INTENT) {
-            if (IntentHandler.determineExternalIntentSource(intent)
-                    == IntentHandler.ExternalAppId.CHROME) {
-                source = ShortcutSource.EXTERNAL_INTENT_FROM_CHROME;
-            }
-        }
-
-        if (source == ShortcutSource.WEBAPK_SHARE_TARGET && shareData != null
-                && shareData.files != null && shareData.files.size() > 0) {
-            source = ShortcutSource.WEBAPK_SHARE_TARGET_FILE;
-        }
-
-        boolean canUseSplashFromContentProvider = IntentUtils.safeGetBooleanExtra(
-                intent, WebApkConstants.EXTRA_SPLASH_PROVIDED_BY_WEBAPK, false);
-
-        return create(webApkPackageName, url, source, forceNavigation,
-                canUseSplashFromContentProvider, shareData);
-    }
-
-    /**
-     * Returns whether the WebAPK has a content provider which provides an image to use for the
-     * splash screen.
-     */
-    private static boolean hasContentProviderForSplash(String webApkPackageName) {
-        PackageManager packageManager = ContextUtils.getApplicationContext().getPackageManager();
-        ProviderInfo providerInfo = packageManager.resolveContentProvider(
-                WebApkCommonUtils.generateSplashContentProviderAuthority(webApkPackageName), 0);
-        return (providerInfo != null
-                && TextUtils.equals(providerInfo.packageName, webApkPackageName));
-    }
-
-    private static @WebApkDistributor int getDistributor(Bundle bundle, String packageName) {
-        String distributor = IntentUtils.safeGetString(bundle, WebApkMetaDataKeys.DISTRIBUTOR);
-        if (!TextUtils.isEmpty(distributor)) {
-            if (TextUtils.equals(distributor, "browser")) {
-                return WebApkDistributor.BROWSER;
-            }
-            if (TextUtils.equals(distributor, "device_policy")) {
-                return WebApkDistributor.DEVICE_POLICY;
-            }
-            return WebApkDistributor.OTHER;
-        }
-        return packageName.startsWith(WebApkConstants.WEBAPK_PACKAGE_PREFIX)
-                ? WebApkDistributor.BROWSER
-                : WebApkDistributor.OTHER;
+        return create(WebApkIntentDataProvider.create(intent));
     }
 
     /**
@@ -259,96 +136,8 @@
      */
     public static WebApkInfo create(String webApkPackageName, String url, int source,
             boolean forceNavigation, boolean canUseSplashFromContentProvider, ShareData shareData) {
-        // Unlike non-WebAPK web apps, WebAPK ids are predictable. A malicious actor may send an
-        // intent with a valid start URL and arbitrary other data. Only use the start URL, the
-        // package name and the ShortcutSource from the launch intent and extract the remaining data
-        // from the <meta-data> in the WebAPK's Android manifest.
-
-        Bundle bundle = extractWebApkMetaData(webApkPackageName);
-        if (bundle == null) {
-            return null;
-        }
-
-        Context appContext = ContextUtils.getApplicationContext();
-        PackageManager pm = appContext.getPackageManager();
-        Resources res = null;
-        int apkVersion = 0;
-        try {
-            res = pm.getResourcesForApplication(webApkPackageName);
-            apkVersion = pm.getPackageInfo(webApkPackageName, 0).versionCode;
-        } catch (PackageManager.NameNotFoundException e) {
-            return null;
-        }
-
-        int nameId = res.getIdentifier(RESOURCE_NAME, RESOURCE_STRING_TYPE, webApkPackageName);
-        int shortNameId =
-                res.getIdentifier(RESOURCE_SHORT_NAME, RESOURCE_STRING_TYPE, webApkPackageName);
-        String name = nameId != 0 ? res.getString(nameId)
-                                  : IntentUtils.safeGetString(bundle, WebApkMetaDataKeys.NAME);
-        String shortName = shortNameId != 0
-                ? res.getString(shortNameId)
-                : IntentUtils.safeGetString(bundle, WebApkMetaDataKeys.SHORT_NAME);
-
-        String scope = IntentUtils.safeGetString(bundle, WebApkMetaDataKeys.SCOPE);
-
-        @WebDisplayMode
-        int displayMode = displayModeFromString(
-                IntentUtils.safeGetString(bundle, WebApkMetaDataKeys.DISPLAY_MODE));
-        int orientation = orientationFromString(
-                IntentUtils.safeGetString(bundle, WebApkMetaDataKeys.ORIENTATION));
-        long themeColor = WebApkMetaDataUtils.getLongFromMetaData(bundle,
-                WebApkMetaDataKeys.THEME_COLOR, ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING);
-        long backgroundColor =
-                WebApkMetaDataUtils.getLongFromMetaData(bundle, WebApkMetaDataKeys.BACKGROUND_COLOR,
-                        ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING);
-
-        // Fetch the default background color from the WebAPK's resources. Fetching the default
-        // background color from the WebAPK is important for consistency when:
-        // - A new version of Chrome has changed the default background color.
-        // - Chrome has not yet requested an update for the WebAPK and the WebAPK still has the old
-        //   default background color in its resources.
-        // New-style WebAPKs use the background color and default background color in both the
-        // WebAPK and Chrome processes.
-        int defaultBackgroundColorId =
-                IntentUtils.safeGetInt(bundle, WebApkMetaDataKeys.DEFAULT_BACKGROUND_COLOR_ID, 0);
-        int defaultBackgroundColor = (defaultBackgroundColorId == 0)
-                ? SplashLayout.getDefaultBackgroundColor(appContext)
-                : ApiCompatibilityUtils.getColor(res, defaultBackgroundColorId);
-
-        int shellApkVersion =
-                IntentUtils.safeGetInt(bundle, WebApkMetaDataKeys.SHELL_APK_VERSION, 0);
-
-        String manifestUrl = IntentUtils.safeGetString(bundle, WebApkMetaDataKeys.WEB_MANIFEST_URL);
-        String manifestStartUrl = IntentUtils.safeGetString(bundle, WebApkMetaDataKeys.START_URL);
-        Map<String, String> iconUrlToMurmur2HashMap = getIconUrlAndIconMurmur2HashMap(bundle);
-
-        @WebApkDistributor
-        int distributor = getDistributor(bundle, webApkPackageName);
-
-        int primaryIconId = IntentUtils.safeGetInt(bundle, WebApkMetaDataKeys.ICON_ID, 0);
-        boolean isPrimaryIconMaskable =
-                IntentUtils.safeGetBoolean(bundle, WebApkMetaDataKeys.IS_ICON_MASKABLE, false);
-
-        int badgeIconId = IntentUtils.safeGetInt(bundle, WebApkMetaDataKeys.BADGE_ICON_ID, 0);
-        int splashIconId = IntentUtils.safeGetInt(bundle, WebApkMetaDataKeys.SPLASH_ID, 0);
-
-        Pair<String, ShareTarget> shareTargetActivityNameAndData =
-                extractFirstShareTarget(webApkPackageName);
-        String shareTargetActivityName = shareTargetActivityNameAndData.first;
-        ShareTarget shareTarget = shareTargetActivityNameAndData.second;
-
-        boolean isSplashProvidedByWebApk =
-                (canUseSplashFromContentProvider && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
-                        && hasContentProviderForSplash(webApkPackageName));
-
-        return create(url, scope, new WebappIcon(webApkPackageName, primaryIconId),
-                new WebappIcon(webApkPackageName, badgeIconId),
-                new WebappIcon(webApkPackageName, splashIconId), name, shortName, displayMode,
-                orientation, source, themeColor, backgroundColor, defaultBackgroundColor,
-                isPrimaryIconMaskable, webApkPackageName, shellApkVersion, manifestUrl,
-                manifestStartUrl, distributor, iconUrlToMurmur2HashMap, shareTarget,
-                shareTargetActivityName, forceNavigation, isSplashProvidedByWebApk, shareData,
-                apkVersion);
+        return create(WebApkIntentDataProvider.create(webApkPackageName, url, source,
+                forceNavigation, canUseSplashFromContentProvider, shareData));
     }
 
     /**
@@ -397,91 +186,53 @@
             Map<String, String> iconUrlToMurmur2HashMap, ShareTarget shareTarget,
             String shareTargetActivityName, boolean forceNavigation,
             boolean isSplashProvidedByWebApk, ShareData shareData, int webApkVersionCode) {
-        if (url == null || manifestStartUrl == null || webApkPackageName == null) {
-            Log.e(TAG,
-                    "Incomplete data provided: " + url + ", " + manifestStartUrl + ", "
-                            + webApkPackageName);
-            return null;
-        }
-
-        // The default scope should be computed from the Web Manifest start URL. If the WebAPK was
-        // launched from a deep link {@link startUrl} may be different from the Web Manifest start
-        // URL.
-        if (TextUtils.isEmpty(scope)) {
-            scope = ShortcutHelper.getScopeFromUrl(manifestStartUrl);
-        }
-
-        return new WebApkInfo(url, scope, primaryIcon, badgeIcon, splashIcon, name, shortName,
-                displayMode, orientation, source, themeColor, backgroundColor,
-                defaultBackgroundColor, isPrimaryIconMaskable, webApkPackageName, shellApkVersion,
-                manifestUrl, manifestStartUrl, distributor, iconUrlToMurmur2HashMap, shareTarget,
-                shareTargetActivityName, forceNavigation, isSplashProvidedByWebApk, shareData,
-                webApkVersionCode);
+        return create(WebApkIntentDataProvider.create(url, scope, primaryIcon, badgeIcon,
+                splashIcon, name, shortName, displayMode, orientation, source, themeColor,
+                backgroundColor, defaultBackgroundColor, isPrimaryIconMaskable, webApkPackageName,
+                shellApkVersion, manifestUrl, manifestStartUrl, distributor,
+                iconUrlToMurmur2HashMap, shareTarget, shareTargetActivityName, forceNavigation,
+                isSplashProvidedByWebApk, shareData, webApkVersionCode));
     }
 
-    protected WebApkInfo(String url, String scope, WebappIcon primaryIcon, WebappIcon badgeIcon,
-            WebappIcon splashIcon, String name, String shortName, @WebDisplayMode int displayMode,
-            int orientation, int source, long themeColor, long backgroundColor,
-            int defaultBackgroundColor, boolean isPrimaryIconMaskable, String webApkPackageName,
-            int shellApkVersion, String manifestUrl, String manifestStartUrl,
-            @WebApkDistributor int distributor, Map<String, String> iconUrlToMurmur2HashMap,
-            ShareTarget shareTarget, String shareTargetActivityName, boolean forceNavigation,
-            boolean isSplashProvidedByWebApk, ShareData shareData, int webApkVersionCode) {
-        super(WebappRegistry.webApkIdForPackage(webApkPackageName), url, scope, primaryIcon, name,
-                shortName, displayMode, orientation, source, themeColor, backgroundColor,
-                defaultBackgroundColor, false /* isIconGenerated */,
-                isPrimaryIconMaskable /* isIconAdaptive */, forceNavigation);
-        mBadgeIcon = (badgeIcon != null) ? badgeIcon : new WebappIcon();
-        mSplashIcon = (splashIcon != null) ? splashIcon : new WebappIcon();
-        mApkPackageName = webApkPackageName;
-        mShellApkVersion = shellApkVersion;
-        mManifestUrl = manifestUrl;
-        mManifestStartUrl = manifestStartUrl;
-        mDistributor = distributor;
-        mIconUrlToMurmur2HashMap = iconUrlToMurmur2HashMap;
-        mIsSplashProvidedByWebApk = isSplashProvidedByWebApk;
-        mShareData = shareData;
-        mShareTarget = shareTarget;
-        if (mShareTarget == null) {
-            mShareTarget = new ShareTarget();
-        }
-        mShareTargetActivityName = shareTargetActivityName;
-        mApkVersionCode = webApkVersionCode;
+    private static WebApkInfo create(@Nullable BrowserServicesIntentDataProvider provider) {
+        return (provider != null) ? new WebApkInfo(provider) : null;
     }
 
-    protected WebApkInfo() {}
+    public WebApkInfo(@NonNull BrowserServicesIntentDataProvider provider) {
+        super(provider);
+    }
 
     /**
      * Returns the badge icon in Bitmap form.
      */
     public WebappIcon badgeIcon() {
-        return mBadgeIcon;
+        return getWebApkExtras().badgeIcon;
     }
 
     /**
      * Returns the splash icon in Bitmap form.
      */
     public WebappIcon splashIcon() {
-        return mSplashIcon;
+        return getWebApkExtras().splashIcon;
     }
 
     /** Returns data about the WebAPK's share intent handlers. */
     public ShareTarget shareTarget() {
-        return mShareTarget;
+        return getWebApkExtras().shareTarget;
     }
 
     /**
      * Returns name of activity or activity alias in WebAPK which handles share intents.
      */
     public String shareTargetActivityName() {
-        return mShareTargetActivityName;
+        return getWebApkExtras().shareTargetActivityName;
     }
 
     /**
      * Returns the WebAPK's version code.
      */
     public int webApkVersionCode() {
-        return mApkVersionCode;
+        return getWebApkExtras().webApkVersionCode;
     }
 
     @Override
@@ -491,36 +242,42 @@
 
     @Override
     public String webApkPackageName() {
-        return mApkPackageName;
+        return getWebApkExtras().webApkPackageName;
     }
 
     @Override
     public boolean isSplashProvidedByWebApk() {
-        return mIsSplashProvidedByWebApk;
+        return getWebApkExtras().isSplashProvidedByWebApk;
     }
 
     public int shellApkVersion() {
-        return mShellApkVersion;
+        return getWebApkExtras().shellApkVersion;
     }
 
     public String manifestUrl() {
-        return mManifestUrl;
+        return getWebApkExtras().manifestUrl;
     }
 
     public String manifestStartUrl() {
-        return mManifestStartUrl;
+        return getWebApkExtras().manifestStartUrl;
     }
 
     public @WebApkDistributor int distributor() {
-        return mDistributor;
+        return getWebApkExtras().distributor;
     }
 
     public Map<String, String> iconUrlToMurmur2HashMap() {
-        return mIconUrlToMurmur2HashMap;
+        return getWebApkExtras().iconUrlToMurmur2HashMap;
     }
 
     public ShareData shareData() {
-        return mShareData;
+        return getWebApkExtras().shareData;
+    }
+
+    private WebApkExtras getWebApkExtras() {
+        WebApkExtras extras = mProvider.getWebApkExtras();
+        assert extras != null;
+        return extras;
     }
 
     @Override
@@ -535,164 +292,6 @@
                 WebApkConstants.EXTRA_SPLASH_PROVIDED_BY_WEBAPK, isSplashProvidedByWebApk());
     }
 
-    /**
-     * Extracts meta data from a WebAPK's Android Manifest.
-     * @param webApkPackageName WebAPK's package name.
-     * @return Bundle with the extracted meta data.
-     */
-    private static Bundle extractWebApkMetaData(String webApkPackageName) {
-        PackageManager packageManager = ContextUtils.getApplicationContext().getPackageManager();
-        try {
-            ApplicationInfo appInfo = packageManager.getApplicationInfo(
-                    webApkPackageName, PackageManager.GET_META_DATA);
-            return appInfo.metaData;
-        } catch (PackageManager.NameNotFoundException e) {
-            return null;
-        }
-    }
-
-    /**
-     * Extract the icon URLs and icon hashes from the WebAPK's meta data, and returns a map of these
-     * {URL, hash} pairs. The icon URLs/icon hashes are stored in a single meta data tag in the
-     * WebAPK's AndroidManifest.xml as following:
-     * "URL1 hash1 URL2 hash2 URL3 hash3..."
-     */
-    private static Map<String, String> getIconUrlAndIconMurmur2HashMap(Bundle metaData) {
-        Map<String, String> iconUrlAndIconMurmur2HashMap = new HashMap<String, String>();
-        String iconUrlsAndIconMurmur2Hashes = metaData.getString(
-                WebApkMetaDataKeys.ICON_URLS_AND_ICON_MURMUR2_HASHES);
-        if (TextUtils.isEmpty(iconUrlsAndIconMurmur2Hashes)) return iconUrlAndIconMurmur2HashMap;
-
-        // Parse the metadata tag which contains "URL1 hash1 URL2 hash2 URL3 hash3..." pairs and
-        // create a hash map.
-        // TODO(hanxi): crbug.com/666349. Add a test to verify that the icon URLs in WebAPKs'
-        // AndroidManifest.xml don't contain space.
-        String[] urlsAndHashes = iconUrlsAndIconMurmur2Hashes.split("[ ]+");
-        if (urlsAndHashes.length % 2 != 0) {
-            Log.e(TAG, "The icon URLs and icon murmur2 hashes don't come in pairs.");
-            return iconUrlAndIconMurmur2HashMap;
-        }
-        for (int i = 0; i < urlsAndHashes.length; i += 2) {
-            iconUrlAndIconMurmur2HashMap.put(urlsAndHashes[i], urlsAndHashes[i + 1]);
-        }
-        return iconUrlAndIconMurmur2HashMap;
-    }
-
-    /**
-     * Returns the WebDisplayMode which matches {@link displayMode}.
-     * @param displayMode One of https://www.w3.org/TR/appmanifest/#dfn-display-modes-values
-     * @return The matching WebDisplayMode. {@link WebDisplayMode#Undefined} if there is no match.
-     */
-    private static @WebDisplayMode int displayModeFromString(String displayMode) {
-        if (displayMode == null) {
-            return WebDisplayMode.UNDEFINED;
-        }
-
-        if (displayMode.equals("fullscreen")) {
-            return WebDisplayMode.FULLSCREEN;
-        } else if (displayMode.equals("standalone")) {
-            return WebDisplayMode.STANDALONE;
-        } else if (displayMode.equals("minimal-ui")) {
-            return WebDisplayMode.MINIMAL_UI;
-        } else if (displayMode.equals("browser")) {
-            return WebDisplayMode.BROWSER;
-        } else {
-            return WebDisplayMode.UNDEFINED;
-        }
-    }
-
-    /**
-     * Returns the ScreenOrientationValue which matches {@link orientation}.
-     * @param orientation One of https://w3c.github.io/screen-orientation/#orientationlocktype-enum
-     * @return The matching ScreenOrientationValue. {@link ScreenOrientationValues#DEFAULT} if there
-     * is no match.
-     */
-    private static int orientationFromString(String orientation) {
-        if (orientation == null) {
-            return ScreenOrientationValues.DEFAULT;
-        }
-
-        if (orientation.equals("any")) {
-            return ScreenOrientationValues.ANY;
-        } else if (orientation.equals("natural")) {
-            return ScreenOrientationValues.NATURAL;
-        } else if (orientation.equals("landscape")) {
-            return ScreenOrientationValues.LANDSCAPE;
-        } else if (orientation.equals("landscape-primary")) {
-            return ScreenOrientationValues.LANDSCAPE_PRIMARY;
-        } else if (orientation.equals("landscape-secondary")) {
-            return ScreenOrientationValues.LANDSCAPE_SECONDARY;
-        } else if (orientation.equals("portrait")) {
-            return ScreenOrientationValues.PORTRAIT;
-        } else if (orientation.equals("portrait-primary")) {
-            return ScreenOrientationValues.PORTRAIT_PRIMARY;
-        } else if (orientation.equals("portrait-secondary")) {
-            return ScreenOrientationValues.PORTRAIT_SECONDARY;
-        } else {
-            return ScreenOrientationValues.DEFAULT;
-        }
-    }
-
-    /**
-     * Returns the name of activity or activity alias in WebAPK which handles share intents, and
-     * the data about the handler.
-     */
-    private static Pair<String, ShareTarget> extractFirstShareTarget(String webApkPackageName) {
-        Intent shareIntent = new Intent();
-        shareIntent.setAction(Intent.ACTION_SEND);
-        shareIntent.setPackage(webApkPackageName);
-        shareIntent.setType("*/*");
-        List<ResolveInfo> resolveInfos =
-                ContextUtils.getApplicationContext().getPackageManager().queryIntentActivities(
-                        shareIntent, PackageManager.GET_META_DATA);
-
-        for (ResolveInfo resolveInfo : resolveInfos) {
-            Bundle shareTargetMetaData = resolveInfo.activityInfo.metaData;
-            if (shareTargetMetaData == null) {
-                continue;
-            }
-
-            String shareTargetActivityName = resolveInfo.activityInfo.name;
-
-            String shareAction =
-                    IntentUtils.safeGetString(shareTargetMetaData, WebApkMetaDataKeys.SHARE_ACTION);
-            if (TextUtils.isEmpty(shareAction)) {
-                return new Pair<>(null, new ShareTarget());
-            }
-
-            String encodedFileNames = IntentUtils.safeGetString(
-                    shareTargetMetaData, WebApkMetaDataKeys.SHARE_PARAM_NAMES);
-            String[] fileNames = WebApkShareTargetUtil.decodeJsonStringArray(encodedFileNames);
-
-            String encodedFileAccepts = IntentUtils.safeGetString(
-                    shareTargetMetaData, WebApkMetaDataKeys.SHARE_PARAM_ACCEPTS);
-            String[][] fileAccepts = WebApkShareTargetUtil.decodeJsonAccepts(encodedFileAccepts);
-
-            String shareMethod =
-                    IntentUtils.safeGetString(shareTargetMetaData, WebApkMetaDataKeys.SHARE_METHOD);
-            boolean isShareMethodPost =
-                    shareMethod != null && shareMethod.toUpperCase(Locale.ENGLISH).equals("POST");
-
-            String shareEncType = IntentUtils.safeGetString(
-                    shareTargetMetaData, WebApkMetaDataKeys.SHARE_ENCTYPE);
-            boolean isShareEncTypeMultipart = shareEncType != null
-                    && shareEncType.toLowerCase(Locale.ENGLISH).equals("multipart/form-data");
-
-            ShareTarget target = new ShareTarget(
-                    IntentUtils.safeGetString(shareTargetMetaData, WebApkMetaDataKeys.SHARE_ACTION),
-                    IntentUtils.safeGetString(
-                            shareTargetMetaData, WebApkMetaDataKeys.SHARE_PARAM_TITLE),
-                    IntentUtils.safeGetString(
-                            shareTargetMetaData, WebApkMetaDataKeys.SHARE_PARAM_TEXT),
-                    IntentUtils.safeGetString(
-                            shareTargetMetaData, WebApkMetaDataKeys.SHARE_PARAM_URL),
-                    isShareMethodPost, isShareEncTypeMultipart, fileNames, fileAccepts);
-
-            return new Pair<>(shareTargetActivityName, target);
-        }
-        return new Pair<>(null, new ShareTarget());
-    }
-
     /** Returns the value if it is non-null. Returns an empty string otherwise. */
     private static String replaceNullWithEmpty(String value) {
         return (value == null) ? "" : value;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkIntentDataProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkIntentDataProvider.java
new file mode 100644
index 0000000..fb54a07
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkIntentDataProvider.java
@@ -0,0 +1,530 @@
+// Copyright 2019 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.
+
+package org.chromium.chrome.browser.webapps;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ProviderInfo;
+import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.text.TextUtils;
+import android.util.Pair;
+
+import org.chromium.base.ApiCompatibilityUtils;
+import org.chromium.base.ContextUtils;
+import org.chromium.base.Log;
+import org.chromium.blink_public.platform.WebDisplayMode;
+import org.chromium.chrome.browser.IntentHandler;
+import org.chromium.chrome.browser.ShortcutHelper;
+import org.chromium.chrome.browser.ShortcutSource;
+import org.chromium.chrome.browser.browserservices.BrowserServicesIntentDataProvider;
+import org.chromium.chrome.browser.util.IntentUtils;
+import org.chromium.chrome.browser.webapps.WebApkInfo.ShareData;
+import org.chromium.chrome.browser.webapps.WebApkInfo.ShareTarget;
+import org.chromium.content_public.common.ScreenOrientationValues;
+import org.chromium.webapk.lib.common.WebApkCommonUtils;
+import org.chromium.webapk.lib.common.WebApkConstants;
+import org.chromium.webapk.lib.common.WebApkMetaDataKeys;
+import org.chromium.webapk.lib.common.WebApkMetaDataUtils;
+import org.chromium.webapk.lib.common.splash.SplashLayout;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+/**
+ * Stores info for WebAPK.
+ */
+public class WebApkIntentDataProvider extends BrowserServicesIntentDataProvider {
+    public static final String RESOURCE_NAME = "name";
+    public static final String RESOURCE_SHORT_NAME = "short_name";
+    public static final String RESOURCE_STRING_TYPE = "string";
+
+    private static final String TAG = "WebApkInfo";
+
+    private WebappExtras mWebappExtras;
+    private WebApkExtras mWebApkExtras;
+
+    public static WebApkIntentDataProvider createEmpty() {
+        return new WebApkIntentDataProvider(WebappExtras.createEmpty(), WebApkExtras.createEmpty());
+    }
+
+    /**
+     * Constructs a WebApkIntentDataProvider from the passed in Intent and <meta-data> in the
+     * WebAPK's Android manifest.
+     * @param intent Intent containing info about the app.
+     */
+    public static WebApkIntentDataProvider create(Intent intent) {
+        String webApkPackageName =
+                IntentUtils.safeGetStringExtra(intent, WebApkConstants.EXTRA_WEBAPK_PACKAGE_NAME);
+
+        if (TextUtils.isEmpty(webApkPackageName)) {
+            return null;
+        }
+
+        // Force navigation if the extra is not specified to avoid breaking deep linking for old
+        // WebAPKs which don't specify the {@link ShortcutHelper#EXTRA_FORCE_NAVIGATION} intent
+        // extra.
+        boolean forceNavigation = IntentUtils.safeGetBooleanExtra(
+                intent, ShortcutHelper.EXTRA_FORCE_NAVIGATION, true);
+
+        ShareData shareData = null;
+
+        String shareActivityClassName = IntentUtils.safeGetStringExtra(
+                intent, WebApkConstants.EXTRA_WEBAPK_SELECTED_SHARE_TARGET_ACTIVITY_CLASS_NAME);
+
+        // Share Target when shareActivityClassName is present.
+        if (!TextUtils.isEmpty(shareActivityClassName)) {
+            shareData = new ShareData();
+            shareData.shareActivityClassName = shareActivityClassName;
+            shareData.subject = IntentUtils.safeGetStringExtra(intent, Intent.EXTRA_SUBJECT);
+            shareData.text = IntentUtils.safeGetStringExtra(intent, Intent.EXTRA_TEXT);
+            shareData.files = IntentUtils.getParcelableArrayListExtra(intent, Intent.EXTRA_STREAM);
+            if (shareData.files == null) {
+                Uri file = IntentUtils.safeGetParcelableExtra(intent, Intent.EXTRA_STREAM);
+                if (file != null) {
+                    shareData.files = new ArrayList<>();
+                    shareData.files.add(file);
+                }
+            }
+        }
+
+        String url = IntentUtils.safeGetStringExtra(intent, ShortcutHelper.EXTRA_URL);
+        int source = sourceFromIntent(intent, shareData);
+
+        boolean canUseSplashFromContentProvider = IntentUtils.safeGetBooleanExtra(
+                intent, WebApkConstants.EXTRA_SPLASH_PROVIDED_BY_WEBAPK, false);
+
+        return create(webApkPackageName, url, source, forceNavigation,
+                canUseSplashFromContentProvider, shareData);
+    }
+
+    /**
+     * Returns whether the WebAPK has a content provider which provides an image to use for the
+     * splash screen.
+     */
+    private static boolean hasContentProviderForSplash(String webApkPackageName) {
+        PackageManager packageManager = ContextUtils.getApplicationContext().getPackageManager();
+        ProviderInfo providerInfo = packageManager.resolveContentProvider(
+                WebApkCommonUtils.generateSplashContentProviderAuthority(webApkPackageName), 0);
+        return (providerInfo != null
+                && TextUtils.equals(providerInfo.packageName, webApkPackageName));
+    }
+
+    private static @WebApkDistributor int getDistributor(Bundle bundle, String packageName) {
+        String distributor = IntentUtils.safeGetString(bundle, WebApkMetaDataKeys.DISTRIBUTOR);
+        if (!TextUtils.isEmpty(distributor)) {
+            if (TextUtils.equals(distributor, "browser")) {
+                return WebApkDistributor.BROWSER;
+            }
+            if (TextUtils.equals(distributor, "device_policy")) {
+                return WebApkDistributor.DEVICE_POLICY;
+            }
+            return WebApkDistributor.OTHER;
+        }
+        return packageName.startsWith(WebApkConstants.WEBAPK_PACKAGE_PREFIX)
+                ? WebApkDistributor.BROWSER
+                : WebApkDistributor.OTHER;
+    }
+
+    /**
+     * Constructs a WebApkIntentDataProvider from the passed in parameters and <meta-data> in the
+     * WebAPK's Android manifest.
+     *
+     * @param webApkPackageName The package name of the WebAPK.
+     * @param url Url that the WebAPK should navigate to when launched.
+     * @param source Source that the WebAPK was launched from.
+     * @param forceNavigation Whether the WebAPK should navigate to {@link url} if it is already
+     *                        running.
+     * @param canUseSplashFromContentProvider Whether the WebAPK's content provider can be
+     *                                        queried for a screenshot of the splash screen.
+     * @param shareData Shared information from the share intent.
+     */
+    public static WebApkIntentDataProvider create(String webApkPackageName, String url, int source,
+            boolean forceNavigation, boolean canUseSplashFromContentProvider, ShareData shareData) {
+        // Unlike non-WebAPK web apps, WebAPK ids are predictable. A malicious actor may send an
+        // intent with a valid start URL and arbitrary other data. Only use the start URL, the
+        // package name and the ShortcutSource from the launch intent and extract the remaining data
+        // from the <meta-data> in the WebAPK's Android manifest.
+
+        Bundle bundle = extractWebApkMetaData(webApkPackageName);
+        if (bundle == null) {
+            return null;
+        }
+
+        Context appContext = ContextUtils.getApplicationContext();
+        PackageManager pm = appContext.getPackageManager();
+        Resources res = null;
+        int apkVersion = 0;
+        try {
+            res = pm.getResourcesForApplication(webApkPackageName);
+            apkVersion = pm.getPackageInfo(webApkPackageName, 0).versionCode;
+        } catch (PackageManager.NameNotFoundException e) {
+            return null;
+        }
+
+        int nameId = res.getIdentifier(RESOURCE_NAME, RESOURCE_STRING_TYPE, webApkPackageName);
+        int shortNameId =
+                res.getIdentifier(RESOURCE_SHORT_NAME, RESOURCE_STRING_TYPE, webApkPackageName);
+        String name = nameId != 0 ? res.getString(nameId)
+                                  : IntentUtils.safeGetString(bundle, WebApkMetaDataKeys.NAME);
+        String shortName = shortNameId != 0
+                ? res.getString(shortNameId)
+                : IntentUtils.safeGetString(bundle, WebApkMetaDataKeys.SHORT_NAME);
+
+        String scope = IntentUtils.safeGetString(bundle, WebApkMetaDataKeys.SCOPE);
+
+        @WebDisplayMode
+        int displayMode = displayModeFromString(
+                IntentUtils.safeGetString(bundle, WebApkMetaDataKeys.DISPLAY_MODE));
+        int orientation = orientationFromString(
+                IntentUtils.safeGetString(bundle, WebApkMetaDataKeys.ORIENTATION));
+        long themeColor = WebApkMetaDataUtils.getLongFromMetaData(bundle,
+                WebApkMetaDataKeys.THEME_COLOR, ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING);
+        long backgroundColor =
+                WebApkMetaDataUtils.getLongFromMetaData(bundle, WebApkMetaDataKeys.BACKGROUND_COLOR,
+                        ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING);
+
+        // Fetch the default background color from the WebAPK's resources. Fetching the default
+        // background color from the WebAPK is important for consistency when:
+        // - A new version of Chrome has changed the default background color.
+        // - Chrome has not yet requested an update for the WebAPK and the WebAPK still has the old
+        //   default background color in its resources.
+        // New-style WebAPKs use the background color and default background color in both the
+        // WebAPK and Chrome processes.
+        int defaultBackgroundColorId =
+                IntentUtils.safeGetInt(bundle, WebApkMetaDataKeys.DEFAULT_BACKGROUND_COLOR_ID, 0);
+        int defaultBackgroundColor = (defaultBackgroundColorId == 0)
+                ? SplashLayout.getDefaultBackgroundColor(appContext)
+                : ApiCompatibilityUtils.getColor(res, defaultBackgroundColorId);
+
+        int shellApkVersion =
+                IntentUtils.safeGetInt(bundle, WebApkMetaDataKeys.SHELL_APK_VERSION, 0);
+
+        String manifestUrl = IntentUtils.safeGetString(bundle, WebApkMetaDataKeys.WEB_MANIFEST_URL);
+        String manifestStartUrl = IntentUtils.safeGetString(bundle, WebApkMetaDataKeys.START_URL);
+        Map<String, String> iconUrlToMurmur2HashMap = getIconUrlAndIconMurmur2HashMap(bundle);
+
+        @WebApkDistributor
+        int distributor = getDistributor(bundle, webApkPackageName);
+
+        int primaryIconId = IntentUtils.safeGetInt(bundle, WebApkMetaDataKeys.ICON_ID, 0);
+        boolean isPrimaryIconMaskable =
+                IntentUtils.safeGetBoolean(bundle, WebApkMetaDataKeys.IS_ICON_MASKABLE, false);
+
+        int badgeIconId = IntentUtils.safeGetInt(bundle, WebApkMetaDataKeys.BADGE_ICON_ID, 0);
+        int splashIconId = IntentUtils.safeGetInt(bundle, WebApkMetaDataKeys.SPLASH_ID, 0);
+
+        Pair<String, ShareTarget> shareTargetActivityNameAndData =
+                extractFirstShareTarget(webApkPackageName);
+        String shareTargetActivityName = shareTargetActivityNameAndData.first;
+        ShareTarget shareTarget = shareTargetActivityNameAndData.second;
+
+        boolean isSplashProvidedByWebApk =
+                (canUseSplashFromContentProvider && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
+                        && hasContentProviderForSplash(webApkPackageName));
+
+        return create(url, scope, new WebappIcon(webApkPackageName, primaryIconId),
+                new WebappIcon(webApkPackageName, badgeIconId),
+                new WebappIcon(webApkPackageName, splashIconId), name, shortName, displayMode,
+                orientation, source, themeColor, backgroundColor, defaultBackgroundColor,
+                isPrimaryIconMaskable, webApkPackageName, shellApkVersion, manifestUrl,
+                manifestStartUrl, distributor, iconUrlToMurmur2HashMap, shareTarget,
+                shareTargetActivityName, forceNavigation, isSplashProvidedByWebApk, shareData,
+                apkVersion);
+    }
+
+    /**
+     * Construct a {@link WebApkIntentDataProvider} instance.
+     * @param url                      URL that the WebAPK should navigate to when launched.
+     * @param scope                    Scope for the WebAPK.
+     * @param primaryIcon              Primary icon to show for the WebAPK.
+     * @param badgeIcon                Badge icon to use for notifications.
+     * @param splashIcon               Splash icon to use for the splash screen.
+     * @param name                     Name of the WebAPK.
+     * @param shortName                The short name of the WebAPK.
+     * @param displayMode              Display mode of the WebAPK.
+     * @param orientation              Orientation of the WebAPK.
+     * @param source                   Source that the WebAPK was launched from.
+     * @param themeColor               The theme color of the WebAPK.
+     * @param backgroundColor          The background color of the WebAPK.
+     * @param defaultBackgroundColor   The background color to use if the Web Manifest does not
+     *                                 provide a background color.
+     * @param isPrimaryIconMaskable    Is the primary icon maskable.
+     * @param webApkPackageName        The package of the WebAPK.
+     * @param shellApkVersion          Version of the code in //chrome/android/webapk/shell_apk.
+     * @param manifestUrl              URL of the Web Manifest.
+     * @param manifestStartUrl         URL that the WebAPK should navigate to when launched from
+     *                                 the homescreen. Different from the {@link url} parameter if
+     *                                 the WebAPK is launched from a deep link.
+     * @param distributor              The source from where the WebAPK is installed.
+     * @param iconUrlToMurmur2HashMap  Map of the WebAPK's icon URLs to Murmur2 hashes of the
+     *                                 icon untransformed bytes.
+     * @param shareTarget              shareTarget data for {@link shareTargetActivityName}
+     * @param shareTargetActivityName  Name of activity or activity alias in WebAPK which handles
+     *                                 share intents
+     * @param forceNavigation          Whether the WebAPK should navigate to {@link url} if the
+     *                                 WebAPK is already open.
+     * @param isSplashProvidedByWebApk Whether the WebAPK (1) launches an internal activity to
+     *                                 display the splash screen and (2) has a content provider
+     *                                 which provides a screenshot of the splash screen.
+     * @param shareData                Shared information from the share intent.
+     * @param webApkVersionCode        WebAPK's version code.
+     */
+    public static WebApkIntentDataProvider create(String url, String scope, WebappIcon primaryIcon,
+            WebappIcon badgeIcon, WebappIcon splashIcon, String name, String shortName,
+            @WebDisplayMode int displayMode, int orientation, int source, long themeColor,
+            long backgroundColor, int defaultBackgroundColor, boolean isPrimaryIconMaskable,
+            String webApkPackageName, int shellApkVersion, String manifestUrl,
+            String manifestStartUrl, @WebApkDistributor int distributor,
+            Map<String, String> iconUrlToMurmur2HashMap, ShareTarget shareTarget,
+            String shareTargetActivityName, boolean forceNavigation,
+            boolean isSplashProvidedByWebApk, ShareData shareData, int webApkVersionCode) {
+        if (url == null || manifestStartUrl == null || webApkPackageName == null) {
+            Log.e(TAG,
+                    "Incomplete data provided: " + url + ", " + manifestStartUrl + ", "
+                            + webApkPackageName);
+            return null;
+        }
+
+        // The default scope should be computed from the Web Manifest start URL. If the WebAPK was
+        // launched from a deep link {@link startUrl} may be different from the Web Manifest start
+        // URL.
+        if (TextUtils.isEmpty(scope)) {
+            scope = ShortcutHelper.getScopeFromUrl(manifestStartUrl);
+        }
+
+        if (primaryIcon == null) {
+            primaryIcon = new WebappIcon();
+        }
+
+        if (badgeIcon == null) {
+            badgeIcon = new WebappIcon();
+        }
+
+        if (splashIcon == null) {
+            splashIcon = new WebappIcon();
+        }
+
+        if (shareTarget == null) {
+            shareTarget = new ShareTarget();
+        }
+
+        WebappExtras webappExtras =
+                new WebappExtras(WebappRegistry.webApkIdForPackage(webApkPackageName), url, scope,
+                        primaryIcon, name, shortName, displayMode, orientation, source,
+                        WebappIntentDataProvider.integerColorFromLongColor(themeColor),
+                        WebappIntentDataProvider.integerColorFromLongColor(backgroundColor),
+                        defaultBackgroundColor, false /* isIconGenerated */, isPrimaryIconMaskable,
+                        forceNavigation);
+        WebApkExtras webApkExtras = new WebApkExtras(webApkPackageName, badgeIcon, splashIcon,
+                shellApkVersion, manifestUrl, manifestStartUrl, distributor,
+                iconUrlToMurmur2HashMap, shareTarget, shareTargetActivityName,
+                isSplashProvidedByWebApk, shareData, webApkVersionCode);
+        return new WebApkIntentDataProvider(webappExtras, webApkExtras);
+    }
+
+    private WebApkIntentDataProvider(WebappExtras webappExtras, WebApkExtras webApkExtras) {
+        mWebappExtras = webappExtras;
+        mWebApkExtras = webApkExtras;
+    }
+
+    private static int sourceFromIntent(Intent intent, ShareData shareData) {
+        int source = IntentUtils.safeGetIntExtra(
+                intent, ShortcutHelper.EXTRA_SOURCE, ShortcutSource.UNKNOWN);
+        if (source >= ShortcutSource.COUNT) {
+            return ShortcutSource.UNKNOWN;
+        }
+        if (source == ShortcutSource.EXTERNAL_INTENT
+                && IntentHandler.determineExternalIntentSource(intent)
+                        == IntentHandler.ExternalAppId.CHROME) {
+            return ShortcutSource.EXTERNAL_INTENT_FROM_CHROME;
+        }
+
+        if (source == ShortcutSource.WEBAPK_SHARE_TARGET && shareData != null
+                && shareData.files != null && shareData.files.size() > 0) {
+            return ShortcutSource.WEBAPK_SHARE_TARGET_FILE;
+        }
+        return source;
+    }
+
+    /**
+     * Extracts meta data from a WebAPK's Android Manifest.
+     * @param webApkPackageName WebAPK's package name.
+     * @return Bundle with the extracted meta data.
+     */
+    private static Bundle extractWebApkMetaData(String webApkPackageName) {
+        PackageManager packageManager = ContextUtils.getApplicationContext().getPackageManager();
+        try {
+            ApplicationInfo appInfo = packageManager.getApplicationInfo(
+                    webApkPackageName, PackageManager.GET_META_DATA);
+            return appInfo.metaData;
+        } catch (PackageManager.NameNotFoundException e) {
+            return null;
+        }
+    }
+
+    /**
+     * Extract the icon URLs and icon hashes from the WebAPK's meta data, and returns a map of these
+     * {URL, hash} pairs. The icon URLs/icon hashes are stored in a single meta data tag in the
+     * WebAPK's AndroidManifest.xml as following:
+     * "URL1 hash1 URL2 hash2 URL3 hash3..."
+     */
+    private static Map<String, String> getIconUrlAndIconMurmur2HashMap(Bundle metaData) {
+        Map<String, String> iconUrlAndIconMurmur2HashMap = new HashMap<String, String>();
+        String iconUrlsAndIconMurmur2Hashes =
+                metaData.getString(WebApkMetaDataKeys.ICON_URLS_AND_ICON_MURMUR2_HASHES);
+        if (TextUtils.isEmpty(iconUrlsAndIconMurmur2Hashes)) return iconUrlAndIconMurmur2HashMap;
+
+        // Parse the metadata tag which contains "URL1 hash1 URL2 hash2 URL3 hash3..." pairs and
+        // create a hash map.
+        // TODO(hanxi): crbug.com/666349. Add a test to verify that the icon URLs in WebAPKs'
+        // AndroidManifest.xml don't contain space.
+        String[] urlsAndHashes = iconUrlsAndIconMurmur2Hashes.split("[ ]+");
+        if (urlsAndHashes.length % 2 != 0) {
+            Log.e(TAG, "The icon URLs and icon murmur2 hashes don't come in pairs.");
+            return iconUrlAndIconMurmur2HashMap;
+        }
+        for (int i = 0; i < urlsAndHashes.length; i += 2) {
+            iconUrlAndIconMurmur2HashMap.put(urlsAndHashes[i], urlsAndHashes[i + 1]);
+        }
+        return iconUrlAndIconMurmur2HashMap;
+    }
+
+    /**
+     * Returns the WebDisplayMode which matches {@link displayMode}.
+     * @param displayMode One of https://www.w3.org/TR/appmanifest/#dfn-display-modes-values
+     * @return The matching WebDisplayMode. {@link WebDisplayMode#Undefined} if there is no match.
+     */
+    private static @WebDisplayMode int displayModeFromString(String displayMode) {
+        if (displayMode == null) {
+            return WebDisplayMode.UNDEFINED;
+        }
+
+        if (displayMode.equals("fullscreen")) {
+            return WebDisplayMode.FULLSCREEN;
+        } else if (displayMode.equals("standalone")) {
+            return WebDisplayMode.STANDALONE;
+        } else if (displayMode.equals("minimal-ui")) {
+            return WebDisplayMode.MINIMAL_UI;
+        } else if (displayMode.equals("browser")) {
+            return WebDisplayMode.BROWSER;
+        } else {
+            return WebDisplayMode.UNDEFINED;
+        }
+    }
+
+    /**
+     * Returns the ScreenOrientationValue which matches {@link orientation}.
+     * @param orientation One of https://w3c.github.io/screen-orientation/#orientationlocktype-enum
+     * @return The matching ScreenOrientationValue. {@link ScreenOrientationValues#DEFAULT} if there
+     * is no match.
+     */
+    private static int orientationFromString(String orientation) {
+        if (orientation == null) {
+            return ScreenOrientationValues.DEFAULT;
+        }
+
+        if (orientation.equals("any")) {
+            return ScreenOrientationValues.ANY;
+        } else if (orientation.equals("natural")) {
+            return ScreenOrientationValues.NATURAL;
+        } else if (orientation.equals("landscape")) {
+            return ScreenOrientationValues.LANDSCAPE;
+        } else if (orientation.equals("landscape-primary")) {
+            return ScreenOrientationValues.LANDSCAPE_PRIMARY;
+        } else if (orientation.equals("landscape-secondary")) {
+            return ScreenOrientationValues.LANDSCAPE_SECONDARY;
+        } else if (orientation.equals("portrait")) {
+            return ScreenOrientationValues.PORTRAIT;
+        } else if (orientation.equals("portrait-primary")) {
+            return ScreenOrientationValues.PORTRAIT_PRIMARY;
+        } else if (orientation.equals("portrait-secondary")) {
+            return ScreenOrientationValues.PORTRAIT_SECONDARY;
+        } else {
+            return ScreenOrientationValues.DEFAULT;
+        }
+    }
+
+    /**
+     * Returns the name of activity or activity alias in WebAPK which handles share intents, and
+     * the data about the handler.
+     */
+    private static Pair<String, ShareTarget> extractFirstShareTarget(String webApkPackageName) {
+        Intent shareIntent = new Intent();
+        shareIntent.setAction(Intent.ACTION_SEND);
+        shareIntent.setPackage(webApkPackageName);
+        shareIntent.setType("*/*");
+        List<ResolveInfo> resolveInfos =
+                ContextUtils.getApplicationContext().getPackageManager().queryIntentActivities(
+                        shareIntent, PackageManager.GET_META_DATA);
+
+        for (ResolveInfo resolveInfo : resolveInfos) {
+            Bundle shareTargetMetaData = resolveInfo.activityInfo.metaData;
+            if (shareTargetMetaData == null) {
+                continue;
+            }
+
+            String shareTargetActivityName = resolveInfo.activityInfo.name;
+
+            String shareAction =
+                    IntentUtils.safeGetString(shareTargetMetaData, WebApkMetaDataKeys.SHARE_ACTION);
+            if (TextUtils.isEmpty(shareAction)) {
+                return new Pair<>(null, new ShareTarget());
+            }
+
+            String encodedFileNames = IntentUtils.safeGetString(
+                    shareTargetMetaData, WebApkMetaDataKeys.SHARE_PARAM_NAMES);
+            String[] fileNames = WebApkShareTargetUtil.decodeJsonStringArray(encodedFileNames);
+
+            String encodedFileAccepts = IntentUtils.safeGetString(
+                    shareTargetMetaData, WebApkMetaDataKeys.SHARE_PARAM_ACCEPTS);
+            String[][] fileAccepts = WebApkShareTargetUtil.decodeJsonAccepts(encodedFileAccepts);
+
+            String shareMethod =
+                    IntentUtils.safeGetString(shareTargetMetaData, WebApkMetaDataKeys.SHARE_METHOD);
+            boolean isShareMethodPost =
+                    shareMethod != null && shareMethod.toUpperCase(Locale.ENGLISH).equals("POST");
+
+            String shareEncType = IntentUtils.safeGetString(
+                    shareTargetMetaData, WebApkMetaDataKeys.SHARE_ENCTYPE);
+            boolean isShareEncTypeMultipart = shareEncType != null
+                    && shareEncType.toLowerCase(Locale.ENGLISH).equals("multipart/form-data");
+
+            ShareTarget target = new ShareTarget(
+                    IntentUtils.safeGetString(shareTargetMetaData, WebApkMetaDataKeys.SHARE_ACTION),
+                    IntentUtils.safeGetString(
+                            shareTargetMetaData, WebApkMetaDataKeys.SHARE_PARAM_TITLE),
+                    IntentUtils.safeGetString(
+                            shareTargetMetaData, WebApkMetaDataKeys.SHARE_PARAM_TEXT),
+                    IntentUtils.safeGetString(
+                            shareTargetMetaData, WebApkMetaDataKeys.SHARE_PARAM_URL),
+                    isShareMethodPost, isShareEncTypeMultipart, fileNames, fileAccepts);
+
+            return new Pair<>(shareTargetActivityName, target);
+        }
+        return new Pair<>(null, new ShareTarget());
+    }
+
+    @Override
+    @Nullable
+    public WebappExtras getWebappExtras() {
+        return mWebappExtras;
+    }
+
+    @Override
+    @Nullable
+    public WebApkExtras getWebApkExtras() {
+        return mWebApkExtras;
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
index 37515d5..08624191 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
@@ -159,7 +159,7 @@
 
         super.onNewIntent(intent);
 
-        WebappInfo newWebappInfo = popWebappInfo(WebappInfo.idFromIntent(intent));
+        WebappInfo newWebappInfo = popWebappInfo(WebappIntentDataProvider.idFromIntent(intent));
         if (newWebappInfo == null) newWebappInfo = createWebappInfo(intent);
 
         if (newWebappInfo == null) {
@@ -263,7 +263,7 @@
     @Override
     public void performPreInflationStartup() {
         Intent intent = getIntent();
-        String id = WebappInfo.idFromIntent(intent);
+        String id = WebappIntentDataProvider.idFromIntent(intent);
         WebappInfo info = popWebappInfo(id);
         // When WebappActivity is killed by the Android OS, and an entry stays in "Android Recents"
         // (The user does not swipe it away), when WebappActivity is relaunched it is relaunched
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappExtras.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappExtras.java
new file mode 100644
index 0000000..2f78347
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappExtras.java
@@ -0,0 +1,119 @@
+// Copyright 2019 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.
+
+package org.chromium.chrome.browser.webapps;
+
+import android.graphics.Color;
+
+import org.chromium.blink_public.platform.WebDisplayMode;
+import org.chromium.chrome.browser.ShortcutSource;
+import org.chromium.content_public.common.ScreenOrientationValues;
+
+/**
+ * Stores webapp specific information on behalf of {@link BrowserServicesIntentDataProvider}.
+ */
+public class WebappExtras {
+    public final String id;
+
+    /**
+     * The URL to navigate to.
+     */
+    public final String url;
+
+    /**
+     * The navigation scope of the webapp's application context.
+     */
+    public final String scopeUrl;
+
+    /**
+     * The webapp's launcher icon.
+     */
+    public final WebappIcon icon;
+
+    /**
+     * The webapp's name as it is usually displayed to the user.
+     */
+    public final String name;
+
+    /**
+     * Short version of the webapp's name.
+     */
+    public final String shortName;
+
+    public final @WebDisplayMode int displayMode;
+
+    /**
+     * The screen orientation to lock the webapp to.
+     */
+    public final @ScreenOrientationValues int orientation;
+
+    /**
+     * If the webapp was launched from the home screen or the app list: source where the webapp was
+     * added from.
+     * Otherwise: reason that the webapp was launched (e.g. deep link).
+     */
+    public final @ShortcutSource int source;
+
+    /**
+     * Theme color of the webapp.
+     * TODO(pkotwicz): Remove this property in favor of
+     * {@link BrowserServicesIntentDataProvider#getToolbarColor()}
+     */
+    public final Integer themeColor;
+
+    /**
+     * Background color for webapp's splash screen.
+     */
+    public final Integer backgroundColor;
+
+    /**
+     * Background color to use if the Web Manifest does not provide a background color.
+     */
+    public final int defaultBackgroundColor;
+
+    /**
+     * Whether {@link icon} was generated by Chromium.
+     */
+    public final boolean isIconGenerated;
+
+    /**
+     * Whether {@link #icon} should be used as an Android Adaptive icon.
+     */
+    public final boolean isIconAdaptive;
+
+    /**
+     * Whether the webapp should be navigated to {@link #url} if the webapp is already open.
+     */
+    public final boolean shouldForceNavigation;
+
+    public static WebappExtras createEmpty() {
+        return new WebappExtras(null /* id */, null /* url */, null /* scopeUrl */,
+                new WebappIcon(), null /* name */, null /* shortName */, WebDisplayMode.UNDEFINED,
+                ScreenOrientationValues.DEFAULT, ShortcutSource.UNKNOWN, null /* themeColor */,
+                null /* backgroundColor */, Color.WHITE /* defaultBackgroundColor */,
+                false /* isIconGenerated */, false /* isIconAdaptive */,
+                false /* shouldForceNavigation */);
+    }
+
+    public WebappExtras(String id, String url, String scopeUrl, WebappIcon icon, String name,
+            String shortName, @WebDisplayMode int displayMode, int orientation, int source,
+            Integer themeColor, Integer backgroundColor, int defaultBackgroundColor,
+            boolean isIconGenerated, boolean isIconAdaptive, boolean shouldForceNavigation) {
+        this.id = id;
+        this.url = url;
+        this.scopeUrl = scopeUrl;
+        this.icon = icon;
+        this.name = name;
+        this.shortName = shortName;
+        this.displayMode = displayMode;
+        this.orientation = orientation;
+        this.source = source;
+        this.themeColor = themeColor;
+        this.backgroundColor = backgroundColor;
+        this.defaultBackgroundColor = defaultBackgroundColor;
+        this.isIconGenerated = isIconGenerated;
+        this.isIconAdaptive = isIconAdaptive;
+        this.shouldForceNavigation = shouldForceNavigation;
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappInfo.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappInfo.java
index f1a05251bd..3bb4b49 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappInfo.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappInfo.java
@@ -5,72 +5,21 @@
 package org.chromium.chrome.browser.webapps;
 
 import android.content.Intent;
-import android.text.TextUtils;
+import android.support.annotation.NonNull;
 
-import org.chromium.base.ContextUtils;
-import org.chromium.base.Log;
 import org.chromium.blink_public.platform.WebDisplayMode;
 import org.chromium.chrome.browser.ShortcutHelper;
 import org.chromium.chrome.browser.ShortcutSource;
-import org.chromium.chrome.browser.util.IntentUtils;
-import org.chromium.content_public.common.ScreenOrientationValues;
-import org.chromium.webapk.lib.common.splash.SplashLayout;
+import org.chromium.chrome.browser.browserservices.BrowserServicesIntentDataProvider;
 
 /**
  * Stores info about a web app.
  */
 public class WebappInfo {
-    private static final String TAG = "WebappInfo";
-
-    private String mId;
-    private WebappIcon mIcon;
-    private String mUrl;
-    private String mScopeUrl;
-    private String mName;
-    private String mShortName;
-    private @WebDisplayMode int mDisplayMode;
-    private int mOrientation;
-    private int mSource;
-    private long mThemeColor;
-    private long mBackgroundColor;
-    private int mDefaultBackgroundColor;
-    private boolean mIsIconGenerated;
-    private boolean mIsIconAdaptive;
-    private boolean mForceNavigation;
+    protected final BrowserServicesIntentDataProvider mProvider;
 
     public static WebappInfo createEmpty() {
-        return new WebappInfo();
-    }
-
-    protected static String urlFromIntent(Intent intent) {
-        return IntentUtils.safeGetStringExtra(intent, ShortcutHelper.EXTRA_URL);
-    }
-
-    protected static int sourceFromIntent(Intent intent) {
-        int source = IntentUtils.safeGetIntExtra(
-                intent, ShortcutHelper.EXTRA_SOURCE, ShortcutSource.UNKNOWN);
-        if (source >= ShortcutSource.COUNT) {
-            source = ShortcutSource.UNKNOWN;
-        }
-        return source;
-    }
-
-    private static String titleFromIntent(Intent intent) {
-        // The reference to title has been kept for reasons of backward compatibility. For intents
-        // and shortcuts which were created before we utilized the concept of name and shortName,
-        // we set the name and shortName to be the title.
-        String title = IntentUtils.safeGetStringExtra(intent, ShortcutHelper.EXTRA_TITLE);
-        return title == null ? "" : title;
-    }
-
-    private static String nameFromIntent(Intent intent) {
-        String name = IntentUtils.safeGetStringExtra(intent, ShortcutHelper.EXTRA_NAME);
-        return name == null ? titleFromIntent(intent) : name;
-    }
-
-    private static String shortNameFromIntent(Intent intent) {
-        String shortName = IntentUtils.safeGetStringExtra(intent, ShortcutHelper.EXTRA_SHORT_NAME);
-        return shortName == null ? titleFromIntent(intent) : shortName;
+        return new WebappInfo(WebappIntentDataProvider.createEmpty());
     }
 
     /**
@@ -78,96 +27,20 @@
      * @param intent Intent containing info about the app.
      */
     public static WebappInfo create(Intent intent) {
-        String id = idFromIntent(intent);
-        String url = urlFromIntent(intent);
-        if (id == null || url == null) {
-            Log.e(TAG, "Incomplete data provided: " + id + ", " + url);
-            return null;
-        }
-
-        String icon = IntentUtils.safeGetStringExtra(intent, ShortcutHelper.EXTRA_ICON);
-        String scope = IntentUtils.safeGetStringExtra(intent, ShortcutHelper.EXTRA_SCOPE);
-        @WebDisplayMode
-        int displayMode = IntentUtils.safeGetIntExtra(
-                intent, ShortcutHelper.EXTRA_DISPLAY_MODE, WebDisplayMode.STANDALONE);
-        int orientation = IntentUtils.safeGetIntExtra(
-                intent, ShortcutHelper.EXTRA_ORIENTATION, ScreenOrientationValues.DEFAULT);
-        int source = sourceFromIntent(intent);
-        long themeColor = IntentUtils.safeGetLongExtra(intent,
-                ShortcutHelper.EXTRA_THEME_COLOR,
-                ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING);
-        long backgroundColor = IntentUtils.safeGetLongExtra(intent,
-                ShortcutHelper.EXTRA_BACKGROUND_COLOR,
-                ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING);
-        boolean isIconGenerated = IntentUtils.safeGetBooleanExtra(intent,
-                ShortcutHelper.EXTRA_IS_ICON_GENERATED, false);
-        boolean isIconAdaptive = IntentUtils.safeGetBooleanExtra(intent,
-                ShortcutHelper.EXTRA_IS_ICON_ADAPTIVE, false);
-        boolean forceNavigation = IntentUtils.safeGetBooleanExtra(
-                intent, ShortcutHelper.EXTRA_FORCE_NAVIGATION, false);
-
-        String name = nameFromIntent(intent);
-        String shortName = shortNameFromIntent(intent);
-
-        int defaultBackgroundColor =
-                SplashLayout.getDefaultBackgroundColor(ContextUtils.getApplicationContext());
-        return new WebappInfo(id, url, scope, new WebappIcon(icon), name, shortName, displayMode,
-                orientation, source, themeColor, backgroundColor, defaultBackgroundColor,
-                isIconGenerated, isIconAdaptive, forceNavigation);
+        WebappIntentDataProvider provider = WebappIntentDataProvider.create(intent);
+        return (provider == null) ? null : new WebappInfo(provider);
     }
 
-    /**
-     * Construct a WebappInfo.
-     * @param id              ID for the webapp.
-     * @param url             URL for the webapp.
-     * @param scope           Scope for the webapp.
-     * @param icon            Icon to show for the webapp.
-     * @param name            Name of the webapp.
-     * @param shortName       The short name of the webapp.
-     * @param displayMode     Display mode of the webapp.
-     * @param orientation     Orientation of the webapp.
-     * @param source          Source where the webapp was added from.
-     * @param themeColor      The theme color of the webapp.
-     * @param backgroundColor The background color of the webapp.
-     * @param isIconGenerated Whether the |icon| was generated by Chromium.
-     * @param isIconAdaptive  Whether the Icon is an Android Adaptive Icon.
-     * @param forceNavigation Whether the webapp should navigate to {@link url} if the
-     *                        webapp is already open.
-     */
-    protected WebappInfo(String id, String url, String scope, WebappIcon icon, String name,
-            String shortName, @WebDisplayMode int displayMode, int orientation, int source,
-            long themeColor, long backgroundColor, int defaultBackgroundColor,
-            boolean isIconGenerated, boolean isIconAdaptive, boolean forceNavigation) {
-        if (TextUtils.isEmpty(scope)) {
-            scope = ShortcutHelper.getScopeFromUrl(url);
-        }
-
-        mIcon = (icon != null) ? icon : new WebappIcon();
-        mId = id;
-        mName = name;
-        mShortName = shortName;
-        mUrl = url;
-        mScopeUrl = scope;
-        mDisplayMode = displayMode;
-        mOrientation = orientation;
-        mSource = source;
-        mThemeColor = themeColor;
-        mBackgroundColor = backgroundColor;
-        mDefaultBackgroundColor = defaultBackgroundColor;
-        mIsIconGenerated = isIconGenerated;
-        mIsIconAdaptive = isIconAdaptive;
-        mForceNavigation = forceNavigation;
-    }
-
-    protected WebappInfo() {
+    protected WebappInfo(@NonNull BrowserServicesIntentDataProvider provider) {
+        mProvider = provider;
     }
 
     public String id() {
-        return mId;
+        return getWebappExtras().id;
     }
 
     public String url() {
-        return mUrl;
+        return getWebappExtras().url;
     }
 
     /**
@@ -175,25 +48,23 @@
      * Chrome receives a ACTION_START_WEBAPP intent.
      */
     public boolean shouldForceNavigation() {
-        return mForceNavigation;
+        return getWebappExtras().shouldForceNavigation;
     }
 
-    // TODO(yusufo) : Plumb the scope for the Webapp through the support library/client Android
-    // manifest for TrustedWebActivity.
     public String scopeUrl() {
-        return mScopeUrl;
+        return getWebappExtras().scopeUrl;
     }
 
     public String name() {
-        return mName;
+        return getWebappExtras().name;
     }
 
     public String shortName() {
-        return mShortName;
+        return getWebappExtras().shortName;
     }
 
     public @WebDisplayMode int displayMode() {
-        return mDisplayMode;
+        return getWebappExtras().displayMode;
     }
 
     public boolean isForWebApk() {
@@ -205,11 +76,11 @@
     }
 
     public int orientation() {
-        return mOrientation;
+        return getWebappExtras().orientation;
     }
 
     public int source() {
-        return mSource;
+        return getWebappExtras().source;
     }
 
     /**
@@ -218,15 +89,14 @@
      * error state of ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING.
      */
     public long themeColor() {
-        return mThemeColor;
+        return WebappIntentDataProvider.longColorFromIntegerColor(getWebappExtras().themeColor);
     }
 
     /**
      * Returns whether the theme color specified in the Intent is valid.
-     * A theme color isn't valid if its value is ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING;
      */
     public boolean hasValidThemeColor() {
-        return mThemeColor != ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING;
+        return getWebappExtras().themeColor != null;
     }
 
     /**
@@ -235,16 +105,15 @@
      * error state of ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING.
      */
     public long backgroundColor() {
-        return mBackgroundColor;
+        return WebappIntentDataProvider.longColorFromIntegerColor(
+                getWebappExtras().backgroundColor);
     }
 
     /**
      * Returns whether the background color specified in the Intent is valid.
-     * A background color isn't valid if its value is
-     * ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING.
      */
     public boolean hasValidBackgroundColor() {
-        return mBackgroundColor != ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING;
+        return getWebappExtras().backgroundColor != null;
     }
 
     /**
@@ -252,28 +121,30 @@
      * the value is valid. Returns the webapp's default background color otherwise.
      */
     public int backgroundColorFallbackToDefault() {
-        return hasValidBackgroundColor() ? (int) mBackgroundColor : mDefaultBackgroundColor;
+        Integer backgroundColor = getWebappExtras().backgroundColor;
+        return (backgroundColor == null) ? getWebappExtras().defaultBackgroundColor
+                                         : backgroundColor.intValue();
     }
 
     /**
      * Returns the icon.
      */
     public WebappIcon icon() {
-        return mIcon;
+        return getWebappExtras().icon;
     }
 
     /**
      * Returns whether the {@link #icon} should be used as an Android Adaptive Icon.
      */
     public boolean isIconAdaptive() {
-        return mIsIconAdaptive;
+        return getWebappExtras().isIconAdaptive;
     }
 
     /**
      * Returns whether the icon was generated by Chromium.
      */
     public boolean isIconGenerated() {
-        return mIsIconGenerated;
+        return getWebappExtras().isIconGenerated;
     }
 
     /**
@@ -306,9 +177,6 @@
         intent.putExtra(ShortcutHelper.EXTRA_IS_ICON_ADAPTIVE, isIconAdaptive());
     }
 
-    public static String idFromIntent(Intent intent) {
-        return IntentUtils.safeGetStringExtra(intent, ShortcutHelper.EXTRA_ID);
-    }
     /**
      * Returns true if the WebappInfo was created for an Intent fired from a launcher shortcut (as
      * opposed to an intent from a push notification or other internal source).
@@ -320,4 +188,10 @@
                 && source != ShortcutSource.WEBAPK_SHARE_TARGET
                 && source != ShortcutSource.WEBAPK_SHARE_TARGET_FILE;
     }
+
+    private WebappExtras getWebappExtras() {
+        WebappExtras extras = mProvider.getWebappExtras();
+        assert extras != null;
+        return extras;
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappIntentDataProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappIntentDataProvider.java
new file mode 100644
index 0000000..42ecfdbb
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappIntentDataProvider.java
@@ -0,0 +1,147 @@
+// Copyright 2019 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.
+
+package org.chromium.chrome.browser.webapps;
+
+import android.content.Intent;
+import android.support.annotation.Nullable;
+import android.text.TextUtils;
+
+import org.chromium.base.ContextUtils;
+import org.chromium.base.Log;
+import org.chromium.blink_public.platform.WebDisplayMode;
+import org.chromium.chrome.browser.ShortcutHelper;
+import org.chromium.chrome.browser.ShortcutSource;
+import org.chromium.chrome.browser.browserservices.BrowserServicesIntentDataProvider;
+import org.chromium.chrome.browser.util.IntentUtils;
+import org.chromium.content_public.common.ScreenOrientationValues;
+import org.chromium.webapk.lib.common.splash.SplashLayout;
+
+/**
+ * Stores info about a web app.
+ */
+public class WebappIntentDataProvider extends BrowserServicesIntentDataProvider {
+    private static final String TAG = "WebappInfo";
+
+    private WebappExtras mWebappExtras;
+
+    public static WebappIntentDataProvider createEmpty() {
+        return new WebappIntentDataProvider(WebappExtras.createEmpty());
+    }
+
+    /**
+     * Converts color from signed Integer where an unspecified color is represented as null to
+     * to unsigned long where an unspecified color is represented as
+     * {@link ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING}.
+     */
+    public static long longColorFromIntegerColor(Integer color) {
+        if (color != null) {
+            // Convert signed int to unsigned long.
+            return (color.intValue() & 0xffffffffL);
+        }
+        return ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING;
+    }
+
+    /**
+     * Converts color from unsigned long where an unspecified color is represented as
+     * {@link ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING} to a signed Integer where an
+     * unspecified color is represented as null.
+     */
+    public static Integer integerColorFromLongColor(long longColor) {
+        return (longColor == ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING)
+                ? null
+                : Integer.valueOf((int) longColor);
+    }
+
+    public static String idFromIntent(Intent intent) {
+        return IntentUtils.safeGetStringExtra(intent, ShortcutHelper.EXTRA_ID);
+    }
+
+    private static int sourceFromIntent(Intent intent) {
+        int source = IntentUtils.safeGetIntExtra(
+                intent, ShortcutHelper.EXTRA_SOURCE, ShortcutSource.UNKNOWN);
+        if (source >= ShortcutSource.COUNT) {
+            source = ShortcutSource.UNKNOWN;
+        }
+        return source;
+    }
+
+    private static String titleFromIntent(Intent intent) {
+        // The reference to title has been kept for reasons of backward compatibility. For intents
+        // and shortcuts which were created before we utilized the concept of name and shortName,
+        // we set the name and shortName to be the title.
+        String title = IntentUtils.safeGetStringExtra(intent, ShortcutHelper.EXTRA_TITLE);
+        return title == null ? "" : title;
+    }
+
+    private static String nameFromIntent(Intent intent) {
+        String name = IntentUtils.safeGetStringExtra(intent, ShortcutHelper.EXTRA_NAME);
+        return name == null ? titleFromIntent(intent) : name;
+    }
+
+    private static String shortNameFromIntent(Intent intent) {
+        String shortName = IntentUtils.safeGetStringExtra(intent, ShortcutHelper.EXTRA_SHORT_NAME);
+        return shortName == null ? titleFromIntent(intent) : shortName;
+    }
+
+    /**
+     * Construct a WebappIntentDataProvider.
+     * @param intent Intent containing info about the app.
+     */
+    public static WebappIntentDataProvider create(Intent intent) {
+        String id = idFromIntent(intent);
+        String url = IntentUtils.safeGetStringExtra(intent, ShortcutHelper.EXTRA_URL);
+        if (id == null || url == null) {
+            Log.e(TAG, "Incomplete data provided: " + id + ", " + url);
+            return null;
+        }
+
+        String icon = IntentUtils.safeGetStringExtra(intent, ShortcutHelper.EXTRA_ICON);
+
+        String scope = IntentUtils.safeGetStringExtra(intent, ShortcutHelper.EXTRA_SCOPE);
+        if (TextUtils.isEmpty(scope)) {
+            scope = ShortcutHelper.getScopeFromUrl(url);
+        }
+
+        @WebDisplayMode
+        int displayMode = IntentUtils.safeGetIntExtra(
+                intent, ShortcutHelper.EXTRA_DISPLAY_MODE, WebDisplayMode.STANDALONE);
+        int orientation = IntentUtils.safeGetIntExtra(
+                intent, ShortcutHelper.EXTRA_ORIENTATION, ScreenOrientationValues.DEFAULT);
+        int source = sourceFromIntent(intent);
+        Integer themeColor = integerColorFromLongColor(
+                IntentUtils.safeGetLongExtra(intent, ShortcutHelper.EXTRA_THEME_COLOR,
+                        ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING));
+        Integer backgroundColor = integerColorFromLongColor(
+                IntentUtils.safeGetLongExtra(intent, ShortcutHelper.EXTRA_BACKGROUND_COLOR,
+                        ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING));
+        boolean isIconGenerated = IntentUtils.safeGetBooleanExtra(
+                intent, ShortcutHelper.EXTRA_IS_ICON_GENERATED, false);
+        boolean isIconAdaptive = IntentUtils.safeGetBooleanExtra(
+                intent, ShortcutHelper.EXTRA_IS_ICON_ADAPTIVE, false);
+        boolean forceNavigation = IntentUtils.safeGetBooleanExtra(
+                intent, ShortcutHelper.EXTRA_FORCE_NAVIGATION, false);
+
+        String name = nameFromIntent(intent);
+        String shortName = shortNameFromIntent(intent);
+
+        int defaultBackgroundColor =
+                SplashLayout.getDefaultBackgroundColor(ContextUtils.getApplicationContext());
+
+        WebappExtras webappExtras = new WebappExtras(id, url, scope, new WebappIcon(icon), name,
+                shortName, displayMode, orientation, source, themeColor, backgroundColor,
+                defaultBackgroundColor, isIconGenerated, isIconAdaptive, forceNavigation);
+        return new WebappIntentDataProvider(webappExtras);
+    }
+
+    private WebappIntentDataProvider(WebappExtras webappExtras) {
+        mWebappExtras = webappExtras;
+    }
+
+    @Override
+    @Nullable
+    public WebappExtras getWebappExtras() {
+        return mWebappExtras;
+    }
+}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkInfoTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkInfoTest.java
index 9bc7bba..6f527e611 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkInfoTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkInfoTest.java
@@ -370,10 +370,10 @@
         String name = "WebAPK name";
         String shortName = "WebAPK short name";
         FakeResources res = new FakeResources();
-        res.addStringForTesting(WebApkInfo.RESOURCE_NAME, WebApkInfo.RESOURCE_STRING_TYPE,
-                WEBAPK_PACKAGE_NAME, 1, name);
-        res.addStringForTesting(WebApkInfo.RESOURCE_SHORT_NAME, WebApkInfo.RESOURCE_STRING_TYPE,
-                WEBAPK_PACKAGE_NAME, 2, shortName);
+        res.addStringForTesting(WebApkIntentDataProvider.RESOURCE_NAME,
+                WebApkIntentDataProvider.RESOURCE_STRING_TYPE, WEBAPK_PACKAGE_NAME, 1, name);
+        res.addStringForTesting(WebApkIntentDataProvider.RESOURCE_SHORT_NAME,
+                WebApkIntentDataProvider.RESOURCE_STRING_TYPE, WEBAPK_PACKAGE_NAME, 2, shortName);
         WebApkTestHelper.setResource(WEBAPK_PACKAGE_NAME, res);
 
         Intent intent = new Intent();
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerUnitTest.java
index 0f7e6b4..598d3d2a01b 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerUnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerUnitTest.java
@@ -896,6 +896,17 @@
         assertTrue(checkUpdateNeededForFetchedManifest(fetchedV1ShareTarget, oldNoShareTarget));
     }
 
+    /** Test that an upgrade is requested when the Web Manifest 'scope' changes. */
+    @Test
+    public void testManifestScopeChangedShouldUpgrade() {
+        ManifestData oldData = defaultManifestData();
+        // webapk_installer.cc sets the scope to the default scope if the scope is empty.
+        oldData.scopeUrl = "/scope1/";
+        ManifestData fetchedData = defaultManifestData();
+        fetchedData.scopeUrl = "/scope2/";
+        assertTrue(checkUpdateNeededForFetchedManifest(oldData, fetchedData));
+    }
+
     /**
      * Test that an upgrade is not requested when the Web Manifest did not change and the Web
      * Manifest scope is empty.
@@ -1039,6 +1050,62 @@
         assertFalse(checkUpdateNeededForFetchedManifest(androidManifestData, fetchedManifestData));
     }
 
+    /** Test that an upgrade is requested when the Web Manifest 'short_name' changes. */
+    @Test
+    public void testManifestShortNameChangedShouldUpgrade() {
+        ManifestData fetchedData = defaultManifestData();
+        fetchedData.shortName = SHORT_NAME + "2";
+        assertTrue(checkUpdateNeededForFetchedManifest(defaultManifestData(), fetchedData));
+    }
+
+    /** Test that an upgrade is requested when the Web Manifest 'name' changes. */
+    @Test
+    public void testManifestNameChangedShouldUpgrade() {
+        ManifestData fetchedData = defaultManifestData();
+        fetchedData.name = NAME + "2";
+        assertTrue(checkUpdateNeededForFetchedManifest(defaultManifestData(), fetchedData));
+    }
+
+    /** Test that an upgrade is requested when the Web Manifest 'display' changes. */
+    @Test
+    public void testManifestDisplayModeChangedShouldUpgrade() {
+        ManifestData oldData = defaultManifestData();
+        oldData.displayMode = WebDisplayMode.STANDALONE;
+        ManifestData fetchedData = defaultManifestData();
+        fetchedData.displayMode = WebDisplayMode.FULLSCREEN;
+        assertTrue(checkUpdateNeededForFetchedManifest(oldData, fetchedData));
+    }
+
+    /** Test that an upgrade is requested when the Web Manifest 'orientation' changes. */
+    @Test
+    public void testManifestOrientationChangedShouldUpgrade() {
+        ManifestData oldData = defaultManifestData();
+        oldData.orientation = ScreenOrientationValues.LANDSCAPE;
+        ManifestData fetchedData = defaultManifestData();
+        fetchedData.orientation = ScreenOrientationValues.PORTRAIT;
+        assertTrue(checkUpdateNeededForFetchedManifest(oldData, fetchedData));
+    }
+
+    /** Test that an upgrade is requested when the Web Manifest 'theme_color' changes. */
+    @Test
+    public void testManifestThemeColorChangedShouldUpgrade() {
+        ManifestData oldData = defaultManifestData();
+        oldData.themeColor = 1L;
+        ManifestData fetchedData = defaultManifestData();
+        fetchedData.themeColor = 2L;
+        assertTrue(checkUpdateNeededForFetchedManifest(oldData, fetchedData));
+    }
+
+    /** Test that an upgrade is requested when the Web Manifest 'background_color' changes. */
+    @Test
+    public void testManifestBackgroundColorChangedShouldUpgrade() {
+        ManifestData oldData = defaultManifestData();
+        oldData.backgroundColor = 1L;
+        ManifestData fetchedData = defaultManifestData();
+        fetchedData.backgroundColor = 2L;
+        assertTrue(checkUpdateNeededForFetchedManifest(oldData, fetchedData));
+    }
+
     /**
      * Test that an upgrade is not requested if the AndroidManifest does not have a valid background
      * color and the default background color in the WebAPK's resources is different than
@@ -1046,7 +1113,7 @@
      * {@link SplashLayout#getDefaultBackgroundColor()} in a new Chrome version).
      */
     @Test
-    public void testDefaultBackgroundColorHasChangedShouldUpgrade() {
+    public void testDefaultBackgroundColorHasChangedShouldNotUpgrade() {
         int oldDefaultBackgroundColor = 3;
         int splashLayoutDefaultBackgroundColor =
                 SplashLayout.getDefaultBackgroundColor(RuntimeEnvironment.application);
@@ -1063,6 +1130,16 @@
         assertFalse(checkUpdateNeededForFetchedManifest(androidManifestData, fetchedManifestData));
     }
 
+    /** Test that an upgrade is requested when the Web Manifest 'start_url' changes. */
+    @Test
+    public void testManifestStartUrlChangedShouldUpgrade() {
+        ManifestData oldData = defaultManifestData();
+        oldData.startUrl = "/old_start_url.html";
+        ManifestData fetchedData = defaultManifestData();
+        fetchedData.startUrl = "/new_start_url.html";
+        assertTrue(checkUpdateNeededForFetchedManifest(oldData, fetchedData));
+    }
+
     /**
      * Tests that a WebAPK update is requested immediately if:
      * the Shell APK is out of date,
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index a3560e87..76e0c76 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -2946,6 +2946,10 @@
       sources += [
         "android/dev_ui/dev_ui_module_provider.cc",
         "android/dev_ui/dev_ui_module_provider.h",
+        "ui/webui/android/dev_ui_loader/dev_ui_loader_message_handler.cc",
+        "ui/webui/android/dev_ui_loader/dev_ui_loader_message_handler.h",
+        "ui/webui/android/dev_ui_loader/dev_ui_loader_ui.cc",
+        "ui/webui/android/dev_ui_loader/dev_ui_loader_ui.h",
       ]
       deps += [ "//chrome/android/modules/dev_ui/provider:jni_headers" ]
     }
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd
index fb00d41..b8974c32 100644
--- a/chrome/browser/browser_resources.grd
+++ b/chrome/browser/browser_resources.grd
@@ -187,6 +187,7 @@
         <include name="IDR_SNIPPETS_INTERNALS_CSS" file="resources\snippets_internals\snippets_internals.css" compress="gzip" type="BINDATA" />
         <include name="IDR_SNIPPETS_INTERNALS_JS" file="resources\snippets_internals\snippets_internals.js" compress="gzip" type="BINDATA" />
         <include name="IDR_SNIPPETS_INTERNALS_MOJOM_LITE_JS" file="${root_gen_dir}\chrome\browser\ui\webui\snippets_internals\snippets_internals.mojom-lite.js" use_base_dir="false" type="BINDATA" compress="gzip" />
+        <part file="resources/dev_ui_loader/dev_ui_loader.grdp" />
       </if>
 
       <if expr="enable_supervised_users">
diff --git a/chrome/browser/extensions/api/web_request/web_request_apitest.cc b/chrome/browser/extensions/api/web_request/web_request_apitest.cc
index 6c950b9..a908dfec55 100644
--- a/chrome/browser/extensions/api/web_request/web_request_apitest.cc
+++ b/chrome/browser/extensions/api/web_request/web_request_apitest.cc
@@ -2527,10 +2527,7 @@
 
 // An extension should be able to modify the request header for service worker
 // script by using WebRequest API.
-//
-// Disabled due to https://crbug.com/995763.
-IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
-                       DISABLED_ServiceWorkerScript) {
+IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, ServiceWorkerScript) {
   // The extension to be used in this test adds foo=bar request header.
   const char kScriptPath[] = "/echoheader_service_worker.js";
   int served_service_worker_count = 0;
diff --git a/chrome/browser/lookalikes/safety_tips/reputation_service.cc b/chrome/browser/lookalikes/safety_tips/reputation_service.cc
index 0d3b9d9..172667c 100644
--- a/chrome/browser/lookalikes/safety_tips/reputation_service.cc
+++ b/chrome/browser/lookalikes/safety_tips/reputation_service.cc
@@ -202,6 +202,8 @@
                              engaged_domain.domain_and_registry);
                    });
   if (already_engaged != engaged_sites.end()) {
+    std::move(callback).Run(security_state::SafetyTipStatus::kNone,
+                            IsIgnored(url), url);
     return;
   }
 
@@ -216,6 +218,8 @@
   // Empty domain_and_registry happens on private domains.
   if (navigated_domain.domain_and_registry.empty() ||
       lookalikes::IsTopDomain(navigated_domain)) {
+    std::move(callback).Run(security_state::SafetyTipStatus::kNone,
+                            IsIgnored(url), url);
     return;
   }
 
@@ -228,6 +232,8 @@
   }
 
   // TODO(crbug/984725): 5. Additional client-side heuristics
+  std::move(callback).Run(security_state::SafetyTipStatus::kNone,
+                          IsIgnored(url), url);
 }
 
 security_state::SafetyTipStatus GetUrlBlockType(const GURL& url) {
diff --git a/chrome/browser/lookalikes/safety_tips/reputation_service.h b/chrome/browser/lookalikes/safety_tips/reputation_service.h
index af4d9df..4ae6a6b8 100644
--- a/chrome/browser/lookalikes/safety_tips/reputation_service.h
+++ b/chrome/browser/lookalikes/safety_tips/reputation_service.h
@@ -37,7 +37,10 @@
 
   // Calculate the overall reputation status of the given URL, and
   // asynchronously call |callback| with the results. See
-  // ReputationCheckCallback above for details on what's returned.
+  // ReputationCheckCallback above for details on what's returned. |callback|
+  // will be called regardless of whether |url| is flagged or
+  // not. (Specifically, |callback| will be called with SafetyTipStatus::kNone
+  // if the url is not flagged).
   void GetReputationStatus(const GURL& url, ReputationCheckCallback callback);
 
   // Tells the service that the user has explicitly ignored the warning.
diff --git a/chrome/browser/lookalikes/safety_tips/reputation_web_contents_observer.cc b/chrome/browser/lookalikes/safety_tips/reputation_web_contents_observer.cc
index dccf3b3..95d4621 100644
--- a/chrome/browser/lookalikes/safety_tips/reputation_web_contents_observer.cc
+++ b/chrome/browser/lookalikes/safety_tips/reputation_web_contents_observer.cc
@@ -43,6 +43,11 @@
              : security_state::SafetyTipStatus::kNone;
 }
 
+void ReputationWebContentsObserver::RegisterReputationCheckCallbackForTesting(
+    base::OnceClosure callback) {
+  reputation_check_callback_for_testing_ = std::move(callback);
+}
+
 ReputationWebContentsObserver::ReputationWebContentsObserver(
     content::WebContents* web_contents)
     : WebContentsObserver(web_contents),
@@ -72,12 +77,14 @@
     bool user_ignored,
     const GURL& url) {
   if (safety_tip_status == security_state::SafetyTipStatus::kNone) {
+    MaybeCallReputationCheckCallback();
     return;
   }
 
   // TODO(crbug/987754): Record metrics here.
 
   if (user_ignored) {
+    MaybeCallReputationCheckCallback();
     return;
   }
   // Set this field independent of whether the feature to show the UI is
@@ -89,12 +96,20 @@
   last_safety_tip_navigation_entry_id_ =
       web_contents()->GetController().GetLastCommittedEntry()->GetUniqueID();
 
+  MaybeCallReputationCheckCallback();
+
   if (!base::FeatureList::IsEnabled(features::kSafetyTipUI)) {
     return;
   }
   ShowSafetyTipDialog(web_contents(), safety_tip_status, url);
 }
 
+void ReputationWebContentsObserver::MaybeCallReputationCheckCallback() {
+  if (reputation_check_callback_for_testing_.is_null())
+    return;
+  std::move(reputation_check_callback_for_testing_).Run();
+}
+
 WEB_CONTENTS_USER_DATA_KEY_IMPL(ReputationWebContentsObserver)
 
 }  // namespace safety_tips
diff --git a/chrome/browser/lookalikes/safety_tips/reputation_web_contents_observer.h b/chrome/browser/lookalikes/safety_tips/reputation_web_contents_observer.h
index 2af4abb5..f2adca9 100644
--- a/chrome/browser/lookalikes/safety_tips/reputation_web_contents_observer.h
+++ b/chrome/browser/lookalikes/safety_tips/reputation_web_contents_observer.h
@@ -7,6 +7,7 @@
 
 #include <set>
 
+#include "base/callback_forward.h"
 #include "chrome/browser/lookalikes/safety_tips/reputation_service.h"
 #include "chrome/browser/lookalikes/safety_tips/safety_tip_ui.h"
 #include "components/security_state/core/security_state.h"
@@ -41,6 +42,10 @@
   security_state::SafetyTipStatus GetSafetyTipStatusForVisibleNavigation()
       const;
 
+  // Allows tests to register a callback to be called when the next reputation
+  // check finishes.
+  void RegisterReputationCheckCallbackForTesting(base::OnceClosure callback);
+
  private:
   friend class content::WebContentsUserData<ReputationWebContentsObserver>;
 
@@ -56,6 +61,10 @@
       bool user_ignored,
       const GURL& url);
 
+  // A helper method that calls and resets
+  // |reputation_check_callback_for_testing_| if it is set.
+  void MaybeCallReputationCheckCallback();
+
   Profile* profile_;
   // Used to cache the last safety tip type (and associated navigation entry ID)
   // so that Page Info can fetch this information without performing a
@@ -65,6 +74,8 @@
       security_state::SafetyTipStatus::kNone;
   int last_safety_tip_navigation_entry_id_ = 0;
 
+  base::OnceClosure reputation_check_callback_for_testing_;
+
   base::WeakPtrFactory<ReputationWebContentsObserver> weak_factory_{this};
   WEB_CONTENTS_USER_DATA_KEY_DECL();
 };
diff --git a/chrome/browser/navigation_predictor/navigation_predictor.cc b/chrome/browser/navigation_predictor/navigation_predictor.cc
index cd94d91..beb646421 100644
--- a/chrome/browser/navigation_predictor/navigation_predictor.cc
+++ b/chrome/browser/navigation_predictor/navigation_predictor.cc
@@ -963,7 +963,8 @@
   // TODO(chelu): https://crbug.com/850624/. Experiment with other heuristic
   // algorithms for computing the anchor elements score.
   double score =
-      (ratio_area_scale_ * (metrics.ratio_area * 100.0)) +
+      (ratio_area_scale_ * GetLinearBucketForRatioArea(
+                               static_cast<int>(metrics.ratio_area * 100.0))) +
       (metrics.is_in_iframe ? is_in_iframe_scale_ : 0.0) +
       (metrics.contains_image ? contains_image_scale_ : 0.0) + host_score +
       (metrics.is_url_incremented_by_one ? is_url_incremented_scale_ : 0.0) +
@@ -971,7 +972,8 @@
       (target_engagement_score_scale_ * target_engagement_score) +
       (area_rank_scale_ * area_rank_score) +
       (ratio_distance_root_top_scale_ *
-       (metrics.ratio_distance_root_top * 100.0));
+       GetLinearBucketForLinkLocation(
+           static_cast<int>(metrics.ratio_distance_root_top * 100.0)));
 
   if (normalize_navigation_scores_) {
     score = score / sum_link_scales_ * 100.0;
@@ -986,15 +988,24 @@
     return 0;
   } else {
     DCHECK(!viewport_size_.IsEmpty());
-    return (link_total_scale_ * number_of_anchors_) +
-           (iframe_link_total_scale_ * number_of_anchors_in_iframe_) +
-           (increment_link_total_scale_ * number_of_anchors_url_incremented_) +
-           (same_origin_link_total_scale_ * number_of_anchors_same_host_) +
-           (image_link_total_scale_ * number_of_anchors_contains_image_) +
-           (clickable_space_scale_ * total_clickable_space_) +
-           (median_link_location_scale_ * median_link_location_) +
-           (viewport_width_scale_ * viewport_size_.width()) +
-           (viewport_height_scale_ * viewport_size_.height());
+    return (link_total_scale_ *
+            GetBucketMinForPageMetrics(number_of_anchors_)) +
+           (iframe_link_total_scale_ *
+            GetBucketMinForPageMetrics(number_of_anchors_in_iframe_)) +
+           (increment_link_total_scale_ *
+            GetBucketMinForPageMetrics(number_of_anchors_url_incremented_)) +
+           (same_origin_link_total_scale_ *
+            GetBucketMinForPageMetrics(number_of_anchors_same_host_)) +
+           (image_link_total_scale_ *
+            GetBucketMinForPageMetrics(number_of_anchors_contains_image_)) +
+           (clickable_space_scale_ *
+            GetBucketMinForPageMetrics(total_clickable_space_)) +
+           (median_link_location_scale_ *
+            GetLinearBucketForLinkLocation(median_link_location_)) +
+           (viewport_width_scale_ *
+            GetBucketMinForPageMetrics(viewport_size_.width())) +
+           (viewport_height_scale_ *
+            GetBucketMinForPageMetrics(viewport_size_.height()));
   }
 }
 
diff --git a/chrome/browser/notifications/scheduler/internal/scheduler_utils.cc b/chrome/browser/notifications/scheduler/internal/scheduler_utils.cc
index f9f86f3..ed484f0 100644
--- a/chrome/browser/notifications/scheduler/internal/scheduler_utils.cc
+++ b/chrome/browser/notifications/scheduler/internal/scheduler_utils.cc
@@ -4,9 +4,7 @@
 
 #include "chrome/browser/notifications/scheduler/internal/scheduler_utils.h"
 
-#include <algorithm>
 #include <utility>
-#include <vector>
 
 #include "base/containers/circular_deque.h"
 #include "base/task/post_task.h"
@@ -16,35 +14,6 @@
 #include "ui/gfx/codec/png_codec.h"
 
 namespace notifications {
-namespace {
-
-using FirstAndLastIters =
-    std::pair<base::circular_deque<Impression>::const_iterator,
-              base::circular_deque<Impression>::const_iterator>;
-
-base::Optional<FirstAndLastIters> FindFirstAndLastNotificationShownToday(
-    const base::circular_deque<Impression>& impressions,
-    const base::Time& now,
-    const base::Time& beginning_of_today) {
-  if (impressions.empty() || impressions.cbegin()->create_time > now ||
-      impressions.crbegin()->create_time < beginning_of_today)
-    return base::nullopt;
-
-  auto last =
-      std::upper_bound(impressions.cbegin(), impressions.cend(), now,
-                       [](const base::Time& lhs, const Impression& rhs) {
-                         return lhs < rhs.create_time;
-                       });
-
-  auto first =
-      std::lower_bound(impressions.cbegin(), last, beginning_of_today,
-                       [](const Impression& lhs, const base::Time& rhs) {
-                         return lhs.create_time < rhs;
-                       });
-  return base::make_optional<FirstAndLastIters>(first, last - 1);
-}
-
-}  // namespace
 
 bool ToLocalHour(int hour,
                  const base::Time& today,
@@ -84,30 +53,24 @@
     int* shown_total,
     SchedulerClientType* last_shown_type,
     base::Clock* clock) {
-  base::Time last_shown_time;
   base::Time now = clock->Now();
   base::Time beginning_of_today;
   bool success = ToLocalHour(0, now, 0, &beginning_of_today);
+  base::Time last_shown_time = beginning_of_today;
   DCHECK(success);
   for (const auto& state : client_states) {
     auto* client_state = state.second;
-
-    auto iter_pair = FindFirstAndLastNotificationShownToday(
-        client_state->impressions, now, beginning_of_today);
-
-    if (!iter_pair)
-      continue;
-
-    if (iter_pair->second != client_state->impressions.cend())
-      DLOG(ERROR) << "Wrong format: time stamped to the future! "
-                  << iter_pair->second->create_time;
-
-    if (iter_pair->second->create_time > last_shown_time) {
-      last_shown_time = iter_pair->second->create_time;
-      *last_shown_type = client_state->type;
+    int count = 0;
+    for (const auto& impression : client_state->impressions) {
+      if (impression.create_time >= beginning_of_today &&
+          impression.create_time <= now) {
+        count++;
+        if (impression.create_time >= last_shown_time) {
+          last_shown_time = impression.create_time;
+          *last_shown_type = client_state->type;
+        }
+      }
     }
-
-    int count = std::distance(iter_pair->first, iter_pair->second) + 1;
     (*shown_per_type)[client_state->type] = count;
     (*shown_total) += count;
   }
diff --git a/chrome/browser/notifications/scheduler/internal/scheduler_utils_unittest.cc b/chrome/browser/notifications/scheduler/internal/scheduler_utils_unittest.cc
index 4522f42..950f9f35 100644
--- a/chrome/browser/notifications/scheduler/internal/scheduler_utils_unittest.cc
+++ b/chrome/browser/notifications/scheduler/internal/scheduler_utils_unittest.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/notifications/scheduler/internal/scheduler_utils.h"
 
 #include <algorithm>
+#include <vector>
 
 #include "base/containers/circular_deque.h"
 #include "base/guid.h"
@@ -31,17 +32,25 @@
     ToLocalHour(0, clock_.Now(), 0, &beginning_of_today_);
   }
 
-  void CreateFakeImpressions(std::vector<base::Time> times,
-                             base::circular_deque<Impression>& impressions) {
-    impressions.clear();
+  void CreateFakeImpressions(ClientState* client_state,
+                             const std::vector<base::Time>& times) {
+    DCHECK(client_state);
+    client_state->impressions.clear();
+    auto type = client_state->type;
     for (const auto& time : times) {
-      impressions.emplace_back(SchedulerClientType::kTest1,
-                               base::GenerateGUID(), time);
+      client_state->impressions.emplace_back(type, base::GenerateGUID(), time);
     }
-    std::sort(impressions.begin(), impressions.end(),
-              [](const Impression& lhs, const Impression& rhs) {
-                return lhs.create_time < rhs.create_time;
-              });
+  }
+
+  std::unique_ptr<ClientState> CreateFakeClientStateWithImpression(
+      SchedulerClientType type,
+      const SchedulerConfig& config,
+      const std::vector<base::Time>& times) {
+    auto client_state = std::make_unique<ClientState>();
+    client_state->type = type;
+    client_state->current_max_daily_show = config.initial_daily_shown_per_type;
+    CreateFakeImpressions(client_state.get(), times);
+    return client_state;
   }
 
  protected:
@@ -85,6 +94,56 @@
   EXPECT_EQ(expected, another_day);
 }
 
+TEST_F(SchedulerUtilsTest, NotificationsShownTodayMultipleClients) {
+  InitFakeClock();
+  base::Time now = clock()->Now();
+  // Create fake clients.
+  std::map<SchedulerClientType, const ClientState*> client_states;
+  //            begin_of_today         now                  end_of_today
+  // client1  * |                   *  *                    | *
+  // client2  * *   *                  |  *                 | *
+  // client3  * |                      |                    | *
+
+  std::vector<base::Time> create_times = {
+      now - base::TimeDelta::FromSeconds(2) /*today*/,
+      now - base::TimeDelta::FromSeconds(1) /*today*/,
+      beginning_of_today() - base::TimeDelta::FromSeconds(1) /*yesterday*/,
+      beginning_of_today() + base::TimeDelta::FromDays(1) /*tomorrow*/};
+  auto new_client1 = CreateFakeClientStateWithImpression(
+      SchedulerClientType::kTest1, config(), create_times);
+
+  create_times = {
+      now /*today*/,
+      beginning_of_today() + base::TimeDelta::FromDays(1) /*tomorrow*/,
+      beginning_of_today() - base::TimeDelta::FromSeconds(1) /*yesterday*/,
+      beginning_of_today() + base::TimeDelta::FromSeconds(1) /*today*/,
+      beginning_of_today() /*today*/};
+  auto new_client2 = CreateFakeClientStateWithImpression(
+      SchedulerClientType::kTest2, config(), create_times);
+
+  create_times = {
+      beginning_of_today() - base::TimeDelta::FromSeconds(2), /*yesterday*/
+      beginning_of_today() + base::TimeDelta::FromDays(1)     /*tomorrow*/
+  };
+  auto new_client3 = CreateFakeClientStateWithImpression(
+      SchedulerClientType::kTest3, config(), create_times);
+
+  client_states[SchedulerClientType::kTest1] = new_client1.get();
+  client_states[SchedulerClientType::kTest2] = new_client2.get();
+  client_states[SchedulerClientType::kTest3] = new_client3.get();
+
+  std::map<SchedulerClientType, int> shown_per_type;
+  int shown_total = 0;
+  SchedulerClientType last_shown_type = SchedulerClientType::kUnknown;
+  NotificationsShownToday(client_states, &shown_per_type, &shown_total,
+                          &last_shown_type, clock());
+  EXPECT_EQ(shown_total, 5);
+  EXPECT_EQ(last_shown_type, SchedulerClientType::kTest2);
+  EXPECT_EQ(shown_per_type.at(SchedulerClientType::kTest1), 2);
+  EXPECT_EQ(shown_per_type.at(SchedulerClientType::kTest2), 3);
+  EXPECT_EQ(shown_per_type.at(SchedulerClientType::kTest3), 0);
+}
+
 TEST_F(SchedulerUtilsTest, NotificationsShownToday) {
   // Create fake client.
   auto new_client = CreateNewClientState(SchedulerClientType::kTest1, config());
@@ -102,16 +161,16 @@
       beginning_of_today() + base::TimeDelta::FromSeconds(1) /*today*/,
       beginning_of_today() /*today*/};
 
-  CreateFakeImpressions(create_times, new_client->impressions);
+  CreateFakeImpressions(new_client.get(), create_times);
   count = NotificationsShownToday(new_client.get(), clock());
   EXPECT_EQ(count, 3);
 
   // Test case 3:
   create_times = {
       beginning_of_today() - base::TimeDelta::FromSeconds(2), /*yesterday*/
-      beginning_of_today() - base::TimeDelta::FromDays(2),    /*tomorrow*/
+      beginning_of_today() + base::TimeDelta::FromDays(1),    /*tomorrow*/
   };
-  CreateFakeImpressions(create_times, new_client->impressions);
+  CreateFakeImpressions(new_client.get(), create_times);
   count = NotificationsShownToday(new_client.get(), clock());
   EXPECT_EQ(count, 0);
 
@@ -120,7 +179,7 @@
       now /*today*/, now - base::TimeDelta::FromSeconds(1) /*today*/,
       beginning_of_today() - base::TimeDelta::FromSeconds(1) /*yesterday*/,
       beginning_of_today() + base::TimeDelta::FromDays(1) /*tomorrow*/};
-  CreateFakeImpressions(create_times, new_client->impressions);
+  CreateFakeImpressions(new_client.get(), create_times);
   count = NotificationsShownToday(new_client.get(), clock());
   EXPECT_EQ(count, 2);
 }
diff --git a/chrome/browser/page_load_metrics/observers/security_state_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/security_state_page_load_metrics_observer.cc
index ecbb421..a3aa308 100644
--- a/chrome/browser/page_load_metrics/observers/security_state_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/security_state_page_load_metrics_observer.cc
@@ -66,13 +66,21 @@
 }
 
 // static
-std::string
-SecurityStatePageLoadMetricsObserver::GetPageEndReasonHistogramNameForTesting(
-    security_state::SecurityLevel level) {
+std::string SecurityStatePageLoadMetricsObserver::
+    GetSecurityLevelPageEndReasonHistogramNameForTesting(
+        security_state::SecurityLevel level) {
   return security_state::GetSecurityLevelHistogramName(
       kPageEndReasonPrefix, level);
 }
 
+// static
+std::string SecurityStatePageLoadMetricsObserver::
+    GetSafetyTipPageEndReasonHistogramNameForTesting(
+        security_state::SafetyTipStatus safety_tip_status) {
+  return security_state::GetSafetyTipHistogramName(kPageEndReasonPrefix,
+                                                   safety_tip_status);
+}
+
 SecurityStatePageLoadMetricsObserver::SecurityStatePageLoadMetricsObserver(
     SiteEngagementService* engagement_service)
     : content::WebContentsObserver(), engagement_service_(engagement_service) {}
@@ -111,6 +119,8 @@
       SecurityStateTabHelper::FromWebContents(web_contents);
   initial_security_level_ = security_state_tab_helper_->GetSecurityLevel();
   current_security_level_ = initial_security_level_;
+  current_safety_tip_status_ =
+      security_state_tab_helper_->GetVisibleSecurityState()->safety_tip_status;
 
   base::UmaHistogramEnumeration(kSecurityLevelOnCommit, initial_security_level_,
                                 security_state::SECURITY_LEVEL_COUNT);
@@ -154,6 +164,7 @@
         final_engagement_score, 100);
   }
 
+  // Record security level UMA histograms.
   base::UmaHistogramEnumeration(
       security_state::GetSecurityLevelHistogramName(kPageEndReasonPrefix,
                                                     current_security_level_),
@@ -167,10 +178,24 @@
   base::UmaHistogramEnumeration(kSecurityLevelOnComplete,
                                 current_security_level_,
                                 security_state::SECURITY_LEVEL_COUNT);
+
+  // Record Safety Tip UMA histograms.
+  base::UmaHistogramEnumeration(
+      security_state::GetSafetyTipHistogramName(kPageEndReasonPrefix,
+                                                current_safety_tip_status_),
+      GetDelegate().GetPageEndReason(),
+      page_load_metrics::PAGE_END_REASON_COUNT);
+  base::UmaHistogramCustomTimes(
+      security_state::GetSafetyTipHistogramName(kTimeOnPagePrefix,
+                                                current_safety_tip_status_),
+      GetDelegate().GetVisibilityTracker().GetForegroundDuration(),
+      base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromHours(1), 100);
 }
 
 void SecurityStatePageLoadMetricsObserver::DidChangeVisibleSecurityState() {
   if (!security_state_tab_helper_)
     return;
   current_security_level_ = security_state_tab_helper_->GetSecurityLevel();
+  current_safety_tip_status_ =
+      security_state_tab_helper_->GetVisibleSecurityState()->safety_tip_status;
 }
diff --git a/chrome/browser/page_load_metrics/observers/security_state_page_load_metrics_observer.h b/chrome/browser/page_load_metrics/observers/security_state_page_load_metrics_observer.h
index 69fd2ff7..2b61e9e6 100644
--- a/chrome/browser/page_load_metrics/observers/security_state_page_load_metrics_observer.h
+++ b/chrome/browser/page_load_metrics/observers/security_state_page_load_metrics_observer.h
@@ -40,8 +40,10 @@
       security_state::SecurityLevel level);
   static std::string GetEngagementFinalHistogramNameForTesting(
       security_state::SecurityLevel level);
-  static std::string GetPageEndReasonHistogramNameForTesting(
+  static std::string GetSecurityLevelPageEndReasonHistogramNameForTesting(
       security_state::SecurityLevel level);
+  static std::string GetSafetyTipPageEndReasonHistogramNameForTesting(
+      security_state::SafetyTipStatus safety_tip_status);
 
   explicit SecurityStatePageLoadMetricsObserver(
       SiteEngagementService* engagement_service);
@@ -67,6 +69,11 @@
   double initial_engagement_score_ = 0.0;
   security_state::SecurityLevel initial_security_level_ = security_state::NONE;
   security_state::SecurityLevel current_security_level_ = security_state::NONE;
+  // For Safety Tips, unlike SecurityLevel, we only track the current status
+  // because Safety Tip status does not change once the initial reputation check
+  // (begun at commit time) completes.
+  security_state::SafetyTipStatus current_safety_tip_status_ =
+      security_state::SafetyTipStatus::kUnknown;
   ukm::SourceId source_id_ = ukm::kInvalidSourceId;
 
   DISALLOW_COPY_AND_ASSIGN(SecurityStatePageLoadMetricsObserver);
diff --git a/chrome/browser/page_load_metrics/observers/security_state_page_load_metrics_observer_browsertest.cc b/chrome/browser/page_load_metrics/observers/security_state_page_load_metrics_observer_browsertest.cc
index 67b0c317..3ab3065 100644
--- a/chrome/browser/page_load_metrics/observers/security_state_page_load_metrics_observer_browsertest.cc
+++ b/chrome/browser/page_load_metrics/observers/security_state_page_load_metrics_observer_browsertest.cc
@@ -10,6 +10,8 @@
 #include "base/task/post_task.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
+#include "chrome/browser/lookalikes/safety_tips/reputation_web_contents_observer.h"
+#include "chrome/browser/lookalikes/safety_tips/safety_tip_test_utils.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
@@ -154,7 +156,8 @@
   // Navigation metrics.
   histogram_tester()->ExpectUniqueSample(
       SecurityStatePageLoadMetricsObserver::
-          GetPageEndReasonHistogramNameForTesting(security_state::SECURE),
+          GetSecurityLevelPageEndReasonHistogramNameForTesting(
+              security_state::SECURE),
       page_load_metrics::END_CLOSE, 1);
 }
 
@@ -220,10 +223,53 @@
 
   histogram_tester()->ExpectUniqueSample(
       SecurityStatePageLoadMetricsObserver::
-          GetPageEndReasonHistogramNameForTesting(security_state::SECURE),
+          GetSecurityLevelPageEndReasonHistogramNameForTesting(
+              security_state::SECURE),
       page_load_metrics::END_RELOAD, 1);
 }
 
+// Tests that the Safety Tip page end reason histogram is recorded properly, by
+// reloading the page and checking that the reload-page reason is recorded in
+// the histogram.
+IN_PROC_BROWSER_TEST_F(SecurityStatePageLoadMetricsBrowserTest,
+                       ReloadPageWithSafetyTip) {
+  StartHttpsServer(net::EmbeddedTestServer::CERT_OK);
+  GURL url = https_test_server()->GetURL("/simple.html");
+
+  // The histogram should be recorded regardless of whether the page is flagged
+  // with a Safety Tip or not.
+  for (bool flag_page : {false, true}) {
+    base::HistogramTester histogram_tester;
+    if (flag_page) {
+      SetSafetyTipBadRepPatterns({url.host() + "/"});
+    }
+
+    content::WebContents* contents =
+        browser()->tab_strip_model()->GetActiveWebContents();
+    safety_tips::ReputationWebContentsObserver* rep_observer =
+        safety_tips::ReputationWebContentsObserver::FromWebContents(contents);
+    ASSERT_TRUE(rep_observer);
+
+    // Navigate to |url| and wait for the reputation check to complete before
+    // checking the histograms.
+    base::RunLoop run_loop;
+    rep_observer->RegisterReputationCheckCallbackForTesting(
+        run_loop.QuitClosure());
+    ui_test_utils::NavigateToURL(browser(), url);
+    run_loop.Run();
+
+    chrome::Reload(browser(), WindowOpenDisposition::CURRENT_TAB);
+    EXPECT_TRUE(content::WaitForLoadStop(contents));
+
+    histogram_tester.ExpectUniqueSample(
+        SecurityStatePageLoadMetricsObserver::
+            GetSafetyTipPageEndReasonHistogramNameForTesting(
+                flag_page ? security_state::SafetyTipStatus::kBadReputation
+                          : security_state::SafetyTipStatus::kNone),
+        page_load_metrics::END_RELOAD, 1);
+  }
+}
+
 IN_PROC_BROWSER_TEST_F(SecurityStatePageLoadMetricsBrowserTest, OtherScheme) {
   ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIVersionURL));
   CloseAllTabs();
@@ -247,7 +293,8 @@
 
   histogram_tester()->ExpectTotalCount(
       SecurityStatePageLoadMetricsObserver::
-          GetPageEndReasonHistogramNameForTesting(security_state::NONE),
+          GetSecurityLevelPageEndReasonHistogramNameForTesting(
+              security_state::NONE),
       0);
 }
 
@@ -357,10 +404,43 @@
 
   histogram_tester()->ExpectTotalCount(
       SecurityStatePageLoadMetricsObserver::
-          GetPageEndReasonHistogramNameForTesting(security_state::SECURE),
+          GetSecurityLevelPageEndReasonHistogramNameForTesting(
+              security_state::SECURE),
       0);
 }
 
+// Tests that the Safety Tip page end reason histogram is recorded properly on a
+// net error page. No Safety Tip should appear on net errors.
+IN_PROC_BROWSER_TEST_F(SecurityStatePageLoadMetricsBrowserTest,
+                       SafetyTipHostDoesNotExist) {
+  GURL url("http://nonexistent.test/page.html");
+
+  for (bool flag_page : {false, true}) {
+    if (flag_page) {
+      SetSafetyTipBadRepPatterns({url.host() + "/"});
+    }
+    content::WebContents* contents =
+        browser()->tab_strip_model()->GetActiveWebContents();
+    safety_tips::ReputationWebContentsObserver* rep_observer =
+        safety_tips::ReputationWebContentsObserver::FromWebContents(contents);
+    ASSERT_TRUE(rep_observer);
+
+    // Navigate to |url| and wait for the reputation check to complete before
+    // checking the histograms.
+    base::RunLoop run_loop;
+    rep_observer->RegisterReputationCheckCallbackForTesting(
+        run_loop.QuitClosure());
+    ui_test_utils::NavigateToURL(browser(), url);
+    run_loop.Run();
+
+    histogram_tester()->ExpectTotalCount(
+        SecurityStatePageLoadMetricsObserver::
+            GetSafetyTipPageEndReasonHistogramNameForTesting(
+                security_state::SafetyTipStatus::kNone),
+        0);
+  }
+}
+
 IN_PROC_BROWSER_TEST_F(SecurityStatePageLoadMetricsBrowserTest,
                        Navigate_Both_NonHtmlMainResource) {
   StartHttpServer();
@@ -392,7 +472,8 @@
 
   histogram_tester()->ExpectTotalCount(
       SecurityStatePageLoadMetricsObserver::
-          GetPageEndReasonHistogramNameForTesting(security_state::SECURE),
+          GetSecurityLevelPageEndReasonHistogramNameForTesting(
+              security_state::SECURE),
       0);
 }
 
@@ -416,8 +497,14 @@
   run_loop.Run();
   CloseAllTabs();
 
-  auto samples =
+  auto security_level_samples =
       histogram_tester()->GetAllSamples("Security.TimeOnPage2.SECURE");
-  EXPECT_EQ(1u, samples.size());
-  EXPECT_LE(kMinForegroundTime.InMilliseconds(), samples.front().min);
+  EXPECT_EQ(1u, security_level_samples.size());
+  EXPECT_LE(kMinForegroundTime.InMilliseconds(),
+            security_level_samples.front().min);
+  auto safety_tip_samples =
+      histogram_tester()->GetAllSamples("Security.TimeOnPage2.SafetyTip_None");
+  EXPECT_EQ(1u, safety_tip_samples.size());
+  EXPECT_LE(kMinForegroundTime.InMilliseconds(),
+            safety_tip_samples.front().min);
 }
diff --git a/chrome/browser/previews/resource_loading_hints/resource_loading_hints_browsertest.cc b/chrome/browser/previews/resource_loading_hints/resource_loading_hints_browsertest.cc
index 3dca722..d6d1210 100644
--- a/chrome/browser/previews/resource_loading_hints/resource_loading_hints_browsertest.cc
+++ b/chrome/browser/previews/resource_loading_hints/resource_loading_hints_browsertest.cc
@@ -778,7 +778,7 @@
   // Whitelist resource loading hints for https_hint_setup_url()'s' host.
   // Set pattern to a string that does not matches https_url() path.
   ASSERT_EQ(std::string::npos, https_url().path().find("mismatched_pattern"));
-  SetDefaultOnlyResourceLoadingHintsWithPagePattern(https_url(),
+  SetDefaultOnlyResourceLoadingHintsWithPagePattern(https_hint_setup_url(),
                                                     "mismatched_pattern");
 
   SetExpectedFooJpgRequest(true);
@@ -811,7 +811,7 @@
   if (use_preload_resources_webpage() && !use_render_frame_observer())
     return;
   // Whitelist resource loading hints for https_url()'s' host and pattern.
-  SetDefaultOnlyResourceLoadingHintsWithPagePattern(https_url(),
+  SetDefaultOnlyResourceLoadingHintsWithPagePattern(https_hint_setup_url(),
                                                     https_url().path());
 
   // Hints should be used when loading https_url().
diff --git a/chrome/browser/resources/dev_ui_loader/dev_ui_loader.css b/chrome/browser/resources/dev_ui_loader/dev_ui_loader.css
new file mode 100644
index 0000000..da1deed5
--- /dev/null
+++ b/chrome/browser/resources/dev_ui_loader/dev_ui_loader.css
@@ -0,0 +1,7 @@
+/* Copyright 2019 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. */
+
+body {
+  font-family: 'DejaVu Sans', Arial, sans-serif;
+}
diff --git a/chrome/browser/resources/dev_ui_loader/dev_ui_loader.grdp b/chrome/browser/resources/dev_ui_loader/dev_ui_loader.grdp
new file mode 100644
index 0000000..547e30b
--- /dev/null
+++ b/chrome/browser/resources/dev_ui_loader/dev_ui_loader.grdp
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<grit-part>
+  <include name="IDR_DEV_UI_LOADER_HTML" file="resources/dev_ui_loader/dev_ui_loader.html" compress="gzip" type="BINDATA" />
+  <include name="IDR_DEV_UI_LOADER_CSS" file="resources/dev_ui_loader/dev_ui_loader.css" compress="gzip" type="BINDATA" />
+  <include name="IDR_DEV_UI_LOADER_JS" file="resources/dev_ui_loader/dev_ui_loader.js" compress="gzip" type="BINDATA" />
+</grit-part>
diff --git a/chrome/browser/resources/dev_ui_loader/dev_ui_loader.html b/chrome/browser/resources/dev_ui_loader/dev_ui_loader.html
new file mode 100644
index 0000000..89b48b8
--- /dev/null
+++ b/chrome/browser/resources/dev_ui_loader/dev_ui_loader.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta charset="utf-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <title>DevUI DFM Loader Interstitial</title>
+  <link rel="stylesheet" href="dev_ui_loader.css">
+  <script src="chrome://resources/js/cr.js"></script>
+  <script src="chrome://resources/js/promise_resolver.js"></script>
+  <script src="dev_ui_loader.js"></script>
+</head>
+<body>
+<div id="failure-message" hidden>
+  <p>Failed to install Developer UI for Chrome (internet connection needed).</p>
+  <p>Please reload page to retry.</p>
+</div>
+</body>
+</html>
diff --git a/chrome/browser/resources/dev_ui_loader/dev_ui_loader.js b/chrome/browser/resources/dev_ui_loader/dev_ui_loader.js
new file mode 100644
index 0000000..ec1af3aa
--- /dev/null
+++ b/chrome/browser/resources/dev_ui_loader/dev_ui_loader.js
@@ -0,0 +1,36 @@
+// Copyright 2019 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.
+
+(function() {
+'use strict';
+
+/** @param {string} page */
+function redirectToChromePage(page) {
+  // Use replace() so the current page disappears from history.
+  location.replace('chrome://' + page);
+}
+
+function doInstall() {
+  cr.sendWithPromise('installAndLoadDevUiDfm').then((response) => {
+    const query = new URL(window.location).searchParams;
+    const targetPage = (query.get('page') || '').replace(/[^a-z0-9_\-]/g, '');
+    const status = response[0];
+    if (status === 'failure') {
+      document.querySelector('#failure-message').hidden = false;
+    } else if (status === 'success' || status === 'noop') {
+      redirectToChromePage(targetPage);
+    }
+  });
+}
+
+document.addEventListener('DOMContentLoaded', () => {
+  cr.sendWithPromise('getDevUiDfmState').then((state) => {
+    if (state === 'installed') {
+      redirectToChromePage('chrome-urls');
+    } else if (state === 'not-installed' || 'not-loaded') {
+      doInstall();
+    }
+  });
+});
+})();
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index ee66dd1..a72290f9 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -789,6 +789,7 @@
     }
     deps += [
       "//chrome/android:jni_headers",
+      "//chrome/android/features/dev_ui:buildflags",
       "//chrome/browser/android/thin_webview:thin_webview",
       "//components/embedder_support/android:web_contents_delegate",
       "//components/navigation_interception",
diff --git a/chrome/browser/ui/app_list/search/zero_state_file_provider.cc b/chrome/browser/ui/app_list/search/zero_state_file_provider.cc
index 77a3266..4c44ecbe 100644
--- a/chrome/browser/ui/app_list/search/zero_state_file_provider.cc
+++ b/chrome/browser/ui/app_list/search/zero_state_file_provider.cc
@@ -23,16 +23,14 @@
 namespace app_list {
 namespace {
 
-using StringResults = std::vector<std::pair<std::string, float>>;
-using FilePathResults = std::vector<std::pair<base::FilePath, float>>;
-
 constexpr int kMaxLocalFiles = 10;
 
-// Given the output of RecurrenceRanker::RankTopN, filter out all results that
-// don't exist on disk. Returns the filtered results, with each result string
-// converted to a base::FilePath.
-FilePathResults FilterNonexistentFiles(const StringResults& ranker_results) {
-  FilePathResults results;
+// Given the output of RecurrenceRanker::RankTopN, partition files by whether
+// they exist or not on disk. Returns a pair of vectors: <valid, invalid>.
+internal::ValidAndInvalidResults ValidateFiles(
+    const std::vector<std::pair<std::string, float>>& ranker_results) {
+  internal::ScoredResults valid;
+  internal::Results invalid;
   for (const auto& path_score : ranker_results) {
     // We use FilePath::FromUTF8Unsafe to decode the filepath string. As per its
     // documentation, this is a safe use of the function because
@@ -40,9 +38,11 @@
     // filepaths are UTF8.
     const auto& path = base::FilePath::FromUTF8Unsafe(path_score.first);
     if (base::PathExists(path))
-      results.emplace_back(path, path_score.second);
+      valid.emplace_back(path, path_score.second);
+    else
+      invalid.emplace_back(path);
   }
-  return results;
+  return {valid, invalid};
 }
 
 }  // namespace
@@ -84,15 +84,20 @@
 
   base::PostTaskAndReplyWithResult(
       task_runner_.get(), FROM_HERE,
-      base::BindOnce(&FilterNonexistentFiles,
-                     files_ranker_->RankTopN(kMaxLocalFiles)),
+      base::BindOnce(&ValidateFiles, files_ranker_->RankTopN(kMaxLocalFiles)),
       base::BindOnce(&ZeroStateFileProvider::SetSearchResults,
                      weak_factory_.GetWeakPtr()));
 }
 
-void ZeroStateFileProvider::SetSearchResults(FilePathResults results) {
+void ZeroStateFileProvider::SetSearchResults(
+    const internal::ValidAndInvalidResults& results) {
+  // Delete invalid results from the model.
+  for (const auto& path : results.second)
+    files_ranker_->RemoveTarget(path.value());
+
+  // Use valid results for search results.
   SearchProvider::Results new_results;
-  for (const auto& filepath_score : results) {
+  for (const auto& filepath_score : results.first) {
     new_results.emplace_back(std::make_unique<ZeroStateFileResult>(
         filepath_score.first, filepath_score.second, profile_));
   }
diff --git a/chrome/browser/ui/app_list/search/zero_state_file_provider.h b/chrome/browser/ui/app_list/search/zero_state_file_provider.h
index 0cfd05657..6830016 100644
--- a/chrome/browser/ui/app_list/search/zero_state_file_provider.h
+++ b/chrome/browser/ui/app_list/search/zero_state_file_provider.h
@@ -28,6 +28,13 @@
 }  // namespace file_manager
 
 namespace app_list {
+namespace internal {
+
+using Results = std::vector<base::FilePath>;
+using ScoredResults = std::vector<std::pair<base::FilePath, float>>;
+using ValidAndInvalidResults = std::pair<ScoredResults, Results>;
+
+}  // namespace internal
 
 class RecurrenceRanker;
 
@@ -45,9 +52,10 @@
   void OnFilesOpened(const std::vector<FileOpenEvent>& file_opens) override;
 
  private:
-  // Converts |results| into ZeroStateFilesResults and sets them as this
-  // provider's results.
-  void SetSearchResults(std::vector<std::pair<base::FilePath, float>> results);
+  // Takes a pair of vectors: <valid paths, invalid paths>, and converts the
+  // valid paths to ZeroStatFilesResults and sets them as this provider's
+  // results. The invalid paths are removed from the model.
+  void SetSearchResults(const internal::ValidAndInvalidResults& results);
 
   // The reference to profile to get ZeroStateFileProvider service.
   Profile* const profile_;
diff --git a/chrome/browser/ui/webui/android/dev_ui_loader/dev_ui_loader_message_handler.cc b/chrome/browser/ui/webui/android/dev_ui_loader/dev_ui_loader_message_handler.cc
new file mode 100644
index 0000000..9fd69a5
--- /dev/null
+++ b/chrome/browser/ui/webui/android/dev_ui_loader/dev_ui_loader_message_handler.cc
@@ -0,0 +1,85 @@
+// Copyright 2019 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 "chrome/browser/ui/webui/android/dev_ui_loader/dev_ui_loader_message_handler.h"
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/values.h"
+#include "chrome/browser/android/dev_ui/dev_ui_module_provider.h"
+
+DevUiLoaderMessageHandler::DevUiLoaderMessageHandler() = default;
+
+DevUiLoaderMessageHandler::~DevUiLoaderMessageHandler() = default;
+
+void DevUiLoaderMessageHandler::RegisterMessages() {
+  web_ui()->RegisterMessageCallback(
+      "getDevUiDfmState",
+      base::BindRepeating(&DevUiLoaderMessageHandler::HandleGetDevUiDfmState,
+                          weak_ptr_factory_.GetWeakPtr()));
+  web_ui()->RegisterMessageCallback(
+      "installAndLoadDevUiDfm",
+      base::BindRepeating(
+          &DevUiLoaderMessageHandler::HandleInstallAndLoadDevUiDfm,
+          weak_ptr_factory_.GetWeakPtr()));
+}
+
+void DevUiLoaderMessageHandler::HandleGetDevUiDfmState(
+    const base::ListValue* args) {
+  const base::Value* callback_id = nullptr;
+  CHECK(args->Get(0, &callback_id));
+  const char* response = "ready";
+  if (!dev_ui::DevUiModuleProvider::GetInstance().ModuleInstalled())
+    response = "not-installed";
+  else if (!dev_ui::DevUiModuleProvider::GetInstance().ModuleLoaded())
+    response = "not-loaded";
+  AllowJavascript();
+  ResolveJavascriptCallback(*callback_id, base::Value(response));
+}
+
+void DevUiLoaderMessageHandler::ReplyToJavaScript(
+    const base::Value& callback_id,
+    const char* return_value) {
+  AllowJavascript();
+  base::ListValue response;
+  response.GetList().emplace_back(base::Value(return_value));
+  ResolveJavascriptCallback(callback_id, response);
+}
+
+void DevUiLoaderMessageHandler::HandleInstallAndLoadDevUiDfm(
+    const base::ListValue* args) {
+  const base::Value* callback_id = nullptr;
+  CHECK(args->Get(0, &callback_id));
+
+  if (!dev_ui::DevUiModuleProvider::GetInstance().ModuleInstalled()) {
+    dev_ui::DevUiModuleProvider::GetInstance().InstallModule(base::BindOnce(
+        &DevUiLoaderMessageHandler::OnDevUiDfmInstallWithStatus,
+        weak_ptr_factory_.GetWeakPtr(), callback_id->GetString()));
+
+  } else if (!dev_ui::DevUiModuleProvider::GetInstance().ModuleLoaded()) {
+    dev_ui::DevUiModuleProvider::GetInstance().LoadModule(base::BindOnce(
+        &DevUiLoaderMessageHandler::OnDevUiResourceLoaded,
+        weak_ptr_factory_.GetWeakPtr(), callback_id->GetString()));
+
+  } else {
+    ReplyToJavaScript(*callback_id, "noop");
+  }
+}
+
+void DevUiLoaderMessageHandler::OnDevUiDfmInstallWithStatus(
+    std::string callback_id_string,
+    bool success) {
+  if (success) {
+    dev_ui::DevUiModuleProvider::GetInstance().LoadModule(
+        base::BindOnce(&DevUiLoaderMessageHandler::OnDevUiResourceLoaded,
+                       weak_ptr_factory_.GetWeakPtr(), callback_id_string));
+  } else {
+    ReplyToJavaScript(base::Value(callback_id_string), "failure");
+  }
+}
+
+void DevUiLoaderMessageHandler::OnDevUiResourceLoaded(
+    std::string callback_id_string) {
+  ReplyToJavaScript(base::Value(callback_id_string), "success");
+}
diff --git a/chrome/browser/ui/webui/android/dev_ui_loader/dev_ui_loader_message_handler.h b/chrome/browser/ui/webui/android/dev_ui_loader/dev_ui_loader_message_handler.h
new file mode 100644
index 0000000..0492102
--- /dev/null
+++ b/chrome/browser/ui/webui/android/dev_ui_loader/dev_ui_loader_message_handler.h
@@ -0,0 +1,65 @@
+// Copyright 2019 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 CHROME_BROWSER_UI_WEBUI_ANDROID_DEV_UI_LOADER_DEV_UI_LOADER_MESSAGE_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_ANDROID_DEV_UI_LOADER_DEV_UI_LOADER_MESSAGE_HANDLER_H_
+
+#include <string>
+
+#include "base/memory/weak_ptr.h"
+#include "build/build_config.h"
+#include "chrome/android/features/dev_ui/buildflags.h"
+#include "content/public/browser/web_ui_message_handler.h"
+
+#if !defined(OS_ANDROID) || !BUILDFLAG(DFMIFY_DEV_UI)
+#error Unsupported platform.
+#endif
+
+namespace base {
+class ListValue;
+class Value;
+}  // namespace base
+
+class DevUiLoaderMessageHandler : public content::WebUIMessageHandler {
+ public:
+  DevUiLoaderMessageHandler();
+  ~DevUiLoaderMessageHandler() override;
+
+ private:
+  DevUiLoaderMessageHandler(const DevUiLoaderMessageHandler&) = delete;
+  void operator=(const DevUiLoaderMessageHandler&) = delete;
+
+  // WebUIMessageHandler
+  void RegisterMessages() override;
+
+  // Called from JavaScript. |args| specifies id for callback, which receives
+  // one of the following responses:
+  // * "not-installed" if the DevUI DFM is not installed.
+  // * "not-loaded" if the DevUI DFM is installed, but not loaded.
+  // * "ready" if the DevUI DFM is installed and loaded.
+  void HandleGetDevUiDfmState(const base::ListValue* args);
+
+  // Helper for HandleInstallAndLoadDevUiDfm().
+  void ReplyToJavaScript(const base::Value& callback_id,
+                         const char* return_value);
+
+  // Called from JavaScript. |args| specifies id for callback, which receives
+  // one of the following responses:
+  // * "noop" if the DevUI DFM is already installed and loaded.
+  // * "success" if DevUI DFM install / load takes place, and succeeds.
+  // * "failure" if DevUI DFM install / load takes place, but fails.
+  void HandleInstallAndLoadDevUiDfm(const base::ListValue* args);
+
+  // Callback for dev_ui::DevUiModuleProvider::InstallModule().
+  void OnDevUiDfmInstallWithStatus(std::string callback_id_string,
+                                   bool success);
+
+  // Callback for dev_ui::DevUiModuleProvider::LoadModule().
+  void OnDevUiResourceLoaded(std::string callback_id_string);
+
+  // Factory for creating references in callbacks.
+  base::WeakPtrFactory<DevUiLoaderMessageHandler> weak_ptr_factory_{this};
+};
+
+#endif  // CHROME_BROWSER_UI_WEBUI_ANDROID_DEV_UI_LOADER_DEV_UI_LOADER_MESSAGE_HANDLER_H_
diff --git a/chrome/browser/ui/webui/android/dev_ui_loader/dev_ui_loader_ui.cc b/chrome/browser/ui/webui/android/dev_ui_loader/dev_ui_loader_ui.cc
new file mode 100644
index 0000000..52622ee
--- /dev/null
+++ b/chrome/browser/ui/webui/android/dev_ui_loader/dev_ui_loader_ui.cc
@@ -0,0 +1,30 @@
+// Copyright 2019 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 "chrome/browser/ui/webui/android/dev_ui_loader/dev_ui_loader_ui.h"
+
+#include <memory>
+#include <utility>
+
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/webui/android/dev_ui_loader/dev_ui_loader_message_handler.h"
+#include "chrome/grit/browser_resources.h"
+#include "content/public/browser/web_ui_data_source.h"
+#include "url/gurl.h"
+
+DevUiLoaderUI::DevUiLoaderUI(content::WebUI* web_ui_in, const GURL& url)
+    : WebUIController(web_ui_in) {
+  std::unique_ptr<content::WebUIDataSource> html_source;
+  html_source.reset(content::WebUIDataSource::Create(url.host()));
+  html_source->SetDefaultResource(IDR_DEV_UI_LOADER_HTML);
+  html_source->AddResourcePath("dev_ui_loader.html", IDR_DEV_UI_LOADER_HTML);
+  html_source->AddResourcePath("dev_ui_loader.js", IDR_DEV_UI_LOADER_JS);
+  html_source->AddResourcePath("dev_ui_loader.css", IDR_DEV_UI_LOADER_CSS);
+
+  Profile* profile = Profile::FromWebUI(web_ui());
+  content::WebUIDataSource::Add(profile, html_source.release());
+  web_ui()->AddMessageHandler(std::make_unique<DevUiLoaderMessageHandler>());
+}
+
+DevUiLoaderUI::~DevUiLoaderUI() = default;
diff --git a/chrome/browser/ui/webui/android/dev_ui_loader/dev_ui_loader_ui.h b/chrome/browser/ui/webui/android/dev_ui_loader/dev_ui_loader_ui.h
new file mode 100644
index 0000000..d8b70e7
--- /dev/null
+++ b/chrome/browser/ui/webui/android/dev_ui_loader/dev_ui_loader_ui.h
@@ -0,0 +1,32 @@
+// Copyright 2019 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 CHROME_BROWSER_UI_WEBUI_ANDROID_DEV_UI_LOADER_DEV_UI_LOADER_UI_H_
+#define CHROME_BROWSER_UI_WEBUI_ANDROID_DEV_UI_LOADER_DEV_UI_LOADER_UI_H_
+
+#include "base/memory/weak_ptr.h"
+#include "build/build_config.h"
+#include "chrome/android/features/dev_ui/buildflags.h"
+#include "content/public/browser/web_ui_controller.h"
+
+#if !defined(OS_ANDROID) || !BUILDFLAG(DFMIFY_DEV_UI)
+#error Unsupported platform.
+#endif
+
+class GURL;
+
+class DevUiLoaderUI : public content::WebUIController {
+ public:
+  DevUiLoaderUI(content::WebUI* web_ui_in, const GURL& url);
+  ~DevUiLoaderUI() override;
+
+ private:
+  DevUiLoaderUI(const DevUiLoaderUI&) = delete;
+  void operator=(const DevUiLoaderUI&) = delete;
+
+  // Factory for creating references in callbacks.
+  base::WeakPtrFactory<DevUiLoaderUI> weak_ptr_factory_{this};
+};
+
+#endif  // CHROME_BROWSER_UI_WEBUI_ANDROID_DEV_UI_LOADER_DEV_UI_LOADER_UI_H_
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
index 51bc3c9..3dd61b1 100644
--- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
+++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ui/webui/chrome_web_ui_controller_factory.h"
 
 #include <stddef.h>
+#include <utility>
 
 #include "base/bind.h"
 #include "base/feature_list.h"
@@ -123,6 +124,7 @@
 #endif
 
 #if defined(OS_ANDROID)
+#include "chrome/android/features/dev_ui/buildflags.h"
 #include "chrome/browser/ui/webui/explore_sites_internals/explore_sites_internals_ui.h"
 #include "chrome/browser/ui/webui/offline/offline_internals_ui.h"
 #include "chrome/browser/ui/webui/snippets_internals/snippets_internals_ui.h"
@@ -132,7 +134,10 @@
 #if BUILDFLAG(ENABLE_FEED_IN_CHROME)
 #include "chrome/browser/ui/webui/feed_internals/feed_internals_ui.h"
 #endif  // BUILDFLAG(ENABLE_FEED_IN_CHROME)
-#else
+#if BUILDFLAG(DFMIFY_DEV_UI)
+#include "chrome/browser/ui/webui/android/dev_ui_loader/dev_ui_loader_ui.h"
+#endif  // BUILDFLAG(DFMIFY_DEV_UI)
+#else   // defined(OS_ANDROID)
 #include "chrome/browser/ui/webui/bookmarks/bookmarks_ui.h"
 #include "chrome/browser/ui/webui/devtools_ui.h"
 #include "chrome/browser/ui/webui/downloads/downloads_ui.h"
@@ -143,7 +148,7 @@
 #include "chrome/browser/ui/webui/page_not_available_for_guest/page_not_available_for_guest_ui.h"
 #include "chrome/browser/ui/webui/sync_file_system_internals/sync_file_system_internals_ui.h"
 #include "chrome/browser/ui/webui/system_info_ui.h"
-#endif
+#endif  // defined(OS_ANDROID)
 
 #if defined(OS_CHROMEOS)
 #include "base/system/sys_info.h"
@@ -260,6 +265,15 @@
   return new T(web_ui);
 }
 
+#if defined(OS_ANDROID)
+#if BUILDFLAG(DFMIFY_DEV_UI)
+template <>
+WebUIController* NewWebUI<DevUiLoaderUI>(WebUI* web_ui, const GURL& url) {
+  return new DevUiLoaderUI(web_ui, url);
+}
+#endif  // BUILDFLAG(DFMIFY_DEV_UI)
+#endif  // defined(OS_ANDROID)
+
 #if !defined(OS_ANDROID)
 template <>
 WebUIController* NewWebUI<PageNotAvailableForGuestUI>(WebUI* web_ui,
@@ -347,6 +361,13 @@
     return nullptr;
   }
 
+#if defined(OS_ANDROID)
+#if BUILDFLAG(DFMIFY_DEV_UI)
+  if (url.host_piece() == chrome::kChromeUIDevUiLoaderHost)
+    return &NewWebUI<DevUiLoaderUI>;
+#endif  // BUILDFLAG(DFMIFY_DEV_UI)
+#endif  // defined(OS_ANDROID)
+
   // Please keep this in alphabetical order. If #ifs or special logics are
   // required, add it below in the appropriate section.
   //
diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_constants.cc
index 71adf51..9a0781a4 100644
--- a/chrome/common/webui_url_constants.cc
+++ b/chrome/common/webui_url_constants.cc
@@ -57,6 +57,8 @@
 const char kChromeUIDeviceLogHost[] = "device-log";
 const char kChromeUIDevicesHost[] = "devices";
 const char kChromeUIDevicesURL[] = "chrome://devices/";
+const char kChromeUIDevUiLoaderHost[] = "dev-ui-loader";
+const char kChromeUIDevUiLoaderURL[] = "chrome://dev-ui-loader/";
 const char kChromeUIDomainReliabilityInternalsHost[] =
     "domain-reliability-internals";
 const char kChromeUIDownloadInternalsHost[] = "download-internals";
diff --git a/chrome/common/webui_url_constants.h b/chrome/common/webui_url_constants.h
index 4f3531d..0c46b710 100644
--- a/chrome/common/webui_url_constants.h
+++ b/chrome/common/webui_url_constants.h
@@ -64,6 +64,8 @@
 extern const char kChromeUIDeviceLogHost[];
 extern const char kChromeUIDevicesHost[];
 extern const char kChromeUIDevicesURL[];
+extern const char kChromeUIDevUiLoaderHost[];
+extern const char kChromeUIDevUiLoaderURL[];
 extern const char kChromeUIDomainReliabilityInternalsHost[];
 extern const char kChromeUIDownloadInternalsHost[];
 extern const char kChromeUIDownloadsHost[];
diff --git a/chrome/test/data/xr/e2e_test_files/html/test_inline_vr_poses.html b/chrome/test/data/xr/e2e_test_files/html/test_inline_vr_poses.html
index 67682181..e905a78 100644
--- a/chrome/test/data/xr/e2e_test_files/html/test_inline_vr_poses.html
+++ b/chrome/test/data/xr/e2e_test_files/html/test_inline_vr_poses.html
@@ -25,7 +25,9 @@
         [sessionTypes.IMMERSIVE]: 'local',
         [sessionTypes.MAGIC_WINDOW]: 'local',
         [sessionTypes.AR]: 'local'
-      }
+      };
+
+      nonImmersiveSessionInit = { requiredFeatures: ['local'] };
       requestMagicWindowSession();
 
       let MAX_FRAME_CALLBACKS = 10;
diff --git a/chrome/test/data/xr/e2e_test_files/resources/webxr_boilerplate.js b/chrome/test/data/xr/e2e_test_files/resources/webxr_boilerplate.js
index a05c66a1..719a87f 100644
--- a/chrome/test/data/xr/e2e_test_files/resources/webxr_boilerplate.js
+++ b/chrome/test/data/xr/e2e_test_files/resources/webxr_boilerplate.js
@@ -74,6 +74,7 @@
 sessionInfos[sessionTypes.MAGIC_WINDOW] = new SessionInfo();
 
 var immersiveSessionInit = {};
+var nonImmersiveSessionInit = {};
 
 function getSessionType(session) {
   if (session.mode == 'immersive-vr') {
@@ -209,7 +210,7 @@
 function requestMagicWindowSession() {
   // Set up an inline session (magic window) drawing into the full screen canvas
   // on the page
-  navigator.xr.requestSession('inline')
+  navigator.xr.requestSession('inline', nonImmersiveSessionInit)
   .then((session) => {
     session.mode = 'inline';
     sessionInfos[sessionTypes.MAGIC_WINDOW].currentSession = session;
diff --git a/chromecast/media/cma/backend/android/java/src/org/chromium/chromecast/cma/backend/android/AudioSinkAudioTrackImpl.java b/chromecast/media/cma/backend/android/java/src/org/chromium/chromecast/cma/backend/android/AudioSinkAudioTrackImpl.java
index 25ac84b..20cb3c6 100644
--- a/chromecast/media/cma/backend/android/java/src/org/chromium/chromecast/cma/backend/android/AudioSinkAudioTrackImpl.java
+++ b/chromecast/media/cma/backend/android/java/src/org/chromium/chromecast/cma/backend/android/AudioSinkAudioTrackImpl.java
@@ -12,6 +12,7 @@
 import android.media.AudioTimestamp;
 import android.media.AudioTrack;
 import android.os.Build;
+import android.os.SystemClock;
 import android.support.annotation.IntDef;
 import android.util.SparseIntArray;
 
@@ -109,14 +110,10 @@
     private static final long UNDERRUN_LOG_THROTTLE_PERIOD = SEC_IN_NSEC;
 
     // Internally Android fetches data from AudioTrack buffer in periods of 20ms.
-    private static final long ANDROID_AUDIO_PERIOD_SIZE_USEC = 20000;
-
-    // Minimum amount of data written to the AudioTrack before we can call play().
-    // This is needed to avoid hitting a (false) underrun.
-    private static final long PLAY_START_THRESHOLD_USEC = 40000;
+    private static final long ANDROID_AUDIO_PERIOD_SIZE_US = 20000;
 
     // Threshold at which we start logging low buffer warnings.
-    private static final long VERY_LOW_BUFFER_LEVEL_USEC = ANDROID_AUDIO_PERIOD_SIZE_USEC;
+    private static final long VERY_LOW_BUFFER_LEVEL = ANDROID_AUDIO_PERIOD_SIZE_US;
 
     private static long sInstanceCounter;
 
@@ -135,7 +132,7 @@
     private static final long MAX_TIME_IGNORING_TSTAMPS_NSECS = SEC_IN_NSEC;
 
     // Additional padding for minimum buffer time, determined experimentally.
-    private static final long MIN_BUFFERED_TIME_PADDING_USEC = 120000;
+    private static final long MIN_BUFFERED_TIME_PADDING_US = ANDROID_AUDIO_PERIOD_SIZE_US;
 
     // Max retries for AudioTrackBuilder
     private static final int MAX_RETRIES_FOR_AUDIO_TRACKS = 1;
@@ -152,7 +149,6 @@
     private ThrottledLog mBufferLevelWarningLog;
     private ThrottledLog mUnderrunWarningLog;
     private ThrottledLog mTStampJitterWarningLog;
-    private ThrottledLog mStatisticsLog;
 
     @IntDef({ReferenceTimestampState.STARTING_UP, ReferenceTimestampState.STABLE,
             ReferenceTimestampState.RESYNCING_AFTER_PAUSE,
@@ -181,9 +177,6 @@
 
     private AudioTrack mAudioTrack;
 
-    private long mBufferSizeInSec; // Size of AudioTrack Buffer allocated.
-    private long mBufferLevelUsec;
-
     // Timestamping logic for RenderingDelay calculations. See also the description for
     // getNewFramePos0Timestamp() for additional information.
     private long mRefNanoTimeAtFramePos0; // Reference time used to interpolate new timestamps at
@@ -223,7 +216,7 @@
      * Converts the given nanoseconds value into microseconds with proper rounding. It is assumed
      * that the value given is positive.
      */
-    private static long nSecToUsec(long nsecs) {
+    private static long convertNsecsToUsecs(long nsecs) {
         return (nsecs + 500) / 1000;
     }
 
@@ -239,7 +232,7 @@
     public static long getMinimumBufferedTime(int sampleRateInHz) {
         int sizeBytes = AudioTrack.getMinBufferSize(sampleRateInHz, CHANNEL_CONFIG, AUDIO_FORMAT);
         long sizeUs = SEC_IN_USEC * (long) sizeBytes / (BYTES_PER_FRAME * (long) sampleRateInHz);
-        return sizeUs + MIN_BUFFERED_TIME_PADDING_USEC;
+        return sizeUs + MIN_BUFFERED_TIME_PADDING_US;
     }
 
     @CalledByNative
@@ -296,6 +289,12 @@
         return mLastTimestampUpdateNsec != NO_TIMESTAMP;
     }
 
+    /** Converts the given number of frames into an equivalent nanoTime period. */
+    private long convertFramesToNanoTime(long numOfFrames) {
+        // Use proper rounding (assumes all numbers are positive).
+        return (SEC_IN_NSEC * numOfFrames + mSampleRateInHz / 2) / mSampleRateInHz;
+    }
+
     /**
      * Initializes the instance by creating the AudioTrack object and allocating
      * the shared memory buffers.
@@ -309,7 +308,6 @@
         mBufferLevelWarningLog = new ThrottledLog(Log::w, 5, 1000, 5000);
         mUnderrunWarningLog = new ThrottledLog(Log::w, 5, 1000, 5000);
         mTStampJitterWarningLog = new ThrottledLog(Log::w, 5, 1000, 5000);
-        mStatisticsLog = new ThrottledLog(Log::i, 1, 1000, 5000);
 
         Log.i(mTag,
                 "Init:"
@@ -340,10 +338,10 @@
 
         int bufferSizeInBytes = MIN_BUFFER_SIZE_MULTIPLIER
                 * AudioTrack.getMinBufferSize(mSampleRateInHz, CHANNEL_CONFIG, AUDIO_FORMAT);
-        mBufferSizeInSec = bytesToSec(bufferSizeInBytes);
+        int bufferSizeInMs = 1000 * bufferSizeInBytes / (BYTES_PER_FRAME * mSampleRateInHz);
         Log.i(mTag,
-                "Init: create an AudioTrack of size=" + bufferSizeInBytes + " (" + mBufferSizeInSec
-                        + "sec) usageType=" + usageType + " contentType=" + contentType
+                "Init: create an AudioTrack of size=" + bufferSizeInBytes + " (" + bufferSizeInMs
+                        + "ms) usageType=" + usageType + " contentType=" + contentType
                         + " with session-id=" + sessionId);
 
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
@@ -419,10 +417,16 @@
         return mAudioTrack.getPlayState() == AudioTrack.PLAYSTATE_STOPPED;
     }
 
-    /**
-     * Stops the AudioTrack and returns an estimate of the time it takes for the remaining data
-     * left in the internal queue to be played out (in usecs).
-     */
+    private boolean isPlaying() {
+        return mAudioTrack.getPlayState() == AudioTrack.PLAYSTATE_PLAYING;
+    }
+
+    private boolean isPaused() {
+        return mAudioTrack.getPlayState() == AudioTrack.PLAYSTATE_PAUSED;
+    }
+
+    /** Stops the AudioTrack and returns an estimate of the time it takes for the remaining data
+     * left in the internal queue to be played out (in usecs). */
     @CalledByNative
     private long prepareForShutdown() {
         long playtimeLeftNsecs;
@@ -442,7 +446,7 @@
             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                 long most_frames_left =
                         Math.min(mTotalFramesWritten, mAudioTrack.getBufferSizeInFrames());
-                playtimeLeftNsecs = SEC_IN_NSEC * framesToSec(most_frames_left);
+                playtimeLeftNsecs = convertFramesToNanoTime(most_frames_left);
             } else {
                 // Using pre-M API. Don't know how many frames there are, so assume the worst case.
                 playtimeLeftNsecs = 0;
@@ -452,10 +456,8 @@
     }
 
     @CalledByNative
-    /**
-     * Closes the instance by stopping playback and releasing the AudioTrack
-     * object.
-     */
+    /** Closes the instance by stopping playback and releasing the AudioTrack
+     * object. */
     private void close() {
         Log.i(mTag, "Close AudioSinkAudioTrackImpl!");
         if (!mIsInitialized) {
@@ -480,7 +482,7 @@
         }
     }
 
-    private int getUnderrunCount() {
+    int getUnderrunCount() {
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
             return mAudioTrack.getUnderrunCount();
         }
@@ -488,62 +490,18 @@
         return 0;
     }
 
-    /** Convert the given number of bytes into an equivalent frames with proper rounding */
-    private long bytesToFrames(long bytes) {
-        return (bytes + BYTES_PER_FRAME / 2) / BYTES_PER_FRAME;
-    }
-
-    /** Convert the given number of frames into an equivalent seconds */
-    private long framesToSec(long frames) {
-        return frames / mSampleRateInHz;
-    }
-
-    /** Convert the given number of bytes into an equivalent seconds with proper rounding */
-    private long bytesToSec(long bytes) {
-        return framesToSec(bytesToFrames(bytes));
-    }
-
-    private void startPlayingIfItIsTime() {
-        if (mTotalFramesWritten > PLAY_START_THRESHOLD_USEC) {
-            play();
-        }
-    }
-
-    private void waitUntilBufferAvail(int bytes) {
-        long sleepTimeUsec = SEC_IN_USEC * bytesToSec(bytes);
-        long bufferSizeInUsec = SEC_IN_USEC * mBufferSizeInSec;
-        if (sleepTimeUsec >= bufferSizeInUsec / 2) {
-            sleepTimeUsec = bufferSizeInUsec / 2;
-        } else {
-            long d = sleepTimeUsec / ANDROID_AUDIO_PERIOD_SIZE_USEC;
-            if (d * ANDROID_AUDIO_PERIOD_SIZE_USEC < sleepTimeUsec) {
-                sleepTimeUsec = (d + 1) * ANDROID_AUDIO_PERIOD_SIZE_USEC;
-            }
-        }
-
-        if (DEBUG_LEVEL >= 1) {
-            Log.i(mTag, "Buffer full, sleep for " + sleepTimeUsec + "usec");
-        }
-
-        try {
-            Thread.sleep(sleepTimeUsec / 1000);
-        } catch (InterruptedException ex) {
-            Log.i(mTag, "Sleep was interrupted: " + ex);
-        }
-    }
-
-    /**
-     * Writes the PCM data of the given size into the AudioTrack object. The
+    /** Writes the PCM data of the given size into the AudioTrack object. The
      * PCM data is provided through the memory-mapped ByteBuffer.
      *
      * Returns the number of bytes written into the AudioTrack object, -1 for
      * error.
      */
     @CalledByNative
-    private int writePcm(int totalBytesToWrite) {
+    private int writePcm(int sizeInBytes) {
         if (DEBUG_LEVEL >= 3) {
             Log.i(mTag,
-                    "Writing new PCM data [" + totalBytesToWrite + "] state=" + getPlayStateString()
+                    "Writing new PCM data:"
+                            + " sizeInBytes=" + sizeInBytes + " state=" + getPlayStateString()
                             + " underruns=" + mLastUnderrunCount);
         }
 
@@ -553,70 +511,65 @@
         }
 
         // Check buffer level before feeding in new data.
-        checkBufferLevel();
+        if (haveValidRefPoint()) checkBufferLevel();
 
         // Setup the PCM ByteBuffer correctly.
-        mPcmBuffer.limit(totalBytesToWrite);
+        mPcmBuffer.limit(sizeInBytes);
+        mPcmBuffer.position(0);
 
-        long maxTimeToWriteNsec = 2 * bytesToSec(totalBytesToWrite) * SEC_IN_NSEC;
-        long startTimeNsec = System.nanoTime();
+        // Feed into AudioTrack - blocking call.
+        long beforeMsecs = SystemClock.elapsedRealtime();
+        int bytesWritten = mAudioTrack.write(mPcmBuffer, sizeInBytes, AudioTrack.WRITE_BLOCKING);
 
-        int bytesLeftToWrite = totalBytesToWrite;
-        int bytesWritten = 0;
+        if (bytesWritten < 0) {
+            int error = bytesWritten;
+            Log.e(mTag, "Couldn't write into AudioTrack (" + error + ")");
+            return error;
+        }
 
-        while (bytesLeftToWrite > 0) {
-            mPcmBuffer.position(totalBytesToWrite - bytesLeftToWrite);
-            long beforeNsecs = System.nanoTime();
-            bytesWritten =
-                    mAudioTrack.write(mPcmBuffer, bytesLeftToWrite, AudioTrack.WRITE_NON_BLOCKING);
+        if (isStopped()) {
+            // Data was written, start playing now.
+            play();
 
-            if (bytesWritten < 0) {
-                int error = bytesWritten;
-                Log.e(mTag, "Couldn't write into AudioTrack (" + error + ")");
-                return error;
-            }
-
-            mTotalFramesWritten = bytesToFrames(bytesWritten);
-            bytesLeftToWrite -= bytesWritten;
-            if (isStopped()) {
-                startPlayingIfItIsTime();
-            }
-
-            if (DEBUG_LEVEL >= 3) {
-                long lastRenderingDelayUsec =
-                        (mLastRenderingDelayUsecs == NO_TIMESTAMP) ? -1 : mLastRenderingDelayUsecs;
-                Log.i(mTag,
-                        "  wrote " + bytesWritten + "/" + bytesWritten
-                                + " total_bytes_written=" + (mTotalFramesWritten * BYTES_PER_FRAME)
-                                + " took:" + (elapsedNsec(beforeNsecs) / MSEC_IN_NSEC) + "ms"
-                                + " RenderingDelayUsec=" + lastRenderingDelayUsec
-                                + " BufferLevelUsec=" + mBufferLevelUsec);
-            }
-
-            if (bytesLeftToWrite > 0) {
-                waitUntilBufferAvail(bytesLeftToWrite);
-                checkBufferLevel();
-                maxTimeToWriteNsec = 2 * bytesToSec(bytesLeftToWrite) * SEC_IN_NSEC;
-                startTimeNsec = System.nanoTime();
-            }
-
-            if (bytesLeftToWrite > 0 && elapsedNsec(startTimeNsec) > maxTimeToWriteNsec) {
-                Log.e(mTag, "Took too long to write all data, abort!");
-                break;
+            // If not all data fit on the previous write() call (since we were not in PLAYING state
+            // it didn't block), do a second (now blocking) call to write().
+            int bytesLeft = sizeInBytes - bytesWritten;
+            if (bytesLeft > 0) {
+                mPcmBuffer.position(bytesWritten);
+                int moreBytesWritten =
+                        mAudioTrack.write(mPcmBuffer, bytesLeft, AudioTrack.WRITE_BLOCKING);
+                if (moreBytesWritten < 0) {
+                    int error = moreBytesWritten;
+                    Log.e(mTag, "Couldn't write into AudioTrack (" + error + ")");
+                    return error;
+                }
+                bytesWritten += moreBytesWritten;
             }
         }
-        int totalBytesWritten = totalBytesToWrite - bytesLeftToWrite;
-        updateSampleRateMeasure(bytesToFrames(totalBytesWritten));
 
-        updateRefPointTimestamp();
+        int framesWritten = bytesWritten / BYTES_PER_FRAME;
+        mTotalFramesWritten += framesWritten;
 
-        long lastRenderingDelayUsec =
-                (mLastRenderingDelayUsecs == NO_TIMESTAMP) ? -1 : mLastRenderingDelayUsecs;
-        mStatisticsLog.log(mTag,
-                "SampleRateHz=" + mSampleRateInHz + " RenderingDelayUsec=" + lastRenderingDelayUsec
-                        + " BufferLevelUsec=" + mBufferLevelUsec);
+        if (DEBUG_LEVEL >= 3) {
+            Log.i(mTag,
+                    "  wrote " + bytesWritten + "/" + sizeInBytes
+                            + " total_bytes_written=" + (mTotalFramesWritten * BYTES_PER_FRAME)
+                            + " took:" + (SystemClock.elapsedRealtime() - beforeMsecs) + "ms");
+        }
 
-        return totalBytesWritten;
+        if (bytesWritten < sizeInBytes && isPaused()) {
+            // We are in PAUSED state, in which case the write() is non-blocking. If not all data
+            // was written, we will come back here once we transition back into PLAYING state.
+            return bytesWritten;
+        }
+
+        updateSampleRateMeasure(framesWritten);
+
+        updateRenderingDelay();
+
+        // TODO(ckuiper): Log key statistics (SR and underruns, e.g.) in regular intervals
+
+        return bytesWritten;
     }
 
     /** Returns the elapsed time from the given start_time until now, in nsec. */
@@ -626,13 +579,13 @@
 
     private void checkBufferLevel() {
         long bufferLevel = mTotalFramesWritten - mAudioTrack.getPlaybackHeadPosition();
-        mBufferLevelUsec = SEC_IN_USEC * framesToSec(bufferLevel);
-        if (mBufferLevelUsec <= VERY_LOW_BUFFER_LEVEL_USEC) {
+        long bufferLevelUsec = convertNsecsToUsecs(convertFramesToNanoTime(bufferLevel));
+        if (bufferLevelUsec <= VERY_LOW_BUFFER_LEVEL) {
             long lastRenderingDelayUsec =
                     (mLastRenderingDelayUsecs == NO_TIMESTAMP) ? -1 : mLastRenderingDelayUsecs;
             boolean hitUnderrun = (getUnderrunCount() != mLastUnderrunCount);
             mBufferLevelWarningLog.log(mTag,
-                    "Low buffer level=" + mBufferLevelUsec + "us "
+                    "Low buffer level=" + bufferLevelUsec + "us "
                             + " RD=" + lastRenderingDelayUsec + (hitUnderrun ? "us *" : "us"));
         }
     }
@@ -667,8 +620,8 @@
 
         // Interpolate to get proper Rendering delay.
         long playoutTimeNsecs = getInterpolatedTStampNsecs(mTotalFramesWritten);
-        long playoutTimeUsecs = nSecToUsec(playoutTimeNsecs);
-        long nowUsecs = nSecToUsec(System.nanoTime());
+        long playoutTimeUsecs = convertNsecsToUsecs(playoutTimeNsecs);
+        long nowUsecs = convertNsecsToUsecs(System.nanoTime());
         long delayUsecs = playoutTimeUsecs - nowUsecs;
 
         // Populate RenderingDelay return value for native land.
@@ -701,14 +654,14 @@
             return NO_TIMESTAMP;
         }
         mOriginalFramePosOfLastTimestamp = ts.framePosition;
-        return ts.nanoTime - (SEC_IN_NSEC * framesToSec(ts.framePosition));
+        return ts.nanoTime - convertFramesToNanoTime(ts.framePosition);
     }
 
     /**
      * Returns a timestamp for the given frame position, interpolated from the reference timestamp.
      */
     private long getInterpolatedTStampNsecs(long framePosition) {
-        return mRefNanoTimeAtFramePos0 + (SEC_IN_NSEC * framesToSec(framePosition));
+        return mRefNanoTimeAtFramePos0 + convertFramesToNanoTime(framePosition);
     }
 
     /** Checks for underruns and if detected invalidates the reference point timestamp. */
@@ -834,7 +787,7 @@
                 long devNsec = mRefNanoTimeAtFramePos0 - newNanoTimeAtFramePos0;
                 if (Math.abs(devNsec) > TSTAMP_DEV_THRESHOLD_TO_IGNORE_NSEC) {
                     mTStampJitterWarningLog.log(
-                            mTag, "Too jittery timestamp (" + nSecToUsec(devNsec) + ")");
+                            mTag, "Too jittery timestamp (" + convertNsecsToUsecs(devNsec) + ")");
                     long timeSinceLastGoodTstamp = elapsedNsec(mLastTimestampUpdateNsec);
                     if (timeSinceLastGoodTstamp <= MAX_TIME_IGNORING_TSTAMPS_NSECS) {
                         return; // Ignore this one.
@@ -854,8 +807,8 @@
 
         // Got a new value.
         if (DEBUG_LEVEL >= 1) {
-            long dev1 = nSecToUsec(prevRefNanoTimeAtFramePos0 - newNanoTimeAtFramePos0);
-            long dev2 = nSecToUsec(prevRefNanoTimeAtFramePos0 - mRefNanoTimeAtFramePos0);
+            long dev1 = convertNsecsToUsecs(prevRefNanoTimeAtFramePos0 - newNanoTimeAtFramePos0);
+            long dev2 = convertNsecsToUsecs(prevRefNanoTimeAtFramePos0 - mRefNanoTimeAtFramePos0);
             Log.i(mTag,
                     "Updated mRefNanoTimeAtFramePos0=" + mRefNanoTimeAtFramePos0 / 1000 + " us ("
                             + dev1 + "/" + dev2 + ")");
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM
index 8def6ff..a7d3698 100644
--- a/chromeos/CHROMEOS_LKGM
+++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@
-12465.0.0
\ No newline at end of file
+12472.0.0
\ No newline at end of file
diff --git a/chromeos/components/sync_wifi/BUILD.gn b/chromeos/components/sync_wifi/BUILD.gn
index d9d987be..2ffae58 100644
--- a/chromeos/components/sync_wifi/BUILD.gn
+++ b/chromeos/components/sync_wifi/BUILD.gn
@@ -28,6 +28,7 @@
   testonly = true
   sources = [
     "pending_network_configuration_tracker_impl_unittest.cc",
+    "test_specifics_generator.h",
     "wifi_configuration_bridge_unittest.cc",
   ]
   deps = [
diff --git a/chromeos/components/sync_wifi/pending_network_configuration_tracker.h b/chromeos/components/sync_wifi/pending_network_configuration_tracker.h
index 57c2013..ebef811 100644
--- a/chromeos/components/sync_wifi/pending_network_configuration_tracker.h
+++ b/chromeos/components/sync_wifi/pending_network_configuration_tracker.h
@@ -14,8 +14,8 @@
 
 namespace sync_wifi {
 
-// Tracks updates to the local network stack while they are pending.  Updates
-// are stored persistently.
+// Tracks updates to the local network stack while they are pending, including
+// how many attempts have been executed.  Updates are stored persistently.
 class PendingNetworkConfigurationTracker {
  public:
   PendingNetworkConfigurationTracker() = default;
@@ -35,16 +35,19 @@
   virtual void MarkComplete(const std::string& change_guid,
                             const std::string& ssid) = 0;
 
-  // Returns true if this change is still in the list.  If a change is in
-  // process but a new change comes in for the same ssid, the first one will
-  // no longer be tracked.
-  virtual bool IsChangeTracked(const std::string& change_guid,
-                               const std::string& ssid) = 0;
-
-  // Returns all in flight updates.
+  // Returns all pending updates.
   virtual std::vector<PendingNetworkConfigurationUpdate>
   GetPendingUpdates() = 0;
 
+  // Returns the requested pending update, if it exists.
+  virtual base::Optional<PendingNetworkConfigurationUpdate> GetPendingUpdate(
+      const std::string& change_guid,
+      const std::string& ssid) = 0;
+
+  // Increments the number of completed attempts for the given update.
+  virtual void IncrementCompletedAttempts(const std::string& change_guid,
+                                          const std::string& ssid) = 0;
+
  private:
   DISALLOW_COPY_AND_ASSIGN(PendingNetworkConfigurationTracker);
 };
diff --git a/chromeos/components/sync_wifi/pending_network_configuration_tracker_impl.cc b/chromeos/components/sync_wifi/pending_network_configuration_tracker_impl.cc
index 48fbb34..03e96dd 100644
--- a/chromeos/components/sync_wifi/pending_network_configuration_tracker_impl.cc
+++ b/chromeos/components/sync_wifi/pending_network_configuration_tracker_impl.cc
@@ -14,12 +14,34 @@
 const char kPendingNetworkConfigurationsPref[] =
     "sync_wifi.pending_network_configuration_updates";
 const char kChangeGuidKey[] = "ChangeGuid";
+const char kCompletedAttemptsKey[] = "CompletedAttempts";
 const char kSpecificsKey[] = "Specifics";
 
 std::string GeneratePath(const std::string& ssid, const std::string& subkey) {
   return base::StringPrintf("%s.%s", ssid.c_str(), subkey.c_str());
 }
 
+sync_wifi::PendingNetworkConfigurationUpdate ConvertToPendingUpdate(
+    base::Value* dict,
+    const std::string ssid) {
+  std::string* change_guid = dict->FindStringKey(kChangeGuidKey);
+  base::Optional<sync_pb::WifiConfigurationSpecificsData> specifics;
+  std::string* specifics_string = dict->FindStringKey(kSpecificsKey);
+  if (!specifics_string->empty()) {
+    sync_pb::WifiConfigurationSpecificsData data;
+    data.ParseFromString(*specifics_string);
+    specifics = data;
+  }
+  base::Optional<int> completed_attempts =
+      dict->FindIntPath(kCompletedAttemptsKey);
+
+  DCHECK(change_guid);
+  DCHECK(completed_attempts);
+
+  return sync_wifi::PendingNetworkConfigurationUpdate(
+      ssid, *change_guid, specifics, completed_attempts.value());
+}
+
 }  // namespace
 
 namespace sync_wifi {
@@ -52,42 +74,47 @@
   dict_.SetPath(GeneratePath(ssid, kChangeGuidKey), base::Value(change_guid));
   dict_.SetPath(GeneratePath(ssid, kSpecificsKey),
                 base::Value(serialized_specifics));
+  dict_.SetPath(GeneratePath(ssid, kCompletedAttemptsKey), base::Value(0));
   pref_service_->Set(kPendingNetworkConfigurationsPref, dict_);
 }
 
 void PendingNetworkConfigurationTrackerImpl::MarkComplete(
     const std::string& change_guid,
     const std::string& ssid) {
-  if (!IsChangeTracked(change_guid, ssid))
+  if (!GetPendingUpdate(change_guid, ssid))
     return;
 
   dict_.RemovePath(ssid);
   pref_service_->Set(kPendingNetworkConfigurationsPref, dict_);
 }
 
-bool PendingNetworkConfigurationTrackerImpl::IsChangeTracked(
+void PendingNetworkConfigurationTrackerImpl::IncrementCompletedAttempts(
     const std::string& change_guid,
     const std::string& ssid) {
-  std::string* found_id =
-      dict_.FindStringPath(GeneratePath(ssid, kChangeGuidKey));
-  return found_id && *found_id == change_guid;
+  std::string path = GeneratePath(ssid, kCompletedAttemptsKey);
+  base::Optional<int> completed_attempts = dict_.FindIntPath(path);
+  dict_.SetIntPath(path, completed_attempts.value() + 1);
 }
 
 std::vector<PendingNetworkConfigurationUpdate>
 PendingNetworkConfigurationTrackerImpl::GetPendingUpdates() {
   std::vector<PendingNetworkConfigurationUpdate> list;
   for (const auto& entry : dict_.DictItems()) {
-    base::Optional<sync_pb::WifiConfigurationSpecificsData> specifics;
-    std::string* specifics_string = entry.second.FindStringKey(kSpecificsKey);
-    if (!specifics_string->empty()) {
-      sync_pb::WifiConfigurationSpecificsData data;
-      data.ParseFromString(*specifics_string);
-      specifics = data;
-    }
-    std::string* change_guid = entry.second.FindStringKey(kChangeGuidKey);
-    list.emplace_back(/*ssid=*/entry.first, *change_guid, specifics);
+    list.push_back(
+        ConvertToPendingUpdate(/*dict=*/&entry.second, /*ssid=*/entry.first));
   }
   return list;
 }
+base::Optional<PendingNetworkConfigurationUpdate>
+PendingNetworkConfigurationTrackerImpl::GetPendingUpdate(
+    const std::string& change_guid,
+    const std::string& ssid) {
+  std::string* found_id =
+      dict_.FindStringPath(GeneratePath(ssid, kChangeGuidKey));
+  if (!found_id || *found_id != change_guid)
+    return base::nullopt;
+
+  return ConvertToPendingUpdate(dict_.FindPath(ssid), ssid);
+}
 
 }  // namespace sync_wifi
diff --git a/chromeos/components/sync_wifi/pending_network_configuration_tracker_impl.h b/chromeos/components/sync_wifi/pending_network_configuration_tracker_impl.h
index 0aa5bf8d..2d5a21c 100644
--- a/chromeos/components/sync_wifi/pending_network_configuration_tracker_impl.h
+++ b/chromeos/components/sync_wifi/pending_network_configuration_tracker_impl.h
@@ -33,9 +33,12 @@
       override;
   void MarkComplete(const std::string& change_guid,
                     const std::string& ssid) override;
-  bool IsChangeTracked(const std::string& change_guid,
-                       const std::string& ssid) override;
+  void IncrementCompletedAttempts(const std::string& change_guid,
+                                  const std::string& ssid) override;
   std::vector<PendingNetworkConfigurationUpdate> GetPendingUpdates() override;
+  base::Optional<PendingNetworkConfigurationUpdate> GetPendingUpdate(
+      const std::string& change_guid,
+      const std::string& ssid) override;
 
  private:
   PrefService* pref_service_;
diff --git a/chromeos/components/sync_wifi/pending_network_configuration_tracker_impl_unittest.cc b/chromeos/components/sync_wifi/pending_network_configuration_tracker_impl_unittest.cc
index d4dde97..155bce9 100644
--- a/chromeos/components/sync_wifi/pending_network_configuration_tracker_impl_unittest.cc
+++ b/chromeos/components/sync_wifi/pending_network_configuration_tracker_impl_unittest.cc
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/components/sync_wifi/pending_network_configuration_tracker_impl.h"
-
 #include <memory>
 
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/optional.h"
+#include "chromeos/components/sync_wifi/pending_network_configuration_tracker_impl.h"
+#include "chromeos/components/sync_wifi/test_specifics_generator.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -59,6 +59,26 @@
     return found_guid && *found_guid == update_guid;
   }
 
+  void AssertTrackerHasMatchingUpdate(
+      const std::string& update_guid,
+      const std::string& ssid,
+      int completed_attempts = 0,
+      const base::Optional<sync_pb::WifiConfigurationSpecificsData> specifics =
+          base::nullopt) {
+    base::Optional<PendingNetworkConfigurationUpdate> update =
+        tracker()->GetPendingUpdate(update_guid, ssid);
+    ASSERT_TRUE(update);
+    ASSERT_EQ(ssid, update->ssid());
+    ASSERT_EQ(completed_attempts, update->completed_attempts());
+    std::string serialized_specifics_wants;
+    std::string serialized_specifics_has;
+    if (specifics)
+      specifics->SerializeToString(&serialized_specifics_wants);
+    if (update->specifics())
+      update->specifics()->SerializeToString(&serialized_specifics_has);
+    ASSERT_EQ(serialized_specifics_wants, serialized_specifics_has);
+  }
+
  private:
   std::unique_ptr<sync_preferences::TestingPrefServiceSyncable>
       test_pref_service_;
@@ -69,23 +89,32 @@
 TEST_F(PendingNetworkConfigurationTrackerImplTest, TestMarkComplete) {
   tracker()->TrackPendingUpdate(kChangeGuid1, kFredSsid,
                                 /*specifics=*/base::nullopt);
-  EXPECT_TRUE(tracker()->IsChangeTracked(kChangeGuid1, kFredSsid));
+  AssertTrackerHasMatchingUpdate(kChangeGuid1, kFredSsid);
   EXPECT_EQ(1u, GetPref()->DictSize());
   EXPECT_TRUE(DoesPrefContainPendingUpdate(kFredSsid, kChangeGuid1));
   tracker()->MarkComplete(kChangeGuid1, kFredSsid);
-  EXPECT_FALSE(tracker()->IsChangeTracked(kChangeGuid1, kFredSsid));
+  EXPECT_FALSE(tracker()->GetPendingUpdate(kChangeGuid1, kFredSsid));
   EXPECT_EQ(0u, GetPref()->DictSize());
 }
 
 TEST_F(PendingNetworkConfigurationTrackerImplTest, TestTwoChangesSameNetwork) {
   tracker()->TrackPendingUpdate(kChangeGuid1, kFredSsid,
                                 /*specifics=*/base::nullopt);
-  EXPECT_TRUE(tracker()->IsChangeTracked(kChangeGuid1, kFredSsid));
+  tracker()->IncrementCompletedAttempts(kChangeGuid1, kFredSsid);
+  AssertTrackerHasMatchingUpdate(kChangeGuid1, kFredSsid,
+                                 /*completed_attempts=*/1);
   EXPECT_EQ(1u, GetPref()->DictSize());
+  EXPECT_EQ(1, tracker()
+                   ->GetPendingUpdate(kChangeGuid1, kFredSsid)
+                   ->completed_attempts());
+
   tracker()->TrackPendingUpdate(kChangeGuid2, kFredSsid,
                                 /*specifics=*/base::nullopt);
-  EXPECT_FALSE(tracker()->IsChangeTracked(kChangeGuid1, kFredSsid));
-  EXPECT_TRUE(tracker()->IsChangeTracked(kChangeGuid2, kFredSsid));
+  EXPECT_FALSE(tracker()->GetPendingUpdate(kChangeGuid1, kFredSsid));
+  AssertTrackerHasMatchingUpdate(kChangeGuid2, kFredSsid);
+  EXPECT_EQ(0, tracker()
+                   ->GetPendingUpdate(kChangeGuid2, kFredSsid)
+                   ->completed_attempts());
   EXPECT_EQ(1u, GetPref()->DictSize());
 }
 
@@ -93,13 +122,13 @@
        TestTwoChangesDifferentNetworks) {
   tracker()->TrackPendingUpdate(kChangeGuid1, kFredSsid,
                                 /*specifics=*/base::nullopt);
-  EXPECT_TRUE(tracker()->IsChangeTracked(kChangeGuid1, kFredSsid));
+  AssertTrackerHasMatchingUpdate(kChangeGuid1, kFredSsid);
   EXPECT_TRUE(DoesPrefContainPendingUpdate(kFredSsid, kChangeGuid1));
   EXPECT_EQ(1u, GetPref()->DictSize());
   tracker()->TrackPendingUpdate(kChangeGuid2, kMangoSsid,
                                 /*specifics=*/base::nullopt);
-  EXPECT_TRUE(tracker()->IsChangeTracked(kChangeGuid1, kFredSsid));
-  EXPECT_TRUE(tracker()->IsChangeTracked(kChangeGuid2, kMangoSsid));
+  AssertTrackerHasMatchingUpdate(kChangeGuid1, kFredSsid);
+  AssertTrackerHasMatchingUpdate(kChangeGuid2, kMangoSsid);
   EXPECT_TRUE(DoesPrefContainPendingUpdate(kFredSsid, kChangeGuid1));
   EXPECT_TRUE(DoesPrefContainPendingUpdate(kMangoSsid, kChangeGuid2));
   EXPECT_EQ(2u, GetPref()->DictSize());
@@ -125,4 +154,36 @@
   EXPECT_EQ(kMangoSsid, list[0].ssid());
 }
 
+TEST_F(PendingNetworkConfigurationTrackerImplTest, TestGetPendingUpdate) {
+  sync_pb::WifiConfigurationSpecificsData specifics =
+      CreateSpecifics(kFredSsid);
+  tracker()->TrackPendingUpdate(kChangeGuid1, kFredSsid, specifics);
+
+  AssertTrackerHasMatchingUpdate(kChangeGuid1, kFredSsid,
+                                 /*completed_attempts=*/0, specifics);
+
+  EXPECT_FALSE(tracker()->GetPendingUpdate(kChangeGuid2, kMangoSsid));
+}
+
+TEST_F(PendingNetworkConfigurationTrackerImplTest, TestRetryCounting) {
+  tracker()->TrackPendingUpdate(kChangeGuid1, kFredSsid,
+                                /*specifics=*/base::nullopt);
+  AssertTrackerHasMatchingUpdate(kChangeGuid1, kFredSsid);
+  EXPECT_EQ(1u, GetPref()->DictSize());
+  EXPECT_EQ(0, tracker()
+                   ->GetPendingUpdate(kChangeGuid1, kFredSsid)
+                   ->completed_attempts());
+  tracker()->IncrementCompletedAttempts(kChangeGuid1, kFredSsid);
+  tracker()->IncrementCompletedAttempts(kChangeGuid1, kFredSsid);
+  tracker()->IncrementCompletedAttempts(kChangeGuid1, kFredSsid);
+  EXPECT_EQ(3, tracker()
+                   ->GetPendingUpdate(kChangeGuid1, kFredSsid)
+                   ->completed_attempts());
+  tracker()->IncrementCompletedAttempts(kChangeGuid1, kFredSsid);
+  tracker()->IncrementCompletedAttempts(kChangeGuid1, kFredSsid);
+  EXPECT_EQ(5, tracker()
+                   ->GetPendingUpdate(kChangeGuid1, kFredSsid)
+                   ->completed_attempts());
+}
+
 }  // namespace sync_wifi
diff --git a/chromeos/components/sync_wifi/pending_network_configuration_update.cc b/chromeos/components/sync_wifi/pending_network_configuration_update.cc
index 48361a4..600bd77 100644
--- a/chromeos/components/sync_wifi/pending_network_configuration_update.cc
+++ b/chromeos/components/sync_wifi/pending_network_configuration_update.cc
@@ -9,8 +9,12 @@
 PendingNetworkConfigurationUpdate::PendingNetworkConfigurationUpdate(
     const std::string& ssid,
     const std::string& change_guid,
-    const base::Optional<sync_pb::WifiConfigurationSpecificsData>& specifics)
-    : ssid_(ssid), change_guid_(change_guid), specifics_(specifics) {}
+    const base::Optional<sync_pb::WifiConfigurationSpecificsData>& specifics,
+    int completed_attempts)
+    : ssid_(ssid),
+      change_guid_(change_guid),
+      specifics_(specifics),
+      completed_attempts_(completed_attempts) {}
 
 PendingNetworkConfigurationUpdate::PendingNetworkConfigurationUpdate(
     const PendingNetworkConfigurationUpdate& update) = default;
diff --git a/chromeos/components/sync_wifi/pending_network_configuration_update.h b/chromeos/components/sync_wifi/pending_network_configuration_update.h
index 0a76caf..c0907826 100644
--- a/chromeos/components/sync_wifi/pending_network_configuration_update.h
+++ b/chromeos/components/sync_wifi/pending_network_configuration_update.h
@@ -14,13 +14,15 @@
 
 namespace sync_wifi {
 
-// Represents a change to the local network stack which hasn't been saved yet.
+// Represents a change to the local network stack which hasn't been saved yet,
+// including the number of completed attempts to save it.
 class PendingNetworkConfigurationUpdate {
  public:
   PendingNetworkConfigurationUpdate(
       const std::string& ssid,
       const std::string& change_guid,
-      const base::Optional<sync_pb::WifiConfigurationSpecificsData>& specifics);
+      const base::Optional<sync_pb::WifiConfigurationSpecificsData>& specifics,
+      int completed_attempts);
   PendingNetworkConfigurationUpdate(
       const PendingNetworkConfigurationUpdate& update);
   virtual ~PendingNetworkConfigurationUpdate();
@@ -38,6 +40,8 @@
     return specifics_;
   }
 
+  int completed_attempts() { return completed_attempts_; }
+
   // Returns |true| if the update operation is deleting a network.
   bool IsDeleteOperation() const;
 
@@ -45,6 +49,7 @@
   const std::string ssid_;
   const std::string change_guid_;
   const base::Optional<sync_pb::WifiConfigurationSpecificsData> specifics_;
+  int completed_attempts_;
 };
 
 }  // namespace sync_wifi
diff --git a/chromeos/components/sync_wifi/test_specifics_generator.h b/chromeos/components/sync_wifi/test_specifics_generator.h
new file mode 100644
index 0000000..d9873b0
--- /dev/null
+++ b/chromeos/components/sync_wifi/test_specifics_generator.h
@@ -0,0 +1,38 @@
+// Copyright 2019 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 "components/sync/protocol/wifi_configuration_specifics.pb.h"
+
+#ifndef CHROMEOS_COMPONENTS_SYNC_WIFI_TEST_SPECIFICS_GENERATOR_H_
+#define CHROMEOS_COMPONENTS_SYNC_WIFI_TEST_SPECIFICS_GENERATOR_H_
+
+namespace sync_wifi {
+
+namespace {
+
+sync_pb::WifiConfigurationSpecificsData CreateSpecifics(
+    const std::string& ssid) {
+  sync_pb::WifiConfigurationSpecificsData specifics;
+  specifics.set_ssid(ssid);
+  specifics.set_security_type(
+      sync_pb::WifiConfigurationSpecificsData::SECURITY_TYPE_PSK);
+  specifics.set_passphrase("password");
+  specifics.set_automatically_connect(
+      sync_pb::WifiConfigurationSpecificsData::AUTOMATICALLY_CONNECT_ENABLED);
+  specifics.set_is_preferred(
+      sync_pb::WifiConfigurationSpecificsData::IS_PREFERRED_ENABLED);
+  specifics.set_metered(
+      sync_pb::WifiConfigurationSpecificsData::METERED_OPTION_AUTO);
+  sync_pb::WifiConfigurationSpecificsData_ProxyConfiguration proxy_config;
+  proxy_config.set_proxy_option(sync_pb::WifiConfigurationSpecificsData::
+                                    ProxyConfiguration::PROXY_OPTION_DISABLED);
+  specifics.mutable_proxy_configuration()->CopyFrom(proxy_config);
+  return specifics;
+}
+
+}  // namespace
+
+}  // namespace sync_wifi
+
+#endif  // CHROMEOS_COMPONENTS_SYNC_WIFI_TEST_SPECIFICS_GENERATOR_H_
diff --git a/chromeos/components/sync_wifi/wifi_configuration_bridge_unittest.cc b/chromeos/components/sync_wifi/wifi_configuration_bridge_unittest.cc
index 38ac2649..c2aa328 100644
--- a/chromeos/components/sync_wifi/wifi_configuration_bridge_unittest.cc
+++ b/chromeos/components/sync_wifi/wifi_configuration_bridge_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/run_loop.h"
 #include "base/test/task_environment.h"
 #include "chromeos/components/sync_wifi/synced_network_updater.h"
+#include "chromeos/components/sync_wifi/test_specifics_generator.h"
 #include "components/sync/model/entity_change.h"
 #include "components/sync/model/metadata_batch.h"
 #include "components/sync/model/mock_model_type_change_processor.h"
@@ -39,24 +40,6 @@
 const char kSsidMeow[] = "meow";
 const char kSsidWoof[] = "woof";
 
-WifiConfigurationSpecificsData CreateSpecifics(const std::string& ssid) {
-  WifiConfigurationSpecificsData specifics;
-  specifics.set_ssid(ssid);
-  specifics.set_security_type(
-      WifiConfigurationSpecificsData::SECURITY_TYPE_PSK);
-  specifics.set_passphrase("password");
-  specifics.set_automatically_connect(
-      WifiConfigurationSpecificsData::AUTOMATICALLY_CONNECT_ENABLED);
-  specifics.set_is_preferred(
-      WifiConfigurationSpecificsData::IS_PREFERRED_ENABLED);
-  specifics.set_metered(WifiConfigurationSpecificsData::METERED_OPTION_AUTO);
-  sync_pb::WifiConfigurationSpecificsData_ProxyConfiguration proxy_config;
-  proxy_config.set_proxy_option(WifiConfigurationSpecificsData::
-                                    ProxyConfiguration::PROXY_OPTION_DISABLED);
-  specifics.mutable_proxy_configuration()->CopyFrom(proxy_config);
-  return specifics;
-}
-
 std::unique_ptr<syncer::EntityData> GenerateWifiEntityData(
     const sync_pb::WifiConfigurationSpecificsData& data) {
   auto entity_data = std::make_unique<syncer::EntityData>();
diff --git a/chromeos/services/device_sync/cryptauth_v2_enrollment_manager_impl.cc b/chromeos/services/device_sync/cryptauth_v2_enrollment_manager_impl.cc
index 76eefcb..c9df1a6 100644
--- a/chromeos/services/device_sync/cryptauth_v2_enrollment_manager_impl.cc
+++ b/chromeos/services/device_sync/cryptauth_v2_enrollment_manager_impl.cc
@@ -116,7 +116,7 @@
   }
 }
 
-void RecordEnrollmentResult(CryptAuthEnrollmentResult result) {
+void RecordEnrollmentResult(const CryptAuthEnrollmentResult& result) {
   base::UmaHistogramBoolean("CryptAuth.EnrollmentV2.Result.Success",
                             result.IsSuccess());
   base::UmaHistogramEnumeration("CryptAuth.EnrollmentV2.Result.ResultCode",
@@ -461,37 +461,41 @@
   // Once an enrollment attempt finishes, no other callbacks should be
   // invoked. This is particularly relevant for timeout failures.
   callback_weak_ptr_factory_.InvalidateWeakPtrs();
+
+  // The enrollment result might be owned by the enroller, so we copy the result
+  // here before destroying the enroller.
+  CryptAuthEnrollmentResult enrollment_result_copy = enrollment_result;
   enroller_.reset();
 
-  if (enrollment_result.IsSuccess()) {
+  if (enrollment_result_copy.IsSuccess()) {
     PA_LOG(INFO) << "Enrollment attempt with invocation reason "
                  << current_client_metadata_->invocation_reason()
                  << " succeeded with result code "
-                 << enrollment_result.result_code();
+                 << enrollment_result_copy.result_code();
   } else {
     PA_LOG(WARNING) << "Enrollment attempt with invocation reason "
                     << current_client_metadata_->invocation_reason()
                     << " failed with result code "
-                    << enrollment_result.result_code();
+                    << enrollment_result_copy.result_code();
   }
 
   current_client_metadata_.reset();
 
-  RecordEnrollmentResult(enrollment_result);
+  RecordEnrollmentResult(enrollment_result_copy);
 
-  scheduler_->HandleEnrollmentResult(enrollment_result);
+  scheduler_->HandleEnrollmentResult(enrollment_result_copy);
 
   PA_LOG(INFO) << "Time until next enrollment attempt: "
                << GetTimeToNextAttempt();
 
-  if (!enrollment_result.IsSuccess()) {
+  if (!enrollment_result_copy.IsSuccess()) {
     PA_LOG(INFO) << "Number of consecutive Enrollment failures: "
                  << scheduler_->GetNumConsecutiveEnrollmentFailures();
   }
 
   SetState(State::kIdle);
 
-  NotifyEnrollmentFinished(enrollment_result.IsSuccess());
+  NotifyEnrollmentFinished(enrollment_result_copy.IsSuccess());
 }
 
 void CryptAuthV2EnrollmentManagerImpl::SetState(State state) {
diff --git a/components/constrained_window/constrained_window_views.cc b/components/constrained_window/constrained_window_views.cc
index d818daec..d6f68e0a 100644
--- a/components/constrained_window/constrained_window_views.cc
+++ b/components/constrained_window/constrained_window_views.cc
@@ -208,12 +208,12 @@
 views::Widget* CreateWebModalDialogViews(views::WidgetDelegate* dialog,
                                          content::WebContents* web_contents) {
   DCHECK_EQ(ui::MODAL_TYPE_CHILD, dialog->GetModalType());
+  web_modal::WebContentsModalDialogManager* manager =
+      web_modal::WebContentsModalDialogManager::FromWebContents(web_contents);
+  CHECK(manager);
   return views::DialogDelegate::CreateDialogWidget(
       dialog, nullptr,
-      web_modal::WebContentsModalDialogManager::FromWebContents(web_contents)
-          ->delegate()
-          ->GetWebContentsModalDialogHost()
-          ->GetHostView());
+      manager->delegate()->GetWebContentsModalDialogHost()->GetHostView());
 }
 
 views::Widget* CreateBrowserModalDialogViews(views::DialogDelegate* dialog,
diff --git a/components/exo/data_offer.cc b/components/exo/data_offer.cc
index 1dd9a97..eff37d39 100644
--- a/components/exo/data_offer.cc
+++ b/components/exo/data_offer.cc
@@ -275,12 +275,13 @@
     data_.emplace(utf16_mime_type,
                   EncodeAsRefCountedString(string_content, kUTF16));
     delegate_->OnOffer(utf16_mime_type);
-    // TODO(crbug.com/981247) Arc treates "text/plain" as UTF-16, which is in
-    // volation of the spec. We will temporarily continue to advertise UTF-16
-    // data as "text/plain". Once arc is fixed, we will convert it to ascii.
     const std::string text_plain_mime_type = std::string(ui::kMimeTypeText);
+    // The MIME type standard says that new text/ subtypes should default to a
+    // UTF-8 encoding, but that old ones, including text/plain, keep ASCII as
+    // the default. Nonetheless, we use UTF8 here because it is a superset of
+    // ASCII and the defacto standard text encoding.
     data_.emplace(text_plain_mime_type,
-                  EncodeAsRefCountedString(string_content, kUTF16));
+                  EncodeAsRefCountedString(string_content, kUTF8));
     delegate_->OnOffer(text_plain_mime_type);
   }
 
diff --git a/components/exo/data_offer_unittest.cc b/components/exo/data_offer_unittest.cc
index 0e63c41c..162d36a 100644
--- a/components/exo/data_offer_unittest.cc
+++ b/components/exo/data_offer_unittest.cc
@@ -237,6 +237,15 @@
   data.SetString(base::ASCIIToUTF16("Test data"));
   data_offer.SetDropData(&file_helper, data);
 
+  base::ScopedFD read_pipe;
+  base::ScopedFD write_pipe;
+  ASSERT_TRUE(base::CreatePipe(&read_pipe, &write_pipe));
+
+  data_offer.Receive("text/plain", std::move(write_pipe));
+  std::string result;
+  ASSERT_TRUE(ReadString(std::move(read_pipe), &result));
+  EXPECT_EQ("Test data", result);
+
   base::ScopedFD read_pipe_16;
   base::ScopedFD write_pipe_16;
   ASSERT_TRUE(base::CreatePipe(&read_pipe_16, &write_pipe_16));
diff --git a/components/network_session_configurator/browser/network_session_configurator.cc b/components/network_session_configurator/browser/network_session_configurator.cc
index af811ae..8bd2b25b 100644
--- a/components/network_session_configurator/browser/network_session_configurator.cc
+++ b/components/network_session_configurator/browser/network_session_configurator.cc
@@ -634,6 +634,12 @@
       }
       it++;
     }
+    for (const auto& supported_version : quic::AllSupportedVersions()) {
+      if (quic::AlpnForVersion(supported_version) == version) {
+        supported_versions.push_back(supported_version);
+        break;
+      }
+    }
   }
   return supported_versions;
 }
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 45e18a4..7c7c9b6 100644
--- a/components/network_session_configurator/browser/network_session_configurator_unittest.cc
+++ b/components/network_session_configurator/browser/network_session_configurator_unittest.cc
@@ -508,6 +508,19 @@
   EXPECT_EQ(supported_versions, params_.quic_params.supported_versions);
 }
 
+TEST_F(NetworkSessionConfiguratorTest, QuicVersionFromFieldTrialParamsAlpn) {
+  std::map<std::string, std::string> field_trial_params;
+  field_trial_params["quic_version"] = "h3-T048";
+  variations::AssociateVariationParams("QUIC", "Enabled", field_trial_params);
+  base::FieldTrialList::CreateFieldTrial("QUIC", "Enabled");
+
+  ParseFieldTrials();
+
+  quic::ParsedQuicVersionVector supported_versions = {
+      {quic::PROTOCOL_TLS1_3, quic::QUIC_VERSION_48}};
+  EXPECT_EQ(supported_versions, params_.quic_params.supported_versions);
+}
+
 TEST_F(NetworkSessionConfiguratorTest,
        MultipleQuicVersionFromFieldTrialParams) {
   std::map<std::string, std::string> field_trial_params;
@@ -703,6 +716,18 @@
   }
 }
 
+TEST_F(NetworkSessionConfiguratorTest, QuicVersionAlpn) {
+  base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
+  command_line.AppendSwitch(switches::kEnableQuic);
+  command_line.AppendSwitchASCII(switches::kQuicVersion, "h3-T048");
+
+  ParseCommandLineAndFieldTrials(command_line);
+
+  quic::ParsedQuicVersionVector supported_versions = {
+      {quic::PROTOCOL_TLS1_3, quic::QUIC_VERSION_48}};
+  EXPECT_EQ(supported_versions, params_.quic_params.supported_versions);
+}
+
 TEST_F(NetworkSessionConfiguratorTest, OriginToForceQuicOn) {
   base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
   command_line.AppendSwitch(switches::kEnableQuic);
diff --git a/components/safe_browsing/password_protection/password_protection_request.cc b/components/safe_browsing/password_protection/password_protection_request.cc
index 15ff2a1f..c5c09294 100644
--- a/components/safe_browsing/password_protection/password_protection_request.cc
+++ b/components/safe_browsing/password_protection/password_protection_request.cc
@@ -80,7 +80,8 @@
     bool password_field_exists,
     PasswordProtectionService* pps,
     int request_timeout_in_ms)
-    : web_contents_(web_contents),
+    : content::WebContentsObserver(web_contents),
+      web_contents_(web_contents),
       main_frame_url_(main_frame_url),
       password_form_action_(password_form_action),
       password_form_frame_url_(password_form_frame_url),
@@ -541,4 +542,8 @@
   throttles_.clear();
 }
 
+void PasswordProtectionRequest::WebContentsDestroyed() {
+  Cancel(/*timed_out=*/false);
+}
+
 }  // namespace safe_browsing
diff --git a/components/safe_browsing/password_protection/password_protection_request.h b/components/safe_browsing/password_protection/password_protection_request.h
index 84f9378..6720a117 100644
--- a/components/safe_browsing/password_protection/password_protection_request.h
+++ b/components/safe_browsing/password_protection/password_protection_request.h
@@ -17,6 +17,7 @@
 #include "components/safe_browsing/password_protection/password_protection_service.h"
 #include "components/safe_browsing/proto/csd.pb.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/web_contents_observer.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 
 class GURL;
@@ -50,10 +51,10 @@
 // (8) |   UI   | On receiving response, handle response and finish.
 //     |        | On request timeout, cancel request.
 //     |        | On deletion of |password_protection_service_|, cancel request.
-class PasswordProtectionRequest
-    : public base::RefCountedThreadSafe<
-          PasswordProtectionRequest,
-          content::BrowserThread::DeleteOnUIThread> {
+class PasswordProtectionRequest : public base::RefCountedThreadSafe<
+                                      PasswordProtectionRequest,
+                                      content::BrowserThread::DeleteOnUIThread>,
+                                  public content::WebContentsObserver {
  public:
   PasswordProtectionRequest(content::WebContents* web_contents,
                             const GURL& main_frame_url,
@@ -122,6 +123,9 @@
   // Cancels navigation if there is modal warning showing, resumes it otherwise.
   void HandleDeferredNavigations();
 
+  // WebContentsObserver implementation
+  void WebContentsDestroyed() override;
+
  protected:
   friend class base::RefCountedThreadSafe<PasswordProtectionRequest>;
 
@@ -131,7 +135,7 @@
   friend class base::DeleteHelper<PasswordProtectionRequest>;
   friend class PasswordProtectionServiceTest;
   friend class ChromePasswordProtectionServiceTest;
-  virtual ~PasswordProtectionRequest();
+  ~PasswordProtectionRequest() override;
 
   // Start checking the whitelist.
   void CheckWhitelist();
diff --git a/components/safe_browsing/password_protection/password_protection_service_unittest.cc b/components/safe_browsing/password_protection/password_protection_service_unittest.cc
index 12626335..cc4a0b0 100644
--- a/components/safe_browsing/password_protection/password_protection_service_unittest.cc
+++ b/components/safe_browsing/password_protection/password_protection_service_unittest.cc
@@ -1339,6 +1339,14 @@
   EXPECT_EQ(0U, GetNumberOfNavigationThrottles());
 }
 
+TEST_P(PasswordProtectionServiceTest, TestWebContentsDestroyed) {
+  content::WebContents* web_contents = GetWebContents();
+  InitializeAndStartPasswordOnFocusRequest(
+      true /* match whitelist */, 10000 /* timeout in ms */, web_contents);
+  delete web_contents;
+  task_environment_.FastForwardUntilNoTasksRemain();
+}
+
 INSTANTIATE_TEST_SUITE_P(Regular,
                          PasswordProtectionServiceTest,
                          ::testing::Values(false));
diff --git a/components/security_state/core/security_state.cc b/components/security_state/core/security_state.cc
index 61f6b11..82c3420a 100644
--- a/components/security_state/core/security_state.cc
+++ b/components/security_state/core/security_state.cc
@@ -71,6 +71,22 @@
   }
 }
 
+std::string GetHistogramSuffixForSafetyTipStatus(
+    security_state::SafetyTipStatus safety_tip_status) {
+  switch (safety_tip_status) {
+    case security_state::SafetyTipStatus::kUnknown:
+      return "SafetyTip_Unknown";
+    case security_state::SafetyTipStatus::kNone:
+      return "SafetyTip_None";
+    case security_state::SafetyTipStatus::kBadReputation:
+      return "SafetyTip_BadReputation";
+    case security_state::SafetyTipStatus::kLookalike:
+      return "SafetyTip_Lookalike";
+  };
+  NOTREACHED();
+  return std::string();
+}
+
 }  // namespace
 
 SecurityLevel GetSecurityLevel(
@@ -231,6 +247,11 @@
   return prefix + "." + GetHistogramSuffixForSecurityLevel(level);
 }
 
+std::string GetSafetyTipHistogramName(const std::string& prefix,
+                                      SafetyTipStatus safety_tip_status) {
+  return prefix + "." + GetHistogramSuffixForSafetyTipStatus(safety_tip_status);
+}
+
 bool IsSHA1InChain(const VisibleSecurityState& visible_security_state) {
   return visible_security_state.certificate &&
          (visible_security_state.cert_status &
diff --git a/components/security_state/core/security_state.h b/components/security_state/core/security_state.h
index 21264f18..b624933 100644
--- a/components/security_state/core/security_state.h
+++ b/components/security_state/core/security_state.h
@@ -210,6 +210,10 @@
 std::string GetSecurityLevelHistogramName(
     const std::string& prefix, security_state::SecurityLevel level);
 
+// Returns the given prefix suffixed with a dot and the given Safety Tip status.
+std::string GetSafetyTipHistogramName(const std::string& prefix,
+                                      SafetyTipStatus safety_tip_status);
+
 bool IsSHA1InChain(const VisibleSecurityState& visible_security_state);
 
 }  // namespace security_state
diff --git a/content/browser/android/text_suggestion_host_android.cc b/content/browser/android/text_suggestion_host_android.cc
index 37e7049..6e0cabe5 100644
--- a/content/browser/android/text_suggestion_host_android.cc
+++ b/content/browser/android/text_suggestion_host_android.cc
@@ -63,7 +63,7 @@
 void TextSuggestionHostAndroid::UpdateRenderProcessConnection(
     RenderWidgetHostViewAndroid* old_rwhva,
     RenderWidgetHostViewAndroid* new_rwhva) {
-  text_suggestion_backend_ = nullptr;
+  text_suggestion_backend_.reset();
   if (old_rwhva)
     old_rwhva->set_text_suggestion_host(nullptr);
   if (new_rwhva)
@@ -75,8 +75,8 @@
     JNIEnv* env,
     const JavaParamRef<jobject>&,
     const base::android::JavaParamRef<jstring>& replacement) {
-  const blink::mojom::TextSuggestionBackendPtr& text_suggestion_backend =
-      GetTextSuggestionBackend();
+  const mojo::Remote<blink::mojom::TextSuggestionBackend>&
+      text_suggestion_backend = GetTextSuggestionBackend();
   if (!text_suggestion_backend)
     return;
   text_suggestion_backend->ApplySpellCheckSuggestion(
@@ -88,8 +88,8 @@
     const JavaParamRef<jobject>&,
     int marker_tag,
     int suggestion_index) {
-  const blink::mojom::TextSuggestionBackendPtr& text_suggestion_backend =
-      GetTextSuggestionBackend();
+  const mojo::Remote<blink::mojom::TextSuggestionBackend>&
+      text_suggestion_backend = GetTextSuggestionBackend();
   if (!text_suggestion_backend)
     return;
   text_suggestion_backend->ApplyTextSuggestion(marker_tag, suggestion_index);
@@ -98,8 +98,8 @@
 void TextSuggestionHostAndroid::DeleteActiveSuggestionRange(
     JNIEnv*,
     const JavaParamRef<jobject>&) {
-  const blink::mojom::TextSuggestionBackendPtr& text_suggestion_backend =
-      GetTextSuggestionBackend();
+  const mojo::Remote<blink::mojom::TextSuggestionBackend>&
+      text_suggestion_backend = GetTextSuggestionBackend();
   if (!text_suggestion_backend)
     return;
   text_suggestion_backend->DeleteActiveSuggestionRange();
@@ -109,8 +109,8 @@
     JNIEnv* env,
     const JavaParamRef<jobject>&,
     const base::android::JavaParamRef<jstring>& word) {
-  const blink::mojom::TextSuggestionBackendPtr& text_suggestion_backend =
-      GetTextSuggestionBackend();
+  const mojo::Remote<blink::mojom::TextSuggestionBackend>&
+      text_suggestion_backend = GetTextSuggestionBackend();
   if (!text_suggestion_backend)
     return;
   text_suggestion_backend->OnNewWordAddedToDictionary(
@@ -120,8 +120,8 @@
 void TextSuggestionHostAndroid::OnSuggestionMenuClosed(
     JNIEnv*,
     const JavaParamRef<jobject>&) {
-  const blink::mojom::TextSuggestionBackendPtr& text_suggestion_backend =
-      GetTextSuggestionBackend();
+  const mojo::Remote<blink::mojom::TextSuggestionBackend>&
+      text_suggestion_backend = GetTextSuggestionBackend();
   if (!text_suggestion_backend)
     return;
   text_suggestion_backend->OnSuggestionMenuClosed();
@@ -254,20 +254,20 @@
   return nullptr;
 }
 
-const blink::mojom::TextSuggestionBackendPtr&
+const mojo::Remote<blink::mojom::TextSuggestionBackend>&
 TextSuggestionHostAndroid::GetTextSuggestionBackend() {
   if (!text_suggestion_backend_) {
     if (RenderFrameHost* rfh = GetFocusedFrame()) {
       rfh->GetRemoteInterfaces()->GetInterface(
-          mojo::MakeRequest(&text_suggestion_backend_));
+          text_suggestion_backend_.BindNewPipeAndPassReceiver());
     }
   }
   return text_suggestion_backend_;
 }
 
 void TextSuggestionHostAndroid::OnSuggestionMenuTimeout() {
-  const blink::mojom::TextSuggestionBackendPtr& text_suggestion_backend =
-      GetTextSuggestionBackend();
+  const mojo::Remote<blink::mojom::TextSuggestionBackend>&
+      text_suggestion_backend = GetTextSuggestionBackend();
   if (!text_suggestion_backend)
     return;
   text_suggestion_backend->SuggestionMenuTimeoutCallback(
diff --git a/content/browser/android/text_suggestion_host_android.h b/content/browser/android/text_suggestion_host_android.h
index 340343a..6de00b1 100644
--- a/content/browser/android/text_suggestion_host_android.h
+++ b/content/browser/android/text_suggestion_host_android.h
@@ -7,6 +7,7 @@
 
 #include "content/browser/android/render_widget_host_connector.h"
 #include "content/browser/renderer_host/input/timeout_monitor.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
 #include "third_party/blink/public/mojom/input/input_host.mojom.h"
 #include "third_party/blink/public/mojom/input/input_messages.mojom.h"
@@ -96,7 +97,8 @@
  private:
   RenderFrameHost* GetFocusedFrame();
   base::android::ScopedJavaLocalRef<jobject> GetJavaTextSuggestionHost();
-  const blink::mojom::TextSuggestionBackendPtr& GetTextSuggestionBackend();
+  const mojo::Remote<blink::mojom::TextSuggestionBackend>&
+  GetTextSuggestionBackend();
   // Used by the spell check menu timer to notify Blink that the timer has
   // expired.
   void OnSuggestionMenuTimeout();
@@ -106,7 +108,7 @@
   // Current RenderWidgetHostView connected to this instance. Can be null.
   RenderWidgetHostViewAndroid* rwhva_;
   JavaObjectWeakGlobalRef java_text_suggestion_host_;
-  blink::mojom::TextSuggestionBackendPtr text_suggestion_backend_;
+  mojo::Remote<blink::mojom::TextSuggestionBackend> text_suggestion_backend_;
   TimeoutMonitor suggestion_menu_timeout_;
 };
 
diff --git a/content/browser/android/text_suggestion_host_mojo_impl_android.cc b/content/browser/android/text_suggestion_host_mojo_impl_android.cc
index c16d8c0c..d46c449 100644
--- a/content/browser/android/text_suggestion_host_mojo_impl_android.cc
+++ b/content/browser/android/text_suggestion_host_mojo_impl_android.cc
@@ -5,7 +5,7 @@
 #include "content/browser/android/text_suggestion_host_mojo_impl_android.h"
 
 #include "content/browser/android/text_suggestion_host_android.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "mojo/public/cpp/bindings/self_owned_receiver.h"
 
 namespace content {
 
@@ -16,10 +16,10 @@
 // static
 void TextSuggestionHostMojoImplAndroid::Create(
     TextSuggestionHostAndroid* text_suggestion_host,
-    blink::mojom::TextSuggestionHostRequest request) {
-  mojo::MakeStrongBinding(
+    mojo::PendingReceiver<blink::mojom::TextSuggestionHost> receiver) {
+  mojo::MakeSelfOwnedReceiver(
       std::make_unique<TextSuggestionHostMojoImplAndroid>(text_suggestion_host),
-      std::move(request));
+      std::move(receiver));
 }
 
 void TextSuggestionHostMojoImplAndroid::StartSuggestionMenuTimer() {
diff --git a/content/browser/android/text_suggestion_host_mojo_impl_android.h b/content/browser/android/text_suggestion_host_mojo_impl_android.h
index b5a0eee..78a5f45 100644
--- a/content/browser/android/text_suggestion_host_mojo_impl_android.h
+++ b/content/browser/android/text_suggestion_host_mojo_impl_android.h
@@ -5,6 +5,7 @@
 #ifndef CONTENT_BROWSER_ANDROID_TEXT_SUGGESTION_HOST_MOJO_IMPL_ANDROID_H_
 #define CONTENT_BROWSER_ANDROID_TEXT_SUGGESTION_HOST_MOJO_IMPL_ANDROID_H_
 
+#include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "third_party/blink/public/mojom/input/input_host.mojom.h"
 
 namespace content {
@@ -17,8 +18,9 @@
  public:
   explicit TextSuggestionHostMojoImplAndroid(TextSuggestionHostAndroid*);
 
-  static void Create(TextSuggestionHostAndroid*,
-                     blink::mojom::TextSuggestionHostRequest request);
+  static void Create(
+      TextSuggestionHostAndroid*,
+      mojo::PendingReceiver<blink::mojom::TextSuggestionHost> receiver);
 
   void StartSuggestionMenuTimer() final;
 
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index c5bc1e6..c5434f3 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -4476,7 +4476,7 @@
       base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kEnableExperimentalWebPlatformFeatures)) {
     registry_->AddInterface(base::BindRepeating(
-        &RenderFrameHostImpl::BindSmsReceiverRequest, base::Unretained(this)));
+        &RenderFrameHostImpl::BindSmsReceiverReceiver, base::Unretained(this)));
   }
 }
 
@@ -6313,14 +6313,14 @@
   return chooser;
 }
 
-void RenderFrameHostImpl::BindSmsReceiverRequest(
-    blink::mojom::SmsReceiverRequest request) {
+void RenderFrameHostImpl::BindSmsReceiverReceiver(
+    mojo::PendingReceiver<blink::mojom::SmsReceiver> receiver) {
   if (GetParent()) {
     mojo::ReportBadMessage("Must be in top-level browser context.");
     return;
   }
   auto* provider = BrowserMainLoop::GetInstance()->GetSmsProvider();
-  SmsService::Create(provider, this, std::move(request));
+  SmsService::Create(provider, this, std::move(receiver));
 }
 
 void RenderFrameHostImpl::GetInterface(
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index 7b41f4f..9e031023 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -1520,7 +1520,8 @@
       mojo::PendingReceiver<blink::mojom::Authenticator> receiver);
 #endif
 
-  void BindSmsReceiverRequest(blink::mojom::SmsReceiverRequest request);
+  void BindSmsReceiverReceiver(
+      mojo::PendingReceiver<blink::mojom::SmsReceiver> receiver);
 
   // service_manager::mojom::InterfaceProvider:
   void GetInterface(const std::string& interface_name,
diff --git a/content/browser/frame_host/render_frame_proxy_host.cc b/content/browser/frame_host/render_frame_proxy_host.cc
index dc5b056..3235bc0c 100644
--- a/content/browser/frame_host/render_frame_proxy_host.cc
+++ b/content/browser/frame_host/render_frame_proxy_host.cc
@@ -460,12 +460,18 @@
 
       // Transfer user activation state in the frame tree in the browser and
       // the non-source and non-target renderer processes when
-      // |transfer_user_activation| is true.
+      // |transfer_user_activation| is true. We are making an expriment with
+      // dynamic delegation of "autoplay" capability using this post message
+      // approach to transfer user activation.
       // TODO(lanwei): we should transfer user activation state only when
       // |source_rfh| and |target_rfh| are in the same frame tree.
-      if (base::FeatureList::IsEnabled(
+      bool should_transfer_user_activation =
+          base::FeatureList::IsEnabled(
               features::kUserActivationPostMessageTransfer) &&
-          message.transfer_user_activation &&
+          message.transfer_user_activation;
+      should_transfer_user_activation =
+          should_transfer_user_activation || message.allow_autoplay;
+      if (should_transfer_user_activation &&
           source_rfh->frame_tree_node()->HasTransientUserActivation()) {
         target_rfh->frame_tree_node()->TransferUserActivationFrom(source_rfh);
       }
diff --git a/content/browser/indexed_db/indexed_db_index_writer.cc b/content/browser/indexed_db/indexed_db_index_writer.cc
index 8b53ee34..9bdb91f2 100644
--- a/content/browser/indexed_db/indexed_db_index_writer.cc
+++ b/content/browser/indexed_db/indexed_db_index_writer.cc
@@ -13,6 +13,7 @@
 #include "content/browser/indexed_db/indexed_db_tracing.h"
 #include "content/browser/indexed_db/indexed_db_transaction.h"
 #include "third_party/blink/public/common/indexeddb/indexeddb_metadata.h"
+#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h"
 
 using base::ASCIIToUTF16;
 using blink::IndexedDBIndexKeys;
@@ -131,13 +132,27 @@
     // A copy is made because additional keys may be added.
     std::vector<IndexedDBKey> keys = it.keys;
 
-    // If the object_store is using auto_increment, then any indexes with an
-    // identical key_path need to also use the primary (generated) key as a key.
-    if (key_was_generated && (index.key_path == object_store.key_path))
-      keys.push_back(primary_key);
+    // If the object_store is using a key generator to produce the primary key,
+    // and the store uses in-line keys, index key paths may reference it.
+    if (key_was_generated && !object_store.key_path.IsNull()) {
+      if (index.key_path == object_store.key_path) {
+        // The index key path is the same as the store's key path - no index key
+        // will have been sent by the front end, so synthesize one here.
+        keys.push_back(primary_key);
+
+      } else if (index.key_path.type() == blink::mojom::IDBKeyPathType::Array) {
+        // An index with compound keys for a store with a key generator and
+        // in-line keys may need subkeys filled in. These are represented as
+        // "holes", which are not otherwise allowed.
+        for (size_t i = 0; i < keys.size(); ++i) {
+          if (keys[i].HasHoles())
+            keys[i] = keys[i].FillHoles(primary_key);
+        }
+      }
+    }
 
     std::unique_ptr<IndexWriter> index_writer(
-        std::make_unique<IndexWriter>(index, keys));
+        std::make_unique<IndexWriter>(index, std::move(keys)));
     bool can_add_keys = false;
     bool backing_store_success =
         index_writer->VerifyIndexKeys(backing_store,
diff --git a/content/browser/net/reporting_service_proxy.cc b/content/browser/net/reporting_service_proxy.cc
index 38b4037..7963744 100644
--- a/content/browser/net/reporting_service_proxy.cc
+++ b/content/browser/net/reporting_service_proxy.cc
@@ -15,7 +15,7 @@
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/site_instance.h"
 #include "content/public/browser/storage_partition.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "mojo/public/cpp/bindings/self_owned_receiver.h"
 #include "net/reporting/reporting_report.h"
 #include "net/reporting/reporting_service.h"
 #include "net/url_request/url_request_context.h"
@@ -152,12 +152,12 @@
 // static
 void CreateReportingServiceProxy(
     int render_process_id,
-    blink::mojom::ReportingServiceProxyRequest request) {
+    mojo::PendingReceiver<blink::mojom::ReportingServiceProxy> receiver) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
-  mojo::MakeStrongBinding(
+  mojo::MakeSelfOwnedReceiver(
       std::make_unique<ReportingServiceProxyImpl>(render_process_id),
-      std::move(request));
+      std::move(receiver));
 }
 
 }  // namespace content
diff --git a/content/browser/net/reporting_service_proxy.h b/content/browser/net/reporting_service_proxy.h
index 3764098..489f553 100644
--- a/content/browser/net/reporting_service_proxy.h
+++ b/content/browser/net/reporting_service_proxy.h
@@ -5,6 +5,7 @@
 #ifndef CONTENT_BROWSER_NET_REPORTING_SERVICE_PROXY_H_
 #define CONTENT_BROWSER_NET_REPORTING_SERVICE_PROXY_H_
 
+#include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "third_party/blink/public/mojom/reporting/reporting.mojom.h"
 
 namespace content {
@@ -13,7 +14,7 @@
 // |render_process_id|'s NetworkContext. This must be called on the UI thread.
 void CreateReportingServiceProxy(
     int render_process_id,
-    blink::mojom::ReportingServiceProxyRequest request);
+    mojo::PendingReceiver<blink::mojom::ReportingServiceProxy> receiver);
 
 }  // namespace content
 
diff --git a/content/browser/service_worker/service_worker_context_core.cc b/content/browser/service_worker/service_worker_context_core.cc
index ad49c24..e87204fc 100644
--- a/content/browser/service_worker/service_worker_context_core.cc
+++ b/content/browser/service_worker/service_worker_context_core.cc
@@ -502,45 +502,6 @@
   return next_embedded_worker_id_++;
 }
 
-scoped_refptr<blink::URLLoaderFactoryBundle>
-ServiceWorkerContextCore::GetLoaderFactoryBundleForUpdateCheck() {
-  DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
-  DCHECK(blink::ServiceWorkerUtils::IsImportedScriptUpdateCheckEnabled());
-
-  // Update the default factory in the bundle with a newly cloned network
-  // factory before update check because the old default factory may be invalid
-  // due to crash of network service.
-  // TODO(crbug.com/995763): This should call WillCreateURLLoaderFactory().
-
-  if (ServiceWorkerContext::IsServiceWorkerOnUIEnabled()) {
-    StoragePartitionImpl* storage_partition = wrapper()->storage_partition();
-    if (storage_partition) {
-      mojo::PendingRemote<network::mojom::URLLoaderFactory> remote;
-      scoped_refptr<network::SharedURLLoaderFactory> network_factory =
-          storage_partition->GetURLLoaderFactoryForBrowserProcess();
-      network_factory->Clone(remote.InitWithNewPipeAndPassReceiver());
-
-      auto pending_factory_bundle =
-          std::make_unique<blink::URLLoaderFactoryBundleInfo>();
-      pending_factory_bundle->pending_default_factory() = std::move(remote);
-      loader_factory_bundle_for_update_check_->Update(
-          std::move(pending_factory_bundle));
-    }
-  } else {
-    network::mojom::URLLoaderFactoryPtr network_factory_ptr;
-    loader_factory_getter_->CloneNetworkFactory(
-        mojo::MakeRequest(&network_factory_ptr));
-    auto pending_factory_bundle =
-        std::make_unique<blink::URLLoaderFactoryBundleInfo>();
-    pending_factory_bundle->pending_default_factory() =
-        network_factory_ptr.PassInterface();
-    loader_factory_bundle_for_update_check_->Update(
-        std::move(pending_factory_bundle));
-  }
-
-  return loader_factory_bundle_for_update_check_;
-}
-
 void ServiceWorkerContextCore::RegistrationComplete(
     const GURL& scope,
     ServiceWorkerContextCore::RegistrationCallback callback,
diff --git a/content/browser/service_worker/service_worker_context_core.h b/content/browser/service_worker/service_worker_context_core.h
index 164c4ef8..c3fbdcfa 100644
--- a/content/browser/service_worker/service_worker_context_core.h
+++ b/content/browser/service_worker/service_worker_context_core.h
@@ -280,21 +280,17 @@
     return loader_factory_getter_.get();
   }
 
+  const scoped_refptr<blink::URLLoaderFactoryBundle>&
+  loader_factory_bundle_for_update_check() {
+    return loader_factory_bundle_for_update_check_;
+  }
+
   base::WeakPtr<ServiceWorkerContextCore> AsWeakPtr() {
     return weak_factory_.GetWeakPtr();
   }
 
   int GetNextEmbeddedWorkerId();
 
-  // Called when ServiceWorkerImportedScriptUpdateCheck is enabled.
-  // Returns a factory bundle suitable for the browser process to use to fetch
-  // a non-installed service worker main script or imported script during an
-  // update check. It must not be sent to a renderer process. The bundle does
-  // not support reconnection to the network service, so it should be used for
-  // only a single service worker update check.
-  scoped_refptr<blink::URLLoaderFactoryBundle>
-  GetLoaderFactoryBundleForUpdateCheck();
-
  private:
   friend class ServiceWorkerContextCoreTest;
   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextCoreTest, FailureInfo);
diff --git a/content/browser/service_worker/service_worker_context_wrapper.cc b/content/browser/service_worker/service_worker_context_wrapper.cc
index 5ab1912..d9082e6 100644
--- a/content/browser/service_worker/service_worker_context_wrapper.cc
+++ b/content/browser/service_worker/service_worker_context_wrapper.cc
@@ -1920,6 +1920,91 @@
   return factory_bundle;
 }
 
+void ServiceWorkerContextWrapper::GetLoaderFactoryForUpdateCheck(
+    const GURL& scope,
+    base::OnceCallback<void(scoped_refptr<network::SharedURLLoaderFactory>)>
+        callback) {
+  DCHECK_CURRENTLY_ON(GetCoreThreadId());
+
+  RunOrPostTaskOnThread(
+      FROM_HERE, BrowserThread::UI,
+      base::BindOnce(
+          &ServiceWorkerContextWrapper::SetUpLoaderFactoryForUpdateCheckOnUI,
+          this, scope,
+          base::BindOnce(
+              &ServiceWorkerContextWrapper::DidSetUpLoaderFactoryForUpdateCheck,
+              this, std::move(callback))));
+}
+
+void ServiceWorkerContextWrapper::SetUpLoaderFactoryForUpdateCheckOnUI(
+    const GURL& scope,
+    base::OnceCallback<
+        void(mojo::PendingRemote<network::mojom::URLLoaderFactory>,
+             mojo::PendingReceiver<network::mojom::URLLoaderFactory>,
+             bool)> setup_complete_callback) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+  mojo::PendingRemote<network::mojom::URLLoaderFactory> remote;
+  mojo::PendingReceiver<network::mojom::URLLoaderFactory> pending_receiver =
+      remote.InitWithNewPipeAndPassReceiver();
+  mojo::PendingRemote<network::mojom::TrustedURLLoaderHeaderClient>
+      default_header_client;
+  bool bypass_redirect_checks = false;
+
+  if (storage_partition_) {
+    GetContentClient()->browser()->WillCreateURLLoaderFactory(
+        storage_partition_->browser_context(), /*frame=*/nullptr,
+        ChildProcessHost::kInvalidUniqueID,
+        ContentBrowserClient::URLLoaderFactoryType::kServiceWorkerScript,
+        url::Origin::Create(scope), &pending_receiver, &default_header_client,
+        &bypass_redirect_checks);
+  }
+
+  RunOrPostTaskOnThread(
+      FROM_HERE, GetCoreThreadId(),
+      base::BindOnce(std::move(setup_complete_callback), std::move(remote),
+                     std::move(pending_receiver), bypass_redirect_checks));
+}
+
+void ServiceWorkerContextWrapper::DidSetUpLoaderFactoryForUpdateCheck(
+    base::OnceCallback<void(scoped_refptr<network::SharedURLLoaderFactory>)>
+        callback,
+    mojo::PendingRemote<network::mojom::URLLoaderFactory> remote,
+    mojo::PendingReceiver<network::mojom::URLLoaderFactory> pending_receiver,
+    bool bypass_redirect_checks) {
+  DCHECK_CURRENTLY_ON(GetCoreThreadId());
+
+  // Set up a Mojo connection to the network loader factory.
+  if (IsServiceWorkerOnUIEnabled()) {
+    if (!storage_partition_) {
+      std::move(callback).Run(nullptr);
+      return;
+    }
+    scoped_refptr<network::SharedURLLoaderFactory> network_factory =
+        storage_partition_->GetURLLoaderFactoryForBrowserProcess();
+    network_factory->Clone(std::move(pending_receiver));
+  } else {
+    context()->loader_factory_getter()->CloneNetworkFactory(
+        std::move(pending_receiver));
+  }
+
+  // Clone context()->loader_factory_bundle_for_update_check() and set up the
+  // default factory.
+  std::unique_ptr<network::SharedURLLoaderFactoryInfo>
+      loader_factory_bundle_info =
+          context()->loader_factory_bundle_for_update_check()->Clone();
+  static_cast<blink::URLLoaderFactoryBundleInfo*>(
+      loader_factory_bundle_info.get())
+      ->pending_default_factory() = std::move(remote);
+  static_cast<blink::URLLoaderFactoryBundleInfo*>(
+      loader_factory_bundle_info.get())
+      ->set_bypass_redirect_checks(bypass_redirect_checks);
+  scoped_refptr<network::SharedURLLoaderFactory> loader_factory =
+      network::SharedURLLoaderFactory::Create(
+          std::move(loader_factory_bundle_info));
+  std::move(callback).Run(std::move(loader_factory));
+}
+
 bool ServiceWorkerContextWrapper::HasRegistrationForOrigin(
     const GURL& origin) const {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
diff --git a/content/browser/service_worker/service_worker_context_wrapper.h b/content/browser/service_worker/service_worker_context_wrapper.h
index 65a3f16..17166fd 100644
--- a/content/browser/service_worker/service_worker_context_wrapper.h
+++ b/content/browser/service_worker/service_worker_context_wrapper.h
@@ -318,6 +318,13 @@
   bool HasRegistrationForOrigin(const GURL& origin) const;
   void WaitForRegistrationsInitializedForTest();
 
+  // This must be called on the core thread, and the |callback| also runs on
+  // the core thread which can be called with nullptr on failure.
+  void GetLoaderFactoryForUpdateCheck(
+      const GURL& scope,
+      base::OnceCallback<void(scoped_refptr<network::SharedURLLoaderFactory>)>
+          callback);
+
  private:
   friend class BackgroundSyncManagerTest;
   friend class base::RefCountedThreadSafe<ServiceWorkerContextWrapper>;
@@ -436,6 +443,24 @@
   CreateNonNetworkURLLoaderFactoryBundleInfoForUpdateCheck(
       BrowserContext* browser_context);
 
+  void SetUpLoaderFactoryForUpdateCheckOnUI(
+      const GURL& scope,
+      base::OnceCallback<
+          void(mojo::PendingRemote<network::mojom::URLLoaderFactory>,
+               mojo::PendingReceiver<network::mojom::URLLoaderFactory>,
+               bool)> setup_complete_callback);
+
+  // This method completes the remaining work of
+  // SetUpLoaderFactoryForUpdateCheckOnUI() on Core thread: Binds the pending
+  // network factory receiver and creates the loader factory bundle for update
+  // check.
+  void DidSetUpLoaderFactoryForUpdateCheck(
+      base::OnceCallback<void(scoped_refptr<network::SharedURLLoaderFactory>)>
+          callback,
+      mojo::PendingRemote<network::mojom::URLLoaderFactory> remote,
+      mojo::PendingReceiver<network::mojom::URLLoaderFactory> pending_receiver,
+      bool bypass_redirect_checks);
+
   // Called when the stored registrations are loaded, and each time a new
   // service worker is registered.
   void OnRegistrationUpdated(
diff --git a/content/browser/service_worker/service_worker_register_job.cc b/content/browser/service_worker/service_worker_register_job.cc
index 1bd93e6..b2fcab14 100644
--- a/content/browser/service_worker/service_worker_register_job.cc
+++ b/content/browser/service_worker/service_worker_register_job.cc
@@ -312,9 +312,21 @@
 }
 
 void ServiceWorkerRegisterJob::TriggerUpdateCheckInBrowser(
-    ServiceWorkerUpdateChecker::UpdateStatusCallback callback) {
+    scoped_refptr<network::SharedURLLoaderFactory> loader_factory) {
+  DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
   DCHECK_EQ(GetUpdateCheckType(),
             UpdateCheckType::kAllScriptsBeforeStartWorker);
+
+  if (!loader_factory) {
+    // We can't continue with update checking appropriately without
+    // |loader_factory|. Null |loader_factory| means that the storage partition
+    // was not available probably because it's shutting down.
+    // This terminates the current job (|this|).
+    Complete(blink::ServiceWorkerStatusCode::kErrorAbort,
+             ServiceWorkerConsts::kShutdownErrorMessage);
+    return;
+  }
+
   ServiceWorkerVersion* version_to_update = registration()->GetNewestVersion();
   base::TimeDelta time_since_last_check =
       base::Time::Now() - registration()->last_update_check();
@@ -327,10 +339,12 @@
 
   update_checker_ = std::make_unique<ServiceWorkerUpdateChecker>(
       std::move(resources), script_url_, script_resource_id, version_to_update,
-      context_->GetLoaderFactoryBundleForUpdateCheck(), force_bypass_cache_,
+      std::move(loader_factory), force_bypass_cache_,
       registration()->update_via_cache(), time_since_last_check,
       context_.get());
-  update_checker_->Start(std::move(callback));
+  update_checker_->Start(
+      base::BindOnce(&ServiceWorkerRegisterJob::OnUpdateCheckFinished,
+                     weak_factory_.GetWeakPtr()));
 }
 
 ServiceWorkerRegisterJob::UpdateCheckType
@@ -492,8 +506,11 @@
         StartWorkerForUpdate();
         return;
       }
-      TriggerUpdateCheckInBrowser(
-          base::BindOnce(&ServiceWorkerRegisterJob::OnUpdateCheckFinished,
+
+      // This will start the update check after loader factory is retrieved.
+      context_->wrapper()->GetLoaderFactoryForUpdateCheck(
+          scope_,
+          base::BindOnce(&ServiceWorkerRegisterJob::TriggerUpdateCheckInBrowser,
                          weak_factory_.GetWeakPtr()));
       return;
     case UpdateCheckType::kMainScriptDuringStartWorker:
diff --git a/content/browser/service_worker/service_worker_register_job.h b/content/browser/service_worker/service_worker_register_job.h
index f688e5d..e7c84f8 100644
--- a/content/browser/service_worker/service_worker_register_job.h
+++ b/content/browser/service_worker/service_worker_register_job.h
@@ -117,7 +117,7 @@
   // Trigger the UpdateCheckType::kAllScriptsBeforeStartWorker type check if
   // ServiceWorkerImportedScriptUpdateCheck is enabled.
   void TriggerUpdateCheckInBrowser(
-      ServiceWorkerUpdateChecker::UpdateStatusCallback callback);
+      scoped_refptr<network::SharedURLLoaderFactory> loader_factory);
 
   // When ServiceWorkerImportedScriptUpdateCheck is enabled, returns
   // UpdateCheckType::kAllScriptsBeforeStartWorker, otherwise, returns
diff --git a/content/browser/service_worker/service_worker_single_script_update_checker_unittest.cc b/content/browser/service_worker/service_worker_single_script_update_checker_unittest.cc
index 11af6899..76532aa7 100644
--- a/content/browser/service_worker/service_worker_single_script_update_checker_unittest.cc
+++ b/content/browser/service_worker/service_worker_single_script_update_checker_unittest.cc
@@ -8,9 +8,10 @@
 #include "base/bind.h"
 #include "base/containers/queue.h"
 #include "base/run_loop.h"
+#include "base/test/bind_test_util.h"
 #include "base/test/scoped_feature_list.h"
 #include "content/browser/service_worker/embedded_worker_test_helper.h"
-#include "content/browser/service_worker/service_worker_context_core.h"
+#include "content/browser/service_worker/service_worker_context_wrapper.h"
 #include "content/browser/service_worker/service_worker_storage.h"
 #include "content/browser/service_worker/service_worker_test_utils.h"
 #include "content/public/test/browser_task_environment.h"
@@ -117,14 +118,15 @@
       network::TestURLLoaderFactory* loader_factory,
       base::Optional<CheckResult>* out_check_result) {
     helper_->SetNetworkFactory(loader_factory);
+    GetLoaderFactoryForUpdateCheck(scope);
     return std::make_unique<ServiceWorkerSingleScriptUpdateChecker>(
         GURL(url), url == main_script_url, GURL(main_script_url), scope,
         force_bypass_cache, update_via_cache, time_since_last_check,
         net::HttpRequestHeaders(),
         base::BindRepeating([](BrowserContext* context) { return context; },
                             browser_context_.get()),
-        helper_->context()->GetLoaderFactoryBundleForUpdateCheck(),
-        std::move(compare_reader), std::move(copy_reader), std::move(writer),
+        loader_factory_for_update_check_, std::move(compare_reader),
+        std::move(copy_reader), std::move(writer),
         base::BindOnce(
             [](base::Optional<CheckResult>* out_check_result_param,
                const GURL& script_url,
@@ -159,10 +161,25 @@
   }
 
  protected:
+  void GetLoaderFactoryForUpdateCheck(const GURL& scope) {
+    base::RunLoop loop;
+    helper_->context_wrapper()->GetLoaderFactoryForUpdateCheck(
+        scope,
+        base::BindLambdaForTesting(
+            [&](scoped_refptr<network::SharedURLLoaderFactory> loader_factory) {
+              DCHECK(loader_factory);
+              loader_factory_for_update_check_ = std::move(loader_factory);
+              loop.Quit();
+            }));
+    loop.Run();
+  }
+
   BrowserTaskEnvironment task_environment_;
   std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
   base::test::ScopedFeatureList feature_list_;
   std::unique_ptr<TestBrowserContext> browser_context_;
+  scoped_refptr<network::SharedURLLoaderFactory>
+      loader_factory_for_update_check_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerSingleScriptUpdateCheckerTest);
diff --git a/content/browser/sms/sms_service.cc b/content/browser/sms/sms_service.cc
index 19876bd..1232cecf 100644
--- a/content/browser/sms/sms_service.cc
+++ b/content/browser/sms/sms_service.cc
@@ -20,21 +20,23 @@
 
 namespace content {
 
-SmsService::SmsService(SmsProvider* provider,
-                       const url::Origin& origin,
-                       RenderFrameHost* host,
-                       blink::mojom::SmsReceiverRequest request)
-    : FrameServiceBase(host, std::move(request)),
+SmsService::SmsService(
+    SmsProvider* provider,
+    const url::Origin& origin,
+    RenderFrameHost* host,
+    mojo::PendingReceiver<blink::mojom::SmsReceiver> receiver)
+    : FrameServiceBase(host, std::move(receiver)),
       sms_provider_(provider),
       origin_(origin) {}
 
-SmsService::SmsService(SmsProvider* provider,
-                       RenderFrameHost* host,
-                       blink::mojom::SmsReceiverRequest request)
+SmsService::SmsService(
+    SmsProvider* provider,
+    RenderFrameHost* host,
+    mojo::PendingReceiver<blink::mojom::SmsReceiver> receiver)
     : SmsService(provider,
                  host->GetLastCommittedOrigin(),
                  host,
-                 std::move(request)) {}
+                 std::move(receiver)) {}
 
 SmsService::~SmsService() {
   if (callback_)
@@ -42,15 +44,16 @@
 }
 
 // static
-void SmsService::Create(SmsProvider* provider,
-                        RenderFrameHost* host,
-                        blink::mojom::SmsReceiverRequest request) {
+void SmsService::Create(
+    SmsProvider* provider,
+    RenderFrameHost* host,
+    mojo::PendingReceiver<blink::mojom::SmsReceiver> receiver) {
   DCHECK(host);
 
   // SmsService owns itself. It will self-destruct when a mojo interface
   // error occurs, the render frame host is deleted, or the render frame host
   // navigates to a new document.
-  new SmsService(provider, host, std::move(request));
+  new SmsService(provider, host, std::move(receiver));
 }
 
 void SmsService::Receive(base::TimeDelta timeout, ReceiveCallback callback) {
diff --git a/content/browser/sms/sms_service.h b/content/browser/sms/sms_service.h
index 694ce7c..8d093bc 100644
--- a/content/browser/sms/sms_service.h
+++ b/content/browser/sms/sms_service.h
@@ -15,7 +15,7 @@
 #include "content/browser/sms/sms_provider.h"
 #include "content/common/content_export.h"
 #include "content/public/browser/frame_service_base.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "third_party/blink/public/mojom/sms/sms_receiver.mojom.h"
 #include "url/origin.h"
 
@@ -36,13 +36,15 @@
  public:
   static void Create(SmsProvider*,
                      RenderFrameHost*,
-                     blink::mojom::SmsReceiverRequest);
+                     mojo::PendingReceiver<blink::mojom::SmsReceiver>);
 
-  SmsService(SmsProvider*, RenderFrameHost*, blink::mojom::SmsReceiverRequest);
+  SmsService(SmsProvider*,
+             RenderFrameHost*,
+             mojo::PendingReceiver<blink::mojom::SmsReceiver>);
   SmsService(SmsProvider*,
              const url::Origin&,
              RenderFrameHost*,
-             blink::mojom::SmsReceiverRequest);
+             mojo::PendingReceiver<blink::mojom::SmsReceiver>);
   ~SmsService() override;
 
   // content::SmsProvider::Observer:
diff --git a/content/browser/sms/sms_service_unittest.cc b/content/browser/sms/sms_service_unittest.cc
index f69937d..7f60333 100644
--- a/content/browser/sms/sms_service_unittest.cc
+++ b/content/browser/sms/sms_service_unittest.cc
@@ -22,7 +22,7 @@
 #include "content/public/test/test_browser_context.h"
 #include "content/public/test/test_renderer_host.h"
 #include "content/public/test/test_service_manager_context.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "mojo/public/cpp/test_support/test_utils.h"
 #include "services/service_manager/public/cpp/bind_source_info.h"
 #include "services/service_manager/public/cpp/connector.h"
@@ -34,7 +34,6 @@
 using base::Optional;
 using base::TimeDelta;
 using blink::mojom::SmsReceiver;
-using blink::mojom::SmsReceiverPtr;
 using blink::mojom::SmsStatus;
 using std::string;
 using ::testing::_;
@@ -55,7 +54,7 @@
 
 // Service encapsulates a SmsService endpoint, with all of its dependencies
 // mocked out (and the common plumbing needed to inject them), and a
-// SmsReceiverPtr endpoint that tests can use to make requests.
+// mojo::Remote<SmsReceiver> endpoint that tests can use to make requests.
 // It exposes some common methods, like MakeRequest and NotifyReceive, but it
 // also exposes the low level mocks that enables tests to set expectations and
 // control the testing environment.
@@ -65,9 +64,9 @@
     WebContentsImpl* web_contents_impl =
         reinterpret_cast<WebContentsImpl*>(web_contents);
     web_contents_impl->SetDelegate(&delegate_);
-    service_ = std::make_unique<SmsService>(&provider_, origin,
-                                            web_contents->GetMainFrame(),
-                                            mojo::MakeRequest(&service_ptr_));
+    service_ = std::make_unique<SmsService>(
+        &provider_, origin, web_contents->GetMainFrame(),
+        service_remote_.BindNewPipeAndPassReceiver());
   }
 
   Service(WebContents* web_contents)
@@ -93,7 +92,7 @@
   }
 
   void MakeRequest(TimeDelta timeout, SmsReceiver::ReceiveCallback callback) {
-    service_ptr_->Receive(timeout, std::move(callback));
+    service_remote_->Receive(timeout, std::move(callback));
   }
 
   void NotifyReceive(const GURL& url, const string& message) {
@@ -103,7 +102,7 @@
  private:
   NiceMock<MockSmsWebContentsDelegate> delegate_;
   NiceMock<MockSmsProvider> provider_;
-  blink::mojom::SmsReceiverPtr service_ptr_;
+  mojo::Remote<blink::mojom::SmsReceiver> service_remote_;
   std::unique_ptr<SmsService> service_;
 };
 
@@ -353,8 +352,9 @@
   web_contents_impl->SetDelegate(&delegate);
 
   NiceMock<MockSmsProvider> provider;
-  blink::mojom::SmsReceiverPtr service_ptr;
-  SmsService::Create(&provider, main_rfh(), mojo::MakeRequest(&service_ptr));
+  mojo::Remote<blink::mojom::SmsReceiver> service;
+  SmsService::Create(&provider, main_rfh(),
+                     service.BindNewPipeAndPassReceiver());
 
   base::RunLoop navigate;
 
@@ -364,7 +364,7 @@
 
   base::RunLoop reload;
 
-  service_ptr->Receive(
+  service->Receive(
       base::TimeDelta::FromSeconds(10),
       base::BindLambdaForTesting(
           [&reload](SmsStatus status, const base::Optional<std::string>& sms) {
diff --git a/content/browser/storage_partition_impl_unittest.cc b/content/browser/storage_partition_impl_unittest.cc
index d07c963..f4545670 100644
--- a/content/browser/storage_partition_impl_unittest.cc
+++ b/content/browser/storage_partition_impl_unittest.cc
@@ -409,26 +409,6 @@
     return data_exists_for_origin;
   }
 
-  // Opens the file created for ClearKey (in kOrigin1) for writing. Caller
-  // needs to verify if the file was opened or not.
-  base::File OpenClearKeyFileForWrite() {
-    AwaitCompletionHelper await_completion;
-    base::File file;
-    storage::AsyncFileUtil* async_file_util =
-        filesystem_context_->GetAsyncFileUtil(
-            storage::kFileSystemTypePluginPrivate);
-    std::unique_ptr<storage::FileSystemOperationContext> operation_context =
-        std::make_unique<storage::FileSystemOperationContext>(
-            filesystem_context_);
-    async_file_util->CreateOrOpen(
-        std::move(operation_context), clearkey_file_,
-        base::File::FLAG_OPEN | base::File::FLAG_WRITE,
-        base::BindOnce(&RemovePluginPrivateDataTester::OnFileOpened,
-                       base::Unretained(this), &file, &await_completion));
-    await_completion.BlockUntilNotified();
-    return file;
-  }
-
  private:
   // Creates a PluginPrivateFileSystem for the |plugin_name| and |origin|
   // provided. Returns the file system ID for the created
@@ -533,14 +513,6 @@
     await_completion->Notify();
   }
 
-  void OnFileOpened(base::File* file_result,
-                    AwaitCompletionHelper* await_completion,
-                    base::File file,
-                    base::OnceClosure on_close_callback) {
-    *file_result = std::move(file);
-    await_completion->Notify();
-  }
-
   // If |origin| exists in the PluginPrivateFileSystem, set
   // |data_exists_for_origin| to true, false otherwise.
   void CheckIfDataExistsForOriginOnFileTaskRunner(
@@ -1544,38 +1516,6 @@
   EXPECT_TRUE(tester.DataExistsForOrigin(kOrigin2));
 }
 
-TEST_F(StoragePartitionImplTest, RemovePluginPrivateDataWhileWriting) {
-  StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
-      BrowserContext::GetDefaultStoragePartition(browser_context()));
-
-  RemovePluginPrivateDataTester tester(partition->GetFileSystemContext());
-  tester.AddPluginPrivateTestData();
-  EXPECT_TRUE(tester.DataExistsForOrigin(kOrigin1));
-  EXPECT_TRUE(tester.DataExistsForOrigin(kOrigin2));
-
-  const char test_data[] = {0, 1, 2, 3, 4, 5};
-  base::File file = tester.OpenClearKeyFileForWrite();
-  EXPECT_TRUE(file.IsValid());
-  EXPECT_EQ(static_cast<int>(base::size(test_data)),
-            file.Write(0, test_data, base::size(test_data)));
-
-  base::RunLoop run_loop;
-  base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::BindOnce(&ClearPluginPrivateData, partition, GURL(),
-                                base::Time(), base::Time::Max(), &run_loop));
-  run_loop.Run();
-
-  EXPECT_FALSE(tester.DataExistsForOrigin(kOrigin1));
-  EXPECT_FALSE(tester.DataExistsForOrigin(kOrigin2));
-
-  const char more_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
-  EXPECT_EQ(static_cast<int>(base::size(more_data)),
-            file.WriteAtCurrentPos(more_data, base::size(more_data)));
-
-  base::File file2 = tester.OpenClearKeyFileForWrite();
-  EXPECT_FALSE(file2.IsValid());
-}
-
 TEST_F(StoragePartitionImplTest, RemovePluginPrivateDataAfterDeletion) {
   StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
       BrowserContext::GetDefaultStoragePartition(browser_context()));
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn
index ec9e250c..34a0524 100644
--- a/content/renderer/BUILD.gn
+++ b/content/renderer/BUILD.gn
@@ -218,8 +218,6 @@
     "media/webrtc/rtc_rtp_sender.h",
     "media/webrtc/rtc_rtp_transceiver.cc",
     "media/webrtc/rtc_rtp_transceiver.h",
-    "media/webrtc/rtc_video_decoder_factory.cc",
-    "media/webrtc/rtc_video_decoder_factory.h",
     "media/webrtc/rtc_video_encoder_factory.cc",
     "media/webrtc/rtc_video_encoder_factory.h",
     "media/webrtc/stun_field_trial.cc",
@@ -501,7 +499,6 @@
     "//third_party/webrtc/modules/audio_processing:api",
     "//third_party/webrtc/modules/audio_processing:audio_processing_statistics",
     "//third_party/webrtc/modules/audio_processing/aec_dump",
-    "//third_party/webrtc/modules/video_coding:video_codec_interface",
     "//third_party/webrtc/modules/video_coding:webrtc_h264",
     "//third_party/webrtc/p2p:libstunprober",
     "//third_party/webrtc/p2p:rtc_p2p",
diff --git a/content/renderer/media/webrtc/video_codec_factory.cc b/content/renderer/media/webrtc/video_codec_factory.cc
index ea42207..9cb4f5f 100644
--- a/content/renderer/media/webrtc/video_codec_factory.cc
+++ b/content/renderer/media/webrtc/video_codec_factory.cc
@@ -9,9 +9,9 @@
 #include "base/memory/ptr_util.h"
 #include "build/build_config.h"
 #include "content/public/common/content_switches.h"
-#include "content/renderer/media/webrtc/rtc_video_decoder_factory.h"
 #include "content/renderer/media/webrtc/rtc_video_encoder_factory.h"
 #include "media/base/media_switches.h"
+#include "third_party/blink/public/platform/modules/peerconnection/rtc_video_decoder_factory.h"
 #include "third_party/webrtc/api/video_codecs/video_decoder_software_fallback_wrapper.h"
 #include "third_party/webrtc/api/video_codecs/video_encoder_software_fallback_wrapper.h"
 #include "third_party/webrtc/media/base/codec.h"
@@ -199,7 +199,7 @@
   const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
   if (gpu_factories && gpu_factories->IsGpuVideoAcceleratorEnabled() &&
       !cmd_line->HasSwitch(switches::kDisableWebRtcHWDecoding)) {
-    decoder_factory.reset(new RTCVideoDecoderFactory(gpu_factories));
+    decoder_factory.reset(new blink::RTCVideoDecoderFactory(gpu_factories));
   }
 
   return std::make_unique<DecoderAdapter>(std::move(decoder_factory));
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
index 4d3a6b9..40355d8 100644
--- a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
@@ -278,7 +278,7 @@
 crbug.com/angleproject/2909 [ win nvidia vulkan passthrough ] conformance/ogles/GL/faceforward/faceforward_001_to_006.html [ Failure ]
 crbug.com/angleproject/2722 [ win nvidia vulkan passthrough ] conformance/textures/misc/texture-attachment-formats.html [ Failure ]
 crbug.com/angleproject/2722 [ win nvidia vulkan passthrough ] conformance/renderbuffers/framebuffer-state-restoration.html [ Failure ]
-crbug.com/angleproject/2987 [ win7 nvidia vulkan passthrough ] conformance/misc/uninitialized-test.html [ Failure ]
+crbug.com/angleproject/3883 [ win nvidia vulkan passthrough ] conformance/misc/uninitialized-test.html [ Failure ]
 
 # Vulkan / Win / AMD / Passthrough command decoder
 crbug.com/angleproject/2722 [ win amd vulkan passthrough ] conformance/rendering/clipping-wide-points.html [ Failure ]
diff --git a/device/fido/cable/fido_cable_device.cc b/device/fido/cable/fido_cable_device.cc
index f41deea..df77590 100644
--- a/device/fido/cable/fido_cable_device.cc
+++ b/device/fido/cable/fido_cable_device.cc
@@ -39,78 +39,9 @@
   return constructed_nonce;
 }
 
-bool EncryptOutgoingMessage(
-    const base::Optional<FidoCableDevice::EncryptionData>& encryption_data,
-    std::vector<uint8_t>* message_to_encrypt) {
-  if (!encryption_data)
-    return false;
-
-  const auto nonce = ConstructEncryptionNonce(
-      encryption_data->nonce, true /* is_sender_client */,
-      encryption_data->write_sequence_num);
-  if (!nonce)
-    return false;
-
-  crypto::Aead aes_key(crypto::Aead::AES_256_GCM);
-  aes_key.Init(encryption_data->session_key);
-  DCHECK_EQ(nonce->size(), aes_key.NonceLength());
-
-  const uint8_t additional_data[1] = {
-      base::strict_cast<uint8_t>(FidoBleDeviceCommand::kMsg)};
-  std::vector<uint8_t> ciphertext =
-      aes_key.Seal(*message_to_encrypt, *nonce, additional_data);
-  message_to_encrypt->swap(ciphertext);
-  return true;
-}
-
-bool DecryptIncomingMessage(
-    const base::Optional<FidoCableDevice::EncryptionData>& encryption_data,
-    FidoBleFrame* incoming_frame) {
-  if (!encryption_data)
-    return false;
-
-  const auto nonce = ConstructEncryptionNonce(
-      encryption_data->nonce, false /* is_sender_client */,
-      encryption_data->read_sequence_num);
-  if (!nonce)
-    return false;
-
-  crypto::Aead aes_key(crypto::Aead::AES_256_GCM);
-  aes_key.Init(encryption_data->session_key);
-  DCHECK_EQ(nonce->size(), aes_key.NonceLength());
-
-  const uint8_t additional_data[1] = {
-      base::strict_cast<uint8_t>(incoming_frame->command())};
-  base::Optional<std::vector<uint8_t>> plaintext =
-      aes_key.Open(incoming_frame->data(), *nonce, additional_data);
-  if (!plaintext) {
-    FIDO_LOG(ERROR) << "Failed to decrypt caBLE message.";
-    return false;
-  }
-
-  incoming_frame->data().swap(*plaintext);
-  return true;
-}
-
 }  // namespace
 
-// FidoCableDevice::EncryptionData ----------------------------------------
-
-FidoCableDevice::EncryptionData::EncryptionData(
-    base::span<const uint8_t, 32> encryption_key,
-    base::span<const uint8_t, 8> nonce)
-    : session_key(fido_parsing_utils::Materialize(encryption_key)),
-      nonce(fido_parsing_utils::Materialize(nonce)) {}
-
-FidoCableDevice::EncryptionData::EncryptionData(EncryptionData&& data) =
-    default;
-
-FidoCableDevice::EncryptionData& FidoCableDevice::EncryptionData::operator=(
-    EncryptionData&& other) = default;
-
-FidoCableDevice::EncryptionData::~EncryptionData() = default;
-
-// FidoCableDevice::EncryptionData ----------------------------------------
+FidoCableDevice::EncryptionData::EncryptionData() = default;
 
 FidoCableDevice::FidoCableDevice(BluetoothAdapter* adapter, std::string address)
     : FidoBleDevice(adapter, std::move(address)) {}
@@ -123,7 +54,8 @@
 FidoDevice::CancelToken FidoCableDevice::DeviceTransact(
     std::vector<uint8_t> command,
     DeviceCallback callback) {
-  if (!EncryptOutgoingMessage(encryption_data_, &command)) {
+  if (!encryption_data_ ||
+      !EncryptOutgoingMessage(*encryption_data_, &command)) {
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE, base::BindOnce(std::move(callback), base::nullopt));
     state_ = State::kDeviceError;
@@ -145,7 +77,8 @@
   state_ = frame ? State::kReady : State::kDeviceError;
 
   if (frame && frame->command() != FidoBleDeviceCommand::kControl) {
-    if (!DecryptIncomingMessage(encryption_data_, &frame.value())) {
+    if (!encryption_data_ ||
+        !DecryptIncomingMessage(*encryption_data_, &frame.value())) {
       state_ = State::kDeviceError;
       frame = base::nullopt;
     }
@@ -177,11 +110,68 @@
     base::span<const uint8_t, 8> nonce) {
   // Encryption data must be set at most once during Cable handshake protocol.
   DCHECK(!encryption_data_);
-  encryption_data_.emplace(session_key, nonce);
+  encryption_data_.emplace();
+  encryption_data_->session_key = fido_parsing_utils::Materialize(session_key);
+  encryption_data_->nonce = fido_parsing_utils::Materialize(nonce);
 }
 
 FidoTransportProtocol FidoCableDevice::DeviceTransport() const {
   return FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy;
 }
 
+void FidoCableDevice::SetSequenceNumbersForTesting(uint32_t read_seq,
+                                                   uint32_t write_seq) {
+  encryption_data_->write_sequence_num = write_seq;
+  encryption_data_->read_sequence_num = read_seq;
+}
+
+// static
+bool FidoCableDevice::EncryptOutgoingMessage(
+    const EncryptionData& encryption_data,
+    std::vector<uint8_t>* message_to_encrypt) {
+  const auto nonce = ConstructEncryptionNonce(
+      encryption_data.nonce, true /* is_sender_client */,
+      encryption_data.write_sequence_num);
+  if (!nonce)
+    return false;
+
+  crypto::Aead aes_key(crypto::Aead::AES_256_GCM);
+  aes_key.Init(encryption_data.session_key);
+  DCHECK_EQ(nonce->size(), aes_key.NonceLength());
+
+  const uint8_t additional_data[1] = {
+      base::strict_cast<uint8_t>(FidoBleDeviceCommand::kMsg)};
+  std::vector<uint8_t> ciphertext =
+      aes_key.Seal(*message_to_encrypt, *nonce, additional_data);
+  message_to_encrypt->swap(ciphertext);
+  return true;
+}
+
+// static
+bool FidoCableDevice::DecryptIncomingMessage(
+    const EncryptionData& encryption_data,
+    FidoBleFrame* incoming_frame) {
+  const auto nonce = ConstructEncryptionNonce(
+      encryption_data.nonce, false /* is_sender_client */,
+      encryption_data.read_sequence_num);
+  if (!nonce)
+    return false;
+
+  crypto::Aead aes_key(crypto::Aead::AES_256_GCM);
+  aes_key.Init(encryption_data.session_key);
+  DCHECK_EQ(nonce->size(), aes_key.NonceLength());
+
+  const uint8_t additional_data[1] = {
+      base::strict_cast<uint8_t>(incoming_frame->command())};
+  base::Optional<std::vector<uint8_t>> plaintext =
+      aes_key.Open(incoming_frame->data(), *nonce, additional_data);
+  if (!plaintext) {
+    FIDO_LOG(ERROR) << "Failed to decrypt caBLE message.";
+    return false;
+  }
+
+  incoming_frame->data().swap(*plaintext);
+  return true;
+}
+
 }  // namespace device
diff --git a/device/fido/cable/fido_cable_device.h b/device/fido/cable/fido_cable_device.h
index 0d498af..504a7c0 100644
--- a/device/fido/cable/fido_cable_device.h
+++ b/device/fido/cable/fido_cable_device.h
@@ -26,23 +26,6 @@
 
 class COMPONENT_EXPORT(DEVICE_FIDO) FidoCableDevice : public FidoBleDevice {
  public:
-  // Encapsulates state FidoCableDevice maintains to encrypt and decrypt
-  // data within FidoBleFrame.
-  struct COMPONENT_EXPORT(DEVICE_FIDO) EncryptionData {
-    EncryptionData(base::span<const uint8_t, 32> session_key,
-                   base::span<const uint8_t, 8> nonce);
-    EncryptionData(EncryptionData&& data);
-    EncryptionData& operator=(EncryptionData&& other);
-    ~EncryptionData();
-
-    std::array<uint8_t, 32> session_key;
-    std::array<uint8_t, 8> nonce;
-    uint32_t write_sequence_num = 0;
-    uint32_t read_sequence_num = 0;
-
-    DISALLOW_COPY_AND_ASSIGN(EncryptionData);
-  };
-
   using FrameCallback = FidoBleTransaction::FrameCallback;
 
   FidoCableDevice(BluetoothAdapter* adapter, std::string address);
@@ -64,11 +47,27 @@
                          base::span<const uint8_t, 8> nonce);
   FidoTransportProtocol DeviceTransport() const override;
 
+  // SetCountersForTesting allows tests to set the message counters. Non-test
+  // code must not call this function.
+  void SetSequenceNumbersForTesting(uint32_t read_counter,
+                                    uint32_t write_counter);
+
  private:
-  FRIEND_TEST_ALL_PREFIXES(FidoCableDeviceTest,
-                           TestCableDeviceSendMultipleRequests);
-  FRIEND_TEST_ALL_PREFIXES(FidoCableDeviceTest,
-                           TestCableDeviceErrorOnMaxCounter);
+  // Encapsulates state FidoCableDevice maintains to encrypt and decrypt
+  // data within FidoBleFrame.
+  struct EncryptionData {
+    EncryptionData();
+
+    std::array<uint8_t, 32> session_key;
+    std::array<uint8_t, 8> nonce;
+    uint32_t write_sequence_num = 0;
+    uint32_t read_sequence_num = 0;
+  };
+
+  static bool EncryptOutgoingMessage(const EncryptionData& encryption_data,
+                                     std::vector<uint8_t>* message_to_encrypt);
+  static bool DecryptIncomingMessage(const EncryptionData& encryption_data,
+                                     FidoBleFrame* incoming_frame);
 
   base::Optional<EncryptionData> encryption_data_;
   base::WeakPtrFactory<FidoCableDevice> weak_factory_{this};
diff --git a/device/fido/cable/fido_cable_device_unittest.cc b/device/fido/cable/fido_cable_device_unittest.cc
index 1979d32..2c0a388 100644
--- a/device/fido/cable/fido_cable_device_unittest.cc
+++ b/device/fido/cable/fido_cable_device_unittest.cc
@@ -174,34 +174,6 @@
   ConnectWithLength(kControlPointLength);
 
   EXPECT_CALL(*connection(), WriteControlPointPtr(_, _))
-      .WillOnce(Invoke([this](const auto& data, auto* cb) {
-        base::SequencedTaskRunnerHandle::Get()->PostTask(
-            FROM_HERE, base::BindOnce(std::move(*cb), true));
-
-        const auto authenticator_reply = authenticator()->ReplyWithSameMessage(
-            base::make_span(data).subspan(kCTAPFramingLength));
-        base::SequencedTaskRunnerHandle::Get()->PostTask(
-            FROM_HERE, base::BindOnce(connection()->read_callback(),
-                                      ConstructSerializedOutgoingFragment(
-                                          authenticator_reply)));
-      }));
-
-  TestDeviceCallbackReceiver callback_receiver;
-  device()->DeviceTransact(fido_parsing_utils::Materialize(kTestData),
-                           callback_receiver.callback());
-
-  callback_receiver.WaitForCallback();
-  const auto& value = callback_receiver.value();
-  ASSERT_TRUE(value);
-  EXPECT_THAT(*value, ::testing::ElementsAreArray(kTestData));
-}
-
-// Test that FidoCableDevice properly updates counters when sending/receiving
-// multiple requests.
-TEST_F(FidoCableDeviceTest, TestCableDeviceSendMultipleRequests) {
-  ConnectWithLength(kControlPointLength);
-  EXPECT_CALL(*connection(), WriteControlPointPtr(_, _))
-      .Times(2)
       .WillRepeatedly(Invoke([this](const auto& data, auto* cb) {
         base::SequencedTaskRunnerHandle::Get()->PostTask(
             FROM_HERE, base::BindOnce(std::move(*cb), true));
@@ -214,30 +186,18 @@
                                           authenticator_reply)));
       }));
 
-  ASSERT_TRUE(device()->encryption_data_);
-  EXPECT_EQ(0u, device()->encryption_data_->write_sequence_num);
-  EXPECT_EQ(0u, device()->encryption_data_->read_sequence_num);
+  for (size_t i = 0; i < 3; i++) {
+    SCOPED_TRACE(i);
 
-  TestDeviceCallbackReceiver callback_receiver1;
-  device()->DeviceTransact(fido_parsing_utils::Materialize(kTestData),
-                           callback_receiver1.callback());
-  callback_receiver1.WaitForCallback();
-  const auto& value1 = callback_receiver1.value();
-  ASSERT_TRUE(value1);
-  EXPECT_THAT(*value1, ::testing::ElementsAreArray(kTestData));
-  EXPECT_EQ(1u, device()->encryption_data_->write_sequence_num);
-  EXPECT_EQ(1u, device()->encryption_data_->read_sequence_num);
+    TestDeviceCallbackReceiver callback_receiver;
+    device()->DeviceTransact(fido_parsing_utils::Materialize(kTestData),
+                             callback_receiver.callback());
 
-  constexpr uint8_t kTestData2[] = {'T', 'E', 'S', 'T', '2'};
-  TestDeviceCallbackReceiver callback_receiver2;
-  device()->DeviceTransact(fido_parsing_utils::Materialize(kTestData2),
-                           callback_receiver2.callback());
-  callback_receiver2.WaitForCallback();
-  const auto& value2 = callback_receiver2.value();
-  ASSERT_TRUE(value2);
-  EXPECT_THAT(*value2, ::testing::ElementsAreArray(kTestData2));
-  EXPECT_EQ(2u, device()->encryption_data_->write_sequence_num);
-  EXPECT_EQ(2u, device()->encryption_data_->read_sequence_num);
+    callback_receiver.WaitForCallback();
+    const auto& value = callback_receiver.value();
+    ASSERT_TRUE(value);
+    EXPECT_THAT(*value, ::testing::ElementsAreArray(kTestData));
+  }
 }
 
 TEST_F(FidoCableDeviceTest, TestCableDeviceFailOnIncorrectSessionKey) {
@@ -322,8 +282,7 @@
       }));
 
   TestDeviceCallbackReceiver callback_receiver;
-  ASSERT_TRUE(device()->encryption_data_);
-  device()->encryption_data_->read_sequence_num = kInvalidCounter;
+  device()->SetSequenceNumbersForTesting(kInvalidCounter, 0);
   device()->DeviceTransact(fido_parsing_utils::Materialize(kTestData),
                            callback_receiver.callback());
 
diff --git a/extensions/browser/api/web_request/web_request_api.cc b/extensions/browser/api/web_request/web_request_api.cc
index f9e1b62..b692888 100644
--- a/extensions/browser/api/web_request/web_request_api.cc
+++ b/extensions/browser/api/web_request/web_request_api.cc
@@ -712,10 +712,9 @@
               browser_context_));
   WebRequestProxyingURLLoaderFactory::StartProxying(
       browser_context, is_navigation ? -1 : render_process_id,
-      type == URLLoaderFactoryType::kDownload, request_id_generator_,
-      std::move(navigation_ui_data), std::move(proxied_receiver),
-      std::move(target_factory_info), std::move(header_client_receiver),
-      proxies_.get());
+      request_id_generator_, std::move(navigation_ui_data),
+      std::move(proxied_receiver), std::move(target_factory_info),
+      std::move(header_client_receiver), proxies_.get(), type);
   return true;
 }
 
diff --git a/extensions/browser/api/web_request/web_request_info.cc b/extensions/browser/api/web_request/web_request_info.cc
index a330972..3e84b22 100644
--- a/extensions/browser/api/web_request/web_request_info.cc
+++ b/extensions/browser/api/web_request/web_request_info.cc
@@ -161,7 +161,8 @@
     int32_t routing_id,
     const network::ResourceRequest& request,
     bool is_download,
-    bool is_async)
+    bool is_async,
+    bool is_service_worker_script)
     : id(request_id),
       url(request.url),
       site_for_cookies(request.site_for_cookies),
@@ -173,7 +174,8 @@
       initiator(request.request_initiator),
       type(static_cast<content::ResourceType>(request.resource_type)),
       is_async(is_async),
-      extra_request_headers(request.headers) {
+      extra_request_headers(request.headers),
+      is_service_worker_script(is_service_worker_script) {
   if (url.SchemeIsWSOrWSS())
     web_request_type = WebRequestResourceType::WEB_SOCKET;
   else if (is_download)
@@ -236,7 +238,8 @@
       is_web_view(params.is_web_view),
       web_view_instance_id(params.web_view_instance_id),
       web_view_rules_registry_id(params.web_view_rules_registry_id),
-      web_view_embedder_process_id(params.web_view_embedder_process_id) {}
+      web_view_embedder_process_id(params.web_view_embedder_process_id),
+      is_service_worker_script(params.is_service_worker_script) {}
 
 WebRequestInfo::~WebRequestInfo() = default;
 
diff --git a/extensions/browser/api/web_request/web_request_info.h b/extensions/browser/api/web_request/web_request_info.h
index bbe9337..ac265b0 100644
--- a/extensions/browser/api/web_request/web_request_info.h
+++ b/extensions/browser/api/web_request/web_request_info.h
@@ -49,7 +49,8 @@
       int32_t routing_id,
       const network::ResourceRequest& request,
       bool is_download,
-      bool is_async);
+      bool is_async,
+      bool is_service_worker_script);
 
   ~WebRequestInfoInitParams();
 
@@ -72,6 +73,7 @@
   int web_view_rules_registry_id = -1;
   int web_view_embedder_process_id = -1;
   ExtensionApiFrameIdMap::FrameData frame_data;
+  bool is_service_worker_script = false;
 
  private:
   void InitializeWebViewAndFrameData(
@@ -169,6 +171,8 @@
   mutable base::Optional<declarative_net_request::RulesetManager::Action>
       dnr_action;
 
+  const bool is_service_worker_script;
+
  private:
   DISALLOW_COPY_AND_ASSIGN(WebRequestInfo);
 };
diff --git a/extensions/browser/api/web_request/web_request_info_unittest.cc b/extensions/browser/api/web_request/web_request_info_unittest.cc
index 74640e6..1cafa25 100644
--- a/extensions/browser/api/web_request/web_request_info_unittest.cc
+++ b/extensions/browser/api/web_request/web_request_info_unittest.cc
@@ -28,8 +28,8 @@
   request.request_body->AppendFileRange(base::FilePath(kFilePath), 0,
                                         std::numeric_limits<uint64_t>::max(),
                                         base::Time());
-  WebRequestInfo info(
-      WebRequestInfoInitParams(0, 0, 0, nullptr, 0, request, false, false));
+  WebRequestInfo info(WebRequestInfoInitParams(0, 0, 0, nullptr, 0, request,
+                                               false, false, false));
   ASSERT_TRUE(info.request_body_data);
   auto* value = info.request_body_data->FindKey(
       extension_web_request_api_constants::kRequestBodyRawKey);
diff --git a/extensions/browser/api/web_request/web_request_permissions.cc b/extensions/browser/api/web_request/web_request_permissions.cc
index 8eb46c35..e6754765 100644
--- a/extensions/browser/api/web_request/web_request_permissions.cc
+++ b/extensions/browser/api/web_request/web_request_permissions.cc
@@ -246,6 +246,14 @@
   bool is_request_from_browser = request.render_process_id == -1;
 
   if (is_request_from_browser) {
+    // Browser initiated service worker script requests (e.g., for update check)
+    // are not hidden.
+    if (request.is_service_worker_script) {
+      DCHECK(request.type == content::ResourceType::kServiceWorker ||
+             request.type == content::ResourceType::kScript);
+      return false;
+    }
+
     // Hide all non-navigation requests made by the browser. crbug.com/884932.
     if (!request.is_navigation_request)
       return true;
diff --git a/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc b/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc
index 77e8042..6290a9b 100644
--- a/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc
+++ b/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc
@@ -68,14 +68,12 @@
     int32_t routing_id,
     uint32_t options,
     const network::ResourceRequest& request,
-    bool is_download,
     const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
     network::mojom::URLLoaderRequest loader_request,
     network::mojom::URLLoaderClientPtr client)
     : factory_(factory),
       request_(request),
       original_initiator_(request.request_initiator),
-      is_download_(is_download),
       request_id_(request_id),
       network_service_request_id_(network_service_request_id),
       routing_id_(routing_id),
@@ -130,8 +128,9 @@
       request_id_, factory_->render_process_id_, request_.render_frame_id,
       factory_->navigation_ui_data_ ? factory_->navigation_ui_data_->DeepCopy()
                                     : nullptr,
-      routing_id_, request_for_info, is_download_,
-      !(options_ & network::mojom::kURLLoadOptionSynchronous)));
+      routing_id_, request_for_info, factory_->IsForDownload(),
+      !(options_ & network::mojom::kURLLoadOptionSynchronous),
+      factory_->IsForServiceWorkerScript()));
 
   current_request_uses_header_client_ =
       factory_->url_loader_header_client_receiver_.is_bound() &&
@@ -356,6 +355,16 @@
       auth_info, std::move(callback)));
 }
 
+bool WebRequestProxyingURLLoaderFactory::IsForServiceWorkerScript() const {
+  return loader_factory_type_ == content::ContentBrowserClient::
+                                     URLLoaderFactoryType::kServiceWorkerScript;
+}
+
+bool WebRequestProxyingURLLoaderFactory::IsForDownload() const {
+  return loader_factory_type_ ==
+         content::ContentBrowserClient::URLLoaderFactoryType::kDownload;
+}
+
 void WebRequestProxyingURLLoaderFactory::InProgressRequest::OnLoaderCreated(
     mojo::PendingReceiver<network::mojom::TrustedHeaderClient> receiver) {
   header_client_receiver_.Bind(std::move(receiver));
@@ -839,20 +848,20 @@
 WebRequestProxyingURLLoaderFactory::WebRequestProxyingURLLoaderFactory(
     content::BrowserContext* browser_context,
     int render_process_id,
-    bool is_download,
     scoped_refptr<WebRequestAPI::RequestIDGenerator> request_id_generator,
     std::unique_ptr<ExtensionNavigationUIData> navigation_ui_data,
     network::mojom::URLLoaderFactoryRequest loader_request,
     network::mojom::URLLoaderFactoryPtrInfo target_factory_info,
     mojo::PendingReceiver<network::mojom::TrustedURLLoaderHeaderClient>
         header_client_receiver,
-    WebRequestAPI::ProxySet* proxies)
+    WebRequestAPI::ProxySet* proxies,
+    content::ContentBrowserClient::URLLoaderFactoryType loader_factory_type)
     : browser_context_(browser_context),
       render_process_id_(render_process_id),
-      is_download_(is_download),
       request_id_generator_(std::move(request_id_generator)),
       navigation_ui_data_(std::move(navigation_ui_data)),
-      proxies_(proxies) {
+      proxies_(proxies),
+      loader_factory_type_(loader_factory_type) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   // base::Unretained is safe here because the callback will be canceled when
   // |shutdown_notifier_| is destroyed, and |proxies_| owns this.
@@ -878,21 +887,21 @@
 void WebRequestProxyingURLLoaderFactory::StartProxying(
     content::BrowserContext* browser_context,
     int render_process_id,
-    bool is_download,
     scoped_refptr<WebRequestAPI::RequestIDGenerator> request_id_generator,
     std::unique_ptr<ExtensionNavigationUIData> navigation_ui_data,
     network::mojom::URLLoaderFactoryRequest loader_request,
     network::mojom::URLLoaderFactoryPtrInfo target_factory_info,
     mojo::PendingReceiver<network::mojom::TrustedURLLoaderHeaderClient>
         header_client_receiver,
-    WebRequestAPI::ProxySet* proxies) {
+    WebRequestAPI::ProxySet* proxies,
+    content::ContentBrowserClient::URLLoaderFactoryType loader_factory_type) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   auto proxy = std::make_unique<WebRequestProxyingURLLoaderFactory>(
-      browser_context, render_process_id, is_download,
-      std::move(request_id_generator), std::move(navigation_ui_data),
-      std::move(loader_request), std::move(target_factory_info),
-      std::move(header_client_receiver), proxies);
+      browser_context, render_process_id, std::move(request_id_generator),
+      std::move(navigation_ui_data), std::move(loader_request),
+      std::move(target_factory_info), std::move(header_client_receiver),
+      proxies, loader_factory_type);
 
   proxies->AddProxy(std::move(proxy));
 }
@@ -907,8 +916,10 @@
     const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
-  // Make sure we are not proxying a browser initiated non-navigation request.
-  DCHECK(render_process_id_ != -1 || navigation_ui_data_);
+  // Make sure we are not proxying a browser initiated non-navigation request
+  // except for loading service worker scripts.
+  DCHECK(render_process_id_ != -1 || navigation_ui_data_ ||
+         IsForServiceWorkerScript());
 
   // The request ID doesn't really matter. It just needs to be unique
   // per-BrowserContext so extensions can make sense of it.  Note that
@@ -927,10 +938,10 @@
   }
 
   auto result = requests_.emplace(
-      web_request_id, std::make_unique<InProgressRequest>(
-                          this, web_request_id, request_id, routing_id, options,
-                          request, is_download_, traffic_annotation,
-                          std::move(loader_request), std::move(client)));
+      web_request_id,
+      std::make_unique<InProgressRequest>(
+          this, web_request_id, request_id, routing_id, options, request,
+          traffic_annotation, std::move(loader_request), std::move(client)));
   result.first->second->Restart();
 }
 
diff --git a/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.h b/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.h
index 7452fc01..c4f34864 100644
--- a/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.h
+++ b/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.h
@@ -15,6 +15,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/optional.h"
 #include "components/keyed_service/core/keyed_service_shutdown_notifier.h"
+#include "content/public/browser/content_browser_client.h"
 #include "extensions/browser/api/web_request/web_request_api.h"
 #include "extensions/browser/api/web_request/web_request_info.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
@@ -49,7 +50,6 @@
         int32_t network_service_request_id,
         uint32_t options,
         const network::ResourceRequest& request,
-        bool is_download,
         const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
         network::mojom::URLLoaderRequest loader_request,
         network::mojom::URLLoaderClientPtr client);
@@ -122,7 +122,6 @@
     WebRequestProxyingURLLoaderFactory* const factory_;
     network::ResourceRequest request_;
     const base::Optional<url::Origin> original_initiator_;
-    const bool is_download_;
     const uint64_t request_id_;
     const int32_t network_service_request_id_;
     const int32_t routing_id_;
@@ -187,28 +186,28 @@
   WebRequestProxyingURLLoaderFactory(
       content::BrowserContext* browser_context,
       int render_process_id,
-      bool is_download,
       scoped_refptr<WebRequestAPI::RequestIDGenerator> request_id_generator,
       std::unique_ptr<ExtensionNavigationUIData> navigation_ui_data,
       network::mojom::URLLoaderFactoryRequest loader_request,
       network::mojom::URLLoaderFactoryPtrInfo target_factory_info,
       mojo::PendingReceiver<network::mojom::TrustedURLLoaderHeaderClient>
           header_client_receiver,
-      WebRequestAPI::ProxySet* proxies);
+      WebRequestAPI::ProxySet* proxies,
+      content::ContentBrowserClient::URLLoaderFactoryType loader_factory_type);
 
   ~WebRequestProxyingURLLoaderFactory() override;
 
   static void StartProxying(
       content::BrowserContext* browser_context,
       int render_process_id,
-      bool is_download,
       scoped_refptr<WebRequestAPI::RequestIDGenerator> request_id_generator,
       std::unique_ptr<ExtensionNavigationUIData> navigation_ui_data,
       network::mojom::URLLoaderFactoryRequest loader_request,
       network::mojom::URLLoaderFactoryPtrInfo target_factory_info,
       mojo::PendingReceiver<network::mojom::TrustedURLLoaderHeaderClient>
           header_client_receiver,
-      WebRequestAPI::ProxySet* proxies);
+      WebRequestAPI::ProxySet* proxies,
+      content::ContentBrowserClient::URLLoaderFactoryType loader_factory_type);
 
   // network::mojom::URLLoaderFactory:
   void CreateLoaderAndStart(network::mojom::URLLoaderRequest loader_request,
@@ -234,6 +233,14 @@
       int32_t request_id,
       WebRequestAPI::AuthRequestCallback callback) override;
 
+  content::ContentBrowserClient::URLLoaderFactoryType loader_factory_type()
+      const {
+    return loader_factory_type_;
+  }
+
+  bool IsForServiceWorkerScript() const;
+  bool IsForDownload() const;
+
  private:
   void OnTargetFactoryError();
   void OnProxyBindingError();
@@ -242,7 +249,6 @@
 
   content::BrowserContext* const browser_context_;
   const int render_process_id_;
-  const bool is_download_;
   scoped_refptr<WebRequestAPI::RequestIDGenerator> request_id_generator_;
   std::unique_ptr<ExtensionNavigationUIData> navigation_ui_data_;
   mojo::BindingSet<network::mojom::URLLoaderFactory> proxy_bindings_;
@@ -252,6 +258,9 @@
   // Owns |this|.
   WebRequestAPI::ProxySet* const proxies_;
 
+  const content::ContentBrowserClient::URLLoaderFactoryType
+      loader_factory_type_;
+
   // Mapping from our own internally generated request ID to an
   // InProgressRequest instance.
   std::map<uint64_t, std::unique_ptr<InProgressRequest>> requests_;
diff --git a/extensions/browser/api/web_request/web_request_proxying_websocket.cc b/extensions/browser/api/web_request/web_request_proxying_websocket.cc
index 585fa267..7df1fa30 100644
--- a/extensions/browser/api/web_request/web_request_proxying_websocket.cc
+++ b/extensions/browser/api/web_request/web_request_proxying_websocket.cc
@@ -65,8 +65,9 @@
                                      nullptr,
                                      MSG_ROUTING_NONE,
                                      request,
-                                     false /* is_download */,
-                                     true /* is_async */)),
+                                     /*is_download=*/false,
+                                     /*is_async=*/true,
+                                     /*is_service_worker_script=*/false)),
       proxies_(proxies) {
   // base::Unretained is safe here because the callback will be canceled when
   // |shutdown_notifier_| is destroyed, and |proxies_| owns this.
diff --git a/gpu/command_buffer/service/framebuffer_manager.cc b/gpu/command_buffer/service/framebuffer_manager.cc
index 96dea36..0cce8cf 100644
--- a/gpu/command_buffer/service/framebuffer_manager.cc
+++ b/gpu/command_buffer/service/framebuffer_manager.cc
@@ -386,8 +386,7 @@
       draw_buffer_bound_mask_(0u),
       adjusted_draw_buffer_bound_mask_(0u),
       last_color_attachment_id_(-1),
-      read_buffer_(GL_COLOR_ATTACHMENT0),
-      flip_y_(false) {
+      read_buffer_(GL_COLOR_ATTACHMENT0) {
   manager->StartTracking(this);
   DCHECK_GT(manager->max_draw_buffers_, 0u);
   draw_buffers_.reset(new GLenum[manager->max_draw_buffers_]);
diff --git a/gpu/command_buffer/service/framebuffer_manager.h b/gpu/command_buffer/service/framebuffer_manager.h
index 1670640..794df67 100644
--- a/gpu/command_buffer/service/framebuffer_manager.h
+++ b/gpu/command_buffer/service/framebuffer_manager.h
@@ -236,9 +236,6 @@
 
   void UnmarkAsComplete() { framebuffer_complete_state_count_id_ = 0; }
 
-  bool GetFlipY() const { return flip_y_; }
-  void SetFlipY(bool flip_y) { flip_y_ = flip_y; }
-
  private:
   friend class FramebufferManager;
   friend class base::RefCounted<Framebuffer>;
@@ -318,8 +315,6 @@
 
   GLenum read_buffer_;
 
-  bool flip_y_;
-
   DISALLOW_COPY_AND_ASSIGN(Framebuffer);
 };
 
diff --git a/gpu/command_buffer/service/gles2_cmd_apply_framebuffer_attachment_cmaa_intel.cc b/gpu/command_buffer/service/gles2_cmd_apply_framebuffer_attachment_cmaa_intel.cc
index 655f84e..433277b4 100644
--- a/gpu/command_buffer/service/gles2_cmd_apply_framebuffer_attachment_cmaa_intel.cc
+++ b/gpu/command_buffer/service/gles2_cmd_apply_framebuffer_attachment_cmaa_intel.cc
@@ -26,7 +26,6 @@
       supports_usampler_(true),
       supports_r8_image_(true),
       is_gles31_compatible_(false),
-      flip_y_(false),
       frame_id_(0),
       width_(0),
       height_(0),
@@ -227,7 +226,7 @@
       GLenum internal_format = attachment->internal_format();
 
       // Resize internal structures - only if needed.
-      OnSize(width, height, framebuffer->GetFlipY());
+      OnSize(width, height);
 
       // CMAA internally expects GL_RGBA8 textures.
       // Process using a GL_RGBA8 copy if this is not the case.
@@ -498,16 +497,14 @@
 }
 
 void ApplyFramebufferAttachmentCMAAINTELResourceManager::OnSize(GLint width,
-                                                                GLint height,
-                                                                bool flip_y) {
-  if (height_ == height && width_ == width && flip_y_ == flip_y)
+                                                                GLint height) {
+  if (height_ == height && width_ == width)
     return;
 
   ReleaseTextures();
 
   height_ = height;
   width_ = width;
-  flip_y_ = flip_y;
 
   glGenTextures(1, &rgba8_texture_);
   glBindTexture(GL_TEXTURE_2D, rgba8_texture_);
@@ -549,10 +546,6 @@
   // Create the FBO
   glGenFramebuffersEXT(1, &cmaa_framebuffer_);
   glBindFramebufferEXT(GL_FRAMEBUFFER, cmaa_framebuffer_);
-  if (flip_y_) {
-    glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA,
-                            GL_TRUE);
-  }
 
   // We need to clear the textures before they are first used.
   // The algorithm self-clears them later.
diff --git a/gpu/command_buffer/service/gles2_cmd_apply_framebuffer_attachment_cmaa_intel.h b/gpu/command_buffer/service/gles2_cmd_apply_framebuffer_attachment_cmaa_intel.h
index 11ded04..33bade3 100644
--- a/gpu/command_buffer/service/gles2_cmd_apply_framebuffer_attachment_cmaa_intel.h
+++ b/gpu/command_buffer/service/gles2_cmd_apply_framebuffer_attachment_cmaa_intel.h
@@ -44,7 +44,7 @@
                               GLuint dest_texture,
                               bool do_copy);
 
-  void OnSize(GLint width, GLint height, bool flip_y);
+  void OnSize(GLint width, GLint height);
   void ReleaseTextures();
 
   GLuint CreateProgram(const char* defines,
@@ -58,7 +58,6 @@
   bool supports_usampler_;
   bool supports_r8_image_;
   bool is_gles31_compatible_;
-  bool flip_y_;
 
   int frame_id_;
 
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index e44125a..e0f77fd 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -8261,19 +8261,12 @@
                                                GLenum pname,
                                                GLint param) {
   const char* func_name = "glFramebufferParameteri";
-  DCHECK(pname == GL_FRAMEBUFFER_FLIP_Y_MESA);
   Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
   if (!framebuffer) {
     LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, func_name, "no framebuffer bound");
     return;
   }
-  if (param != GL_TRUE && param != GL_FALSE) {
-    LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, func_name,
-                       "invalid parameter, only GL_TRUE or GL_FALSE accepted");
-    return;
-  }
   api()->glFramebufferParameteriFn(target, pname, param);
-  framebuffer->SetFlipY(param == GL_TRUE);
 }
 
 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
diff --git a/media/gpu/OWNERS b/media/gpu/OWNERS
index be483dd..18fb4fa 100644
--- a/media/gpu/OWNERS
+++ b/media/gpu/OWNERS
@@ -1,9 +1,12 @@
-acourbot@chromium.org
 dalecurtis@chromium.org
 dcastagna@chromium.org
+liberato@chromium.org
+sandersd@chromium.org
+
+# For chromeos/, linux/, v4l2/, and vaapi/ -specific changes.
+acourbot@chromium.org
 hiroh@chromium.org
 jcliang@chromium.org
 kcwu@chromium.org
-liberato@chromium.org
+mcasas@chromium.org
 posciak@chromium.org
-sandersd@chromium.org
diff --git a/media/media_options.gni b/media/media_options.gni
index 12cfbb9..044068e 100644
--- a/media/media_options.gni
+++ b/media/media_options.gni
@@ -61,7 +61,7 @@
   enable_mpeg_h_audio_demuxing = proprietary_codecs && is_chromecast
 
   enable_mse_mpeg2ts_stream_parser =
-      proprietary_codecs && (is_chromecast || use_fuzzing_engine)
+      proprietary_codecs && (is_chromecast || is_fuchsia || use_fuzzing_engine)
 
   # Enable parsing for the 'cbcs' encryption scheme added by MPEG Common
   # Encryption 3rd Edition (ISO/IEC 23001-7), published 02/15/2016.
diff --git a/net/cert/trial_comparison_cert_verifier_unittest.cc b/net/cert/trial_comparison_cert_verifier_unittest.cc
index 4b0d6c7d..148fffef 100644
--- a/net/cert/trial_comparison_cert_verifier_unittest.cc
+++ b/net/cert/trial_comparison_cert_verifier_unittest.cc
@@ -1206,7 +1206,7 @@
   CertVerifyResult result;
   std::unique_ptr<CertVerifier::Request> request;
   int error =
-      verifier.Verify(params, &result, base::BindRepeating(&NotCalledCallback),
+      verifier.Verify(params, &result, base::BindOnce(&NotCalledCallback),
                       &request, NetLogWithSource());
   ASSERT_THAT(error, IsError(ERR_IO_PENDING));
   EXPECT_TRUE(request);
@@ -1264,7 +1264,7 @@
   CertVerifyResult result;
   std::unique_ptr<CertVerifier::Request> request;
   int error =
-      verifier->Verify(params, &result, base::BindRepeating(&NotCalledCallback),
+      verifier->Verify(params, &result, base::BindOnce(&NotCalledCallback),
                        &request, NetLogWithSource());
   ASSERT_THAT(error, IsError(ERR_IO_PENDING));
   EXPECT_TRUE(request);
diff --git a/net/cert_net/cert_net_fetcher_impl.cc b/net/cert_net/cert_net_fetcher_impl.cc
index a215458..4517ae3 100644
--- a/net/cert_net/cert_net_fetcher_impl.cc
+++ b/net/cert_net/cert_net_fetcher_impl.cc
@@ -501,9 +501,9 @@
 
   // Start a timer to limit how long the job runs for.
   if (request_params_->timeout > base::TimeDelta())
-    timer_.Start(
-        FROM_HERE, request_params_->timeout,
-        base::Bind(&Job::FailRequest, base::Unretained(this), ERR_TIMED_OUT));
+    timer_.Start(FROM_HERE, request_params_->timeout,
+                 base::BindOnce(&Job::FailRequest, base::Unretained(this),
+                                ERR_TIMED_OUT));
 }
 
 void Job::Cancel() {
diff --git a/net/extras/sqlite/sqlite_persistent_cookie_store_perftest.cc b/net/extras/sqlite/sqlite_persistent_cookie_store_perftest.cc
index d281b90..46850fbc 100644
--- a/net/extras/sqlite/sqlite_persistent_cookie_store_perftest.cc
+++ b/net/extras/sqlite/sqlite_persistent_cookie_store_perftest.cc
@@ -66,8 +66,8 @@
   }
 
   void Load() {
-    store_->Load(base::Bind(&SQLitePersistentCookieStorePerfTest::OnLoaded,
-                            base::Unretained(this)),
+    store_->Load(base::BindOnce(&SQLitePersistentCookieStorePerfTest::OnLoaded,
+                                base::Unretained(this)),
                  NetLogWithSource());
     loaded_event_.Wait();
   }
@@ -162,8 +162,8 @@
     StartPerfMeasurement();
     store_->LoadCookiesForKey(
         domain_name,
-        base::Bind(&SQLitePersistentCookieStorePerfTest::OnKeyLoaded,
-                   base::Unretained(this)));
+        base::BindOnce(&SQLitePersistentCookieStorePerfTest::OnKeyLoaded,
+                       base::Unretained(this)));
     key_loaded_event_.Wait();
     EndPerfMeasurement();
 
diff --git a/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc b/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc
index 12039b1..25edec0 100644
--- a/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc
+++ b/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc
@@ -115,8 +115,8 @@
 
   void Load(CanonicalCookieVector* cookies) {
     EXPECT_FALSE(loaded_event_.IsSignaled());
-    store_->Load(base::Bind(&SQLitePersistentCookieStoreTest::OnLoaded,
-                            base::Unretained(this)),
+    store_->Load(base::BindOnce(&SQLitePersistentCookieStoreTest::OnLoaded,
+                                base::Unretained(this)),
                  net_log_.bound());
     loaded_event_.Wait();
     cookies->swap(cookies_);
@@ -126,7 +126,7 @@
     base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
                               base::WaitableEvent::InitialState::NOT_SIGNALED);
     store_->Flush(
-        base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event)));
+        base::BindOnce(&base::WaitableEvent::Signal, base::Unretained(&event)));
     event.Wait();
   }
 
@@ -323,15 +323,15 @@
   background_task_runner_->PostTask(
       FROM_HERE, base::BindOnce(&SQLitePersistentCookieStoreTest::WaitOnDBEvent,
                                 base::Unretained(this)));
-  store_->Load(base::Bind(&SQLitePersistentCookieStoreTest::OnLoaded,
-                          base::Unretained(this)),
+  store_->Load(base::BindOnce(&SQLitePersistentCookieStoreTest::OnLoaded,
+                              base::Unretained(this)),
                NetLogWithSource());
   t += base::TimeDelta::FromMicroseconds(10);
   AddCookieWithExpiration("A", "B", "c.com", "/", t, base::Time());
   base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
                             base::WaitableEvent::InitialState::NOT_SIGNALED);
   store_->Flush(
-      base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event)));
+      base::BindOnce(&base::WaitableEvent::Signal, base::Unretained(&event)));
 
   // Now the DB-thread queue contains:
   // (active:)
@@ -352,8 +352,8 @@
   store_ = new SQLitePersistentCookieStore(
       temp_dir_.GetPath().Append(kCookieFilename), client_task_runner_,
       background_task_runner_, true, nullptr);
-  store_->Load(base::Bind(&SQLitePersistentCookieStoreTest::OnLoaded,
-                          base::Unretained(this)),
+  store_->Load(base::BindOnce(&SQLitePersistentCookieStoreTest::OnLoaded,
+                              base::Unretained(this)),
                NetLogWithSource());
   loaded_event_.Wait();
   ASSERT_EQ(4u, cookies_.size());
@@ -389,14 +389,15 @@
       FROM_HERE, base::BindOnce(&SQLitePersistentCookieStoreTest::WaitOnDBEvent,
                                 base::Unretained(this)));
   BoundTestNetLog net_log;
-  store_->Load(base::Bind(&SQLitePersistentCookieStoreTest::OnLoaded,
-                          base::Unretained(this)),
+  store_->Load(base::BindOnce(&SQLitePersistentCookieStoreTest::OnLoaded,
+                              base::Unretained(this)),
                net_log.bound());
   base::RunLoop run_loop;
   net_log.SetObserverCaptureMode(NetLogCaptureMode::kDefault);
   store_->LoadCookiesForKey(
-      "aaa.com", base::Bind(&SQLitePersistentCookieStoreTest::OnKeyLoaded,
-                            base::Unretained(this), run_loop.QuitClosure()));
+      "aaa.com",
+      base::BindOnce(&SQLitePersistentCookieStoreTest::OnKeyLoaded,
+                     base::Unretained(this), run_loop.QuitClosure()));
   background_task_runner_->PostTask(
       FROM_HERE, base::BindOnce(&SQLitePersistentCookieStoreTest::WaitOnDBEvent,
                                 base::Unretained(this)));
diff --git a/net/extras/sqlite/sqlite_persistent_reporting_and_nel_store_unittest.cc b/net/extras/sqlite/sqlite_persistent_reporting_and_nel_store_unittest.cc
index 7c5f0fc7..4843093 100644
--- a/net/extras/sqlite/sqlite_persistent_reporting_and_nel_store_unittest.cc
+++ b/net/extras/sqlite/sqlite_persistent_reporting_and_nel_store_unittest.cc
@@ -120,7 +120,7 @@
   void LoadNelPolicies(
       std::vector<NetworkErrorLoggingService::NelPolicy>* policies_out) {
     base::RunLoop run_loop;
-    store_->LoadNelPolicies(base::BindRepeating(
+    store_->LoadNelPolicies(base::BindOnce(
         &SQLitePersistentReportingAndNelStoreTest::OnNelPoliciesLoaded,
         base::Unretained(this), &run_loop, policies_out));
     run_loop.Run();
@@ -138,7 +138,7 @@
       std::vector<ReportingEndpoint>* endpoints_out,
       std::vector<CachedReportingEndpointGroup>* groups_out) {
     base::RunLoop run_loop;
-    store_->LoadReportingClients(base::BindRepeating(
+    store_->LoadReportingClients(base::BindOnce(
         &SQLitePersistentReportingAndNelStoreTest::OnReportingClientsLoaded,
         base::Unretained(this), &run_loop, endpoints_out, groups_out));
     run_loop.Run();
diff --git a/net/http/alternative_service.cc b/net/http/alternative_service.cc
index 6b1f0d2..c35a3968 100644
--- a/net/http/alternative_service.cc
+++ b/net/http/alternative_service.cc
@@ -38,6 +38,16 @@
   }
 }
 
+quic::ParsedQuicVersion ParsedQuicVersionFromAlpn(
+    base::StringPiece str,
+    quic::ParsedQuicVersionVector supported_versions) {
+  for (const quic::ParsedQuicVersion version : supported_versions) {
+    if (AlpnForVersion(version) == str)
+      return version;
+  }
+  return {quic::PROTOCOL_UNSUPPORTED, quic::QUIC_VERSION_UNSUPPORTED};
+}
+
 }  // anonymous namespace
 
 void HistogramAlternateProtocolUsage(AlternateProtocolUsage usage,
@@ -173,22 +183,38 @@
   AlternativeServiceInfoVector alternative_service_info_vector;
   for (const spdy::SpdyAltSvcWireFormat::AlternativeService&
            alternative_service_entry : alternative_service_vector) {
+    if (!IsPortValid(alternative_service_entry.port))
+      continue;
+
     NextProto protocol =
         NextProtoFromString(alternative_service_entry.protocol_id);
-    if (!IsAlternateProtocolValid(protocol) ||
-        !IsProtocolEnabled(protocol, is_http2_enabled, is_quic_enabled) ||
-        !IsPortValid(alternative_service_entry.port)) {
-      continue;
-    }
     // Check if QUIC version is supported. Filter supported QUIC versions.
     quic::ParsedQuicVersionVector advertised_versions;
-    if (protocol == kProtoQUIC && !alternative_service_entry.version.empty()) {
-      advertised_versions = FilterSupportedAltSvcVersions(
-          alternative_service_entry, supported_quic_versions,
-          support_ietf_format_quic_altsvc);
-      if (advertised_versions.empty())
+    if (protocol == kProtoQUIC) {
+      if (!IsProtocolEnabled(protocol, is_http2_enabled, is_quic_enabled))
         continue;
+      if (!alternative_service_entry.version.empty()) {
+        advertised_versions = FilterSupportedAltSvcVersions(
+            alternative_service_entry, supported_quic_versions,
+            support_ietf_format_quic_altsvc);
+        if (advertised_versions.empty())
+          continue;
+      }
+    } else if (!IsAlternateProtocolValid(protocol)) {
+      quic::ParsedQuicVersion version = ParsedQuicVersionFromAlpn(
+          alternative_service_entry.protocol_id, supported_quic_versions);
+      if (version.handshake_protocol == quic::PROTOCOL_UNSUPPORTED ||
+          version.transport_version == quic::QUIC_VERSION_UNSUPPORTED) {
+        continue;
+      }
+      protocol = kProtoQUIC;
+      advertised_versions = {version};
     }
+    if (!IsAlternateProtocolValid(protocol) ||
+        !IsProtocolEnabled(protocol, is_http2_enabled, is_quic_enabled)) {
+      continue;
+    }
+
     AlternativeService alternative_service(protocol,
                                            alternative_service_entry.host,
                                            alternative_service_entry.port);
diff --git a/net/http/http_stream_factory.cc b/net/http/http_stream_factory.cc
index b3d49e6..55df864 100644
--- a/net/http/http_stream_factory.cc
+++ b/net/http/http_stream_factory.cc
@@ -43,6 +43,7 @@
 
 namespace {
 const char kAlternativeServiceHeader[] = "Alt-Svc";
+
 }  // namespace
 
 HttpStreamFactory::HttpStreamFactory(HttpNetworkSession* session)
diff --git a/net/http/http_stream_factory_job_controller_unittest.cc b/net/http/http_stream_factory_job_controller_unittest.cc
index 2f9c443..9d3c052 100644
--- a/net/http/http_stream_factory_job_controller_unittest.cc
+++ b/net/http/http_stream_factory_job_controller_unittest.cc
@@ -1046,7 +1046,12 @@
        AltJobSucceedsMainJobBlockedControllerDestroyed) {
   quic_data_ = std::make_unique<MockQuicData>(
       HttpNetworkSession::Params().quic_params.supported_versions.front());
-  quic_data_->AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
+  if (VersionUsesQpack(HttpNetworkSession::Params()
+                           .quic_params.supported_versions.front()
+                           .transport_version)) {
+    quic_data_->AddWrite(SYNCHRONOUS,
+                         client_maker_.MakeInitialSettingsPacket(1));
+  }
   quic_data_->AddRead(ASYNC, OK);
 
   HttpRequestInfo request_info;
@@ -2321,9 +2326,13 @@
 }
 
 TEST_F(HttpStreamFactoryJobControllerTest, PreconnectToHostWithValidAltSvc) {
-  quic_data_ = std::make_unique<MockQuicData>(
-      HttpNetworkSession::Params().quic_params.supported_versions.front());
-  quic_data_->AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
+  auto version =
+      HttpNetworkSession::Params().quic_params.supported_versions.front();
+  quic_data_ = std::make_unique<MockQuicData>(version);
+  if (VersionUsesQpack(version.transport_version)) {
+    quic_data_->AddWrite(SYNCHRONOUS,
+                         client_maker_.MakeInitialSettingsPacket(1));
+  }
   quic_data_->AddRead(ASYNC, OK);
 
   HttpRequestInfo request_info;
@@ -3005,11 +3014,14 @@
   const bool enable_ip_based_pooling = ::testing::get<0>(GetParam());
   const bool enable_alternative_services = ::testing::get<1>(GetParam());
   if (enable_alternative_services) {
-    quic_data_ = std::make_unique<MockQuicData>(
-        HttpNetworkSession::Params().quic_params.supported_versions.front());
+    auto version =
+        HttpNetworkSession::Params().quic_params.supported_versions.front();
+    quic_data_ = std::make_unique<MockQuicData>(version);
     quic_data_->AddConnect(SYNCHRONOUS, OK);
-    quic_data_->AddWrite(SYNCHRONOUS,
-                         client_maker_.MakeInitialSettingsPacket(1));
+    if (VersionUsesQpack(version.transport_version)) {
+      quic_data_->AddWrite(SYNCHRONOUS,
+                           client_maker_.MakeInitialSettingsPacket(1));
+    }
     quic_data_->AddRead(ASYNC, OK);
   }
   tcp_data_ = std::make_unique<SequencedSocketData>();
diff --git a/net/http/http_stream_factory_unittest.cc b/net/http/http_stream_factory_unittest.cc
index a954e813c..e4226c3 100644
--- a/net/http/http_stream_factory_unittest.cc
+++ b/net/http/http_stream_factory_unittest.cc
@@ -2438,9 +2438,13 @@
   spdy::SpdyPriority priority =
       ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY);
   size_t spdy_headers_frame_length;
-  mock_quic_data.AddWrite(client_packet_maker().MakeInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version().transport_version)) {
+    mock_quic_data.AddWrite(
+        client_packet_maker().MakeInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data.AddWrite(client_packet_maker().MakeRequestHeadersPacket(
-      2, GetNthClientInitiatedBidirectionalStreamId(0),
+      packet_num++, GetNthClientInitiatedBidirectionalStreamId(0),
       /*should_include_version=*/true,
       /*fin=*/true, priority,
       client_packet_maker().GetRequestHeaders("GET", "https", "/"),
@@ -2563,9 +2567,13 @@
   spdy::SpdyPriority priority =
       ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY);
   size_t spdy_headers_frame_length;
-  mock_quic_data.AddWrite(client_packet_maker().MakeInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version().transport_version)) {
+    mock_quic_data.AddWrite(
+        client_packet_maker().MakeInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data.AddWrite(client_packet_maker().MakeRequestHeadersPacket(
-      2, GetNthClientInitiatedBidirectionalStreamId(0),
+      packet_num++, GetNthClientInitiatedBidirectionalStreamId(0),
       /*should_include_version=*/true,
       /*fin=*/true, priority,
       client_packet_maker().GetRequestHeaders("GET", "https", "/"),
@@ -2814,9 +2822,13 @@
   spdy::SpdyPriority priority =
       ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY);
   size_t spdy_headers_frame_length;
-  mock_quic_data.AddWrite(client_packet_maker().MakeInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version().transport_version)) {
+    mock_quic_data.AddWrite(
+        client_packet_maker().MakeInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data.AddWrite(client_packet_maker().MakeRequestHeadersPacket(
-      2, GetNthClientInitiatedBidirectionalStreamId(0),
+      packet_num++, GetNthClientInitiatedBidirectionalStreamId(0),
       /*should_include_version=*/true,
       /*fin=*/true, priority,
       client_packet_maker().GetRequestHeaders("GET", "https", "/"),
@@ -2833,9 +2845,13 @@
   // Prepare mock QUIC data for a second session establishment.
   client_packet_maker().Reset();
   MockQuicData mock_quic_data2(version());
-  mock_quic_data2.AddWrite(client_packet_maker().MakeInitialSettingsPacket(1));
+  packet_num = 1;
+  if (VersionUsesQpack(version().transport_version)) {
+    mock_quic_data2.AddWrite(
+        client_packet_maker().MakeInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data2.AddWrite(client_packet_maker().MakeRequestHeadersPacket(
-      2, GetNthClientInitiatedBidirectionalStreamId(0),
+      packet_num++, GetNthClientInitiatedBidirectionalStreamId(0),
       /*should_include_version=*/true,
       /*fin=*/true, priority,
       client_packet_maker().GetRequestHeaders("GET", "https", "/"),
@@ -3432,6 +3448,188 @@
              HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct())));
 }
 
+class ProcessAlternativeServicesTest : public TestWithTaskEnvironment {
+ public:
+  ProcessAlternativeServicesTest() {
+    session_params_.enable_quic = true;
+
+    session_context_.proxy_resolution_service = proxy_resolution_service_.get();
+    session_context_.host_resolver = &host_resolver_;
+    session_context_.cert_verifier = &cert_verifier_;
+    session_context_.transport_security_state = &transport_security_state_;
+    session_context_.cert_transparency_verifier = &ct_verifier_;
+    session_context_.client_socket_factory = &socket_factory_;
+    session_context_.ct_policy_enforcer = &ct_policy_enforcer_;
+    session_context_.ssl_config_service = &ssl_config_service_;
+    session_context_.http_server_properties = &http_server_properties_;
+  }
+
+ protected:
+  HttpNetworkSession::Params session_params_;
+  HttpNetworkSession::Context session_context_;
+  std::unique_ptr<HttpNetworkSession> session_;
+  HttpServerProperties http_server_properties_;
+
+ private:
+  std::unique_ptr<ProxyResolutionService> proxy_resolution_service_ =
+      ProxyResolutionService::CreateDirect();
+  SSLConfigServiceDefaults ssl_config_service_;
+  MockClientSocketFactory socket_factory_;
+  MockHostResolver host_resolver_;
+  MockCertVerifier cert_verifier_;
+  TransportSecurityState transport_security_state_;
+  MultiLogCTVerifier ct_verifier_;
+  DefaultCTPolicyEnforcer ct_policy_enforcer_;
+};
+
+TEST_F(ProcessAlternativeServicesTest, ProcessEmptyAltSvc) {
+  session_ =
+      std::make_unique<HttpNetworkSession>(session_params_, session_context_);
+  url::SchemeHostPort origin;
+  NetworkIsolationKey network_isolation_key;
+
+  scoped_refptr<HttpResponseHeaders> headers(
+      base::MakeRefCounted<HttpResponseHeaders>(""));
+  session_->http_stream_factory()->ProcessAlternativeServices(
+      session_.get(), network_isolation_key, headers.get(), origin);
+
+  AlternativeServiceInfoVector alternatives =
+      http_server_properties_.GetAlternativeServiceInfos(origin,
+                                                         network_isolation_key);
+  EXPECT_TRUE(alternatives.empty());
+}
+
+TEST_F(ProcessAlternativeServicesTest, ProcessAltSvcClear) {
+  session_ =
+      std::make_unique<HttpNetworkSession>(session_params_, session_context_);
+  url::SchemeHostPort origin(url::kHttpsScheme, "example.com", 443);
+  ;
+  NetworkIsolationKey network_isolation_key(
+      url::Origin::Create(GURL("https://example.com")),
+      url::Origin::Create(GURL("https://example.com")));
+
+  http_server_properties_.SetAlternativeServices(
+      origin, network_isolation_key,
+      {AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
+          {kProtoQUIC, "", 443},
+          base::Time::Now() + base::TimeDelta::FromSeconds(30),
+          quic::AllSupportedVersions())});
+
+  EXPECT_FALSE(http_server_properties_
+                   .GetAlternativeServiceInfos(origin, network_isolation_key)
+                   .empty());
+
+  scoped_refptr<HttpResponseHeaders> headers(
+      base::MakeRefCounted<HttpResponseHeaders>(""));
+  headers->AddHeader("alt-svc: clear");
+
+  session_->http_stream_factory()->ProcessAlternativeServices(
+      session_.get(), network_isolation_key, headers.get(), origin);
+
+  AlternativeServiceInfoVector alternatives =
+      http_server_properties_.GetAlternativeServiceInfos(origin,
+                                                         network_isolation_key);
+  EXPECT_TRUE(alternatives.empty());
+}
+
+TEST_F(ProcessAlternativeServicesTest, ProcessAltSvcQuic) {
+  session_params_.quic_params.supported_versions = quic::AllSupportedVersions();
+  session_ =
+      std::make_unique<HttpNetworkSession>(session_params_, session_context_);
+  url::SchemeHostPort origin(url::kHttpsScheme, "example.com", 443);
+
+  NetworkIsolationKey network_isolation_key(
+      url::Origin::Create(GURL("https://example.com")),
+      url::Origin::Create(GURL("https://example.com")));
+
+  scoped_refptr<HttpResponseHeaders> headers(
+      base::MakeRefCounted<HttpResponseHeaders>(""));
+  headers->AddHeader("alt-svc: quic=\":443\"; v=\"99,48,47,46,43,39\"");
+
+  session_->http_stream_factory()->ProcessAlternativeServices(
+      session_.get(), network_isolation_key, headers.get(), origin);
+
+  AlternativeServiceInfoVector alternatives =
+      http_server_properties_.GetAlternativeServiceInfos(origin,
+                                                         network_isolation_key);
+  ASSERT_EQ(1u, alternatives.size());
+  EXPECT_EQ(kProtoQUIC, alternatives[0].protocol());
+  EXPECT_EQ(HostPortPair("example.com", 443), alternatives[0].host_port_pair());
+  EXPECT_EQ(quic::AllSupportedVersions().size(),
+            alternatives[0].advertised_versions().size());
+  for (quic::ParsedQuicVersion version : quic::AllSupportedVersions()) {
+    EXPECT_TRUE(base::Contains(alternatives[0].advertised_versions(), version))
+        << version;
+  }
+}
+
+TEST_F(ProcessAlternativeServicesTest, ProcessAltSvcQuicIetf) {
+  session_params_.quic_params.supported_versions = quic::AllSupportedVersions();
+  session_ =
+      std::make_unique<HttpNetworkSession>(session_params_, session_context_);
+  url::SchemeHostPort origin(url::kHttpsScheme, "example.com", 443);
+
+  NetworkIsolationKey network_isolation_key(
+      url::Origin::Create(GURL("https://example.com")),
+      url::Origin::Create(GURL("https://example.com")));
+
+  scoped_refptr<HttpResponseHeaders> headers(
+      base::MakeRefCounted<HttpResponseHeaders>(""));
+  headers->AddHeader(
+      "alt-svc: "
+      "h3-Q099=\":443\",h3-Q048=\":443\",h3-Q047=\":443\",h3-Q043=\":443\",h3-"
+      "Q039=\":443\"");
+
+  session_->http_stream_factory()->ProcessAlternativeServices(
+      session_.get(), network_isolation_key, headers.get(), origin);
+
+  quic::ParsedQuicVersionVector versions = {
+      {quic::PROTOCOL_QUIC_CRYPTO, quic::QUIC_VERSION_99},
+      {quic::PROTOCOL_QUIC_CRYPTO, quic::QUIC_VERSION_48},
+      {quic::PROTOCOL_QUIC_CRYPTO, quic::QUIC_VERSION_47},
+      {quic::PROTOCOL_QUIC_CRYPTO, quic::QUIC_VERSION_43},
+      {quic::PROTOCOL_QUIC_CRYPTO, quic::QUIC_VERSION_39},
+  };
+  AlternativeServiceInfoVector alternatives =
+      http_server_properties_.GetAlternativeServiceInfos(origin,
+                                                         network_isolation_key);
+  ASSERT_EQ(versions.size(), alternatives.size());
+  for (size_t i = 0; i < alternatives.size(); ++i) {
+    EXPECT_EQ(kProtoQUIC, alternatives[i].protocol());
+    EXPECT_EQ(HostPortPair("example.com", 443),
+              alternatives[i].host_port_pair());
+    EXPECT_EQ(1u, alternatives[i].advertised_versions().size());
+    EXPECT_EQ(versions[i], alternatives[i].advertised_versions()[0]);
+  }
+}
+
+TEST_F(ProcessAlternativeServicesTest, ProcessAltSvcHttp2) {
+  session_params_.quic_params.supported_versions = quic::AllSupportedVersions();
+  session_ =
+      std::make_unique<HttpNetworkSession>(session_params_, session_context_);
+  url::SchemeHostPort origin(url::kHttpsScheme, "example.com", 443);
+
+  NetworkIsolationKey network_isolation_key(
+      url::Origin::Create(GURL("https://example.com")),
+      url::Origin::Create(GURL("https://example.com")));
+
+  scoped_refptr<HttpResponseHeaders> headers(
+      base::MakeRefCounted<HttpResponseHeaders>(""));
+  headers->AddHeader("alt-svc: h2=\"other.example.com:443\"");
+
+  session_->http_stream_factory()->ProcessAlternativeServices(
+      session_.get(), network_isolation_key, headers.get(), origin);
+
+  AlternativeServiceInfoVector alternatives =
+      http_server_properties_.GetAlternativeServiceInfos(origin,
+                                                         network_isolation_key);
+  ASSERT_EQ(1u, alternatives.size());
+  EXPECT_EQ(kProtoHTTP2, alternatives[0].protocol());
+  EXPECT_EQ(HostPortPair("other.example.com", 443),
+            alternatives[0].host_port_pair());
+  EXPECT_EQ(0u, alternatives[0].advertised_versions().size());
+}
+
 }  // namespace
 
 }  // namespace net
diff --git a/net/log/file_net_log_observer.cc b/net/log/file_net_log_observer.cc
index 4c50ece..981c904 100644
--- a/net/log/file_net_log_observer.cc
+++ b/net/log/file_net_log_observer.cc
@@ -386,9 +386,9 @@
   net_log()->RemoveObserver(this);
 
   base::OnceClosure bound_flush_then_stop =
-      base::Bind(&FileNetLogObserver::FileWriter::FlushThenStop,
-                 base::Unretained(file_writer_.get()), write_queue_,
-                 base::Passed(&polled_data));
+      base::BindOnce(&FileNetLogObserver::FileWriter::FlushThenStop,
+                     base::Unretained(file_writer_.get()), write_queue_,
+                     std::move(polled_data));
 
   // Note that PostTaskAndReply() requires a non-null closure.
   if (!optional_callback.is_null()) {
diff --git a/net/proxy_resolution/multi_threaded_proxy_resolver_unittest.cc b/net/proxy_resolution/multi_threaded_proxy_resolver_unittest.cc
index b01fa1f..d7b5a6b 100644
--- a/net/proxy_resolution/multi_threaded_proxy_resolver_unittest.cc
+++ b/net/proxy_resolution/multi_threaded_proxy_resolver_unittest.cc
@@ -737,7 +737,7 @@
     std::unique_ptr<ProxyResolver> resolver;
     EXPECT_EQ(ERR_IO_PENDING, resolver_factory.CreateProxyResolver(
                                   PacFileData::FromUTF8("pac script bytes"),
-                                  &resolver, base::Bind(&Fail), &request));
+                                  &resolver, base::BindOnce(&Fail), &request));
     EXPECT_TRUE(request);
     request.reset();
   }
@@ -782,7 +782,7 @@
         kNumThreads, std::make_unique<BlockableProxyResolverFactory>());
     EXPECT_EQ(ERR_IO_PENDING, resolver_factory.CreateProxyResolver(
                                   PacFileData::FromUTF8("pac script bytes"),
-                                  &resolver, base::Bind(&Fail), &request));
+                                  &resolver, base::BindOnce(&Fail), &request));
     EXPECT_TRUE(request);
   }
   // The factory destructor will block until the worker thread stops, but it may
diff --git a/net/proxy_resolution/pac_file_decider.cc b/net/proxy_resolution/pac_file_decider.cc
index 8c5fc8d..a66025b4 100644
--- a/net/proxy_resolution/pac_file_decider.cc
+++ b/net/proxy_resolution/pac_file_decider.cc
@@ -286,7 +286,7 @@
   next_state_ = STATE_QUICK_CHECK_COMPLETE;
   quick_check_timer_.Start(
       FROM_HERE, base::TimeDelta::FromMilliseconds(kQuickCheckDelayMs),
-      base::BindRepeating(callback, ERR_NAME_NOT_RESOLVED));
+      base::BindOnce(callback, ERR_NAME_NOT_RESOLVED));
 
   return resolve_request_->Start(callback);
 }
@@ -323,7 +323,7 @@
 
     return dhcp_pac_file_fetcher_->Fetch(
         &pac_script_,
-        base::Bind(&PacFileDecider::OnIOCompletion, base::Unretained(this)),
+        base::BindOnce(&PacFileDecider::OnIOCompletion, base::Unretained(this)),
         net_log_, NetworkTrafficAnnotationTag(traffic_annotation_));
   }
 
@@ -334,7 +334,7 @@
 
   return pac_file_fetcher_->Fetch(
       effective_pac_url, &pac_script_,
-      base::Bind(&PacFileDecider::OnIOCompletion, base::Unretained(this)),
+      base::BindOnce(&PacFileDecider::OnIOCompletion, base::Unretained(this)),
       NetworkTrafficAnnotationTag(traffic_annotation_));
 }
 
diff --git a/net/proxy_resolution/proxy_resolution_service.cc b/net/proxy_resolution/proxy_resolution_service.cc
index fc422b4..bea9e508 100644
--- a/net/proxy_resolution/proxy_resolution_service.cc
+++ b/net/proxy_resolution/proxy_resolution_service.cc
@@ -571,9 +571,10 @@
   int DoDecidePacFile() {
     next_state_ = STATE_DECIDE_PAC_FILE_COMPLETE;
 
-    return decider_->Start(
-        config_, wait_delay_, proxy_resolver_factory_->expects_pac_bytes(),
-        base::Bind(&InitProxyResolver::OnIOCompletion, base::Unretained(this)));
+    return decider_->Start(config_, wait_delay_,
+                           proxy_resolver_factory_->expects_pac_bytes(),
+                           base::BindOnce(&InitProxyResolver::OnIOCompletion,
+                                          base::Unretained(this)));
   }
 
   int DoDecidePacFileComplete(int result) {
@@ -593,7 +594,8 @@
     next_state_ = STATE_CREATE_RESOLVER_COMPLETE;
     return proxy_resolver_factory_->CreateProxyResolver(
         script_data_.data, proxy_resolver_,
-        base::Bind(&InitProxyResolver::OnIOCompletion, base::Unretained(this)),
+        base::BindOnce(&InitProxyResolver::OnIOCompletion,
+                       base::Unretained(this)),
         &create_resolver_request_);
   }
 
@@ -740,8 +742,8 @@
     decider_->set_quick_check_enabled(quick_check_enabled_);
     int result = decider_->Start(
         config_, TimeDelta(), proxy_resolver_expects_pac_bytes_,
-        base::Bind(&PacFileDeciderPoller::OnPacFileDeciderCompleted,
-                   base::Unretained(this)));
+        base::BindOnce(&PacFileDeciderPoller::OnPacFileDeciderCompleted,
+                       base::Unretained(this)));
 
     if (result != ERR_IO_PENDING)
       OnPacFileDeciderCompleted(result);
@@ -945,8 +947,8 @@
 
   return resolver()->GetProxyForURL(
       url_, results_,
-      base::Bind(&ProxyResolutionService::RequestImpl::QueryComplete,
-                 base::Unretained(this)),
+      base::BindOnce(&ProxyResolutionService::RequestImpl::QueryComplete,
+                     base::Unretained(this)),
       &resolve_job_, net_log_);
 }
 
@@ -1664,8 +1666,8 @@
       &resolver_, resolver_factory_.get(), pac_file_fetcher_.get(),
       dhcp_pac_file_fetcher_.get(), net_log_, fetched_config_.value(),
       wait_delay,
-      base::Bind(&ProxyResolutionService::OnInitProxyResolverComplete,
-                 base::Unretained(this)));
+      base::BindOnce(&ProxyResolutionService::OnInitProxyResolverComplete,
+                     base::Unretained(this)));
 
   if (rv != ERR_IO_PENDING)
     OnInitProxyResolverComplete(rv);
@@ -1686,8 +1688,8 @@
   int rv = init_proxy_resolver_->StartSkipDecider(
       &resolver_, resolver_factory_.get(), effective_config, decider_result,
       script_data,
-      base::Bind(&ProxyResolutionService::OnInitProxyResolverComplete,
-                 base::Unretained(this)));
+      base::BindOnce(&ProxyResolutionService::OnInitProxyResolverComplete,
+                     base::Unretained(this)));
 
   if (rv != ERR_IO_PENDING)
     OnInitProxyResolverComplete(rv);
diff --git a/net/quic/bidirectional_stream_quic_impl_unittest.cc b/net/quic/bidirectional_stream_quic_impl_unittest.cc
index a00e8075..00cecd9 100644
--- a/net/quic/bidirectional_stream_quic_impl_unittest.cc
+++ b/net/quic/bidirectional_stream_quic_impl_unittest.cc
@@ -864,9 +864,6 @@
       GetNthClientInitiatedBidirectionalStreamId(0), kFin, DEFAULT_PRIORITY,
       &spdy_request_headers_frame_length));
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
-  if (!quic::VersionUsesQpack(version_.transport_version)) {
-    AddWrite(ConstructInitialSettingsPacket());
-  }
   AddWrite(ConstructClientAckPacket(3, 1, 2));
 
   Initialize();
@@ -973,9 +970,6 @@
       GetNthClientInitiatedBidirectionalStreamId(1), kFin, DEFAULT_PRIORITY,
       GetNthClientInitiatedBidirectionalStreamId(0), nullptr));
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
-  if (!quic::VersionUsesQpack(version_.transport_version)) {
-    AddWrite(ConstructInitialSettingsPacket());
-  }
   AddWrite(ConstructClientAckPacket(3, 1, 2));
   Initialize();
 
@@ -1039,7 +1033,8 @@
 TEST_P(BidirectionalStreamQuicImplTest, CoalesceDataBuffersNotHeadersFrame) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  AddWrite(ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    AddWrite(ConstructInitialSettingsPacket());
   const char kBody1[] = "here are some data";
   const char kBody2[] = "data keep coming";
   std::string header = ConstructDataHeader(strlen(kBody1));
@@ -1178,7 +1173,8 @@
        SendDataCoalesceDataBufferAndHeaderFrame) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  AddWrite(ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    AddWrite(ConstructInitialSettingsPacket());
   const char kBody1[] = "here are some data";
   std::string header = ConstructDataHeader(strlen(kBody1));
   if (version_.transport_version == quic::QUIC_VERSION_99) {
@@ -1292,7 +1288,8 @@
        SendvDataCoalesceDataBuffersAndHeaderFrame) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  AddWrite(ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    AddWrite(ConstructInitialSettingsPacket());
   const char kBody1[] = "here are some data";
   const char kBody2[] = "data keep coming";
   std::string header = ConstructDataHeader(strlen(kBody1));
@@ -1423,7 +1420,8 @@
 // headers to be sent, if that write fails the stream does not crash.
 TEST_P(BidirectionalStreamQuicImplTest,
        SendDataWriteErrorCoalesceDataBufferAndHeaderFrame) {
-  AddWrite(ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    AddWrite(ConstructInitialSettingsPacket());
   AddWriteError(SYNCHRONOUS, ERR_CONNECTION_REFUSED);
 
   Initialize();
@@ -1458,7 +1456,8 @@
 // headers to be sent, if that write fails the stream does not crash.
 TEST_P(BidirectionalStreamQuicImplTest,
        SendvDataWriteErrorCoalesceDataBufferAndHeaderFrame) {
-  AddWrite(ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    AddWrite(ConstructInitialSettingsPacket());
   AddWriteError(SYNCHRONOUS, ERR_CONNECTION_REFUSED);
 
   Initialize();
@@ -1496,7 +1495,8 @@
 TEST_P(BidirectionalStreamQuicImplTest, PostRequest) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  AddWrite(ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    AddWrite(ConstructInitialSettingsPacket());
   AddWrite(ConstructRequestHeadersPacketInner(
       GetNthClientInitiatedBidirectionalStreamId(0), !kFin, DEFAULT_PRIORITY,
       &spdy_request_headers_frame_length));
@@ -1589,7 +1589,8 @@
 TEST_P(BidirectionalStreamQuicImplTest, EarlyDataOverrideRequest) {
   SetRequest("PUT", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  AddWrite(ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    AddWrite(ConstructInitialSettingsPacket());
   AddWrite(ConstructRequestHeadersPacketInner(
       GetNthClientInitiatedBidirectionalStreamId(0), !kFin, DEFAULT_PRIORITY,
       &spdy_request_headers_frame_length));
@@ -1683,7 +1684,8 @@
 TEST_P(BidirectionalStreamQuicImplTest, InterleaveReadDataAndSendData) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  AddWrite(ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    AddWrite(ConstructInitialSettingsPacket());
   AddWrite(ConstructRequestHeadersPacketInner(
       GetNthClientInitiatedBidirectionalStreamId(0), !kFin, DEFAULT_PRIORITY,
       &spdy_request_headers_frame_length));
@@ -1743,9 +1745,12 @@
   const char kResponseBody[] = "Hello world!";
 
   std::string header2 = ConstructDataHeader(strlen(kResponseBody));
-  // Server sends a data packet.
-  ProcessPacket(ConstructAckAndDataPacket(3, !kIncludeVersion, 2, 1, 1, !kFin,
-                                          header2 + kResponseBody,
+  // Server sends a data packet
+  int server_ack = 1;
+  if (VersionUsesQpack(version_.transport_version))
+    server_ack++;
+  ProcessPacket(ConstructAckAndDataPacket(3, !kIncludeVersion, server_ack++, 1,
+                                          1, !kFin, header2 + kResponseBody,
                                           &server_maker_));
 
   EXPECT_EQ(static_cast<int64_t>(strlen(kResponseBody)), cb.WaitForResult());
@@ -1758,10 +1763,10 @@
   TestCompletionCallback cb2;
   rv = delegate->ReadData(cb2.callback());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
-  ProcessPacket(ConstructAckAndDataPacket(4, !kIncludeVersion, 3, 1, 1, kFin,
+  ProcessPacket(
+      ConstructAckAndDataPacket(4, !kIncludeVersion, server_ack++, 1, 1, kFin,
 
-                                          header2 + kResponseBody,
-                                          &server_maker_));
+                                header2 + kResponseBody, &server_maker_));
 
   EXPECT_EQ(static_cast<int64_t>(strlen(kResponseBody)), cb2.WaitForResult());
 
@@ -1790,9 +1795,6 @@
       GetNthClientInitiatedBidirectionalStreamId(0), kFin, DEFAULT_PRIORITY,
       &spdy_request_headers_frame_length));
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
-  if (!quic::VersionUsesQpack(version_.transport_version)) {
-    AddWrite(ConstructInitialSettingsPacket());
-  }
   Initialize();
 
   BidirectionalStreamRequestInfo request;
@@ -1837,9 +1839,6 @@
       GetNthClientInitiatedBidirectionalStreamId(0), kFin, DEFAULT_PRIORITY,
       &spdy_request_headers_frame_length));
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
-  if (!quic::VersionUsesQpack(version_.transport_version)) {
-    AddWrite(ConstructInitialSettingsPacket());
-  }
   // Why does QUIC ack Rst? Is this expected?
   AddWrite(ConstructClientAckPacket(3, 1, 2));
 
@@ -1897,7 +1896,8 @@
 TEST_P(BidirectionalStreamQuicImplTest, SessionClosedBeforeReadData) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  AddWrite(ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    AddWrite(ConstructInitialSettingsPacket());
   AddWrite(ConstructRequestHeadersPacketInner(
       GetNthClientInitiatedBidirectionalStreamId(0), !kFin, DEFAULT_PRIORITY,
       &spdy_request_headers_frame_length));
@@ -2005,7 +2005,8 @@
 
 TEST_P(BidirectionalStreamQuicImplTest, SessionCloseDuringOnStreamReady) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
-  AddWrite(ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    AddWrite(ConstructInitialSettingsPacket());
   AddWriteError(SYNCHRONOUS, ERR_CONNECTION_REFUSED);
 
   Initialize();
@@ -2032,7 +2033,8 @@
 TEST_P(BidirectionalStreamQuicImplTest, DeleteStreamDuringOnStreamReady) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  AddWrite(ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    AddWrite(ConstructInitialSettingsPacket());
   AddWrite(ConstructRequestHeadersPacketInner(
       GetNthClientInitiatedBidirectionalStreamId(0), !kFin, DEFAULT_PRIORITY,
       &spdy_request_headers_frame_length));
@@ -2063,7 +2065,8 @@
 TEST_P(BidirectionalStreamQuicImplTest, DeleteStreamAfterReadData) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  AddWrite(ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    AddWrite(ConstructInitialSettingsPacket());
   AddWrite(ConstructRequestHeadersPacketInner(
       GetNthClientInitiatedBidirectionalStreamId(0), !kFin, DEFAULT_PRIORITY,
       &spdy_request_headers_frame_length));
@@ -2118,7 +2121,8 @@
 TEST_P(BidirectionalStreamQuicImplTest, DeleteStreamDuringOnHeadersReceived) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  AddWrite(ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    AddWrite(ConstructInitialSettingsPacket());
   AddWrite(ConstructRequestHeadersPacketInner(
       GetNthClientInitiatedBidirectionalStreamId(0), !kFin, DEFAULT_PRIORITY,
       &spdy_request_headers_frame_length));
@@ -2165,7 +2169,8 @@
 TEST_P(BidirectionalStreamQuicImplTest, DeleteStreamDuringOnDataRead) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  AddWrite(ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    AddWrite(ConstructInitialSettingsPacket());
   AddWrite(ConstructRequestHeadersPacketInner(
       GetNthClientInitiatedBidirectionalStreamId(0), !kFin, DEFAULT_PRIORITY,
       &spdy_request_headers_frame_length));
@@ -2224,7 +2229,8 @@
   const char kBody[] = "here is some data";
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  AddWrite(ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    AddWrite(ConstructInitialSettingsPacket());
   AddWrite(ConstructRequestHeadersPacketInner(
       GetNthClientInitiatedBidirectionalStreamId(0), !kFin, DEFAULT_PRIORITY,
       &spdy_request_headers_frame_length));
diff --git a/net/quic/platform/impl/quic_logging_impl.h b/net/quic/platform/impl/quic_logging_impl.h
index 0c240cb..ff72671 100644
--- a/net/quic/platform/impl/quic_logging_impl.h
+++ b/net/quic/platform/impl/quic_logging_impl.h
@@ -68,6 +68,7 @@
 #endif
 
 #define QUIC_PREDICT_FALSE_IMPL(x) x
+#define QUIC_PREDICT_TRUE_IMPL(x) x
 
 #define QUIC_NOTREACHED_IMPL() NOTREACHED()
 
diff --git a/net/quic/platform/impl/quic_mutex_impl.h b/net/quic/platform/impl/quic_mutex_impl.h
index d652dfe..da657ce 100644
--- a/net/quic/platform/impl/quic_mutex_impl.h
+++ b/net/quic/platform/impl/quic_mutex_impl.h
@@ -10,6 +10,17 @@
 #include "base/synchronization/waitable_event.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
 
+#define QUIC_EXCLUSIVE_LOCKS_REQUIRED_IMPL EXCLUSIVE_LOCKS_REQUIRED
+#define QUIC_GUARDED_BY_IMPL GUARDED_BY
+#define QUIC_LOCKABLE_IMPL LOCKABLE
+#define QUIC_LOCKS_EXCLUDED_IMPL LOCKS_EXCLUDED
+#define QUIC_SHARED_LOCKS_REQUIRED_IMPL SHARED_LOCKS_REQUIRED
+#define QUIC_EXCLUSIVE_LOCK_FUNCTION_IMPL EXCLUSIVE_LOCK_FUNCTION
+#define QUIC_UNLOCK_FUNCTION_IMPL UNLOCK_FUNCTION
+#define QUIC_SHARED_LOCK_FUNCTION_IMPL SHARED_LOCK_FUNCTION
+#define QUIC_SCOPED_LOCKABLE_IMPL SCOPED_LOCKABLE
+#define QUIC_ASSERT_SHARED_LOCK_IMPL ASSERT_SHARED_LOCK
+
 #ifndef EXCLUSIVE_LOCK_FUNCTION
 #define EXCLUSIVE_LOCK_FUNCTION(...)
 #endif
@@ -49,7 +60,7 @@
 namespace quic {
 
 // A class wrapping a non-reentrant mutex.
-class LOCKABLE QUIC_EXPORT_PRIVATE QuicLockImpl {
+class QUIC_LOCKABLE_IMPL QUIC_EXPORT_PRIVATE QuicLockImpl {
  public:
   QuicLockImpl() = default;
 
diff --git a/net/quic/quic_chromium_client_session_test.cc b/net/quic/quic_chromium_client_session_test.cc
index ccbe8a5..a0ab96b 100644
--- a/net/quic/quic_chromium_client_session_test.cc
+++ b/net/quic/quic_chromium_client_session_test.cc
@@ -263,12 +263,13 @@
 // kAppendInitiatingFrameOriginToNetworkIsolationKey.
 
 TEST_P(QuicChromiumClientSessionTest, IsFatalErrorNotSetForNonFatalError) {
-  MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
-  std::unique_ptr<quic::QuicEncryptedPacket> settings_packet(
-      client_maker_.MakeInitialSettingsPacket(1));
-  MockWrite writes[] = {
-      MockWrite(ASYNC, settings_packet->data(), settings_packet->length(), 1)};
-  socket_data_.reset(new SequencedSocketData(reads, writes));
+  MockQuicData quic_data(version_);
+  if (VersionUsesQpack(version_.transport_version))
+    quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
+  quic_data.AddRead(ASYNC, ERR_IO_PENDING);
+  quic_data.AddRead(ASYNC, OK);  // EOF
+  quic_data.AddSocketDataToFactory(&socket_factory_);
+
   Initialize();
 
   SSLInfo ssl_info;
@@ -286,12 +287,12 @@
 }
 
 TEST_P(QuicChromiumClientSessionTest, IsFatalErrorSetForFatalError) {
-  MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
-  std::unique_ptr<quic::QuicEncryptedPacket> settings_packet(
-      client_maker_.MakeInitialSettingsPacket(1));
-  MockWrite writes[] = {
-      MockWrite(ASYNC, settings_packet->data(), settings_packet->length(), 1)};
-  socket_data_.reset(new SequencedSocketData(reads, writes));
+  MockQuicData quic_data(version_);
+  if (VersionUsesQpack(version_.transport_version))
+    quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
+  quic_data.AddRead(ASYNC, ERR_IO_PENDING);
+  quic_data.AddRead(ASYNC, OK);  // EOF
+  quic_data.AddSocketDataToFactory(&socket_factory_);
   Initialize();
 
   SSLInfo ssl_info;
@@ -308,19 +309,20 @@
 }
 
 TEST_P(QuicChromiumClientSessionTest, CryptoConnect) {
-  MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
-  std::unique_ptr<quic::QuicEncryptedPacket> settings_packet(
-      client_maker_.MakeInitialSettingsPacket(1));
-  MockWrite writes[] = {
-      MockWrite(ASYNC, settings_packet->data(), settings_packet->length(), 1)};
-  socket_data_.reset(new SequencedSocketData(reads, writes));
+  MockQuicData quic_data(version_);
+  if (VersionUsesQpack(version_.transport_version))
+    quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
+  quic_data.AddRead(ASYNC, ERR_IO_PENDING);
+  quic_data.AddRead(ASYNC, OK);  // EOF
+  quic_data.AddSocketDataToFactory(&socket_factory_);
   Initialize();
   CompleteCryptoHandshake();
 }
 
 TEST_P(QuicChromiumClientSessionTest, Handle) {
   MockQuicData quic_data(version_);
-  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
+  if (VersionUsesQpack(version_.transport_version))
+    quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
   quic_data.AddRead(ASYNC, ERR_IO_PENDING);
   quic_data.AddRead(ASYNC, OK);  // EOF
   quic_data.AddSocketDataToFactory(&socket_factory_);
@@ -402,7 +404,8 @@
 
 TEST_P(QuicChromiumClientSessionTest, StreamRequest) {
   MockQuicData quic_data(version_);
-  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
+  if (VersionUsesQpack(version_.transport_version))
+    quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
   quic_data.AddRead(ASYNC, ERR_IO_PENDING);
   quic_data.AddRead(ASYNC, OK);  // EOF
   quic_data.AddSocketDataToFactory(&socket_factory_);
@@ -426,7 +429,8 @@
 
 TEST_P(QuicChromiumClientSessionTest, ConfirmationRequiredStreamRequest) {
   MockQuicData quic_data(version_);
-  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
+  if (VersionUsesQpack(version_.transport_version))
+    quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
   quic_data.AddRead(ASYNC, ERR_IO_PENDING);
   quic_data.AddRead(ASYNC, OK);  // EOF
   quic_data.AddSocketDataToFactory(&socket_factory_);
@@ -450,7 +454,8 @@
 
 TEST_P(QuicChromiumClientSessionTest, StreamRequestBeforeConfirmation) {
   MockQuicData quic_data(version_);
-  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
+  if (VersionUsesQpack(version_.transport_version))
+    quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
   quic_data.AddRead(ASYNC, ERR_IO_PENDING);
   quic_data.AddRead(ASYNC, OK);  // EOF
   quic_data.AddSocketDataToFactory(&socket_factory_);
@@ -479,11 +484,16 @@
 
 TEST_P(QuicChromiumClientSessionTest, CancelStreamRequestBeforeRelease) {
   MockQuicData quic_data(version_);
-  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
-  quic_data.AddWrite(SYNCHRONOUS,
-                     client_maker_.MakeRstPacket(
-                         2, true, GetNthClientInitiatedBidirectionalStreamId(0),
-                         quic::QUIC_STREAM_CANCELLED));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    quic_data.AddWrite(SYNCHRONOUS,
+                       client_maker_.MakeInitialSettingsPacket(packet_num++));
+  }
+  quic_data.AddWrite(
+      SYNCHRONOUS,
+      client_maker_.MakeRstPacket(packet_num++, true,
+                                  GetNthClientInitiatedBidirectionalStreamId(0),
+                                  quic::QUIC_STREAM_CANCELLED));
   quic_data.AddRead(ASYNC, ERR_IO_PENDING);
   quic_data.AddRead(ASYNC, OK);  // EOF
   quic_data.AddSocketDataToFactory(&socket_factory_);
@@ -507,8 +517,8 @@
 
 TEST_P(QuicChromiumClientSessionTest, AsyncStreamRequest) {
   MockQuicData quic_data(version_);
-  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
   if (version_.transport_version == quic::QUIC_VERSION_99) {
+    quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
     // The open stream limit is set to 50 by
     // MockCryptoClientStream::SetConfigNegotiated() so when the 51st stream is
     // requested, a STREAMS_BLOCKED will be sent, indicating that it's blocked
@@ -529,7 +539,7 @@
   } else {
     quic_data.AddWrite(
         SYNCHRONOUS, client_maker_.MakeRstPacket(
-                         2, true, GetNthClientInitiatedBidirectionalStreamId(0),
+                         1, true, GetNthClientInitiatedBidirectionalStreamId(0),
                          quic::QUIC_RST_ACKNOWLEDGEMENT));
   }
   quic_data.AddRead(ASYNC, ERR_IO_PENDING);
@@ -583,8 +593,8 @@
 
 TEST_P(QuicChromiumClientSessionTest, ClosedWithAsyncStreamRequest) {
   MockQuicData quic_data(version_);
-  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
   if (version_.transport_version == quic::QUIC_VERSION_99) {
+    quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
     // The open stream limit is set to 50 by
     // MockCryptoClientStream::SetConfigNegotiated() so when the 51st stream is
     // requested, a STREAMS_BLOCKED will be sent, indicating that it's blocked
@@ -645,8 +655,8 @@
 
 TEST_P(QuicChromiumClientSessionTest, CancelPendingStreamRequest) {
   MockQuicData quic_data(version_);
-  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
   if (version_.transport_version == quic::QUIC_VERSION_99) {
+    quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
     // The open stream limit is set to 50 by
     // MockCryptoClientStream::SetConfigNegotiated() so when the 51st stream is
     // requested, a STREAMS_BLOCKED will be sent.
@@ -663,7 +673,7 @@
   } else {
     quic_data.AddWrite(
         SYNCHRONOUS, client_maker_.MakeRstPacket(
-                         2, true, GetNthClientInitiatedBidirectionalStreamId(0),
+                         1, true, GetNthClientInitiatedBidirectionalStreamId(0),
                          quic::QUIC_RST_ACKNOWLEDGEMENT));
   }
   quic_data.AddRead(ASYNC, ERR_IO_PENDING);
@@ -716,16 +726,26 @@
 
 TEST_P(QuicChromiumClientSessionTest, ConnectionCloseBeforeStreamRequest) {
   MockQuicData quic_data(version_);
-  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    quic_data.AddWrite(SYNCHRONOUS,
+                       client_maker_.MakeInitialSettingsPacket(packet_num++));
+  }
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakePingPacket(packet_num++, true));
   quic_data.AddRead(
       ASYNC,
       server_maker_.MakeConnectionClosePacket(
           1, false, quic::QUIC_CRYPTO_VERSION_NOT_SUPPORTED, "Time to panic!"));
+
   quic_data.AddSocketDataToFactory(&socket_factory_);
 
   Initialize();
   CompleteCryptoHandshake();
 
+  // Send a ping so that client has outgoing traffic before receiving packets.
+  session_->SendPing();
+
   // Pump the message loop to read the connection close packet.
   base::RunLoop().RunUntilIdle();
 
@@ -784,10 +804,16 @@
 
 TEST_P(QuicChromiumClientSessionTest, ConnectionCloseWithPendingStreamRequest) {
   MockQuicData quic_data(version_);
-  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (version_.transport_version == quic::QUIC_VERSION_99) {
+    quic_data.AddWrite(SYNCHRONOUS,
+                       client_maker_.MakeInitialSettingsPacket(packet_num++));
+  }
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakePingPacket(packet_num++, true));
   if (version_.transport_version == quic::QUIC_VERSION_99) {
     quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeStreamsBlockedPacket(
-                                        2, true, 50,
+                                        packet_num++, true, 50,
                                         /*unidirectional=*/false));
   }
   quic_data.AddRead(ASYNC, ERR_IO_PENDING);
@@ -800,6 +826,9 @@
   Initialize();
   CompleteCryptoHandshake();
 
+  // Send a ping so that client has outgoing traffic before receiving packets.
+  session_->SendPing();
+
   // Open the maximum number of streams so that a subsequent request
   // can not proceed immediately.
   const size_t kMaxOpenStreams = GetMaxAllowedOutgoingBidirectionalStreams();
@@ -830,8 +859,8 @@
 
 TEST_P(QuicChromiumClientSessionTest, MaxNumStreams) {
   MockQuicData quic_data(version_);
-  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
   if (version_.transport_version == quic::QUIC_VERSION_99) {
+    quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
     // Initial configuration is 50 dynamic streams. Taking into account
     // the static stream (headers), expect to block on when hitting the limit
     // of 50 streams
@@ -853,7 +882,7 @@
   } else {
     quic_data.AddWrite(
         SYNCHRONOUS, client_maker_.MakeRstPacket(
-                         2, true, GetNthClientInitiatedBidirectionalStreamId(0),
+                         1, true, GetNthClientInitiatedBidirectionalStreamId(0),
                          quic::QUIC_RST_ACKNOWLEDGEMENT));
   }
   quic_data.AddRead(ASYNC, ERR_IO_PENDING);
@@ -897,17 +926,19 @@
 
 TEST_P(QuicChromiumClientSessionTest, PushStreamTimedOutNoResponse) {
   base::HistogramTester histogram_tester;
-  MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
-  std::unique_ptr<quic::QuicEncryptedPacket> settings_packet(
-      client_maker_.MakeInitialSettingsPacket(1));
-  std::unique_ptr<quic::QuicEncryptedPacket> client_rst(
-      client_maker_.MakeRstPacket(
-          2, true, GetNthServerInitiatedUnidirectionalStreamId(0),
-          quic::QUIC_PUSH_STREAM_TIMED_OUT));
-  MockWrite writes[] = {
-      MockWrite(ASYNC, settings_packet->data(), settings_packet->length(), 1),
-      MockWrite(ASYNC, client_rst->data(), client_rst->length(), 2)};
-  socket_data_.reset(new SequencedSocketData(reads, writes));
+  MockQuicData quic_data(version_);
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    quic_data.AddWrite(ASYNC,
+                       client_maker_.MakeInitialSettingsPacket(packet_num++));
+  }
+  quic_data.AddWrite(ASYNC, client_maker_.MakeRstPacket(
+                                packet_num++, true,
+                                GetNthServerInitiatedUnidirectionalStreamId(0),
+                                quic::QUIC_PUSH_STREAM_TIMED_OUT));
+  quic_data.AddRead(ASYNC, ERR_IO_PENDING);
+  quic_data.AddRead(ASYNC, OK);  // EOF
+  quic_data.AddSocketDataToFactory(&socket_factory_);
   Initialize();
 
   ProofVerifyDetailsChromium details;
@@ -949,17 +980,19 @@
 
 TEST_P(QuicChromiumClientSessionTest, PushStreamTimedOutWithResponse) {
   base::HistogramTester histogram_tester;
-  MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
-  std::unique_ptr<quic::QuicEncryptedPacket> settings_packet(
-      client_maker_.MakeInitialSettingsPacket(1));
-  std::unique_ptr<quic::QuicEncryptedPacket> client_rst(
-      client_maker_.MakeRstPacket(
-          2, true, GetNthServerInitiatedUnidirectionalStreamId(0),
-          quic::QUIC_PUSH_STREAM_TIMED_OUT));
-  MockWrite writes[] = {
-      MockWrite(ASYNC, settings_packet->data(), settings_packet->length(), 1),
-      MockWrite(ASYNC, client_rst->data(), client_rst->length(), 2)};
-  socket_data_.reset(new SequencedSocketData(reads, writes));
+  MockQuicData quic_data(version_);
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    quic_data.AddWrite(ASYNC,
+                       client_maker_.MakeInitialSettingsPacket(packet_num++));
+  }
+  quic_data.AddWrite(ASYNC, client_maker_.MakeRstPacket(
+                                packet_num++, true,
+                                GetNthServerInitiatedUnidirectionalStreamId(0),
+                                quic::QUIC_PUSH_STREAM_TIMED_OUT));
+  quic_data.AddRead(ASYNC, ERR_IO_PENDING);
+  quic_data.AddRead(ASYNC, OK);  // EOF
+  quic_data.AddSocketDataToFactory(&socket_factory_);
   Initialize();
 
   ProofVerifyDetailsChromium details;
@@ -1009,18 +1042,19 @@
   if (!quic::VersionHasStreamType(version_.transport_version))
     return;
 
-  MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
-  std::unique_ptr<quic::QuicEncryptedPacket> settings_packet(
-      client_maker_.MakeInitialSettingsPacket(1));
-  std::unique_ptr<quic::QuicEncryptedPacket> client_rst(
-      client_maker_.MakeRstPacket(
-          2, true, GetNthServerInitiatedUnidirectionalStreamId(0),
-          quic::QUIC_RST_ACKNOWLEDGEMENT));
-
-  MockWrite writes[] = {
-      MockWrite(ASYNC, settings_packet->data(), settings_packet->length(), 1),
-      MockWrite(ASYNC, client_rst->data(), client_rst->length(), 2)};
-  socket_data_.reset(new SequencedSocketData(reads, writes));
+  MockQuicData quic_data(version_);
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    quic_data.AddWrite(ASYNC,
+                       client_maker_.MakeInitialSettingsPacket(packet_num++));
+  }
+  quic_data.AddWrite(ASYNC, client_maker_.MakeRstPacket(
+                                packet_num++, true,
+                                GetNthServerInitiatedUnidirectionalStreamId(0),
+                                quic::QUIC_RST_ACKNOWLEDGEMENT));
+  quic_data.AddRead(ASYNC, ERR_IO_PENDING);
+  quic_data.AddRead(ASYNC, OK);  // EOF
+  quic_data.AddSocketDataToFactory(&socket_factory_);
 
   Initialize();
   CompleteCryptoHandshake();
@@ -1040,18 +1074,19 @@
   if (!quic::VersionHasStreamType(version_.transport_version))
     return;
 
-  MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
-  std::unique_ptr<quic::QuicEncryptedPacket> settings_packet(
-      client_maker_.MakeInitialSettingsPacket(1));
-  std::unique_ptr<quic::QuicEncryptedPacket> client_rst(
-      client_maker_.MakeRstPacket(
-          2, true, GetNthServerInitiatedUnidirectionalStreamId(0),
-          quic::QUIC_RST_ACKNOWLEDGEMENT));
-
-  MockWrite writes[] = {
-      MockWrite(ASYNC, settings_packet->data(), settings_packet->length(), 1),
-      MockWrite(ASYNC, client_rst->data(), client_rst->length(), 2)};
-  socket_data_.reset(new SequencedSocketData(reads, writes));
+  MockQuicData quic_data(version_);
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    quic_data.AddWrite(ASYNC,
+                       client_maker_.MakeInitialSettingsPacket(packet_num++));
+  }
+  quic_data.AddWrite(ASYNC, client_maker_.MakeRstPacket(
+                                packet_num++, true,
+                                GetNthServerInitiatedUnidirectionalStreamId(0),
+                                quic::QUIC_RST_ACKNOWLEDGEMENT));
+  quic_data.AddRead(ASYNC, ERR_IO_PENDING);
+  quic_data.AddRead(ASYNC, OK);  // EOF
+  quic_data.AddSocketDataToFactory(&socket_factory_);
 
   Initialize();
   CompleteCryptoHandshake();
@@ -1064,18 +1099,19 @@
 }
 
 TEST_P(QuicChromiumClientSessionTest, CancelPushWhenPendingValidation) {
-  MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
-  std::unique_ptr<quic::QuicEncryptedPacket> settings_packet(
-      client_maker_.MakeInitialSettingsPacket(1));
-  std::unique_ptr<quic::QuicEncryptedPacket> client_rst(
-      client_maker_.MakeRstPacket(2, true,
-                                  GetNthClientInitiatedBidirectionalStreamId(0),
-                                  quic::QUIC_RST_ACKNOWLEDGEMENT));
-
-  MockWrite writes[] = {
-      MockWrite(ASYNC, settings_packet->data(), settings_packet->length(), 1),
-      MockWrite(ASYNC, client_rst->data(), client_rst->length(), 2)};
-  socket_data_.reset(new SequencedSocketData(reads, writes));
+  MockQuicData quic_data(version_);
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    quic_data.AddWrite(ASYNC,
+                       client_maker_.MakeInitialSettingsPacket(packet_num++));
+  }
+  quic_data.AddWrite(ASYNC, client_maker_.MakeRstPacket(
+                                packet_num++, true,
+                                GetNthClientInitiatedBidirectionalStreamId(0),
+                                quic::QUIC_RST_ACKNOWLEDGEMENT));
+  quic_data.AddRead(ASYNC, ERR_IO_PENDING);
+  quic_data.AddRead(ASYNC, OK);  // EOF
+  quic_data.AddSocketDataToFactory(&socket_factory_);
   Initialize();
 
   ProofVerifyDetailsChromium details;
@@ -1121,17 +1157,19 @@
 
 TEST_P(QuicChromiumClientSessionTest, CancelPushBeforeReceivingResponse) {
   base::HistogramTester histogram_tester;
-  MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
-  std::unique_ptr<quic::QuicEncryptedPacket> settings_packet(
-      client_maker_.MakeInitialSettingsPacket(1));
-  std::unique_ptr<quic::QuicEncryptedPacket> client_rst(
-      client_maker_.MakeRstPacket(
-          2, true, GetNthServerInitiatedUnidirectionalStreamId(0),
-          quic::QUIC_STREAM_CANCELLED));
-  MockWrite writes[] = {
-      MockWrite(ASYNC, settings_packet->data(), settings_packet->length(), 1),
-      MockWrite(ASYNC, client_rst->data(), client_rst->length(), 2)};
-  socket_data_.reset(new SequencedSocketData(reads, writes));
+  MockQuicData quic_data(version_);
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    quic_data.AddWrite(ASYNC,
+                       client_maker_.MakeInitialSettingsPacket(packet_num++));
+  }
+  quic_data.AddWrite(ASYNC, client_maker_.MakeRstPacket(
+                                packet_num++, true,
+                                GetNthServerInitiatedUnidirectionalStreamId(0),
+                                quic::QUIC_STREAM_CANCELLED));
+  quic_data.AddRead(ASYNC, ERR_IO_PENDING);
+  quic_data.AddRead(ASYNC, OK);  // EOF
+  quic_data.AddSocketDataToFactory(&socket_factory_);
   Initialize();
 
   ProofVerifyDetailsChromium details;
@@ -1173,17 +1211,20 @@
 
 TEST_P(QuicChromiumClientSessionTest, CancelPushAfterReceivingResponse) {
   base::HistogramTester histogram_tester;
-  MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
-  std::unique_ptr<quic::QuicEncryptedPacket> settings_packet(
-      client_maker_.MakeInitialSettingsPacket(1));
-  std::unique_ptr<quic::QuicEncryptedPacket> client_rst(
-      client_maker_.MakeRstPacket(
-          2, true, GetNthServerInitiatedUnidirectionalStreamId(0),
-          quic::QUIC_STREAM_CANCELLED));
-  MockWrite writes[] = {
-      MockWrite(ASYNC, settings_packet->data(), settings_packet->length(), 1),
-      MockWrite(ASYNC, client_rst->data(), client_rst->length(), 2)};
-  socket_data_.reset(new SequencedSocketData(reads, writes));
+  MockQuicData quic_data(version_);
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    quic_data.AddWrite(ASYNC,
+                       client_maker_.MakeInitialSettingsPacket(packet_num++));
+  }
+  quic_data.AddWrite(ASYNC, client_maker_.MakeRstPacket(
+                                packet_num++, true,
+                                GetNthServerInitiatedUnidirectionalStreamId(0),
+                                quic::QUIC_STREAM_CANCELLED));
+  quic_data.AddRead(ASYNC, ERR_IO_PENDING);
+  quic_data.AddRead(ASYNC, OK);  // EOF
+  quic_data.AddSocketDataToFactory(&socket_factory_);
+
   Initialize();
 
   ProofVerifyDetailsChromium details;
@@ -1232,8 +1273,8 @@
 
 TEST_P(QuicChromiumClientSessionTest, MaxNumStreamsViaRequest) {
   MockQuicData quic_data(version_);
-  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
   if (version_.transport_version == quic::QUIC_VERSION_99) {
+    quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
     quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeStreamsBlockedPacket(
                                         2, true, 50,
                                         /*unidirectional=*/false));
@@ -1247,7 +1288,7 @@
   } else {
     quic_data.AddWrite(
         SYNCHRONOUS, client_maker_.MakeRstPacket(
-                         2, true, GetNthClientInitiatedBidirectionalStreamId(0),
+                         1, true, GetNthClientInitiatedBidirectionalStreamId(0),
                          quic::QUIC_RST_ACKNOWLEDGEMENT));
   }
   quic_data.AddRead(ASYNC, ERR_IO_PENDING);
@@ -1287,12 +1328,12 @@
 }
 
 TEST_P(QuicChromiumClientSessionTest, GoAwayReceived) {
-  MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
-  std::unique_ptr<quic::QuicEncryptedPacket> settings_packet(
-      client_maker_.MakeInitialSettingsPacket(1));
-  MockWrite writes[] = {
-      MockWrite(ASYNC, settings_packet->data(), settings_packet->length(), 1)};
-  socket_data_.reset(new SequencedSocketData(reads, writes));
+  MockQuicData quic_data(version_);
+  if (VersionUsesQpack(version_.transport_version))
+    quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
+  quic_data.AddRead(ASYNC, ERR_IO_PENDING);
+  quic_data.AddRead(ASYNC, OK);  // EOF
+  quic_data.AddSocketDataToFactory(&socket_factory_);
   Initialize();
   CompleteCryptoHandshake();
 
@@ -1306,12 +1347,12 @@
 }
 
 TEST_P(QuicChromiumClientSessionTest, CanPool) {
-  MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
-  std::unique_ptr<quic::QuicEncryptedPacket> settings_packet(
-      client_maker_.MakeInitialSettingsPacket(1));
-  MockWrite writes[] = {
-      MockWrite(ASYNC, settings_packet->data(), settings_packet->length(), 1)};
-  socket_data_.reset(new SequencedSocketData(reads, writes));
+  MockQuicData quic_data(version_);
+  if (VersionUsesQpack(version_.transport_version))
+    quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
+  quic_data.AddRead(ASYNC, ERR_IO_PENDING);
+  quic_data.AddRead(ASYNC, OK);  // EOF
+  quic_data.AddSocketDataToFactory(&socket_factory_);
   Initialize();
   // Load a cert that is valid for:
   //   www.example.org
@@ -1381,12 +1422,12 @@
       QuicSessionKey(kServerHostname, kServerPort, PRIVACY_MODE_DISABLED,
                      SocketTag(), kNetworkIsolationKey1);
 
-  MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
-  std::unique_ptr<quic::QuicEncryptedPacket> settings_packet(
-      client_maker_.MakeInitialSettingsPacket(1));
-  MockWrite writes[] = {
-      MockWrite(ASYNC, settings_packet->data(), settings_packet->length(), 1)};
-  socket_data_.reset(new SequencedSocketData(reads, writes));
+  MockQuicData quic_data(version_);
+  if (VersionUsesQpack(version_.transport_version))
+    quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
+  quic_data.AddRead(ASYNC, ERR_IO_PENDING);
+  quic_data.AddRead(ASYNC, OK);  // EOF
+  quic_data.AddSocketDataToFactory(&socket_factory_);
   Initialize();
   // Load a cert that is valid for:
   //   www.example.org
@@ -1439,12 +1480,12 @@
   // ProofVerifyDetailsChromium are faked.)
   const char kNoPinsHost[] = "no-pkp.example.org";
 
-  MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
-  std::unique_ptr<quic::QuicEncryptedPacket> settings_packet(
-      client_maker_.MakeInitialSettingsPacket(1));
-  MockWrite writes[] = {
-      MockWrite(ASYNC, settings_packet->data(), settings_packet->length(), 1)};
-  socket_data_.reset(new SequencedSocketData(reads, writes));
+  MockQuicData quic_data(version_);
+  if (VersionUsesQpack(version_.transport_version))
+    quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
+  quic_data.AddRead(ASYNC, ERR_IO_PENDING);
+  quic_data.AddRead(ASYNC, OK);  // EOF
+  quic_data.AddSocketDataToFactory(&socket_factory_);
   Initialize();
 
   transport_security_state_.EnableStaticPinsForTesting();
@@ -1470,12 +1511,12 @@
 TEST_P(QuicChromiumClientSessionTest, ConnectionPooledWithMatchingPin) {
   ScopedTransportSecurityStateSource scoped_security_state_source;
 
-  MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
-  std::unique_ptr<quic::QuicEncryptedPacket> settings_packet(
-      client_maker_.MakeInitialSettingsPacket(1));
-  MockWrite writes[] = {
-      MockWrite(ASYNC, settings_packet->data(), settings_packet->length(), 1)};
-  socket_data_.reset(new SequencedSocketData(reads, writes));
+  MockQuicData quic_data(version_);
+  if (VersionUsesQpack(version_.transport_version))
+    quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
+  quic_data.AddRead(ASYNC, ERR_IO_PENDING);
+  quic_data.AddRead(ASYNC, OK);  // EOF
+  quic_data.AddSocketDataToFactory(&socket_factory_);
   Initialize();
 
   transport_security_state_.EnableStaticPinsForTesting();
@@ -1500,21 +1541,30 @@
 }
 
 TEST_P(QuicChromiumClientSessionTest, MigrateToSocket) {
-  MockRead old_reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
-  std::unique_ptr<quic::QuicEncryptedPacket> settings_packet(
-      client_maker_.MakeInitialSettingsPacket(1));
-  MockWrite old_writes[] = {
-      MockWrite(ASYNC, settings_packet->data(), settings_packet->length(), 1)};
-  socket_data_.reset(new SequencedSocketData(old_reads, old_writes));
+  MockQuicData quic_data(version_);
+  int packet_num = 1;
+  socket_data_.reset();
+  if (VersionUsesQpack(version_.transport_version)) {
+    quic_data.AddWrite(SYNCHRONOUS,
+                       client_maker_.MakeInitialSettingsPacket(packet_num++));
+  }
+  quic_data.AddRead(ASYNC, ERR_IO_PENDING);
+  quic_data.AddRead(ASYNC, OK);  // EOF
+  quic_data.AddSocketDataToFactory(&socket_factory_);
   Initialize();
   CompleteCryptoHandshake();
 
   char data[] = "ABCD";
   std::unique_ptr<quic::QuicEncryptedPacket> client_ping;
   std::unique_ptr<quic::QuicEncryptedPacket> ack_and_data_out;
-  client_ping = client_maker_.MakeAckAndPingPacket(2, false, 1, 1, 1);
+  if (VersionUsesQpack(version_.transport_version)) {
+    client_ping =
+        client_maker_.MakeAckAndPingPacket(packet_num++, false, 1, 1, 1);
+  } else {
+    client_ping = client_maker_.MakePingPacket(packet_num++, true);
+  }
   ack_and_data_out = client_maker_.MakeDataPacket(
-      3, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
+      packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true, false,
       quic::QuicStringPiece(data));
   std::unique_ptr<quic::QuicEncryptedPacket> server_ping(
       server_maker_.MakePingPacket(1, /*include_version=*/false));
@@ -1565,19 +1615,23 @@
 }
 
 TEST_P(QuicChromiumClientSessionTest, MigrateToSocketMaxReaders) {
-  MockRead old_reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
-  std::unique_ptr<quic::QuicEncryptedPacket> settings_packet(
-      client_maker_.MakeInitialSettingsPacket(1));
-  MockWrite old_writes[] = {
-      MockWrite(ASYNC, settings_packet->data(), settings_packet->length(), 1)};
-  socket_data_.reset(new SequencedSocketData(old_reads, old_writes));
+  MockQuicData quic_data(version_);
+  socket_data_.reset();
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    quic_data.AddWrite(SYNCHRONOUS,
+                       client_maker_.MakeInitialSettingsPacket(packet_num++));
+  }
+  quic_data.AddRead(ASYNC, ERR_IO_PENDING);
+  quic_data.AddRead(ASYNC, OK);  // EOF
+  quic_data.AddSocketDataToFactory(&socket_factory_);
   Initialize();
   CompleteCryptoHandshake();
 
   for (size_t i = 0; i < kMaxReadersPerQuicSession; ++i) {
     MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 1)};
     std::unique_ptr<quic::QuicEncryptedPacket> ping_out(
-        client_maker_.MakePingPacket(i + 2, /*include_version=*/true));
+        client_maker_.MakePingPacket(i + packet_num, /*include_version=*/true));
     MockWrite writes[] = {
         MockWrite(SYNCHRONOUS, ping_out->data(), ping_out->length(), i + 2)};
     StaticSocketDataProvider socket_data(reads, writes);
@@ -1618,21 +1672,38 @@
   }
 }
 
-TEST_P(QuicChromiumClientSessionTest, MigrateToSocketReadError) {
-  std::unique_ptr<quic::QuicEncryptedPacket> settings_packet(
-      client_maker_.MakeInitialSettingsPacket(1));
-  std::unique_ptr<quic::QuicEncryptedPacket> client_ping;
-  client_ping = client_maker_.MakeAckAndPingPacket(2, false, 1, 1, 1);
+// TODO(renjietang): Find out why this test fails on trybot but passes locally,
+// with FLAGS_quic_reloadable_flag_quic_do_not_send_settings flipped.
+TEST_P(QuicChromiumClientSessionTest, DISABLED_MigrateToSocketReadError) {
+  std::unique_ptr<quic::QuicEncryptedPacket> settings_packet;
+  std::unique_ptr<quic::QuicEncryptedPacket> client_ping =
+      client_maker_.MakeAckAndPingPacket(2, false, 1, 1, 1);
+  std::unique_ptr<quic::QuicEncryptedPacket> initial_ping;
+  if (VersionUsesQpack(version_.transport_version)) {
+    settings_packet = client_maker_.MakeInitialSettingsPacket(1);
+    MockWrite old_writes[] = {MockWrite(ASYNC, settings_packet->data(),
+                                        settings_packet->length(), 0)};
+    MockRead old_reads[] = {
+        MockRead(ASYNC, ERR_IO_PENDING, 1),  // causes reading to pause.
+        MockRead(ASYNC, ERR_NETWORK_CHANGED, 2)};
+    socket_data_.reset(new SequencedSocketData(old_reads, old_writes));
+  } else {
+    initial_ping = client_maker_.MakePingPacket(1, true);
+    MockWrite old_writes[] = {
+        MockWrite(ASYNC, initial_ping->data(), initial_ping->length(), 0)};
+    MockRead old_reads[] = {
+        MockRead(ASYNC, ERR_IO_PENDING, 1),  // causes reading to pause.
+        MockRead(ASYNC, ERR_NETWORK_CHANGED, 2)};
+    socket_data_.reset(new SequencedSocketData(old_reads, old_writes));
+  }
+
   std::unique_ptr<quic::QuicEncryptedPacket> server_ping(
       server_maker_.MakePingPacket(1, /*include_version=*/false));
-  MockWrite old_writes[] = {
-      MockWrite(ASYNC, settings_packet->data(), settings_packet->length(), 0)};
-  MockRead old_reads[] = {
-      MockRead(ASYNC, ERR_IO_PENDING, 1),  // causes reading to pause.
-      MockRead(ASYNC, ERR_NETWORK_CHANGED, 2)};
-  socket_data_.reset(new SequencedSocketData(old_reads, old_writes));
   Initialize();
   CompleteCryptoHandshake();
+
+  if (!VersionUsesQpack(version_.transport_version))
+    session_->SendPing();
   MockWrite writes[] = {
       MockWrite(SYNCHRONOUS, client_ping->data(), client_ping->length(), 1)};
   MockRead new_reads[] = {
@@ -1754,11 +1825,19 @@
   migrate_session_early_v2_ = true;
 
   MockQuicData quic_data(version_);
-  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
-  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakePingPacket(2, true));
-  quic_data.AddRead(ASYNC, server_maker_.MakeAckPacket(1, 2, 1, 1, false));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    quic_data.AddWrite(SYNCHRONOUS,
+                       client_maker_.MakeInitialSettingsPacket(packet_num++));
+  }
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakePingPacket(packet_num++, true));
 
-  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakePingPacket(3, false));
+  quic_data.AddRead(
+      ASYNC, server_maker_.MakeAckPacket(1, packet_num - 1, 1, 1, false));
+
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakePingPacket(packet_num++, false));
   quic_data.AddRead(ASYNC, ERR_IO_PENDING);
   quic_data.AddRead(ASYNC, OK);  // EOF
   quic_data.AddSocketDataToFactory(&socket_factory_);
diff --git a/net/quic/quic_flags_list.h b/net/quic/quic_flags_list.h
index 8792f53..ea95ac1 100644
--- a/net/quic/quic_flags_list.h
+++ b/net/quic/quic_flags_list.h
@@ -182,7 +182,7 @@
 QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_version_47, false)
 
 // If true, enable QUIC version 48.
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_version_48_2, false)
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_version_48_2, true)
 
 // If true, disable QUIC version 39.
 QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_disable_version_39, false)
@@ -405,7 +405,7 @@
           false)
 
 // If true, no SPDY SETTINGS will be sent after handshake is confirmed.
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_do_not_send_settings, false)
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_do_not_send_settings, true)
 
 // The maximum amount of CRYPTO frame data that can be buffered.
 QUIC_FLAG(int32_t, FLAGS_quic_max_buffered_crypto_bytes, 16 * 1024)
diff --git a/net/quic/quic_http_stream_test.cc b/net/quic/quic_http_stream_test.cc
index 53ba0e6..46e3e7e 100644
--- a/net/quic/quic_http_stream_test.cc
+++ b/net/quic/quic_http_stream_test.cc
@@ -282,8 +282,10 @@
     send_algorithm_ = new quic::test::MockSendAlgorithm();
     EXPECT_CALL(*send_algorithm_, InRecovery()).WillRepeatedly(Return(false));
     EXPECT_CALL(*send_algorithm_, InSlowStart()).WillRepeatedly(Return(false));
-    EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
-        .Times(testing::AtLeast(1));
+    if (VersionUsesQpack(version_.transport_version)) {
+      EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
+          .Times(testing::AtLeast(1));
+    }
     EXPECT_CALL(*send_algorithm_, OnCongestionEvent(_, _, _, _, _))
         .Times(AnyNumber());
     EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
@@ -617,6 +619,11 @@
     return client_maker_.MakeInitialSettingsPacket(1);
   }
 
+  std::unique_ptr<quic::QuicReceivedPacket> ConstructInitialSettingsPacket(
+      int packet_number) {
+    return client_maker_.MakeInitialSettingsPacket(packet_number);
+  }
+
   std::string ConstructDataHeader(size_t body_len) {
     if (version_.transport_version != quic::QUIC_VERSION_99) {
       return "";
@@ -739,10 +746,13 @@
 TEST_P(QuicHttpStreamTest, GetRequest) {
   SetRequest("GET", "/", DEFAULT_PRIORITY);
   size_t spdy_request_header_frame_length;
-  AddWrite(ConstructInitialSettingsPacket());
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version))
+    AddWrite(ConstructInitialSettingsPacket(packet_number++));
   AddWrite(InnerConstructRequestHeadersPacket(
-      2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
-      DEFAULT_PRIORITY, &spdy_request_header_frame_length));
+      packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
+      kIncludeVersion, kFin, DEFAULT_PRIORITY,
+      &spdy_request_header_frame_length));
 
   Initialize();
 
@@ -800,18 +810,23 @@
   SetRequest("GET", "/", DEFAULT_PRIORITY);
   size_t spdy_request_header_frame_length;
 
-  AddWrite(ConstructInitialSettingsPacket());
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version))
+    AddWrite(ConstructInitialSettingsPacket(packet_number++));
   AddWrite(InnerConstructRequestHeadersPacket(
-      2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
-      DEFAULT_PRIORITY, &spdy_request_header_frame_length));
+      packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
+      kIncludeVersion, kFin, DEFAULT_PRIORITY,
+      &spdy_request_header_frame_length));
 
   // SetRequest() again for second request as |request_headers_| was moved.
   SetRequest("GET", "/", DEFAULT_PRIORITY);
   AddWrite(InnerConstructRequestHeadersPacket(
-      3, GetNthClientInitiatedBidirectionalStreamId(1), kIncludeVersion, kFin,
-      DEFAULT_PRIORITY, GetNthClientInitiatedBidirectionalStreamId(0),
+      packet_number++, GetNthClientInitiatedBidirectionalStreamId(1),
+      kIncludeVersion, kFin, DEFAULT_PRIORITY,
+      GetNthClientInitiatedBidirectionalStreamId(0),
       &spdy_request_header_frame_length));
-  AddWrite(ConstructClientAckPacket(4, 3, 1, 2));  // Ack the responses.
+  AddWrite(ConstructClientAckPacket(packet_number++, 3, 1,
+                                    2));  // Ack the responses.
 
   Initialize();
 
@@ -886,11 +901,15 @@
 TEST_P(QuicHttpStreamTest, GetRequestWithTrailers) {
   SetRequest("GET", "/", DEFAULT_PRIORITY);
   size_t spdy_request_header_frame_length;
-  AddWrite(ConstructInitialSettingsPacket());
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version))
+    AddWrite(ConstructInitialSettingsPacket(packet_number++));
   AddWrite(InnerConstructRequestHeadersPacket(
-      2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
-      DEFAULT_PRIORITY, &spdy_request_header_frame_length));
-  AddWrite(ConstructClientAckPacket(3, 3, 1, 2));  // Ack the data packet.
+      packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
+      kIncludeVersion, kFin, DEFAULT_PRIORITY,
+      &spdy_request_header_frame_length));
+  AddWrite(ConstructClientAckPacket(packet_number++, 3, 1,
+                                    2));  // Ack the data packet.
 
   Initialize();
 
@@ -981,10 +1000,13 @@
 TEST_P(QuicHttpStreamTest, GetRequestLargeResponse) {
   SetRequest("GET", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  AddWrite(ConstructInitialSettingsPacket());
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version))
+    AddWrite(ConstructInitialSettingsPacket(packet_number++));
   AddWrite(InnerConstructRequestHeadersPacket(
-      2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
-      DEFAULT_PRIORITY, &spdy_request_headers_frame_length));
+      packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
+      kIncludeVersion, kFin, DEFAULT_PRIORITY,
+      &spdy_request_headers_frame_length));
   Initialize();
 
   request_.method = "GET";
@@ -1107,10 +1129,13 @@
 TEST_P(QuicHttpStreamTest, LogGranularQuicConnectionError) {
   SetRequest("GET", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  AddWrite(ConstructInitialSettingsPacket());
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version))
+    AddWrite(ConstructInitialSettingsPacket(packet_number++));
   AddWrite(InnerConstructRequestHeadersPacket(
-      2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
-      DEFAULT_PRIORITY, &spdy_request_headers_frame_length));
+      packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
+      kIncludeVersion, kFin, DEFAULT_PRIORITY,
+      &spdy_request_headers_frame_length));
   AddWrite(ConstructAckAndRstStreamPacket(3));
   Initialize();
 
@@ -1189,10 +1214,13 @@
 TEST_P(QuicHttpStreamTest, SessionClosedBeforeReadResponseHeaders) {
   SetRequest("GET", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  AddWrite(ConstructInitialSettingsPacket());
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version))
+    AddWrite(ConstructInitialSettingsPacket(packet_number++));
   AddWrite(InnerConstructRequestHeadersPacket(
-      2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
-      DEFAULT_PRIORITY, &spdy_request_headers_frame_length));
+      packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
+      kIncludeVersion, kFin, DEFAULT_PRIORITY,
+      &spdy_request_headers_frame_length));
   Initialize();
 
   request_.method = "GET";
@@ -1220,22 +1248,24 @@
 TEST_P(QuicHttpStreamTest, SendPostRequest) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  AddWrite(ConstructInitialSettingsPacket());
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version))
+    AddWrite(ConstructInitialSettingsPacket(packet_number++));
 
   std::string header = ConstructDataHeader(strlen(kUploadData));
   if (version_.transport_version != quic::QUIC_VERSION_99) {
     AddWrite(ConstructRequestHeadersAndDataFramesPacket(
-        2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
-        DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
-        {kUploadData}));
+        packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
+        kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
+        &spdy_request_headers_frame_length, {kUploadData}));
   } else {
     AddWrite(ConstructRequestHeadersAndDataFramesPacket(
-        2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
-        DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
-        {header, kUploadData}));
+        packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
+        kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
+        &spdy_request_headers_frame_length, {header, kUploadData}));
   }
 
-  AddWrite(ConstructClientAckPacket(3, 3, 1, 2));
+  AddWrite(ConstructClientAckPacket(packet_number++, 3, 1, 2));
 
   Initialize();
 
@@ -1301,21 +1331,23 @@
 TEST_P(QuicHttpStreamTest, SendPostRequestAndReceiveSoloFin) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  AddWrite(ConstructInitialSettingsPacket());
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version))
+    AddWrite(ConstructInitialSettingsPacket(packet_number++));
   std::string header = ConstructDataHeader(strlen(kUploadData));
   if (version_.transport_version != quic::QUIC_VERSION_99) {
     AddWrite(ConstructRequestHeadersAndDataFramesPacket(
-        2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
-        DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
-        {kUploadData}));
+        packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
+        kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
+        &spdy_request_headers_frame_length, {kUploadData}));
   } else {
     AddWrite(ConstructRequestHeadersAndDataFramesPacket(
-        2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
-        DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
-        {header, kUploadData}));
+        packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
+        kIncludeVersion, kFin, DEFAULT_PRIORITY, 0,
+        &spdy_request_headers_frame_length, {header, kUploadData}));
   }
 
-  AddWrite(ConstructClientAckPacket(3, 3, 1, 2));
+  AddWrite(ConstructClientAckPacket(packet_number++, 3, 1, 2));
 
   Initialize();
 
@@ -1383,24 +1415,27 @@
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   size_t chunk_size = strlen(kUploadData);
   size_t spdy_request_headers_frame_length;
-  AddWrite(ConstructInitialSettingsPacket());
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version))
+    AddWrite(ConstructInitialSettingsPacket(packet_number++));
   std::string header = ConstructDataHeader(chunk_size);
   if (version_.transport_version == quic::QUIC_VERSION_99) {
     AddWrite(ConstructRequestHeadersAndDataFramesPacket(
-        2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
-        !kFin, DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
-        {header, kUploadData}));
-    AddWrite(ConstructClientMultipleDataFramesPacket(3, kIncludeVersion, kFin,
-                                                     {header, kUploadData}));
+        packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
+        kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
+        &spdy_request_headers_frame_length, {header, kUploadData}));
+    AddWrite(ConstructClientMultipleDataFramesPacket(
+        packet_number++, kIncludeVersion, kFin, {header, kUploadData}));
   } else {
     AddWrite(ConstructRequestHeadersAndDataFramesPacket(
-        2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
-        !kFin, DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
-        {kUploadData}));
-    AddWrite(ConstructClientDataPacket(3, kIncludeVersion, kFin, kUploadData));
+        packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
+        kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
+        &spdy_request_headers_frame_length, {kUploadData}));
+    AddWrite(ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin,
+                                       kUploadData));
   }
 
-  AddWrite(ConstructClientAckPacket(4, 3, 1, 2));
+  AddWrite(ConstructClientAckPacket(packet_number++, 3, 1, 2));
   Initialize();
 
   upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
@@ -1466,22 +1501,25 @@
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   size_t chunk_size = strlen(kUploadData);
   size_t spdy_request_headers_frame_length;
-  AddWrite(ConstructInitialSettingsPacket());
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version))
+    AddWrite(ConstructInitialSettingsPacket(packet_number++));
   std::string header = ConstructDataHeader(chunk_size);
 
   if (version_.transport_version != quic::QUIC_VERSION_99) {
     AddWrite(ConstructRequestHeadersAndDataFramesPacket(
-        2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
-        !kFin, DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
-        {kUploadData}));
+        packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
+        kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
+        &spdy_request_headers_frame_length, {kUploadData}));
   } else {
     AddWrite(ConstructRequestHeadersAndDataFramesPacket(
-        2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
-        !kFin, DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
-        {header, kUploadData}));
+        packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
+        kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
+        &spdy_request_headers_frame_length, {header, kUploadData}));
   }
-  AddWrite(ConstructClientDataPacket(3, kIncludeVersion, kFin, ""));
-  AddWrite(ConstructClientAckPacket(4, 3, 1, 2));
+  AddWrite(
+      ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin, ""));
+  AddWrite(ConstructClientAckPacket(packet_number++, 3, 1, 2));
   Initialize();
 
   upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
@@ -1544,12 +1582,16 @@
 TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithOneEmptyDataPacket) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  AddWrite(ConstructInitialSettingsPacket());
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version))
+    AddWrite(ConstructInitialSettingsPacket(packet_number++));
   AddWrite(InnerConstructRequestHeadersPacket(
-      2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, !kFin,
-      DEFAULT_PRIORITY, &spdy_request_headers_frame_length));
-  AddWrite(ConstructClientDataPacket(3, kIncludeVersion, kFin, ""));
-  AddWrite(ConstructClientAckPacket(4, 3, 1, 2));
+      packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
+      kIncludeVersion, !kFin, DEFAULT_PRIORITY,
+      &spdy_request_headers_frame_length));
+  AddWrite(
+      ConstructClientDataPacket(packet_number++, kIncludeVersion, kFin, ""));
+  AddWrite(ConstructClientAckPacket(packet_number++, 3, 1, 2));
   Initialize();
 
   upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
@@ -1611,11 +1653,14 @@
 TEST_P(QuicHttpStreamTest, DestroyedEarly) {
   SetRequest("GET", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  AddWrite(ConstructInitialSettingsPacket());
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version))
+    AddWrite(ConstructInitialSettingsPacket(packet_number++));
   AddWrite(InnerConstructRequestHeadersPacket(
-      2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
-      DEFAULT_PRIORITY, &spdy_request_headers_frame_length));
-  AddWrite(ConstructAckAndRstStreamPacket(3));
+      packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
+      kIncludeVersion, kFin, DEFAULT_PRIORITY,
+      &spdy_request_headers_frame_length));
+  AddWrite(ConstructAckAndRstStreamPacket(packet_number++));
   Initialize();
 
   request_.method = "GET";
@@ -1656,10 +1701,12 @@
 TEST_P(QuicHttpStreamTest, Priority) {
   SetRequest("GET", "/", MEDIUM);
   size_t spdy_request_headers_frame_length;
-  AddWrite(ConstructInitialSettingsPacket());
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version))
+    AddWrite(ConstructInitialSettingsPacket(packet_number++));
   AddWrite(InnerConstructRequestHeadersPacket(
-      2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
-      MEDIUM, &spdy_request_headers_frame_length));
+      packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
+      kIncludeVersion, kFin, MEDIUM, &spdy_request_headers_frame_length));
   Initialize();
 
   request_.method = "GET";
@@ -1697,18 +1744,20 @@
 TEST_P(QuicHttpStreamTest, SessionClosedDuringDoLoop) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  AddWrite(ConstructInitialSettingsPacket());
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version))
+    AddWrite(ConstructInitialSettingsPacket(packet_number++));
   std::string header = ConstructDataHeader(strlen(kUploadData));
   if (version_.transport_version != quic::QUIC_VERSION_99) {
     AddWrite(ConstructRequestHeadersAndDataFramesPacket(
-        2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
-        !kFin, DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
-        {kUploadData}));
+        packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
+        kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
+        &spdy_request_headers_frame_length, {kUploadData}));
   } else {
     AddWrite(ConstructRequestHeadersAndDataFramesPacket(
-        2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
-        !kFin, DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
-        {header, kUploadData}));
+        packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
+        kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
+        &spdy_request_headers_frame_length, {header, kUploadData}));
   }
 
   // Second data write will result in a synchronous failure which will close
@@ -1748,7 +1797,8 @@
 
 TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersComplete) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
-  AddWrite(ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    AddWrite(ConstructInitialSettingsPacket());
   AddWrite(SYNCHRONOUS, ERR_FAILED);
   Initialize();
 
@@ -1779,7 +1829,8 @@
 
 TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersCompleteReadResponse) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
-  AddWrite(ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    AddWrite(ConstructInitialSettingsPacket());
   AddWrite(SYNCHRONOUS, ERR_FAILED);
   Initialize();
 
@@ -1814,10 +1865,13 @@
 TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBodyComplete) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  AddWrite(ConstructInitialSettingsPacket());
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version))
+    AddWrite(ConstructInitialSettingsPacket(packet_number++));
   AddWrite(InnerConstructRequestHeadersPacket(
-      2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, !kFin,
-      DEFAULT_PRIORITY, &spdy_request_headers_frame_length));
+      packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
+      kIncludeVersion, !kFin, DEFAULT_PRIORITY,
+      &spdy_request_headers_frame_length));
   AddWrite(SYNCHRONOUS, ERR_FAILED);
   Initialize();
 
@@ -1853,18 +1907,20 @@
 TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBundledBodyComplete) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  AddWrite(ConstructInitialSettingsPacket());
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version))
+    AddWrite(ConstructInitialSettingsPacket(packet_number++));
   std::string header = ConstructDataHeader(strlen(kUploadData));
   if (version_.transport_version != quic::QUIC_VERSION_99) {
     AddWrite(ConstructRequestHeadersAndDataFramesPacket(
-        2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
-        !kFin, DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
-        {kUploadData}));
+        packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
+        kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
+        &spdy_request_headers_frame_length, {kUploadData}));
   } else {
     AddWrite(ConstructRequestHeadersAndDataFramesPacket(
-        2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
-        !kFin, DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
-        {header, kUploadData}));
+        packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
+        kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
+        &spdy_request_headers_frame_length, {header, kUploadData}));
   }
 
   AddWrite(SYNCHRONOUS, ERR_FAILED);
@@ -1914,6 +1970,8 @@
   EXPECT_EQ(OK,
             stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
                                       net_log_.bound(), callback_.callback()));
+  ASSERT_EQ(OK,
+            stream_->SendRequest(headers_, &response_, callback_.callback()));
 
   // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
   // packet, but does it matter?
@@ -1962,8 +2020,6 @@
   EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
   EXPECT_TRUE(AtEof());
 
-  EXPECT_EQ(0, stream_->GetTotalSentBytes());
-  EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
   EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
   EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
                                  strlen(kResponseBody) + header.length()),
@@ -1981,6 +2037,8 @@
   EXPECT_EQ(OK,
             stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
                                       net_log_.bound(), callback_.callback()));
+  ASSERT_EQ(OK,
+            stream_->SendRequest(headers_, &response_, callback_.callback()));
 
   // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
   // packet, but does it matter?
@@ -2036,8 +2094,6 @@
   EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
   EXPECT_TRUE(AtEof());
 
-  EXPECT_EQ(0, stream_->GetTotalSentBytes());
-  EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
   EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
   EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
                                  strlen(kResponseBody) + header.length()),
@@ -2056,6 +2112,8 @@
   EXPECT_EQ(OK,
             stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
                                       net_log_.bound(), callback_.callback()));
+  ASSERT_EQ(OK,
+            stream_->SendRequest(headers_, &response_, callback_.callback()));
 
   // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
   // packet, but does it matter?
@@ -2098,6 +2156,8 @@
   EXPECT_EQ(OK,
             stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
                                       net_log_.bound(), callback_.callback()));
+  ASSERT_EQ(OK,
+            stream_->SendRequest(headers_, &response_, callback_.callback()));
 
   // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
   // packet, but does it matter?
@@ -2151,8 +2211,6 @@
   EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
   EXPECT_TRUE(AtEof());
 
-  EXPECT_EQ(0, stream_->GetTotalSentBytes());
-  EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
   EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
   EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
                                  strlen(kResponseBody) + header.length()),
@@ -2170,6 +2228,8 @@
   EXPECT_EQ(OK,
             stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
                                       net_log_.bound(), callback_.callback()));
+  ASSERT_EQ(OK,
+            stream_->SendRequest(headers_, &response_, callback_.callback()));
 
   // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
   // packet, but does it matter?
@@ -2194,6 +2254,8 @@
   EXPECT_EQ(OK,
             stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
                                       net_log_.bound(), callback_.callback()));
+  ASSERT_EQ(OK,
+            stream_->SendRequest(headers_, &response_, callback_.callback()));
 
   push_promise_["accept-encoding"] = "gzip";
 
@@ -2254,8 +2316,6 @@
   EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
   EXPECT_TRUE(AtEof());
 
-  EXPECT_EQ(0, stream_->GetTotalSentBytes());
-  EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
   EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
   EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
                                  strlen(kResponseBody) + header.length()),
@@ -2268,25 +2328,6 @@
   request_headers_[":path"] = "/bar";
   request_headers_["accept-encoding"] = "sdch";
 
-  size_t spdy_request_header_frame_length;
-  AddWrite(ConstructInitialSettingsPacket());
-
-  uint64_t client_packet_number = 2;
-  if ((client_headers_include_h2_stream_dependency_ &&
-       version_.transport_version >= quic::QUIC_VERSION_43) ||
-      VersionHasStreamType(version_.transport_version)) {
-    AddWrite(ConstructClientPriorityPacket(client_packet_number++,
-                                           kIncludeVersion, promise_id_, 0,
-                                           DEFAULT_PRIORITY));
-  }
-  AddWrite(ConstructClientRstStreamVaryMismatchAndRequestHeadersPacket(
-      client_packet_number++,
-      stream_id_ + quic::QuicUtils::StreamIdDelta(version_.transport_version),
-      !kIncludeVersion, kFin, DEFAULT_PRIORITY, promise_id_,
-      &spdy_request_header_frame_length));
-  AddWrite(ConstructClientAckPacket(client_packet_number++, 3, 1, 2));
-  AddWrite(ConstructClientRstStreamCancelledPacket(client_packet_number++));
-
   Initialize();
 
   // Initialize the first stream, for receiving the promise on.
@@ -2296,6 +2337,8 @@
   EXPECT_EQ(OK,
             stream_->InitializeStream(&request_, true, DEFAULT_PRIORITY,
                                       net_log_.bound(), callback_.callback()));
+  ASSERT_EQ(OK,
+            stream_->SendRequest(headers_, &response_, callback_.callback()));
 
   push_promise_["accept-encoding"] = "gzip";
 
@@ -2380,23 +2423,18 @@
   stream_->Close(true);
 
   EXPECT_TRUE(AtEof());
-
-  // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
-  // headers and payload.
-  EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
-            promised_stream_->GetTotalSentBytes());
-  EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length),
-            promised_stream_->GetTotalReceivedBytes());
 }
 
 TEST_P(QuicHttpStreamTest, DataReadErrorSynchronous) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  AddWrite(ConstructInitialSettingsPacket());
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version))
+    AddWrite(ConstructInitialSettingsPacket(packet_number++));
   AddWrite(ConstructRequestAndRstPacket(
-      2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, !kFin,
-      DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
-      quic::QUIC_ERROR_PROCESSING_STREAM));
+      packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
+      kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
+      &spdy_request_headers_frame_length, quic::QUIC_ERROR_PROCESSING_STREAM));
 
   Initialize();
 
@@ -2426,11 +2464,15 @@
 TEST_P(QuicHttpStreamTest, DataReadErrorAsynchronous) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  AddWrite(ConstructInitialSettingsPacket());
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version))
+    AddWrite(ConstructInitialSettingsPacket(packet_number++));
   AddWrite(InnerConstructRequestHeadersPacket(
-      2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, !kFin,
-      DEFAULT_PRIORITY, &spdy_request_headers_frame_length));
-  AddWrite(ConstructClientRstStreamErrorPacket(3, !kIncludeVersion));
+      packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
+      kIncludeVersion, !kFin, DEFAULT_PRIORITY,
+      &spdy_request_headers_frame_length));
+  AddWrite(
+      ConstructClientRstStreamErrorPacket(packet_number++, !kIncludeVersion));
 
   Initialize();
 
diff --git a/net/quic/quic_network_transaction_unittest.cc b/net/quic/quic_network_transaction_unittest.cc
index da85df7..74ef8a52 100644
--- a/net/quic/quic_network_transaction_unittest.cc
+++ b/net/quic/quic_network_transaction_unittest.cc
@@ -999,7 +999,8 @@
       MockCryptoClientStream::CONFIRM_HANDSHAKE);
 
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  if (VersionUsesQpack(version_.transport_version))
+    mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   mock_quic_data.AddWrite(SYNCHRONOUS, ERR_INTERNET_DISCONNECTED);
   mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
   mock_quic_data.AddRead(ASYNC, OK);              // No more data to read
@@ -1029,7 +1030,8 @@
       MockCryptoClientStream::CONFIRM_HANDSHAKE);
 
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  if (VersionUsesQpack(version_.transport_version))
+    mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   mock_quic_data.AddWrite(ASYNC, ERR_INTERNET_DISCONNECTED);
   mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
   mock_quic_data.AddRead(ASYNC, OK);              // No more data to read
@@ -1055,11 +1057,16 @@
       HostPortPair::FromString("mail.example.org:443"));
 
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "https", "/")));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -1069,7 +1076,8 @@
       ASYNC, ConstructServerDataPacket(
                  2, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
                  header + "hello!"));
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(3, 2, 1, 1));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 2, 1, 1));
   mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // No more data to read
 
   mock_quic_data.AddSocketDataToFactory(&socket_factory_);
@@ -1089,11 +1097,16 @@
       HostPortPair::FromString("mail.example.org:443"));
 
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "https", "/")));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -1103,7 +1116,8 @@
       ASYNC, ConstructServerDataPacket(
                  2, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
                  header + "hello!"));
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(3, 2, 1, 1));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 2, 1, 1));
   mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // No more data to read
 
   mock_quic_data.AddSocketDataToFactory(&socket_factory_);
@@ -1123,11 +1137,16 @@
       HostPortPair::FromString("mail.example.org:443"));
 
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "https", "/")));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -1137,7 +1156,8 @@
       ASYNC, ConstructServerDataPacket(
                  2, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
                  header + "hello!"));
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(3, 2, 1, 1));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 2, 1, 1));
   mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // No more data to read
 
   mock_quic_data.AddSocketDataToFactory(&socket_factory_);
@@ -1196,11 +1216,16 @@
       HostPortPair::FromString("mail.example.org:443"));
 
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "https", "/")));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          true, GetRequestHeaders("GET", "https", "/")));
   spdy::SpdyHeaderBlock response_headers = GetResponseHeaders("200 OK");
   response_headers["key1"] = std::string(30000, 'A');
   response_headers["key2"] = std::string(30000, 'A');
@@ -1247,9 +1272,10 @@
                  packet_number, GetNthClientInitiatedBidirectionalStreamId(0),
                  false, true, header + "hello!"));
   mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // No more data to read
-  mock_quic_data.AddWrite(ASYNC, ConstructClientAckPacket(3, 2, 1, 1));
   mock_quic_data.AddWrite(ASYNC,
-                          ConstructClientAckPacket(4, packet_number, 3, 1));
+                          ConstructClientAckPacket(packet_num++, 2, 1, 1));
+  mock_quic_data.AddWrite(
+      ASYNC, ConstructClientAckPacket(packet_num++, packet_number, 3, 1));
 
   mock_quic_data.AddSocketDataToFactory(&socket_factory_);
 
@@ -1266,11 +1292,16 @@
       HostPortPair::FromString("mail.example.org:443"));
 
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "https", "/")));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          true, GetRequestHeaders("GET", "https", "/")));
 
   spdy::SpdyHeaderBlock response_headers = GetResponseHeaders("200 OK");
   response_headers["key1"] = std::string(30000, 'A');
@@ -1321,10 +1352,11 @@
                  packet_number, GetNthClientInitiatedBidirectionalStreamId(0),
                  false, true, header + "hello!"));
   mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // No more data to read
-  mock_quic_data.AddWrite(ASYNC, ConstructClientAckPacket(3, 2, 1, 1));
+  mock_quic_data.AddWrite(ASYNC,
+                          ConstructClientAckPacket(packet_num++, 2, 1, 1));
   mock_quic_data.AddWrite(
       ASYNC, ConstructClientAckAndRstPacket(
-                 4, GetNthClientInitiatedBidirectionalStreamId(0),
+                 packet_num++, GetNthClientInitiatedBidirectionalStreamId(0),
                  quic::QUIC_HEADERS_TOO_LARGE, packet_number, 3, 1));
 
   mock_quic_data.AddSocketDataToFactory(&socket_factory_);
@@ -1344,11 +1376,16 @@
   AddQuicAlternateProtocolMapping(MockCryptoClientStream::CONFIRM_HANDSHAKE);
 
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "https", "/")));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -1358,7 +1395,8 @@
       ASYNC, ConstructServerDataPacket(
                  2, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
                  header + "hello!"));
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(3, 2, 1, 1));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 2, 1, 1));
   mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // No more data to read
 
   mock_quic_data.AddSocketDataToFactory(&socket_factory_);
@@ -1376,11 +1414,16 @@
       "QUIC mail.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "http", "/")));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          true, GetRequestHeaders("GET", "http", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -1390,7 +1433,8 @@
       ASYNC, ConstructServerDataPacket(
                  2, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
                  header + "hello!"));
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(3, 2, 1, 1));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 2, 1, 1));
   mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING);  // No more data to read
   mock_quic_data.AddRead(ASYNC, 0);               // EOF
 
@@ -1422,11 +1466,16 @@
 
   client_maker_.set_hostname(origin_host);
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "http", "/")));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          true, GetRequestHeaders("GET", "http", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -1436,7 +1485,8 @@
       ASYNC, ConstructServerDataPacket(
                  2, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
                  header + "hello!"));
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(3, 2, 1, 1));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 2, 1, 1));
   mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING);  // No more data to read
   mock_quic_data.AddRead(ASYNC, 0);
   mock_quic_data.AddSocketDataToFactory(&socket_factory_);
@@ -1481,11 +1531,16 @@
   client_maker_.set_hostname(origin.host());
   MockQuicData mock_quic_data(version_);
 
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "https", "/")));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -1495,7 +1550,8 @@
       ASYNC, ConstructServerDataPacket(
                  2, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
                  header + "hello!"));
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(3, 2, 1, 1));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 2, 1, 1));
   mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING);  // No more data to read
   mock_quic_data.AddRead(ASYNC, 0);
   mock_quic_data.AddSocketDataToFactory(&socket_factory_);
@@ -1573,11 +1629,16 @@
   // Second request should be sent via QUIC as a new list of verions supported
   // by the client has been advertised by the server.
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "https", "/")));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -1587,7 +1648,8 @@
       ASYNC, ConstructServerDataPacket(
                  2, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
                  header + "hello!"));
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(3, 2, 1, 1));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 2, 1, 1));
   mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING);  // No more data to read
   mock_quic_data.AddRead(ASYNC, 0);               // EOF
 
@@ -1644,11 +1706,16 @@
   // deterministic. The first main job gets aborted without the socket pool ever
   // dispensing the socket, making it available for the second try.
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "https", "/")));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
@@ -1701,11 +1768,13 @@
       HostPortPair::FromString("mail.example.org:443"));
 
   MockQuicData mock_quic_data1(version_);
-  mock_quic_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  if (VersionUsesQpack(version_.transport_version))
+    mock_quic_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   mock_quic_data1.AddRead(ASYNC, ERR_SOCKET_NOT_CONNECTED);
   client_maker_.Reset();
   MockQuicData mock_quic_data2(version_);
-  mock_quic_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  if (VersionUsesQpack(version_.transport_version))
+    mock_quic_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details_);
   mock_quic_data2.AddRead(ASYNC, ERR_SOCKET_NOT_CONNECTED);
   crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details_);
@@ -1764,11 +1833,16 @@
   socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
 
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "https", "/")));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -1778,7 +1852,56 @@
       ASYNC, ConstructServerDataPacket(
                  2, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
                  header + "hello!"));
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(3, 2, 1, 1));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 2, 1, 1));
+  mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING);  // No more data to read
+  mock_quic_data.AddRead(ASYNC, 0);               // EOF
+
+  mock_quic_data.AddSocketDataToFactory(&socket_factory_);
+
+  AddHangingNonAlternateProtocolSocketData();
+  CreateSession();
+
+  SendRequestAndExpectHttpResponse("hello world");
+  SendRequestAndExpectQuicResponse("hello!");
+}
+
+TEST_P(QuicNetworkTransactionTest, UseIetfAlternativeServiceForQuic) {
+  std::string alt_svc_header =
+      "Alt-Svc: " + quic::AlpnForVersion(version_) + "=\":443\"\r\n\r\n";
+  MockRead http_reads[] = {
+      MockRead("HTTP/1.1 200 OK\r\n"), MockRead(alt_svc_header.data()),
+      MockRead("hello world"),
+      MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
+      MockRead(ASYNC, OK)};
+
+  StaticSocketDataProvider http_data(http_reads, base::span<MockWrite>());
+  socket_factory_.AddSocketDataProvider(&http_data);
+  AddCertificate(&ssl_data_);
+  socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
+
+  MockQuicData mock_quic_data(version_);
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
+  mock_quic_data.AddWrite(
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          true, GetRequestHeaders("GET", "https", "/")));
+  mock_quic_data.AddRead(
+      ASYNC, ConstructServerResponseHeadersPacket(
+                 1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
+                 GetResponseHeaders("200 OK")));
+  std::string header = ConstructDataHeader(6);
+  mock_quic_data.AddRead(
+      ASYNC, ConstructServerDataPacket(
+                 2, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
+                 header + "hello!"));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 2, 1, 1));
   mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING);  // No more data to read
   mock_quic_data.AddRead(ASYNC, 0);               // EOF
 
@@ -1832,11 +1955,16 @@
   // Second request with kNetworkIsolationKey1, can finally use QUIC, since
   // alternative service infrmation has been received in this context before.
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "https", "/")));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -1846,7 +1974,8 @@
       ASYNC, ConstructServerDataPacket(
                  2, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
                  header + "hello!"));
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(3, 2, 1, 1));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 2, 1, 1));
   mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING);  // No more data to read
   mock_quic_data.AddRead(ASYNC, 0);               // EOF
 
@@ -1908,11 +2037,16 @@
   socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
 
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "https", "/")));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -1922,7 +2056,8 @@
       ASYNC, ConstructServerDataPacket(
                  2, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
                  header + "hello!"));
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(3, 2, 1, 1));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 2, 1, 1));
   mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING);  // No more data to read
   mock_quic_data.AddRead(ASYNC, 0);               // EOF
 
@@ -1968,11 +2103,16 @@
   socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
 
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "https", "/")));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -1982,7 +2122,8 @@
       ASYNC, ConstructServerDataPacket(
                  2, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
                  header + "hello!"));
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(3, 2, 1, 1));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 2, 1, 1));
   mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING);  // No more data to read
   mock_quic_data.AddRead(ASYNC, 0);               // EOF
 
@@ -2010,11 +2151,16 @@
   socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
 
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "https", "/")));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -2024,7 +2170,8 @@
       ASYNC, ConstructServerDataPacket(
                  2, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
                  header + "hello!"));
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(3, 2, 1, 1));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 2, 1, 1));
   mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING);  // No more data to read
   mock_quic_data.AddRead(ASYNC, 0);               // EOF
 
@@ -2140,11 +2287,16 @@
   socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
 
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "https", "/")));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -2154,7 +2306,8 @@
       ASYNC, ConstructServerDataPacket(
                  2, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
                  header + "hello!"));
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(3, 2, 1, 1));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 2, 1, 1));
   mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING);  // No more data to read
   mock_quic_data.AddRead(ASYNC, 0);               // EOF
 
@@ -2202,11 +2355,16 @@
   socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
 
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "https", "/")));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -2216,7 +2374,8 @@
       ASYNC, ConstructServerDataPacket(
                  2, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
                  header + "hello!"));
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(3, 2, 1, 1));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 2, 1, 1));
   mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING);  // No more data to read
   mock_quic_data.AddRead(ASYNC, 0);               // EOF
 
@@ -2235,11 +2394,16 @@
     return;
   }
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "https", "/")));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -2250,16 +2414,18 @@
                          ConstructServerGoAwayPacket(
                              2, quic::QUIC_ERROR_MIGRATING_PORT,
                              "connection migration with port change only"));
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(3, 2, 1, 1));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 2, 1, 1));
   std::string header = ConstructDataHeader(6);
   mock_quic_data.AddRead(
       SYNCHRONOUS, ConstructServerDataPacket(
                        3, GetNthClientInitiatedBidirectionalStreamId(0), false,
                        true, header + "hello!"));
-  mock_quic_data.AddWrite(SYNCHRONOUS,
-                          ConstructClientAckAndRstPacket(
-                              4, GetNthClientInitiatedBidirectionalStreamId(0),
-                              quic::QUIC_STREAM_CANCELLED, 3, 3, 1));
+  mock_quic_data.AddWrite(
+      SYNCHRONOUS,
+      ConstructClientAckAndRstPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0),
+          quic::QUIC_STREAM_CANCELLED, 3, 3, 1));
   mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING);  // No more data to read
   mock_quic_data.AddRead(ASYNC, 0);               // EOF
 
@@ -2466,7 +2632,8 @@
                       client_maker_.MakeDummyCHLOPacket(1));  // CHLO
 
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
-  quic_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(2));
+  if (VersionUsesQpack(version_.transport_version))
+    quic_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(2));
   quic_data2.AddSocketDataToFactory(&socket_factory_);
 
   // Resolve the host resolution synchronously.
@@ -2570,18 +2737,23 @@
 
   // Quic connection will then be retried on the alternate network.
   MockQuicData quic_data2(version_);
+  packet_num = 1;
   quic_data2.AddWrite(SYNCHRONOUS,
-                      client_maker_.MakeDummyCHLOPacket(1));  // CHLO
+                      client_maker_.MakeDummyCHLOPacket(packet_num++));  // CHLO
 
   const std::string body = "hello!";
   std::string header = ConstructDataHeader(body.length());
 
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
-  quic_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(2));
+  if (VersionUsesQpack(version_.transport_version)) {
+    quic_data2.AddWrite(SYNCHRONOUS,
+                        ConstructInitialSettingsPacket(packet_num++));
+  }
   quic_data2.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       3, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "https", "/")));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          true, GetRequestHeaders("GET", "https", "/")));
   quic_data2.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -2590,7 +2762,8 @@
       ASYNC, ConstructServerDataPacket(
                  2, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
                  header + body));
-  quic_data2.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(4, 2, 1, 1));
+  quic_data2.AddWrite(SYNCHRONOUS,
+                      ConstructClientAckPacket(packet_num++, 2, 1, 1));
   quic_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // No more data to read
   quic_data2.AddSocketDataToFactory(&socket_factory_);
 
@@ -2667,58 +2840,26 @@
           priority, GetRequestHeaders("GET", "https", "/"), 0, nullptr));
 
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
-  if (version_.transport_version != quic::QUIC_VERSION_99) {
-    quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(2));
-    // TLP 1
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 3, true));
-    // TLP 2
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(2, 4, true));
-    // RTO 1
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 5, true));
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(2, 6, true));
-    // RTO 2
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 7, true));
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(2, 8, true));
-    // RTO 3
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 9, true));
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(2, 10, true));
 
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeConnectionClosePacket(
-                           11, true, quic::QUIC_NETWORK_IDLE_TIMEOUT,
-                           "No recent network activity."));
-  } else {
-    // Settings were sent in the request packet so there is only 1 packet to
-    // retransmit.
-    // TLP 1
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 2, true));
-    // TLP 2
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 3, true));
-    // RTO 1
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 4, true));
-    // RTO 2
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 5, true));
-    // RTO 3
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 6, true));
+  // TLP 1
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(1, 2, true));
+  // TLP 2
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(1, 3, true));
+  // RTO 1
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(1, 4, true));
+  // RTO 2
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(1, 5, true));
+  // RTO 3
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(1, 6, true));
 
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeConnectionClosePacket(
-                           7, true, quic::QUIC_NETWORK_IDLE_TIMEOUT,
-                           "No recent network activity."));
-  }
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeConnectionClosePacket(
+                                      7, true, quic::QUIC_NETWORK_IDLE_TIMEOUT,
+                                      "No recent network activity."));
 
   quic_data.AddRead(ASYNC, ERR_IO_PENDING);
   quic_data.AddRead(ASYNC, OK);
@@ -2781,64 +2922,28 @@
           priority, GetRequestHeaders("GET", "https", "/"), 0, nullptr));
 
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
-  if (version_.transport_version != quic::QUIC_VERSION_99) {
-    quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(2));
-    // TLP 1
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 3, true));
-    // TLP 2
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(2, 4, true));
-    // RTO 1
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 5, true));
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(2, 6, true));
-    // RTO 2
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 7, true));
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(2, 8, true));
-    // RTO 3
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 9, true));
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(2, 10, true));
-    // RTO 4
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 11, true));
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(2, 12, true));
-    // RTO 5
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeConnectionClosePacket(
-                           13, true, quic::QUIC_TOO_MANY_RTOS,
-                           "5 consecutive retransmission timeouts"));
-  } else {
-    // TLP 1
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 2, true));
-    // TLP 2
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 3, true));
-    // RTO 1
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 4, true));
-    // RTO 2
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 5, true));
-    // RTO 3
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 6, true));
-    // RTO 4
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 7, true));
-    // RTO 5
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeConnectionClosePacket(
-                           8, true, quic::QUIC_TOO_MANY_RTOS,
-                           "5 consecutive retransmission timeouts"));
-  }
+  // TLP 1
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(1, 2, true));
+  // TLP 2
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(1, 3, true));
+  // RTO 1
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(1, 4, true));
+  // RTO 2
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(1, 5, true));
+  // RTO 3
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(1, 6, true));
+  // RTO 4
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(1, 7, true));
+  // RTO 5
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeConnectionClosePacket(
+                                      8, true, quic::QUIC_TOO_MANY_RTOS,
+                                      "5 consecutive retransmission timeouts"));
 
   quic_data.AddRead(ASYNC, OK);
   quic_data.AddSocketDataToFactory(&socket_factory_);
@@ -2900,86 +3005,45 @@
           priority, GetRequestHeaders("GET", "https", "/"), 0, nullptr));
 
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
-  if (version_.transport_version != quic::QUIC_VERSION_99) {
-    quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(2));
-  }
 
-  if (quic::VersionUsesQpack(version_.transport_version)) {
-    quic_data.AddWrite(
-        SYNCHRONOUS, client_maker_.MakeRstPacket(
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRstPacket(
                          2, true, GetNthClientInitiatedBidirectionalStreamId(0),
                          quic::QUIC_STREAM_CANCELLED));
-    // Since the headers are sent on the data stream, when the stream is reset
-    // the headers are no longer retransmitted.
-    client_maker_.RemoveSavedStreamFrames(
-        GetNthClientInitiatedBidirectionalStreamId(0));
-    // TLP 1
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 3, true));
-    // TLP 2
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(2, 4, true));
-    // RTO 1
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 5, true));
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(2, 6, true));
-    // RTO 2
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 7, true));
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(2, 8, true));
-    // RTO 3
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 9, true));
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(2, 10, true));
-    // RTO 4
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 11, true));
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(2, 12, true));
-    // RTO 5
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeConnectionClosePacket(
-                           13, true, quic::QUIC_TOO_MANY_RTOS,
-                           "5 consecutive retransmission timeouts"));
-  } else {
-    quic_data.AddWrite(
-        SYNCHRONOUS, client_maker_.MakeRstPacket(
-                         3, true, GetNthClientInitiatedBidirectionalStreamId(0),
-                         quic::QUIC_STREAM_CANCELLED));
-    // TLP 1
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 4, true));
-    // TLP 2
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(2, 5, true));
-    // RTO 1
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(3, 6, true));
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 7, true));
-    // RTO 2
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(2, 8, true));
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(3, 9, true));
-    // RTO 3
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 10, true));
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(2, 11, true));
-    // RTO 4
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(3, 12, true));
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 13, true));
+  // Since the headers are sent on the data stream, when the stream is reset
+  // the headers are no longer retransmitted.
+  client_maker_.RemoveSavedStreamFrames(
+      GetNthClientInitiatedBidirectionalStreamId(0));
+  // TLP 1
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(1, 3, true));
+  // TLP 2
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(2, 4, true));
+  // RTO 1
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(1, 5, true));
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(2, 6, true));
+  // RTO 2
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(1, 7, true));
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(2, 8, true));
+  // RTO 3
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(1, 9, true));
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(2, 10, true));
+  // RTO 4
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(1, 11, true));
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(2, 12, true));
   // RTO 5
   quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeConnectionClosePacket(
-                                      14, true, quic::QUIC_TOO_MANY_RTOS,
+                                      13, true, quic::QUIC_TOO_MANY_RTOS,
                                       "5 consecutive retransmission timeouts"));
-  }
 
   quic_data.AddRead(ASYNC, OK);
   quic_data.AddSocketDataToFactory(&socket_factory_);
@@ -3038,10 +3102,6 @@
                          true, GetRequestHeaders("GET", "https", "/")));
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
   uint64_t packet_number = 2;
-  if (version_.transport_version != quic::QUIC_VERSION_99) {
-    quic_data.AddWrite(SYNCHRONOUS,
-                       ConstructInitialSettingsPacket(packet_number++));
-  }
   quic_data.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
   // Peer sending data from an non-existing stream causes this end to raise
   // error and close connection.
@@ -3116,58 +3176,25 @@
           priority, GetRequestHeaders("GET", "https", "/"), 0, nullptr));
 
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
-  if (version_.transport_version != quic::QUIC_VERSION_99) {
-    quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(2));
-    // TLP 1
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 3, true));
-    // TLP 2
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(2, 4, true));
-    // RTO 1
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 5, true));
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(2, 6, true));
-    // RTO 2
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 7, true));
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(2, 8, true));
-    // RTO 3
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 9, true));
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(2, 10, true));
+  // TLP 1
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(1, 2, true));
+  // TLP 2
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(1, 3, true));
+  // RTO 1
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(1, 4, true));
+  // RTO 2
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(1, 5, true));
+  // RTO 3
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(1, 6, true));
 
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeConnectionClosePacket(
-                           11, true, quic::QUIC_NETWORK_IDLE_TIMEOUT,
-                           "No recent network activity."));
-  } else {
-    // Settings were sent in the request packet so there is only 1 packet to
-    // retransmit.
-    // TLP 1
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 2, true));
-    // TLP 2
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 3, true));
-    // RTO 1
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 4, true));
-    // RTO 2
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 5, true));
-    // RTO 3
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 6, true));
-
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeConnectionClosePacket(
-                           7, true, quic::QUIC_NETWORK_IDLE_TIMEOUT,
-                           "No recent network activity."));
-  }
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeConnectionClosePacket(
+                                      7, true, quic::QUIC_NETWORK_IDLE_TIMEOUT,
+                                      "No recent network activity."));
 
   quic_data.AddRead(ASYNC, ERR_IO_PENDING);
   quic_data.AddRead(ASYNC, OK);
@@ -3255,58 +3282,25 @@
           priority, GetRequestHeaders("GET", "https", "/"), 0, nullptr));
 
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
-  if (version_.transport_version != quic::QUIC_VERSION_99) {
-    quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(2));
-    // TLP 1
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 3, true));
-    // TLP 2
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(2, 4, true));
-    // RTO 1
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 5, true));
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(2, 6, true));
-    // RTO 2
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 7, true));
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(2, 8, true));
-    // RTO 3
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 9, true));
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(2, 10, true));
+  // TLP 1
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(1, 2, true));
+  // TLP 2
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(1, 3, true));
+  // RTO 1
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(1, 4, true));
+  // RTO 2
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(1, 5, true));
+  // RTO 3
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(1, 6, true));
 
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeConnectionClosePacket(
-                           11, true, quic::QUIC_NETWORK_IDLE_TIMEOUT,
-                           "No recent network activity."));
-  } else {
-    // Settings were sent in the request packet so there is only 1 packet to
-    // retransmit.
-    // TLP 1
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 2, true));
-    // TLP 2
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 3, true));
-    // RTO 1
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 4, true));
-    // RTO 2
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 5, true));
-    // RTO 3
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 6, true));
-
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeConnectionClosePacket(
-                           7, true, quic::QUIC_NETWORK_IDLE_TIMEOUT,
-                           "No recent network activity."));
-  }
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeConnectionClosePacket(
+                                      7, true, quic::QUIC_NETWORK_IDLE_TIMEOUT,
+                                      "No recent network activity."));
 
   quic_data.AddRead(ASYNC, ERR_IO_PENDING);
   quic_data.AddRead(ASYNC, OK);
@@ -3398,81 +3392,39 @@
           priority, GetRequestHeaders("GET", "https", "/"), 0, nullptr));
 
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
-  if (version_.transport_version != quic::QUIC_VERSION_99) {
-    quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(2));
 
-    quic_data.AddRead(
-        ASYNC, ConstructServerResponseHeadersPacket(
-                   1, GetNthClientInitiatedBidirectionalStreamId(0), false,
-                   false, GetResponseHeaders("200 OK")));
-    // quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(3, 1, 1));
-    quic_data.AddWrite(
-        SYNCHRONOUS,
-        ConstructClientAckPacket(3, 1, 1, 1,
-                                 quic::QuicTime::Delta::FromMilliseconds(25)));
+  // Settings were sent in the request packet so there is only 1 packet to
+  // retransmit.
+  quic_data.AddRead(ASYNC, ConstructServerResponseHeadersPacket(
+                               1, GetNthClientInitiatedBidirectionalStreamId(0),
+                               false, false, GetResponseHeaders("200 OK")));
+  // quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(3, 1, 1));
+  quic_data.AddWrite(
+      SYNCHRONOUS,
+      ConstructClientAckPacket(2, 1, 1, 1,
+                               quic::QuicTime::Delta::FromMilliseconds(25)));
 
-    // TLP 1
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 4, false));
-    // TLP 2
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(2, 5, false));
-    // RTO 1
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 6, false));
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(2, 7, false));
-    // RTO 2
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 8, false));
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(2, 9, false));
-    // RTO 3
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 10, false));
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(2, 11, false));
+  // TLP 1
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(1, 3, false));
+  // TLP 2
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(1, 4, false));
+  // RTO 1
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(1, 5, false));
+  // RTO 2
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(1, 6, false));
+  // RTO 3
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(1, 7, false));
 
-    quic_data.AddWrite(
-        SYNCHRONOUS,
-        client_maker_.MakeAckAndConnectionClosePacket(
-            12, false, quic::QuicTime::Delta::FromMilliseconds(4000), 1, 1, 1,
-            quic::QUIC_NETWORK_IDLE_TIMEOUT, "No recent network activity.", 0));
-  } else {
-    // Settings were sent in the request packet so there is only 1 packet to
-    // retransmit.
-    quic_data.AddRead(
-        ASYNC, ConstructServerResponseHeadersPacket(
-                   1, GetNthClientInitiatedBidirectionalStreamId(0), false,
-                   false, GetResponseHeaders("200 OK")));
-    // quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(3, 1, 1));
-    quic_data.AddWrite(
-        SYNCHRONOUS,
-        ConstructClientAckPacket(2, 1, 1, 1,
-                                 quic::QuicTime::Delta::FromMilliseconds(25)));
-
-    // TLP 1
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 3, false));
-    // TLP 2
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 4, false));
-    // RTO 1
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 5, false));
-    // RTO 2
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 6, false));
-    // RTO 3
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 7, false));
-
-    quic_data.AddWrite(
-        SYNCHRONOUS,
-        client_maker_.MakeAckAndConnectionClosePacket(
-            8, false, quic::QuicTime::Delta::FromMilliseconds(4000), 1, 1, 1,
-            quic::QUIC_NETWORK_IDLE_TIMEOUT, "No recent network activity.", 0));
-  }
+  quic_data.AddWrite(
+      SYNCHRONOUS,
+      client_maker_.MakeAckAndConnectionClosePacket(
+          8, false, quic::QuicTime::Delta::FromMilliseconds(4000), 1, 1, 1,
+          quic::QUIC_NETWORK_IDLE_TIMEOUT, "No recent network activity.", 0));
 
   quic_data.AddRead(ASYNC, ERR_IO_PENDING);
   quic_data.AddRead(ASYNC, OK);
@@ -3548,67 +3500,28 @@
           priority, GetRequestHeaders("GET", "https", "/"), 0, nullptr));
 
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
-  if (version_.transport_version != quic::QUIC_VERSION_99) {
-    quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(2));
+  // TLP 1
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(1, 2, true));
+  // TLP 2
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(1, 3, true));
+  // RTO 1
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(1, 4, true));
+  // RTO 2
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(1, 5, true));
+  // RTO 3
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(1, 6, true));
+  // RTO 4
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(1, 7, true));
 
-    // TLP 1
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 3, true));
-    // TLP 2
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(2, 4, true));
-    // RTO 1
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 5, true));
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(2, 6, true));
-    // RTO 2
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 7, true));
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(2, 8, true));
-    // RTO 3
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 9, true));
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(2, 10, true));
-    // RTO 4
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 11, true));
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(2, 12, true));
-
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeConnectionClosePacket(
-                           13, true, quic::QUIC_TOO_MANY_RTOS,
-                           "5 consecutive retransmission timeouts"));
-  } else {
-    // Settings were sent in the request packet so there is only 1 packet to
-    // retransmit.
-    // TLP 1
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 2, true));
-    // TLP 2
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 3, true));
-    // RTO 1
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 4, true));
-    // RTO 2
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 5, true));
-    // RTO 3
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 6, true));
-    // RTO 4
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 7, true));
-
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeConnectionClosePacket(
-                           8, true, quic::QUIC_TOO_MANY_RTOS,
-                           "5 consecutive retransmission timeouts"));
-  }
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeConnectionClosePacket(
+                                      8, true, quic::QUIC_TOO_MANY_RTOS,
+                                      "5 consecutive retransmission timeouts"));
   quic_data.AddRead(ASYNC, OK);
   quic_data.AddSocketDataToFactory(&socket_factory_);
 
@@ -3695,83 +3608,44 @@
 
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
 
-  if (quic::VersionUsesQpack(version_.transport_version)) {
-    quic_data.AddWrite(
-        SYNCHRONOUS, client_maker_.MakeRstPacket(
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRstPacket(
                          2, true, GetNthClientInitiatedBidirectionalStreamId(0),
                          quic::QUIC_STREAM_CANCELLED));
-    // Since the headers are sent on the data stream, when the stream is reset
-    // the headers are no longer retransmitted.
-    client_maker_.RemoveSavedStreamFrames(
-        GetNthClientInitiatedBidirectionalStreamId(0));
-    // TLP 1
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 3, true));
-    // TLP 2
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(2, 4, true));
-    // RTO 1
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 5, true));
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(2, 6, true));
-    // RTO 2
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 7, true));
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(2, 8, true));
-    // RTO 3
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 9, true));
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(2, 10, true));
-    // RTO 4
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 11, true));
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(2, 12, true));
-    // RTO 5
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeConnectionClosePacket(
-                           13, true, quic::QUIC_TOO_MANY_RTOS,
-                           "5 consecutive retransmission timeouts"));
-  } else {
-    quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(2));
-    quic_data.AddWrite(
-        SYNCHRONOUS, client_maker_.MakeRstPacket(
-                         3, true, GetNthClientInitiatedBidirectionalStreamId(0),
-                         quic::QUIC_STREAM_CANCELLED));
-    // TLP 1
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 4, true));
-    // TLP 2
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(2, 5, true));
-    // RTO 1
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(3, 6, true));
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 7, true));
-    // RTO 2
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(2, 8, true));
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(3, 9, true));
-    // RTO 3
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 10, true));
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(2, 11, true));
-    // RTO 4
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(3, 12, true));
-    quic_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeRetransmissionPacket(1, 13, true));
+  // Since the headers are sent on the data stream, when the stream is reset
+  // the headers are no longer retransmitted.
+  client_maker_.RemoveSavedStreamFrames(
+      GetNthClientInitiatedBidirectionalStreamId(0));
+  // TLP 1
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(1, 3, true));
+  // TLP 2
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(2, 4, true));
+  // RTO 1
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(1, 5, true));
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(2, 6, true));
+  // RTO 2
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(1, 7, true));
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(2, 8, true));
+  // RTO 3
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(1, 9, true));
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(2, 10, true));
+  // RTO 4
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(1, 11, true));
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeRetransmissionPacket(2, 12, true));
   // RTO 5
   quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeConnectionClosePacket(
-                                      14, true, quic::QUIC_TOO_MANY_RTOS,
+                                      13, true, quic::QUIC_TOO_MANY_RTOS,
                                       "5 consecutive retransmission timeouts"));
-  }
 
   quic_data.AddRead(ASYNC, OK);
   quic_data.AddSocketDataToFactory(&socket_factory_);
@@ -3834,10 +3708,6 @@
                          true, GetRequestHeaders("GET", "https", "/")));
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
   uint64_t packet_number = 2;
-  if (version_.transport_version != quic::QUIC_VERSION_99) {
-    quic_data.AddWrite(SYNCHRONOUS,
-                       ConstructInitialSettingsPacket(packet_number++));
-  }
   quic_data.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
 
   // Peer sending data from an non-existing stream causes this end to raise
@@ -3930,9 +3800,6 @@
           priority, GetRequestHeaders("GET", "https", "/"), 0, nullptr));
 
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
-  if (version_.transport_version != quic::QUIC_VERSION_99) {
-    quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(2));
-  }
   quic_data.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
 
   quic_data.AddRead(ASYNC,
@@ -4023,11 +3890,16 @@
   crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
 
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "https", "/")));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -4037,7 +3909,8 @@
       ASYNC, ConstructServerDataPacket(
                  2, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
                  header + "hello!"));
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(3, 2, 1, 1));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 2, 1, 1));
   mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING);  // No more data to read
   mock_quic_data.AddRead(ASYNC, 0);               // EOF
 
@@ -4095,12 +3968,17 @@
   verify_details.cert_verify_result.is_issued_by_known_root = true;
   crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
 
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   // First request.
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "https", "/")));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -4110,7 +3988,8 @@
       ASYNC, ConstructServerDataPacket(
                  2, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
                  header + "hello!"));
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(3, 2, 1, 1));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 2, 1, 1));
 
   // Second request will go over the pooled QUIC connection, but will be
   // reset by the server.
@@ -4124,8 +4003,8 @@
   mock_quic_data.AddWrite(
       SYNCHRONOUS,
       ConstructClientRequestHeadersPacket(
-          4, GetNthClientInitiatedBidirectionalStreamId(1), false, true,
-          GetRequestHeaders("GET", "https", "/", &client_maker2),
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(1), false,
+          true, GetRequestHeaders("GET", "https", "/", &client_maker2),
           GetNthClientInitiatedBidirectionalStreamId(0)));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerRstPacket(
@@ -4238,11 +4117,16 @@
   // Open a session to foo.example.org:443 using the first entry of the
   // alternative service list.
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "https", "/")));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          true, GetRequestHeaders("GET", "https", "/")));
 
   std::string alt_svc_list =
       "quic=\"mail.example.org:444\", quic=\"foo.example.org:443\", "
@@ -4256,16 +4140,18 @@
       ASYNC, ConstructServerDataPacket(
                  2, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
                  header + "hello!"));
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(3, 2, 1, 1));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 2, 1, 1));
 
   // Second QUIC request data.
   // Connection pooling, using existing session, no need to include version
   // as version negotiation has been completed.
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       4, GetNthClientInitiatedBidirectionalStreamId(1), false,
-                       true, GetRequestHeaders("GET", "https", "/"),
-                       GetNthClientInitiatedBidirectionalStreamId(0)));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(1), false,
+          true, GetRequestHeaders("GET", "https", "/"),
+          GetNthClientInitiatedBidirectionalStreamId(0)));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  3, GetNthClientInitiatedBidirectionalStreamId(1), false, false,
@@ -4275,7 +4161,8 @@
                  4, GetNthClientInitiatedBidirectionalStreamId(1), false, true,
                  header + "hello!"));
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientAckAndConnectionClosePacket(5, 4, 3, 1));
+      SYNCHRONOUS,
+      ConstructClientAckAndConnectionClosePacket(packet_num++, 4, 3, 1));
   mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING);  // No more data to read
   mock_quic_data.AddRead(ASYNC, 0);               // EOF
 
@@ -4303,11 +4190,16 @@
   // Open a session to foo.example.org:443 using the first entry of the
   // alternative service list.
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "http", "/")));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          true, GetRequestHeaders("GET", "http", "/")));
 
   std::string alt_svc_list;
   mock_quic_data.AddRead(
@@ -4319,16 +4211,18 @@
       ASYNC, ConstructServerDataPacket(
                  2, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
                  header + "hello!"));
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(3, 2, 1, 1));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 2, 1, 1));
 
   // Second QUIC request data.
   // Connection pooling, using existing session, no need to include version
   // as version negotiation has been completed.
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       4, GetNthClientInitiatedBidirectionalStreamId(1), false,
-                       true, GetRequestHeaders("GET", "http", "/"),
-                       GetNthClientInitiatedBidirectionalStreamId(0)));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(1), false,
+          true, GetRequestHeaders("GET", "http", "/"),
+          GetNthClientInitiatedBidirectionalStreamId(0)));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  3, GetNthClientInitiatedBidirectionalStreamId(1), false, false,
@@ -4338,7 +4232,8 @@
                  4, GetNthClientInitiatedBidirectionalStreamId(1), false, true,
                  header + "hello!"));
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientAckAndConnectionClosePacket(5, 4, 3, 1));
+      SYNCHRONOUS,
+      ConstructClientAckAndConnectionClosePacket(packet_num++, 4, 3, 1));
   mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING);  // No more data to read
   mock_quic_data.AddRead(ASYNC, 0);               // EOF
 
@@ -4381,12 +4276,17 @@
   session_params_.quic_params.allow_remote_alt_svc = true;
   MockQuicData mock_quic_data(version_);
 
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   // First request.
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "https", "/")));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -4396,14 +4296,16 @@
       ASYNC, ConstructServerDataPacket(
                  2, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
                  header + "hello!"));
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(3, 2, 1, 1));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 2, 1, 1));
 
   // Second request.
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       4, GetNthClientInitiatedBidirectionalStreamId(1), false,
-                       true, GetRequestHeaders("GET", "https", "/"),
-                       GetNthClientInitiatedBidirectionalStreamId(0)));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(1), false,
+          true, GetRequestHeaders("GET", "https", "/"),
+          GetNthClientInitiatedBidirectionalStreamId(0)));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  3, GetNthClientInitiatedBidirectionalStreamId(1), false, false,
@@ -4413,7 +4315,8 @@
                  4, GetNthClientInitiatedBidirectionalStreamId(1), false, true,
                  header + "hello!"));
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientAckAndConnectionClosePacket(5, 4, 3, 1));
+      SYNCHRONOUS,
+      ConstructClientAckAndConnectionClosePacket(packet_num++, 4, 3, 1));
   mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING);  // No more data to read
   mock_quic_data.AddRead(ASYNC, 0);               // EOF
 
@@ -4463,12 +4366,17 @@
 
   MockQuicData mock_quic_data(version_);
 
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   // First request.
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "https", "/")));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -4478,7 +4386,8 @@
       ASYNC, ConstructServerDataPacket(
                  2, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
                  header + "hello!"));
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(3, 2, 1, 1));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 2, 1, 1));
 
   // Second request.
   QuicTestPacketMaker client_maker2(
@@ -4491,8 +4400,8 @@
   mock_quic_data.AddWrite(
       SYNCHRONOUS,
       ConstructClientRequestHeadersPacket(
-          4, GetNthClientInitiatedBidirectionalStreamId(1), false, true,
-          GetRequestHeaders("GET", "https", "/", &client_maker2),
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(1), false,
+          true, GetRequestHeaders("GET", "https", "/", &client_maker2),
           GetNthClientInitiatedBidirectionalStreamId(0)));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
@@ -4503,7 +4412,8 @@
                  4, GetNthClientInitiatedBidirectionalStreamId(1), false, true,
                  header + "hello!"));
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientAckAndConnectionClosePacket(5, 4, 3, 1));
+      SYNCHRONOUS,
+      ConstructClientAckAndConnectionClosePacket(packet_num++, 4, 3, 1));
   mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING);  // No more data to read
   mock_quic_data.AddRead(ASYNC, 0);               // EOF
 
@@ -4597,12 +4507,17 @@
   server_maker_.set_hostname("www.example.org");
   client_maker_.set_hostname("www.example.org");
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   // First QUIC request data.
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "https", "/")));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          true, GetRequestHeaders("GET", "https", "/")));
 
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
@@ -4613,13 +4528,14 @@
       ASYNC, ConstructServerDataPacket(
                  2, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
                  header + "hello from mail QUIC!"));
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(3, 2, 1, 1));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 2, 1, 1));
   // Second QUIC request data.
   mock_quic_data.AddWrite(
       SYNCHRONOUS,
       ConstructClientRequestHeadersPacket(
-          4, GetNthClientInitiatedBidirectionalStreamId(1), false, true,
-          GetRequestHeaders("GET", "https", "/", &client_maker),
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(1), false,
+          true, GetRequestHeaders("GET", "https", "/", &client_maker),
           GetNthClientInitiatedBidirectionalStreamId(0)));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
@@ -4630,7 +4546,8 @@
                  4, GetNthClientInitiatedBidirectionalStreamId(1), false, true,
                  header + "hello from mail QUIC!"));
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientAckAndConnectionClosePacket(5, 4, 3, 1));
+      SYNCHRONOUS,
+      ConstructClientAckAndConnectionClosePacket(packet_num++, 4, 3, 1));
   mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING);  // No more data to read
   mock_quic_data.AddRead(ASYNC, 0);               // EOF
 
@@ -4702,11 +4619,16 @@
   socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
 
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "https", "/")));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -4716,7 +4638,8 @@
       ASYNC, ConstructServerDataPacket(
                  2, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
                  header + "hello!"));
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(3, 2, 1, 1));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 2, 1, 1));
   mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING);  // No more data to read
   mock_quic_data.AddRead(ASYNC, 0);               // EOF
 
@@ -4756,11 +4679,16 @@
   socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
 
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "https", "/")));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -4770,7 +4698,8 @@
       ASYNC, ConstructServerDataPacket(
                  2, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
                  header + "hello!"));
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(3, 2, 1, 1));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 2, 1, 1));
   mock_quic_data.AddRead(SYNCHRONOUS, 0);  // EOF
 
   mock_quic_data.AddSocketDataToFactory(&socket_factory_);
@@ -4790,11 +4719,16 @@
       "HTTPS mail.example.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "http", "/")));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          true, GetRequestHeaders("GET", "http", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -4804,7 +4738,8 @@
       ASYNC, ConstructServerDataPacket(
                  2, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
                  header + "hello!"));
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(3, 2, 1, 1));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 2, 1, 1));
   mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING);  // No more data to read
   mock_quic_data.AddRead(ASYNC, 0);               // EOF
 
@@ -4990,11 +4925,16 @@
 
 TEST_P(QuicNetworkTransactionTest, ZeroRTTWithConfirmationRequired) {
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "https", "/")));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -5004,7 +4944,8 @@
       ASYNC, ConstructServerDataPacket(
                  2, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
                  header + "hello!"));
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(3, 2, 1, 1));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 2, 1, 1));
   mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // No more data to read
   mock_quic_data.AddSocketDataToFactory(&socket_factory_);
 
@@ -5059,11 +5000,6 @@
 
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
 
-  if (version_.transport_version != quic::QUIC_VERSION_99) {
-    mock_quic_data.AddWrite(
-        SYNCHRONOUS, client_maker_.MakeSettingsPacket(packet_number++, false));
-  }
-
   mock_quic_data.AddWrite(
       SYNCHRONOUS,
       ConstructClientRequestHeadersPacket(
@@ -5143,11 +5079,6 @@
 
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
 
-  if (version_.transport_version != quic::QUIC_VERSION_99) {
-    mock_quic_data.AddWrite(
-        SYNCHRONOUS, client_maker_.MakeSettingsPacket(packet_number++, false));
-  }
-
   mock_quic_data.AddWrite(
       SYNCHRONOUS,
       ConstructClientRequestHeadersPacket(
@@ -5214,11 +5145,16 @@
        LogGranularQuicErrorCodeOnQuicProtocolErrorLocal) {
   session_params_.quic_params.retry_without_alt_svc_on_quic_errors = false;
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "https", "/")));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          true, GetRequestHeaders("GET", "https", "/")));
   // Read a close connection packet with
   // quic::QuicErrorCode: quic::QUIC_CRYPTO_VERSION_NOT_SUPPORTED from the peer.
   mock_quic_data.AddRead(ASYNC, ConstructServerConnectionClosePacket(1));
@@ -5263,11 +5199,16 @@
        LogGranularQuicErrorCodeOnQuicProtocolErrorRemote) {
   session_params_.quic_params.retry_without_alt_svc_on_quic_errors = false;
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "https", "/")));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          true, GetRequestHeaders("GET", "https", "/")));
   // Peer sending data from an non-existing stream causes this end to raise
   // error and close connection.
   mock_quic_data.AddRead(
@@ -5275,11 +5216,11 @@
                  1, false, GetNthClientInitiatedBidirectionalStreamId(47),
                  quic::QUIC_STREAM_LAST_ERROR));
   std::string quic_error_details = "Data for nonexistent stream";
-  mock_quic_data.AddWrite(SYNCHRONOUS,
-                          ConstructClientAckAndConnectionClosePacket(
-                              3, quic::QuicTime::Delta::Zero(), 1, 1, 1,
-                              quic::QUIC_INVALID_STREAM_ID, quic_error_details,
-                              quic::IETF_RST_STREAM));
+  mock_quic_data.AddWrite(
+      SYNCHRONOUS, ConstructClientAckAndConnectionClosePacket(
+                       packet_num++, quic::QuicTime::Delta::Zero(), 1, 1, 1,
+                       quic::QUIC_INVALID_STREAM_ID, quic_error_details,
+                       quic::IETF_RST_STREAM));
   mock_quic_data.AddSocketDataToFactory(&socket_factory_);
 
   // The non-alternate protocol job needs to hang in order to guarantee that
@@ -5316,11 +5257,16 @@
 
 TEST_P(QuicNetworkTransactionTest, RstSteamErrorHandling) {
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "https", "/")));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          true, GetRequestHeaders("GET", "https", "/")));
   // Read the response headers, then a RST_STREAM frame.
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
@@ -5330,7 +5276,8 @@
       ASYNC, ConstructServerRstPacket(
                  2, false, GetNthClientInitiatedBidirectionalStreamId(0),
                  quic::QUIC_STREAM_CANCELLED));
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(3, 2, 1, 1));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 2, 1, 1));
   mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // No more read data.
   mock_quic_data.AddSocketDataToFactory(&socket_factory_);
 
@@ -5378,11 +5325,16 @@
 TEST_P(QuicNetworkTransactionTest, RstSteamBeforeHeaders) {
   session_params_.quic_params.retry_without_alt_svc_on_quic_errors = false;
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "https", "/")));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerRstPacket(
                  1, false, GetNthClientInitiatedBidirectionalStreamId(0),
@@ -5569,11 +5521,16 @@
   http_server_properties_->SetSupportsQuic(true, IPAddress(1, 2, 3, 4));
 
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "https", "/")));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -5583,7 +5540,8 @@
       ASYNC, ConstructServerDataPacket(
                  2, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
                  header + "hello!"));
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(3, 2, 1, 1));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 2, 1, 1));
   mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // No more data to read
   mock_quic_data.AddSocketDataToFactory(&socket_factory_);
   // No HTTP data is mocked as TCP job will be delayed and never starts.
@@ -5852,11 +5810,16 @@
   EXPECT_FALSE(
       test_socket_performance_watcher_factory_.rtt_notification_received());
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "https", "/")));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -5866,7 +5829,8 @@
       ASYNC, ConstructServerDataPacket(
                  2, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
                  header + "hello!"));
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(3, 2, 1, 1));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 2, 1, 1));
   mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // No more read data.
   mock_quic_data.AddSocketDataToFactory(&socket_factory_);
 
@@ -5932,10 +5896,19 @@
   session_params_.quic_params.origins_to_force_quic_on.insert(
       HostPortPair::FromString("mail.example.org:443"));
 
-  MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
-  MockWrite writes[] = {MockWrite(SYNCHRONOUS, ERR_FAILED, 1)};
+  MockQuicData mock_quic_data(version_);
+  if (!VersionUsesQpack(version_.transport_version))
+    mock_quic_data.AddRead(SYNCHRONOUS, OK);
+  else
+    mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+  mock_quic_data.AddWrite(SYNCHRONOUS, ERR_FAILED);
+  mock_quic_data.AddSocketDataToFactory(&socket_factory_);
+
+  /*MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
+  //MockWrite writes[] = {MockWrite(SYNCHRONOUS, ERR_FAILED, 1)};
+  MockWrite writes[] = {};
   SequencedSocketData socket_data(reads, writes);
-  socket_factory_.AddSocketDataProvider(&socket_data);
+  socket_factory_.AddSocketDataProvider(&socket_data);*/
 
   // The non-alternate protocol job needs to hang in order to guarantee that
   // the alternate-protocol job will "win".
@@ -5970,11 +5943,16 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    socket_data.AddWrite(SYNCHRONOUS,
+                         ConstructInitialSettingsPacket(packet_num++));
+  }
   socket_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       false, GetRequestHeaders("POST", "https", "/")));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          false, GetRequestHeaders("POST", "https", "/")));
   socket_data.AddWrite(SYNCHRONOUS, ERR_FAILED);
   socket_data.AddSocketDataToFactory(&socket_factory_);
 
@@ -6012,12 +5990,17 @@
       HostPortPair::FromString("mail.example.org:443"));
 
   MockQuicData socket_data(version_);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    socket_data.AddWrite(SYNCHRONOUS,
+                         ConstructInitialSettingsPacket(packet_num++));
+  }
   socket_data.AddWrite(ASYNC, ERR_NO_BUFFER_SPACE);
   socket_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "https", "/")));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          true, GetRequestHeaders("GET", "https", "/")));
   socket_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -6027,12 +6010,14 @@
       ASYNC, ConstructServerDataPacket(
                  2, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
                  header + "hello!"));
-  socket_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(3, 2, 1, 1));
+  socket_data.AddWrite(SYNCHRONOUS,
+                       ConstructClientAckPacket(packet_num++, 2, 1, 1));
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // No more data to read
   socket_data.AddWrite(
-      SYNCHRONOUS, client_maker_.MakeAckAndConnectionClosePacket(
-                       4, false, quic::QuicTime::Delta::FromMilliseconds(0), 2,
-                       1, 1, quic::QUIC_CONNECTION_CANCELLED, "net error", 0));
+      SYNCHRONOUS,
+      client_maker_.MakeAckAndConnectionClosePacket(
+          packet_num++, false, quic::QuicTime::Delta::FromMilliseconds(0), 2, 1,
+          1, quic::QUIC_CONNECTION_CANCELLED, "net error", 0));
 
   socket_data.AddSocketDataToFactory(&socket_factory_);
 
@@ -6047,12 +6032,17 @@
       HostPortPair::FromString("mail.example.org:443"));
 
   MockQuicData socket_data(version_);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    socket_data.AddWrite(SYNCHRONOUS,
+                         ConstructInitialSettingsPacket(packet_num++));
+  }
   socket_data.AddWrite(SYNCHRONOUS, ERR_NO_BUFFER_SPACE);
   socket_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "https", "/")));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          true, GetRequestHeaders("GET", "https", "/")));
   socket_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -6062,12 +6052,14 @@
       ASYNC, ConstructServerDataPacket(
                  2, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
                  header + "hello!"));
-  socket_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(3, 2, 1, 1));
+  socket_data.AddWrite(SYNCHRONOUS,
+                       ConstructClientAckPacket(packet_num++, 2, 1, 1));
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // No more data to read
   socket_data.AddWrite(
-      SYNCHRONOUS, client_maker_.MakeAckAndConnectionClosePacket(
-                       4, false, quic::QuicTime::Delta::FromMilliseconds(0), 2,
-                       1, 1, quic::QUIC_CONNECTION_CANCELLED, "net error", 0));
+      SYNCHRONOUS,
+      client_maker_.MakeAckAndConnectionClosePacket(
+          packet_num++, false, quic::QuicTime::Delta::FromMilliseconds(0), 2, 1,
+          1, quic::QUIC_CONNECTION_CANCELLED, "net error", 0));
 
   socket_data.AddSocketDataToFactory(&socket_factory_);
 
@@ -6084,7 +6076,8 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // No more data to read
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   for (int i = 0; i < 13; ++i) {  // 12 retries then one final failure.
     socket_data.AddWrite(ASYNC, ERR_NO_BUFFER_SPACE);
   }
@@ -6120,7 +6113,8 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // No more data to read
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   for (int i = 0; i < 13; ++i) {  // 12 retries then one final failure.
     socket_data.AddWrite(ASYNC, ERR_NO_BUFFER_SPACE);
   }
@@ -6159,12 +6153,17 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    socket_data.AddWrite(SYNCHRONOUS,
+                         ConstructInitialSettingsPacket(packet_num++));
+  }
   socket_data.AddWrite(SYNCHRONOUS, ERR_MSG_TOO_BIG);
   // Connection close packet will be sent for MSG_TOO_BIG.
   socket_data.AddWrite(
-      SYNCHRONOUS, client_maker_.MakeConnectionClosePacket(
-                       3, true, quic::QUIC_PACKET_WRITE_ERROR, error_details));
+      SYNCHRONOUS,
+      client_maker_.MakeConnectionClosePacket(
+          packet_num + 1, true, quic::QUIC_PACKET_WRITE_ERROR, error_details));
   socket_data.AddSocketDataToFactory(&socket_factory_);
 
   CreateSession();
@@ -6187,8 +6186,10 @@
 
   MockQuicData mock_quic_data(version_);
   uint64_t client_packet_number = 1;
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(client_packet_number++));
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(
+        SYNCHRONOUS, ConstructInitialSettingsPacket(client_packet_number++));
+  }
   mock_quic_data.AddWrite(
       SYNCHRONOUS,
       ConstructClientRequestHeadersPacket(
@@ -6275,8 +6276,10 @@
   MockQuicData mock_quic_data(version_);
   uint64_t client_packet_number = 1;
   // Initial SETTINGS frame.
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(client_packet_number++));
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(
+        SYNCHRONOUS, ConstructInitialSettingsPacket(client_packet_number++));
+  }
   // First request: GET https://mail.example.org/
   mock_quic_data.AddWrite(
       SYNCHRONOUS,
@@ -6363,8 +6366,10 @@
   MockQuicData mock_quic_data(version_);
 
   int write_packet_index = 1;
-  mock_quic_data.AddWrite(SYNCHRONOUS,
-                          ConstructInitialSettingsPacket(write_packet_index++));
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(
+        SYNCHRONOUS, ConstructInitialSettingsPacket(write_packet_index++));
+  }
 
   std::string header = ConstructDataHeader(1);
   if (version_.transport_version != quic::QUIC_VERSION_99) {
@@ -6455,14 +6460,19 @@
       HostPortPair::FromString("mail.example.org:443"));
 
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   spdy::SpdyHeaderBlock headers(GetRequestHeaders("GET", "https", "/"));
   headers["user-agent"] = "";
   headers["accept-encoding"] = "gzip, deflate";
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, std::move(headers)));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          true, std::move(headers)));
 
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
@@ -6480,7 +6490,8 @@
       ASYNC, ConstructServerDataPacket(
                  2, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
                  "Main Resource Data"));
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(3, 2, 1, 1));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 2, 1, 1));
 
   mock_quic_data.AddRead(ASYNC, 0);  // EOF
 
@@ -6526,8 +6537,10 @@
 
   MockQuicData mock_quic_data(version_);
   uint64_t client_packet_number = 1;
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(client_packet_number++));
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(
+        SYNCHRONOUS, ConstructInitialSettingsPacket(client_packet_number++));
+  }
   spdy::SpdyHeaderBlock headers(GetRequestHeaders("GET", "https", "/"));
   headers["user-agent"] = "";
   headers["accept-encoding"] = "gzip, deflate";
@@ -6653,11 +6666,16 @@
   socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
 
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "https", "/")));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -6667,7 +6685,8 @@
       ASYNC, ConstructServerDataPacket(
                  2, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
                  header + "hello!"));
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(3, 2, 1, 1));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 2, 1, 1));
   mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING);  // No more data to read
   mock_quic_data.AddRead(ASYNC, 0);               // EOF
 
@@ -7027,12 +7046,16 @@
       &clock_, origin1_, quic::Perspective::IS_SERVER, false);
 
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS,
-                          ConstructInitialSettingsPacket(1, &client_maker));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(
+                                             packet_num++, &client_maker));
+  }
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       &client_maker));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          &client_maker));
   mock_quic_data.AddRead(
       ASYNC,
       ConstructServerResponseHeadersPacket(
@@ -7041,8 +7064,9 @@
       ASYNC,
       ConstructServerDataPacket(
           2, GetNthClientInitiatedBidirectionalStreamId(0), &server_maker));
-  mock_quic_data.AddWrite(SYNCHRONOUS,
-                          ConstructClientAckPacket(3, 2, 1, 1, &client_maker));
+  mock_quic_data.AddWrite(
+      SYNCHRONOUS,
+      ConstructClientAckPacket(packet_num++, 2, 1, 1, &client_maker));
 
   client_maker.set_hostname(origin2_);
   server_maker.set_hostname(origin2_);
@@ -7050,7 +7074,7 @@
   mock_quic_data.AddWrite(
       SYNCHRONOUS,
       ConstructClientRequestHeadersPacket(
-          4, GetNthClientInitiatedBidirectionalStreamId(1), false,
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(1), false,
           GetNthClientInitiatedBidirectionalStreamId(0), &client_maker));
   mock_quic_data.AddRead(
       ASYNC,
@@ -7060,8 +7084,9 @@
       ASYNC,
       ConstructServerDataPacket(
           4, GetNthClientInitiatedBidirectionalStreamId(1), &server_maker));
-  mock_quic_data.AddWrite(SYNCHRONOUS,
-                          ConstructClientAckPacket(5, 4, 3, 1, &client_maker));
+  mock_quic_data.AddWrite(
+      SYNCHRONOUS,
+      ConstructClientAckPacket(packet_num++, 4, 3, 1, &client_maker));
   mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING);  // No more data to read
   mock_quic_data.AddRead(ASYNC, 0);               // EOF
 
@@ -7124,12 +7149,16 @@
       &clock_, origin1_, quic::Perspective::IS_SERVER, false);
 
   MockQuicData mock_quic_data1(version_);
-  mock_quic_data1.AddWrite(SYNCHRONOUS,
-                           ConstructInitialSettingsPacket(1, &client_maker1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(
+                                              packet_num++, &client_maker1));
+  }
   mock_quic_data1.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       &client_maker1));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          &client_maker1));
   mock_quic_data1.AddRead(
       ASYNC,
       ConstructServerResponseHeadersPacket(
@@ -7139,7 +7168,8 @@
       ConstructServerDataPacket(
           2, GetNthClientInitiatedBidirectionalStreamId(0), &server_maker1));
   mock_quic_data1.AddWrite(
-      SYNCHRONOUS, ConstructClientAckPacket(3, 2, 1, 1, &client_maker1));
+      SYNCHRONOUS,
+      ConstructClientAckPacket(packet_num++, 2, 1, 1, &client_maker1));
   mock_quic_data1.AddRead(ASYNC, ERR_IO_PENDING);  // No more data to read
   mock_quic_data1.AddRead(ASYNC, 0);               // EOF
 
@@ -7154,12 +7184,16 @@
       &clock_, origin2_, quic::Perspective::IS_SERVER, false);
 
   MockQuicData mock_quic_data2(version_);
-  mock_quic_data2.AddWrite(SYNCHRONOUS,
-                           ConstructInitialSettingsPacket(1, &client_maker2));
+  int packet_num2 = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(
+                                              packet_num2++, &client_maker2));
+  }
   mock_quic_data2.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       &client_maker2));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num2++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          &client_maker2));
   mock_quic_data2.AddRead(
       ASYNC,
       ConstructServerResponseHeadersPacket(
@@ -7169,7 +7203,8 @@
       ConstructServerDataPacket(
           2, GetNthClientInitiatedBidirectionalStreamId(0), &server_maker2));
   mock_quic_data2.AddWrite(
-      SYNCHRONOUS, ConstructClientAckPacket(3, 2, 1, 1, &client_maker2));
+      SYNCHRONOUS,
+      ConstructClientAckPacket(packet_num2++, 2, 1, 1, &client_maker2));
   mock_quic_data2.AddRead(ASYNC, ERR_IO_PENDING);  // No more data to read
   mock_quic_data2.AddRead(ASYNC, 0);               // EOF
 
@@ -7189,8 +7224,10 @@
 
   MockQuicData mock_quic_data(version_);
   uint64_t client_packet_number = 1;
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(client_packet_number++));
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(
+        SYNCHRONOUS, ConstructInitialSettingsPacket(client_packet_number++));
+  }
   mock_quic_data.AddWrite(
       SYNCHRONOUS,
       ConstructClientRequestHeadersPacket(
@@ -7314,27 +7351,34 @@
 
   MockQuicData mock_quic_data(version_);
 
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "https", "/")));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          true, GetRequestHeaders("GET", "https", "/")));
 
   mock_quic_data.AddRead(
       ASYNC, ConstructServerPushPromisePacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0),
                  GetNthServerInitiatedUnidirectionalStreamId(0), false,
                  std::move(pushed_request_headers), &server_maker_));
-  mock_quic_data.AddWrite(SYNCHRONOUS,
-                          ConstructClientRstPacket(
-                              3, GetNthServerInitiatedUnidirectionalStreamId(0),
-                              quic::QUIC_INVALID_PROMISE_URL));
+  mock_quic_data.AddWrite(
+      SYNCHRONOUS,
+      ConstructClientRstPacket(packet_num++,
+                               GetNthServerInitiatedUnidirectionalStreamId(0),
+                               quic::QUIC_INVALID_PROMISE_URL));
 
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  2, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
                  GetResponseHeaders("200 OK")));
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(4, 2, 1, 1));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 2, 1, 1));
 
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
@@ -7345,7 +7389,8 @@
       ASYNC, ConstructServerDataPacket(
                  4, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
                  header + "hello!"));
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(5, 4, 3, 1));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 4, 3, 1));
 
   mock_quic_data.AddRead(ASYNC, 0);
   mock_quic_data.AddSocketDataToFactory(&socket_factory_);
@@ -7371,12 +7416,17 @@
       "QUIC proxy.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       false, HttpProxyConnectJob::kH2QuicTunnelPriority,
-                       ConnectRequestHeaders("mail.example.org:443"), 0));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          false, HttpProxyConnectJob::kH2QuicTunnelPriority,
+          ConnectRequestHeaders("mail.example.org:443"), 0));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -7391,14 +7441,14 @@
     mock_quic_data.AddWrite(
         SYNCHRONOUS,
         ConstructClientAckAndDataPacket(
-            3, false, GetNthClientInitiatedBidirectionalStreamId(0), 1, 1, 1,
-            false, quic::QuicStringPiece(get_request)));
+            packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0),
+            1, 1, 1, false, quic::QuicStringPiece(get_request)));
   } else {
     mock_quic_data.AddWrite(
         SYNCHRONOUS,
         ConstructClientAckAndMultipleDataFramesPacket(
-            3, false, GetNthClientInitiatedBidirectionalStreamId(0), 1, 1, 1,
-            false, {header, std::string(get_request)}));
+            packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0),
+            1, 1, 1, false, {header, std::string(get_request)}));
   }
 
   const char get_response[] =
@@ -7414,12 +7464,14 @@
       SYNCHRONOUS, ConstructServerDataPacket(
                        3, GetNthClientInitiatedBidirectionalStreamId(0), false,
                        false, header3 + std::string("0123456789")));
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(4, 3, 2, 1));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 3, 2, 1));
   mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // No more data to read
 
   mock_quic_data.AddWrite(
       SYNCHRONOUS,
-      ConstructClientRstPacket(5, GetNthClientInitiatedBidirectionalStreamId(0),
+      ConstructClientRstPacket(packet_num++,
+                               GetNthClientInitiatedBidirectionalStreamId(0),
                                quic::QUIC_STREAM_CANCELLED));
 
   mock_quic_data.AddSocketDataToFactory(&socket_factory_);
@@ -7459,12 +7511,17 @@
       "QUIC proxy.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       false, HttpProxyConnectJob::kH2QuicTunnelPriority,
-                       ConnectRequestHeaders("mail.example.org:443"), 0));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          false, HttpProxyConnectJob::kH2QuicTunnelPriority,
+          ConnectRequestHeaders("mail.example.org:443"), 0));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -7479,14 +7536,16 @@
     mock_quic_data.AddWrite(
         SYNCHRONOUS,
         ConstructClientAckAndDataPacket(
-            3, false, GetNthClientInitiatedBidirectionalStreamId(0), 1, 1, 1,
-            false, quic::QuicStringPiece(get_frame.data(), get_frame.size())));
+            packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0),
+            1, 1, 1, false,
+            quic::QuicStringPiece(get_frame.data(), get_frame.size())));
   } else {
     mock_quic_data.AddWrite(
         SYNCHRONOUS,
         ConstructClientAckAndMultipleDataFramesPacket(
-            3, false, GetNthClientInitiatedBidirectionalStreamId(0), 1, 1, 1,
-            false, {header, std::string(get_frame.data(), get_frame.size())}));
+            packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0),
+            1, 1, 1, false,
+            {header, std::string(get_frame.data(), get_frame.size())}));
   }
   spdy::SpdySerializedFrame resp_frame =
       spdy_util.ConstructSpdyGetReply(nullptr, 0, 1);
@@ -7504,12 +7563,14 @@
       ConstructServerDataPacket(
           3, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
           header3 + std::string(data_frame.data(), data_frame.size())));
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(4, 3, 2, 1));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 3, 2, 1));
   mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // No more data to read
 
   mock_quic_data.AddWrite(
       SYNCHRONOUS,
-      ConstructClientRstPacket(5, GetNthClientInitiatedBidirectionalStreamId(0),
+      ConstructClientRstPacket(packet_num++,
+                               GetNthClientInitiatedBidirectionalStreamId(0),
                                quic::QUIC_STREAM_CANCELLED));
 
   mock_quic_data.AddSocketDataToFactory(&socket_factory_);
@@ -7552,8 +7613,10 @@
 
   MockQuicData mock_quic_data(version_);
   int write_packet_index = 1;
-  mock_quic_data.AddWrite(SYNCHRONOUS,
-                          ConstructInitialSettingsPacket(write_packet_index++));
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(
+        SYNCHRONOUS, ConstructInitialSettingsPacket(write_packet_index++));
+  }
   mock_quic_data.AddWrite(
       SYNCHRONOUS,
       ConstructClientRequestHeadersPacket(
@@ -7702,14 +7765,19 @@
       "QUIC proxy.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
 
   // CONNECT request and response for first request
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       false, HttpProxyConnectJob::kH2QuicTunnelPriority,
-                       ConnectRequestHeaders("mail.example.org:443"), 0));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          false, HttpProxyConnectJob::kH2QuicTunnelPriority,
+          ConnectRequestHeaders("mail.example.org:443"), 0));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -7725,14 +7793,14 @@
     mock_quic_data.AddWrite(
         SYNCHRONOUS,
         ConstructClientAckAndDataPacket(
-            3, false, GetNthClientInitiatedBidirectionalStreamId(0), 1, 1, 1,
-            false, quic::QuicStringPiece(get_request)));
+            packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0),
+            1, 1, 1, false, quic::QuicStringPiece(get_request)));
   } else {
     mock_quic_data.AddWrite(
         SYNCHRONOUS,
         ConstructClientAckAndMultipleDataFramesPacket(
-            3, false, GetNthClientInitiatedBidirectionalStreamId(0), 1, 1, 1,
-            false, {header, std::string(get_request)}));
+            packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0),
+            1, 1, 1, false, {header, std::string(get_request)}));
   }
 
   const char get_response[] =
@@ -7748,15 +7816,17 @@
       SYNCHRONOUS, ConstructServerDataPacket(
                        3, GetNthClientInitiatedBidirectionalStreamId(0), false,
                        false, header3 + std::string("0123456789")));
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(4, 3, 2, 1));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 3, 2, 1));
 
   // CONNECT request and response for second request
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       5, GetNthClientInitiatedBidirectionalStreamId(1), false,
-                       false, HttpProxyConnectJob::kH2QuicTunnelPriority,
-                       ConnectRequestHeaders("different.example.org:443"),
-                       GetNthClientInitiatedBidirectionalStreamId(0)));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(1), false,
+          false, HttpProxyConnectJob::kH2QuicTunnelPriority,
+          ConnectRequestHeaders("different.example.org:443"),
+          GetNthClientInitiatedBidirectionalStreamId(0)));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  4, GetNthClientInitiatedBidirectionalStreamId(1), false, false,
@@ -7771,14 +7841,16 @@
     mock_quic_data.AddWrite(
         SYNCHRONOUS,
         ConstructClientAckAndDataPacket(
-            6, false, GetNthClientInitiatedBidirectionalStreamId(1), 4, 4, 1,
-            false, quic::QuicStringPiece(get_frame.data(), get_frame.size())));
+            packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(1),
+            4, 4, 1, false,
+            quic::QuicStringPiece(get_frame.data(), get_frame.size())));
   } else {
     mock_quic_data.AddWrite(
         SYNCHRONOUS,
         ConstructClientAckAndMultipleDataFramesPacket(
-            6, false, GetNthClientInitiatedBidirectionalStreamId(1), 4, 4, 1,
-            false, {header4, std::string(get_frame.data(), get_frame.size())}));
+            packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(1),
+            4, 4, 1, false,
+            {header4, std::string(get_frame.data(), get_frame.size())}));
   }
 
   spdy::SpdySerializedFrame resp_frame =
@@ -7797,16 +7869,19 @@
                  6, GetNthClientInitiatedBidirectionalStreamId(1), false, false,
                  header6 + std::string(data_frame.data(), data_frame.size())));
 
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(7, 6, 5, 1));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 6, 5, 1));
   mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // No more data to read
 
   mock_quic_data.AddWrite(
       SYNCHRONOUS,
-      ConstructClientRstPacket(8, GetNthClientInitiatedBidirectionalStreamId(0),
+      ConstructClientRstPacket(packet_num++,
+                               GetNthClientInitiatedBidirectionalStreamId(0),
                                quic::QUIC_STREAM_CANCELLED));
   mock_quic_data.AddWrite(
       SYNCHRONOUS,
-      ConstructClientRstPacket(9, GetNthClientInitiatedBidirectionalStreamId(1),
+      ConstructClientRstPacket(packet_num++,
+                               GetNthClientInitiatedBidirectionalStreamId(1),
                                quic::QUIC_STREAM_CANCELLED));
 
   mock_quic_data.AddSocketDataToFactory(&socket_factory_);
@@ -7862,21 +7937,27 @@
       "QUIC proxy.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       false, HttpProxyConnectJob::kH2QuicTunnelPriority,
-                       ConnectRequestHeaders("mail.example.org:443"), 0));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          false, HttpProxyConnectJob::kH2QuicTunnelPriority,
+          ConnectRequestHeaders("mail.example.org:443"), 0));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
                  GetResponseHeaders("500")));
   mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // No more data to read
-  mock_quic_data.AddWrite(SYNCHRONOUS,
-                          ConstructClientAckAndRstPacket(
-                              3, GetNthClientInitiatedBidirectionalStreamId(0),
-                              quic::QUIC_STREAM_CANCELLED, 1, 1, 1));
+  mock_quic_data.AddWrite(
+      SYNCHRONOUS,
+      ConstructClientAckAndRstPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0),
+          quic::QUIC_STREAM_CANCELLED, 1, 1, 1));
 
   mock_quic_data.AddSocketDataToFactory(&socket_factory_);
 
@@ -7908,12 +7989,17 @@
       "QUIC proxy.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       false, HttpProxyConnectJob::kH2QuicTunnelPriority,
-                       ConnectRequestHeaders("mail.example.org:443"), 0));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          false, HttpProxyConnectJob::kH2QuicTunnelPriority,
+          ConnectRequestHeaders("mail.example.org:443"), 0));
   mock_quic_data.AddRead(ASYNC, ERR_CONNECTION_FAILED);
 
   mock_quic_data.AddSocketDataToFactory(&socket_factory_);
@@ -7944,27 +8030,34 @@
       "QUIC proxy.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       false, HttpProxyConnectJob::kH2QuicTunnelPriority,
-                       ConnectRequestHeaders("mail.example.org:443"), 0));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          false, HttpProxyConnectJob::kH2QuicTunnelPriority,
+          ConnectRequestHeaders("mail.example.org:443"), 0));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
                  GetResponseHeaders("200 OK")));
-  mock_quic_data.AddWrite(SYNCHRONOUS,
-                          ConstructClientAckAndRstPacket(
-                              3, GetNthClientInitiatedBidirectionalStreamId(0),
-                              quic::QUIC_STREAM_CANCELLED, 1, 1, 1));
+  mock_quic_data.AddWrite(
+      SYNCHRONOUS,
+      ConstructClientAckAndRstPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0),
+          quic::QUIC_STREAM_CANCELLED, 1, 1, 1));
 
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       4, GetNthClientInitiatedBidirectionalStreamId(1), false,
-                       false, HttpProxyConnectJob::kH2QuicTunnelPriority,
-                       ConnectRequestHeaders("mail.example.org:443"),
-                       GetNthClientInitiatedBidirectionalStreamId(0)));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(1), false,
+          false, HttpProxyConnectJob::kH2QuicTunnelPriority,
+          ConnectRequestHeaders("mail.example.org:443"),
+          GetNthClientInitiatedBidirectionalStreamId(0)));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  2, GetNthClientInitiatedBidirectionalStreamId(1), false, false,
@@ -7979,14 +8072,14 @@
     mock_quic_data.AddWrite(
         SYNCHRONOUS,
         ConstructClientAckAndDataPacket(
-            5, false, GetNthClientInitiatedBidirectionalStreamId(1), 2, 2, 1,
-            false, quic::QuicStringPiece(get_request)));
+            packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(1),
+            2, 2, 1, false, quic::QuicStringPiece(get_request)));
   } else {
     mock_quic_data.AddWrite(
         SYNCHRONOUS,
         ConstructClientAckAndMultipleDataFramesPacket(
-            5, false, GetNthClientInitiatedBidirectionalStreamId(1), 2, 2, 1,
-            false, {header, std::string(get_request)}));
+            packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(1),
+            2, 2, 1, false, {header, std::string(get_request)}));
   }
   const char get_response[] =
       "HTTP/1.1 200 OK\r\n"
@@ -8002,12 +8095,14 @@
       SYNCHRONOUS, ConstructServerDataPacket(
                        4, GetNthClientInitiatedBidirectionalStreamId(1), false,
                        false, header3 + std::string("0123456789")));
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(6, 4, 3, 1));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 4, 3, 1));
   mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // No more data to read
 
   mock_quic_data.AddWrite(
       SYNCHRONOUS,
-      ConstructClientRstPacket(7, GetNthClientInitiatedBidirectionalStreamId(1),
+      ConstructClientRstPacket(packet_num++,
+                               GetNthClientInitiatedBidirectionalStreamId(1),
                                quic::QUIC_STREAM_CANCELLED));
 
   mock_quic_data.AddSocketDataToFactory(&socket_factory_);
@@ -8061,15 +8156,20 @@
       "QUIC proxy.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
 
   spdy::SpdyHeaderBlock headers = ConnectRequestHeaders("mail.example.org:443");
   headers["user-agent"] = kConfiguredUserAgent;
   mock_quic_data.AddWrite(
       SYNCHRONOUS,
       ConstructClientRequestHeadersPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, false,
-          HttpProxyConnectJob::kH2QuicTunnelPriority, std::move(headers), 0));
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          false, HttpProxyConnectJob::kH2QuicTunnelPriority, std::move(headers),
+          0));
   // Return an error, so the transaction stops here (this test isn't interested
   // in the rest).
   mock_quic_data.AddRead(ASYNC, ERR_CONNECTION_FAILED);
@@ -8109,12 +8209,17 @@
   const RequestPriority request_priority = MEDIUM;
 
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       false, HttpProxyConnectJob::kH2QuicTunnelPriority,
-                       ConnectRequestHeaders("mail.example.org:443"), 0));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+          false, HttpProxyConnectJob::kH2QuicTunnelPriority,
+          ConnectRequestHeaders("mail.example.org:443"), 0));
   // Return an error, so the transaction stops here (this test isn't interested
   // in the rest).
   mock_quic_data.AddRead(ASYNC, ERR_CONNECTION_FAILED);
@@ -8146,8 +8251,16 @@
   const RequestPriority kRequestPriority2 = LOWEST;
 
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(ASYNC, ConstructInitialSettingsPacket(1));
-  mock_quic_data.AddWrite(SYNCHRONOUS, ERR_FAILED);
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(ASYNC, ConstructInitialSettingsPacket(1));
+    mock_quic_data.AddWrite(SYNCHRONOUS, ERR_FAILED);
+  } else {
+    mock_quic_data.AddWrite(
+        SYNCHRONOUS, ConstructClientRequestHeadersPacket(
+                         1, GetNthClientInitiatedBidirectionalStreamId(0), true,
+                         false, HttpProxyConnectJob::kH2QuicTunnelPriority,
+                         ConnectRequestHeaders("mail.example.org:443"), 0));
+  }
   // This should never be reached.
   mock_quic_data.AddRead(ASYNC, ERR_CONNECTION_FAILED);
   mock_quic_data.AddSocketDataToFactory(&socket_factory_);
@@ -8228,13 +8341,17 @@
     MockQuicData mock_quic_data(version_);
     quic::QuicStreamOffset server_data_offset = 0;
 
-    mock_quic_data.AddWrite(SYNCHRONOUS,
-                            client_maker->MakeInitialSettingsPacket(1));
+    int packet_num = 1;
+    if (VersionUsesQpack(version_.transport_version)) {
+      mock_quic_data.AddWrite(
+          SYNCHRONOUS, client_maker->MakeInitialSettingsPacket(packet_num++));
+    }
 
     mock_quic_data.AddWrite(
         SYNCHRONOUS,
         client_maker->MakeRequestHeadersPacket(
-            2, GetNthClientInitiatedBidirectionalStreamId(0), true, false,
+            packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+            false,
             ConvertRequestPriorityToQuicPriority(
                 HttpProxyConnectJob::kH2QuicTunnelPriority),
             client_maker->ConnectRequestHeaders("mail.example.org:443"), 0,
@@ -8262,13 +8379,13 @@
     }
     server_data_offset += 10;
 
-    mock_quic_data.AddWrite(SYNCHRONOUS,
-                            client_maker->MakeAckPacket(3, 2, 1, 1, true));
+    mock_quic_data.AddWrite(
+        SYNCHRONOUS, client_maker->MakeAckPacket(packet_num++, 2, 1, 1, true));
 
     mock_quic_data.AddWrite(
         SYNCHRONOUS,
         client_maker->MakeRstPacket(
-            4, false, GetNthClientInitiatedBidirectionalStreamId(0),
+            packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0),
             quic::QUIC_STREAM_CANCELLED,
             /*include_stop_sending_if_v99=*/true));
 
@@ -8277,7 +8394,8 @@
     mock_quic_data.AddWrite(
         SYNCHRONOUS,
         client_maker->MakeRequestHeadersPacket(
-            5, GetNthClientInitiatedBidirectionalStreamId(1), false, false,
+            packet_num++, GetNthClientInitiatedBidirectionalStreamId(1), false,
+            false,
             ConvertRequestPriorityToQuicPriority(
                 HttpProxyConnectJob::kH2QuicTunnelPriority),
             std::move(headers), GetNthClientInitiatedBidirectionalStreamId(0),
@@ -8298,7 +8416,7 @@
     mock_quic_data.AddWrite(
         SYNCHRONOUS,
         client_maker->MakeAckAndRstPacket(
-            6, false, GetNthClientInitiatedBidirectionalStreamId(1),
+            packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(1),
             quic::QUIC_STREAM_CANCELLED, 3, 3, 1, true));
 
     mock_quic_data.AddSocketDataToFactory(&socket_factory_);
@@ -8396,22 +8514,26 @@
       GetNthServerInitiatedUnidirectionalStreamId(1);
 
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+  }
 
   // Client sends "GET" requests for "/0.png", "/1.png", "/2.png".
-  mock_quic_data.AddWrite(SYNCHRONOUS,
-                          ConstructClientRequestHeadersPacket(
-                              2, client_stream_0, true, true, HIGHEST,
-                              GetRequestHeaders("GET", "https", "/0.jpg"), 0));
+  mock_quic_data.AddWrite(
+      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
+                       packet_num++, client_stream_0, true, true, HIGHEST,
+                       GetRequestHeaders("GET", "https", "/0.jpg"), 0));
   mock_quic_data.AddWrite(
       SYNCHRONOUS,
       ConstructClientRequestHeadersPacket(
-          3, client_stream_1, true, true, MEDIUM,
+          packet_num++, client_stream_1, true, true, MEDIUM,
           GetRequestHeaders("GET", "https", "/1.jpg"), client_stream_0));
   mock_quic_data.AddWrite(
       SYNCHRONOUS,
       ConstructClientRequestHeadersPacket(
-          4, client_stream_2, true, true, MEDIUM,
+          packet_num++, client_stream_2, true, true, MEDIUM,
           GetRequestHeaders("GET", "https", "/2.jpg"), client_stream_1));
 
   // Server replies "OK" for the three requests.
@@ -8421,7 +8543,8 @@
   mock_quic_data.AddRead(ASYNC, ConstructServerResponseHeadersPacket(
                                     2, client_stream_1, false, false,
                                     GetResponseHeaders("200 OK")));
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(5, 2, 1, 1));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 2, 1, 1));
   mock_quic_data.AddRead(ASYNC, ConstructServerResponseHeadersPacket(
                                     3, client_stream_2, false, false,
                                     GetResponseHeaders("200 OK")));
@@ -8437,7 +8560,7 @@
   mock_quic_data.AddWrite(
       SYNCHRONOUS,
       ConstructClientAckAndPriorityFramesPacket(
-          6, false, 4, 3, 1,
+          packet_num++, false, 4, 3, 1,
           {{push_stream_0, client_stream_2,
             ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY)}}));
   mock_quic_data.AddRead(
@@ -8446,14 +8569,15 @@
           5, client_stream_0, push_stream_1, false,
           GetRequestHeaders("GET", "https", "/pushed_1.jpg"), &server_maker_));
   mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientPriorityPacket(
-                                           7, false, push_stream_1,
+                                           packet_num++, false, push_stream_1,
                                            push_stream_0, DEFAULT_PRIORITY));
 
   // Server sends the response headers for the two push promises.
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  6, push_stream_0, false, false, GetResponseHeaders("200 OK")));
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(8, 6, 5, 1));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 6, 5, 1));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  7, push_stream_1, false, false, GetResponseHeaders("200 OK")));
@@ -8464,7 +8588,7 @@
   mock_quic_data.AddWrite(
       SYNCHRONOUS,
       ConstructClientAckAndPriorityFramesPacket(
-          9, false, 7, 7, 1,
+          packet_num++, false, 7, 7, 1,
           {{push_stream_1, client_stream_2,
             ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY)},
            {push_stream_0, client_stream_0,
@@ -8478,7 +8602,8 @@
   mock_quic_data.AddRead(
       SYNCHRONOUS, ConstructServerDataPacket(9, client_stream_1, false, true,
                                              header + "hello 1!"));
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(10, 9, 8, 1));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 9, 8, 1));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerDataPacket(10, client_stream_2, false, true,
                                        header + "hello 2!"));
@@ -8486,7 +8611,8 @@
   mock_quic_data.AddRead(
       SYNCHRONOUS, ConstructServerDataPacket(11, push_stream_0, false, true,
                                              header2 + "and hello 0!"));
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(11, 11, 10, 1));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructClientAckPacket(packet_num++, 11, 10, 1));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerDataPacket(12, push_stream_1, false, true,
                                        header2 + "and hello 1!"));
@@ -8616,14 +8742,17 @@
           quic::QuicUtils::CreateRandomConnectionId(&random_generator_),
           &clock_, kDefaultServerHostName, quic::Perspective::IS_SERVER, false);
 
-      unpartitioned_mock_quic_data.AddWrite(
-          SYNCHRONOUS, client_maker1.MakeInitialSettingsPacket(1));
+      int packet_num = 1;
+      if (VersionUsesQpack(version_.transport_version)) {
+        unpartitioned_mock_quic_data.AddWrite(
+            SYNCHRONOUS, client_maker1.MakeInitialSettingsPacket(packet_num++));
+      }
 
       unpartitioned_mock_quic_data.AddWrite(
           SYNCHRONOUS,
           client_maker1.MakeRequestHeadersPacket(
-              2, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-              ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY),
+              packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+              true, ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY),
               GetRequestHeaders("GET", url1.scheme(), "/1"), 0, nullptr));
       unpartitioned_mock_quic_data.AddRead(
           ASYNC, server_maker1.MakeResponseHeadersPacket(
@@ -8634,12 +8763,13 @@
                      2, GetNthClientInitiatedBidirectionalStreamId(0), false,
                      true, ConstructDataHeader(1) + "1"));
       unpartitioned_mock_quic_data.AddWrite(
-          SYNCHRONOUS, ConstructClientAckPacket(3, 2, 1, 1));
+          SYNCHRONOUS, ConstructClientAckPacket(packet_num++, 2, 1, 1));
 
       unpartitioned_mock_quic_data.AddWrite(
           SYNCHRONOUS,
           client_maker1.MakeRequestHeadersPacket(
-              4, GetNthClientInitiatedBidirectionalStreamId(1), false, true,
+              packet_num++, GetNthClientInitiatedBidirectionalStreamId(1),
+              false, true,
               ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY),
               GetRequestHeaders("GET", url2.scheme(), "/2"), 0, nullptr));
       unpartitioned_mock_quic_data.AddRead(
@@ -8651,12 +8781,14 @@
                      4, GetNthClientInitiatedBidirectionalStreamId(1), false,
                      true, ConstructDataHeader(1) + "2"));
       unpartitioned_mock_quic_data.AddWrite(
-          SYNCHRONOUS, ConstructClientAckAndConnectionClosePacket(5, 4, 3, 1));
+          SYNCHRONOUS,
+          ConstructClientAckAndConnectionClosePacket(packet_num++, 4, 3, 1));
 
       unpartitioned_mock_quic_data.AddWrite(
           SYNCHRONOUS,
           client_maker1.MakeRequestHeadersPacket(
-              6, GetNthClientInitiatedBidirectionalStreamId(2), false, true,
+              packet_num++, GetNthClientInitiatedBidirectionalStreamId(2),
+              false, true,
               ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY),
               GetRequestHeaders("GET", url3.scheme(), "/3"), 0, nullptr));
       unpartitioned_mock_quic_data.AddRead(
@@ -8668,7 +8800,8 @@
                      6, GetNthClientInitiatedBidirectionalStreamId(2), false,
                      true, ConstructDataHeader(1) + "3"));
       unpartitioned_mock_quic_data.AddWrite(
-          SYNCHRONOUS, ConstructClientAckAndConnectionClosePacket(7, 6, 5, 1));
+          SYNCHRONOUS,
+          ConstructClientAckAndConnectionClosePacket(packet_num++, 6, 5, 1));
 
       unpartitioned_mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
 
@@ -8685,13 +8818,18 @@
           quic::QuicUtils::CreateRandomConnectionId(&random_generator_),
           &clock_, kDefaultServerHostName, quic::Perspective::IS_SERVER, false);
 
-      partitioned_mock_quic_data1.AddWrite(
-          SYNCHRONOUS, client_maker2.MakeInitialSettingsPacket(1));
+      int packet_num2 = 1;
+      if (VersionUsesQpack(version_.transport_version)) {
+        partitioned_mock_quic_data1.AddWrite(
+            SYNCHRONOUS,
+            client_maker2.MakeInitialSettingsPacket(packet_num2++));
+      }
 
       partitioned_mock_quic_data1.AddWrite(
           SYNCHRONOUS,
           client_maker2.MakeRequestHeadersPacket(
-              2, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
+              packet_num2++, GetNthClientInitiatedBidirectionalStreamId(0),
+              true, true,
               ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY),
               GetRequestHeaders("GET", url1.scheme(), "/1"), 0, nullptr));
       partitioned_mock_quic_data1.AddRead(
@@ -8703,12 +8841,14 @@
                      2, GetNthClientInitiatedBidirectionalStreamId(0), false,
                      true, ConstructDataHeader(1) + "1"));
       partitioned_mock_quic_data1.AddWrite(
-          SYNCHRONOUS, client_maker2.MakeAckPacket(3, 2, 1, 1, true));
+          SYNCHRONOUS,
+          client_maker2.MakeAckPacket(packet_num2++, 2, 1, 1, true));
 
       partitioned_mock_quic_data1.AddWrite(
           SYNCHRONOUS,
           client_maker2.MakeRequestHeadersPacket(
-              4, GetNthClientInitiatedBidirectionalStreamId(1), false, true,
+              packet_num2++, GetNthClientInitiatedBidirectionalStreamId(1),
+              false, true,
               ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY),
               GetRequestHeaders("GET", url3.scheme(), "/3"), 0, nullptr));
       partitioned_mock_quic_data1.AddRead(
@@ -8720,7 +8860,8 @@
                      4, GetNthClientInitiatedBidirectionalStreamId(1), false,
                      true, ConstructDataHeader(1) + "3"));
       partitioned_mock_quic_data1.AddWrite(
-          SYNCHRONOUS, client_maker2.MakeAckPacket(5, 4, 3, 1, true));
+          SYNCHRONOUS,
+          client_maker2.MakeAckPacket(packet_num2++, 4, 3, 1, true));
 
       partitioned_mock_quic_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
 
@@ -8735,13 +8876,18 @@
           quic::QuicUtils::CreateRandomConnectionId(&random_generator_),
           &clock_, kDefaultServerHostName, quic::Perspective::IS_SERVER, false);
 
-      partitioned_mock_quic_data2.AddWrite(
-          SYNCHRONOUS, client_maker3.MakeInitialSettingsPacket(1));
+      int packet_num3 = 1;
+      if (VersionUsesQpack(version_.transport_version)) {
+        partitioned_mock_quic_data2.AddWrite(
+            SYNCHRONOUS,
+            client_maker3.MakeInitialSettingsPacket(packet_num3++));
+      }
 
       partitioned_mock_quic_data2.AddWrite(
           SYNCHRONOUS,
           client_maker3.MakeRequestHeadersPacket(
-              2, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
+              packet_num3++, GetNthClientInitiatedBidirectionalStreamId(0),
+              true, true,
               ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY),
               GetRequestHeaders("GET", url2.scheme(), "/2"), 0, nullptr));
       partitioned_mock_quic_data2.AddRead(
@@ -8753,7 +8899,8 @@
                      2, GetNthClientInitiatedBidirectionalStreamId(0), false,
                      true, ConstructDataHeader(1) + "2"));
       partitioned_mock_quic_data2.AddWrite(
-          SYNCHRONOUS, client_maker3.MakeAckPacket(3, 2, 1, 1, true));
+          SYNCHRONOUS,
+          client_maker3.MakeAckPacket(packet_num3++, 2, 1, 1, true));
 
       partitioned_mock_quic_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
 
@@ -8853,13 +9000,17 @@
         version_, quic::QuicUtils::CreateRandomConnectionId(&random_generator_),
         &clock_, kDefaultServerHostName, quic::Perspective::IS_SERVER, false);
 
-    mock_quic_data[index]->AddWrite(SYNCHRONOUS,
-                                    client_maker.MakeInitialSettingsPacket(1));
+    int packet_num = 1;
+    if (VersionUsesQpack(version_.transport_version)) {
+      mock_quic_data[index]->AddWrite(
+          SYNCHRONOUS, client_maker.MakeInitialSettingsPacket(packet_num++));
+    }
 
     mock_quic_data[index]->AddWrite(
         SYNCHRONOUS,
         client_maker.MakeRequestHeadersPacket(
-            2, GetNthClientInitiatedBidirectionalStreamId(0), true, false,
+            packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+            false,
             ConvertRequestPriorityToQuicPriority(
                 HttpProxyConnectJob::kH2QuicTunnelPriority),
             ConnectRequestHeaders("mail.example.org:443"), 0, nullptr));
@@ -8871,16 +9022,16 @@
     std::string header = ConstructDataHeader(strlen(kGetRequest));
     if (version_.transport_version != quic::QUIC_VERSION_99) {
       mock_quic_data[index]->AddWrite(
-          SYNCHRONOUS,
-          client_maker.MakeAckAndDataPacket(
-              3, false, GetNthClientInitiatedBidirectionalStreamId(0), 1, 1, 1,
-              false, quic::QuicStringPiece(kGetRequest)));
+          SYNCHRONOUS, client_maker.MakeAckAndDataPacket(
+                           packet_num++, false,
+                           GetNthClientInitiatedBidirectionalStreamId(0), 1, 1,
+                           1, false, quic::QuicStringPiece(kGetRequest)));
     } else {
       mock_quic_data[index]->AddWrite(
-          SYNCHRONOUS,
-          client_maker.MakeAckAndMultipleDataFramesPacket(
-              3, false, GetNthClientInitiatedBidirectionalStreamId(0), 1, 1, 1,
-              false, {header, std::string(kGetRequest)}));
+          SYNCHRONOUS, client_maker.MakeAckAndMultipleDataFramesPacket(
+                           packet_num++, false,
+                           GetNthClientInitiatedBidirectionalStreamId(0), 1, 1,
+                           1, false, {header, std::string(kGetRequest)}));
     }
 
     std::string header2 = ConstructDataHeader(strlen(kGetResponse));
@@ -8894,7 +9045,7 @@
             3, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
             ConstructDataHeader(10) + std::string("0123456789")));
     mock_quic_data[index]->AddWrite(
-        SYNCHRONOUS, client_maker.MakeAckPacket(4, 3, 2, 1, true));
+        SYNCHRONOUS, client_maker.MakeAckPacket(packet_num++, 3, 2, 1, true));
     mock_quic_data[index]->AddRead(SYNCHRONOUS,
                                    ERR_IO_PENDING);  // No more data to read
 
diff --git a/net/quic/quic_proxy_client_socket_unittest.cc b/net/quic/quic_proxy_client_socket_unittest.cc
index 94f5439..dc6bf4e 100644
--- a/net/quic/quic_proxy_client_socket_unittest.cc
+++ b/net/quic/quic_proxy_client_socket_unittest.cc
@@ -583,13 +583,18 @@
 };
 
 TEST_P(QuicProxyClientSocketTest, ConnectSendsCorrectRequest) {
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructSettingsPacket(1));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructConnectRequestPacket(2));
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data_.AddWrite(SYNCHRONOUS,
+                             ConstructSettingsPacket(packet_number++));
+  }
+  mock_quic_data_.AddWrite(SYNCHRONOUS,
+                           ConstructConnectRequestPacket(packet_number++));
   mock_quic_data_.AddRead(ASYNC, ConstructServerConnectReplyPacket(1, !kFin));
   mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   mock_quic_data_.AddWrite(
-      SYNCHRONOUS,
-      ConstructAckAndRstPacket(3, quic::QUIC_STREAM_CANCELLED, 1, 1, 1));
+      SYNCHRONOUS, ConstructAckAndRstPacket(
+                       packet_number++, quic::QUIC_STREAM_CANCELLED, 1, 1, 1));
 
   Initialize();
 
@@ -603,14 +608,19 @@
 }
 
 TEST_P(QuicProxyClientSocketTest, ConnectWithAuthRequested) {
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructSettingsPacket(1));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructConnectRequestPacket(2));
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data_.AddWrite(SYNCHRONOUS,
+                             ConstructSettingsPacket(packet_number++));
+  }
+  mock_quic_data_.AddWrite(SYNCHRONOUS,
+                           ConstructConnectRequestPacket(packet_number++));
   mock_quic_data_.AddRead(ASYNC,
                           ConstructServerConnectAuthReplyPacket(1, !kFin));
   mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   mock_quic_data_.AddWrite(
-      SYNCHRONOUS,
-      ConstructAckAndRstPacket(3, quic::QUIC_STREAM_CANCELLED, 1, 1, 1));
+      SYNCHRONOUS, ConstructAckAndRstPacket(
+                       packet_number++, quic::QUIC_STREAM_CANCELLED, 1, 1, 1));
 
   Initialize();
 
@@ -622,13 +632,18 @@
 }
 
 TEST_P(QuicProxyClientSocketTest, ConnectWithAuthCredentials) {
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructSettingsPacket(1));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructConnectAuthRequestPacket(2));
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data_.AddWrite(SYNCHRONOUS,
+                             ConstructSettingsPacket(packet_number++));
+  }
+  mock_quic_data_.AddWrite(SYNCHRONOUS,
+                           ConstructConnectAuthRequestPacket(packet_number++));
   mock_quic_data_.AddRead(ASYNC, ConstructServerConnectReplyPacket(1, !kFin));
   mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   mock_quic_data_.AddWrite(
-      SYNCHRONOUS,
-      ConstructAckAndRstPacket(3, quic::QUIC_STREAM_CANCELLED, 1, 1, 1));
+      SYNCHRONOUS, ConstructAckAndRstPacket(
+                       packet_number++, quic::QUIC_STREAM_CANCELLED, 1, 1, 1));
 
   Initialize();
 
@@ -648,14 +663,19 @@
 
 // Tests that a redirect response from a CONNECT fails.
 TEST_P(QuicProxyClientSocketTest, ConnectRedirects) {
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructSettingsPacket(1));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructConnectRequestPacket(2));
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data_.AddWrite(SYNCHRONOUS,
+                             ConstructSettingsPacket(packet_number++));
+  }
+  mock_quic_data_.AddWrite(SYNCHRONOUS,
+                           ConstructConnectRequestPacket(packet_number++));
   mock_quic_data_.AddRead(ASYNC,
                           ConstructServerConnectRedirectReplyPacket(1, !kFin));
   mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   mock_quic_data_.AddWrite(
-      SYNCHRONOUS,
-      ConstructAckAndRstPacket(3, quic::QUIC_STREAM_CANCELLED, 1, 1, 1));
+      SYNCHRONOUS, ConstructAckAndRstPacket(
+                       packet_number++, quic::QUIC_STREAM_CANCELLED, 1, 1, 1));
 
   Initialize();
 
@@ -674,8 +694,13 @@
 }
 
 TEST_P(QuicProxyClientSocketTest, ConnectFails) {
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructSettingsPacket(1));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructConnectRequestPacket(2));
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data_.AddWrite(SYNCHRONOUS,
+                             ConstructSettingsPacket(packet_number++));
+  }
+  mock_quic_data_.AddWrite(SYNCHRONOUS,
+                           ConstructConnectRequestPacket(packet_number++));
   mock_quic_data_.AddRead(ASYNC, 0);  // EOF
 
   Initialize();
@@ -688,17 +713,23 @@
 }
 
 TEST_P(QuicProxyClientSocketTest, WasEverUsedReturnsCorrectValue) {
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructSettingsPacket(1));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructConnectRequestPacket(2));
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data_.AddWrite(SYNCHRONOUS,
+                             ConstructSettingsPacket(packet_number++));
+  }
+  mock_quic_data_.AddWrite(SYNCHRONOUS,
+                           ConstructConnectRequestPacket(packet_number++));
   mock_quic_data_.AddRead(ASYNC, ConstructServerConnectReplyPacket(1, !kFin));
   mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   mock_quic_data_.AddWrite(
-      SYNCHRONOUS,
-      ConstructAckAndRstPacket(3, quic::QUIC_STREAM_CANCELLED, 1, 1, 1));
+      SYNCHRONOUS, ConstructAckAndRstPacket(
+                       packet_number++, quic::QUIC_STREAM_CANCELLED, 1, 1, 1));
 
   Initialize();
 
-  EXPECT_TRUE(sock_->WasEverUsed());  // Used due to crypto handshake
+  if (VersionUsesQpack(version_.transport_version))
+    EXPECT_TRUE(sock_->WasEverUsed());  // Used due to crypto handshake
   AssertConnectSucceeds();
   EXPECT_TRUE(sock_->WasEverUsed());
   sock_->Disconnect();
@@ -706,8 +737,13 @@
 }
 
 TEST_P(QuicProxyClientSocketTest, GetPeerAddressReturnsCorrectValues) {
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructSettingsPacket(1));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructConnectRequestPacket(2));
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data_.AddWrite(SYNCHRONOUS,
+                             ConstructSettingsPacket(packet_number++));
+  }
+  mock_quic_data_.AddWrite(SYNCHRONOUS,
+                           ConstructConnectRequestPacket(packet_number++));
   mock_quic_data_.AddRead(ASYNC, ConstructServerConnectReplyPacket(1, !kFin));
   mock_quic_data_.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
   mock_quic_data_.AddRead(ASYNC, 0);               // EOF
@@ -732,18 +768,25 @@
 }
 
 TEST_P(QuicProxyClientSocketTest, IsConnectedAndIdle) {
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructSettingsPacket(1));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructConnectRequestPacket(2));
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data_.AddWrite(SYNCHRONOUS,
+                             ConstructSettingsPacket(packet_number++));
+  }
+  mock_quic_data_.AddWrite(SYNCHRONOUS,
+                           ConstructConnectRequestPacket(packet_number++));
   mock_quic_data_.AddRead(ASYNC, ConstructServerConnectReplyPacket(1, !kFin));
   mock_quic_data_.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
 
   std::string header = ConstructDataHeader(kLen1);
   mock_quic_data_.AddRead(
       ASYNC, ConstructServerDataPacket(2, header + std::string(kMsg1, kLen1)));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructAckPacket(3, 2, 1, 1));
-  mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   mock_quic_data_.AddWrite(SYNCHRONOUS,
-                           ConstructRstPacket(4, quic::QUIC_STREAM_CANCELLED));
+                           ConstructAckPacket(packet_number++, 2, 1, 1));
+  mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+  mock_quic_data_.AddWrite(
+      SYNCHRONOUS,
+      ConstructRstPacket(packet_number++, quic::QUIC_STREAM_CANCELLED));
 
   Initialize();
 
@@ -764,8 +807,13 @@
 }
 
 TEST_P(QuicProxyClientSocketTest, GetTotalReceivedBytes) {
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructSettingsPacket(1));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructConnectRequestPacket(2));
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data_.AddWrite(SYNCHRONOUS,
+                             ConstructSettingsPacket(packet_number++));
+  }
+  mock_quic_data_.AddWrite(SYNCHRONOUS,
+                           ConstructConnectRequestPacket(packet_number++));
   mock_quic_data_.AddRead(ASYNC, ConstructServerConnectReplyPacket(1, !kFin));
   mock_quic_data_.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
 
@@ -773,10 +821,12 @@
   mock_quic_data_.AddRead(
       ASYNC,
       ConstructServerDataPacket(2, header + std::string(kMsg333, kLen333)));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructAckPacket(3, 2, 1, 1));
-  mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   mock_quic_data_.AddWrite(SYNCHRONOUS,
-                           ConstructRstPacket(4, quic::QUIC_STREAM_CANCELLED));
+                           ConstructAckPacket(packet_number++, 2, 1, 1));
+  mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+  mock_quic_data_.AddWrite(
+      SYNCHRONOUS,
+      ConstructRstPacket(packet_number++, quic::QUIC_STREAM_CANCELLED));
 
   Initialize();
 
@@ -805,16 +855,19 @@
 }
 
 TEST_P(QuicProxyClientSocketTest, SetStreamPriority) {
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructSettingsPacket(1));
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructSettingsPacket(1));
+  }
   // Despite setting the priority to HIGHEST, the requets initial priority of
   // LOWEST is used.
-  mock_quic_data_.AddWrite(SYNCHRONOUS,
-                           ConstructConnectRequestPacket(2, LOWEST));
+  mock_quic_data_.AddWrite(
+      SYNCHRONOUS, ConstructConnectRequestPacket(packet_number++, LOWEST));
   mock_quic_data_.AddRead(ASYNC, ConstructServerConnectReplyPacket(1, !kFin));
   mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   mock_quic_data_.AddWrite(
-      SYNCHRONOUS,
-      ConstructAckAndRstPacket(3, quic::QUIC_STREAM_CANCELLED, 1, 1, 1));
+      SYNCHRONOUS, ConstructAckAndRstPacket(
+                       packet_number++, quic::QUIC_STREAM_CANCELLED, 1, 1, 1));
 
   Initialize();
 
@@ -823,29 +876,39 @@
 }
 
 TEST_P(QuicProxyClientSocketTest, WriteSendsDataInDataFrame) {
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructSettingsPacket(1));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructConnectRequestPacket(2));
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data_.AddWrite(SYNCHRONOUS,
+                             ConstructSettingsPacket(packet_number++));
+  }
+  mock_quic_data_.AddWrite(SYNCHRONOUS,
+                           ConstructConnectRequestPacket(packet_number++));
   mock_quic_data_.AddRead(ASYNC, ConstructServerConnectReplyPacket(1, !kFin));
   mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   if (version_.transport_version == quic::QUIC_VERSION_99) {
     std::string header = ConstructDataHeader(kLen1);
     mock_quic_data_.AddWrite(
-        SYNCHRONOUS, ConstructAckAndMultipleDataFramesPacket(
-                         3, 1, 1, 1, {header, std::string(kMsg1, kLen1)}));
+        SYNCHRONOUS,
+        ConstructAckAndMultipleDataFramesPacket(
+            packet_number++, 1, 1, 1, {header, std::string(kMsg1, kLen1)}));
     std::string header2 = ConstructDataHeader(kLen2);
-    mock_quic_data_.AddWrite(SYNCHRONOUS,
-                             ConstructMultipleDataFramesPacket(
-                                 4, {header2, std::string(kMsg2, kLen2)}));
-    mock_quic_data_.AddWrite(
-        SYNCHRONOUS, ConstructRstPacket(5, quic::QUIC_STREAM_CANCELLED));
-  } else {
     mock_quic_data_.AddWrite(
         SYNCHRONOUS,
-        ConstructAckAndDataPacket(3, 1, 1, 1, std::string(kMsg1, kLen1)));
-    mock_quic_data_.AddWrite(SYNCHRONOUS,
-                             ConstructDataPacket(4, std::string(kMsg2, kLen2)));
+        ConstructMultipleDataFramesPacket(
+            packet_number++, {header2, std::string(kMsg2, kLen2)}));
     mock_quic_data_.AddWrite(
-        SYNCHRONOUS, ConstructRstPacket(5, quic::QUIC_STREAM_CANCELLED));
+        SYNCHRONOUS,
+        ConstructRstPacket(packet_number++, quic::QUIC_STREAM_CANCELLED));
+  } else {
+    mock_quic_data_.AddWrite(
+        SYNCHRONOUS, ConstructAckAndDataPacket(packet_number++, 1, 1, 1,
+                                               std::string(kMsg1, kLen1)));
+    mock_quic_data_.AddWrite(
+        SYNCHRONOUS,
+        ConstructDataPacket(packet_number++, std::string(kMsg2, kLen2)));
+    mock_quic_data_.AddWrite(
+        SYNCHRONOUS,
+        ConstructRstPacket(packet_number++, quic::QUIC_STREAM_CANCELLED));
   }
 
   Initialize();
@@ -858,8 +921,10 @@
 
 TEST_P(QuicProxyClientSocketTest, WriteSplitsLargeDataIntoMultiplePackets) {
   int write_packet_index = 1;
-  mock_quic_data_.AddWrite(SYNCHRONOUS,
-                           ConstructSettingsPacket(write_packet_index++));
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data_.AddWrite(SYNCHRONOUS,
+                             ConstructSettingsPacket(write_packet_index++));
+  }
   mock_quic_data_.AddWrite(SYNCHRONOUS,
                            ConstructConnectRequestPacket(write_packet_index++));
   mock_quic_data_.AddRead(ASYNC, ConstructServerConnectReplyPacket(1, !kFin));
@@ -960,18 +1025,25 @@
 // ----------- Read
 
 TEST_P(QuicProxyClientSocketTest, ReadReadsDataInDataFrame) {
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructSettingsPacket(1));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructConnectRequestPacket(2));
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data_.AddWrite(SYNCHRONOUS,
+                             ConstructSettingsPacket(packet_number++));
+  }
+  mock_quic_data_.AddWrite(SYNCHRONOUS,
+                           ConstructConnectRequestPacket(packet_number++));
   mock_quic_data_.AddRead(ASYNC, ConstructServerConnectReplyPacket(1, !kFin));
   mock_quic_data_.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
 
   std::string header = ConstructDataHeader(kLen1);
   mock_quic_data_.AddRead(
       ASYNC, ConstructServerDataPacket(2, header + std::string(kMsg1, kLen1)));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructAckPacket(3, 2, 1, 1));
-  mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   mock_quic_data_.AddWrite(SYNCHRONOUS,
-                           ConstructRstPacket(4, quic::QUIC_STREAM_CANCELLED));
+                           ConstructAckPacket(packet_number++, 2, 1, 1));
+  mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+  mock_quic_data_.AddWrite(
+      SYNCHRONOUS,
+      ConstructRstPacket(packet_number++, quic::QUIC_STREAM_CANCELLED));
 
   Initialize();
 
@@ -982,15 +1054,21 @@
 }
 
 TEST_P(QuicProxyClientSocketTest, ReadDataFromBufferedFrames) {
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructSettingsPacket(1));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructConnectRequestPacket(2));
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data_.AddWrite(SYNCHRONOUS,
+                             ConstructSettingsPacket(packet_number++));
+  }
+  mock_quic_data_.AddWrite(SYNCHRONOUS,
+                           ConstructConnectRequestPacket(packet_number++));
   mock_quic_data_.AddRead(ASYNC, ConstructServerConnectReplyPacket(1, !kFin));
   mock_quic_data_.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
 
   std::string header = ConstructDataHeader(kLen1);
   mock_quic_data_.AddRead(
       ASYNC, ConstructServerDataPacket(2, header + std::string(kMsg1, kLen1)));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructAckPacket(3, 2, 1, 1));
+  mock_quic_data_.AddWrite(SYNCHRONOUS,
+                           ConstructAckPacket(packet_number++, 2, 1, 1));
   mock_quic_data_.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
 
   std::string header2 = ConstructDataHeader(kLen2);
@@ -999,8 +1077,8 @@
   mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
 
   mock_quic_data_.AddWrite(
-      SYNCHRONOUS,
-      ConstructAckAndRstPacket(4, quic::QUIC_STREAM_CANCELLED, 3, 3, 1));
+      SYNCHRONOUS, ConstructAckAndRstPacket(
+                       packet_number++, quic::QUIC_STREAM_CANCELLED, 3, 3, 1));
 
   Initialize();
 
@@ -1014,23 +1092,29 @@
 }
 
 TEST_P(QuicProxyClientSocketTest, ReadDataMultipleBufferedFrames) {
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructSettingsPacket(1));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructConnectRequestPacket(2));
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data_.AddWrite(SYNCHRONOUS,
+                             ConstructSettingsPacket(packet_number++));
+  }
+  mock_quic_data_.AddWrite(SYNCHRONOUS,
+                           ConstructConnectRequestPacket(packet_number++));
   mock_quic_data_.AddRead(ASYNC, ConstructServerConnectReplyPacket(1, !kFin));
   mock_quic_data_.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
 
   std::string header = ConstructDataHeader(kLen1);
   mock_quic_data_.AddRead(
       ASYNC, ConstructServerDataPacket(2, header + std::string(kMsg1, kLen1)));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructAckPacket(3, 2, 1, 1));
+  mock_quic_data_.AddWrite(SYNCHRONOUS,
+                           ConstructAckPacket(packet_number++, 2, 1, 1));
   std::string header2 = ConstructDataHeader(kLen2);
   mock_quic_data_.AddRead(
       ASYNC, ConstructServerDataPacket(3, header2 + std::string(kMsg2, kLen2)));
   mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
 
   mock_quic_data_.AddWrite(
-      SYNCHRONOUS,
-      ConstructAckAndRstPacket(4, quic::QUIC_STREAM_CANCELLED, 3, 3, 1));
+      SYNCHRONOUS, ConstructAckAndRstPacket(
+                       packet_number++, quic::QUIC_STREAM_CANCELLED, 3, 3, 1));
 
   Initialize();
 
@@ -1044,23 +1128,29 @@
 }
 
 TEST_P(QuicProxyClientSocketTest, LargeReadWillMergeDataFromDifferentFrames) {
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructSettingsPacket(1));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructConnectRequestPacket(2));
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data_.AddWrite(SYNCHRONOUS,
+                             ConstructSettingsPacket(packet_number++));
+  }
+  mock_quic_data_.AddWrite(SYNCHRONOUS,
+                           ConstructConnectRequestPacket(packet_number++));
   mock_quic_data_.AddRead(ASYNC, ConstructServerConnectReplyPacket(1, !kFin));
   mock_quic_data_.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
 
   std::string header = ConstructDataHeader(kLen3);
   mock_quic_data_.AddRead(
       ASYNC, ConstructServerDataPacket(2, header + std::string(kMsg3, kLen3)));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructAckPacket(3, 2, 1, 1));
+  mock_quic_data_.AddWrite(SYNCHRONOUS,
+                           ConstructAckPacket(packet_number++, 2, 1, 1));
   std::string header2 = ConstructDataHeader(kLen3);
   mock_quic_data_.AddRead(
       ASYNC, ConstructServerDataPacket(3, header2 + std::string(kMsg3, kLen3)));
   mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
 
   mock_quic_data_.AddWrite(
-      SYNCHRONOUS,
-      ConstructAckAndRstPacket(4, quic::QUIC_STREAM_CANCELLED, 3, 3, 1));
+      SYNCHRONOUS, ConstructAckAndRstPacket(
+                       packet_number++, quic::QUIC_STREAM_CANCELLED, 3, 3, 1));
 
   Initialize();
 
@@ -1074,8 +1164,13 @@
 }
 
 TEST_P(QuicProxyClientSocketTest, MultipleShortReadsThenMoreRead) {
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructSettingsPacket(1));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructConnectRequestPacket(2));
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data_.AddWrite(SYNCHRONOUS,
+                             ConstructSettingsPacket(packet_number++));
+  }
+  mock_quic_data_.AddWrite(SYNCHRONOUS,
+                           ConstructConnectRequestPacket(packet_number++));
   mock_quic_data_.AddRead(ASYNC, ConstructServerConnectReplyPacket(1, !kFin));
   mock_quic_data_.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
 
@@ -1085,7 +1180,8 @@
   mock_quic_data_.AddRead(
       ASYNC, ConstructServerDataPacket(2, header + std::string(kMsg1, kLen1)));
   offset += kLen1 + header.length();
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructAckPacket(3, 2, 1, 1));
+  mock_quic_data_.AddWrite(SYNCHRONOUS,
+                           ConstructAckPacket(packet_number++, 2, 1, 1));
 
   std::string header2 = ConstructDataHeader(kLen3);
   mock_quic_data_.AddRead(
@@ -1094,7 +1190,8 @@
   mock_quic_data_.AddRead(
       ASYNC, ConstructServerDataPacket(4, header2 + std::string(kMsg3, kLen3)));
   offset += kLen3 + header2.length();
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructAckPacket(4, 4, 3, 1));
+  mock_quic_data_.AddWrite(SYNCHRONOUS,
+                           ConstructAckPacket(packet_number++, 4, 3, 1));
 
   std::string header3 = ConstructDataHeader(kLen2);
   mock_quic_data_.AddRead(
@@ -1103,8 +1200,8 @@
   mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
 
   mock_quic_data_.AddWrite(
-      SYNCHRONOUS,
-      ConstructAckAndRstPacket(5, quic::QUIC_STREAM_CANCELLED, 5, 5, 1));
+      SYNCHRONOUS, ConstructAckAndRstPacket(
+                       packet_number++, quic::QUIC_STREAM_CANCELLED, 5, 5, 1));
 
   Initialize();
 
@@ -1121,23 +1218,29 @@
 }
 
 TEST_P(QuicProxyClientSocketTest, ReadWillSplitDataFromLargeFrame) {
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructSettingsPacket(1));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructConnectRequestPacket(2));
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data_.AddWrite(SYNCHRONOUS,
+                             ConstructSettingsPacket(packet_number++));
+  }
+  mock_quic_data_.AddWrite(SYNCHRONOUS,
+                           ConstructConnectRequestPacket(packet_number++));
   mock_quic_data_.AddRead(ASYNC, ConstructServerConnectReplyPacket(1, !kFin));
   mock_quic_data_.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
 
   std::string header = ConstructDataHeader(kLen1);
   mock_quic_data_.AddRead(
       ASYNC, ConstructServerDataPacket(2, header + std::string(kMsg1, kLen1)));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructAckPacket(3, 2, 1, 1));
+  mock_quic_data_.AddWrite(SYNCHRONOUS,
+                           ConstructAckPacket(packet_number++, 2, 1, 1));
   std::string header2 = ConstructDataHeader(kLen33);
   mock_quic_data_.AddRead(ASYNC, ConstructServerDataPacket(
                                      3, header2 + std::string(kMsg33, kLen33)));
   mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
 
   mock_quic_data_.AddWrite(
-      SYNCHRONOUS,
-      ConstructAckAndRstPacket(4, quic::QUIC_STREAM_CANCELLED, 3, 3, 1));
+      SYNCHRONOUS, ConstructAckAndRstPacket(
+                       packet_number++, quic::QUIC_STREAM_CANCELLED, 3, 3, 1));
 
   Initialize();
 
@@ -1154,8 +1257,13 @@
 }
 
 TEST_P(QuicProxyClientSocketTest, MultipleReadsFromSameLargeFrame) {
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructSettingsPacket(1));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructConnectRequestPacket(2));
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data_.AddWrite(SYNCHRONOUS,
+                             ConstructSettingsPacket(packet_number++));
+  }
+  mock_quic_data_.AddWrite(SYNCHRONOUS,
+                           ConstructConnectRequestPacket(packet_number++));
   mock_quic_data_.AddRead(ASYNC, ConstructServerConnectReplyPacket(1, !kFin));
   mock_quic_data_.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
 
@@ -1163,11 +1271,13 @@
   mock_quic_data_.AddRead(
       ASYNC,
       ConstructServerDataPacket(2, header + std::string(kMsg333, kLen333)));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructAckPacket(3, 2, 1, 1));
+  mock_quic_data_.AddWrite(SYNCHRONOUS,
+                           ConstructAckPacket(packet_number++, 2, 1, 1));
   mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
 
-  mock_quic_data_.AddWrite(SYNCHRONOUS,
-                           ConstructRstPacket(4, quic::QUIC_STREAM_CANCELLED));
+  mock_quic_data_.AddWrite(
+      SYNCHRONOUS,
+      ConstructRstPacket(packet_number++, quic::QUIC_STREAM_CANCELLED));
 
   Initialize();
 
@@ -1188,8 +1298,13 @@
 }
 
 TEST_P(QuicProxyClientSocketTest, ReadAuthResponseBody) {
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructSettingsPacket(1));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructConnectRequestPacket(2));
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data_.AddWrite(SYNCHRONOUS,
+                             ConstructSettingsPacket(packet_number++));
+  }
+  mock_quic_data_.AddWrite(SYNCHRONOUS,
+                           ConstructConnectRequestPacket(packet_number++));
   mock_quic_data_.AddRead(ASYNC,
                           ConstructServerConnectAuthReplyPacket(1, !kFin));
   mock_quic_data_.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
@@ -1197,15 +1312,16 @@
   std::string header = ConstructDataHeader(kLen1);
   mock_quic_data_.AddRead(
       ASYNC, ConstructServerDataPacket(2, header + std::string(kMsg1, kLen1)));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructAckPacket(3, 2, 1, 1));
+  mock_quic_data_.AddWrite(SYNCHRONOUS,
+                           ConstructAckPacket(packet_number++, 2, 1, 1));
   std::string header2 = ConstructDataHeader(kLen2);
   mock_quic_data_.AddRead(
       ASYNC, ConstructServerDataPacket(3, header2 + std::string(kMsg2, kLen2)));
   mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
 
   mock_quic_data_.AddWrite(
-      SYNCHRONOUS,
-      ConstructAckAndRstPacket(4, quic::QUIC_STREAM_CANCELLED, 3, 3, 1));
+      SYNCHRONOUS, ConstructAckAndRstPacket(
+                       packet_number++, quic::QUIC_STREAM_CANCELLED, 3, 3, 1));
 
   Initialize();
 
@@ -1219,15 +1335,21 @@
 }
 
 TEST_P(QuicProxyClientSocketTest, ReadErrorResponseBody) {
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructSettingsPacket(1));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructConnectRequestPacket(2));
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data_.AddWrite(SYNCHRONOUS,
+                             ConstructSettingsPacket(packet_number++));
+  }
+  mock_quic_data_.AddWrite(SYNCHRONOUS,
+                           ConstructConnectRequestPacket(packet_number++));
   mock_quic_data_.AddRead(ASYNC,
                           ConstructServerConnectErrorReplyPacket(1, !kFin));
   std::string header = ConstructDataHeader(kLen1);
   mock_quic_data_.AddRead(
       SYNCHRONOUS,
       ConstructServerDataPacket(2, header + std::string(kMsg1, kLen1)));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructAckPacket(3, 2, 1, 1));
+  mock_quic_data_.AddWrite(SYNCHRONOUS,
+                           ConstructAckPacket(packet_number++, 2, 1, 1));
   std::string header2 = ConstructDataHeader(kLen2);
   mock_quic_data_.AddRead(
       SYNCHRONOUS,
@@ -1235,8 +1357,8 @@
   mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
 
   mock_quic_data_.AddWrite(
-      SYNCHRONOUS,
-      ConstructAckAndRstPacket(4, quic::QUIC_STREAM_CANCELLED, 3, 3, 1));
+      SYNCHRONOUS, ConstructAckAndRstPacket(
+                       packet_number++, quic::QUIC_STREAM_CANCELLED, 3, 3, 1));
   Initialize();
 
   AssertConnectFails(ERR_TUNNEL_CONNECTION_FAILED);
@@ -1246,8 +1368,10 @@
 
 TEST_P(QuicProxyClientSocketTest, AsyncReadAroundWrite) {
   int write_packet_index = 1;
-  mock_quic_data_.AddWrite(SYNCHRONOUS,
-                           ConstructSettingsPacket(write_packet_index++));
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data_.AddWrite(SYNCHRONOUS,
+                             ConstructSettingsPacket(write_packet_index++));
+  }
   mock_quic_data_.AddWrite(SYNCHRONOUS,
                            ConstructConnectRequestPacket(write_packet_index++));
   mock_quic_data_.AddRead(ASYNC, ConstructServerConnectReplyPacket(1, !kFin));
@@ -1304,15 +1428,21 @@
 }
 
 TEST_P(QuicProxyClientSocketTest, AsyncWriteAroundReads) {
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructSettingsPacket(1));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructConnectRequestPacket(2));
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data_.AddWrite(SYNCHRONOUS,
+                             ConstructSettingsPacket(packet_number++));
+  }
+  mock_quic_data_.AddWrite(SYNCHRONOUS,
+                           ConstructConnectRequestPacket(packet_number++));
   mock_quic_data_.AddRead(ASYNC, ConstructServerConnectReplyPacket(1, !kFin));
   mock_quic_data_.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
 
   std::string header = ConstructDataHeader(kLen1);
   mock_quic_data_.AddRead(
       ASYNC, ConstructServerDataPacket(2, header + std::string(kMsg1, kLen1)));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructAckPacket(3, 2, 1, 1));
+  mock_quic_data_.AddWrite(SYNCHRONOUS,
+                           ConstructAckPacket(packet_number++, 2, 1, 1));
   mock_quic_data_.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
 
   std::string header2 = ConstructDataHeader(kLen3);
@@ -1324,22 +1454,23 @@
 
   std::string header3 = ConstructDataHeader(kLen2);
   if (version_.transport_version != quic::QUIC_VERSION_99) {
-    mock_quic_data_.AddWrite(ASYNC,
-                             ConstructDataPacket(4, std::string(kMsg2, kLen2)));
     mock_quic_data_.AddWrite(
-        SYNCHRONOUS,
-        ConstructAckAndDataPacket(5, 3, 3, 1, std::string(kMsg2, kLen2)));
+        ASYNC, ConstructDataPacket(packet_number++, std::string(kMsg2, kLen2)));
+    mock_quic_data_.AddWrite(
+        SYNCHRONOUS, ConstructAckAndDataPacket(packet_number++, 3, 3, 1,
+                                               std::string(kMsg2, kLen2)));
   } else {
-    mock_quic_data_.AddWrite(ASYNC,
-                             ConstructMultipleDataFramesPacket(
-                                 4, {header3, std::string(kMsg2, kLen2)}));
     mock_quic_data_.AddWrite(
-        ASYNC, ConstructAckAndDataPacket(5, 3, 3, 1,
+        ASYNC, ConstructMultipleDataFramesPacket(
+                   packet_number++, {header3, std::string(kMsg2, kLen2)}));
+    mock_quic_data_.AddWrite(
+        ASYNC, ConstructAckAndDataPacket(packet_number++, 3, 3, 1,
                                          header3 + std::string(kMsg2, kLen2)));
   }
 
-  mock_quic_data_.AddWrite(SYNCHRONOUS,
-                           ConstructRstPacket(6, quic::QUIC_STREAM_CANCELLED));
+  mock_quic_data_.AddWrite(
+      SYNCHRONOUS,
+      ConstructRstPacket(packet_number++, quic::QUIC_STREAM_CANCELLED));
 
   Initialize();
 
@@ -1369,8 +1500,13 @@
 
 // Reading from an already closed socket should return 0
 TEST_P(QuicProxyClientSocketTest, ReadOnClosedSocketReturnsZero) {
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructSettingsPacket(1));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructConnectRequestPacket(2));
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data_.AddWrite(SYNCHRONOUS,
+                             ConstructSettingsPacket(packet_number++));
+  }
+  mock_quic_data_.AddWrite(SYNCHRONOUS,
+                           ConstructConnectRequestPacket(packet_number++));
   mock_quic_data_.AddRead(ASYNC, ConstructServerConnectReplyPacket(1, !kFin));
   mock_quic_data_.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
 
@@ -1391,8 +1527,13 @@
 
 // Read pending when socket is closed should return 0
 TEST_P(QuicProxyClientSocketTest, PendingReadOnCloseReturnsZero) {
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructSettingsPacket(1));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructConnectRequestPacket(2));
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data_.AddWrite(SYNCHRONOUS,
+                             ConstructSettingsPacket(packet_number++));
+  }
+  mock_quic_data_.AddWrite(SYNCHRONOUS,
+                           ConstructConnectRequestPacket(packet_number++));
   mock_quic_data_.AddRead(ASYNC, ConstructServerConnectReplyPacket(1, !kFin));
   mock_quic_data_.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
 
@@ -1411,13 +1552,18 @@
 
 // Reading from a disconnected socket is an error
 TEST_P(QuicProxyClientSocketTest, ReadOnDisconnectSocketReturnsNotConnected) {
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructSettingsPacket(1));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructConnectRequestPacket(2));
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data_.AddWrite(SYNCHRONOUS,
+                             ConstructSettingsPacket(packet_number++));
+  }
+  mock_quic_data_.AddWrite(SYNCHRONOUS,
+                           ConstructConnectRequestPacket(packet_number++));
   mock_quic_data_.AddRead(ASYNC, ConstructServerConnectReplyPacket(1, !kFin));
   mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   mock_quic_data_.AddWrite(
-      SYNCHRONOUS,
-      ConstructAckAndRstPacket(3, quic::QUIC_STREAM_CANCELLED, 1, 1, 1));
+      SYNCHRONOUS, ConstructAckAndRstPacket(
+                       packet_number++, quic::QUIC_STREAM_CANCELLED, 1, 1, 1));
 
   Initialize();
 
@@ -1432,18 +1578,25 @@
 // Reading data after receiving FIN should return buffered data received before
 // FIN, then 0.
 TEST_P(QuicProxyClientSocketTest, ReadAfterFinReceivedReturnsBufferedData) {
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructSettingsPacket(1));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructConnectRequestPacket(2));
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data_.AddWrite(SYNCHRONOUS,
+                             ConstructSettingsPacket(packet_number++));
+  }
+  mock_quic_data_.AddWrite(SYNCHRONOUS,
+                           ConstructConnectRequestPacket(packet_number++));
   mock_quic_data_.AddRead(ASYNC, ConstructServerConnectReplyPacket(1, !kFin));
   mock_quic_data_.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
 
   std::string header = ConstructDataHeader(kLen1);
   mock_quic_data_.AddRead(ASYNC, ConstructServerDataFinPacket(
                                      2, header + std::string(kMsg1, kLen1)));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructAckPacket(3, 2, 1, 1));
-  mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   mock_quic_data_.AddWrite(SYNCHRONOUS,
-                           ConstructRstPacket(4, quic::QUIC_STREAM_CANCELLED));
+                           ConstructAckPacket(packet_number++, 2, 1, 1));
+  mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+  mock_quic_data_.AddWrite(
+      SYNCHRONOUS,
+      ConstructRstPacket(packet_number++, quic::QUIC_STREAM_CANCELLED));
 
   Initialize();
 
@@ -1462,8 +1615,13 @@
 
 // Calling Write() on a closed socket is an error.
 TEST_P(QuicProxyClientSocketTest, WriteOnClosedStream) {
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructSettingsPacket(1));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructConnectRequestPacket(2));
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data_.AddWrite(SYNCHRONOUS,
+                             ConstructSettingsPacket(packet_number++));
+  }
+  mock_quic_data_.AddWrite(SYNCHRONOUS,
+                           ConstructConnectRequestPacket(packet_number++));
   mock_quic_data_.AddRead(ASYNC, ConstructServerConnectReplyPacket(1, !kFin));
   mock_quic_data_.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
 
@@ -1480,13 +1638,18 @@
 
 // Calling Write() on a disconnected socket is an error.
 TEST_P(QuicProxyClientSocketTest, WriteOnDisconnectedSocket) {
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructSettingsPacket(1));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructConnectRequestPacket(2));
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data_.AddWrite(SYNCHRONOUS,
+                             ConstructSettingsPacket(packet_number++));
+  }
+  mock_quic_data_.AddWrite(SYNCHRONOUS,
+                           ConstructConnectRequestPacket(packet_number++));
   mock_quic_data_.AddRead(ASYNC, ConstructServerConnectReplyPacket(1, !kFin));
   mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   mock_quic_data_.AddWrite(
-      SYNCHRONOUS,
-      ConstructAckAndRstPacket(3, quic::QUIC_STREAM_CANCELLED, 1, 1, 1));
+      SYNCHRONOUS, ConstructAckAndRstPacket(
+                       packet_number++, quic::QUIC_STREAM_CANCELLED, 1, 1, 1));
 
   Initialize();
 
@@ -1500,8 +1663,13 @@
 // If the socket is closed with a pending Write(), the callback should be called
 // with the same error the session was closed with.
 TEST_P(QuicProxyClientSocketTest, WritePendingOnClose) {
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructSettingsPacket(1));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructConnectRequestPacket(2));
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data_.AddWrite(SYNCHRONOUS,
+                             ConstructSettingsPacket(packet_number++));
+  }
+  mock_quic_data_.AddWrite(SYNCHRONOUS,
+                           ConstructConnectRequestPacket(packet_number++));
   mock_quic_data_.AddRead(ASYNC, ConstructServerConnectReplyPacket(1, !kFin));
   mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   mock_quic_data_.AddWrite(SYNCHRONOUS, ERR_IO_PENDING);
@@ -1531,8 +1699,13 @@
 }
 
 TEST_P(QuicProxyClientSocketTest, DisconnectWithWritePending) {
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructSettingsPacket(1));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructConnectRequestPacket(2));
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data_.AddWrite(SYNCHRONOUS,
+                             ConstructSettingsPacket(packet_number++));
+  }
+  mock_quic_data_.AddWrite(SYNCHRONOUS,
+                           ConstructConnectRequestPacket(packet_number++));
   mock_quic_data_.AddRead(ASYNC, ConstructServerConnectReplyPacket(1, !kFin));
   mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   mock_quic_data_.AddWrite(SYNCHRONOUS, ERR_IO_PENDING);
@@ -1566,13 +1739,18 @@
 // If the socket is Disconnected with a pending Read(), the callback
 // should not be called.
 TEST_P(QuicProxyClientSocketTest, DisconnectWithReadPending) {
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructSettingsPacket(1));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructConnectRequestPacket(2));
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data_.AddWrite(SYNCHRONOUS,
+                             ConstructSettingsPacket(packet_number++));
+  }
+  mock_quic_data_.AddWrite(SYNCHRONOUS,
+                           ConstructConnectRequestPacket(packet_number++));
   mock_quic_data_.AddRead(ASYNC, ConstructServerConnectReplyPacket(1, !kFin));
   mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   mock_quic_data_.AddWrite(
-      SYNCHRONOUS,
-      ConstructAckAndRstPacket(3, quic::QUIC_STREAM_CANCELLED, 1, 1, 1));
+      SYNCHRONOUS, ConstructAckAndRstPacket(
+                       packet_number++, quic::QUIC_STREAM_CANCELLED, 1, 1, 1));
 
   Initialize();
 
@@ -1594,8 +1772,13 @@
 // If the socket is Reset when both a read and write are pending,
 // both should be called back.
 TEST_P(QuicProxyClientSocketTest, RstWithReadAndWritePending) {
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructSettingsPacket(1));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructConnectRequestPacket(2));
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data_.AddWrite(SYNCHRONOUS,
+                             ConstructSettingsPacket(packet_number++));
+  }
+  mock_quic_data_.AddWrite(SYNCHRONOUS,
+                           ConstructConnectRequestPacket(packet_number++));
   mock_quic_data_.AddRead(ASYNC, ConstructServerConnectReplyPacket(1, !kFin));
   mock_quic_data_.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
 
@@ -1604,18 +1787,21 @@
   mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   std::string header = ConstructDataHeader(kLen2);
   if (version_.transport_version != quic::QUIC_VERSION_99) {
-    mock_quic_data_.AddWrite(ASYNC, ConstructAckAndDataPacket(
-                                        3, 1, 1, 1, std::string(kMsg2, kLen2)));
+    mock_quic_data_.AddWrite(
+        ASYNC, ConstructAckAndDataPacket(packet_number++, 1, 1, 1,
+                                         std::string(kMsg2, kLen2)));
     mock_quic_data_.AddWrite(
         SYNCHRONOUS,
-        ConstructAckAndRstPacket(4, quic::QUIC_RST_ACKNOWLEDGEMENT, 2, 2, 1));
+        ConstructAckAndRstPacket(packet_number++,
+                                 quic::QUIC_RST_ACKNOWLEDGEMENT, 2, 2, 1));
   } else {
-    mock_quic_data_.AddWrite(
-        ASYNC, ConstructAckAndMultipleDataFramesPacket(
-                   3, 1, 1, 1, {header, std::string(kMsg2, kLen2)}));
+    mock_quic_data_.AddWrite(ASYNC, ConstructAckAndMultipleDataFramesPacket(
+                                        packet_number++, 1, 1, 1,
+                                        {header, std::string(kMsg2, kLen2)}));
     mock_quic_data_.AddWrite(
         SYNCHRONOUS,
-        ConstructAckAndRstOnlyPacket(4, quic::QUIC_STREAM_CANCELLED, 2, 2, 1));
+        ConstructAckAndRstOnlyPacket(packet_number++,
+                                     quic::QUIC_STREAM_CANCELLED, 2, 2, 1));
   }
 
   Initialize();
@@ -1644,18 +1830,25 @@
 // Makes sure the proxy client socket's source gets the expected NetLog events
 // and only the expected NetLog events (No SpdySession events).
 TEST_P(QuicProxyClientSocketTest, NetLog) {
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructSettingsPacket(1));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructConnectRequestPacket(2));
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data_.AddWrite(SYNCHRONOUS,
+                             ConstructSettingsPacket(packet_number++));
+  }
+  mock_quic_data_.AddWrite(SYNCHRONOUS,
+                           ConstructConnectRequestPacket(packet_number++));
   mock_quic_data_.AddRead(ASYNC, ConstructServerConnectReplyPacket(1, !kFin));
   mock_quic_data_.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
 
   std::string header = ConstructDataHeader(kLen1);
   mock_quic_data_.AddRead(
       ASYNC, ConstructServerDataPacket(2, header + std::string(kMsg1, kLen1)));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructAckPacket(3, 2, 1, 1));
-  mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   mock_quic_data_.AddWrite(SYNCHRONOUS,
-                           ConstructRstPacket(4, quic::QUIC_STREAM_CANCELLED));
+                           ConstructAckPacket(packet_number++, 2, 1, 1));
+  mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+  mock_quic_data_.AddWrite(
+      SYNCHRONOUS,
+      ConstructRstPacket(packet_number++, quic::QUIC_STREAM_CANCELLED));
 
   Initialize();
 
@@ -1725,8 +1918,13 @@
 // read callback causes the socket to be deleted, the write callback should
 // not be called.
 TEST_P(QuicProxyClientSocketTest, RstWithReadAndWritePendingDelete) {
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructSettingsPacket(1));
-  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructConnectRequestPacket(2));
+  int packet_number = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    mock_quic_data_.AddWrite(SYNCHRONOUS,
+                             ConstructSettingsPacket(packet_number++));
+  }
+  mock_quic_data_.AddWrite(SYNCHRONOUS,
+                           ConstructConnectRequestPacket(packet_number++));
   mock_quic_data_.AddRead(ASYNC, ConstructServerConnectReplyPacket(1, !kFin));
   mock_quic_data_.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
 
@@ -1734,19 +1932,22 @@
       ASYNC, ConstructServerRstPacket(2, quic::QUIC_STREAM_CANCELLED));
   mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   if (version_.transport_version != quic::QUIC_VERSION_99) {
-    mock_quic_data_.AddWrite(ASYNC, ConstructAckAndDataPacket(
-                                        3, 1, 1, 1, std::string(kMsg1, kLen1)));
+    mock_quic_data_.AddWrite(
+        ASYNC, ConstructAckAndDataPacket(packet_number++, 1, 1, 1,
+                                         std::string(kMsg1, kLen1)));
     mock_quic_data_.AddWrite(
         SYNCHRONOUS,
-        ConstructAckAndRstPacket(4, quic::QUIC_RST_ACKNOWLEDGEMENT, 2, 2, 1));
+        ConstructAckAndRstPacket(packet_number++,
+                                 quic::QUIC_RST_ACKNOWLEDGEMENT, 2, 2, 1));
   } else {
     std::string header = ConstructDataHeader(kLen1);
-    mock_quic_data_.AddWrite(
-        ASYNC, ConstructAckAndMultipleDataFramesPacket(
-                   3, 1, 1, 1, {header, std::string(kMsg1, kLen1)}));
+    mock_quic_data_.AddWrite(ASYNC, ConstructAckAndMultipleDataFramesPacket(
+                                        packet_number++, 1, 1, 1,
+                                        {header, std::string(kMsg1, kLen1)}));
     mock_quic_data_.AddWrite(
         SYNCHRONOUS,
-        ConstructAckAndRstOnlyPacket(4, quic::QUIC_STREAM_CANCELLED, 2, 2, 1));
+        ConstructAckAndRstOnlyPacket(packet_number++,
+                                     quic::QUIC_STREAM_CANCELLED, 2, 2, 1));
   }
 
   Initialize();
diff --git a/net/quic/quic_stream_factory_test.cc b/net/quic/quic_stream_factory_test.cc
index 9b0f16c..ba27faf 100644
--- a/net/quic/quic_stream_factory_test.cc
+++ b/net/quic/quic_stream_factory_test.cc
@@ -353,7 +353,8 @@
 
     MockQuicData socket_data(version_);
     socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-    socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+    if (VersionUsesQpack(version_.transport_version))
+      socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
     socket_data.AddSocketDataToFactory(socket_factory_.get());
 
     QuicStreamRequest request(factory_.get());
@@ -494,13 +495,19 @@
     // migration.
     MockQuicData socket_data2(version_);
     socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-    socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+    int packet_num = 1;
+    if (VersionUsesQpack(version_.transport_version)) {
+      socket_data2.AddWrite(SYNCHRONOUS,
+                            ConstructInitialSettingsPacket(packet_num++));
+    }
     socket_data2.AddWrite(
-        SYNCHRONOUS, client_maker_.MakePingPacket(2, /*include_version=*/true));
+        SYNCHRONOUS,
+        client_maker_.MakePingPacket(packet_num++, /*include_version=*/true));
     socket_data2.AddWrite(
-        SYNCHRONOUS, client_maker_.MakeRstPacket(
-                         3, true, GetNthClientInitiatedBidirectionalStreamId(0),
-                         quic::QUIC_STREAM_CANCELLED));
+        SYNCHRONOUS,
+        client_maker_.MakeRstPacket(
+            packet_num++, true, GetNthClientInitiatedBidirectionalStreamId(0),
+            quic::QUIC_STREAM_CANCELLED));
     socket_data2.AddSocketDataToFactory(socket_factory_.get());
 
     // Create request and QuicHttpStream.
@@ -884,7 +891,8 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
   QuicStreamRequest request(factory_.get());
@@ -966,7 +974,8 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
   QuicStreamRequest request(factory_.get());
@@ -994,7 +1003,8 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
   auto request = std::make_unique<QuicStreamRequest>(factory_.get());
@@ -1024,7 +1034,8 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
   QuicStreamRequest request(factory_.get());
@@ -1066,7 +1077,8 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
   QuicStreamRequest request(factory_.get());
@@ -1105,7 +1117,8 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
   QuicStreamRequest request(factory_.get());
@@ -1168,8 +1181,10 @@
 
     MockQuicData socket_data(version_);
     socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-    socket_data.AddWrite(SYNCHRONOUS,
-                         packet_maker.MakeInitialSettingsPacket(1));
+    if (VersionUsesQpack(version_.transport_version)) {
+      socket_data.AddWrite(SYNCHRONOUS,
+                           packet_maker.MakeInitialSettingsPacket(1));
+    }
     socket_data.AddSocketDataToFactory(socket_factory_.get());
 
     QuicStreamRequest request(factory_.get());
@@ -1210,7 +1225,8 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
   QuicStreamRequest request(factory_.get());
@@ -1243,7 +1259,8 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
   QuicStreamRequest request(factory_.get());
@@ -1271,7 +1288,8 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
   QuicStreamRequest request(factory_.get());
@@ -1303,7 +1321,8 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
   QuicStreamRequest request(factory_.get());
@@ -1378,8 +1397,10 @@
 
     MockQuicData socket_data(version_);
     socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-    socket_data.AddWrite(SYNCHRONOUS,
-                         packet_maker.MakeInitialSettingsPacket(1));
+    if (VersionUsesQpack(version_.transport_version)) {
+      socket_data.AddWrite(SYNCHRONOUS,
+                           packet_maker.MakeInitialSettingsPacket(1));
+    }
     socket_data.AddSocketDataToFactory(socket_factory_.get());
 
     QuicStreamRequest request(factory_.get());
@@ -1467,7 +1488,8 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
   HostPortPair server2(kServer2HostName, kDefaultServerPort);
@@ -1524,16 +1546,11 @@
   HostPortPair server2(kServer2HostName, kDefaultServerPort);
   host_resolver_->rules()->AddIPLiteralRule(server2.host(), "192.168.0.1", "");
 
-  MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
-  std::unique_ptr<quic::QuicEncryptedPacket> settings_packet(
-      client_maker_.MakeInitialSettingsPacket(1));
-  MockWrite writes[] = {MockWrite(SYNCHRONOUS, settings_packet->data(),
-                                  settings_packet->length(), 1)};
-
-  SequencedSocketData socket_data(reads, writes);
-  QuicPacketPrinter printer(version_);
-  socket_data.set_printer(&printer);
-  socket_factory_->AddSocketDataProvider(&socket_data);
+  MockQuicData socket_data1(version_);
+  socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  socket_data1.AddSocketDataToFactory(socket_factory_.get());
 
   ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
   crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
@@ -1553,8 +1570,8 @@
   std::unique_ptr<HttpStream> stream2 = CreateStream(&request2);
   EXPECT_TRUE(stream2.get());
 
-  EXPECT_TRUE(socket_data.AllReadDataConsumed());
-  EXPECT_TRUE(socket_data.AllWriteDataConsumed());
+  EXPECT_TRUE(socket_data1.AllReadDataConsumed());
+  EXPECT_TRUE(socket_data1.AllWriteDataConsumed());
   // EXPECT_EQ(GetActiveSession(host_port_pair_), GetActiveSession(server2));
 }
 
@@ -1566,12 +1583,14 @@
 
   MockQuicData socket_data1(version_);
   socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data1.AddSocketDataToFactory(socket_factory_.get());
   client_maker_.Reset();
   MockQuicData socket_data2(version_);
   socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data2.AddSocketDataToFactory(socket_factory_.get());
 
   HostPortPair server2(kServer2HostName, kDefaultServerPort);
@@ -1629,7 +1648,8 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
   HostPortPair server1(kDefaultServerHostName, 443);
@@ -1673,7 +1693,8 @@
   Initialize();
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
   HostPortPair server1(kDefaultServerHostName, 443);
@@ -1724,12 +1745,14 @@
 
   MockQuicData socket_data1(version_);
   socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data1.AddSocketDataToFactory(socket_factory_.get());
   client_maker_.Reset();
   MockQuicData socket_data2(version_);
   socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data2.AddSocketDataToFactory(socket_factory_.get());
 
   HostPortPair server1(kDefaultServerHostName, 443);
@@ -1791,12 +1814,14 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data.AddSocketDataToFactory(socket_factory_.get());
   client_maker_.Reset();
   MockQuicData socket_data2(version_);
   socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data2.AddSocketDataToFactory(socket_factory_.get());
 
   QuicStreamRequest request(factory_.get());
@@ -1853,8 +1878,8 @@
 
   quic::QuicStreamId stream_id = GetNthClientInitiatedBidirectionalStreamId(0);
   MockQuicData socket_data(version_);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   if (version_.transport_version == quic::QUIC_VERSION_99) {
+    socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
     socket_data.AddWrite(SYNCHRONOUS, client_maker_.MakeStreamsBlockedPacket(
                                           2, true, 50,
                                           /*unidirectional=*/false));
@@ -1869,7 +1894,7 @@
                                                   /*unidirectional=*/false));
   } else {
     socket_data.AddWrite(
-        SYNCHRONOUS, client_maker_.MakeRstPacket(2, true, stream_id,
+        SYNCHRONOUS, client_maker_.MakeRstPacket(1, true, stream_id,
                                                  quic::QUIC_STREAM_CANCELLED));
     socket_data.AddRead(
         ASYNC, server_maker_.MakeRstPacket(1, false, stream_id,
@@ -1984,7 +2009,8 @@
   Initialize();
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data.AddSocketDataToFactory(socket_factory_.get());
   {
     QuicStreamRequest request(factory_.get());
@@ -2022,18 +2048,25 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    socket_data.AddWrite(SYNCHRONOUS,
+                         ConstructInitialSettingsPacket(packet_num++));
+  }
   socket_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRstPacket(2, quic::QUIC_RST_ACKNOWLEDGEMENT));
-  socket_data.AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeConnectionClosePacket(
-                           3, true, quic::QUIC_PEER_GOING_AWAY, "net error"));
+      SYNCHRONOUS,
+      ConstructClientRstPacket(packet_num++, quic::QUIC_RST_ACKNOWLEDGEMENT));
+  socket_data.AddWrite(
+      SYNCHRONOUS,
+      client_maker_.MakeConnectionClosePacket(
+          packet_num++, true, quic::QUIC_PEER_GOING_AWAY, "net error"));
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
   client_maker_.Reset();
   MockQuicData socket_data2(version_);
   socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data2.AddSocketDataToFactory(socket_factory_.get());
 
   QuicStreamRequest request(factory_.get());
@@ -2116,7 +2149,8 @@
   client_maker_.Reset();
   MockQuicData socket_data2(version_);
   socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data2.AddSocketDataToFactory(socket_factory_.get());
 
   QuicStreamRequest request2(factory_.get());
@@ -2183,7 +2217,8 @@
   client_maker_.Reset();
   MockQuicData socket_data2(version_);
   socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data2.AddSocketDataToFactory(socket_factory_.get());
 
   QuicStreamRequest request2(factory_.get());
@@ -2222,18 +2257,25 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    socket_data.AddWrite(SYNCHRONOUS,
+                         ConstructInitialSettingsPacket(packet_num++));
+  }
   socket_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRstPacket(2, quic::QUIC_RST_ACKNOWLEDGEMENT));
+      SYNCHRONOUS,
+      ConstructClientRstPacket(packet_num++, quic::QUIC_RST_ACKNOWLEDGEMENT));
   socket_data.AddWrite(
-      SYNCHRONOUS, client_maker_.MakeConnectionClosePacket(
-                       3, true, quic::QUIC_IP_ADDRESS_CHANGED, "net error"));
+      SYNCHRONOUS,
+      client_maker_.MakeConnectionClosePacket(
+          packet_num, true, quic::QUIC_IP_ADDRESS_CHANGED, "net error"));
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
   client_maker_.Reset();
   MockQuicData socket_data2(version_);
   socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data2.AddSocketDataToFactory(socket_factory_.get());
 
   QuicStreamRequest request(factory_.get());
@@ -2252,7 +2294,7 @@
   EXPECT_EQ(OK, stream->InitializeStream(&request_info, false, DEFAULT_PRIORITY,
                                          net_log_, CompletionOnceCallback()));
 
-  // Check an active session exisits for the destination.
+  // Check an active session exists for the destination.
   EXPECT_TRUE(HasActiveSession(host_port_pair_));
   QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
   EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
@@ -2306,11 +2348,16 @@
   crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
 
   MockQuicData quic_data1(version_);
-  quic_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    quic_data1.AddWrite(SYNCHRONOUS,
+                        ConstructInitialSettingsPacket(packet_num++));
+  }
   quic_data1.AddWrite(
       SYNCHRONOUS,
-      ConstructGetRequestPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
+      ConstructGetRequestPacket(packet_num++,
+                                GetNthClientInitiatedBidirectionalStreamId(0),
+                                true, true));
   quic_data1.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
   quic_data1.AddRead(
       ASYNC,
@@ -2322,7 +2369,8 @@
   client_maker_.Reset();
   MockQuicData quic_data2(version_);
   quic_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // Hanging read.
-  quic_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
+  if (VersionUsesQpack(version_.transport_version))
+    quic_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   quic_data2.AddSocketDataToFactory(socket_factory_.get());
 
   // Create request and QuicHttpStream.
@@ -2406,9 +2454,14 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    socket_data.AddWrite(SYNCHRONOUS,
+                         ConstructInitialSettingsPacket(packet_num++));
+  }
   socket_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRstPacket(2, quic::QUIC_STREAM_CANCELLED));
+      SYNCHRONOUS,
+      ConstructClientRstPacket(packet_num, quic::QUIC_STREAM_CANCELLED));
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
   QuicStreamRequest request(factory_.get());
@@ -2478,35 +2531,41 @@
 
   MockQuicData quic_data1(version_);
   quic_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // Hanging Read.
-  quic_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    quic_data1.AddWrite(SYNCHRONOUS,
+                        ConstructInitialSettingsPacket(packet_num++));
+  }
   quic_data1.AddWrite(
       write_mode,
-      ConstructGetRequestPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
+      ConstructGetRequestPacket(packet_num++,
+                                GetNthClientInitiatedBidirectionalStreamId(0),
+                                true, true));
   quic_data1.AddSocketDataToFactory(socket_factory_.get());
 
   // Set up the second socket data provider that is used after migration.
   // The response to the earlier request is read on the new socket.
   MockQuicData quic_data2(version_);
   // Connectivity probe to be sent on the new path.
-  quic_data2.AddWrite(SYNCHRONOUS,
-                      client_maker_.MakeConnectivityProbingPacket(3, true));
+  quic_data2.AddWrite(SYNCHRONOUS, client_maker_.MakeConnectivityProbingPacket(
+                                       packet_num++, true));
   quic_data2.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
   // Connectivity probe to receive from the server.
   quic_data2.AddRead(ASYNC,
                      server_maker_.MakeConnectivityProbingPacket(1, false));
   // Ping packet to send after migration is completed.
-  quic_data2.AddWrite(ASYNC,
-                      client_maker_.MakeAckAndPingPacket(4, false, 1, 1, 1));
+  quic_data2.AddWrite(
+      ASYNC, client_maker_.MakeAckAndPingPacket(packet_num++, false, 1, 1, 1));
   quic_data2.AddRead(
       ASYNC,
       ConstructOkResponsePacket(
           2, GetNthClientInitiatedBidirectionalStreamId(0), false, false));
   quic_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   quic_data2.AddWrite(
-      SYNCHRONOUS, client_maker_.MakeAckAndRstPacket(
-                       5, false, GetNthClientInitiatedBidirectionalStreamId(0),
-                       quic::QUIC_STREAM_CANCELLED, 2, 2, 1, true));
+      SYNCHRONOUS,
+      client_maker_.MakeAckAndRstPacket(
+          packet_num, false, GetNthClientInitiatedBidirectionalStreamId(0),
+          quic::QUIC_STREAM_CANCELLED, 2, 2, 1, true));
   quic_data2.AddSocketDataToFactory(socket_factory_.get());
 
   // Create request and QuicHttpStream.
@@ -2651,38 +2710,44 @@
 
   MockQuicData quic_data1(version_);
   quic_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // Hanging Read.
-  quic_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    quic_data1.AddWrite(SYNCHRONOUS,
+                        ConstructInitialSettingsPacket(packet_num++));
+  }
   quic_data1.AddWrite(
       SYNCHRONOUS,
-      ConstructGetRequestPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
+      ConstructGetRequestPacket(packet_num++,
+                                GetNthClientInitiatedBidirectionalStreamId(0),
+                                true, true));
   quic_data1.AddSocketDataToFactory(socket_factory_.get());
 
   // Set up the second socket data provider that is used after migration.
   // The response to the earlier request is read on the new socket.
   MockQuicData quic_data2(version_);
   // First connectivity probe to be sent on the new path.
-  quic_data2.AddWrite(SYNCHRONOUS,
-                      client_maker_.MakeConnectivityProbingPacket(3, true));
+  quic_data2.AddWrite(SYNCHRONOUS, client_maker_.MakeConnectivityProbingPacket(
+                                       packet_num++, true));
   quic_data2.AddRead(ASYNC,
                      ERR_IO_PENDING);  // Pause so that we can control time.
   // Connectivity probe to receive from the server.
   quic_data2.AddRead(ASYNC,
                      server_maker_.MakeConnectivityProbingPacket(1, false));
   // Second connectivity probe which will complete asynchronously.
-  quic_data2.AddWrite(ASYNC,
-                      client_maker_.MakeConnectivityProbingPacket(4, true));
+  quic_data2.AddWrite(
+      ASYNC, client_maker_.MakeConnectivityProbingPacket(packet_num++, true));
   quic_data2.AddRead(
       ASYNC,
       ConstructOkResponsePacket(
           2, GetNthClientInitiatedBidirectionalStreamId(0), false, false));
   quic_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  quic_data2.AddWrite(ASYNC,
-                      client_maker_.MakeAckAndPingPacket(5, false, 1, 1, 1));
   quic_data2.AddWrite(
-      SYNCHRONOUS, client_maker_.MakeAckAndRstPacket(
-                       6, false, GetNthClientInitiatedBidirectionalStreamId(0),
-                       quic::QUIC_STREAM_CANCELLED, 2, 2, 1, true));
+      ASYNC, client_maker_.MakeAckAndPingPacket(packet_num++, false, 1, 1, 1));
+  quic_data2.AddWrite(
+      SYNCHRONOUS,
+      client_maker_.MakeAckAndRstPacket(
+          packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0),
+          quic::QUIC_STREAM_CANCELLED, 2, 2, 1, true));
 
   quic_data2.AddSocketDataToFactory(socket_factory_.get());
 
@@ -2827,7 +2892,8 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
   // Create request and QuicHttpStream.
@@ -2910,16 +2976,20 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    socket_data.AddWrite(SYNCHRONOUS,
+                         ConstructInitialSettingsPacket(packet_num++));
+  }
   if (!migrate_idle_sessions) {
     socket_data.AddWrite(
-        SYNCHRONOUS,
-        client_maker_.MakeRstAckAndConnectionClosePacket(
-            3, false, GetNthClientInitiatedBidirectionalStreamId(0),
-            quic::QUIC_STREAM_CANCELLED,
-            quic::QuicTime::Delta::FromMilliseconds(0), 1, 1, 1,
-            quic::QUIC_CONNECTION_MIGRATION_NO_MIGRATABLE_STREAMS,
-            "net error"));
+        SYNCHRONOUS, client_maker_.MakeRstAckAndConnectionClosePacket(
+                         packet_num + 1, false,
+                         GetNthClientInitiatedBidirectionalStreamId(0),
+                         quic::QUIC_STREAM_CANCELLED,
+                         quic::QuicTime::Delta::FromMilliseconds(0), 1, 1, 1,
+                         quic::QUIC_CONNECTION_MIGRATION_NO_MIGRATABLE_STREAMS,
+                         "net error"));
   }
 
   socket_data.AddSocketDataToFactory(socket_factory_.get());
@@ -2927,8 +2997,8 @@
   // Set up the second socket data provider that is used for probing.
   MockQuicData quic_data1(version_);
   // Connectivity probe to be sent on the new path.
-  quic_data1.AddWrite(SYNCHRONOUS,
-                      client_maker_.MakeConnectivityProbingPacket(2, true));
+  quic_data1.AddWrite(SYNCHRONOUS, client_maker_.MakeConnectivityProbingPacket(
+                                       packet_num++, true));
   quic_data1.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
   // Connectivity probe to receive from the server.
   quic_data1.AddRead(ASYNC,
@@ -2939,11 +3009,11 @@
     quic_data1.AddWrite(
         SYNCHRONOUS,
         client_maker_.MakeRstPacket(
-            3, false, GetNthClientInitiatedBidirectionalStreamId(0),
+            packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0),
             quic::QUIC_STREAM_CANCELLED));
     // Ping packet to send after migration is completed.
-    quic_data1.AddWrite(SYNCHRONOUS,
-                        client_maker_.MakeAckAndPingPacket(4, false, 1, 1, 1));
+    quic_data1.AddWrite(SYNCHRONOUS, client_maker_.MakeAckAndPingPacket(
+                                         packet_num++, false, 1, 1, 1));
   }
   quic_data1.AddSocketDataToFactory(socket_factory_.get());
 
@@ -3005,11 +3075,16 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    socket_data.AddWrite(SYNCHRONOUS,
+                         ConstructInitialSettingsPacket(packet_num++));
+  }
   socket_data.AddWrite(
-      SYNCHRONOUS, client_maker_.MakeRstPacket(
-                       2, true, GetNthClientInitiatedBidirectionalStreamId(0),
-                       quic::QUIC_STREAM_CANCELLED));
+      SYNCHRONOUS,
+      client_maker_.MakeRstPacket(packet_num++, true,
+                                  GetNthClientInitiatedBidirectionalStreamId(0),
+                                  quic::QUIC_STREAM_CANCELLED));
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
   // Create request and QuicHttpStream.
@@ -3078,27 +3153,37 @@
   MockQuicData socket_data(version_);
   if (migrate_idle_sessions) {
     failed_socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-    failed_socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+    int packet_num = 1;
+    if (VersionUsesQpack(version_.transport_version)) {
+      failed_socket_data.AddWrite(SYNCHRONOUS,
+                                  ConstructInitialSettingsPacket(packet_num++));
+    }
     // A RESET will be sent to the peer to cancel the non-migratable stream.
     failed_socket_data.AddWrite(
-        SYNCHRONOUS, client_maker_.MakeRstPacket(
-                         2, true, GetNthClientInitiatedBidirectionalStreamId(0),
-                         quic::QUIC_STREAM_CANCELLED));
+        SYNCHRONOUS,
+        client_maker_.MakeRstPacket(
+            packet_num++, true, GetNthClientInitiatedBidirectionalStreamId(0),
+            quic::QUIC_STREAM_CANCELLED));
     failed_socket_data.AddSocketDataToFactory(socket_factory_.get());
 
     // Set up second socket data provider that is used after migration.
     socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // Hanging read.
     // Ping packet to send after migration.
     socket_data.AddWrite(
-        SYNCHRONOUS, client_maker_.MakePingPacket(3, /*include_version=*/true));
+        SYNCHRONOUS,
+        client_maker_.MakePingPacket(packet_num++, /*include_version=*/true));
     socket_data.AddSocketDataToFactory(socket_factory_.get());
   } else {
     socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-    socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+    int packet_num = 1;
+    if (VersionUsesQpack(version_.transport_version))
+      socket_data.AddWrite(SYNCHRONOUS,
+                           ConstructInitialSettingsPacket(packet_num++));
     socket_data.AddWrite(
-        SYNCHRONOUS, client_maker_.MakeRstPacket(
-                         2, true, GetNthClientInitiatedBidirectionalStreamId(0),
-                         quic::QUIC_STREAM_CANCELLED));
+        SYNCHRONOUS,
+        client_maker_.MakeRstPacket(
+            packet_num++, true, GetNthClientInitiatedBidirectionalStreamId(0),
+            quic::QUIC_STREAM_CANCELLED));
     socket_data.AddSocketDataToFactory(socket_factory_.get());
   }
 
@@ -3159,11 +3244,16 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    socket_data.AddWrite(SYNCHRONOUS,
+                         ConstructInitialSettingsPacket(packet_num++));
+  }
   socket_data.AddWrite(
-      SYNCHRONOUS, client_maker_.MakeRstPacket(
-                       2, true, GetNthClientInitiatedBidirectionalStreamId(0),
-                       quic::QUIC_RST_ACKNOWLEDGEMENT));
+      SYNCHRONOUS,
+      client_maker_.MakeRstPacket(packet_num++, true,
+                                  GetNthClientInitiatedBidirectionalStreamId(0),
+                                  quic::QUIC_RST_ACKNOWLEDGEMENT));
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
   // Create request and QuicHttpStream.
@@ -3228,13 +3318,17 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    socket_data.AddWrite(SYNCHRONOUS,
+                         ConstructInitialSettingsPacket(packet_num++));
+  }
   if (!migrate_idle_sessions) {
     socket_data.AddWrite(
-        SYNCHRONOUS,
-        client_maker_.MakeConnectionClosePacket(
-            2, true, quic::QUIC_CONNECTION_MIGRATION_NO_MIGRATABLE_STREAMS,
-            "net error"));
+        SYNCHRONOUS, client_maker_.MakeConnectionClosePacket(
+                         packet_num, true,
+                         quic::QUIC_CONNECTION_MIGRATION_NO_MIGRATABLE_STREAMS,
+                         "net error"));
   }
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
@@ -3242,16 +3336,17 @@
   if (migrate_idle_sessions) {
     // Set up the second socket data provider that is used for probing.
     // Connectivity probe to be sent on the new path.
-    quic_data1.AddWrite(SYNCHRONOUS,
-                        client_maker_.MakeConnectivityProbingPacket(2, true));
+    quic_data1.AddWrite(
+        SYNCHRONOUS,
+        client_maker_.MakeConnectivityProbingPacket(packet_num++, true));
     quic_data1.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
     // Connectivity probe to receive from the server.
     quic_data1.AddRead(ASYNC,
                        server_maker_.MakeConnectivityProbingPacket(1, false));
     quic_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // Hanging read.
     // Ping packet to send after migration is completed.
-    quic_data1.AddWrite(SYNCHRONOUS,
-                        client_maker_.MakeAckAndPingPacket(3, false, 1, 1, 1));
+    quic_data1.AddWrite(SYNCHRONOUS, client_maker_.MakeAckAndPingPacket(
+                                         packet_num, false, 1, 1, 1));
     quic_data1.AddSocketDataToFactory(socket_factory_.get());
   }
 
@@ -3309,7 +3404,11 @@
 
   MockQuicData default_socket_data(version_);
   default_socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  default_socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    default_socket_data.AddWrite(SYNCHRONOUS,
+                                 ConstructInitialSettingsPacket(packet_num++));
+  }
   default_socket_data.AddSocketDataToFactory(socket_factory_.get());
 
   MockQuicData alternate_socket_data(version_);
@@ -3319,7 +3418,8 @@
                                   ERR_IO_PENDING);  // Hanging read.
     // Ping packet to send after migration.
     alternate_socket_data.AddWrite(
-        SYNCHRONOUS, client_maker_.MakePingPacket(2, /*include_version=*/true));
+        SYNCHRONOUS,
+        client_maker_.MakePingPacket(packet_num, /*include_version=*/true));
     alternate_socket_data.AddSocketDataToFactory(socket_factory_.get());
   }
 
@@ -3381,8 +3481,10 @@
   int packet_number = 1;
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS,
-                       ConstructInitialSettingsPacket(packet_number++));
+  if (VersionUsesQpack(version_.transport_version)) {
+    socket_data.AddWrite(SYNCHRONOUS,
+                         ConstructInitialSettingsPacket(packet_number++));
+  }
   socket_data.AddWrite(
       SYNCHRONOUS,
       ConstructGetRequestPacket(packet_number++,
@@ -3504,11 +3606,16 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    socket_data.AddWrite(SYNCHRONOUS,
+                         ConstructInitialSettingsPacket(packet_num++));
+  }
   socket_data.AddWrite(
       SYNCHRONOUS,
-      ConstructGetRequestPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
+      ConstructGetRequestPacket(packet_num++,
+                                GetNthClientInitiatedBidirectionalStreamId(0),
+                                true, true));
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
   // Create request and QuicHttpStream.
@@ -3558,16 +3665,18 @@
   // The response to the earlier request is read on this new socket.
   MockQuicData socket_data1(version_);
   socket_data1.AddWrite(
-      SYNCHRONOUS, client_maker_.MakePingPacket(3, /*include_version=*/true));
+      SYNCHRONOUS,
+      client_maker_.MakePingPacket(packet_num++, /*include_version=*/true));
   socket_data1.AddRead(
       ASYNC,
       ConstructOkResponsePacket(
           1, GetNthClientInitiatedBidirectionalStreamId(0), false, false));
   socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   socket_data1.AddWrite(
-      SYNCHRONOUS, client_maker_.MakeAckAndRstPacket(
-                       4, false, GetNthClientInitiatedBidirectionalStreamId(0),
-                       quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true));
+      SYNCHRONOUS,
+      client_maker_.MakeAckAndRstPacket(
+          packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0),
+          quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true));
   socket_data1.AddSocketDataToFactory(socket_factory_.get());
 
   // Add a new network and notify the stream factory of a new connected network.
@@ -3632,8 +3741,10 @@
   int packet_number = 1;
   MockQuicData quic_data1(version_);
   quic_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // Hanging Read.
-  quic_data1.AddWrite(SYNCHRONOUS,
-                      ConstructInitialSettingsPacket(packet_number++));
+  if (VersionUsesQpack(version_.transport_version)) {
+    quic_data1.AddWrite(SYNCHRONOUS,
+                        ConstructInitialSettingsPacket(packet_number++));
+  }
   quic_data1.AddWrite(
       SYNCHRONOUS,
       ConstructGetRequestPacket(packet_number++,
@@ -3808,8 +3919,10 @@
   int packet_number = 1;
   MockQuicData quic_data1(version_);
   quic_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // Hanging Read.
-  quic_data1.AddWrite(SYNCHRONOUS,
-                      ConstructInitialSettingsPacket(packet_number++));
+  if (VersionUsesQpack(version_.transport_version)) {
+    quic_data1.AddWrite(SYNCHRONOUS,
+                        ConstructInitialSettingsPacket(packet_number++));
+  }
   quic_data1.AddWrite(
       SYNCHRONOUS,
       ConstructGetRequestPacket(packet_number++,
@@ -3962,11 +4075,16 @@
   crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
 
   MockQuicData quic_data1(version_);
-  quic_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    quic_data1.AddWrite(SYNCHRONOUS,
+                        ConstructInitialSettingsPacket(packet_num++));
+  }
   quic_data1.AddWrite(
       SYNCHRONOUS,
-      ConstructGetRequestPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
+      ConstructGetRequestPacket(packet_num,
+                                GetNthClientInitiatedBidirectionalStreamId(0),
+                                true, true));
   quic_data1.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
   quic_data1.AddRead(
       ASYNC,
@@ -3978,7 +4096,8 @@
   client_maker_.Reset();
   MockQuicData quic_data2(version_);
   quic_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // Hanging read.
-  quic_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    quic_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   quic_data2.AddSocketDataToFactory(socket_factory_.get());
 
   // Creat request and QuicHttpStream.
@@ -4073,20 +4192,26 @@
       ->QueueNetworkMadeDefault(kDefaultNetworkForTests);
 
   MockQuicData quic_data(version_);
-  quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    quic_data.AddWrite(SYNCHRONOUS,
+                       ConstructInitialSettingsPacket(packet_num++));
+  }
   quic_data.AddWrite(
       SYNCHRONOUS,
-      ConstructGetRequestPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
+      ConstructGetRequestPacket(packet_num++,
+                                GetNthClientInitiatedBidirectionalStreamId(0),
+                                true, true));
   quic_data.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
   quic_data.AddRead(ASYNC, ConstructOkResponsePacket(
                                1, GetNthClientInitiatedBidirectionalStreamId(0),
                                false, false));
   quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   quic_data.AddWrite(
-      SYNCHRONOUS, client_maker_.MakeAckAndRstPacket(
-                       3, false, GetNthClientInitiatedBidirectionalStreamId(0),
-                       quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true));
+      SYNCHRONOUS,
+      client_maker_.MakeAckAndRstPacket(
+          packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0),
+          quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true));
   quic_data.AddSocketDataToFactory(socket_factory_.get());
 
   // Set up second socket that will immediately return disconnected.
@@ -4190,8 +4315,10 @@
 
   int packet_number = 1;
   MockQuicData quic_data1(version_);
-  quic_data1.AddWrite(SYNCHRONOUS,
-                      ConstructInitialSettingsPacket(packet_number++));
+  if (VersionUsesQpack(version_.transport_version)) {
+    quic_data1.AddWrite(SYNCHRONOUS,
+                        ConstructInitialSettingsPacket(packet_number++));
+  }
   quic_data1.AddWrite(
       SYNCHRONOUS,
       ConstructGetRequestPacket(packet_number++,
@@ -4356,35 +4483,41 @@
 
   MockQuicData quic_data1(version_);
   quic_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // Hanging Read.
-  quic_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    quic_data1.AddWrite(SYNCHRONOUS,
+                        ConstructInitialSettingsPacket(packet_num++));
+  }
   quic_data1.AddWrite(
       SYNCHRONOUS,
-      ConstructGetRequestPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
+      ConstructGetRequestPacket(packet_num++,
+                                GetNthClientInitiatedBidirectionalStreamId(0),
+                                true, true));
   quic_data1.AddSocketDataToFactory(socket_factory_.get());
 
   // Set up the second socket data provider that is used after migration.
   // The response to the earlier request is read on the new socket.
   MockQuicData quic_data2(version_);
   // Connectivity probe to be sent on the new path.
-  quic_data2.AddWrite(SYNCHRONOUS,
-                      client_maker_.MakeConnectivityProbingPacket(3, true));
+  quic_data2.AddWrite(SYNCHRONOUS, client_maker_.MakeConnectivityProbingPacket(
+                                       packet_num++, true));
   quic_data2.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
   // Connectivity probe to receive from the server.
   quic_data2.AddRead(ASYNC,
                      server_maker_.MakeConnectivityProbingPacket(1, false));
   // Ping packet to send after migration is completed.
-  quic_data2.AddWrite(ASYNC,
-                      client_maker_.MakeAckAndPingPacket(4, false, 1, 1, 1));
+  quic_data2.AddWrite(
+      ASYNC, client_maker_.MakeAckAndPingPacket(packet_num++, false, 1, 1, 1));
   quic_data2.AddRead(
       ASYNC,
       ConstructOkResponsePacket(
           2, GetNthClientInitiatedBidirectionalStreamId(0), false, false));
   quic_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   quic_data2.AddWrite(
-      SYNCHRONOUS, client_maker_.MakeAckAndRstPacket(
-                       5, false, GetNthClientInitiatedBidirectionalStreamId(0),
-                       quic::QUIC_STREAM_CANCELLED, 2, 2, 1, true));
+      SYNCHRONOUS,
+      client_maker_.MakeAckAndRstPacket(
+          packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0),
+          quic::QUIC_STREAM_CANCELLED, 2, 2, 1, true));
   quic_data2.AddSocketDataToFactory(socket_factory_.get());
 
   // Create request and QuicHttpStream.
@@ -4508,13 +4641,15 @@
 
   MockQuicData socket_data1(version_);
   socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data1.AddWrite(ASYNC, OK);
   socket_data1.AddSocketDataToFactory(socket_factory_.get());
   client_maker_.Reset();
   MockQuicData socket_data2(version_);
   socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data2.AddWrite(ASYNC, OK);
   socket_data2.AddSocketDataToFactory(socket_factory_.get());
 
@@ -4633,11 +4768,16 @@
   crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
 
   MockQuicData quic_data(version_);
-  quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    quic_data.AddWrite(SYNCHRONOUS,
+                       ConstructInitialSettingsPacket(packet_num++));
+  }
   quic_data.AddWrite(
       SYNCHRONOUS,
-      ConstructGetRequestPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
+      ConstructGetRequestPacket(packet_num++,
+                                GetNthClientInitiatedBidirectionalStreamId(0),
+                                true, true));
   quic_data.AddRead(ASYNC, ERR_IO_PENDING);  // Pause for path degrading signal.
 
   // The rest of the data will still flow in the original socket as there is no
@@ -4647,9 +4787,10 @@
                                false, false));
   quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   quic_data.AddWrite(
-      SYNCHRONOUS, client_maker_.MakeAckAndRstPacket(
-                       3, false, GetNthClientInitiatedBidirectionalStreamId(0),
-                       quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true));
+      SYNCHRONOUS,
+      client_maker_.MakeAckAndRstPacket(
+          packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0),
+          quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true));
   quic_data.AddSocketDataToFactory(socket_factory_.get());
 
   // Create request and QuicHttpStream.
@@ -4730,24 +4871,28 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    socket_data.AddWrite(SYNCHRONOUS,
+                         ConstructInitialSettingsPacket(packet_num++));
+  }
   if (!migrate_idle_sessions) {
     socket_data.AddWrite(
-        SYNCHRONOUS,
-        client_maker_.MakeRstAckAndConnectionClosePacket(
-            3, false, GetNthClientInitiatedBidirectionalStreamId(0),
-            quic::QUIC_STREAM_CANCELLED,
-            quic::QuicTime::Delta::FromMilliseconds(0), 1, 1, 1,
-            quic::QUIC_CONNECTION_MIGRATION_NO_MIGRATABLE_STREAMS,
-            "net error"));
+        SYNCHRONOUS, client_maker_.MakeRstAckAndConnectionClosePacket(
+                         packet_num + 1, false,
+                         GetNthClientInitiatedBidirectionalStreamId(0),
+                         quic::QUIC_STREAM_CANCELLED,
+                         quic::QuicTime::Delta::FromMilliseconds(0), 1, 1, 1,
+                         quic::QUIC_CONNECTION_MIGRATION_NO_MIGRATABLE_STREAMS,
+                         "net error"));
   }
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
   // Set up the second socket data provider that is used for probing.
   MockQuicData quic_data1(version_);
   // Connectivity probe to be sent on the new path.
-  quic_data1.AddWrite(SYNCHRONOUS,
-                      client_maker_.MakeConnectivityProbingPacket(2, true));
+  quic_data1.AddWrite(SYNCHRONOUS, client_maker_.MakeConnectivityProbingPacket(
+                                       packet_num++, true));
   quic_data1.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
   // Connectivity probe to receive from the server.
   quic_data1.AddRead(ASYNC,
@@ -4758,11 +4903,11 @@
     quic_data1.AddWrite(
         SYNCHRONOUS,
         client_maker_.MakeRstPacket(
-            3, false, GetNthClientInitiatedBidirectionalStreamId(0),
+            packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0),
             quic::QUIC_STREAM_CANCELLED));
     // Ping packet to send after migration is completed.
-    quic_data1.AddWrite(SYNCHRONOUS,
-                        client_maker_.MakeAckAndPingPacket(4, false, 1, 1, 1));
+    quic_data1.AddWrite(SYNCHRONOUS, client_maker_.MakeAckAndPingPacket(
+                                         packet_num++, false, 1, 1, 1));
   }
   quic_data1.AddSocketDataToFactory(socket_factory_.get());
 
@@ -4825,11 +4970,16 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    socket_data.AddWrite(SYNCHRONOUS,
+                         ConstructInitialSettingsPacket(packet_num++));
+  }
   socket_data.AddWrite(
-      SYNCHRONOUS, client_maker_.MakeRstPacket(
-                       2, true, GetNthClientInitiatedBidirectionalStreamId(0),
-                       quic::QUIC_STREAM_CANCELLED));
+      SYNCHRONOUS,
+      client_maker_.MakeRstPacket(packet_num++, true,
+                                  GetNthClientInitiatedBidirectionalStreamId(0),
+                                  quic::QUIC_STREAM_CANCELLED));
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
   // Create request and QuicHttpStream.
@@ -4898,7 +5048,11 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    socket_data.AddWrite(SYNCHRONOUS,
+                         ConstructInitialSettingsPacket(packet_num++));
+  }
   socket_data.AddWrite(ASYNC, ERR_ADDRESS_UNREACHABLE);
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
@@ -4908,13 +5062,14 @@
   MockQuicData socket_data1(version_);
   socket_data1.AddWrite(
       SYNCHRONOUS,
-      ConstructGetRequestPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
+      ConstructGetRequestPacket(packet_num++,
+                                GetNthClientInitiatedBidirectionalStreamId(0),
+                                true, true));
   client_maker_.set_coalesce_http_frames(true);
   socket_data1.AddWrite(
       SYNCHRONOUS,
       ConstructGetRequestPacket(
-          3, GetNthClientInitiatedBidirectionalStreamId(1),
+          packet_num++, GetNthClientInitiatedBidirectionalStreamId(1),
           GetNthClientInitiatedBidirectionalStreamId(0), true, true));
   socket_data1.AddRead(
       ASYNC,
@@ -4922,14 +5077,16 @@
           1, GetNthClientInitiatedBidirectionalStreamId(0), false, false));
   socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   socket_data1.AddWrite(
-      SYNCHRONOUS, client_maker_.MakeAckAndRstPacket(
-                       4, false, GetNthClientInitiatedBidirectionalStreamId(0),
-                       quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true));
+      SYNCHRONOUS,
+      client_maker_.MakeAckAndRstPacket(
+          packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0),
+          quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true));
   socket_data1.AddWrite(
-      SYNCHRONOUS, client_maker_.MakeRstPacket(
-                       5, false, GetNthClientInitiatedBidirectionalStreamId(1),
-                       quic::QUIC_STREAM_CANCELLED,
-                       /*include_stop_sending_if_v99=*/true));
+      SYNCHRONOUS,
+      client_maker_.MakeRstPacket(packet_num++, false,
+                                  GetNthClientInitiatedBidirectionalStreamId(1),
+                                  quic::QUIC_STREAM_CANCELLED,
+                                  /*include_stop_sending_if_v99=*/true));
 
   socket_data1.AddSocketDataToFactory(socket_factory_.get());
 
@@ -5049,7 +5206,11 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    socket_data.AddWrite(SYNCHRONOUS,
+                         ConstructInitialSettingsPacket(packet_num++));
+  }
   socket_data.AddWrite(ASYNC, ERR_ADDRESS_UNREACHABLE);
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
@@ -5059,8 +5220,9 @@
   MockQuicData quic_data2(version_);
   quic_data2.AddWrite(
       SYNCHRONOUS,
-      ConstructGetRequestPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
+      ConstructGetRequestPacket(packet_num++,
+                                GetNthClientInitiatedBidirectionalStreamId(0),
+                                true, true));
   quic_data2.AddRead(
       ASYNC,
       ConstructOkResponsePacket(
@@ -5130,18 +5292,20 @@
   // Set up the third socket data provider for migrate back to default network.
   MockQuicData quic_data3(version_);
   // Connectivity probe to be sent on the new path.
-  quic_data3.AddWrite(SYNCHRONOUS,
-                      client_maker_.MakeConnectivityProbingPacket(3, false));
+  quic_data3.AddWrite(SYNCHRONOUS, client_maker_.MakeConnectivityProbingPacket(
+                                       packet_num++, false));
   // Connectivity probe to receive from the server.
   quic_data3.AddRead(ASYNC,
                      server_maker_.MakeConnectivityProbingPacket(2, false));
   quic_data3.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  quic_data3.AddWrite(ASYNC, client_maker_.MakeAckPacket(4, 1, 2, 1, 1, true));
   quic_data3.AddWrite(
-      SYNCHRONOUS, client_maker_.MakeRstPacket(
-                       5, false, GetNthClientInitiatedBidirectionalStreamId(0),
-                       quic::QUIC_STREAM_CANCELLED,
-                       /*include_stop_sending_if_v99=*/true));
+      ASYNC, client_maker_.MakeAckPacket(packet_num++, 1, 2, 1, 1, true));
+  quic_data3.AddWrite(
+      SYNCHRONOUS,
+      client_maker_.MakeRstPacket(packet_num++, false,
+                                  GetNthClientInitiatedBidirectionalStreamId(0),
+                                  quic::QUIC_STREAM_CANCELLED,
+                                  /*include_stop_sending_if_v99=*/true));
   quic_data3.AddSocketDataToFactory(socket_factory_.get());
 
   // Fast forward to fire the migrate back timer and verify the session
@@ -5344,30 +5508,36 @@
 
   // Socket data for connection on the alternate network.
   MockQuicData socket_data2(version_);
-  socket_data2.AddWrite(SYNCHRONOUS, client_maker_.MakeDummyCHLOPacket(1));
+  int packet_num = 1;
+  socket_data2.AddWrite(SYNCHRONOUS,
+                        client_maker_.MakeDummyCHLOPacket(packet_num++));
   socket_data2.AddRead(ASYNC, ERR_IO_PENDING);  // Pause.
   // Change the encryption level after handshake is confirmed.
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
-  socket_data2.AddWrite(ASYNC, ConstructInitialSettingsPacket(2));
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data2.AddWrite(ASYNC, ConstructInitialSettingsPacket(packet_num++));
   socket_data2.AddWrite(
       ASYNC, ConstructGetRequestPacket(
-                 3, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
+                 packet_num++, GetNthClientInitiatedBidirectionalStreamId(0),
+                 true, true));
   socket_data2.AddRead(
       ASYNC,
       ConstructOkResponsePacket(
           1, GetNthClientInitiatedBidirectionalStreamId(0), false, false));
   socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   socket_data2.AddWrite(
-      SYNCHRONOUS, client_maker_.MakeAckAndRstPacket(
-                       5, false, GetNthClientInitiatedBidirectionalStreamId(0),
-                       quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true));
+      SYNCHRONOUS,
+      client_maker_.MakeAckAndRstPacket(
+          packet_num + 1, false, GetNthClientInitiatedBidirectionalStreamId(0),
+          quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true));
   socket_data2.AddSocketDataToFactory(socket_factory_.get());
 
   // Socket data for probing on the default network.
   MockQuicData probing_data(version_);
   probing_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // Hanging read.
-  probing_data.AddWrite(SYNCHRONOUS,
-                        client_maker_.MakeConnectivityProbingPacket(4, false));
+  probing_data.AddWrite(
+      SYNCHRONOUS,
+      client_maker_.MakeConnectivityProbingPacket(packet_num, false));
   probing_data.AddSocketDataToFactory(socket_factory_.get());
 
   // Create request and QuicHttpStream.
@@ -5507,7 +5677,8 @@
   client_maker_.Reset();
   MockQuicData socket_data2(version_);
   socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data2.AddSocketDataToFactory(socket_factory_.get());
 
   QuicStreamRequest request2(factory_.get());
@@ -5561,23 +5732,28 @@
 
   // Socket data for connection on the alternate network.
   MockQuicData socket_data2(version_);
-  socket_data2.AddWrite(SYNCHRONOUS, client_maker_.MakeDummyCHLOPacket(1));
+  int packet_num = 1;
+  socket_data2.AddWrite(SYNCHRONOUS,
+                        client_maker_.MakeDummyCHLOPacket(packet_num++));
   socket_data2.AddRead(ASYNC, ERR_IO_PENDING);  // Pause.
   // Change the encryption level after handshake is confirmed.
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
-  socket_data2.AddWrite(ASYNC, ConstructInitialSettingsPacket(2));
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data2.AddWrite(ASYNC, ConstructInitialSettingsPacket(packet_num++));
   socket_data2.AddWrite(
       ASYNC, ConstructGetRequestPacket(
-                 3, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
+                 packet_num++, GetNthClientInitiatedBidirectionalStreamId(0),
+                 true, true));
   socket_data2.AddRead(
       ASYNC,
       ConstructOkResponsePacket(
           1, GetNthClientInitiatedBidirectionalStreamId(0), false, false));
   socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   socket_data2.AddWrite(
-      SYNCHRONOUS, client_maker_.MakeAckAndRstPacket(
-                       4, false, GetNthClientInitiatedBidirectionalStreamId(0),
-                       quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true));
+      SYNCHRONOUS,
+      client_maker_.MakeAckAndRstPacket(
+          packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0),
+          quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true));
   socket_data2.AddSocketDataToFactory(socket_factory_.get());
 
   // Create request, should fail after the write of the CHLO fails.
@@ -5644,7 +5820,11 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    socket_data.AddWrite(SYNCHRONOUS,
+                         ConstructInitialSettingsPacket(packet_num++));
+  }
   socket_data.AddWrite(write_error_mode, ERR_ADDRESS_UNREACHABLE);
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
@@ -5680,17 +5860,19 @@
   MockQuicData socket_data1(version_);
   socket_data1.AddWrite(
       SYNCHRONOUS,
-      ConstructGetRequestPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
+      ConstructGetRequestPacket(packet_num++,
+                                GetNthClientInitiatedBidirectionalStreamId(0),
+                                true, true));
   socket_data1.AddRead(
       ASYNC,
       ConstructOkResponsePacket(
           1, GetNthClientInitiatedBidirectionalStreamId(0), false, false));
   socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   socket_data1.AddWrite(
-      SYNCHRONOUS, client_maker_.MakeAckAndRstPacket(
-                       3, false, GetNthClientInitiatedBidirectionalStreamId(0),
-                       quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true));
+      SYNCHRONOUS,
+      client_maker_.MakeAckAndRstPacket(
+          packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0),
+          quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true));
   socket_data1.AddSocketDataToFactory(socket_factory_.get());
 
   // Send GET request on stream. This should cause a write error, which triggers
@@ -5741,7 +5923,8 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data.AddWrite(write_error_mode, ERR_ADDRESS_UNREACHABLE);
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
@@ -5851,7 +6034,11 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    socket_data.AddWrite(SYNCHRONOUS,
+                         ConstructInitialSettingsPacket(packet_num++));
+  }
   socket_data.AddWrite(write_error_mode, ERR_ADDRESS_UNREACHABLE);
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
@@ -5861,22 +6048,25 @@
   MockQuicData socket_data1(version_);
   socket_data1.AddWrite(
       SYNCHRONOUS,
-      ConstructGetRequestPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
+      ConstructGetRequestPacket(packet_num++,
+                                GetNthClientInitiatedBidirectionalStreamId(0),
+                                true, true));
   socket_data1.AddRead(
       ASYNC,
       ConstructOkResponsePacket(
           1, GetNthClientInitiatedBidirectionalStreamId(0), false, false));
   socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   socket_data1.AddWrite(
-      SYNCHRONOUS, client_maker_.MakeAckAndRstPacket(
-                       3, false, GetNthClientInitiatedBidirectionalStreamId(0),
-                       quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true));
+      SYNCHRONOUS,
+      client_maker_.MakeAckAndRstPacket(
+          packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0),
+          quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true));
   socket_data1.AddWrite(
-      SYNCHRONOUS, client_maker_.MakeRstPacket(
-                       4, false, GetNthClientInitiatedBidirectionalStreamId(1),
-                       quic::QUIC_STREAM_CANCELLED,
-                       /*include_stop_sending_if_v99=*/true));
+      SYNCHRONOUS,
+      client_maker_.MakeRstPacket(packet_num++, false,
+                                  GetNthClientInitiatedBidirectionalStreamId(1),
+                                  quic::QUIC_STREAM_CANCELLED,
+                                  /*include_stop_sending_if_v99=*/true));
 
   socket_data1.AddSocketDataToFactory(socket_factory_.get());
 
@@ -5983,8 +6173,10 @@
   MockQuicData socket_data(version_);
 
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS,
-                       ConstructInitialSettingsPacket(packet_number++));
+  if (VersionUsesQpack(version_.transport_version)) {
+    socket_data.AddWrite(SYNCHRONOUS,
+                         ConstructInitialSettingsPacket(packet_number++));
+  }
   socket_data.AddWrite(write_error_mode, ERR_ADDRESS_UNREACHABLE);
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
@@ -6120,8 +6312,10 @@
   int packet_number = 1;
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS,
-                       ConstructInitialSettingsPacket(packet_number++));
+  if (VersionUsesQpack(version_.transport_version)) {
+    socket_data.AddWrite(SYNCHRONOUS,
+                         ConstructInitialSettingsPacket(packet_number++));
+  }
   socket_data.AddWrite(write_error_mode,
                        ERR_ADDRESS_UNREACHABLE);  // Write error.
   socket_data.AddSocketDataToFactory(socket_factory_.get());
@@ -6262,10 +6456,14 @@
 
   MockQuicData failed_socket_data(version_);
   MockQuicData socket_data(version_);
+  int packet_num = 1;
   if (migrate_idle_sessions) {
     // The socket data provider for the original socket before migration.
     failed_socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-    failed_socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+    if (VersionUsesQpack(version_.transport_version)) {
+      failed_socket_data.AddWrite(SYNCHRONOUS,
+                                  ConstructInitialSettingsPacket(packet_num++));
+    }
     failed_socket_data.AddWrite(write_error_mode, ERR_ADDRESS_UNREACHABLE);
     failed_socket_data.AddSocketDataToFactory(socket_factory_.get());
 
@@ -6276,17 +6474,20 @@
     // the packet will still be retransimitted at the connection level.
     socket_data.AddWrite(
         SYNCHRONOUS,
-        ConstructGetRequestPacket(
-            2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
+        ConstructGetRequestPacket(packet_num++,
+                                  GetNthClientInitiatedBidirectionalStreamId(0),
+                                  true, true));
     // A RESET will be sent to the peer to cancel the non-migratable stream.
     socket_data.AddWrite(
-        SYNCHRONOUS, client_maker_.MakeRstPacket(
-                         3, true, GetNthClientInitiatedBidirectionalStreamId(0),
-                         quic::QUIC_STREAM_CANCELLED));
+        SYNCHRONOUS,
+        client_maker_.MakeRstPacket(
+            packet_num++, true, GetNthClientInitiatedBidirectionalStreamId(0),
+            quic::QUIC_STREAM_CANCELLED));
     socket_data.AddSocketDataToFactory(socket_factory_.get());
   } else {
     socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-    socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+    if (VersionUsesQpack(version_.transport_version))
+      socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
     socket_data.AddWrite(write_error_mode, ERR_ADDRESS_UNREACHABLE);
     socket_data.AddSocketDataToFactory(socket_factory_.get());
   }
@@ -6374,7 +6575,8 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data.AddWrite(write_error_mode, ERR_ADDRESS_UNREACHABLE);
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
@@ -6464,7 +6666,11 @@
   // write erorr.
   MockQuicData socket_data1(version_);
   socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    socket_data1.AddWrite(SYNCHRONOUS,
+                          ConstructInitialSettingsPacket(packet_num++));
+  }
   socket_data1.AddWrite(write_error_mode_on_old_network,
                         ERR_ADDRESS_UNREACHABLE);  // Write Error
   socket_data1.AddSocketDataToFactory(socket_factory_.get());
@@ -6489,17 +6695,19 @@
   MockQuicData socket_data2(version_);
   socket_data2.AddWrite(
       SYNCHRONOUS,
-      ConstructGetRequestPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
+      ConstructGetRequestPacket(packet_num++,
+                                GetNthClientInitiatedBidirectionalStreamId(0),
+                                true, true));
   socket_data2.AddRead(
       ASYNC,
       ConstructOkResponsePacket(
           1, GetNthClientInitiatedBidirectionalStreamId(0), false, false));
   socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   socket_data2.AddWrite(
-      SYNCHRONOUS, client_maker_.MakeAckAndRstPacket(
-                       3, false, GetNthClientInitiatedBidirectionalStreamId(0),
-                       quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true));
+      SYNCHRONOUS,
+      client_maker_.MakeAckAndRstPacket(
+          packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0),
+          quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true));
   socket_data2.AddSocketDataToFactory(socket_factory_.get());
 
   // Create request and QuicHttpStream.
@@ -6630,7 +6838,11 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    socket_data.AddWrite(SYNCHRONOUS,
+                         ConstructInitialSettingsPacket(packet_num++));
+  }
   socket_data.AddWrite(SYNCHRONOUS, ERR_ADDRESS_UNREACHABLE);
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
@@ -6666,17 +6878,19 @@
   MockQuicData socket_data1(version_);
   socket_data1.AddWrite(
       SYNCHRONOUS,
-      ConstructGetRequestPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
+      ConstructGetRequestPacket(packet_num++,
+                                GetNthClientInitiatedBidirectionalStreamId(0),
+                                true, true));
   socket_data1.AddRead(
       ASYNC,
       ConstructOkResponsePacket(
           1, GetNthClientInitiatedBidirectionalStreamId(0), false, false));
   socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   socket_data1.AddWrite(
-      SYNCHRONOUS, client_maker_.MakeAckAndRstPacket(
-                       3, false, GetNthClientInitiatedBidirectionalStreamId(0),
-                       quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true));
+      SYNCHRONOUS,
+      client_maker_.MakeAckAndRstPacket(
+          packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0),
+          quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true));
   socket_data1.AddSocketDataToFactory(socket_factory_.get());
 
   // First queue a network change notification in the message loop.
@@ -6762,7 +6976,11 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    socket_data.AddWrite(SYNCHRONOUS,
+                         ConstructInitialSettingsPacket(packet_num++));
+  }
   socket_data.AddWrite(SYNCHRONOUS, ERR_ADDRESS_UNREACHABLE);
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
@@ -6798,17 +7016,19 @@
   MockQuicData socket_data1(version_);
   socket_data1.AddWrite(
       SYNCHRONOUS,
-      ConstructGetRequestPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
+      ConstructGetRequestPacket(packet_num++,
+                                GetNthClientInitiatedBidirectionalStreamId(0),
+                                true, true));
   socket_data1.AddRead(
       ASYNC,
       ConstructOkResponsePacket(
           1, GetNthClientInitiatedBidirectionalStreamId(0), false, false));
   socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   socket_data1.AddWrite(
-      SYNCHRONOUS, client_maker_.MakeAckAndRstPacket(
-                       3, false, GetNthClientInitiatedBidirectionalStreamId(0),
-                       quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true));
+      SYNCHRONOUS,
+      client_maker_.MakeAckAndRstPacket(
+          packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0),
+          quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true));
   socket_data1.AddSocketDataToFactory(socket_factory_.get());
 
   // Send GET request on stream. This should cause a write error,
@@ -6900,7 +7120,11 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // Hanging read.
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    socket_data.AddWrite(SYNCHRONOUS,
+                         ConstructInitialSettingsPacket(packet_num++));
+  }
   socket_data.AddWrite(write_error_mode, ERR_FAILED);
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
@@ -6947,17 +7171,19 @@
   MockQuicData socket_data1(version_);
   socket_data1.AddWrite(
       SYNCHRONOUS,
-      ConstructGetRequestPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
+      ConstructGetRequestPacket(packet_num++,
+                                GetNthClientInitiatedBidirectionalStreamId(0),
+                                true, true));
   socket_data1.AddRead(
       ASYNC,
       ConstructOkResponsePacket(
           1, GetNthClientInitiatedBidirectionalStreamId(0), false, false));
   socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   socket_data1.AddWrite(
-      SYNCHRONOUS, client_maker_.MakeAckAndRstPacket(
-                       3, false, GetNthClientInitiatedBidirectionalStreamId(0),
-                       quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true));
+      SYNCHRONOUS,
+      client_maker_.MakeAckAndRstPacket(
+          packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0),
+          quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true));
   socket_data1.AddSocketDataToFactory(socket_factory_.get());
 
   // On a DISCONNECTED notification, nothing happens.
@@ -7027,12 +7253,17 @@
   QuicStreamFactoryPeer::SetTaskRunner(factory_.get(), task_runner.get());
 
   MockQuicData socket_data(version_);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    socket_data.AddWrite(SYNCHRONOUS,
+                         ConstructInitialSettingsPacket(packet_num++));
+  }
   socket_data.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
   socket_data.AddWrite(
       ASYNC, ERR_ADDRESS_UNREACHABLE,
-      ConstructGetRequestPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
+      ConstructGetRequestPacket(packet_num++,
+                                GetNthClientInitiatedBidirectionalStreamId(0),
+                                true, true));
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
@@ -7066,16 +7297,18 @@
   // migration. The response to the request is read on this new socket.
   MockQuicData socket_data1(version_);
   socket_data1.AddWrite(
-      SYNCHRONOUS, client_maker_.MakePingPacket(3, /*include_version=*/true));
+      SYNCHRONOUS,
+      client_maker_.MakePingPacket(packet_num++, /*include_version=*/true));
   socket_data1.AddRead(
       ASYNC,
       ConstructOkResponsePacket(
           1, GetNthClientInitiatedBidirectionalStreamId(0), false, false));
   socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   socket_data1.AddWrite(
-      SYNCHRONOUS, client_maker_.MakeAckAndRstPacket(
-                       4, false, GetNthClientInitiatedBidirectionalStreamId(0),
-                       quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true));
+      SYNCHRONOUS,
+      client_maker_.MakeAckAndRstPacket(
+          packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0),
+          quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true));
   socket_data1.AddSocketDataToFactory(socket_factory_.get());
 
   // Send GET request on stream.
@@ -7133,7 +7366,11 @@
   QuicStreamFactoryPeer::SetTaskRunner(factory_.get(), task_runner.get());
 
   MockQuicData socket_data(version_);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    socket_data.AddWrite(SYNCHRONOUS,
+                         ConstructInitialSettingsPacket(packet_num++));
+  }
   socket_data.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
   socket_data.AddRead(ASYNC, ERR_ADDRESS_UNREACHABLE);
   socket_data.AddSocketDataToFactory(socket_factory_.get());
@@ -7169,20 +7406,23 @@
   // response to the request is read on this new socket.
   MockQuicData socket_data1(version_);
   socket_data1.AddWrite(
-      SYNCHRONOUS, client_maker_.MakePingPacket(2, /*include_version=*/true));
+      SYNCHRONOUS,
+      client_maker_.MakePingPacket(packet_num++, /*include_version=*/true));
   socket_data1.AddWrite(
       SYNCHRONOUS,
-      ConstructGetRequestPacket(
-          3, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
+      ConstructGetRequestPacket(packet_num++,
+                                GetNthClientInitiatedBidirectionalStreamId(0),
+                                true, true));
   socket_data1.AddRead(
       ASYNC,
       ConstructOkResponsePacket(
           1, GetNthClientInitiatedBidirectionalStreamId(0), false, false));
   socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   socket_data1.AddWrite(
-      SYNCHRONOUS, client_maker_.MakeAckAndRstPacket(
-                       4, false, GetNthClientInitiatedBidirectionalStreamId(0),
-                       quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true));
+      SYNCHRONOUS,
+      client_maker_.MakeAckAndRstPacket(
+          packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0),
+          quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true));
   socket_data1.AddSocketDataToFactory(socket_factory_.get());
 
   EXPECT_EQ(0u, task_runner->GetPendingTaskCount());
@@ -7245,7 +7485,11 @@
   QuicStreamFactoryPeer::SetTaskRunner(factory_.get(), task_runner.get());
 
   MockQuicData socket_data(version_);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    socket_data.AddWrite(SYNCHRONOUS,
+                         ConstructInitialSettingsPacket(packet_num++));
+  }
   socket_data.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
   socket_data.AddRead(ASYNC, ERR_ADDRESS_UNREACHABLE);
   socket_data.AddSocketDataToFactory(socket_factory_.get());
@@ -7281,20 +7525,23 @@
   // response to the request is read on this new socket.
   MockQuicData socket_data1(version_);
   socket_data1.AddWrite(
-      SYNCHRONOUS, client_maker_.MakePingPacket(2, /*include_version=*/true));
+      SYNCHRONOUS,
+      client_maker_.MakePingPacket(packet_num++, /*include_version=*/true));
   socket_data1.AddWrite(
       SYNCHRONOUS,
-      ConstructGetRequestPacket(
-          3, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
+      ConstructGetRequestPacket(packet_num++,
+                                GetNthClientInitiatedBidirectionalStreamId(0),
+                                true, true));
   socket_data1.AddRead(
       ASYNC,
       ConstructOkResponsePacket(
           1, GetNthClientInitiatedBidirectionalStreamId(0), false, false));
   socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   socket_data1.AddWrite(
-      SYNCHRONOUS, client_maker_.MakeAckAndRstPacket(
-                       4, false, GetNthClientInitiatedBidirectionalStreamId(0),
-                       quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true));
+      SYNCHRONOUS,
+      client_maker_.MakeAckAndRstPacket(
+          packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0),
+          quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true));
   socket_data1.AddSocketDataToFactory(socket_factory_.get());
 
   EXPECT_EQ(0u, task_runner->GetPendingTaskCount());
@@ -7359,7 +7606,11 @@
       std::make_unique<QuicChromiumAlarmFactory>(task_runner.get(), &clock_));
 
   MockQuicData socket_data(version_);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    socket_data.AddWrite(SYNCHRONOUS,
+                         ConstructInitialSettingsPacket(packet_num++));
+  }
   socket_data.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
   socket_data.AddRead(ASYNC, ERR_ADDRESS_UNREACHABLE);
   socket_data.AddSocketDataToFactory(socket_factory_.get());
@@ -7369,13 +7620,15 @@
   // response to the request is read on this new socket.
   MockQuicData socket_data1(version_);
   // The PING packet sent post migration.
-  socket_data1.AddWrite(SYNCHRONOUS, client_maker_.MakePingPacket(2, true));
+  socket_data1.AddWrite(SYNCHRONOUS,
+                        client_maker_.MakePingPacket(packet_num++, true));
   socket_data1.AddWrite(
       SYNCHRONOUS,
-      ConstructGetRequestPacket(
-          3, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
+      ConstructGetRequestPacket(packet_num++,
+                                GetNthClientInitiatedBidirectionalStreamId(0),
+                                true, true));
   socket_data1.AddRead(ASYNC, ERR_IO_PENDING);  // Pause.
-  // Read two packets so that client will send ACK immedaitely.
+  // Read two packets so that client will send ACK immediately.
   socket_data1.AddRead(
       ASYNC,
       ConstructOkResponsePacket(
@@ -7388,9 +7641,11 @@
   // Read an ACK from server which acks all client data.
   socket_data1.AddRead(SYNCHRONOUS,
                        server_maker_.MakeAckPacket(3, 3, 1, 1, false));
-  socket_data1.AddWrite(ASYNC, client_maker_.MakeAckPacket(4, 2, 1, 1, false));
+  socket_data1.AddWrite(
+      ASYNC, client_maker_.MakeAckPacket(packet_num++, 2, 1, 1, false));
   // The PING packet sent for retransmittable on wire.
-  socket_data1.AddWrite(SYNCHRONOUS, client_maker_.MakePingPacket(5, false));
+  socket_data1.AddWrite(SYNCHRONOUS,
+                        client_maker_.MakePingPacket(packet_num++, false));
   socket_data1.AddRead(ASYNC, ERR_IO_PENDING);  // Pause.
   std::string header = ConstructDataHeader(6);
   socket_data1.AddRead(
@@ -7399,9 +7654,10 @@
                  header + "hello!"));
   socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // No more data to read.
   socket_data1.AddWrite(
-      SYNCHRONOUS, client_maker_.MakeRstPacket(
-                       6, false, GetNthClientInitiatedBidirectionalStreamId(0),
-                       quic::QUIC_STREAM_CANCELLED));
+      SYNCHRONOUS,
+      client_maker_.MakeRstPacket(packet_num++, false,
+                                  GetNthClientInitiatedBidirectionalStreamId(0),
+                                  quic::QUIC_STREAM_CANCELLED));
   socket_data1.AddSocketDataToFactory(socket_factory_.get());
 
   // Create request and QuicHttpStream.
@@ -7507,7 +7763,11 @@
       std::make_unique<QuicChromiumAlarmFactory>(task_runner.get(), &clock_));
 
   MockQuicData socket_data(version_);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    socket_data.AddWrite(SYNCHRONOUS,
+                         ConstructInitialSettingsPacket(packet_num++));
+  }
   socket_data.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
   socket_data.AddRead(ASYNC, ERR_ADDRESS_UNREACHABLE);
   socket_data.AddSocketDataToFactory(socket_factory_.get());
@@ -7517,11 +7777,13 @@
   // response to the request is read on this new socket.
   MockQuicData socket_data1(version_);
   // The PING packet sent post migration.
-  socket_data1.AddWrite(SYNCHRONOUS, client_maker_.MakePingPacket(2, true));
+  socket_data1.AddWrite(SYNCHRONOUS,
+                        client_maker_.MakePingPacket(packet_num++, true));
   socket_data1.AddWrite(
       SYNCHRONOUS,
-      ConstructGetRequestPacket(
-          3, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
+      ConstructGetRequestPacket(packet_num++,
+                                GetNthClientInitiatedBidirectionalStreamId(0),
+                                true, true));
   socket_data1.AddRead(ASYNC, ERR_IO_PENDING);  // Pause.
   // Read two packets so that client will send ACK immedaitely.
   socket_data1.AddRead(
@@ -7535,9 +7797,11 @@
   // Read an ACK from server which acks all client data.
   socket_data1.AddRead(SYNCHRONOUS,
                        server_maker_.MakeAckPacket(3, 3, 1, 1, false));
-  socket_data1.AddWrite(ASYNC, client_maker_.MakeAckPacket(4, 2, 1, 1, false));
+  socket_data1.AddWrite(
+      ASYNC, client_maker_.MakeAckPacket(packet_num++, 2, 1, 1, false));
   // The PING packet sent for retransmittable on wire.
-  socket_data1.AddWrite(SYNCHRONOUS, client_maker_.MakePingPacket(5, false));
+  socket_data1.AddWrite(SYNCHRONOUS,
+                        client_maker_.MakePingPacket(packet_num++, false));
   socket_data1.AddRead(ASYNC, ERR_IO_PENDING);  // Pause.
   std::string header = ConstructDataHeader(6);
   socket_data1.AddRead(
@@ -7546,9 +7810,10 @@
                  header + "hello!"));
   socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // No more data to read.
   socket_data1.AddWrite(
-      SYNCHRONOUS, client_maker_.MakeRstPacket(
-                       6, false, GetNthClientInitiatedBidirectionalStreamId(0),
-                       quic::QUIC_STREAM_CANCELLED));
+      SYNCHRONOUS,
+      client_maker_.MakeRstPacket(packet_num++, false,
+                                  GetNthClientInitiatedBidirectionalStreamId(0),
+                                  quic::QUIC_STREAM_CANCELLED));
   socket_data1.AddSocketDataToFactory(socket_factory_.get());
 
   // Create request and QuicHttpStream.
@@ -7653,11 +7918,16 @@
       std::make_unique<QuicChromiumAlarmFactory>(task_runner.get(), &clock_));
 
   MockQuicData socket_data1(version_);
-  socket_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    socket_data1.AddWrite(SYNCHRONOUS,
+                          ConstructInitialSettingsPacket(packet_num++));
+  }
   socket_data1.AddWrite(
       SYNCHRONOUS,
-      ConstructGetRequestPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
+      ConstructGetRequestPacket(packet_num++,
+                                GetNthClientInitiatedBidirectionalStreamId(0),
+                                true, true));
   socket_data1.AddRead(ASYNC, ERR_IO_PENDING);  // Pause.
   // Read two packets so that client will send ACK immedaitely.
   socket_data1.AddRead(
@@ -7671,9 +7941,11 @@
   // Read an ACK from server which acks all client data.
   socket_data1.AddRead(SYNCHRONOUS,
                        server_maker_.MakeAckPacket(3, 2, 1, 1, false));
-  socket_data1.AddWrite(ASYNC, client_maker_.MakeAckPacket(3, 2, 1, 1, false));
+  socket_data1.AddWrite(
+      ASYNC, client_maker_.MakeAckPacket(packet_num++, 2, 1, 1, false));
   // The PING packet sent for retransmittable on wire.
-  socket_data1.AddWrite(SYNCHRONOUS, client_maker_.MakePingPacket(4, false));
+  socket_data1.AddWrite(SYNCHRONOUS,
+                        client_maker_.MakePingPacket(packet_num++, false));
   socket_data1.AddRead(ASYNC, ERR_IO_PENDING);  // Pause.
   std::string header = ConstructDataHeader(6);
   socket_data1.AddRead(
@@ -7682,9 +7954,10 @@
                  header + "hello!"));
   socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // No more data to read.
   socket_data1.AddWrite(
-      SYNCHRONOUS, client_maker_.MakeRstPacket(
-                       5, false, GetNthClientInitiatedBidirectionalStreamId(0),
-                       quic::QUIC_STREAM_CANCELLED));
+      SYNCHRONOUS,
+      client_maker_.MakeRstPacket(packet_num++, false,
+                                  GetNthClientInitiatedBidirectionalStreamId(0),
+                                  quic::QUIC_STREAM_CANCELLED));
   socket_data1.AddSocketDataToFactory(socket_factory_.get());
 
   // Create request and QuicHttpStream.
@@ -7777,11 +8050,16 @@
       std::make_unique<QuicChromiumAlarmFactory>(task_runner.get(), &clock_));
 
   MockQuicData socket_data1(version_);
-  socket_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    socket_data1.AddWrite(SYNCHRONOUS,
+                          ConstructInitialSettingsPacket(packet_num++));
+  }
   socket_data1.AddWrite(
       SYNCHRONOUS,
-      ConstructGetRequestPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
+      ConstructGetRequestPacket(packet_num++,
+                                GetNthClientInitiatedBidirectionalStreamId(0),
+                                true, true));
   socket_data1.AddRead(ASYNC, ERR_IO_PENDING);  // Pause.
   // Read two packets so that client will send ACK immedaitely.
   socket_data1.AddRead(
@@ -7795,7 +8073,8 @@
   // Read an ACK from server which acks all client data.
   socket_data1.AddRead(SYNCHRONOUS,
                        server_maker_.MakeAckPacket(3, 2, 1, 1, false));
-  socket_data1.AddWrite(ASYNC, client_maker_.MakeAckPacket(3, 2, 1, 1, false));
+  socket_data1.AddWrite(
+      ASYNC, client_maker_.MakeAckPacket(packet_num++, 2, 1, 1, false));
   std::string header = ConstructDataHeader(6);
   socket_data1.AddRead(
       ASYNC, ConstructServerDataPacket(
@@ -7803,9 +8082,10 @@
                  header + "hello!"));
   socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // No more data to read.
   socket_data1.AddWrite(
-      SYNCHRONOUS, client_maker_.MakeRstPacket(
-                       4, false, GetNthClientInitiatedBidirectionalStreamId(0),
-                       quic::QUIC_STREAM_CANCELLED));
+      SYNCHRONOUS,
+      client_maker_.MakeRstPacket(packet_num++, false,
+                                  GetNthClientInitiatedBidirectionalStreamId(0),
+                                  quic::QUIC_STREAM_CANCELLED));
   socket_data1.AddSocketDataToFactory(socket_factory_.get());
 
   // Create request and QuicHttpStream.
@@ -7903,11 +8183,16 @@
       std::make_unique<QuicChromiumAlarmFactory>(task_runner.get(), &clock_));
 
   MockQuicData socket_data1(version_);
-  socket_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    socket_data1.AddWrite(SYNCHRONOUS,
+                          ConstructInitialSettingsPacket(packet_num++));
+  }
   socket_data1.AddWrite(
       SYNCHRONOUS,
-      ConstructGetRequestPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
+      ConstructGetRequestPacket(packet_num++,
+                                GetNthClientInitiatedBidirectionalStreamId(0),
+                                true, true));
   socket_data1.AddRead(ASYNC, ERR_IO_PENDING);  // Pause.
   // Read two packets so that client will send ACK immedaitely.
   socket_data1.AddRead(
@@ -7921,9 +8206,11 @@
   // Read an ACK from server which acks all client data.
   socket_data1.AddRead(SYNCHRONOUS,
                        server_maker_.MakeAckPacket(3, 2, 1, 1, false));
-  socket_data1.AddWrite(ASYNC, client_maker_.MakeAckPacket(3, 2, 1, 1, false));
+  socket_data1.AddWrite(
+      ASYNC, client_maker_.MakeAckPacket(packet_num++, 2, 1, 1, false));
   // The PING packet sent for retransmittable on wire.
-  socket_data1.AddWrite(SYNCHRONOUS, client_maker_.MakePingPacket(4, false));
+  socket_data1.AddWrite(SYNCHRONOUS,
+                        client_maker_.MakePingPacket(packet_num++, false));
   socket_data1.AddRead(ASYNC, ERR_IO_PENDING);  // Pause.
   std::string header = ConstructDataHeader(6);
   socket_data1.AddRead(
@@ -7932,9 +8219,10 @@
                  header + "hello!"));
   socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // No more data to read.
   socket_data1.AddWrite(
-      SYNCHRONOUS, client_maker_.MakeRstPacket(
-                       5, false, GetNthClientInitiatedBidirectionalStreamId(0),
-                       quic::QUIC_STREAM_CANCELLED));
+      SYNCHRONOUS,
+      client_maker_.MakeRstPacket(packet_num++, false,
+                                  GetNthClientInitiatedBidirectionalStreamId(0),
+                                  quic::QUIC_STREAM_CANCELLED));
   socket_data1.AddSocketDataToFactory(socket_factory_.get());
 
   // Create request and QuicHttpStream.
@@ -8029,11 +8317,16 @@
       std::make_unique<QuicChromiumAlarmFactory>(task_runner.get(), &clock_));
 
   MockQuicData socket_data1(version_);
-  socket_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    socket_data1.AddWrite(SYNCHRONOUS,
+                          ConstructInitialSettingsPacket(packet_num++));
+  }
   socket_data1.AddWrite(
       SYNCHRONOUS,
-      ConstructGetRequestPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
+      ConstructGetRequestPacket(packet_num++,
+                                GetNthClientInitiatedBidirectionalStreamId(0),
+                                true, true));
   socket_data1.AddRead(ASYNC, ERR_IO_PENDING);  // Pause.
   // Read two packets so that client will send ACK immedaitely.
   socket_data1.AddRead(
@@ -8047,7 +8340,8 @@
   // Read an ACK from server which acks all client data.
   socket_data1.AddRead(SYNCHRONOUS,
                        server_maker_.MakeAckPacket(3, 2, 1, 1, false));
-  socket_data1.AddWrite(ASYNC, client_maker_.MakeAckPacket(3, 2, 1, 1, false));
+  socket_data1.AddWrite(
+      ASYNC, client_maker_.MakeAckPacket(packet_num++, 2, 1, 1, false));
   std::string header = ConstructDataHeader(6);
   socket_data1.AddRead(
       ASYNC, ConstructServerDataPacket(
@@ -8055,9 +8349,10 @@
                  header + "hello!"));
   socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // No more data to read.
   socket_data1.AddWrite(
-      SYNCHRONOUS, client_maker_.MakeRstPacket(
-                       4, false, GetNthClientInitiatedBidirectionalStreamId(0),
-                       quic::QUIC_STREAM_CANCELLED));
+      SYNCHRONOUS,
+      client_maker_.MakeRstPacket(packet_num++, false,
+                                  GetNthClientInitiatedBidirectionalStreamId(0),
+                                  quic::QUIC_STREAM_CANCELLED));
   socket_data1.AddSocketDataToFactory(socket_factory_.get());
 
   // Create request and QuicHttpStream.
@@ -8148,7 +8443,11 @@
   QuicStreamFactoryPeer::SetTaskRunner(factory_.get(), task_runner.get());
 
   MockQuicData socket_data(version_);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    socket_data.AddWrite(SYNCHRONOUS,
+                         ConstructInitialSettingsPacket(packet_num++));
+  }
   socket_data.AddWrite(ASYNC, ERR_FAILED);              // Write error.
   socket_data.AddRead(ASYNC, ERR_ADDRESS_UNREACHABLE);  // Read error.
   socket_data.AddSocketDataToFactory(socket_factory_.get());
@@ -8185,8 +8484,9 @@
   MockQuicData socket_data1(version_);
   socket_data1.AddWrite(
       SYNCHRONOUS,
-      ConstructGetRequestPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
+      ConstructGetRequestPacket(packet_num++,
+                                GetNthClientInitiatedBidirectionalStreamId(0),
+                                true, true));
   client_maker_.set_coalesce_http_frames(true);
   socket_data1.AddRead(
       ASYNC,
@@ -8293,7 +8593,11 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    socket_data.AddWrite(SYNCHRONOUS,
+                         ConstructInitialSettingsPacket(packet_num++));
+  }
   socket_data.AddWrite(write_error_mode, ERR_FAILED);  // Write error.
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
@@ -8346,8 +8650,9 @@
   MockQuicData socket_data1(version_);
   socket_data1.AddWrite(
       SYNCHRONOUS,
-      ConstructGetRequestPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
+      ConstructGetRequestPacket(packet_num++,
+                                GetNthClientInitiatedBidirectionalStreamId(0),
+                                true, true));
   client_maker_.set_coalesce_http_frames(true);
   socket_data1.AddRead(
       ASYNC,
@@ -8355,9 +8660,10 @@
           1, GetNthClientInitiatedBidirectionalStreamId(0), false, false));
   socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   socket_data1.AddWrite(
-      SYNCHRONOUS, client_maker_.MakeAckAndRstPacket(
-                       3, false, GetNthClientInitiatedBidirectionalStreamId(0),
-                       quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true));
+      SYNCHRONOUS,
+      client_maker_.MakeAckAndRstPacket(
+          packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0),
+          quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true));
   socket_data1.AddSocketDataToFactory(socket_factory_.get());
 
   scoped_mock_network_change_notifier_->mock_network_change_notifier()
@@ -8435,7 +8741,11 @@
 
   MockQuicData default_socket_data(version_);
   default_socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  default_socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    default_socket_data.AddWrite(SYNCHRONOUS,
+                                 ConstructInitialSettingsPacket(packet_num++));
+  }
   default_socket_data.AddSocketDataToFactory(socket_factory_.get());
 
   // Set up second socket data provider that is used after migration.
@@ -8443,7 +8753,8 @@
   alternate_socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // Hanging read.
   // Ping packet to send after migration.
   alternate_socket_data.AddWrite(
-      SYNCHRONOUS, client_maker_.MakePingPacket(2, /*include_version=*/true));
+      SYNCHRONOUS,
+      client_maker_.MakePingPacket(packet_num++, /*include_version=*/true));
   alternate_socket_data.AddSocketDataToFactory(socket_factory_.get());
 
   // Set up probing socket for migrating back to the default network.
@@ -8558,7 +8869,11 @@
 
   MockQuicData default_socket_data(version_);
   default_socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  default_socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    default_socket_data.AddWrite(SYNCHRONOUS,
+                                 ConstructInitialSettingsPacket(packet_num++));
+  }
   default_socket_data.AddSocketDataToFactory(socket_factory_.get());
 
   // Set up second socket data provider that is used after migration.
@@ -8566,7 +8881,8 @@
   alternate_socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // Hanging read.
   // Ping packet to send after migration.
   alternate_socket_data.AddWrite(
-      SYNCHRONOUS, client_maker_.MakePingPacket(2, /*include_version=*/true));
+      SYNCHRONOUS,
+      client_maker_.MakePingPacket(packet_num++, /*include_version=*/true));
   alternate_socket_data.AddSocketDataToFactory(socket_factory_.get());
 
   // Set up probing socket for migrating back to the default network.
@@ -8668,11 +8984,16 @@
 
   MockQuicData socket_data1(version_);
   socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    socket_data1.AddWrite(SYNCHRONOUS,
+                          ConstructInitialSettingsPacket(packet_num++));
+  }
   socket_data1.AddWrite(
       SYNCHRONOUS,
-      ConstructGetRequestPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
+      ConstructGetRequestPacket(packet_num++,
+                                GetNthClientInitiatedBidirectionalStreamId(0),
+                                true, true));
   socket_data1.AddSocketDataToFactory(socket_factory_.get());
 
   // Create request and QuicHttpStream.
@@ -8717,16 +9038,18 @@
   // response to the request is read on this new socket.
   MockQuicData socket_data2(version_);
   socket_data2.AddWrite(
-      SYNCHRONOUS, client_maker_.MakePingPacket(3, /*include_version=*/true));
+      SYNCHRONOUS,
+      client_maker_.MakePingPacket(packet_num++, /*include_version=*/true));
   socket_data2.AddRead(
       ASYNC,
       ConstructOkResponsePacket(
           1, GetNthClientInitiatedBidirectionalStreamId(0), false, false));
   socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   socket_data2.AddWrite(
-      SYNCHRONOUS, client_maker_.MakeAckAndRstPacket(
-                       4, false, GetNthClientInitiatedBidirectionalStreamId(0),
-                       quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true));
+      SYNCHRONOUS,
+      client_maker_.MakeAckAndRstPacket(
+          packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0),
+          quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true));
   socket_data2.AddSocketDataToFactory(socket_factory_.get());
 
   const uint8_t kTestIpAddress[] = {1, 2, 3, 4};
@@ -8816,11 +9139,16 @@
   // Set up only socket data provider.
   MockQuicData socket_data1(version_);
   socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    socket_data1.AddWrite(SYNCHRONOUS,
+                          ConstructInitialSettingsPacket(packet_num++));
+  }
   socket_data1.AddWrite(
-      SYNCHRONOUS, client_maker_.MakeRstPacket(
-                       2, true, GetNthClientInitiatedBidirectionalStreamId(0),
-                       quic::QUIC_STREAM_CANCELLED));
+      SYNCHRONOUS,
+      client_maker_.MakeRstPacket(packet_num++, true,
+                                  GetNthClientInitiatedBidirectionalStreamId(0),
+                                  quic::QUIC_STREAM_CANCELLED));
   socket_data1.AddSocketDataToFactory(socket_factory_.get());
 
   // Create request and QuicHttpStream.
@@ -8873,13 +9201,15 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
   client_maker_.Reset();
   MockQuicData socket_data2(version_);
   socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data2.AddSocketDataToFactory(socket_factory_.get());
 
   QuicStreamRequest request(factory_.get());
@@ -9055,13 +9385,15 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
   client_maker_.Reset();
   MockQuicData socket_data2(version_);
   socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data2.AddSocketDataToFactory(socket_factory_.get());
 
   HostPortPair server2(kServer2HostName, kDefaultServerPort);
@@ -9155,7 +9487,8 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
   // Save current state of |race_cert_verification|.
@@ -9316,7 +9649,8 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
   QuicStreamRequest request(factory_.get());
@@ -9361,17 +9695,23 @@
 
   MockQuicData socket_data1(version_);
   socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    socket_data1.AddWrite(SYNCHRONOUS,
+                          ConstructInitialSettingsPacket(packet_num++));
+  }
   socket_data1.AddWrite(
-      SYNCHRONOUS, client_maker_.MakeRstPacket(
-                       2, true, GetNthServerInitiatedUnidirectionalStreamId(0),
-                       quic::QUIC_STREAM_CANCELLED));
+      SYNCHRONOUS,
+      client_maker_.MakeRstPacket(
+          packet_num++, true, GetNthServerInitiatedUnidirectionalStreamId(0),
+          quic::QUIC_STREAM_CANCELLED));
   socket_data1.AddSocketDataToFactory(socket_factory_.get());
 
   client_maker_.Reset();
   MockQuicData socket_data2(version_);
   socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data2.AddSocketDataToFactory(socket_factory_.get());
 
   QuicStreamRequest request(factory_.get());
@@ -9436,7 +9776,8 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
   QuicStreamRequest request1(factory_.get());
@@ -9595,15 +9936,11 @@
   verify_details.cert_verify_result.is_issued_by_known_root = true;
   crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
 
-  MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
-  std::unique_ptr<quic::QuicEncryptedPacket> settings_packet(
-      client_maker_.MakeInitialSettingsPacket(1));
-  MockWrite writes[] = {MockWrite(SYNCHRONOUS, settings_packet->data(),
-                                  settings_packet->length(), 1)};
-  std::unique_ptr<SequencedSocketData> sequenced_socket_data(
-      new SequencedSocketData(reads, writes));
-  socket_factory_->AddSocketDataProvider(sequenced_socket_data.get());
-  sequenced_socket_data_vector_.push_back(std::move(sequenced_socket_data));
+  MockQuicData socket_data(version_);
+  socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  socket_data.AddSocketDataToFactory(socket_factory_.get());
 
   QuicStreamRequest request1(factory_.get());
   EXPECT_EQ(ERR_IO_PENDING,
@@ -9640,7 +9977,8 @@
                                privacy_mode_ == PRIVACY_MODE_ENABLED),
             session1->server_id());
 
-  EXPECT_TRUE(AllDataConsumed());
+  EXPECT_TRUE(socket_data.AllReadDataConsumed());
+  EXPECT_TRUE(socket_data.AllWriteDataConsumed());
 }
 
 // QuicStreamRequest is not pooled if PrivacyMode differs.
@@ -9670,19 +10008,17 @@
   verify_details2.cert_verify_result.is_issued_by_known_root = true;
   crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details2);
 
-  MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
-  std::unique_ptr<quic::QuicEncryptedPacket> settings_packet(
-      client_maker_.MakeInitialSettingsPacket(1));
-  MockWrite writes[] = {MockWrite(SYNCHRONOUS, settings_packet->data(),
-                                  settings_packet->length(), 1)};
-  std::unique_ptr<SequencedSocketData> sequenced_socket_data(
-      new SequencedSocketData(reads, writes));
-  socket_factory_->AddSocketDataProvider(sequenced_socket_data.get());
-  sequenced_socket_data_vector_.push_back(std::move(sequenced_socket_data));
-  std::unique_ptr<SequencedSocketData> sequenced_socket_data1(
-      new SequencedSocketData(reads, writes));
-  socket_factory_->AddSocketDataProvider(sequenced_socket_data1.get());
-  sequenced_socket_data_vector_.push_back(std::move(sequenced_socket_data1));
+  MockQuicData socket_data1(version_);
+  socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  socket_data1.AddSocketDataToFactory(socket_factory_.get());
+  client_maker_.Reset();
+  MockQuicData socket_data2(version_);
+  socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  socket_data2.AddSocketDataToFactory(socket_factory_.get());
 
   QuicStreamRequest request1(factory_.get());
   EXPECT_EQ(ERR_IO_PENDING,
@@ -9722,7 +10058,10 @@
   EXPECT_EQ(quic::QuicServerId(origin2_.host(), origin2_.port(), true),
             session2->server_id());
 
-  EXPECT_TRUE(AllDataConsumed());
+  EXPECT_TRUE(socket_data1.AllReadDataConsumed());
+  EXPECT_TRUE(socket_data1.AllWriteDataConsumed());
+  EXPECT_TRUE(socket_data2.AllReadDataConsumed());
+  EXPECT_TRUE(socket_data2.AllWriteDataConsumed());
 }
 
 // QuicStreamRequest is not pooled if certificate does not match its origin.
@@ -9757,19 +10096,17 @@
   verify_details2.cert_verify_result.is_issued_by_known_root = true;
   crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details2);
 
-  MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
-  std::unique_ptr<quic::QuicEncryptedPacket> settings_packet(
-      client_maker_.MakeInitialSettingsPacket(1));
-  MockWrite writes[] = {MockWrite(SYNCHRONOUS, settings_packet->data(),
-                                  settings_packet->length(), 1)};
-  std::unique_ptr<SequencedSocketData> sequenced_socket_data(
-      new SequencedSocketData(reads, writes));
-  socket_factory_->AddSocketDataProvider(sequenced_socket_data.get());
-  sequenced_socket_data_vector_.push_back(std::move(sequenced_socket_data));
-  std::unique_ptr<SequencedSocketData> sequenced_socket_data1(
-      new SequencedSocketData(reads, writes));
-  socket_factory_->AddSocketDataProvider(sequenced_socket_data1.get());
-  sequenced_socket_data_vector_.push_back(std::move(sequenced_socket_data1));
+  MockQuicData socket_data1(version_);
+  socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  socket_data1.AddSocketDataToFactory(socket_factory_.get());
+  client_maker_.Reset();
+  MockQuicData socket_data2(version_);
+  socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  socket_data2.AddSocketDataToFactory(socket_factory_.get());
 
   QuicStreamRequest request1(factory_.get());
   EXPECT_EQ(ERR_IO_PENDING,
@@ -9811,7 +10148,10 @@
                                privacy_mode_ == PRIVACY_MODE_ENABLED),
             session2->server_id());
 
-  EXPECT_TRUE(AllDataConsumed());
+  EXPECT_TRUE(socket_data1.AllReadDataConsumed());
+  EXPECT_TRUE(socket_data1.AllWriteDataConsumed());
+  EXPECT_TRUE(socket_data2.AllReadDataConsumed());
+  EXPECT_TRUE(socket_data2.AllWriteDataConsumed());
 }
 
 // This test verifies that QuicStreamFactory::ClearCachedStatesInCryptoConfig
@@ -9892,7 +10232,8 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
   QuicStreamRequest request(factory_.get());
@@ -9920,7 +10261,8 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
   QuicStreamRequest request(factory_.get());
@@ -10235,7 +10577,8 @@
 
   MockQuicData quic_data(version_);
   quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   quic_data.AddSocketDataToFactory(socket_factory_.get());
 
   QuicStreamRequest request(factory_.get());
@@ -10270,7 +10613,8 @@
 
   MockQuicData quic_data(version_);
   quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   quic_data.AddSocketDataToFactory(socket_factory_.get());
 
   QuicStreamRequest request(factory_.get());
@@ -10328,7 +10672,8 @@
 
   MockQuicData quic_data(version_);
   quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   quic_data.AddSocketDataToFactory(socket_factory_.get());
 
   QuicStreamRequest request(factory_.get());
@@ -10389,7 +10734,8 @@
 
   MockQuicData quic_data(version_);
   quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   quic_data.AddSocketDataToFactory(socket_factory_.get());
 
   QuicStreamRequest request(factory_.get());
@@ -10456,7 +10802,8 @@
 
   MockQuicData quic_data(version_);
   quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   quic_data.AddSocketDataToFactory(socket_factory_.get());
 
   QuicStreamRequest request(factory_.get());
@@ -10517,18 +10864,23 @@
   // Socket for the stale connection which will invoke connection closure.
   MockQuicData quic_data(version_);
   quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeConnectionClosePacket(
-          2, true, quic::QUIC_STALE_CONNECTION_CANCELLED, "net error"));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    quic_data.AddWrite(SYNCHRONOUS,
+                       ConstructInitialSettingsPacket(packet_num++));
+  }
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeConnectionClosePacket(
+                         packet_num++, true,
+                         quic::QUIC_STALE_CONNECTION_CANCELLED, "net error"));
   quic_data.AddSocketDataToFactory(socket_factory_.get());
 
   // Socket for the new connection.
   client_maker_.Reset();
   MockQuicData quic_data2(version_);
   quic_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  quic_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    quic_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   quic_data2.AddSocketDataToFactory(socket_factory_.get());
 
   QuicStreamRequest request(factory_.get());
@@ -10590,11 +10942,15 @@
 
   MockQuicData quic_data(version_);
   quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeConnectionClosePacket(
-          2, true, quic::QUIC_STALE_CONNECTION_CANCELLED, "net error"));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    quic_data.AddWrite(SYNCHRONOUS,
+                       ConstructInitialSettingsPacket(packet_num++));
+  }
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeConnectionClosePacket(
+                         packet_num++, true,
+                         quic::QUIC_STALE_CONNECTION_CANCELLED, "net error"));
   quic_data.AddSocketDataToFactory(socket_factory_.get());
 
   client_maker_.Reset();
@@ -10674,7 +11030,8 @@
   MockQuicData quic_data2(version_);
   quic_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
-  quic_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    quic_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   quic_data2.AddSocketDataToFactory(socket_factory_.get());
 
   QuicStreamRequest request(factory_.get());
@@ -10784,11 +11141,15 @@
   // Socket for the stale connection which is supposed to disconnect.
   MockQuicData quic_data(version_);
   quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeConnectionClosePacket(
-          2, true, quic::QUIC_STALE_CONNECTION_CANCELLED, "net error"));
+  int packet_num = 1;
+  if (VersionUsesQpack(version_.transport_version)) {
+    quic_data.AddWrite(SYNCHRONOUS,
+                       ConstructInitialSettingsPacket(packet_num++));
+  }
+  quic_data.AddWrite(SYNCHRONOUS,
+                     client_maker_.MakeConnectionClosePacket(
+                         packet_num++, true,
+                         quic::QUIC_STALE_CONNECTION_CANCELLED, "net error"));
   quic_data.AddSocketDataToFactory(socket_factory_.get());
 
   QuicStreamRequest request(factory_.get());
@@ -10894,7 +11255,8 @@
   client_maker_.Reset();
   MockQuicData quic_data2(version_);
   quic_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  quic_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    quic_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   quic_data2.AddSocketDataToFactory(socket_factory_.get());
 
   QuicStreamRequest request(factory_.get());
@@ -11099,7 +11461,8 @@
 
   MockQuicData quic_data(version_);
   quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   quic_data.AddSocketDataToFactory(socket_factory_.get());
 
   QuicStreamRequest request(factory_.get());
@@ -11157,14 +11520,16 @@
 
   MockQuicData quic_data(version_);
   quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   quic_data.AddSocketDataToFactory(socket_factory_.get());
 
   // Socket for the new connection.
   client_maker_.Reset();
   MockQuicData quic_data2(version_);
   quic_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  quic_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    quic_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   quic_data2.AddSocketDataToFactory(socket_factory_.get());
 
   QuicStreamRequest request(factory_.get());
@@ -11235,7 +11600,8 @@
   client_maker_.Reset();
   MockQuicData quic_data2(version_);
   quic_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  quic_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    quic_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   quic_data2.AddSocketDataToFactory(socket_factory_.get());
 
   QuicStreamRequest request(factory_.get());
@@ -11297,7 +11663,9 @@
   socket_data.AddWrite(ASYNC, client_maker_.MakeDummyCHLOPacket(1));
   socket_data.AddWrite(ASYNC, client_maker_.MakeDummyCHLOPacket(2));
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(3));
+  if (VersionUsesQpack(version_.transport_version)) {
+    socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(3));
+  }
 
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
@@ -11351,12 +11719,14 @@
   // Prepare to establish two QUIC sessions.
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data.AddSocketDataToFactory(socket_factory_.get());
   client_maker_.Reset();
   MockQuicData socket_data2(version_);
   socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  if (VersionUsesQpack(version_.transport_version))
+    socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data2.AddSocketDataToFactory(socket_factory_.get());
 
 #if defined(OS_ANDROID)
diff --git a/net/reporting/reporting_delivery_agent.cc b/net/reporting/reporting_delivery_agent.cc
index 7d143363a..19e6b2e8 100644
--- a/net/reporting/reporting_delivery_agent.cc
+++ b/net/reporting/reporting_delivery_agent.cc
@@ -114,8 +114,8 @@
 
   void StartTimer() {
     timer_->Start(FROM_HERE, policy().delivery_interval,
-                  base::BindRepeating(&ReportingDeliveryAgentImpl::OnTimerFired,
-                                      base::Unretained(this)));
+                  base::BindOnce(&ReportingDeliveryAgentImpl::OnTimerFired,
+                                 base::Unretained(this)));
   }
 
   void OnTimerFired() {
diff --git a/net/reporting/reporting_garbage_collector.cc b/net/reporting/reporting_garbage_collector.cc
index f524bfd..be1cc86 100644
--- a/net/reporting/reporting_garbage_collector.cc
+++ b/net/reporting/reporting_garbage_collector.cc
@@ -44,10 +44,9 @@
     if (timer_->IsRunning())
       return;
 
-    timer_->Start(
-        FROM_HERE, context_->policy().garbage_collection_interval,
-        base::BindRepeating(&ReportingGarbageCollectorImpl::CollectGarbage,
-                            base::Unretained(this)));
+    timer_->Start(FROM_HERE, context_->policy().garbage_collection_interval,
+                  base::BindOnce(&ReportingGarbageCollectorImpl::CollectGarbage,
+                                 base::Unretained(this)));
   }
 
  private:
diff --git a/net/reporting/reporting_uploader_unittest.cc b/net/reporting/reporting_uploader_unittest.cc
index d6aad04..7618c118 100644
--- a/net/reporting/reporting_uploader_unittest.cc
+++ b/net/reporting/reporting_uploader_unittest.cc
@@ -480,8 +480,8 @@
   GetCookieListCallback cookie_callback;
   context_.cookie_store()->GetCookieListWithOptionsAsync(
       server_.GetURL("/"), CookieOptions(),
-      base::BindRepeating(&GetCookieListCallback::Run,
-                          base::Unretained(&cookie_callback)));
+      base::BindOnce(&GetCookieListCallback::Run,
+                     base::Unretained(&cookie_callback)));
   cookie_callback.WaitUntilDone();
 
   EXPECT_TRUE(cookie_callback.cookies().empty());
diff --git a/net/socket/socket_posix.cc b/net/socket/socket_posix.cc
index 1e3401b..55396576 100644
--- a/net/socket/socket_posix.cc
+++ b/net/socket/socket_posix.cc
@@ -237,7 +237,6 @@
   if (socket_fd_ == kInvalidSocket || waiting_connect_)
     return false;
 
-#if !defined(OS_FUCHSIA)
   // Checks if connection is alive.
   char c;
   int rv = HANDLE_EINTR(recv(socket_fd_, &c, 1, MSG_PEEK));
@@ -247,34 +246,6 @@
     return false;
 
   return true;
-
-#else   // OS_FUCHSIA
-  // TODO(crbug.com/887587): Remove once MSG_PEEK is implemented on Fuchsia.
-  // Fuchsia currently doesn't support MSG_PEEK flag in recv(), so the code
-  // above doesn't work on Fuchsia.
-
-  // If there is no peer address then this socket was never connected.
-  if (!HasPeerAddress())
-    return false;
-
-  // Use poll(POLLRDHUP) to check whether the socket is disconnected.
-  struct pollfd pollfd;
-  pollfd.fd = socket_fd_;
-  pollfd.events = POLLRDHUP;
-  pollfd.revents = 0;
-  const int poll_result = HANDLE_EINTR(poll(&pollfd, 1, 0));
-
-  if (poll_result == 1) {
-    // The socket is disconnected, so check whether it has data to read.
-    int bytes_available;
-    int ioctl_result =
-        HANDLE_EINTR(ioctl(socket_fd_, FIONREAD, &bytes_available));
-    return ioctl_result == 0 && bytes_available > 0;
-  }
-
-  // The socket is still connected, or poll() reported an error.
-  return poll_result == 0;
-#endif  // OS_FUCHSIA
 }
 
 bool SocketPosix::IsConnectedAndIdle() const {
@@ -283,7 +254,6 @@
   if (socket_fd_ == kInvalidSocket || waiting_connect_)
     return false;
 
-#if !defined(OS_FUCHSIA)
   // Check if connection is alive and we haven't received any data
   // unexpectedly.
   char c;
@@ -294,25 +264,6 @@
     return false;
 
   return true;
-#else   // OS_FUCHSIA
-  // TODO(crbug.com/887587): Remove once MSG_PEEK is implemented.
-  // Fuchsia currently doesn't support MSG_PEEK flag in recv(), so the code
-  // above doesn't work on Fuchsia.
-
-  // If there is no peer address then this socket was never connected.
-  if (!HasPeerAddress())
-    return false;
-
-  // Use poll(POLLIN) to check state of the socket. POLLIN is signaled if the
-  // socket is readable or if it was closed by the peer, i.e. the socket is
-  // connected and idle if and only if POLLIN is not signaled.
-  struct pollfd pollfd;
-  pollfd.fd = socket_fd_;
-  pollfd.events = POLLIN;
-  pollfd.revents = 0;
-  const int poll_result = HANDLE_EINTR(poll(&pollfd, 1, 0));
-  return poll_result == 0;
-#endif  // OS_FUCHSIA
 }
 
 int SocketPosix::Read(IOBuffer* buf,
diff --git a/net/spdy/bidirectional_stream_spdy_impl.cc b/net/spdy/bidirectional_stream_spdy_impl.cc
index f428a75..4e6b9328 100644
--- a/net/spdy/bidirectional_stream_spdy_impl.cc
+++ b/net/spdy/bidirectional_stream_spdy_impl.cc
@@ -79,8 +79,8 @@
       SPDY_BIDIRECTIONAL_STREAM, spdy_session_, request_info_->url,
       false /* no early data */, request_info_->priority,
       request_info_->socket_tag, net_log,
-      base::Bind(&BidirectionalStreamSpdyImpl::OnStreamInitialized,
-                 weak_factory_.GetWeakPtr()),
+      base::BindOnce(&BidirectionalStreamSpdyImpl::OnStreamInitialized,
+                     weak_factory_.GetWeakPtr()),
       traffic_annotation);
   if (rv != ERR_IO_PENDING)
     OnStreamInitialized(rv);
@@ -354,8 +354,8 @@
 
   more_read_data_pending_ = false;
   timer_->Start(FROM_HERE, base::TimeDelta::FromMilliseconds(kBufferTimeMs),
-                base::Bind(&BidirectionalStreamSpdyImpl::DoBufferedRead,
-                           weak_factory_.GetWeakPtr()));
+                base::BindOnce(&BidirectionalStreamSpdyImpl::DoBufferedRead,
+                               weak_factory_.GetWeakPtr()));
 }
 
 void BidirectionalStreamSpdyImpl::DoBufferedRead() {
diff --git a/net/spdy/spdy_network_transaction_unittest.cc b/net/spdy/spdy_network_transaction_unittest.cc
index c0763d2..77683fc0 100644
--- a/net/spdy/spdy_network_transaction_unittest.cc
+++ b/net/spdy/spdy_network_transaction_unittest.cc
@@ -2360,8 +2360,8 @@
   scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(kSize);
   rv = trans->Read(
       buf.get(), kSize,
-      base::Bind(&SpdyNetworkTransactionTest::StartTransactionCallback,
-                 helper.session(), default_url_, log_));
+      base::BindOnce(&SpdyNetworkTransactionTest::StartTransactionCallback,
+                     helper.session(), default_url_, log_));
   ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
   // This forces an err_IO_pending, which sets the callback.
   data.Resume();
@@ -2408,10 +2408,9 @@
   const int kSize = 3000;
   scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(kSize);
   rv = trans->Read(
-      buf.get(),
-      kSize,
-      base::Bind(&SpdyNetworkTransactionTest::DeleteSessionCallback,
-                 base::Unretained(&helper)));
+      buf.get(), kSize,
+      base::BindOnce(&SpdyNetworkTransactionTest::DeleteSessionCallback,
+                     base::Unretained(&helper)));
   ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
   data.Resume();
 
diff --git a/net/spdy/spdy_proxy_client_socket.cc b/net/spdy/spdy_proxy_client_socket.cc
index 4356d96..c5c41ad2 100644
--- a/net/spdy/spdy_proxy_client_socket.cc
+++ b/net/spdy/spdy_proxy_client_socket.cc
@@ -342,8 +342,8 @@
   next_state_ = STATE_GENERATE_AUTH_TOKEN_COMPLETE;
   return auth_->MaybeGenerateAuthToken(
       &request_,
-      base::Bind(&SpdyProxyClientSocket::OnIOComplete,
-                 weak_factory_.GetWeakPtr()),
+      base::BindOnce(&SpdyProxyClientSocket::OnIOComplete,
+                     weak_factory_.GetWeakPtr()),
       net_log_);
 }
 
diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc
index 7d12866..af745dde 100644
--- a/net/spdy/spdy_session.cc
+++ b/net/spdy/spdy_session.cc
@@ -1670,8 +1670,8 @@
   // Bootstrap the read loop.
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE,
-      base::BindRepeating(&SpdySession::PumpReadLoop,
-                          weak_factory_.GetWeakPtr(), READ_STATE_DO_READ, OK));
+      base::BindOnce(&SpdySession::PumpReadLoop, weak_factory_.GetWeakPtr(),
+                     READ_STATE_DO_READ, OK));
 }
 
 // {,Try}CreateStream() can be called with |in_io_loop_| set if a stream is
@@ -2404,8 +2404,8 @@
       in_flight_write_->GetIOBufferForRemainingData();
   return socket_->Write(
       write_io_buffer.get(), in_flight_write_->GetRemainingSize(),
-      base::Bind(&SpdySession::PumpWriteLoop, weak_factory_.GetWeakPtr(),
-                 WRITE_STATE_DO_WRITE_COMPLETE),
+      base::BindOnce(&SpdySession::PumpWriteLoop, weak_factory_.GetWeakPtr(),
+                     WRITE_STATE_DO_WRITE_COMPLETE),
       NetworkTrafficAnnotationTag(in_flight_write_traffic_annotation));
 }
 
diff --git a/remoting/host/BUILD.gn b/remoting/host/BUILD.gn
index bbd15b28..2733d58 100644
--- a/remoting/host/BUILD.gn
+++ b/remoting/host/BUILD.gn
@@ -292,6 +292,8 @@
     "username.h",
     "xmpp_register_support_host_request.cc",
     "xmpp_register_support_host_request.h",
+    "xsession_chooser_linux.cc",
+    "xsession_chooser_ui.inc",
   ]
 
   libs = []
@@ -384,6 +386,7 @@
       "disconnect_window_linux.cc",
       "me2me_desktop_environment.cc",
       "me2me_desktop_environment.h",
+      "xsession_chooser_linux.cc",
     ]
     deps += [
       "//ash",
diff --git a/remoting/host/host_main.cc b/remoting/host/host_main.cc
index c320c3e..430e7c1e 100644
--- a/remoting/host/host_main.cc
+++ b/remoting/host/host_main.cc
@@ -49,6 +49,9 @@
 int FileChooserMain();
 int RdpDesktopSessionMain();
 #endif  // defined(OS_WIN)
+#if defined(OS_LINUX)
+int XSessionChooserMain();
+#endif  // defined(OS_LINUX)
 
 namespace {
 
@@ -143,6 +146,10 @@
   } else if (process_type == kProcessTypeRdpDesktopSession) {
     main_routine = &RdpDesktopSessionMain;
 #endif  // defined(OS_WIN)
+#if defined(OS_LINUX)
+  } else if (process_type == kProcessTypeXSessionChooser) {
+    main_routine = &XSessionChooserMain;
+#endif  // defined(OS_LINUX)
   }
 
   return main_routine;
diff --git a/remoting/host/installer/mac/do_signing.sh b/remoting/host/installer/mac/do_signing.sh
index a8f5493..995c867 100755
--- a/remoting/host/installer/mac/do_signing.sh
+++ b/remoting/host/installer/mac/do_signing.sh
@@ -127,9 +127,11 @@
 
   echo Signing "${name}"
   if [[ -n "${keychain}" ]]; then
-    codesign -vv -s "${id}" --keychain "${keychain}" "${name}"
+    codesign -vv --sign "${id}" --options runtime \
+        --keychain "${keychain}" "${name}"
   else
-    codesign -vv -s "${id}" "${name}"
+    codesign -vv --sign "${id}" --options runtime \
+        "${name}"
   fi
   codesign -v "${name}"
 }
diff --git a/remoting/host/linux/linux_me2me_host.py b/remoting/host/linux/linux_me2me_host.py
index 33207b0..3d78cd5c 100755
--- a/remoting/host/linux/linux_me2me_host.py
+++ b/remoting/host/linux/linux_me2me_host.py
@@ -909,29 +909,8 @@
         # current user.
         return ["/bin/sh", startup_file]
 
-  # Choose a session wrapper script to run the session. On some systems,
-  # /etc/X11/Xsession fails to load the user's .profile, so look for an
-  # alternative wrapper that is more likely to match the script that the
-  # system actually uses for console desktop sessions.
-  SESSION_WRAPPERS = [
-    "/usr/sbin/lightdm-session",
-    "/etc/gdm/Xsession",
-    "/etc/X11/Xsession" ]
-  for session_wrapper in SESSION_WRAPPERS:
-    if os.path.exists(session_wrapper):
-      if os.path.exists("/usr/bin/unity-2d-panel"):
-        # On Ubuntu 12.04, the default session relies on 3D-accelerated
-        # hardware. Trying to run this with a virtual X display produces
-        # weird results on some systems (for example, upside-down and
-        # corrupt displays).  So if the ubuntu-2d session is available,
-        # choose it explicitly.
-        return [session_wrapper, "/usr/bin/gnome-session --session=ubuntu-2d"]
-      else:
-        # Use the session wrapper by itself, and let the system choose a
-        # session.
-        return [session_wrapper]
-  return None
-
+  # If there's no configuration, show the user a session chooser.
+  return [HOST_BINARY_PATH, "--type=xsession_chooser"]
 
 class ParentProcessLogger(object):
   """Redirects logs to the parent process, until the host is ready or quits.
diff --git a/remoting/host/switches.cc b/remoting/host/switches.cc
index a417f4a03..097efc40 100644
--- a/remoting/host/switches.cc
+++ b/remoting/host/switches.cc
@@ -21,6 +21,9 @@
 const char kProcessTypeRdpDesktopSession[] = "rdp_desktop_session";
 const char kProcessTypeEvaluateCapability[] = "evaluate_capability";
 const char kProcessTypeFileChooser[] = "file_chooser";
+#if defined(OS_LINUX)
+const char kProcessTypeXSessionChooser[] = "xsession_chooser";
+#endif  // defined(OS_LINUX)
 
 const char kEvaluateCapabilitySwitchName[] = "evaluate-type";
 
diff --git a/remoting/host/switches.h b/remoting/host/switches.h
index 66d99d4..2d18ef5 100644
--- a/remoting/host/switches.h
+++ b/remoting/host/switches.h
@@ -34,6 +34,9 @@
 extern const char kProcessTypeRdpDesktopSession[];
 extern const char kProcessTypeEvaluateCapability[];
 extern const char kProcessTypeFileChooser[];
+#if defined(OS_LINUX)
+extern const char kProcessTypeXSessionChooser[];
+#endif  // defined(OS_LINUX)
 
 extern const char kEvaluateCapabilitySwitchName[];
 
diff --git a/remoting/host/xsession_chooser_linux.cc b/remoting/host/xsession_chooser_linux.cc
new file mode 100644
index 0000000..7dd3167
--- /dev/null
+++ b/remoting/host/xsession_chooser_linux.cc
@@ -0,0 +1,364 @@
+// Copyright 2019 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.
+
+// This file implements a dialog allowing the user to pick between installed
+// X session types. It finds sessions by looking for .desktop files in
+// /etc/X11/sessions and in the xsessions folder (if any) in each XDG system
+// data directory. (By default, this will be /usr/local/share/xsessions and
+// /usr/share/xsessions.) Once the user selects a session, it will be launched
+// via /etc/X11/Xsession. There will additionally be an "Xsession" will will
+// invoke Xsession without arguments to launch a "default" session based on the
+// system's configuration. If no session .desktop files are found, this will be
+// the only option present.
+
+#include <gtk/gtk.h>
+#include <unistd.h>
+
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/environment.h"
+#include "base/files/file_enumerator.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/i18n/icu_util.h"
+#include "base/logging.h"
+#include "base/message_loop/message_pump_type.h"
+#include "base/optional.h"
+#include "base/run_loop.h"
+#include "base/strings/string_util.h"
+#include "base/task/single_thread_task_executor.h"
+#include "remoting/base/string_resources.h"
+#include "remoting/host/logging.h"
+#include "third_party/icu/source/common/unicode/unistr.h"
+#include "third_party/icu/source/i18n/unicode/coll.h"
+#include "ui/base/glib/glib_signal.h"
+#include "ui/base/glib/scoped_gobject.h"
+#include "ui/base/l10n/l10n_util.h"
+
+#include "remoting/host/xsession_chooser_ui.inc"
+
+namespace remoting {
+
+namespace {
+
+const char XSESSION_SCRIPT[] = "/etc/X11/Xsession";
+
+struct XSession {
+  std::string name;
+  std::string comment;
+  std::vector<std::string> desktop_names;
+  std::string exec;
+};
+
+class SessionDialog {
+ public:
+  SessionDialog(std::vector<XSession> choices,
+                base::OnceCallback<void(XSession)> callback,
+                base::OnceClosure cancel_callback)
+      : choices_(std::move(choices)),
+        callback_(std::move(callback)),
+        cancel_callback_(std::move(cancel_callback)),
+        ui_(gtk_builder_new_from_string(UI, -1)) {
+    gtk_label_set_text(
+        GTK_LABEL(gtk_builder_get_object(ui_, "message")),
+        l10n_util::GetStringUTF8(IDS_SESSION_DIALOG_MESSAGE).c_str());
+    gtk_tree_view_column_set_title(
+        GTK_TREE_VIEW_COLUMN(gtk_builder_get_object(ui_, "name_column")),
+        l10n_util::GetStringUTF8(IDS_SESSION_DIALOG_NAME_COLUMN).c_str());
+    gtk_tree_view_column_set_title(
+        GTK_TREE_VIEW_COLUMN(gtk_builder_get_object(ui_, "comment_column")),
+        l10n_util::GetStringUTF8(IDS_SESSION_DIALOG_COMMENT_COLUMN).c_str());
+
+    GtkListStore* session_store =
+        GTK_LIST_STORE(gtk_builder_get_object(ui_, "session_store"));
+    for (std::size_t i = 0; i < choices_.size(); ++i) {
+      GtkTreeIter iter;
+      gtk_list_store_append(session_store, &iter);
+      // gtk_list_store_set makes its own internal copy of the strings.
+      gtk_list_store_set(session_store, &iter,
+                         INDEX_COLUMN, static_cast<guint>(i),
+                         NAME_COLUMN, choices_[i].name.c_str(),
+                         COMMENT_COLUMN, choices_[i].comment.c_str(),
+                         -1);
+    }
+
+    g_signal_connect(gtk_builder_get_object(ui_, "session_list"),
+                     "row-activated", G_CALLBACK(OnRowActivatedThunk), this);
+    g_signal_connect(gtk_builder_get_object(ui_, "ok_button"), "clicked",
+                     G_CALLBACK(OnOkClickedThunk), this);
+    g_signal_connect(gtk_builder_get_object(ui_, "dialog"), "delete-event",
+                     G_CALLBACK(OnCloseThunk), this);
+  }
+
+  void Show() {
+    gtk_widget_show(GTK_WIDGET(gtk_builder_get_object(ui_, "dialog")));
+  }
+
+ private:
+  void ActivateChoice(std::size_t index) {
+    gtk_widget_hide(GTK_WIDGET(gtk_builder_get_object(ui_, "dialog")));
+    if (callback_) {
+      std::move(callback_).Run(std::move(choices_.at(index)));
+    }
+  }
+
+  CHROMEG_CALLBACK_2(SessionDialog,
+                     void,
+                     OnRowActivated,
+                     GtkTreeView*,
+                     GtkTreePath*,
+                     GtkTreeViewColumn*);
+  CHROMEG_CALLBACK_0(SessionDialog, void, OnOkClicked, GtkButton*);
+  CHROMEG_CALLBACK_1(SessionDialog, gboolean, OnClose, GtkWidget*, GdkEvent*);
+
+  enum Columns { INDEX_COLUMN, NAME_COLUMN, COMMENT_COLUMN, NUM_COLUMNS };
+  std::vector<XSession> choices_;
+  base::OnceCallback<void(XSession)> callback_;
+  base::OnceClosure cancel_callback_;
+  ScopedGObject<GtkBuilder> ui_;
+
+  SessionDialog(const SessionDialog&) = delete;
+  SessionDialog& operator=(const SessionDialog&) = delete;
+};
+
+void SessionDialog::OnRowActivated(GtkTreeView* session_list,
+                                   GtkTreePath* path,
+                                   GtkTreeViewColumn*) {
+  GtkTreeModel* model = gtk_tree_view_get_model(session_list);
+  GtkTreeIter iter;
+  guint index;
+  if (!gtk_tree_model_get_iter(model, &iter, path)) {
+    // Strange, but the user should still be able to click OK to progress.
+    return;
+  }
+  gtk_tree_model_get(model, &iter, INDEX_COLUMN, &index, -1);
+  ActivateChoice(index);
+}
+
+void SessionDialog::OnOkClicked(GtkButton*) {
+  GtkTreeSelection* selection = gtk_tree_view_get_selection(
+      GTK_TREE_VIEW(gtk_builder_get_object(ui_, "session_list")));
+  GtkTreeModel* model;
+  GtkTreeIter iter;
+  guint index;
+  if (!gtk_tree_selection_get_selected(selection, &model, &iter)) {
+    // Nothing selected, so do nothing. Note that the selection mode is set to
+    // "browse", which should, under most circumstances, ensure that exactly one
+    // item is selected, preventing this from being reached. However, it does
+    // not completely guarantee that it can never happen.
+    return;
+  }
+  gtk_tree_model_get(model, &iter, INDEX_COLUMN, &index, -1);
+  ActivateChoice(index);
+}
+
+gboolean SessionDialog::OnClose(GtkWidget* dialog, GdkEvent*) {
+  gtk_widget_hide(dialog);
+  if (cancel_callback_) {
+    std::move(cancel_callback_).Run();
+  }
+  return true;
+}
+
+base::Optional<XSession> TryLoadSession(base::FilePath path) {
+  std::unique_ptr<GKeyFile, void (*)(GKeyFile*)> key_file(g_key_file_new(),
+                                                          &g_key_file_free);
+  GError* error;
+
+  if (!g_key_file_load_from_file(key_file.get(), path.value().c_str(),
+                                 G_KEY_FILE_NONE, &error)) {
+    LOG(WARNING) << "Failed to load " << path << ": " << error->message;
+    g_error_free(error);
+    return base::nullopt;
+  }
+
+  // Files without a "Desktop Entry" group can be ignored. (An empty file can be
+  // put in a higher-priority directory to hide entries from a lower-priority
+  // directory.)
+  if (!g_key_file_has_group(key_file.get(), G_KEY_FILE_DESKTOP_GROUP)) {
+    return base::nullopt;
+  }
+
+  // Files with "NoDisplay" or "Hidden" set should be ignored.
+  for (const char* key :
+       {G_KEY_FILE_DESKTOP_KEY_NO_DISPLAY, G_KEY_FILE_DESKTOP_KEY_HIDDEN}) {
+    if (g_key_file_get_boolean(key_file.get(), G_KEY_FILE_DESKTOP_GROUP, key,
+                               nullptr)) {
+      return base::nullopt;
+    }
+  }
+
+  // If there's a "TryExec" key, we need to check if the specified path is
+  // executable and ignore the entry if not. (However, we should not try to
+  // actually execute the specified path.)
+  if (gchar* try_exec =
+          g_key_file_get_string(key_file.get(), G_KEY_FILE_DESKTOP_GROUP,
+                                G_KEY_FILE_DESKTOP_KEY_TRY_EXEC, nullptr)) {
+    base::FilePath try_exec_path(
+        base::TrimWhitespaceASCII(try_exec, base::TRIM_ALL));
+    g_free(try_exec);
+
+    if (try_exec_path.IsAbsolute()
+            ? access(try_exec_path.value().c_str(), X_OK) != 0
+            : !base::ExecutableExistsInPath(base::Environment::Create().get(),
+                                            try_exec_path.value())) {
+      LOG(INFO) << "Rejecting " << path << " due to TryExec=" << try_exec_path;
+      return base::nullopt;
+    }
+  }
+
+  XSession session;
+  // Required fields.
+  if (gchar* localized_name = g_key_file_get_locale_string(
+          key_file.get(), G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_NAME,
+          nullptr, nullptr)) {
+    session.name = localized_name;
+    g_free(localized_name);
+  } else {
+    LOG(WARNING) << "Failed to load value of " << G_KEY_FILE_DESKTOP_KEY_NAME
+                 << " from " << path;
+    return base::nullopt;
+  }
+
+  if (gchar* exec =
+          g_key_file_get_string(key_file.get(), G_KEY_FILE_DESKTOP_GROUP,
+                                G_KEY_FILE_DESKTOP_KEY_EXEC, nullptr)) {
+    session.exec = exec;
+    g_free(exec);
+  } else {
+    LOG(WARNING) << "Failed to load value of " << G_KEY_FILE_DESKTOP_KEY_EXEC
+                 << " from " << path;
+    return base::nullopt;
+  }
+
+  // Optional fields.
+  if (gchar* localized_comment = g_key_file_get_locale_string(
+          key_file.get(), G_KEY_FILE_DESKTOP_GROUP,
+          G_KEY_FILE_DESKTOP_KEY_COMMENT, nullptr, nullptr)) {
+    session.comment = localized_comment;
+    g_free(localized_comment);
+  }
+
+  // DesktopNames does not yet have a constant in glib.
+  if (gchar** desktop_names =
+          g_key_file_get_string_list(key_file.get(), G_KEY_FILE_DESKTOP_GROUP,
+                                     "DesktopNames", nullptr, nullptr)) {
+    for (std::size_t i = 0; desktop_names[i]; ++i) {
+      session.desktop_names.push_back(desktop_names[i]);
+    }
+    g_strfreev(desktop_names);
+  }
+
+  return session;
+}
+
+std::vector<XSession> CollectXSessions() {
+  std::vector<base::FilePath> session_search_dirs;
+  session_search_dirs.emplace_back("/etc/X11/sessions");
+
+  // Returned list is owned by GLib and should not be modified or freed.
+  const gchar* const* system_data_dirs = g_get_system_data_dirs();
+  // List is null-terminated.
+  for (std::size_t i = 0; system_data_dirs[i]; ++i) {
+    session_search_dirs.push_back(
+        base::FilePath(system_data_dirs[i]).Append("xsessions"));
+  }
+
+  std::map<base::FilePath, base::FilePath> session_files;
+
+  for (const base::FilePath& search_dir : session_search_dirs) {
+    base::FileEnumerator file_enumerator(search_dir, false /* recursive */,
+                                         base::FileEnumerator::FILES,
+                                         "*.desktop");
+    base::FilePath session_path;
+    while (!(session_path = file_enumerator.Next()).empty()) {
+      base::FilePath basename = session_path.BaseName().RemoveFinalExtension();
+      // Files in higher-priority directory should shadow those from lower-
+      // priority directories. Emplace will only insert if an entry with the
+      // same basename wasn't found in a previous directory.
+      session_files.emplace(basename, session_path);
+    }
+  }
+
+  std::vector<XSession> sessions;
+
+  // Ensure there's always at least one session.
+  sessions.push_back(
+      {l10n_util::GetStringUTF8(IDS_SESSION_DIALOG_DEFAULT_SESSION_NAME),
+       l10n_util::GetStringUTF8(IDS_SESSION_DIALOG_DEFAULT_SESSION_COMMENT),
+       {},
+       "default"});
+
+  for (const auto& session : session_files) {
+    base::Optional<XSession> loaded_session = TryLoadSession(session.second);
+    if (loaded_session) {
+      sessions.push_back(std::move(*loaded_session));
+    }
+  }
+
+  UErrorCode err = U_ZERO_ERROR;
+  std::unique_ptr<icu::Collator> collator(icu::Collator::createInstance(err));
+  if (U_SUCCESS(err)) {
+    std::sort(sessions.begin() + 1, sessions.end(),
+              [&](const XSession& first, const XSession& second) {
+                UErrorCode err = U_ZERO_ERROR;
+                UCollationResult result = collator->compare(
+                    icu::UnicodeString::fromUTF8(first.name),
+                    icu::UnicodeString::fromUTF8(second.name), err);
+                // The icu documentation isn't clear under what circumstances
+                // this can fail. base::i18n::CompareString16WithCollator just
+                // does a DCHECK of the result, so do the same here for now.
+                DCHECK(U_SUCCESS(err));
+                return result == UCOL_LESS;
+              });
+  } else {
+    LOG(WARNING) << "Error creating collator. Not sorting list. ("
+                 << u_errorName(err) << ")";
+  }
+
+  return sessions;
+}
+
+void ExecXSession(base::OnceClosure quit_closure, XSession session) {
+  LOG(INFO) << "Running " << XSESSION_SCRIPT << " " << session.exec;
+  if (!session.desktop_names.empty()) {
+    std::unique_ptr<base::Environment> environment =
+        base::Environment::Create();
+    environment->SetVar("XDG_CURRENT_DESKTOP",
+                        base::JoinString(session.desktop_names, ":"));
+  }
+  execl(XSESSION_SCRIPT, XSESSION_SCRIPT, session.exec.c_str(), nullptr);
+  PLOG(ERROR) << "Failed to exec XSession";
+  std::move(quit_closure).Run();
+}
+
+}  // namespace
+
+int XSessionChooserMain() {
+#if GTK_CHECK_VERSION(3, 90, 0)
+  gtk_init();
+#else
+  gtk_init(nullptr, nullptr);
+#endif
+
+  base::SingleThreadTaskExecutor task_executor(base::MessagePumpType::UI);
+  base::RunLoop run_loop;
+
+  SessionDialog dialog(CollectXSessions(),
+                       base::BindOnce(&ExecXSession, run_loop.QuitClosure()),
+                       run_loop.QuitClosure());
+  dialog.Show();
+
+  run_loop.Run();
+
+  // Control only gets to here if something went wrong.
+  return 1;
+}
+
+}  // namespace remoting
diff --git a/remoting/host/xsession_chooser_ui.inc b/remoting/host/xsession_chooser_ui.inc
new file mode 100644
index 0000000..30207688
--- /dev/null
+++ b/remoting/host/xsession_chooser_ui.inc
@@ -0,0 +1,123 @@
+// Copyright 2019 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.
+
+// The user interface definition used for the session chooser.
+
+namespace remoting {
+
+namespace {
+
+const char UI[] = R"UI_Definition(
+  <interface>
+    <requires lib="gtk+" version="3.2"/>
+    <object class="GtkListStore" id="session_store">
+      <columns>
+        <column type="guint"/>
+        <column type="gchararray"/>
+        <column type="gchararray"/>
+      </columns>
+    </object>
+    <object class="GtkDialog" id="dialog">
+      <property name="can_focus">False</property>
+      <property name="default_width">600</property>
+      <property name="default_height">400</property>
+      <property name="type_hint">dialog</property>
+      <child>
+        <placeholder/>
+      </child>
+      <child internal-child="vbox">
+        <object class="GtkBox">
+          <property name="can_focus">False</property>
+          <property name="orientation">vertical</property>
+          <property name="spacing">2</property>
+          <child internal-child="action_area">
+            <object class="GtkButtonBox">
+              <property name="can_focus">False</property>
+              <property name="layout_style">end</property>
+              <child>
+                <object class="GtkButton" id="ok_button">
+                  <property name="label">gtk-ok</property>
+                  <property name="visible">True</property>
+                  <property name="can_focus">True</property>
+                  <property name="receives_default">True</property>
+                  <property name="use_stock">True</property>
+                </object>
+                <packing>
+                  <property name="expand">True</property>
+                  <property name="fill">True</property>
+                  <property name="position">0</property>
+                </packing>
+              </child>
+            </object>
+            <packing>
+              <property name="expand">False</property>
+              <property name="fill">False</property>
+              <property name="position">0</property>
+            </packing>
+          </child>
+          <child>
+            <object class="GtkLabel" id="message">
+              <property name="visible">True</property>
+              <property name="can_focus">False</property>
+              <property name="wrap">True</property>
+            </object>
+            <packing>
+              <property name="expand">False</property>
+              <property name="fill">True</property>
+              <property name="position">1</property>
+            </packing>
+          </child>
+          <child>
+            <object class="GtkScrolledWindow">
+              <property name="visible">True</property>
+              <property name="can_focus">True</property>
+              <property name="shadow_type">in</property>
+              <child>
+                <object class="GtkTreeView" id="session_list">
+                  <property name="visible">True</property>
+                  <property name="can_focus">True</property>
+                  <property name="model">session_store</property>
+                  <child internal-child="selection">
+                    <object class="GtkTreeSelection">
+                      <property name="mode">browse</property>
+                    </object>
+                  </child>
+                  <child>
+                    <object class="GtkTreeViewColumn" id="name_column">
+                      <child>
+                        <object class="GtkCellRendererText"/>
+                        <attributes>
+                          <attribute name="text">1</attribute>
+                        </attributes>
+                      </child>
+                    </object>
+                  </child>
+                  <child>
+                    <object class="GtkTreeViewColumn" id="comment_column">
+                      <child>
+                        <object class="GtkCellRendererText"/>
+                        <attributes>
+                          <attribute name="text">2</attribute>
+                        </attributes>
+                      </child>
+                    </object>
+                  </child>
+                </object>
+              </child>
+            </object>
+            <packing>
+              <property name="expand">True</property>
+              <property name="fill">True</property>
+              <property name="position">2</property>
+            </packing>
+          </child>
+        </object>
+      </child>
+    </object>
+  </interface>
+)UI_Definition";
+
+}  // namespace
+
+}  // namespace remoting
diff --git a/remoting/resources/remoting_strings.grd b/remoting/resources/remoting_strings.grd
index 396cd89..605ce1c 100644
--- a/remoting/resources/remoting_strings.grd
+++ b/remoting/resources/remoting_strings.grd
@@ -1332,6 +1332,23 @@
           Not Now
         </message>
       </if>
+      <if expr="is_linux">
+        <message name="IDS_SESSION_DIALOG_MESSAGE" desc="The message to show at the top of the session-selection dialog.">
+          Select a session to launch within your Chrome Remote Desktop environment. (Note that some session types may not support running within Chrome Remote Desktop and on the local console simultaneously.)
+        </message>
+        <message name="IDS_SESSION_DIALOG_NAME_COLUMN" desc="The title of the column containing the names of potential sessions.">
+          Name
+        </message>
+        <message name="IDS_SESSION_DIALOG_COMMENT_COLUMN" desc="The title of the column containing the comment/description of potential sessions.">
+          Comment
+        </message>
+        <message name="IDS_SESSION_DIALOG_DEFAULT_SESSION_NAME" desc="The name of the entry to launch the default session.">
+          (default)
+        </message>
+        <message name="IDS_SESSION_DIALOG_DEFAULT_SESSION_COMMENT" desc="The comment for the entry to launch the default session.">
+          Launch the default XSession
+        </message>
+      </if> <!-- is_linux -->
     </messages>
   </release>
 </grit>
diff --git a/remoting/resources/remoting_strings_grd/IDS_SESSION_DIALOG_COMMENT_COLUMN.png.sha1 b/remoting/resources/remoting_strings_grd/IDS_SESSION_DIALOG_COMMENT_COLUMN.png.sha1
new file mode 100644
index 0000000..b719af2
--- /dev/null
+++ b/remoting/resources/remoting_strings_grd/IDS_SESSION_DIALOG_COMMENT_COLUMN.png.sha1
@@ -0,0 +1 @@
+bbb2a1814aec1f4862f443ff4c7b5f899ecbf58d
\ No newline at end of file
diff --git a/remoting/resources/remoting_strings_grd/IDS_SESSION_DIALOG_DEFAULT_SESSION_COMMENT.png.sha1 b/remoting/resources/remoting_strings_grd/IDS_SESSION_DIALOG_DEFAULT_SESSION_COMMENT.png.sha1
new file mode 100644
index 0000000..b719af2
--- /dev/null
+++ b/remoting/resources/remoting_strings_grd/IDS_SESSION_DIALOG_DEFAULT_SESSION_COMMENT.png.sha1
@@ -0,0 +1 @@
+bbb2a1814aec1f4862f443ff4c7b5f899ecbf58d
\ No newline at end of file
diff --git a/remoting/resources/remoting_strings_grd/IDS_SESSION_DIALOG_DEFAULT_SESSION_NAME.png.sha1 b/remoting/resources/remoting_strings_grd/IDS_SESSION_DIALOG_DEFAULT_SESSION_NAME.png.sha1
new file mode 100644
index 0000000..b719af2
--- /dev/null
+++ b/remoting/resources/remoting_strings_grd/IDS_SESSION_DIALOG_DEFAULT_SESSION_NAME.png.sha1
@@ -0,0 +1 @@
+bbb2a1814aec1f4862f443ff4c7b5f899ecbf58d
\ No newline at end of file
diff --git a/remoting/resources/remoting_strings_grd/IDS_SESSION_DIALOG_MESSAGE.png.sha1 b/remoting/resources/remoting_strings_grd/IDS_SESSION_DIALOG_MESSAGE.png.sha1
new file mode 100644
index 0000000..b719af2
--- /dev/null
+++ b/remoting/resources/remoting_strings_grd/IDS_SESSION_DIALOG_MESSAGE.png.sha1
@@ -0,0 +1 @@
+bbb2a1814aec1f4862f443ff4c7b5f899ecbf58d
\ No newline at end of file
diff --git a/remoting/resources/remoting_strings_grd/IDS_SESSION_DIALOG_NAME_COLUMN.png.sha1 b/remoting/resources/remoting_strings_grd/IDS_SESSION_DIALOG_NAME_COLUMN.png.sha1
new file mode 100644
index 0000000..b719af2
--- /dev/null
+++ b/remoting/resources/remoting_strings_grd/IDS_SESSION_DIALOG_NAME_COLUMN.png.sha1
@@ -0,0 +1 @@
+bbb2a1814aec1f4862f443ff4c7b5f899ecbf58d
\ No newline at end of file
diff --git a/third_party/blink/common/indexeddb/indexeddb_key.cc b/third_party/blink/common/indexeddb/indexeddb_key.cc
index 99c243e..5616487 100644
--- a/third_party/blink/common/indexeddb/indexeddb_key.cc
+++ b/third_party/blink/common/indexeddb/indexeddb_key.cc
@@ -92,6 +92,38 @@
   return !CompareTo(other);
 }
 
+bool IndexedDBKey::HasHoles() const {
+  if (type_ != mojom::IDBKeyType::Array)
+    return false;
+
+  for (const auto& subkey : array_) {
+    if (subkey.type() == mojom::IDBKeyType::None)
+      return true;
+  }
+  return false;
+}
+
+IndexedDBKey IndexedDBKey::FillHoles(const IndexedDBKey& primary_key) const {
+  if (type_ != mojom::IDBKeyType::Array)
+    return IndexedDBKey(*this);
+
+  std::vector<IndexedDBKey> subkeys;
+  subkeys.reserve(array_.size());
+  for (const auto& subkey : array_) {
+    if (subkey.type() == mojom::IDBKeyType::None) {
+      subkeys.push_back(primary_key);
+    } else {
+      // "Holes" can only exist at the top level of an array key, as (1) they
+      // are produced by an index's array keypath when a member matches the
+      // store's keypath, and (2) array keypaths are flat (no
+      // arrays-of-arrays).
+      DCHECK(!subkey.HasHoles());
+      subkeys.push_back(subkey);
+    }
+  }
+  return IndexedDBKey(subkeys);
+}
+
 int IndexedDBKey::CompareTo(const IndexedDBKey& other) const {
   DCHECK(IsValid());
   DCHECK(other.IsValid());
diff --git a/third_party/blink/public/BUILD.gn b/third_party/blink/public/BUILD.gn
index 94e8fe87..fa19cacd 100644
--- a/third_party/blink/public/BUILD.gn
+++ b/third_party/blink/public/BUILD.gn
@@ -158,9 +158,9 @@
     "platform/modules/mediastream/webrtc_uma_histograms.h",
     "platform/modules/peerconnection/audio_codec_factory.h",
     "platform/modules/peerconnection/rtc_event_log_output_sink.h",
+    "platform/modules/peerconnection/rtc_video_decoder_factory.h",
     "platform/modules/peerconnection/two_keys_adapter_map.h",
     "platform/modules/peerconnection/web_rtc_video_encoder_factory.h",
-    "platform/modules/peerconnection/web_rtc_video_frame_adapter_factory.h",
     "platform/modules/peerconnection/webrtc_audio_sink.h",
     "platform/modules/peerconnection/webrtc_util.h",
     "platform/modules/peerconnection/webrtc_video_track_source.h",
@@ -562,6 +562,7 @@
     "//third_party/webrtc/media:rtc_media_base",
     "//third_party/webrtc/modules/audio_device:audio_device_api",
     "//third_party/webrtc/modules/audio_processing:api",
+    "//third_party/webrtc/modules/video_coding:video_codec_interface",
     "//third_party/webrtc/pc:peerconnection",
     "//third_party/webrtc/rtc_base:rtc_base",
     "//third_party/webrtc/rtc_base:rtc_task_queue",
diff --git a/third_party/blink/public/common/indexeddb/indexeddb_key.h b/third_party/blink/public/common/indexeddb/indexeddb_key.h
index b8279f0..c244cf1a 100644
--- a/third_party/blink/public/common/indexeddb/indexeddb_key.h
+++ b/third_party/blink/public/common/indexeddb/indexeddb_key.h
@@ -61,6 +61,15 @@
 
   size_t size_estimate() const { return size_estimate_; }
 
+  // Tests if this array-type key has "holes". Used in cases where a compound
+  // key references an auto-generated primary key.
+  bool HasHoles() const;
+
+  // Returns a copy of this array-type key, but with "holes" replaced by the
+  // given primary key. Used in cases where a compound key references an
+  // auto-generated primary key.
+  IndexedDBKey FillHoles(const IndexedDBKey&) const WARN_UNUSED_RESULT;
+
  private:
   int CompareTo(const IndexedDBKey& other) const;
 
diff --git a/content/renderer/media/webrtc/rtc_video_decoder_factory.h b/third_party/blink/public/platform/modules/peerconnection/rtc_video_decoder_factory.h
similarity index 65%
rename from content/renderer/media/webrtc/rtc_video_decoder_factory.h
rename to third_party/blink/public/platform/modules/peerconnection/rtc_video_decoder_factory.h
index 622dcb6..54e9bf7 100644
--- a/content/renderer/media/webrtc/rtc_video_decoder_factory.h
+++ b/third_party/blink/public/platform/modules/peerconnection/rtc_video_decoder_factory.h
@@ -2,12 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CONTENT_RENDERER_MEDIA_WEBRTC_RTC_VIDEO_DECODER_FACTORY_H_
-#define CONTENT_RENDERER_MEDIA_WEBRTC_RTC_VIDEO_DECODER_FACTORY_H_
+#ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_PEERCONNECTION_RTC_VIDEO_DECODER_FACTORY_H_
+#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_PEERCONNECTION_RTC_VIDEO_DECODER_FACTORY_H_
 
 #include "base/macros.h"
-#include "base/threading/thread.h"
-#include "content/common/content_export.h"
+#include "third_party/blink/public/platform/web_common.h"
 #include "third_party/webrtc/api/video_codecs/video_decoder_factory.h"
 #include "third_party/webrtc/modules/video_coding/include/video_codec_interface.h"
 
@@ -19,10 +18,13 @@
 class GpuVideoAcceleratorFactories;
 }  // namespace media
 
-namespace content {
+namespace blink {
 
 // TODO(wuchengli): add unittest.
-class CONTENT_EXPORT RTCVideoDecoderFactory
+//
+// TODO(crbug.com/787254): Move this class out of the Blink exposed API when its
+// clients get Onion soup'ed. Also, switch away from using std::vector.
+class BLINK_PLATFORM_EXPORT RTCVideoDecoderFactory
     : public webrtc::VideoDecoderFactory {
  public:
   explicit RTCVideoDecoderFactory(
@@ -42,6 +44,6 @@
   DISALLOW_COPY_AND_ASSIGN(RTCVideoDecoderFactory);
 };
 
-}  // namespace content
+}  // namespace blink
 
-#endif  // CONTENT_RENDERER_MEDIA_WEBRTC_RTC_VIDEO_DECODER_FACTORY_H_
+#endif  // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_PEERCONNECTION_RTC_VIDEO_DECODER_FACTORY_H_
diff --git a/third_party/blink/public/platform/modules/peerconnection/web_rtc_video_frame_adapter_factory.h b/third_party/blink/public/platform/modules/peerconnection/web_rtc_video_frame_adapter_factory.h
deleted file mode 100644
index 553bda2a..0000000
--- a/third_party/blink/public/platform/modules/peerconnection/web_rtc_video_frame_adapter_factory.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2019 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 THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_PEERCONNECTION_WEB_RTC_VIDEO_FRAME_ADAPTER_FACTORY_H_
-#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_PEERCONNECTION_WEB_RTC_VIDEO_FRAME_ADAPTER_FACTORY_H_
-
-#include <memory>
-
-#include "third_party/blink/public/platform/web_common.h"
-#include "third_party/webrtc/api/video_codecs/sdp_video_format.h"
-
-namespace media {
-class GpuVideoAcceleratorFactories;
-}
-
-namespace webrtc {
-class VideoDecoder;
-}
-
-namespace blink {
-
-// Creates and initializes an RTCVideoDecoderAdapter. Returns nullptr if
-// |format| cannot be supported.
-// Called on the worker thread.
-//
-// TODO(crbug.com/787254): Remove this API when its clients are Onion souped.
-BLINK_PLATFORM_EXPORT std::unique_ptr<webrtc::VideoDecoder>
-CreateRTCVideoDecoderAdapter(media::GpuVideoAcceleratorFactories* gpu_factories,
-                             const webrtc::SdpVideoFormat& format);
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_PEERCONNECTION_WEB_RTC_VIDEO_FRAME_ADAPTER_FACTORY_H_
diff --git a/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules.cc b/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules.cc
index 2ab26cc..965f6ec 100644
--- a/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules.cc
+++ b/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules.cc
@@ -439,6 +439,57 @@
                                          exception_state);
 }
 
+// Evaluate an index's key path against a value and return a key. This
+// handles the special case for indexes where a compound key path
+// may result in "holes", depending on the store's properties.
+// Otherwise, nullptr is returned.
+// https://w3c.github.io/IndexedDB/#evaluate-a-key-path-on-a-value
+// A V8 exception may be thrown on bad data or by script's getters; if so,
+// callers should not make further V8 calls.
+static std::unique_ptr<IDBKey> CreateIDBKeyFromValueAndKeyPaths(
+    v8::Isolate* isolate,
+    v8::Local<v8::Value> value,
+    const IDBKeyPath& store_key_path,
+    const IDBKeyPath& index_key_path,
+    ExceptionState& exception_state) {
+  DCHECK(!index_key_path.IsNull());
+  v8::HandleScope handle_scope(isolate);
+  if (index_key_path.GetType() == mojom::IDBKeyPathType::Array) {
+    const Vector<String>& array = index_key_path.Array();
+    const bool uses_inline_keys =
+        store_key_path.GetType() == mojom::IDBKeyPathType::String;
+    IDBKey::KeyArray result;
+    result.ReserveInitialCapacity(array.size());
+    for (const String& path : array) {
+      auto key = CreateIDBKeyFromValueAndKeyPath(isolate, value, path,
+                                                 exception_state);
+      if (exception_state.HadException())
+        return nullptr;
+      if (!key && uses_inline_keys && store_key_path.GetString() == path) {
+        // Compound keys that include the store's inline primary key which
+        // will be generated lazily are represented as "holes".
+        key = IDBKey::CreateNone();
+      } else if (!key) {
+        // Key path evaluation failed.
+        return nullptr;
+      } else if (!key->IsValid()) {
+        // An Invalid key is returned if not valid in this case (but not the
+        // other CreateIDBKeyFromValueAndKeyPath function) because:
+        // * Invalid members are only allowed for multi-entry arrays.
+        // * Array key paths can't be multi-entry.
+        return IDBKey::CreateInvalid();
+      }
+
+      result.emplace_back(std::move(key));
+    }
+    return IDBKey::CreateArray(std::move(result));
+  }
+
+  DCHECK_EQ(index_key_path.GetType(), mojom::IDBKeyPathType::String);
+  return CreateIDBKeyFromValueAndKeyPath(
+      isolate, value, index_key_path.GetString(), exception_state);
+}
+
 // Deserialize just the value data & blobInfo from the given IDBValue.
 //
 // Primary key injection is performed in deserializeIDBValue() below.
@@ -713,6 +764,17 @@
                                          exception_state);
 }
 
+std::unique_ptr<IDBKey> NativeValueTraits<std::unique_ptr<IDBKey>>::NativeValue(
+    v8::Isolate* isolate,
+    v8::Local<v8::Value> value,
+    ExceptionState& exception_state,
+    const IDBKeyPath& store_key_path,
+    const IDBKeyPath& index_key_path) {
+  IDB_TRACE("createIDBKeyFromValueAndKeyPaths");
+  return CreateIDBKeyFromValueAndKeyPaths(isolate, value, store_key_path,
+                                          index_key_path, exception_state);
+}
+
 IDBKeyRange* NativeValueTraits<IDBKeyRange*>::NativeValue(
     v8::Isolate* isolate,
     v8::Local<v8::Value> value,
diff --git a/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules.h b/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules.h
index 82b5d7b..7832132 100644
--- a/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules.h
+++ b/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules.h
@@ -66,7 +66,7 @@
   // Implementation for ScriptValue::To<std::unique_ptr<IDBKey>>().
   //
   // Used by Indexed DB when generating the primary key for a record that is
-  // being stored in an object store that uses in-line keys, or an index key.
+  // being stored in an object store that uses in-line keys.
   // https://w3c.github.io/IndexedDB/#extract-key-from-value
   //
   // Evaluates the given key path against the script value to produce an
@@ -83,6 +83,34 @@
       v8::Local<v8::Value>,
       ExceptionState&,
       const IDBKeyPath&);
+
+  // Implementation for ScriptValue::To<std::unique_ptr<IDBKey>>().
+  //
+  // Used by Indexed DB when generating the index key for a record that is being
+  // stored.
+  // https://w3c.github.io/IndexedDB/#extract-key-from-value
+  //
+  // Evaluates the given key path against the script value to produce an IDBKey.
+  // Returns either:
+  // * A nullptr, if key path evaluation fails.
+  // * An Invalid key, if the evaluation yielded a non-key.
+  // * An IDBKey, otherwise.
+  //
+  // Note that an Array key may contain Invalid members, as the
+  // "multi-entry" index case allows these, and will filter them out later. Use
+  // IsValid() to recursively check.
+  //
+  // If evaluating an index's key path which is an array, and the sub-key path
+  // matches the object store's key path, and that evaluation fails, then a
+  // None key member will be present in the Array key result. This should only
+  // occur when the store has a key generator, which would fill in the primary
+  // key lazily.
+  MODULES_EXPORT static std::unique_ptr<IDBKey> NativeValue(
+      v8::Isolate*,
+      v8::Local<v8::Value>,
+      ExceptionState&,
+      const IDBKeyPath& store_key_path,
+      const IDBKeyPath& index_key_path);
 };
 
 template <>
diff --git a/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules_test.cc b/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules_test.cc
index 9745ddce..f7125da 100644
--- a/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules_test.cc
+++ b/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules_test.cc
@@ -139,6 +139,20 @@
   ASSERT_TRUE(expected == idb_key->Number());
 }
 
+// Compare a key against an array of keys. Supports keys with "holes" (keys of
+// type None), so IDBKey::Compare() can't be used directly.
+void CheckArrayKey(const IDBKey* key, const IDBKey::KeyArray& expected) {
+  EXPECT_EQ(mojom::IDBKeyType::Array, key->GetType());
+  const IDBKey::KeyArray& array = key->Array();
+  EXPECT_EQ(expected.size(), array.size());
+  for (wtf_size_t i = 0; i < array.size(); ++i) {
+    EXPECT_EQ(array[i]->GetType(), expected[i]->GetType());
+    if (array[i]->GetType() != mojom::IDBKeyType::None) {
+      EXPECT_EQ(0, expected[i]->Compare(array[i].get()));
+    }
+  }
+}
+
 // SerializedScriptValue header format offsets are inferred from the Blink and
 // V8 serialization code. The code below DCHECKs that
 constexpr static size_t kSSVHeaderBlinkVersionTagOffset = 0;
@@ -299,6 +313,66 @@
         IDBKeyPath(Vector<String>{"id", "throws"})));
     EXPECT_TRUE(exception_state.HadException());
   }
+
+  {
+    // Compound key path references a property that throws, index case.
+    DummyExceptionStateForTesting exception_state;
+    EXPECT_FALSE(ScriptValue::To<std::unique_ptr<IDBKey>>(
+        scope.GetIsolate(), script_value, exception_state,
+        /*store_key_path=*/IDBKeyPath("id"),
+        /*index_key_path=*/IDBKeyPath(Vector<String>{"id", "throws"})));
+    EXPECT_TRUE(exception_state.HadException());
+  }
+}
+
+TEST(IDBKeyFromValueAndKeyPathsTest, IndexKeys) {
+  V8TestingScope scope;
+  ScriptState* script_state = scope.GetScriptState();
+  v8::Isolate* isolate = scope.GetIsolate();
+  NonThrowableExceptionState exception_state;
+
+  // object = { foo: { bar: "zee" }, bad: null }
+  ScriptValue script_value =
+      V8ObjectBuilder(script_state)
+          .Add("foo", V8ObjectBuilder(script_state).Add("bar", "zee"))
+          .AddNull("bad")
+          .GetScriptValue();
+
+  // Index key path member matches store key path.
+  std::unique_ptr<IDBKey> key = ScriptValue::To<std::unique_ptr<IDBKey>>(
+      isolate, script_value, exception_state,
+      /*store_key_path=*/IDBKeyPath("id"),
+      /*index_key_path=*/IDBKeyPath(Vector<String>{"id", "foo.bar"}));
+  IDBKey::KeyArray expected;
+  expected.emplace_back(IDBKey::CreateNone());
+  expected.emplace_back(IDBKey::CreateString("zee"));
+  CheckArrayKey(key.get(), expected);
+
+  // Index key path member matches, but there are unmatched members too.
+  EXPECT_FALSE(ScriptValue::To<std::unique_ptr<IDBKey>>(
+      isolate, script_value, exception_state,
+      /*store_key_path=*/IDBKeyPath("id"),
+      /*index_key_path=*/IDBKeyPath(Vector<String>{"id", "foo.bar", "nope"})));
+
+  // Index key path member matches, but there are invalid subkeys too.
+  EXPECT_FALSE(
+      ScriptValue::To<std::unique_ptr<IDBKey>>(
+          isolate, script_value, exception_state,
+          /*store_key_path=*/IDBKeyPath("id"),
+          /*index_key_path=*/IDBKeyPath(Vector<String>{"id", "foo.bar", "bad"}))
+          ->IsValid());
+
+  // Index key path member does not match store key path.
+  EXPECT_FALSE(ScriptValue::To<std::unique_ptr<IDBKey>>(
+      isolate, script_value, exception_state,
+      /*store_key_path=*/IDBKeyPath("id"),
+      /*index_key_path=*/IDBKeyPath(Vector<String>{"id2", "foo.bar"})));
+
+  // Index key path is not array, matches store key path.
+  EXPECT_FALSE(ScriptValue::To<std::unique_ptr<IDBKey>>(
+      isolate, script_value, exception_state,
+      /*store_key_path=*/IDBKeyPath("id"),
+      /*index_key_path=*/IDBKeyPath("id")));
 }
 
 TEST(InjectIDBKeyTest, ImplicitValues) {
diff --git a/third_party/blink/renderer/core/editing/suggestion/text_suggestion_backend_impl.cc b/third_party/blink/renderer/core/editing/suggestion/text_suggestion_backend_impl.cc
index 53013412..0633e80 100644
--- a/third_party/blink/renderer/core/editing/suggestion/text_suggestion_backend_impl.cc
+++ b/third_party/blink/renderer/core/editing/suggestion/text_suggestion_backend_impl.cc
@@ -4,7 +4,7 @@
 
 #include "third_party/blink/renderer/core/editing/suggestion/text_suggestion_backend_impl.h"
 
-#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "mojo/public/cpp/bindings/self_owned_receiver.h"
 #include "third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 
@@ -16,10 +16,10 @@
 // static
 void TextSuggestionBackendImpl::Create(
     LocalFrame* frame,
-    mojom::blink::TextSuggestionBackendRequest request) {
-  mojo::MakeStrongBinding(std::unique_ptr<TextSuggestionBackendImpl>(
-                              new TextSuggestionBackendImpl(*frame)),
-                          std::move(request));
+    mojo::PendingReceiver<mojom::blink::TextSuggestionBackend> receiver) {
+  mojo::MakeSelfOwnedReceiver(std::unique_ptr<TextSuggestionBackendImpl>(
+                                  new TextSuggestionBackendImpl(*frame)),
+                              std::move(receiver));
 }
 
 void TextSuggestionBackendImpl::ApplySpellCheckSuggestion(
diff --git a/third_party/blink/renderer/core/editing/suggestion/text_suggestion_backend_impl.h b/third_party/blink/renderer/core/editing/suggestion/text_suggestion_backend_impl.h
index 6009db3..6d5930af 100644
--- a/third_party/blink/renderer/core/editing/suggestion/text_suggestion_backend_impl.h
+++ b/third_party/blink/renderer/core/editing/suggestion/text_suggestion_backend_impl.h
@@ -5,6 +5,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_SUGGESTION_TEXT_SUGGESTION_BACKEND_IMPL_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_SUGGESTION_TEXT_SUGGESTION_BACKEND_IMPL_H_
 
+#include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "third_party/blink/public/mojom/input/input_messages.mojom-blink.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/platform/heap/persistent.h"
@@ -17,7 +18,9 @@
 class CORE_EXPORT TextSuggestionBackendImpl final
     : public mojom::blink::TextSuggestionBackend {
  public:
-  static void Create(LocalFrame*, mojom::blink::TextSuggestionBackendRequest);
+  static void Create(
+      LocalFrame*,
+      mojo::PendingReceiver<mojom::blink::TextSuggestionBackend>);
 
   void ApplySpellCheckSuggestion(const String& suggestion) final;
   void ApplyTextSuggestion(int32_t marker_tag, int32_t suggestion_index) final;
diff --git a/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.cc b/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.cc
index befa220..6b67377 100644
--- a/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.cc
+++ b/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.cc
@@ -235,7 +235,7 @@
 
   if (!text_suggestion_host_) {
     GetFrame().GetInterfaceProvider().GetInterface(
-        mojo::MakeRequest(&text_suggestion_host_));
+        text_suggestion_host_.BindNewPipeAndPassReceiver());
   }
 
   text_suggestion_host_->StartSuggestionMenuTimer();
diff --git a/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.h b/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.h
index e1ab2e4..e3d249f 100644
--- a/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.h
+++ b/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_SUGGESTION_TEXT_SUGGESTION_CONTROLLER_H_
 
 #include <utility>
+#include "mojo/public/cpp/bindings/remote.h"
 #include "third_party/blink/public/mojom/input/input_host.mojom-blink.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/dom/document.h"
@@ -74,7 +75,7 @@
 
   bool is_suggestion_menu_open_;
   const Member<LocalFrame> frame_;
-  mojom::blink::TextSuggestionHostPtr text_suggestion_host_;
+  mojo::Remote<mojom::blink::TextSuggestionHost> text_suggestion_host_;
 
   DISALLOW_COPY_AND_ASSIGN(TextSuggestionController);
 };
diff --git a/third_party/blink/renderer/core/exported/prerendering_test.cc b/third_party/blink/renderer/core/exported/prerendering_test.cc
index 2c37948..c6bacffb 100644
--- a/third_party/blink/renderer/core/exported/prerendering_test.cc
+++ b/third_party/blink/renderer/core/exported/prerendering_test.cc
@@ -35,7 +35,6 @@
 #include "base/memory/ptr_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/prerender/prerender_rel_type.h"
-#include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/web_cache.h"
 #include "third_party/blink/public/platform/web_prerender.h"
 #include "third_party/blink/public/platform/web_prerendering_support.h"
@@ -163,12 +162,12 @@
 class PrerenderingTest : public testing::Test {
  public:
   ~PrerenderingTest() override {
-    Platform::Current()
-        ->GetURLLoaderMockFactory()
-        ->UnregisterAllURLsAndClearMemoryCache();
+    url_test_helpers::UnregisterAllURLsAndClearMemoryCache();
   }
 
   void Initialize(const char* base_url, const char* file_name) {
+    // TODO(crbug.com/751425): We should use the mock functionality
+    // via |web_view_helper_|.
     url_test_helpers::RegisterMockedURLLoadFromBase(
         WebString::FromUTF8(base_url), blink::test::CoreTestDataPath(),
         WebString::FromUTF8(file_name));
diff --git a/third_party/blink/renderer/core/exported/web_document_subresource_filter_test.cc b/third_party/blink/renderer/core/exported/web_document_subresource_filter_test.cc
index bee856da..946a62c 100644
--- a/third_party/blink/renderer/core/exported/web_document_subresource_filter_test.cc
+++ b/third_party/blink/renderer/core/exported/web_document_subresource_filter_test.cc
@@ -6,7 +6,6 @@
 
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/web_cache.h"
 #include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
 #include "third_party/blink/public/web/web_document.h"
@@ -125,15 +124,15 @@
 
  private:
   void RegisterMockedHttpURLLoad(const String& file_name) {
+    // TODO(crbug.com/751425): We should use the mock functionality
+    // via |web_view_helper_|.
     url_test_helpers::RegisterMockedURLLoadFromBase(
         WebString(base_url_), test::CoreTestDataPath(), WebString(file_name));
   }
 
   // testing::Test:
   void TearDown() override {
-    Platform::Current()
-        ->GetURLLoaderMockFactory()
-        ->UnregisterAllURLsAndClearMemoryCache();
+    url_test_helpers::UnregisterAllURLsAndClearMemoryCache();
   }
 
   SubresourceFilteringWebFrameClient client_;
diff --git a/third_party/blink/renderer/core/exported/web_frame_serializer_sanitization_test.cc b/third_party/blink/renderer/core/exported/web_frame_serializer_sanitization_test.cc
index 7dba928..843e9af 100644
--- a/third_party/blink/renderer/core/exported/web_frame_serializer_sanitization_test.cc
+++ b/third_party/blink/renderer/core/exported/web_frame_serializer_sanitization_test.cc
@@ -31,7 +31,6 @@
 #include "third_party/blink/public/web/web_frame_serializer.h"
 
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/web_string.h"
 #include "third_party/blink/public/platform/web_url.h"
 #include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
@@ -69,9 +68,7 @@
   WebFrameSerializerSanitizationTest() { helper_.Initialize(); }
 
   ~WebFrameSerializerSanitizationTest() override {
-    Platform::Current()
-        ->GetURLLoaderMockFactory()
-        ->UnregisterAllURLsAndClearMemoryCache();
+    url_test_helpers::UnregisterAllURLsAndClearMemoryCache();
   }
 
   String GenerateMHTMLFromHtml(const String& url, const String& file_name) {
@@ -122,6 +119,8 @@
   void RegisterMockedFileURLLoad(const KURL& url,
                                  const String& file_path,
                                  const String& mime_type = "image/png") {
+    // TODO(crbug.com/751425): We should use the mock functionality
+    // via |helper_|.
     url_test_helpers::RegisterMockedURLLoad(
         url, test::CoreTestDataPath(file_path.Utf8().c_str()), mime_type);
   }
diff --git a/third_party/blink/renderer/core/exported/web_frame_serializer_test.cc b/third_party/blink/renderer/core/exported/web_frame_serializer_test.cc
index 5acb60a..1eb449d1 100644
--- a/third_party/blink/renderer/core/exported/web_frame_serializer_test.cc
+++ b/third_party/blink/renderer/core/exported/web_frame_serializer_test.cc
@@ -31,7 +31,6 @@
 #include "third_party/blink/public/web/web_frame_serializer.h"
 
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/web_string.h"
 #include "third_party/blink/public/platform/web_url.h"
 #include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
@@ -69,9 +68,7 @@
   WebFrameSerializerTest() { helper_.Initialize(); }
 
   ~WebFrameSerializerTest() override {
-    Platform::Current()
-        ->GetURLLoaderMockFactory()
-        ->UnregisterAllURLsAndClearMemoryCache();
+    url_test_helpers::UnregisterAllURLsAndClearMemoryCache();
   }
 
   void RegisterMockedImageURLLoad(const String& url) {
@@ -84,6 +81,8 @@
   void RegisterMockedFileURLLoad(const KURL& url,
                                  const String& file_path,
                                  const String& mime_type = "image/png") {
+    // TODO(crbug.com/751425): We should use the mock functionality
+    // via |helper_|.
     url_test_helpers::RegisterMockedURLLoad(
         url, test::CoreTestDataPath(file_path.Utf8().c_str()), mime_type);
   }
diff --git a/third_party/blink/renderer/core/exported/web_frame_test.cc b/third_party/blink/renderer/core/exported/web_frame_test.cc
index 65e92a1..64a1cdc7 100644
--- a/third_party/blink/renderer/core/exported/web_frame_test.cc
+++ b/third_party/blink/renderer/core/exported/web_frame_test.cc
@@ -48,7 +48,6 @@
 #include "third_party/blink/public/common/page/launching_process_state.h"
 #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
 #include "third_party/blink/public/mojom/frame/find_in_page.mojom-blink.h"
-#include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/web_cache.h"
 #include "third_party/blink/public/platform/web_coalesced_input_event.h"
 #include "third_party/blink/public/platform/web_float_rect.h"
@@ -198,9 +197,7 @@
         chrome_url_("chrome://") {}
 
   ~WebFrameTest() override {
-    Platform::Current()
-        ->GetURLLoaderMockFactory()
-        ->UnregisterAllURLsAndClearMemoryCache();
+    url_test_helpers::UnregisterAllURLsAndClearMemoryCache();
   }
 
   void DisableRendererSchedulerThrottling() {
@@ -214,20 +211,33 @@
   }
 
   void RegisterMockedHttpURLLoad(const std::string& file_name) {
+    // TODO(crbug.com/751425): We should use the mock functionality
+    // via the WebViewHelper instance in each test case.
     RegisterMockedURLLoadFromBase(base_url_, file_name);
   }
 
   void RegisterMockedChromeURLLoad(const std::string& file_name) {
+    // TODO(crbug.com/751425): We should use the mock functionality
+    // via the WebViewHelper instance in each test case.
     RegisterMockedURLLoadFromBase(chrome_url_, file_name);
   }
 
   void RegisterMockedURLLoadFromBase(const std::string& base_url,
                                      const std::string& file_name) {
+    // TODO(crbug.com/751425): We should use the mock functionality
+    // via the WebViewHelper instance in each test case.
     url_test_helpers::RegisterMockedURLLoadFromBase(
         WebString::FromUTF8(base_url), test::CoreTestDataPath(),
         WebString::FromUTF8(file_name));
   }
 
+  void RegisterMockedURLLoadWithCustomResponse(const WebURL& full_url,
+                                               const WebString& file_path,
+                                               WebURLResponse response) {
+    url_test_helpers::RegisterMockedURLLoadWithCustomResponse(
+        full_url, file_path, response);
+  }
+
   void RegisterMockedHttpURLLoadWithCSP(const std::string& file_name,
                                         const std::string& csp,
                                         bool report_only = false) {
@@ -238,13 +248,15 @@
                     : WebString("Content-Security-Policy"),
         WebString::FromUTF8(csp));
     std::string full_string = base_url_ + file_name;
-    url_test_helpers::RegisterMockedURLLoadWithCustomResponse(
+    RegisterMockedURLLoadWithCustomResponse(
         ToKURL(full_string),
         test::CoreTestDataPath(WebString::FromUTF8(file_name)), response);
   }
 
   void RegisterMockedHttpURLLoadWithMimeType(const std::string& file_name,
                                              const std::string& mime_type) {
+    // TODO(crbug.com/751425): We should use the mock functionality
+    // via the WebViewHelper instance in each test case.
     url_test_helpers::RegisterMockedURLLoadFromBase(
         WebString::FromUTF8(base_url_), test::CoreTestDataPath(),
         WebString::FromUTF8(file_name), WebString::FromUTF8(mime_type));
@@ -669,6 +681,8 @@
 TEST_F(WebFrameTest, LocationSetHostWithMissingPort) {
   std::string file_name = "print-location-href.html";
   RegisterMockedHttpURLLoad(file_name);
+  // TODO(crbug.com/751425): We should use the mock functionality
+  // via the WebViewHelper instance in each test case.
   RegisterMockedURLLoadFromBase("http://internal.test:0/", file_name);
 
   frame_test_helpers::WebViewHelper web_view_helper;
@@ -692,6 +706,8 @@
 TEST_F(WebFrameTest, LocationSetEmptyPort) {
   std::string file_name = "print-location-href.html";
   RegisterMockedHttpURLLoad(file_name);
+  // TODO(crbug.com/751425): We should use the mock functionality
+  // via the WebViewHelper instance in each test case.
   RegisterMockedURLLoadFromBase("http://internal.test:0/", file_name);
 
   frame_test_helpers::WebViewHelper web_view_helper;
@@ -6998,13 +7014,13 @@
   redirect_response.SetMimeType("text/html");
   redirect_response.SetHttpStatusCode(302);
   redirect_response.SetHttpHeaderField("Location", redirect);
-  Platform::Current()->GetURLLoaderMockFactory()->RegisterURL(
-      test_url, redirect_response, file_path);
+  RegisterMockedURLLoadWithCustomResponse(test_url, file_path,
+                                          redirect_response);
 
   WebURLResponse final_response;
   final_response.SetMimeType("text/html");
-  Platform::Current()->GetURLLoaderMockFactory()->RegisterURL(
-      redirect_url, final_response, file_path);
+  RegisterMockedURLLoadWithCustomResponse(redirect_url, file_path,
+                                          final_response);
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "first_party_redirect.html");
@@ -8450,6 +8466,8 @@
 }
 
 TEST_F(WebFrameTest, ManifestCSPFetchAllow) {
+  // TODO(crbug.com/751425): We should use the mock functionality
+  // via the WebViewHelper instance in each test case.
   RegisterMockedURLLoadFromBase(not_base_url_, "link-manifest-fetch.json");
   RegisterMockedHttpURLLoadWithCSP("foo.html", "manifest-src *");
 
@@ -8465,6 +8483,8 @@
 }
 
 TEST_F(WebFrameTest, ManifestCSPFetchSelf) {
+  // TODO(crbug.com/751425): We should use the mock functionality
+  // via the WebViewHelper instance in each test case.
   RegisterMockedURLLoadFromBase(not_base_url_, "link-manifest-fetch.json");
   RegisterMockedHttpURLLoadWithCSP("foo.html", "manifest-src 'self'");
 
@@ -8483,6 +8503,8 @@
 }
 
 TEST_F(WebFrameTest, ManifestCSPFetchSelfReportOnly) {
+  // TODO(crbug.com/751425): We should use the mock functionality
+  // via the WebViewHelper instance in each test case.
   RegisterMockedURLLoadFromBase(not_base_url_, "link-manifest-fetch.json");
   RegisterMockedHttpURLLoadWithCSP("foo.html", "manifest-src 'self'",
                                    /* report only */ true);
@@ -10670,6 +10692,8 @@
 
 TEST_F(WebFrameTest, SaveImageAt) {
   std::string url = base_url_ + "image-with-data-url.html";
+  // TODO(crbug.com/751425): We should use the mock functionality
+  // via the WebViewHelper instance in each test case.
   RegisterMockedURLLoadFromBase(base_url_, "image-with-data-url.html");
   url_test_helpers::RegisterMockedURLLoad(
       ToKURL("http://test"), test::CoreTestDataPath("white-1x1.png"));
@@ -10709,6 +10733,8 @@
 
 TEST_F(WebFrameTest, SaveImageWithImageMap) {
   std::string url = base_url_ + "image-map.html";
+  // TODO(crbug.com/751425): We should use the mock functionality
+  // via the WebViewHelper instance in each test case.
   RegisterMockedURLLoadFromBase(base_url_, "image-map.html");
 
   frame_test_helpers::WebViewHelper helper;
@@ -10744,6 +10770,8 @@
   SaveImageFromDataURLWebFrameClient client;
 
   std::string url = base_url_ + "image-map.html";
+  // TODO(crbug.com/751425): We should use the mock functionality
+  // via the WebViewHelper instance in each test case.
   RegisterMockedURLLoadFromBase(base_url_, "image-map.html");
 
   frame_test_helpers::WebViewHelper helper;
@@ -10931,10 +10959,10 @@
   url_test_helpers::RegisterMockedURLLoad(
       ToKURL(url), test::CoreTestDataPath("not_an_image.ico"), "image/x-icon");
   MultipleDataChunkDelegate delegate;
-  Platform::Current()->GetURLLoaderMockFactory()->SetLoaderDelegate(&delegate);
+  url_test_helpers::SetLoaderDelegate(&delegate);
   frame_test_helpers::WebViewHelper helper;
   helper.InitializeAndLoad(url);
-  Platform::Current()->GetURLLoaderMockFactory()->SetLoaderDelegate(nullptr);
+  url_test_helpers::SetLoaderDelegate(nullptr);
 
   Document* document =
       To<LocalFrame>(helper.GetWebView()->GetPage()->MainFrame())
@@ -12401,7 +12429,7 @@
   // Because the child frame will have placeholder document loader, the main
   // frame will not finish loading, so
   // frame_test_helpers::PumpPendingRequestsForFrameToLoad doesn't work here.
-  Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
+  url_test_helpers::ServeAsynchronousRequests();
 
   // Overwrite the client-handled child frame navigation with about:blank.
   WebLocalFrame* child = main_frame->FirstChild()->ToWebLocalFrame();
diff --git a/third_party/blink/renderer/core/exported/web_layer_test.cc b/third_party/blink/renderer/core/exported/web_layer_test.cc
index 6b09254..20a44c78 100644
--- a/third_party/blink/renderer/core/exported/web_layer_test.cc
+++ b/third_party/blink/renderer/core/exported/web_layer_test.cc
@@ -7,7 +7,6 @@
 #include "cc/trees/effect_node.h"
 #include "cc/trees/transform_node.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
 #include "third_party/blink/public/web/web_script_source.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
@@ -31,12 +30,6 @@
     settings->SetPreferCompositingToLCDTextEnabled(true);
   }
 
-  ~WebLayerListTest() override {
-    Platform::Current()
-        ->GetURLLoaderMockFactory()
-        ->UnregisterAllURLsAndClearMemoryCache();
-  }
-
   void SetUp() override {
     web_view_helper_ = std::make_unique<frame_test_helpers::WebViewHelper>();
     web_view_helper_->Initialize(nullptr, nullptr, &web_widget_client_,
diff --git a/third_party/blink/renderer/core/exported/web_plugin_container_test.cc b/third_party/blink/renderer/core/exported/web_plugin_container_test.cc
index ba31e537..dea2f0f 100644
--- a/third_party/blink/renderer/core/exported/web_plugin_container_test.cc
+++ b/third_party/blink/renderer/core/exported/web_plugin_container_test.cc
@@ -37,7 +37,6 @@
 #include "cc/layers/layer.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/frame/frame_owner_element_type.h"
-#include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/web_coalesced_input_event.h"
 #include "third_party/blink/public/platform/web_mouse_wheel_event.h"
 #include "third_party/blink/public/platform/web_pointer_event.h"
@@ -82,9 +81,7 @@
   WebPluginContainerTest() : base_url_("http://www.test.com/") {}
 
   void TearDown() override {
-    Platform::Current()
-        ->GetURLLoaderMockFactory()
-        ->UnregisterAllURLsAndClearMemoryCache();
+    url_test_helpers::UnregisterAllURLsAndClearMemoryCache();
   }
 
   void CalculateGeometry(WebPluginContainerImpl* plugin_container_impl,
@@ -98,6 +95,8 @@
   void RegisterMockedURL(
       const std::string& file_name,
       const std::string& mime_type = std::string("text/html")) {
+    // TODO(crbug.com/751425): We should use the mock functionality
+    // via the WebViewHelper in each test case.
     url_test_helpers::RegisterMockedURLLoadFromBase(
         WebString::FromUTF8(base_url_), test::CoreTestDataPath(),
         WebString::FromUTF8(file_name), WebString::FromUTF8(mime_type));
diff --git a/third_party/blink/renderer/core/exported/web_searchable_form_data_test.cc b/third_party/blink/renderer/core/exported/web_searchable_form_data_test.cc
index 170095ee..98a4a64 100644
--- a/third_party/blink/renderer/core/exported/web_searchable_form_data_test.cc
+++ b/third_party/blink/renderer/core/exported/web_searchable_form_data_test.cc
@@ -34,7 +34,6 @@
 
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
 #include "third_party/blink/public/web/web_document.h"
 #include "third_party/blink/public/web/web_frame.h"
@@ -50,6 +49,8 @@
 
 void RegisterMockedURLLoadFromBaseURL(const std::string& base_url,
                                       const std::string& file_name) {
+  // TODO(crbug.com/751425): We should use the mock functionality
+  // via |WebSearchableFormDataTest::web_view_helper_|.
   url_test_helpers::RegisterMockedURLLoadFromBase(
       WebString::FromUTF8(base_url), test::CoreTestDataPath(),
       WebString::FromUTF8(file_name));
@@ -60,9 +61,7 @@
   WebSearchableFormDataTest() = default;
 
   ~WebSearchableFormDataTest() override {
-    Platform::Current()
-        ->GetURLLoaderMockFactory()
-        ->UnregisterAllURLsAndClearMemoryCache();
+    url_test_helpers::UnregisterAllURLsAndClearMemoryCache();
   }
 
   frame_test_helpers::WebViewHelper web_view_helper_;
diff --git a/third_party/blink/renderer/core/exported/web_view_test.cc b/third_party/blink/renderer/core/exported/web_view_test.cc
index 77a68d57..ce5b20b7 100644
--- a/third_party/blink/renderer/core/exported/web_view_test.cc
+++ b/third_party/blink/renderer/core/exported/web_view_test.cc
@@ -48,7 +48,6 @@
 #include "third_party/blink/public/common/frame/frame_owner_element_type.h"
 #include "third_party/blink/public/common/manifest/web_display_mode.h"
 #include "third_party/blink/public/mojom/frame/document_interface_broker.mojom-blink.h"
-#include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/web_coalesced_input_event.h"
 #include "third_party/blink/public/platform/web_cursor_info.h"
 #include "third_party/blink/public/platform/web_drag_data.h"
@@ -246,9 +245,7 @@
 
   void TearDown() override {
     EventTiming::SetTickClockForTesting(nullptr);
-    Platform::Current()
-        ->GetURLLoaderMockFactory()
-        ->UnregisterAllURLsAndClearMemoryCache();
+    url_test_helpers::UnregisterAllURLsAndClearMemoryCache();
   }
 
  protected:
@@ -262,6 +259,8 @@
   }
 
   std::string RegisterMockedHttpURLLoad(const std::string& file_name) {
+    // TODO(crbug.com/751425): We should use the mock functionality
+    // via |web_view_helper_|.
     return url_test_helpers::RegisterMockedURLLoadFromBase(
                WebString::FromUTF8(base_url_), test::CoreTestDataPath(),
                WebString::FromUTF8(file_name))
diff --git a/third_party/blink/renderer/core/frame/dom_window.cc b/third_party/blink/renderer/core/frame/dom_window.cc
index 432eeca..82753c7 100644
--- a/third_party/blink/renderer/core/frame/dom_window.cc
+++ b/third_party/blink/renderer/core/frame/dom_window.cc
@@ -493,11 +493,17 @@
       user_activation, options->transferUserActivation(), allow_autoplay);
 
   // Transfer user activation state in the source's renderer when
-  // |transferUserActivation| is true.
+  // |transferUserActivation| is true. We are making an expriment with
+  // dynamic delegation of "autoplay" capability using this post message
+  // approach to transfer user activation.
   // TODO(lanwei): we should execute the below code after the post task fires
   // (for both local and remote posting messages).
-  if (RuntimeEnabledFeatures::UserActivationPostMessageTransferEnabled() &&
-      options->transferUserActivation() &&
+  bool should_transfer_user_activation =
+      RuntimeEnabledFeatures::UserActivationPostMessageTransferEnabled() &&
+      options->transferUserActivation();
+  should_transfer_user_activation =
+      should_transfer_user_activation || allow_autoplay;
+  if (should_transfer_user_activation &&
       LocalFrame::HasTransientUserActivation(source_frame)) {
     GetFrame()->TransferUserActivationFrom(source_frame);
 
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc
index 12b8f0aa..4f724017 100644
--- a/third_party/blink/renderer/core/frame/local_frame.cc
+++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -1544,11 +1544,11 @@
   Client()->DidChangeActiveSchedulerTrackedFeatures(features_mask);
 }
 
-const mojom::blink::ReportingServiceProxyPtr& LocalFrame::GetReportingService()
-    const {
+const mojo::Remote<mojom::blink::ReportingServiceProxy>&
+LocalFrame::GetReportingService() const {
   if (!reporting_service_) {
     Platform::Current()->GetBrowserInterfaceBrokerProxy()->GetInterface(
-        mojo::MakeRequest(&reporting_service_));
+        reporting_service_.BindNewPipeAndPassReceiver());
   }
   return reporting_service_;
 }
diff --git a/third_party/blink/renderer/core/frame/local_frame.h b/third_party/blink/renderer/core/frame/local_frame.h
index 91197df3..0d9bd44 100644
--- a/third_party/blink/renderer/core/frame/local_frame.h
+++ b/third_party/blink/renderer/core/frame/local_frame.h
@@ -33,6 +33,7 @@
 
 #include "base/macros.h"
 #include "base/time/default_tick_clock.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "mojo/public/cpp/bindings/strong_binding_set.h"
 #include "third_party/blink/public/common/frame/occlusion_state.h"
 #include "third_party/blink/public/mojom/ad_tagging/ad_frame.mojom-blink.h"
@@ -414,7 +415,8 @@
 
   SmoothScrollSequencer& GetSmoothScrollSequencer();
 
-  const mojom::blink::ReportingServiceProxyPtr& GetReportingService() const;
+  const mojo::Remote<mojom::blink::ReportingServiceProxy>& GetReportingService()
+      const;
 
   // Overlays a color on top of this LocalFrameView if it is associated with
   // the main frame. Should not have multiple consumers.
@@ -567,7 +569,7 @@
   InterfaceRegistry* const interface_registry_;
   // This is declared mutable so that the service endpoint can be cached by
   // const methods.
-  mutable mojom::blink::ReportingServiceProxyPtr reporting_service_;
+  mutable mojo::Remote<mojom::blink::ReportingServiceProxy> reporting_service_;
 
   IntRect remote_viewport_intersection_;
   FrameOcclusionState occlusion_state_ = FrameOcclusionState::kUnknown;
diff --git a/third_party/blink/renderer/core/frame/reporting_context.cc b/third_party/blink/renderer/core/frame/reporting_context.cc
index 4f105a2..26aea8b 100644
--- a/third_party/blink/renderer/core/frame/reporting_context.cc
+++ b/third_party/blink/renderer/core/frame/reporting_context.cc
@@ -103,11 +103,11 @@
   UseCounter::Count(execution_context_, feature);
 }
 
-const mojom::blink::ReportingServiceProxyPtr&
+const mojo::Remote<mojom::blink::ReportingServiceProxy>&
 ReportingContext::GetReportingService() const {
   if (!reporting_service_) {
     Platform::Current()->GetBrowserInterfaceBrokerProxy()->GetInterface(
-        mojo::MakeRequest(&reporting_service_));
+        reporting_service_.BindNewPipeAndPassReceiver());
   }
   return reporting_service_;
 }
diff --git a/third_party/blink/renderer/core/frame/reporting_context.h b/third_party/blink/renderer/core/frame/reporting_context.h
index fab504ba..c463cb5 100644
--- a/third_party/blink/renderer/core/frame/reporting_context.h
+++ b/third_party/blink/renderer/core/frame/reporting_context.h
@@ -5,6 +5,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_REPORTING_CONTEXT_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_REPORTING_CONTEXT_H_
 
+#include "mojo/public/cpp/bindings/remote.h"
 #include "third_party/blink/public/mojom/reporting/reporting.mojom-blink.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
@@ -48,7 +49,8 @@
   // Counts the use of a report type via UseCounter.
   void CountReport(Report*);
 
-  const mojom::blink::ReportingServiceProxyPtr& GetReportingService() const;
+  const mojo::Remote<mojom::blink::ReportingServiceProxy>& GetReportingService()
+      const;
 
   // Send |report| via the Reporting API to |endpoint|.
   void SendToReportingAPI(Report* report, const String& endpoint) const;
@@ -59,7 +61,7 @@
 
   // This is declared mutable so that the service endpoint can be cached by
   // const methods.
-  mutable mojom::blink::ReportingServiceProxyPtr reporting_service_;
+  mutable mojo::Remote<mojom::blink::ReportingServiceProxy> reporting_service_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/frame/visual_viewport_test.cc b/third_party/blink/renderer/core/frame/visual_viewport_test.cc
index 5b2cfcd..57e3515 100644
--- a/third_party/blink/renderer/core/frame/visual_viewport_test.cc
+++ b/third_party/blink/renderer/core/frame/visual_viewport_test.cc
@@ -10,7 +10,6 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
-#include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/web_coalesced_input_event.h"
 #include "third_party/blink/public/platform/web_input_event.h"
 #include "third_party/blink/public/platform/web_scroll_into_view_params.h"
@@ -104,9 +103,7 @@
   }
 
   ~VisualViewportTest() override {
-    Platform::Current()
-        ->GetURLLoaderMockFactory()
-        ->UnregisterAllURLsAndClearMemoryCache();
+    url_test_helpers::UnregisterAllURLsAndClearMemoryCache();
   }
 
   void NavigateTo(const std::string& url) {
@@ -132,6 +129,8 @@
   void ForceFullCompositingUpdate() { UpdateAllLifecyclePhases(); }
 
   void RegisterMockedHttpURLLoad(const std::string& fileName) {
+    // TODO(crbug.com/751425): We should use the mock functionality
+    // via |helper_|.
     url_test_helpers::RegisterMockedURLLoadFromBase(
         WebString::FromUTF8(base_url_), blink::test::CoreTestDataPath(),
         WebString::FromUTF8(fileName));
@@ -139,6 +138,8 @@
 
   void RegisterMockedHttpURLLoad(const std::string& url,
                                  const std::string& fileName) {
+    // TODO(crbug.com/751425): We should use the mock functionality
+    // via |helper_|.
     url_test_helpers::RegisterMockedURLLoad(
         ToKURL(url),
         blink::test::CoreTestDataPath(WebString::FromUTF8(fileName)));
diff --git a/third_party/blink/renderer/core/html/forms/external_popup_menu_test.cc b/third_party/blink/renderer/core/html/forms/external_popup_menu_test.cc
index b1fda914..5e05a5b 100644
--- a/third_party/blink/renderer/core/html/forms/external_popup_menu_test.cc
+++ b/third_party/blink/renderer/core/html/forms/external_popup_menu_test.cc
@@ -7,7 +7,6 @@
 #include <memory>
 
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
 #include "third_party/blink/public/web/web_external_popup_menu.h"
 #include "third_party/blink/public/web/web_popup_menu_info.h"
@@ -103,12 +102,12 @@
     WebView()->SetUseExternalPopupMenus(true);
   }
   void TearDown() override {
-    Platform::Current()
-        ->GetURLLoaderMockFactory()
-        ->UnregisterAllURLsAndClearMemoryCache();
+    url_test_helpers::UnregisterAllURLsAndClearMemoryCache();
   }
 
   void RegisterMockedURLLoad(const std::string& file_name) {
+    // TODO(crbug.com/751425): We should use the mock functionality
+    // via |helper_|.
     url_test_helpers::RegisterMockedURLLoadFromBase(
         WebString::FromUTF8(base_url_), test::CoreTestDataPath("popup"),
         WebString::FromUTF8(file_name), WebString::FromUTF8("text/html"));
diff --git a/third_party/blink/renderer/core/html/parser/html_preload_scanner_test.cc b/third_party/blink/renderer/core/html/parser/html_preload_scanner_test.cc
index 69e1fb5..d40e3ab 100644
--- a/third_party/blink/renderer/core/html/parser/html_preload_scanner_test.cc
+++ b/third_party/blink/renderer/core/html/parser/html_preload_scanner_test.cc
@@ -7,7 +7,6 @@
 #include <memory>
 #include "base/strings/stringprintf.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/web_client_hints_type.h"
 #include "third_party/blink/public/platform/web_runtime_features.h"
 #include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
@@ -22,6 +21,7 @@
 #include "third_party/blink/renderer/platform/exported/wrapped_resource_response.h"
 #include "third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.h"
 #include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
+#include "third_party/blink/renderer/platform/testing/url_test_helpers.h"
 #include "third_party/blink/renderer/platform/weborigin/security_origin.h"
 
 namespace blink {
@@ -1152,8 +1152,10 @@
            network::mojom::ReferrerPolicy::kAlways);
 
   KURL preload_url("http://example.test/sheet.css");
-  Platform::Current()->GetURLLoaderMockFactory()->RegisterURL(
-      preload_url, WrappedResourceResponse(ResourceResponse()), "");
+  // TODO(crbug.com/751425): We should use the mock functionality
+  // via |PageTestBase::dummy_page_holder_|.
+  url_test_helpers::RegisterMockedURLLoadWithCustomResponse(
+      preload_url, "", WrappedResourceResponse(ResourceResponse()));
 
   ReferrerPolicyTestCase test_case = {
       "http://example.test",
diff --git a/third_party/blink/renderer/core/input/ime_on_focus_test.cc b/third_party/blink/renderer/core/input/ime_on_focus_test.cc
index 69baae1..5f3bfe5 100644
--- a/third_party/blink/renderer/core/input/ime_on_focus_test.cc
+++ b/third_party/blink/renderer/core/input/ime_on_focus_test.cc
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/web_coalesced_input_event.h"
 #include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
 #include "third_party/blink/public/web/web_document.h"
@@ -46,9 +45,7 @@
   ImeOnFocusTest() : base_url_("http://www.test.com/") {}
 
   void TearDown() override {
-    Platform::Current()
-        ->GetURLLoaderMockFactory()
-        ->UnregisterAllURLsAndClearMemoryCache();
+    url_test_helpers::UnregisterAllURLsAndClearMemoryCache();
   }
 
  protected:
diff --git a/third_party/blink/renderer/core/input/touch_action_test.cc b/third_party/blink/renderer/core/input/touch_action_test.cc
index 86780a2..db2f54aa 100644
--- a/third_party/blink/renderer/core/input/touch_action_test.cc
+++ b/third_party/blink/renderer/core/input/touch_action_test.cc
@@ -29,7 +29,6 @@
  */
 
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/web_coalesced_input_event.h"
 #include "third_party/blink/public/platform/web_touch_event.h"
 #include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
@@ -93,21 +92,25 @@
 class TouchActionTest : public testing::Test {
  public:
   TouchActionTest() : base_url_("http://www.test.com/") {
+    // TODO(crbug.com/751425): We should use the mock functionality
+    // via |web_view_helper_|.
     url_test_helpers::RegisterMockedURLLoadFromBase(
         WebString(base_url_), test::CoreTestDataPath(),
         "touch-action-tests.css", "text/css");
+    // TODO(crbug.com/751425): We should use the mock functionality
+    // via |web_view_helper_|.
     url_test_helpers::RegisterMockedURLLoadFromBase(
         WebString(base_url_), test::CoreTestDataPath(), "touch-action-tests.js",
         "text/javascript");
+    // TODO(crbug.com/751425): We should use the mock functionality
+    // via |web_view_helper_|.
     url_test_helpers::RegisterMockedURLLoadFromBase(
         WebString(base_url_), test::CoreTestDataPath(), "white-1x1.png",
         "image/png");
   }
 
   void TearDown() override {
-    Platform::Current()
-        ->GetURLLoaderMockFactory()
-        ->UnregisterAllURLsAndClearMemoryCache();
+    url_test_helpers::UnregisterAllURLsAndClearMemoryCache();
   }
 
  protected:
@@ -197,6 +200,8 @@
 WebViewImpl* TouchActionTest::SetupTest(
     String file,
     TouchActionTrackingWebWidgetClient* client) {
+  // TODO(crbug.com/751425): We should use the mock functionality
+  // via |web_view_helper_|.
   url_test_helpers::RegisterMockedURLLoadFromBase(
       WebString(base_url_), test::CoreTestDataPath(), WebString(file));
   // Note that JavaScript must be enabled for shadow DOM tests.
diff --git a/third_party/blink/renderer/core/layout/layout_geometry_map_test.cc b/third_party/blink/renderer/core/layout/layout_geometry_map_test.cc
index 079346f2..e04efae 100644
--- a/third_party/blink/renderer/core/layout/layout_geometry_map_test.cc
+++ b/third_party/blink/renderer/core/layout/layout_geometry_map_test.cc
@@ -32,7 +32,6 @@
 
 #include "build/build_config.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
 #include "third_party/blink/public/web/web_local_frame_client.h"
 #include "third_party/blink/renderer/core/dom/document.h"
@@ -53,9 +52,7 @@
   LayoutGeometryMapTest() : base_url_("http://www.test.com/") {}
 
   void TearDown() override {
-    Platform::Current()
-        ->GetURLLoaderMockFactory()
-        ->UnregisterAllURLsAndClearMemoryCache();
+    url_test_helpers::UnregisterAllURLsAndClearMemoryCache();
   }
 
  protected:
@@ -138,6 +135,8 @@
   }
 
   void RegisterMockedHttpURLLoad(const std::string& file_name) {
+    // TODO(crbug.com/751425): We should use the mock functionality
+    // via the WebViewHelper instance in each test case.
     url_test_helpers::RegisterMockedURLLoadFromBase(
         WebString::FromUTF8(base_url_), test::CoreTestDataPath(),
         WebString::FromUTF8(file_name));
diff --git a/third_party/blink/renderer/core/loader/link_loader_test.cc b/third_party/blink/renderer/core/loader/link_loader_test.cc
index a24e127..b6fc922 100644
--- a/third_party/blink/renderer/core/loader/link_loader_test.cc
+++ b/third_party/blink/renderer/core/loader/link_loader_test.cc
@@ -10,7 +10,6 @@
 #include "base/test/scoped_feature_list.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/features.h"
-#include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/web_prescient_networking.h"
 #include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
@@ -126,9 +125,7 @@
   }
 
   ~LinkLoaderPreloadTestBase() override {
-    Platform::Current()
-        ->GetURLLoaderMockFactory()
-        ->UnregisterAllURLsAndClearMemoryCache();
+    url_test_helpers::UnregisterAllURLsAndClearMemoryCache();
   }
 
  protected:
@@ -141,6 +138,8 @@
         MakeGarbageCollected<MockLinkLoaderClient>(
             expected.link_loader_should_load_value);
     LinkLoader* loader = LinkLoader::Create(loader_client.Get());
+    // TODO(crbug.com/751425): We should use the mock functionality
+    // via |dummy_page_holder_|.
     url_test_helpers::RegisterMockedErrorURLLoad(params.href);
     loader->LoadLink(params, dummy_page_holder_->GetDocument());
     if (!expected.load_url.IsNull() &&
@@ -587,6 +586,8 @@
       MakeGarbageCollected<MockLinkLoaderClient>(true);
   LinkLoader* loader = LinkLoader::Create(loader_client.Get());
   KURL href_url = KURL(NullURL(), "http://example.test/cat.jpg");
+  // TODO(crbug.com/751425): We should use the mock functionality
+  // via |dummy_page_holder|.
   url_test_helpers::RegisterMockedErrorURLLoad(href_url);
   LinkLoadParameters params(
       LinkRelAttribute("prefetch"), kCrossOriginAttributeNotSet, "image/jpg",
@@ -605,9 +606,7 @@
               network::mojom::RedirectMode::kFollow);
   }
 
-  Platform::Current()
-      ->GetURLLoaderMockFactory()
-      ->UnregisterAllURLsAndClearMemoryCache();
+  platform_->GetURLLoaderMockFactory()->UnregisterAllURLsAndClearMemoryCache();
 }
 
 class LinkLoaderTest : public testing::Test {
@@ -649,6 +648,8 @@
             test_case.link_loader_should_load_value);
     LinkLoader* loader = LinkLoader::Create(loader_client.Get());
     KURL href_url = KURL(NullURL(), test_case.href);
+    // TODO(crbug.com/751425): We should use the mock functionality
+    // via |dummy_page_holder|.
     url_test_helpers::RegisterMockedErrorURLLoad(href_url);
     LinkLoadParameters params(
         LinkRelAttribute("prefetch"), kCrossOriginAttributeNotSet,
@@ -670,8 +671,7 @@
                   resource->GetResourceRequest().GetReferrerPolicy());
       }
     }
-    Platform::Current()
-        ->GetURLLoaderMockFactory()
+    platform_->GetURLLoaderMockFactory()
         ->UnregisterAllURLsAndClearMemoryCache();
   }
 }
@@ -764,6 +764,8 @@
       MakeGarbageCollected<MockLinkLoaderClient>(true);
   LinkLoader* loader = LinkLoader::Create(loader_client.Get());
   KURL href_url = KURL(KURL(), "https://www.example.com/");
+  // TODO(crbug.com/751425): We should use the mock functionality
+  // via |dummy_page_holder|.
   url_test_helpers::RegisterMockedErrorURLLoad(href_url);
   LinkLoadParameters params(
       LinkRelAttribute("preload prefetch"), kCrossOriginAttributeNotSet,
diff --git a/third_party/blink/renderer/core/loader/ping_loader_test.cc b/third_party/blink/renderer/core/loader/ping_loader_test.cc
index f519b4d..ac71a79 100644
--- a/third_party/blink/renderer/core/loader/ping_loader_test.cc
+++ b/third_party/blink/renderer/core/loader/ping_loader_test.cc
@@ -5,7 +5,6 @@
 #include "third_party/blink/renderer/core/loader/ping_loader.h"
 
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/loader/empty_clients.h"
@@ -45,9 +44,7 @@
   }
 
   void TearDown() override {
-    Platform::Current()
-        ->GetURLLoaderMockFactory()
-        ->UnregisterAllURLsAndClearMemoryCache();
+    url_test_helpers::UnregisterAllURLsAndClearMemoryCache();
   }
 
   void SetDocumentURL(const KURL& url) {
@@ -60,6 +57,8 @@
 
   const ResourceRequest& PingAndGetRequest(const KURL& ping_url) {
     KURL destination_url("http://navigation.destination");
+    // TODO(crbug.com/751425): We should use the mock functionality
+    // via |PageTestBase::dummy_page_holder_|.
     url_test_helpers::RegisterMockedURLLoad(
         ping_url, test::CoreTestDataPath("bar.html"), "text/html");
     PingLoader::SendLinkAuditPing(&GetFrame(), ping_url, destination_url);
@@ -70,7 +69,7 @@
     }
     // Serve the ping request, since it will otherwise bleed in to the next
     // test, and once begun there is no way to cancel it directly.
-    Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
+    url_test_helpers::ServeAsynchronousRequests();
     return ping_request;
   }
 
@@ -110,10 +109,12 @@
   SetDocumentURL(KURL("http://localhost/foo.html"));
 
   KURL ping_url("https://localhost/bar.html");
+  // TODO(crbug.com/751425): We should use the mock functionality
+  // via |PageTestBase::dummy_page_holder_|.
   url_test_helpers::RegisterMockedURLLoad(
       ping_url, test::CoreTestDataPath("bar.html"), "text/html");
   PingLoader::SendLinkAuditPing(&GetFrame(), ping_url, destination_url);
-  Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
+  url_test_helpers::ServeAsynchronousRequests();
   const ResourceRequest& request = client_->PingRequest();
   ASSERT_FALSE(request.IsNull());
   ASSERT_EQ(request.Url(), ping_url);
@@ -124,11 +125,13 @@
   SetDocumentURL(KURL("http://localhost/foo.html"));
 
   KURL ping_url("https://localhost/bar.html");
+  // TODO(crbug.com/751425): We should use the mock functionality
+  // via |PageTestBase::dummy_page_holder_|.
   url_test_helpers::RegisterMockedURLLoad(
       ping_url, test::CoreTestDataPath("bar.html"), "text/html");
   PingLoader::SendViolationReport(&GetFrame(), ping_url,
                                   EncodedFormData::Create());
-  Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
+  url_test_helpers::ServeAsynchronousRequests();
   const ResourceRequest& request = client_->PingRequest();
   ASSERT_FALSE(request.IsNull());
   ASSERT_EQ(request.Url(), ping_url);
@@ -139,10 +142,12 @@
   SetDocumentURL(KURL("https://localhost/foo.html"));
 
   KURL ping_url("https://localhost/bar.html");
+  // TODO(crbug.com/751425): We should use the mock functionality
+  // via |PageTestBase::dummy_page_holder_|.
   url_test_helpers::RegisterMockedURLLoad(
       ping_url, test::CoreTestDataPath("bar.html"), "text/html");
   PingLoader::SendBeacon(&GetFrame(), ping_url, "hello");
-  Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
+  url_test_helpers::ServeAsynchronousRequests();
   const ResourceRequest& request = client_->PingRequest();
   ASSERT_FALSE(request.IsNull());
   ASSERT_EQ(request.Url(), ping_url);
diff --git a/third_party/blink/renderer/core/loader/programmatic_scroll_test.cc b/third_party/blink/renderer/core/loader/programmatic_scroll_test.cc
index bdff8d67..9d1f678 100644
--- a/third_party/blink/renderer/core/loader/programmatic_scroll_test.cc
+++ b/third_party/blink/renderer/core/loader/programmatic_scroll_test.cc
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/web_input_event.h"
 #include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
 #include "third_party/blink/public/web/web_frame.h"
@@ -31,13 +30,13 @@
   ProgrammaticScrollTest() : base_url_("http://www.test.com/") {}
 
   void TearDown() override {
-    Platform::Current()
-        ->GetURLLoaderMockFactory()
-        ->UnregisterAllURLsAndClearMemoryCache();
+    url_test_helpers::UnregisterAllURLsAndClearMemoryCache();
   }
 
  protected:
   void RegisterMockedHttpURLLoad(const String& file_name) {
+    // TODO(crbug.com/751425): We should use the mock functionality
+    // via the WebViewHelper instance in each test case.
     url_test_helpers::RegisterMockedURLLoadFromBase(
         WebString(base_url_), test::CoreTestDataPath(), WebString(file_name));
   }
diff --git a/third_party/blink/renderer/core/loader/resource/font_resource_test.cc b/third_party/blink/renderer/core/loader/resource/font_resource_test.cc
index 887b0669..7a5e062b 100644
--- a/third_party/blink/renderer/core/loader/resource/font_resource_test.cc
+++ b/third_party/blink/renderer/core/loader/resource/font_resource_test.cc
@@ -8,7 +8,6 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
-#include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
 #include "third_party/blink/renderer/core/css/css_font_face_src_value.h"
 #include "third_party/blink/renderer/core/loader/resource/mock_font_resource_client.h"
@@ -26,6 +25,7 @@
 #include "third_party/blink/renderer/platform/loader/testing/test_loader_factory.h"
 #include "third_party/blink/renderer/platform/loader/testing/test_resource_fetcher_properties.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+#include "third_party/blink/renderer/platform/testing/url_test_helpers.h"
 #include "third_party/blink/renderer/platform/weborigin/kurl.h"
 
 namespace blink {
@@ -33,9 +33,7 @@
 class FontResourceTest : public testing::Test {
  public:
   void TearDown() override {
-    Platform::Current()
-        ->GetURLLoaderMockFactory()
-        ->UnregisterAllURLsAndClearMemoryCache();
+    url_test_helpers::UnregisterAllURLsAndClearMemoryCache();
   }
 };
 
@@ -59,8 +57,10 @@
   ResourceResponse response(url);
   response.SetHttpStatusCode(200);
   response.SetHttpHeaderField(http_names::kETag, "1234567890");
-  Platform::Current()->GetURLLoaderMockFactory()->RegisterURL(
-      url, WrappedResourceResponse(response), "");
+  // TODO(crbug.com/751425): We should use the mock functionality
+  // via the LoaderFactory.
+  url_test_helpers::RegisterMockedURLLoadWithCustomResponse(
+      url, "", WrappedResourceResponse(response));
 
   MockFetchContext* context = MakeGarbageCollected<MockFetchContext>();
   auto* properties = MakeGarbageCollected<TestResourceFetcherProperties>();
@@ -75,7 +75,7 @@
   Resource* resource1 = FontResource::Fetch(fetch_params1, fetcher, nullptr);
   ASSERT_FALSE(resource1->ErrorOccurred());
   fetcher->StartLoad(resource1);
-  Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
+  url_test_helpers::ServeAsynchronousRequests();
   EXPECT_TRUE(resource1->IsLoaded());
   EXPECT_FALSE(resource1->ErrorOccurred());
 
@@ -105,7 +105,7 @@
   // StartLoad() can be called from any initiator. Here, call it from the
   // latter.
   fetcher->StartLoad(resource3);
-  Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
+  url_test_helpers::ServeAsynchronousRequests();
   EXPECT_TRUE(resource3->IsLoaded());
   EXPECT_FALSE(resource3->ErrorOccurred());
   EXPECT_TRUE(resource2->IsLoaded());
@@ -119,8 +119,10 @@
   KURL url("http://127.0.0.1:8000/font.woff");
   ResourceResponse response(url);
   response.SetHttpStatusCode(200);
-  Platform::Current()->GetURLLoaderMockFactory()->RegisterURL(
-      url, WrappedResourceResponse(response), "");
+  // TODO(crbug.com/751425): We should use the mock functionality
+  // via the LoaderFactory.
+  url_test_helpers::RegisterMockedURLLoadWithCustomResponse(
+      url, "", WrappedResourceResponse(response));
 
   auto dummy_page_holder = std::make_unique<DummyPageHolder>(IntSize(800, 600));
   Document& document = dummy_page_holder->GetDocument();
@@ -177,7 +179,7 @@
   EXPECT_TRUE(client3->FontLoadShortLimitExceededCalled());
   EXPECT_TRUE(client3->FontLoadLongLimitExceededCalled());
 
-  Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
+  url_test_helpers::ServeAsynchronousRequests();
   GetMemoryCache()->Remove(&resource);
 }
 
diff --git a/third_party/blink/renderer/core/loader/threadable_loader_test.cc b/third_party/blink/renderer/core/loader/threadable_loader_test.cc
index 5d8fe7e..73cbbfc 100644
--- a/third_party/blink/renderer/core/loader/threadable_loader_test.cc
+++ b/third_party/blink/renderer/core/loader/threadable_loader_test.cc
@@ -10,7 +10,6 @@
 #include "base/memory/scoped_refptr.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/task_type.h"
 #include "third_party/blink/public/platform/web_url_load_timing.h"
 #include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
@@ -91,22 +90,16 @@
   return KURL("http://example.com/loop").Copy();
 }
 
-void ServeAsynchronousRequests() {
-  Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
-}
-
-void UnregisterAllURLsAndClearMemoryCache() {
-  Platform::Current()
-      ->GetURLLoaderMockFactory()
-      ->UnregisterAllURLsAndClearMemoryCache();
-}
-
 void SetUpSuccessURL() {
+  // TODO(crbug.com/751425): We should use the mock functionality
+  // via |dummy_page_holder_|.
   url_test_helpers::RegisterMockedURLLoad(
       SuccessURL(), test::CoreTestDataPath(kFileName), "text/html");
 }
 
 void SetUpErrorURL() {
+  // TODO(crbug.com/751425): We should use the mock functionality
+  // via |dummy_page_holder_|.
   url_test_helpers::RegisterMockedErrorURLLoad(ErrorURL());
 }
 
@@ -123,6 +116,8 @@
   response.AddHttpHeaderField("Location", SuccessURL().GetString());
   response.AddHttpHeaderField("Access-Control-Allow-Origin", "http://fake.url");
 
+  // TODO(crbug.com/751425): We should use the mock functionality
+  // via |dummy_page_holder_|.
   url_test_helpers::RegisterMockedURLLoadWithCustomResponse(
       url, test::CoreTestDataPath(kFileName), response);
 }
@@ -140,6 +135,8 @@
   response.AddHttpHeaderField("Location", RedirectLoopURL().GetString());
   response.AddHttpHeaderField("Access-Control-Allow-Origin", "http://fake.url");
 
+  // TODO(crbug.com/751425): We should use the mock functionality
+  // via |dummy_page_holder_|.
   url_test_helpers::RegisterMockedURLLoadWithCustomResponse(
       url, test::CoreTestDataPath(kFileName), response);
 }
@@ -186,14 +183,14 @@
 
   void OnSetUp() { SetUpMockURLs(); }
 
-  void OnServeRequests() { ServeAsynchronousRequests(); }
+  void OnServeRequests() { url_test_helpers::ServeAsynchronousRequests(); }
 
   void OnTearDown() {
     if (loader_) {
       loader_->Cancel();
       loader_ = nullptr;
     }
-    UnregisterAllURLsAndClearMemoryCache();
+    url_test_helpers::UnregisterAllURLsAndClearMemoryCache();
   }
 
  private:
diff --git a/third_party/blink/renderer/core/page/scrolling/main_thread_scrolling_reasons_test.cc b/third_party/blink/renderer/core/page/scrolling/main_thread_scrolling_reasons_test.cc
index 503226a..164aeac 100644
--- a/third_party/blink/renderer/core/page/scrolling/main_thread_scrolling_reasons_test.cc
+++ b/third_party/blink/renderer/core/page/scrolling/main_thread_scrolling_reasons_test.cc
@@ -46,9 +46,7 @@
   }
 
   ~MainThreadScrollingReasonsTest() override {
-    Platform::Current()
-        ->GetURLLoaderMockFactory()
-        ->UnregisterAllURLsAndClearMemoryCache();
+    url_test_helpers::UnregisterAllURLsAndClearMemoryCache();
   }
 
   void NavigateTo(const String& url) {
@@ -67,6 +65,8 @@
   }
 
   void RegisterMockedHttpURLLoad(const String& file_name) {
+    // TODO(crbug.com/751425): We should use the mock functionality
+    // via |helper_|.
     url_test_helpers::RegisterMockedURLLoadFromBase(
         WebString(base_url_), test::CoreTestDataPath(), WebString(file_name));
   }
diff --git a/third_party/blink/renderer/core/page/scrolling/root_scroller_test.cc b/third_party/blink/renderer/core/page/scrolling/root_scroller_test.cc
index 3995159..120ccb2d 100644
--- a/third_party/blink/renderer/core/page/scrolling/root_scroller_test.cc
+++ b/third_party/blink/renderer/core/page/scrolling/root_scroller_test.cc
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/web_coalesced_input_event.h"
 #include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
 #include "third_party/blink/public/web/web_console_message.h"
@@ -64,9 +63,7 @@
 
   ~RootScrollerTest() override {
     features_backup_.Restore();
-    Platform::Current()
-        ->GetURLLoaderMockFactory()
-        ->UnregisterAllURLsAndClearMemoryCache();
+    url_test_helpers::UnregisterAllURLsAndClearMemoryCache();
   }
 
   void SetAndSelectRootScroller(Document& document, Element* element) {
@@ -102,6 +99,8 @@
   }
 
   void RegisterMockedHttpURLLoad(const String& file_name) {
+    // TODO(crbug.com/751425): We should use the mock functionality
+    // via |helper_|.
     url_test_helpers::RegisterMockedURLLoadFromBase(
         WebString(base_url_), test::CoreTestDataPath(), WebString(file_name));
   }
diff --git a/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_test.cc b/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_test.cc
index 6e873205..d3bf6a57 100644
--- a/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_test.cc
+++ b/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_test.cc
@@ -28,7 +28,6 @@
 #include "cc/layers/picture_layer.h"
 #include "cc/trees/sticky_position_constraint.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/web_cache.h"
 #include "third_party/blink/public/platform/web_rect.h"
 #include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
@@ -94,9 +93,7 @@
   }
 
   ~ScrollingCoordinatorTest() override {
-    Platform::Current()
-        ->GetURLLoaderMockFactory()
-        ->UnregisterAllURLsAndClearMemoryCache();
+    url_test_helpers::UnregisterAllURLsAndClearMemoryCache();
   }
 
   void NavigateTo(const std::string& url) {
@@ -114,6 +111,8 @@
   }
 
   void RegisterMockedHttpURLLoad(const std::string& file_name) {
+    // TODO(crbug.com/751425): We should use the mock functionality
+    // via |helper_|.
     url_test_helpers::RegisterMockedURLLoadFromBase(
         WebString::FromUTF8(base_url_), test::CoreTestDataPath(),
         WebString::FromUTF8(file_name));
diff --git a/third_party/blink/renderer/core/page/viewport_test.cc b/third_party/blink/renderer/core/page/viewport_test.cc
index 9d49455e..d2a25c0 100644
--- a/third_party/blink/renderer/core/page/viewport_test.cc
+++ b/third_party/blink/renderer/core/page/viewport_test.cc
@@ -29,7 +29,6 @@
  */
 
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
 #include "third_party/blink/public/web/web_console_message.h"
 #include "third_party/blink/public/web/web_frame.h"
@@ -64,18 +63,20 @@
       : base_url_("http://www.test.com/"), chrome_url_("chrome://") {}
 
   ~ViewportTest() override {
-    Platform::Current()
-        ->GetURLLoaderMockFactory()
-        ->UnregisterAllURLsAndClearMemoryCache();
+    url_test_helpers::UnregisterAllURLsAndClearMemoryCache();
   }
 
   void RegisterMockedHttpURLLoad(const std::string& file_name) {
+    // TODO(crbug.com/751425): We should use the mock functionality
+    // via the WebViewHelper instance in each test case.
     url_test_helpers::RegisterMockedURLLoadFromBase(
         WebString::FromUTF8(base_url_), test::CoreTestDataPath(),
         WebString::FromUTF8(file_name));
   }
 
   void RegisterMockedChromeURLLoad(const std::string& file_name) {
+    // TODO(crbug.com/751425): We should use the mock functionality
+    // via the WebViewHelper instance in each test case.
     url_test_helpers::RegisterMockedURLLoadFromBase(
         WebString::FromUTF8(chrome_url_), test::CoreTestDataPath(),
         WebString::FromUTF8(file_name));
diff --git a/third_party/blink/renderer/core/paint/link_highlight_impl_test.cc b/third_party/blink/renderer/core/paint/link_highlight_impl_test.cc
index e2059928..13405ba 100644
--- a/third_party/blink/renderer/core/paint/link_highlight_impl_test.cc
+++ b/third_party/blink/renderer/core/paint/link_highlight_impl_test.cc
@@ -30,7 +30,6 @@
 #include "cc/layers/picture_layer.h"
 #include "cc/trees/layer_tree_host.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/web_float_point.h"
 #include "third_party/blink/public/platform/web_input_event.h"
 #include "third_party/blink/public/platform/web_size.h"
@@ -76,6 +75,8 @@
   }
 
   void SetUp() override {
+    // TODO(crbug.com/751425): We should use the mock functionality
+    // via |web_view_helper_|.
     WebURL url = url_test_helpers::RegisterMockedURLLoadFromBase(
         WebString::FromUTF8("http://www.test.com/"), test::CoreTestDataPath(),
         WebString::FromUTF8("test_touch_link_highlight.html"));
@@ -83,9 +84,7 @@
   }
 
   void TearDown() override {
-    Platform::Current()
-        ->GetURLLoaderMockFactory()
-        ->UnregisterAllURLsAndClearMemoryCache();
+    url_test_helpers::UnregisterAllURLsAndClearMemoryCache();
 
     // Ensure we fully clean up while scoped settings are enabled. Without this,
     // garbage collection would occur after Scoped[setting]ForTest is out of
@@ -441,6 +440,8 @@
   }
 
   void SetUp() override {
+    // TODO(crbug.com/751425): We should use the mock functionality
+    // via |web_view_helper_|.
     WebURL url = url_test_helpers::RegisterMockedURLLoadFromBase(
         WebString::FromUTF8("http://www.test.com/"), test::CoreTestDataPath(),
         WebString::FromUTF8("test_touch_link_highlight_squashing.html"));
diff --git a/third_party/blink/renderer/core/script/BUILD.gn b/third_party/blink/renderer/core/script/BUILD.gn
index ac7886e..80193de 100644
--- a/third_party/blink/renderer/core/script/BUILD.gn
+++ b/third_party/blink/renderer/core/script/BUILD.gn
@@ -48,6 +48,8 @@
     "module_script.h",
     "parsed_specifier.cc",
     "parsed_specifier.h",
+    "pending_import_map.cc",
+    "pending_import_map.h",
     "pending_script.cc",
     "pending_script.h",
     "script.h",
diff --git a/third_party/blink/renderer/core/script/import_map.cc b/third_party/blink/renderer/core/script/import_map.cc
index 03987d78..7fd3c88 100644
--- a/third_party/blink/renderer/core/script/import_map.cc
+++ b/third_party/blink/renderer/core/script/import_map.cc
@@ -7,6 +7,7 @@
 #include <memory>
 #include <utility>
 #include "third_party/blink/public/mojom/devtools/console_message.mojom-blink.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
 #include "third_party/blink/renderer/core/script/layered_api.h"
 #include "third_party/blink/renderer/core/script/modulator.h"
 #include "third_party/blink/renderer/core/script/parsed_specifier.h"
@@ -146,35 +147,30 @@
 // Parse |text| as an import map. Errors (e.g. json parsing error, invalid
 // keys/values, etc.) are basically ignored, except that they are reported to
 // the console |logger|.
-// TODO(hiroshige): Handle errors in a spec-conformant way once specified.
-// https://github.com/WICG/import-maps/issues/100
-ImportMap* ImportMap::Create(const Modulator& modulator_for_built_in_modules,
-                             const String& input,
-                             const KURL& base_url,
-                             ConsoleLogger& logger) {
+ImportMap* ImportMap::Parse(const Modulator& modulator,
+                            const String& input,
+                            const KURL& base_url,
+                            ConsoleLogger& logger,
+                            ScriptValue* error_to_rethrow) {
+  DCHECK(error_to_rethrow);
+
   // <spec step="1">Let parsed be the result of parsing JSON into Infra values
   // given input.</spec>
   std::unique_ptr<JSONValue> parsed = ParseJSON(input);
 
   if (!parsed) {
-    logger.AddConsoleMessage(mojom::ConsoleMessageSource::kOther,
-                             mojom::ConsoleMessageLevel::kError,
-                             "Failed to parse import map: invalid JSON");
-    // TODO(hiroshige): Return null.
-    return MakeGarbageCollected<ImportMap>(modulator_for_built_in_modules,
-                                           SpecifierMap());
+    *error_to_rethrow =
+        modulator.CreateSyntaxError("Failed to parse import map: invalid JSON");
+    return MakeGarbageCollected<ImportMap>(modulator, SpecifierMap());
   }
 
   // <spec step="2">If parsed is not a map, then throw a TypeError indicating
   // that the top-level value must be a JSON object.</spec>
   std::unique_ptr<JSONObject> parsed_map = JSONObject::From(std::move(parsed));
   if (!parsed_map) {
-    logger.AddConsoleMessage(mojom::ConsoleMessageSource::kOther,
-                             mojom::ConsoleMessageLevel::kError,
-                             "Failed to parse import map: not an object");
-    // TODO(hiroshige): Return null.
-    return MakeGarbageCollected<ImportMap>(modulator_for_built_in_modules,
-                                           SpecifierMap());
+    *error_to_rethrow =
+        modulator.CreateTypeError("Failed to parse import map: not an object");
+    return MakeGarbageCollected<ImportMap>(modulator, SpecifierMap());
   }
 
   // <spec step="3">Let sortedAndNormalizedImports be an empty map.</spec>
@@ -187,13 +183,10 @@
     // object.</spec>
     JSONObject* imports = parsed_map->GetJSONObject("imports");
     if (!imports) {
-      logger.AddConsoleMessage(mojom::ConsoleMessageSource::kOther,
-                               mojom::ConsoleMessageLevel::kError,
-                               "Failed to parse import map: \"imports\" "
-                               "top-level key must be a JSON object.");
-      // TODO(hiroshige): Return null.
-      return MakeGarbageCollected<ImportMap>(modulator_for_built_in_modules,
-                                             SpecifierMap());
+      *error_to_rethrow = modulator.CreateTypeError(
+          "Failed to parse import map: \"imports\" "
+          "top-level key must be a JSON object.");
+      return MakeGarbageCollected<ImportMap>(modulator, SpecifierMap());
     }
 
     // <spec step="4.2">Set sortedAndNormalizedImports to the result of sorting
@@ -210,7 +203,7 @@
   // <spec step="8">Return the import map whose imports are
   // sortedAndNormalizedImports and whose scopes scopes are
   // sortedAndNormalizedScopes.</spec>
-  return MakeGarbageCollected<ImportMap>(modulator_for_built_in_modules,
+  return MakeGarbageCollected<ImportMap>(modulator,
                                          sorted_and_normalized_imports);
 }
 
diff --git a/third_party/blink/renderer/core/script/import_map.h b/third_party/blink/renderer/core/script/import_map.h
index 1a3ec8e4..240a2a3 100644
--- a/third_party/blink/renderer/core/script/import_map.h
+++ b/third_party/blink/renderer/core/script/import_map.h
@@ -18,6 +18,7 @@
 class JSONObject;
 class Modulator;
 class ParsedSpecifier;
+class ScriptValue;
 
 // Import maps.
 // https://wicg.github.io/import-maps/
@@ -25,10 +26,11 @@
 class CORE_EXPORT ImportMap final
     : public GarbageCollectedFinalized<ImportMap> {
  public:
-  static ImportMap* Create(const Modulator& modulator_for_built_in_modules,
-                           const String& text,
-                           const KURL& base_url,
-                           ConsoleLogger& logger);
+  static ImportMap* Parse(const Modulator&,
+                          const String& text,
+                          const KURL& base_url,
+                          ConsoleLogger& logger,
+                          ScriptValue* error_to_rethrow);
 
   ImportMap(const Modulator&, const HashMap<String, Vector<KURL>>& imports);
 
diff --git a/third_party/blink/renderer/core/script/modulator.h b/third_party/blink/renderer/core/script/modulator.h
index f2d0415..e9d4f06 100644
--- a/third_party/blink/renderer/core/script/modulator.h
+++ b/third_party/blink/renderer/core/script/modulator.h
@@ -174,8 +174,12 @@
                                   const ReferrerScriptInfo&,
                                   ScriptPromiseResolver*) = 0;
 
+  virtual ScriptValue CreateTypeError(const String& message) const = 0;
+  virtual ScriptValue CreateSyntaxError(const String& message) const = 0;
+
   // Import maps. https://github.com/WICG/import-maps
-  virtual void RegisterImportMap(const ImportMap*) = 0;
+  virtual void RegisterImportMap(const ImportMap*,
+                                 ScriptValue error_to_rethrow) = 0;
   virtual bool IsAcquiringImportMaps() const = 0;
   virtual void ClearIsAcquiringImportMaps() = 0;
   virtual const ImportMap* GetImportMapForTest() const = 0;
diff --git a/third_party/blink/renderer/core/script/modulator_impl_base.cc b/third_party/blink/renderer/core/script/modulator_impl_base.cc
index 782476a..cfc3cca 100644
--- a/third_party/blink/renderer/core/script/modulator_impl_base.cc
+++ b/third_party/blink/renderer/core/script/modulator_impl_base.cc
@@ -237,22 +237,52 @@
   }
 }
 
-void ModulatorImplBase::RegisterImportMap(const ImportMap* import_map) {
+ScriptValue ModulatorImplBase::CreateTypeError(const String& message) const {
+  ScriptState::Scope scope(script_state_);
+  ScriptValue error(script_state_, V8ThrowException::CreateTypeError(
+                                       script_state_->GetIsolate(), message));
+  return error;
+}
+
+ScriptValue ModulatorImplBase::CreateSyntaxError(const String& message) const {
+  ScriptState::Scope scope(script_state_);
+  ScriptValue error(script_state_, V8ThrowException::CreateSyntaxError(
+                                       script_state_->GetIsolate(), message));
+  return error;
+}
+
+// <specdef href="https://wicg.github.io/import-maps/#register-an-import-map">
+void ModulatorImplBase::RegisterImportMap(const ImportMap* import_map,
+                                          ScriptValue error_to_rethrow) {
+  DCHECK(import_map);
+  DCHECK(BuiltInModuleInfraEnabled());
+
+  // <spec step="7">If import map parse result’s error to rethrow is not null,
+  // then:</spec>
+  if (!error_to_rethrow.IsEmpty()) {
+    // <spec step="7.1">Report the exception given import map parse result’s
+    // error to rethrow. ...</spec>
+    if (!IsScriptingDisabled()) {
+      ScriptState::Scope scope(script_state_);
+      ModuleRecord::ReportException(script_state_, error_to_rethrow.V8Value());
+    }
+
+    // <spec step="7.2">Return.</spec>
+    return;
+  }
+
+  // <spec step="8">Update element’s node document's import map with import map
+  // parse result’s import map.</spec>
+  //
+  // TODO(crbug.com/927119): Implement merging. Currently only one import map is
+  // allowed.
   if (import_map_) {
-    // Only one import map is allowed.
-    // TODO(crbug.com/927119): Implement merging.
     GetExecutionContext()->AddConsoleMessage(
         mojom::ConsoleMessageSource::kOther, mojom::ConsoleMessageLevel::kError,
         "Multiple import maps are not yet supported. https://crbug.com/927119");
     return;
   }
 
-  if (!BuiltInModuleInfraEnabled()) {
-    GetExecutionContext()->AddConsoleMessage(
-        mojom::ConsoleMessageSource::kOther, mojom::ConsoleMessageLevel::kError,
-        "Import maps are disabled when Layered API Infra is disabled.");
-    return;
-  }
   import_map_ = import_map;
 }
 
@@ -405,8 +435,7 @@
     v8::Local<v8::Module> record = module_script->V8Module();
     CHECK(!record.IsEmpty());
 
-    // <spec step="7.2">Set evaluationStatus to ModuleRecord::Evaluate().
-    // ...</spec>
+    // <spec step="7.2">Set evaluationStatus to record.Evaluate(). ...</spec>
     error = ModuleRecord::Evaluate(script_state_, record,
                                    module_script->SourceURL());
 
diff --git a/third_party/blink/renderer/core/script/modulator_impl_base.h b/third_party/blink/renderer/core/script/modulator_impl_base.h
index e062a2e..4f21e19 100644
--- a/third_party/blink/renderer/core/script/modulator_impl_base.h
+++ b/third_party/blink/renderer/core/script/modulator_impl_base.h
@@ -80,7 +80,10 @@
                           const ReferrerScriptInfo&,
                           ScriptPromiseResolver*) override;
   const ImportMap* GetImportMapForTest() const final { return import_map_; }
-  void RegisterImportMap(const ImportMap*) final;
+
+  ScriptValue CreateTypeError(const String& message) const override;
+  ScriptValue CreateSyntaxError(const String& message) const override;
+  void RegisterImportMap(const ImportMap*, ScriptValue error_to_rethrow) final;
   bool IsAcquiringImportMaps() const final { return acquiring_import_maps_; }
   void ClearIsAcquiringImportMaps() final { acquiring_import_maps_ = false; }
   ModuleImportMeta HostGetImportMetaProperties(
diff --git a/third_party/blink/renderer/core/script/pending_import_map.cc b/third_party/blink/renderer/core/script/pending_import_map.cc
new file mode 100644
index 0000000..5e762238
--- /dev/null
+++ b/third_party/blink/renderer/core/script/pending_import_map.cc
@@ -0,0 +1,105 @@
+// Copyright 2019 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 "third_party/blink/renderer/core/script/pending_import_map.h"
+
+#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
+#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/script/import_map.h"
+#include "third_party/blink/renderer/core/script/modulator.h"
+#include "third_party/blink/renderer/core/script/script_element_base.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+
+namespace blink {
+
+PendingImportMap* PendingImportMap::CreateInline(ScriptElementBase& element,
+                                                 const String& import_map_text,
+                                                 const KURL& base_url) {
+  Document& element_document = element.GetDocument();
+  Document* context_document = element_document.ContextDocument();
+  Modulator* modulator =
+      Modulator::From(ToScriptStateForMainWorld(context_document->GetFrame()));
+
+  ScriptValue error_to_rethrow;
+  ImportMap* import_map =
+      ImportMap::Parse(*modulator, import_map_text, base_url, *context_document,
+                       &error_to_rethrow);
+  return MakeGarbageCollected<PendingImportMap>(
+      element, import_map, error_to_rethrow, *context_document);
+}
+
+PendingImportMap::PendingImportMap(ScriptElementBase& element,
+                                   ImportMap* import_map,
+                                   ScriptValue error_to_rethrow,
+                                   const Document& original_context_document)
+    : element_(&element),
+      import_map_(import_map),
+      original_context_document_(&original_context_document) {
+  if (!error_to_rethrow.IsEmpty()) {
+    ScriptState::Scope scope(error_to_rethrow.GetScriptState());
+    error_to_rethrow_.Set(error_to_rethrow.GetIsolate(),
+                          error_to_rethrow.V8Value());
+  }
+}
+
+// <specdef href="https://wicg.github.io/import-maps/#register-an-import-map">
+// This is parallel to PendingScript::ExecuteScriptBlock().
+void PendingImportMap::RegisterImportMap() const {
+  // <spec step="1">If element’s the script’s result is null, then fire an event
+  // named error at element, and return.</spec>
+  if (!import_map_) {
+    element_->DispatchErrorEvent();
+    return;
+  }
+
+  // <spec step="2">Let import map parse result be element’s the script’s
+  // result.</spec>
+  //
+  // This is |this|.
+
+  // <spec step="3">Assert: element’s the script’s type is "importmap".</spec>
+  //
+  // <spec step="4">Assert: import map parse result is an import map parse
+  // result.</spec>
+  //
+  // These are ensured by C++ type.
+
+  // <spec step="5">Let settings object be import map parse result’s settings
+  // object.</spec>
+  //
+  // <spec step="6">If element’s node document’s relevant settings object is not
+  // equal to settings object, then return. ...</spec>
+  Document* context_document = element_->GetDocument().ContextDocument();
+  if (!context_document)
+    return;
+  if (original_context_document_ != context_document)
+    return;
+
+  // Steps 7 and 8.
+  LocalFrame* frame = context_document->GetFrame();
+  if (!frame)
+    return;
+
+  Modulator* modulator = Modulator::From(ToScriptStateForMainWorld(frame));
+
+  ScriptState* script_state = modulator->GetScriptState();
+  ScriptState::Scope scope(script_state);
+  ScriptValue error(script_state,
+                    error_to_rethrow_.NewLocal(script_state->GetIsolate()));
+  modulator->RegisterImportMap(import_map_, error);
+
+  // <spec step="9">If element is from an external file, then fire an event
+  // named load at element.</spec>
+  //
+  // TODO(hiroshige): Implement this when external import maps are implemented.
+}
+
+void PendingImportMap::Trace(Visitor* visitor) {
+  visitor->Trace(element_);
+  visitor->Trace(import_map_);
+  visitor->Trace(error_to_rethrow_);
+  visitor->Trace(original_context_document_);
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/script/pending_import_map.h b/third_party/blink/renderer/core/script/pending_import_map.h
new file mode 100644
index 0000000..3344fec
--- /dev/null
+++ b/third_party/blink/renderer/core/script/pending_import_map.h
@@ -0,0 +1,73 @@
+// Copyright 2019 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 THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_PENDING_IMPORT_MAP_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_PENDING_IMPORT_MAP_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
+#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
+#include "third_party/blink/renderer/platform/heap/member.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "v8/include/v8.h"
+
+namespace blink {
+
+class Document;
+class ImportMap;
+class KURL;
+class ScriptElementBase;
+class ScriptValue;
+
+// PendingImportMap serves as a container for an import map after "prepare a
+// script" until it is registered. PendingImportMap is similar to PendingScript.
+//
+// After PendingImportMap is ready, PendingImportMap works mostly as
+// https://wicg.github.io/import-maps/#import-map-parse-result and
+// |element_|'s script's result is |this|,
+// except for "null import map parse result" corresponds to
+// non-null PendingImportMap with |import_map_| == nullptr.
+//
+// Note: Currently we only support inline import maps and PendingImportMap is
+// always ready.
+class CORE_EXPORT PendingImportMap final
+    : public GarbageCollectedFinalized<PendingImportMap> {
+ public:
+  // https://wicg.github.io/import-maps/#create-an-import-map-parse-result
+  // for inline import maps.
+  static PendingImportMap* CreateInline(ScriptElementBase&,
+                                        const String& import_map_text,
+                                        const KURL& base_url);
+
+  PendingImportMap(ScriptElementBase&,
+                   ImportMap*,
+                   ScriptValue error_to_rethrow,
+                   const Document& original_context_document);
+
+  void RegisterImportMap() const;
+
+  virtual void Trace(Visitor* visitor);
+
+ private:
+  Member<ScriptElementBase> element_;
+
+  // https://wicg.github.io/import-maps/#import-map-parse-result-import-map
+  Member<ImportMap> import_map_;
+
+  // https://wicg.github.io/import-maps/#import-map-parse-result-error-to-rethrow
+  // The error is TypeError if the string is non-null, or null otherwise.
+  TraceWrapperV8Reference<v8::Value> error_to_rethrow_;
+
+  // https://wicg.github.io/import-maps/#import-map-parse-result-settings-object
+  // The context document at the time when PrepareScript() is executed.
+  // This is only used to check whether the script element is moved between
+  // documents and thus doesn't retain a strong reference.
+  WeakMember<const Document> original_context_document_;
+
+  DISALLOW_COPY_AND_ASSIGN(PendingImportMap);
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_PENDING_IMPORT_MAP_H_
diff --git a/third_party/blink/renderer/core/script/script_loader.cc b/third_party/blink/renderer/core/script/script_loader.cc
index fa6fd69..5a0d3db3 100644
--- a/third_party/blink/renderer/core/script/script_loader.cc
+++ b/third_party/blink/renderer/core/script/script_loader.cc
@@ -46,6 +46,7 @@
 #include "third_party/blink/renderer/core/script/js_module_script.h"
 #include "third_party/blink/renderer/core/script/modulator.h"
 #include "third_party/blink/renderer/core/script/module_pending_script.h"
+#include "third_party/blink/renderer/core/script/pending_import_map.h"
 #include "third_party/blink/renderer/core/script/script.h"
 #include "third_party/blink/renderer/core/script/script_element_base.h"
 #include "third_party/blink/renderer/core/script/script_runner.h"
@@ -172,50 +173,6 @@
   kShouldFire,
 };
 
-ShouldFireErrorEvent ParseAndRegisterImportMap(ScriptElementBase& element) {
-  Document& element_document = element.GetDocument();
-  Document* context_document = element_document.ContextDocument();
-  DCHECK(context_document);
-  Modulator* modulator =
-      Modulator::From(ToScriptStateForMainWorld(context_document->GetFrame()));
-  DCHECK(modulator);
-
-  // If import maps are not enabled, we do nothing and return here, and also
-  // do not fire error events.
-  if (!modulator->BuiltInModuleInfraEnabled())
-    return ShouldFireErrorEvent::kDoNotFire;
-
-  if (!modulator->IsAcquiringImportMaps()) {
-    element_document.AddConsoleMessage(ConsoleMessage::Create(
-        mojom::ConsoleMessageSource::kJavaScript,
-        mojom::ConsoleMessageLevel::kError,
-        "An import map is added after module script load was triggered."));
-    return ShouldFireErrorEvent::kShouldFire;
-  }
-
-  // TODO(crbug.com/922212): Implemenet external import maps.
-  if (element.HasSourceAttribute()) {
-    element_document.AddConsoleMessage(
-        ConsoleMessage::Create(mojom::ConsoleMessageSource::kJavaScript,
-                               mojom::ConsoleMessageLevel::kError,
-                               "External import maps are not yet supported."));
-    return ShouldFireErrorEvent::kShouldFire;
-  }
-
-  UseCounter::Count(*context_document, WebFeature::kImportMap);
-
-  KURL base_url = element_document.BaseURL();
-  const String import_map_text = element.TextFromChildren();
-  ImportMap* import_map = ImportMap::Create(*modulator, import_map_text,
-                                            base_url, element_document);
-
-  if (!import_map)
-    return ShouldFireErrorEvent::kShouldFire;
-
-  modulator->RegisterImportMap(import_map);
-  return ShouldFireErrorEvent::kDoNotFire;
-}
-
 }  // namespace
 
 // <specdef href="https://html.spec.whatwg.org/C/#prepare-a-script">
@@ -389,6 +346,14 @@
   if (!context_document->CanExecuteScripts(kAboutToExecuteScript))
     return false;
 
+  // Set |is_import_map| only if BuiltInModuleInfraEnabled().
+  if (is_import_map) {
+    Modulator* modulator = Modulator::From(
+        ToScriptStateForMainWorld(context_document->GetFrame()));
+    if (!modulator->BuiltInModuleInfraEnabled())
+      is_import_map = false;
+  }
+
   // <spec step="12">If the script element has a nomodule content attribute and
   // the script's type is "classic", then return. The script is not
   // executed.</spec>
@@ -424,18 +389,6 @@
   if (!IsScriptForEventSupported())
     return false;
 
-  // Process the import map.
-  if (is_import_map) {
-    if (ParseAndRegisterImportMap(*element_) ==
-        ShouldFireErrorEvent::kShouldFire) {
-      element_document.GetTaskRunner(TaskType::kDOMManipulation)
-          ->PostTask(FROM_HERE,
-                     WTF::Bind(&ScriptElementBase::DispatchErrorEvent,
-                               WrapPersistent(element_.Get())));
-    }
-    return false;
-  }
-
   // This FeaturePolicy is still in the process of being added to the spec.
   if (ShouldBlockSyncScriptForFeaturePolicy(element_.Get(), GetScriptType(),
                                             parser_inserted_)) {
@@ -523,6 +476,26 @@
   // TODO(hiroshige): Use a consistent Document everywhere.
   auto* fetch_client_settings_object_fetcher = context_document->Fetcher();
 
+  // https://wicg.github.io/import-maps/#integration-prepare-a-script
+  // If the script’s type is "importmap" and the element’s node document’s
+  // acquiring import maps is false, then queue a task to fire an event named
+  // error at the element, and return. [spec text]
+  if (is_import_map) {
+    Modulator* modulator = Modulator::From(
+        ToScriptStateForMainWorld(context_document->GetFrame()));
+    if (!modulator->IsAcquiringImportMaps()) {
+      element_document.AddConsoleMessage(ConsoleMessage::Create(
+          mojom::ConsoleMessageSource::kJavaScript,
+          mojom::ConsoleMessageLevel::kError,
+          "An import map is added after module script load was triggered."));
+      element_document.GetTaskRunner(TaskType::kDOMManipulation)
+          ->PostTask(FROM_HERE,
+                     WTF::Bind(&ScriptElementBase::DispatchErrorEvent,
+                               WrapPersistent(element_.Get())));
+      return false;
+    }
+  }
+
   // <spec step="24">If the element has a src content attribute, then:</spec>
   if (element_->HasSourceAttribute()) {
     // <spec step="24.1">Let src be the value of the element's src
@@ -559,6 +532,19 @@
     }
 
     // <spec step="24.6">Switch on the script's type:</spec>
+    if (is_import_map) {
+      // TODO(crbug.com/922212): Implement external import maps.
+      element_document.AddConsoleMessage(ConsoleMessage::Create(
+          mojom::ConsoleMessageSource::kJavaScript,
+          mojom::ConsoleMessageLevel::kError,
+          "External import maps are not yet supported."));
+      element_document.GetTaskRunner(TaskType::kDOMManipulation)
+          ->PostTask(FROM_HERE,
+                     WTF::Bind(&ScriptElementBase::DispatchErrorEvent,
+                               WrapPersistent(element_.Get())));
+      return false;
+    }
+
     if (GetScriptType() == mojom::ScriptType::kClassic) {
       // - "classic":
 
@@ -628,6 +614,25 @@
     KURL base_url = element_document.BaseURL();
 
     // <spec step="25.2">Switch on the script's type:</spec>
+
+    if (is_import_map) {
+      UseCounter::Count(*context_document, WebFeature::kImportMap);
+
+      // https://wicg.github.io/import-maps/#integration-prepare-a-script
+      // 1. Let import map parse result be the result of create an import map
+      // parse result, given source text, base URL and settings object. [spec
+      // text]
+      PendingImportMap* pending_import_map = PendingImportMap::CreateInline(
+          *element_, element_->TextFromChildren(), base_url);
+
+      // Because we currently support inline import maps only, the pending
+      // import map is ready immediately and thus we call `register an import
+      // map` synchronously here.
+      pending_import_map->RegisterImportMap();
+
+      return false;
+    }
+
     switch (GetScriptType()) {
         // <spec step="25.2.A">"classic"</spec>
       case mojom::ScriptType::kClassic: {
diff --git a/third_party/blink/renderer/core/testing/dummy_modulator.cc b/third_party/blink/renderer/core/testing/dummy_modulator.cc
index 77e202da..7ab9168 100644
--- a/third_party/blink/renderer/core/testing/dummy_modulator.cc
+++ b/third_party/blink/renderer/core/testing/dummy_modulator.cc
@@ -125,7 +125,17 @@
   NOTREACHED();
 }
 
-void DummyModulator::RegisterImportMap(const ImportMap*) {
+ScriptValue DummyModulator::CreateTypeError(const String& message) const {
+  NOTREACHED();
+  return ScriptValue();
+}
+ScriptValue DummyModulator::CreateSyntaxError(const String& message) const {
+  NOTREACHED();
+  return ScriptValue();
+}
+
+void DummyModulator::RegisterImportMap(const ImportMap*,
+                                       ScriptValue error_to_rethrow) {
   NOTREACHED();
 }
 
diff --git a/third_party/blink/renderer/core/testing/dummy_modulator.h b/third_party/blink/renderer/core/testing/dummy_modulator.h
index f528f6b..6d9ec5c 100644
--- a/third_party/blink/renderer/core/testing/dummy_modulator.h
+++ b/third_party/blink/renderer/core/testing/dummy_modulator.h
@@ -61,7 +61,10 @@
                           const KURL&,
                           const ReferrerScriptInfo&,
                           ScriptPromiseResolver*) override;
-  void RegisterImportMap(const ImportMap*) override;
+  ScriptValue CreateTypeError(const String& message) const override;
+  ScriptValue CreateSyntaxError(const String& message) const override;
+  void RegisterImportMap(const ImportMap*,
+                         ScriptValue error_to_rethrow) override;
   bool IsAcquiringImportMaps() const override;
   void ClearIsAcquiringImportMaps() override;
   ModuleImportMeta HostGetImportMetaProperties(
diff --git a/third_party/blink/renderer/core/testing/sim/sim_network.cc b/third_party/blink/renderer/core/testing/sim/sim_network.cc
index 22911ca..5f7b264 100644
--- a/third_party/blink/renderer/core/testing/sim/sim_network.cc
+++ b/third_party/blink/renderer/core/testing/sim/sim_network.cc
@@ -6,7 +6,6 @@
 
 #include <memory>
 #include <utility>
-#include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/web_url_error.h"
 #include "third_party/blink/public/platform/web_url_loader.h"
 #include "third_party/blink/public/platform/web_url_loader_client.h"
@@ -16,22 +15,23 @@
 #include "third_party/blink/renderer/core/loader/document_loader.h"
 #include "third_party/blink/renderer/core/testing/sim/sim_request.h"
 #include "third_party/blink/renderer/platform/loader/static_data_navigation_body_loader.h"
+#include "third_party/blink/renderer/platform/testing/url_test_helpers.h"
 
 namespace blink {
 
 static SimNetwork* g_network = nullptr;
 
 SimNetwork::SimNetwork() : current_request_(nullptr) {
-  Platform::Current()->GetURLLoaderMockFactory()->SetLoaderDelegate(this);
+  url_test_helpers::SetLoaderDelegate(this);
   DCHECK(!g_network);
   g_network = this;
 }
 
 SimNetwork::~SimNetwork() {
-  Platform::Current()->GetURLLoaderMockFactory()->SetLoaderDelegate(nullptr);
-  Platform::Current()
-      ->GetURLLoaderMockFactory()
-      ->UnregisterAllURLsAndClearMemoryCache();
+  url_test_helpers::SetLoaderDelegate(nullptr);
+  // TODO(crbug.com/751425): We should use the mock functionality
+  // via |SimTest::web_frame_client_| and/or |SimTest::web_view_helper_|.
+  url_test_helpers::UnregisterAllURLsAndClearMemoryCache();
   g_network = nullptr;
 }
 
@@ -41,7 +41,9 @@
 }
 
 void SimNetwork::ServePendingRequests() {
-  Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
+  // TODO(crbug.com/751425): We should use the mock functionality
+  // via |SimTest::web_frame_client_| and/or |SimTest::web_view_helper_|.
+  url_test_helpers::ServeAsynchronousRequests();
 }
 
 void SimNetwork::DidReceiveResponse(WebURLLoaderClient* client,
@@ -106,13 +108,17 @@
   for (const auto& http_header : request.response_http_headers_)
     response.AddHttpHeaderField(http_header.key, http_header.value);
 
-  Platform::Current()->GetURLLoaderMockFactory()->RegisterURL(request.url_,
-                                                              response, "");
+  // TODO(crbug.com/751425): We should use the mock functionality
+  // via |SimTest::web_frame_client_| and/or |SimTest::web_view_helper_|.
+  url_test_helpers::RegisterMockedURLLoadWithCustomResponse(request.url_, "",
+                                                            response);
 }
 
 void SimNetwork::RemoveRequest(SimRequestBase& request) {
   requests_.erase(request.url_);
-  Platform::Current()->GetURLLoaderMockFactory()->UnregisterURL(request.url_);
+  // TODO(crbug.com/751425): We should use the mock functionality
+  // via |SimTest::web_frame_client_| and/or |SimTest::web_view_helper_|.
+  url_test_helpers::RegisterMockedURLUnregister(request.url_);
 }
 
 bool SimNetwork::FillNavigationParamsResponse(WebNavigationParams* params) {
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_object_store.cc b/third_party/blink/renderer/modules/indexeddb/idb_object_store.cc
index 56247dd..8e5b64b 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_object_store.cc
+++ b/third_party/blink/renderer/modules/indexeddb/idb_object_store.cc
@@ -300,11 +300,19 @@
 
 static Vector<std::unique_ptr<IDBKey>> GenerateIndexKeysForValue(
     v8::Isolate* isolate,
+    const IDBObjectStoreMetadata& store_metadata,
     const IDBIndexMetadata& index_metadata,
     const ScriptValue& object_value) {
   NonThrowableExceptionState exception_state;
+
+  // Look up the key using the index's key path.
   std::unique_ptr<IDBKey> index_key = ScriptValue::To<std::unique_ptr<IDBKey>>(
-      isolate, object_value, exception_state, index_metadata.key_path);
+      isolate, object_value, exception_state, store_metadata.key_path,
+      index_metadata.key_path);
+
+  // No match. (In the special case for a store with a key generator and in-line
+  // keys and where the store and index key paths match, the back-end will
+  // synthesize an index key.)
   if (!index_key)
     return Vector<std::unique_ptr<IDBKey>>();
 
@@ -542,10 +550,10 @@
   for (const auto& it : Metadata().indexes) {
     if (clone.IsEmpty())
       value_wrapper.Clone(script_state, &clone);
-    index_keys.emplace_back(
-        IDBIndexKeys{.id = it.key,
-                     .keys = GenerateIndexKeysForValue(
-                         script_state->GetIsolate(), *it.value, clone)});
+    index_keys.emplace_back(IDBIndexKeys{
+        .id = it.key,
+        .keys = GenerateIndexKeysForValue(script_state->GetIsolate(),
+                                          Metadata(), *it.value, clone)});
   }
   // Records 1KB to 1GB.
   UMA_HISTOGRAM_COUNTS_1M(
@@ -687,11 +695,13 @@
                  IDBDatabase* database,
                  int64_t transaction_id,
                  int64_t object_store_id,
+                 scoped_refptr<const IDBObjectStoreMetadata> store_metadata,
                  scoped_refptr<const IDBIndexMetadata> index_metadata)
       : script_state_(script_state),
         database_(database),
         transaction_id_(transaction_id),
         object_store_id_(object_store_id),
+        store_metadata_(store_metadata),
         index_metadata_(std::move(index_metadata)) {
     DCHECK(index_metadata_.get());
   }
@@ -703,6 +713,9 @@
   }
 
  private:
+  const IDBObjectStoreMetadata& ObjectStoreMetadata() const {
+    return *store_metadata_;
+  }
   const IDBIndexMetadata& IndexMetadata() const { return *index_metadata_; }
 
   void Invoke(ExecutionContext* execution_context, Event* event) override {
@@ -737,6 +750,7 @@
       index_keys.emplace_back(IDBIndexKeys{
           .id = IndexMetadata().id,
           .keys = GenerateIndexKeysForValue(script_state_->GetIsolate(),
+                                            ObjectStoreMetadata(),
                                             IndexMetadata(), value)});
 
       database_->Backend()->SetIndexKeys(transaction_id_, object_store_id_,
@@ -757,6 +771,7 @@
   Member<IDBDatabase> database_;
   const int64_t transaction_id_;
   const int64_t object_store_id_;
+  scoped_refptr<const IDBObjectStoreMetadata> store_metadata_;
   scoped_refptr<const IDBIndexMetadata> index_metadata_;
 };
 }  // namespace
@@ -838,7 +853,7 @@
   // This is kept alive by being the success handler of the request, which is in
   // turn kept alive by the owning transaction.
   auto* index_populator = MakeGarbageCollected<IndexPopulator>(
-      script_state, transaction()->db(), transaction_->Id(), Id(),
+      script_state, transaction()->db(), transaction_->Id(), Id(), metadata_,
       std::move(index_metadata));
   index_request->setOnsuccess(index_populator);
   return index;
diff --git a/third_party/blink/renderer/modules/sms/sms_receiver.cc b/third_party/blink/renderer/modules/sms/sms_receiver.cc
index 6213e46..45df98b2 100644
--- a/third_party/blink/renderer/modules/sms/sms_receiver.cc
+++ b/third_party/blink/renderer/modules/sms/sms_receiver.cc
@@ -65,8 +65,8 @@
 
   if (!service_) {
     GetExecutionContext()->GetInterfaceProvider()->GetInterface(
-        mojo::MakeRequest(&service_, task_runner));
-    service_.set_connection_error_handler(WTF::Bind(
+        service_.BindNewPipeAndPassReceiver(task_runner));
+    service_.set_disconnect_handler(WTF::Bind(
         &SMSReceiver::OnSMSReceiverConnectionError, WrapWeakPersistent(this)));
   }
 
diff --git a/third_party/blink/renderer/modules/sms/sms_receiver.h b/third_party/blink/renderer/modules/sms/sms_receiver.h
index 1c5f382..4d2fce0 100644
--- a/third_party/blink/renderer/modules/sms/sms_receiver.h
+++ b/third_party/blink/renderer/modules/sms/sms_receiver.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_SMS_SMS_RECEIVER_H_
 
 #include "base/macros.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "third_party/blink/public/mojom/sms/sms_receiver.mojom-blink.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
 #include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h"
@@ -41,7 +42,7 @@
 
   void OnSMSReceiverConnectionError();
 
-  mojom::blink::SmsReceiverPtr service_;
+  mojo::Remote<mojom::blink::SmsReceiver> service_;
 
   DISALLOW_COPY_AND_ASSIGN(SMSReceiver);
 };
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn
index 354e6c7..c115189c 100644
--- a/third_party/blink/renderer/platform/BUILD.gn
+++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -1240,6 +1240,7 @@
     "peerconnection/rtc_stats_response_base.h",
     "peerconnection/rtc_video_decoder_adapter.cc",
     "peerconnection/rtc_video_decoder_adapter.h",
+    "peerconnection/rtc_video_decoder_factory.cc",
     "peerconnection/rtc_video_encoder.cc",
     "peerconnection/rtc_video_encoder.h",
     "peerconnection/rtc_void_request.h",
diff --git a/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter.cc b/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter.cc
index 007fae4..b4d6e5d2 100644
--- a/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter.cc
+++ b/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter.cc
@@ -8,8 +8,6 @@
 #include <functional>
 #include <utility>
 
-#include "base/bind.h"
-#include "base/bind_helpers.h"
 #include "base/feature_list.h"
 #include "base/location.h"
 #include "base/logging.h"
@@ -28,10 +26,11 @@
 #include "media/base/video_types.h"
 #include "media/video/gpu_video_accelerator_factories.h"
 #include "media/video/video_decode_accelerator.h"
-#include "third_party/blink/public/platform/modules/peerconnection/web_rtc_video_frame_adapter_factory.h"
 #include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
 #include "third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter.h"
 #include "third_party/blink/renderer/platform/webrtc/webrtc_video_utils.h"
+#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
 #include "third_party/webrtc/api/video/video_frame.h"
 #include "third_party/webrtc/media/base/vp9_profile.h"
 #include "third_party/webrtc/modules/video_coding/codecs/h264/include/h264.h"
@@ -40,6 +39,16 @@
 #include "third_party/webrtc/rtc_base/ref_counted_object.h"
 #include "ui/gfx/color_space.h"
 
+namespace WTF {
+
+template <>
+struct CrossThreadCopier<media::VideoDecoderConfig>
+    : public CrossThreadCopierPassThrough<media::VideoDecoderConfig> {
+  STATIC_ONLY(CrossThreadCopier);
+};
+
+}  // namespace WTF
+
 namespace blink {
 
 namespace {
@@ -122,12 +131,6 @@
 
 }  // namespace
 
-std::unique_ptr<webrtc::VideoDecoder> CreateRTCVideoDecoderAdapter(
-    media::GpuVideoAcceleratorFactories* gpu_factories,
-    const webrtc::SdpVideoFormat& format) {
-  return RTCVideoDecoderAdapter::Create(gpu_factories, format);
-}
-
 // static
 std::unique_ptr<RTCVideoDecoderAdapter> RTCVideoDecoderAdapter::Create(
     media::GpuVideoAcceleratorFactories* gpu_factories,
@@ -196,12 +199,14 @@
   bool result = false;
   base::WaitableEvent waiter(base::WaitableEvent::ResetPolicy::MANUAL,
                              base::WaitableEvent::InitialState::NOT_SIGNALED);
-  media::VideoDecoder::InitCB init_cb =
-      base::BindOnce(&FinishWait, &waiter, &result);
-  if (media_task_runner_->PostTask(
-          FROM_HERE,
-          base::BindOnce(&RTCVideoDecoderAdapter::InitializeOnMediaThread,
-                         base::Unretained(this), config, std::move(init_cb)))) {
+  auto init_cb =
+      CrossThreadBindOnce(&FinishWait, CrossThreadUnretained(&waiter),
+                          CrossThreadUnretained(&result));
+  if (PostCrossThreadTask(
+          *media_task_runner_.get(), FROM_HERE,
+          CrossThreadBindOnce(&RTCVideoDecoderAdapter::InitializeOnMediaThread,
+                              CrossThreadUnretained(this), config,
+                              std::move(init_cb)))) {
     waiter.Wait();
   }
   return result;
@@ -315,9 +320,10 @@
     }
     pending_buffers_.push_back(std::move(buffer));
   }
-  media_task_runner_->PostTask(
-      FROM_HERE,
-      base::BindOnce(&RTCVideoDecoderAdapter::DecodeOnMediaThread, weak_this_));
+  PostCrossThreadTask(
+      *media_task_runner_.get(), FROM_HERE,
+      CrossThreadBindOnce(&RTCVideoDecoderAdapter::DecodeOnMediaThread,
+                          weak_this_));
 
   return WEBRTC_VIDEO_CODEC_OK;
 }
@@ -350,7 +356,7 @@
 
 void RTCVideoDecoderAdapter::InitializeOnMediaThread(
     const media::VideoDecoderConfig& config,
-    media::VideoDecoder::InitCB init_cb) {
+    InitCB init_cb) {
   DVLOG(3) << __func__;
   DCHECK(media_task_runner_->BelongsToCurrentThread());
 
@@ -362,11 +368,11 @@
 
     video_decoder_ = gpu_factories_->CreateVideoDecoder(
         media_log_.get(), kImplementation,
-        base::BindRepeating(&OnRequestOverlayInfo));
+        WTF::BindRepeating(&OnRequestOverlayInfo));
 
     if (!video_decoder_) {
-      media_task_runner_->PostTask(FROM_HERE,
-                                   base::BindOnce(std::move(init_cb), false));
+      PostCrossThreadTask(*media_task_runner_.get(), FROM_HERE,
+                          CrossThreadBindOnce(std::move(init_cb), false));
       return;
     }
   }
@@ -377,10 +383,10 @@
   // Encryption is not supported.
   media::CdmContext* cdm_context = nullptr;
 
-  media::VideoDecoder::OutputCB output_cb =
-      base::BindRepeating(&RTCVideoDecoderAdapter::OnOutput, weak_this_);
-
-  video_decoder_->Initialize(config, low_delay, cdm_context, std::move(init_cb),
+  media::VideoDecoder::OutputCB output_cb = ConvertToBaseCallback(
+      CrossThreadBindRepeating(&RTCVideoDecoderAdapter::OnOutput, weak_this_));
+  video_decoder_->Initialize(config, low_delay, cdm_context,
+                             ConvertToBaseOnceCallback(std::move(init_cb)),
                              output_cb, base::DoNothing());
 }
 
@@ -410,7 +416,7 @@
     outstanding_decode_requests_++;
     video_decoder_->Decode(
         std::move(buffer),
-        base::BindRepeating(&RTCVideoDecoderAdapter::OnDecodeDone, weak_this_));
+        WTF::BindRepeating(&RTCVideoDecoderAdapter::OnDecodeDone, weak_this_));
   }
 }
 
@@ -489,17 +495,20 @@
   bool result = false;
   base::WaitableEvent waiter(base::WaitableEvent::ResetPolicy::MANUAL,
                              base::WaitableEvent::InitialState::NOT_SIGNALED);
-  media::VideoDecoder::InitCB init_cb =
-      base::BindRepeating(&FinishWait, &waiter, &result);
+  auto init_cb =
+      CrossThreadBindOnce(&FinishWait, CrossThreadUnretained(&waiter),
+                          CrossThreadUnretained(&result));
   FlushDoneCB flush_success_cb =
-      base::BindOnce(&RTCVideoDecoderAdapter::InitializeOnMediaThread,
-                     weak_this_, config, std::move(init_cb));
+      CrossThreadBindOnce(&RTCVideoDecoderAdapter::InitializeOnMediaThread,
+                          weak_this_, config, std::move(init_cb));
   FlushDoneCB flush_fail_cb =
-      base::BindOnce(&FinishWait, &waiter, &result, false);
-  if (media_task_runner_->PostTask(
-          FROM_HERE, base::BindOnce(&RTCVideoDecoderAdapter::FlushOnMediaThread,
-                                    weak_this_, std::move(flush_success_cb),
-                                    std::move(flush_fail_cb)))) {
+      CrossThreadBindOnce(&FinishWait, CrossThreadUnretained(&waiter),
+                          CrossThreadUnretained(&result), false);
+  if (PostCrossThreadTask(
+          *media_task_runner_.get(), FROM_HERE,
+          CrossThreadBindOnce(&RTCVideoDecoderAdapter::FlushOnMediaThread,
+                              weak_this_, std::move(flush_success_cb),
+                              std::move(flush_fail_cb)))) {
     waiter.Wait();
   }
   return result;
@@ -518,7 +527,7 @@
   // Send EOS frame for flush.
   video_decoder_->Decode(
       media::DecoderBuffer::CreateEOSBuffer(),
-      base::BindRepeating(
+      WTF::BindRepeating(
           [](FlushDoneCB flush_success, FlushDoneCB flush_fail,
              media::DecodeStatus status) {
             if (status == media::DecodeStatus::OK)
diff --git a/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter.h b/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter.h
index 9fa41e5..89bb76c 100644
--- a/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter.h
+++ b/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter.h
@@ -19,6 +19,7 @@
 #include "media/base/video_decoder_config.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
 #include "third_party/blink/renderer/platform/wtf/deque.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
 #include "third_party/webrtc/api/video_codecs/sdp_video_format.h"
 #include "third_party/webrtc/modules/video_coding/include/video_codec_interface.h"
 #include "ui/gfx/geometry/size.h"
@@ -80,7 +81,8 @@
   using CreateVideoDecoderCB =
       base::RepeatingCallback<std::unique_ptr<media::VideoDecoder>(
           media::MediaLog*)>;
-  using FlushDoneCB = base::OnceCallback<void()>;
+  using InitCB = CrossThreadOnceFunction<void(bool)>;
+  using FlushDoneCB = CrossThreadOnceFunction<void()>;
 
   // Called on the worker thread.
   RTCVideoDecoderAdapter(media::GpuVideoAcceleratorFactories* gpu_factories,
@@ -89,7 +91,7 @@
 
   bool InitializeSync(const media::VideoDecoderConfig& config);
   void InitializeOnMediaThread(const media::VideoDecoderConfig& config,
-                               media::VideoDecoder::InitCB init_cb);
+                               InitCB init_cb);
   void DecodeOnMediaThread();
   void OnDecodeDone(media::DecodeStatus status);
   void OnOutput(scoped_refptr<media::VideoFrame> frame);
diff --git a/content/renderer/media/webrtc/rtc_video_decoder_factory.cc b/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_factory.cc
similarity index 92%
rename from content/renderer/media/webrtc/rtc_video_decoder_factory.cc
rename to third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_factory.cc
index 2da5bab..9c7aedc 100644
--- a/content/renderer/media/webrtc/rtc_video_decoder_factory.cc
+++ b/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_factory.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/renderer/media/webrtc/rtc_video_decoder_factory.h"
+#include "third_party/blink/public/platform/modules/peerconnection/rtc_video_decoder_factory.h"
 
 #include <memory>
 
@@ -10,9 +10,9 @@
 #include "base/memory/ptr_util.h"
 #include "build/build_config.h"
 #include "media/video/gpu_video_accelerator_factories.h"
-#include "third_party/blink/public/platform/modules/peerconnection/web_rtc_video_frame_adapter_factory.h"
+#include "third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter.h"
 
-namespace content {
+namespace blink {
 namespace {
 
 // This extra indirection is needed so that we can delete the decoder on the
@@ -79,7 +79,7 @@
     const webrtc::SdpVideoFormat& format) {
   DVLOG(2) << __func__;
   std::unique_ptr<webrtc::VideoDecoder> decoder =
-      blink::CreateRTCVideoDecoderAdapter(gpu_factories_, format);
+      RTCVideoDecoderAdapter::Create(gpu_factories_, format);
   // ScopedVideoDecoder uses the task runner to make sure the decoder is
   // destructed on the correct thread.
   return decoder ? std::make_unique<ScopedVideoDecoder>(
@@ -87,4 +87,4 @@
                  : nullptr;
 }
 
-}  // namespace content
+}  // namespace blink
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc
index e51f0705..6be0831 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc
@@ -412,9 +412,9 @@
     case TaskType::kInternalLoading:
     case TaskType::kNetworking:
     case TaskType::kNetworkingWithURLLoaderAnnotation:
+      return LoadingTaskQueueTraits();
     case TaskType::kNetworkingControl:
-      // Loading task queues are handled separately.
-      return base::nullopt;
+      return LoadingControlTaskQueueTraits();
     // Throttling following tasks may break existing web pages, so tentatively
     // these are unthrottled.
     // TODO(nhiroki): Throttle them again after we're convinced that it's safe
@@ -480,8 +480,9 @@
       return UnpausableTaskQueueTraits();
     case TaskType::kInternalTranslation:
       return ForegroundOnlyTaskQueueTraits();
-    // The TaskType of Inspector tasks need to be unpausable and should not use virtual time
-    // because they need to run on a paused page or when virtual time is paused.
+    // The TaskType of Inspector tasks need to be unpausable and should not use
+    // virtual time because they need to run on a paused page or when virtual
+    // time is paused.
     case TaskType::kInternalInspector:
     // Navigation IPCs do not run using virtual time to avoid hanging.
     case TaskType::kInternalNavigationAssociated:
@@ -525,27 +526,17 @@
 
 scoped_refptr<MainThreadTaskQueue> FrameSchedulerImpl::GetTaskQueue(
     TaskType type) {
-  switch (type) {
-    case TaskType::kInternalLoading:
-    case TaskType::kNetworking:
-    case TaskType::kNetworkingWithURLLoaderAnnotation:
-      return frame_task_queue_controller_->LoadingTaskQueue();
-    case TaskType::kNetworkingControl:
-      return frame_task_queue_controller_->LoadingControlTaskQueue();
-    default:
-      // Non-loading task queue.
-      DCHECK_LT(static_cast<size_t>(type),
-                main_thread_scheduler_->scheduling_settings()
-                    .frame_task_types_to_queue_traits.size());
-      base::Optional<QueueTraits> queue_traits =
-          main_thread_scheduler_->scheduling_settings()
-              .frame_task_types_to_queue_traits[static_cast<size_t>(type)];
-      // We don't have a QueueTraits mapping for |task_type| if it is not a
-      // frame-level task type.
-      DCHECK(queue_traits);
-      return frame_task_queue_controller_->NonLoadingTaskQueue(
-          queue_traits.value());
-  }
+  DCHECK_LT(static_cast<size_t>(type),
+            main_thread_scheduler_->scheduling_settings()
+                .frame_task_types_to_queue_traits.size());
+  base::Optional<QueueTraits> queue_traits =
+      main_thread_scheduler_->scheduling_settings()
+          .frame_task_types_to_queue_traits[static_cast<size_t>(type)];
+  // We don't have a QueueTraits mapping for |task_type| if it is not a
+  // frame-level task type.
+  DCHECK(queue_traits);
+  return frame_task_queue_controller_->GetTaskQueue(
+      queue_traits.value());
 }
 
 std::unique_ptr<WebResourceLoadingTaskRunnerHandle>
@@ -567,8 +558,8 @@
     return ResourceLoadingTaskRunnerHandleImpl::WrapTaskRunner(task_queue);
   }
 
-  return ResourceLoadingTaskRunnerHandleImpl::WrapTaskRunner(
-      frame_task_queue_controller_->LoadingTaskQueue());
+  return ResourceLoadingTaskRunnerHandleImpl::WrapTaskRunner(GetTaskQueue
+      (TaskType::kNetworkingWithURLLoaderAnnotation));
 }
 
 void FrameSchedulerImpl::DidChangeResourceLoadingPriority(
@@ -1034,21 +1025,20 @@
     }
   }
 
-  if (task_queue->queue_class() == MainThreadTaskQueue::QueueClass::kLoading) {
-    if (task_queue->queue_type() ==
-        MainThreadTaskQueue::QueueType::kFrameLoadingControl) {
-      return main_thread_scheduler_
-                     ->should_prioritize_loading_with_compositing()
-                 ? TaskQueue::QueuePriority::kVeryHighPriority
-                 : TaskQueue::QueuePriority::kHighPriority;
-    }
-
-    if (main_thread_scheduler_->should_prioritize_loading_with_compositing())
-      return main_thread_scheduler_->compositor_priority();
+  if (task_queue->GetPrioritisationType() ==
+      MainThreadTaskQueue::QueueTraits::PrioritisationType::kLoadingControl) {
+    return main_thread_scheduler_
+                   ->should_prioritize_loading_with_compositing()
+               ? TaskQueue::QueuePriority::kVeryHighPriority
+               : TaskQueue::QueuePriority::kHighPriority;
   }
 
-  DCHECK_NE(task_queue->queue_type(),
-            MainThreadTaskQueue::QueueType::kFrameLoadingControl);
+  if (task_queue->GetPrioritisationType() ==
+      MainThreadTaskQueue::QueueTraits::PrioritisationType::kLoading &&
+      main_thread_scheduler_->should_prioritize_loading_with_compositing()) {
+    return main_thread_scheduler_->compositor_priority();
+  }
+
   return TaskQueue::QueuePriority::kNormalPriority;
 }
 
@@ -1211,5 +1201,25 @@
   // TODO(keishi): Stop all task queues
 }
 
+MainThreadTaskQueue::QueueTraits
+FrameSchedulerImpl::LoadingTaskQueueTraits() {
+  return QueueTraits()
+      .SetCanBePaused(true)
+      .SetCanBeFrozen(true)
+      .SetCanBeDeferred(true)
+      .SetPrioritisationType(
+          QueueTraits::PrioritisationType::kLoading);
+}
+
+MainThreadTaskQueue::QueueTraits
+FrameSchedulerImpl::LoadingControlTaskQueueTraits() {
+  return QueueTraits()
+      .SetCanBePaused(true)
+      .SetCanBeFrozen(true)
+      .SetCanBeDeferred(true)
+      .SetPrioritisationType(
+          QueueTraits::PrioritisationType::kLoadingControl);
+}
+
 }  // namespace scheduler
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h
index d2fd2b5e..6d27ae3 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h
@@ -289,6 +289,8 @@
   static MainThreadTaskQueue::QueueTraits ForegroundOnlyTaskQueueTraits();
   static MainThreadTaskQueue::QueueTraits
   DoesNotUseVirtualTimeTaskQueueTraits();
+  static MainThreadTaskQueue::QueueTraits LoadingTaskQueueTraits();
+  static MainThreadTaskQueue::QueueTraits LoadingControlTaskQueueTraits();
 
   const FrameScheduler::FrameType frame_type_;
 
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc
index c3454b4..1ffe34a 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc
@@ -152,41 +152,41 @@
     EXPECT_TRUE(throttleable_task_queue());
   }
 
-  scoped_refptr<MainThreadTaskQueue> NonLoadingTaskQueue(
+  scoped_refptr<MainThreadTaskQueue> GetTaskQueue(
       MainThreadTaskQueue::QueueTraits queue_traits) {
     return frame_scheduler_->FrameTaskQueueControllerForTest()
-        ->NonLoadingTaskQueue(queue_traits);
+        ->GetTaskQueue(queue_traits);
   }
 
   scoped_refptr<TaskQueue> ThrottleableTaskQueue() {
-    return NonLoadingTaskQueue(
+    return GetTaskQueue(
         FrameSchedulerImpl::ThrottleableTaskQueueTraits());
   }
 
   scoped_refptr<TaskQueue> LoadingTaskQueue() {
-    return frame_scheduler_->FrameTaskQueueControllerForTest()
-        ->LoadingTaskQueue();
+    return GetTaskQueue(
+        FrameSchedulerImpl::LoadingTaskQueueTraits());
   }
 
   scoped_refptr<TaskQueue> LoadingControlTaskQueue() {
-    return frame_scheduler_->FrameTaskQueueControllerForTest()
-        ->LoadingControlTaskQueue();
+    return GetTaskQueue(
+        FrameSchedulerImpl::LoadingControlTaskQueueTraits());
   }
 
   scoped_refptr<TaskQueue> DeferrableTaskQueue() {
-    return NonLoadingTaskQueue(FrameSchedulerImpl::DeferrableTaskQueueTraits());
+    return GetTaskQueue(FrameSchedulerImpl::DeferrableTaskQueueTraits());
   }
 
   scoped_refptr<TaskQueue> PausableTaskQueue() {
-    return NonLoadingTaskQueue(FrameSchedulerImpl::PausableTaskQueueTraits());
+    return GetTaskQueue(FrameSchedulerImpl::PausableTaskQueueTraits());
   }
 
   scoped_refptr<TaskQueue> UnpausableTaskQueue() {
-    return NonLoadingTaskQueue(FrameSchedulerImpl::UnpausableTaskQueueTraits());
+    return GetTaskQueue(FrameSchedulerImpl::UnpausableTaskQueueTraits());
   }
 
   scoped_refptr<TaskQueue> ForegroundOnlyTaskQueue() {
-    return NonLoadingTaskQueue(
+    return GetTaskQueue(
         FrameSchedulerImpl::ForegroundOnlyTaskQueueTraits());
   }
 
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.cc b/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.cc
index a9109caf..15b978b 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.cc
@@ -39,28 +39,12 @@
 FrameTaskQueueController::~FrameTaskQueueController() = default;
 
 scoped_refptr<MainThreadTaskQueue>
-FrameTaskQueueController::LoadingTaskQueue() {
-  if (!loading_task_queue_)
-    CreateLoadingTaskQueue();
-  DCHECK(loading_task_queue_);
-  return loading_task_queue_;
-}
-
-scoped_refptr<MainThreadTaskQueue>
-FrameTaskQueueController::LoadingControlTaskQueue() {
-  if (!loading_control_task_queue_)
-    CreateLoadingControlTaskQueue();
-  DCHECK(loading_control_task_queue_);
-  return loading_control_task_queue_;
-}
-
-scoped_refptr<MainThreadTaskQueue>
-FrameTaskQueueController::NonLoadingTaskQueue(
+FrameTaskQueueController::GetTaskQueue(
     MainThreadTaskQueue::QueueTraits queue_traits) {
-  if (!non_loading_task_queues_.Contains(queue_traits.Key()))
-    CreateNonLoadingTaskQueue(queue_traits);
-  auto it = non_loading_task_queues_.find(queue_traits.Key());
-  DCHECK(it != non_loading_task_queues_.end());
+  if (!task_queues_.Contains(queue_traits.Key()))
+    CreateTaskQueue(queue_traits);
+  auto it = task_queues_.find(queue_traits.Key());
+  DCHECK(it != task_queues_.end());
   return it->value;
 }
 
@@ -69,28 +53,6 @@
   return all_task_queues_and_voters_;
 }
 
-void FrameTaskQueueController::CreateLoadingTaskQueue() {
-  DCHECK(!loading_task_queue_);
-  // |main_thread_scheduler_impl_| can be null in unit tests.
-  DCHECK(main_thread_scheduler_impl_);
-
-  loading_task_queue_ = main_thread_scheduler_impl_->NewLoadingTaskQueue(
-      MainThreadTaskQueue::QueueType::kFrameLoading, frame_scheduler_impl_);
-  TaskQueueCreated(loading_task_queue_);
-}
-
-void FrameTaskQueueController::CreateLoadingControlTaskQueue() {
-  DCHECK(!loading_control_task_queue_);
-  // |main_thread_scheduler_impl_| can be null in unit tests.
-  DCHECK(main_thread_scheduler_impl_);
-
-  loading_control_task_queue_ =
-      main_thread_scheduler_impl_->NewLoadingTaskQueue(
-          MainThreadTaskQueue::QueueType::kFrameLoadingControl,
-          frame_scheduler_impl_);
-  TaskQueueCreated(loading_control_task_queue_);
-}
-
 scoped_refptr<MainThreadTaskQueue>
 FrameTaskQueueController::NewResourceLoadingTaskQueue() {
   scoped_refptr<MainThreadTaskQueue> task_queue =
@@ -119,9 +81,9 @@
   return task_queue;
 }
 
-void FrameTaskQueueController::CreateNonLoadingTaskQueue(
+void FrameTaskQueueController::CreateTaskQueue(
     QueueTraits queue_traits) {
-  DCHECK(!non_loading_task_queues_.Contains(queue_traits.Key()));
+  DCHECK(!task_queues_.Contains(queue_traits.Key()));
   // |main_thread_scheduler_impl_| can be null in unit tests.
   DCHECK(main_thread_scheduler_impl_);
 
@@ -160,7 +122,7 @@
   scoped_refptr<MainThreadTaskQueue> task_queue =
       main_thread_scheduler_impl_->NewTaskQueue(queue_creation_params);
   TaskQueueCreated(task_queue);
-  non_loading_task_queues_.insert(queue_traits.Key(), task_queue);
+  task_queues_.insert(queue_traits.Key(), task_queue);
 }
 
 void FrameTaskQueueController::TaskQueueCreated(
@@ -218,16 +180,8 @@
 
 void FrameTaskQueueController::AsValueInto(
     base::trace_event::TracedValue* state) const {
-  if (loading_task_queue_) {
-    state->SetString("loading_task_queue",
-                     PointerToString(loading_task_queue_.get()));
-  }
-  if (loading_control_task_queue_) {
-    state->SetString("loading_control_task_queue",
-                     PointerToString(loading_control_task_queue_.get()));
-  }
-  state->BeginArray("non_loading_task_queues");
-  for (const auto it : non_loading_task_queues_) {
+  state->BeginArray("task_queues");
+  for (const auto it : task_queues_) {
     state->AppendString(PointerToString(it.value.get()));
   }
   state->EndArray();
@@ -242,6 +196,14 @@
 // static
 MainThreadTaskQueue::QueueType
 FrameTaskQueueController::QueueTypeFromQueueTraits(QueueTraits queue_traits) {
+  // Order matters here, the priority decisions need to be at the top since
+  // loading/loading control TQs set some of these other bits.
+  if (queue_traits.prioritisation_type ==
+      QueueTraits::PrioritisationType::kLoading)
+    return MainThreadTaskQueue::QueueType::kFrameLoading;
+  if (queue_traits.prioritisation_type ==
+      QueueTraits::PrioritisationType::kLoadingControl)
+    return MainThreadTaskQueue::QueueType::kFrameLoadingControl;
   if (queue_traits.can_be_throttled)
     return MainThreadTaskQueue::QueueType::kFrameThrottleable;
   if (queue_traits.can_be_deferred)
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.h b/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.h
index 96b503d4..956a65b 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.h
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.h
@@ -37,7 +37,7 @@
 
 // FrameTaskQueueController creates and manages and FrameSchedulerImpl's task
 // queues. It is in charge of maintaining mappings between QueueTraits and
-// MainThreadTaskQueues for non-loading queues, for accessing task queues and
+// MainThreadTaskQueues for queues, for accessing task queues and
 // their related voters, and for creating new task queues.
 class PLATFORM_EXPORT FrameTaskQueueController {
   USING_FAST_MALLOC(FrameTaskQueueController);
@@ -67,15 +67,9 @@
                            Delegate*);
   ~FrameTaskQueueController();
 
-  // Return the loading task queue and create it if it doesn't exist.
-  scoped_refptr<MainThreadTaskQueue> LoadingTaskQueue();
-
-  // Return the loading control task queue and create it if it doesn't exist.
-  scoped_refptr<MainThreadTaskQueue> LoadingControlTaskQueue();
-
-  // Return the non-loading task queue associated with the given queue traits,
-  // and created it if it doesn't exist.
-  scoped_refptr<MainThreadTaskQueue> NonLoadingTaskQueue(
+  // Return the task queue associated with the given queue traits,
+  // and create if it doesn't exist.
+  scoped_refptr<MainThreadTaskQueue> GetTaskQueue(
       MainThreadTaskQueue::QueueTraits);
 
   scoped_refptr<MainThreadTaskQueue> NewResourceLoadingTaskQueue();
@@ -106,11 +100,7 @@
  private:
   friend class FrameTaskQueueControllerTest;
 
-  void CreateLoadingTaskQueue();
-
-  void CreateLoadingControlTaskQueue();
-
-  void CreateNonLoadingTaskQueue(MainThreadTaskQueue::QueueTraits);
+  void CreateTaskQueue(MainThreadTaskQueue::QueueTraits);
 
   void TaskQueueCreated(const scoped_refptr<MainThreadTaskQueue>&);
 
@@ -124,20 +114,12 @@
   FrameSchedulerImpl* const frame_scheduler_impl_;
   Delegate* const delegate_;
 
-  // Keep track of loading queues separately. We keep these separate because
-  // loading and loading control task queues share the same queue traits, and
-  // those queue traits can be the same as non-loading queues. This prevents us
-  // from being able to the find right task queue by queue traits alone.
-  scoped_refptr<MainThreadTaskQueue> loading_task_queue_;
-
-  scoped_refptr<MainThreadTaskQueue> loading_control_task_queue_;
-
-  using NonLoadingTaskQueueMap =
+  using TaskQueueMap =
       WTF::HashMap<MainThreadTaskQueue::QueueTraitsKeyType,
                    scoped_refptr<MainThreadTaskQueue>>;
 
-  // Map of all non-loading TaskQueues, indexed by QueueTraits.
-  NonLoadingTaskQueueMap non_loading_task_queues_;
+  // Map of all TaskQueues, indexed by QueueTraits.
+  TaskQueueMap task_queues_;
 
   // Set of all resource loading task queues.
   WTF::HashSet<scoped_refptr<MainThreadTaskQueue>>
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller_unittest.cc b/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller_unittest.cc
index 6b8e7e5..67dbe5b 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller_unittest.cc
@@ -72,16 +72,35 @@
 
  protected:
   scoped_refptr<MainThreadTaskQueue> LoadingTaskQueue() const {
-    return frame_task_queue_controller_->LoadingTaskQueue();
+    return frame_task_queue_controller_->GetTaskQueue(QueueTraits()
+        .SetCanBePaused(true)
+        .SetCanBeFrozen(true)
+        .SetCanBeDeferred(true)
+        .SetPrioritisationType(
+            QueueTraits::PrioritisationType::kLoading));
   }
 
   scoped_refptr<MainThreadTaskQueue> LoadingControlTaskQueue() const {
-    return frame_task_queue_controller_->LoadingControlTaskQueue();
+    return frame_task_queue_controller_->GetTaskQueue(QueueTraits()
+        .SetCanBePaused(true)
+        .SetCanBeFrozen(true)
+        .SetCanBeDeferred(true)
+        .SetPrioritisationType(
+            QueueTraits::PrioritisationType::kLoadingControl));
   }
 
-  scoped_refptr<MainThreadTaskQueue> NonLoadingTaskQueue(
+  scoped_refptr<MainThreadTaskQueue> ThrottleableTaskQueue() const {
+    return frame_task_queue_controller_->GetTaskQueue(QueueTraits()
+      .SetCanBeThrottled(true)
+      .SetCanBeFrozen(true)
+      .SetCanBeDeferred(true)
+      .SetCanBePaused(true)
+      .SetShouldUseVirtualTime(true));
+  }
+
+  scoped_refptr<MainThreadTaskQueue> GetTaskQueue(
       QueueTraits queue_traits) const {
-    return frame_task_queue_controller_->NonLoadingTaskQueue(queue_traits);
+    return frame_task_queue_controller_->GetTaskQueue(queue_traits);
   }
 
   scoped_refptr<MainThreadTaskQueue> NewResourceLoadingTaskQueue() const {
@@ -119,8 +138,8 @@
   all_task_queues.insert(task_queue.get(), QueueCheckResult::kDidNotSeeQueue);
   EXPECT_EQ(all_task_queues.size(), task_queue_created_count());
 
-  // Create the 4 default non-loading task queues used by FrameSchedulerImpl.
-  task_queue = NonLoadingTaskQueue(QueueTraits()
+  // Create the 4 default task queues used by FrameSchedulerImpl.
+  task_queue = GetTaskQueue(QueueTraits()
                                        .SetCanBeThrottled(true)
                                        .SetCanBeDeferred(true)
                                        .SetCanBeFrozen(true)
@@ -130,7 +149,7 @@
   all_task_queues.insert(task_queue.get(), QueueCheckResult::kDidNotSeeQueue);
   EXPECT_EQ(all_task_queues.size(), task_queue_created_count());
 
-  task_queue = NonLoadingTaskQueue(QueueTraits()
+  task_queue = GetTaskQueue(QueueTraits()
                                         .SetCanBeDeferred(true)
                                         .SetCanBePaused(true)
                                         .SetShouldUseVirtualTime(true));
@@ -138,14 +157,14 @@
   all_task_queues.insert(task_queue.get(), QueueCheckResult::kDidNotSeeQueue);
   EXPECT_EQ(all_task_queues.size(), task_queue_created_count());
 
-  task_queue = NonLoadingTaskQueue(QueueTraits()
+  task_queue = GetTaskQueue(QueueTraits()
                                         .SetCanBePaused(true)
                                         .SetShouldUseVirtualTime(true));
   EXPECT_FALSE(all_task_queues.Contains(task_queue));
   all_task_queues.insert(task_queue.get(), QueueCheckResult::kDidNotSeeQueue);
   EXPECT_EQ(all_task_queues.size(), task_queue_created_count());
 
-  task_queue = NonLoadingTaskQueue(QueueTraits()
+  task_queue = GetTaskQueue(QueueTraits()
                                         .SetShouldUseVirtualTime(true));
   EXPECT_FALSE(all_task_queues.Contains(task_queue));
   all_task_queues.insert(task_queue.get(), QueueCheckResult::kDidNotSeeQueue);
@@ -242,7 +261,7 @@
 TEST_F(FrameTaskQueueControllerTest,
        NonWebSchedulingTaskQueueWebSchedulingPriorityNullopt) {
   scoped_refptr<MainThreadTaskQueue> task_queue =
-      frame_task_queue_controller_->NonLoadingTaskQueue(
+      frame_task_queue_controller_->GetTaskQueue(
           MainThreadTaskQueue::QueueTraits());
   EXPECT_EQ(base::nullopt, task_queue->web_scheduling_priority());
 }
@@ -306,6 +325,20 @@
   EXPECT_NE(task_queue1.get(), task_queue2.get());
 }
 
+TEST_F(FrameTaskQueueControllerTest, QueueTypeFromQueueTraits) {
+  scoped_refptr<MainThreadTaskQueue> task_queue = LoadingTaskQueue();
+  EXPECT_EQ(task_queue->queue_type(),
+            MainThreadTaskQueue::QueueType::kFrameLoading);
+
+  task_queue = LoadingControlTaskQueue();
+  EXPECT_EQ(task_queue->queue_type(),
+            MainThreadTaskQueue::QueueType::kFrameLoadingControl);
+
+  task_queue = ThrottleableTaskQueue();
+  EXPECT_EQ(task_queue->queue_type(),
+            MainThreadTaskQueue::QueueType::kFrameThrottleable);
+}
+
 class TaskQueueCreationFromQueueTraitsTest :
     public FrameTaskQueueControllerTest,
     public testing::WithParamInterface<QueueTraits::PrioritisationType> {};
@@ -316,10 +349,12 @@
                             QueueTraits::PrioritisationType::kVeryHigh,
                             QueueTraits::PrioritisationType::kHigh,
                             QueueTraits::PrioritisationType::kBestEffort,
-                            QueueTraits::PrioritisationType::kRegular));
+                            QueueTraits::PrioritisationType::kRegular,
+                            QueueTraits::PrioritisationType::kLoading,
+                            QueueTraits::PrioritisationType::kLoadingControl));
 
 TEST_P(TaskQueueCreationFromQueueTraitsTest,
-        AddAndRetrieveAllNonLoadingTaskQueues) {
+        AddAndRetrieveAllTaskQueues) {
   // Create queues for all combination of queue traits for all combinations of
   // the 6 QueueTraits bits with different PrioritisationTypes.
   WTF::HashSet<scoped_refptr<MainThreadTaskQueue>> all_task_queues;
@@ -336,7 +371,7 @@
             .SetShouldUseVirtualTime(!!(i & 1 << 5))
             .SetPrioritisationType(prioritisation_type);
     scoped_refptr<MainThreadTaskQueue> task_queue =
-        frame_task_queue_controller_->NonLoadingTaskQueue(queue_traits);
+        frame_task_queue_controller_->GetTaskQueue(queue_traits);
     EXPECT_FALSE(all_task_queues.Contains(task_queue));
     all_task_queues.insert(task_queue);
     EXPECT_EQ(task_queue->GetQueueTraits(), queue_traits);
@@ -347,7 +382,7 @@
   EXPECT_EQ(all_task_queues.size(), kTotalUniqueQueueTraits);
   for (const auto& task_queue : all_task_queues) {
     scoped_refptr<MainThreadTaskQueue> returned_task_queue =
-        frame_task_queue_controller_->NonLoadingTaskQueue(
+        frame_task_queue_controller_->GetTaskQueue(
             task_queue->GetQueueTraits());
     EXPECT_EQ(task_queue->GetQueueTraits(),
               returned_task_queue->GetQueueTraits());
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
index f970e88..e7c837f 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
@@ -760,6 +760,7 @@
   return task_queue;
 }
 
+// TODO(sreejakshetty): Cleanup NewLoadingTaskQueue and NewTimerTaskQueue.
 scoped_refptr<MainThreadTaskQueue> MainThreadSchedulerImpl::NewLoadingTaskQueue(
     MainThreadTaskQueue::QueueType queue_type,
     FrameSchedulerImpl* frame_scheduler) {
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc
index cf509ad..1333b750 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc
@@ -389,22 +389,23 @@
 
     loading_control_task_runner_ =
         main_frame_scheduler_->FrameTaskQueueControllerForTest()
-            ->LoadingControlTaskQueue()
+            ->GetTaskQueue(
+             main_frame_scheduler_->LoadingControlTaskQueueTraits())
             ->task_runner();
     timer_task_runner_ = timer_task_queue()->task_runner();
   }
 
   TaskQueue* loading_task_queue() {
+    auto queue_traits = FrameSchedulerImpl::LoadingTaskQueueTraits();
     return main_frame_scheduler_->FrameTaskQueueControllerForTest()
-        ->LoadingTaskQueue()
-        .get();
+        ->GetTaskQueue(queue_traits).get();
   }
 
   TaskQueue* timer_task_queue() {
     auto* frame_task_queue_controller =
         main_frame_scheduler_->FrameTaskQueueControllerForTest();
     return frame_task_queue_controller
-        ->NonLoadingTaskQueue(
+        ->GetTaskQueue(
             main_frame_scheduler_->ThrottleableTaskQueueTraits())
         .get();
   }
@@ -827,7 +828,7 @@
     auto* frame_task_queue_controller =
         scheduler->FrameTaskQueueControllerForTest();
     auto queue_traits = FrameSchedulerImpl::ThrottleableTaskQueueTraits();
-    return frame_task_queue_controller->NonLoadingTaskQueue(queue_traits);
+    return frame_task_queue_controller->GetTaskQueue(queue_traits);
   }
 
   QueueingTimeEstimator* queueing_time_estimator() {
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h
index e98ee7aa..06c4cf1 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h
@@ -126,8 +126,10 @@
       kHigh = 1,
       kBestEffort = 2,
       kRegular = 3,
+      kLoading = 4,
+      kLoadingControl = 5,
 
-      kCount = 4
+      kCount = 6
     };
 
     // kPrioritisationTypeWidthBits is the number of bits required
@@ -136,7 +138,7 @@
     // We need to update it whenever there is a change in
     // PrioritisationType::kCount.
     // TODO(sreejakshetty) make the number of bits calculation automated.
-    static constexpr int kPrioritisationTypeWidthBits = 2;
+    static constexpr int kPrioritisationTypeWidthBits = 3;
     static_assert(static_cast<int>(PrioritisationType::kCount) <=
                     (1 << kPrioritisationTypeWidthBits),
                     "Wrong Instanstiation for kPrioritisationTypeWidthBits");
@@ -351,6 +353,9 @@
 
   QueueTraits GetQueueTraits() const { return queue_traits_; }
 
+  QueueTraits::PrioritisationType GetPrioritisationType() const {
+      return queue_traits_.prioritisation_type;}
+
   void OnTaskReady(const void* frame_scheduler,
                    const base::sequence_manager::Task& task,
                    base::sequence_manager::LazyNow* lazy_now);
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl_unittest.cc b/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl_unittest.cc
index b3827544..d9b8a64 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl_unittest.cc
@@ -114,7 +114,7 @@
     auto* frame_task_queue_controller =
         scheduler->FrameTaskQueueControllerForTest();
     auto queue_traits = FrameSchedulerImpl::ThrottleableTaskQueueTraits();
-    return frame_task_queue_controller->NonLoadingTaskQueue(queue_traits);
+    return frame_task_queue_controller->GetTaskQueue(queue_traits);
   }
 
   base::TimeDelta delay_for_background_tab_freezing() const {
@@ -139,32 +139,32 @@
     return LoadingTaskQueue()->CreateTaskRunner(TaskType::kInternalTest);
   }
 
-  scoped_refptr<MainThreadTaskQueue> NonLoadingTaskQueue(
+  scoped_refptr<MainThreadTaskQueue> GetTaskQueue(
       MainThreadTaskQueue::QueueTraits queue_traits) {
     return frame_scheduler_->FrameTaskQueueControllerForTest()
-        ->NonLoadingTaskQueue(queue_traits);
+        ->GetTaskQueue(queue_traits);
   }
 
   scoped_refptr<MainThreadTaskQueue> ThrottleableTaskQueue() {
-    return NonLoadingTaskQueue(
+    return GetTaskQueue(
         FrameSchedulerImpl::ThrottleableTaskQueueTraits());
   }
 
   scoped_refptr<MainThreadTaskQueue> LoadingTaskQueue() {
-    return frame_scheduler_->FrameTaskQueueControllerForTest()
-        ->LoadingTaskQueue();
+    return GetTaskQueue(
+        FrameSchedulerImpl::LoadingTaskQueueTraits());
   }
 
   scoped_refptr<MainThreadTaskQueue> DeferrableTaskQueue() {
-    return NonLoadingTaskQueue(FrameSchedulerImpl::DeferrableTaskQueueTraits());
+    return GetTaskQueue(FrameSchedulerImpl::DeferrableTaskQueueTraits());
   }
 
   scoped_refptr<MainThreadTaskQueue> PausableTaskQueue() {
-    return NonLoadingTaskQueue(FrameSchedulerImpl::PausableTaskQueueTraits());
+    return GetTaskQueue(FrameSchedulerImpl::PausableTaskQueueTraits());
   }
 
   scoped_refptr<MainThreadTaskQueue> UnpausableTaskQueue() {
-    return NonLoadingTaskQueue(FrameSchedulerImpl::UnpausableTaskQueueTraits());
+    return GetTaskQueue(FrameSchedulerImpl::UnpausableTaskQueueTraits());
   }
 
   bool ShouldFreezePage() { return page_scheduler_->ShouldFreezePage(); }
diff --git a/third_party/blink/renderer/platform/testing/url_test_helpers.cc b/third_party/blink/renderer/platform/testing/url_test_helpers.cc
index ff8c9dd..653acd53 100644
--- a/third_party/blink/renderer/platform/testing/url_test_helpers.cc
+++ b/third_party/blink/renderer/platform/testing/url_test_helpers.cc
@@ -102,5 +102,19 @@
   Platform::Current()->GetURLLoaderMockFactory()->UnregisterURL(url);
 }
 
+void UnregisterAllURLsAndClearMemoryCache() {
+  Platform::Current()
+      ->GetURLLoaderMockFactory()
+      ->UnregisterAllURLsAndClearMemoryCache();
+}
+
+void SetLoaderDelegate(WebURLLoaderTestDelegate* delegate) {
+  Platform::Current()->GetURLLoaderMockFactory()->SetLoaderDelegate(delegate);
+}
+
+void ServeAsynchronousRequests() {
+  Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
+}
+
 }  // namespace url_test_helpers
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/testing/url_test_helpers.h b/third_party/blink/renderer/platform/testing/url_test_helpers.h
index aaf7c51..2edd24f 100644
--- a/third_party/blink/renderer/platform/testing/url_test_helpers.h
+++ b/third_party/blink/renderer/platform/testing/url_test_helpers.h
@@ -33,6 +33,7 @@
 
 #include "third_party/blink/public/platform/web_string.h"
 #include "third_party/blink/public/platform/web_url.h"
+#include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
 #include "third_party/blink/public/platform/web_url_response.h"
 #include "third_party/blink/renderer/platform/weborigin/kurl.h"
 
@@ -85,6 +86,12 @@
 // Registers a mock URL that returns a 404 error.
 void RegisterMockedErrorURLLoad(const WebURL& full_url);
 
+void UnregisterAllURLsAndClearMemoryCache();
+
+void SetLoaderDelegate(WebURLLoaderTestDelegate* delegate);
+
+void ServeAsynchronousRequests();
+
 }  // namespace url_test_helpers
 }  // namespace blink
 
diff --git a/third_party/blink/web_tests/external/wpt/IndexedDB/idbobjectstore_createIndex15-autoincrement-expected.txt b/third_party/blink/web_tests/external/wpt/IndexedDB/idbobjectstore_createIndex15-autoincrement-expected.txt
deleted file mode 100644
index 0b36177..0000000
--- a/third_party/blink/web_tests/external/wpt/IndexedDB/idbobjectstore_createIndex15-autoincrement-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-This is a testharness.js-based test.
-PASS Explicit Primary Key
-FAIL Auto-Increment Primary Key assert_equals: Expected 100. expected (number) 100 but got (object) null
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/IndexedDB/idbobjectstore_createIndex15-autoincrement.htm b/third_party/blink/web_tests/external/wpt/IndexedDB/idbobjectstore_createIndex15-autoincrement.htm
index 87ea39c..98fb99db 100644
--- a/third_party/blink/web_tests/external/wpt/IndexedDB/idbobjectstore_createIndex15-autoincrement.htm
+++ b/third_party/blink/web_tests/external/wpt/IndexedDB/idbobjectstore_createIndex15-autoincrement.htm
@@ -49,4 +49,57 @@
     },
     "Auto-Increment Primary Key"
   );
+
+  indexeddb_test(
+    function(t, db, txn) {
+      // Auto-increment
+      var store = db.createObjectStore("Store3", {keyPath: "id", autoIncrement: true});
+      store.createIndex("CompoundKey", ["num", "id", "other"]);
+
+      var num = 100;
+
+      // Add data to Store3 - valid keys
+      // Objects will be stored in Store3 and keys will get added
+      // to the CompoundKeys index.
+      store.put({num: num++, other: 0});
+      store.put({num: num++, other: [0]});
+
+      // Add data - missing key
+      // Objects will be stored in Store3 but keys won't get added to
+      // the CompoundKeys index because the 'other' keypath doesn't
+      // resolve to a value.
+      store.put({num: num++});
+
+      // Add data to Store3 - invalid keys
+      // Objects will be stored in Store3 but keys won't get added to
+      // the CompoundKeys index because the 'other' property values
+      // aren't valid keys.
+      store.put({num: num++, other: null});
+      store.put({num: num++, other: {}});
+      store.put({num: num++, other: [null]});
+      store.put({num: num++, other: [{}]});
+    },
+    function(t, db) {
+      var store = db.transaction("Store3", "readwrite").objectStore("Store3");
+      const keys = [];
+      let count;
+      store.count().onsuccess = t.step_func(e => { count = e.target.result; });
+      store.index("CompoundKey").openCursor().onsuccess = t.step_func(function(e) {
+        const cursor = e.target.result;
+        if (cursor !== null) {
+          keys.push(cursor.key);
+          cursor.continue();
+          return;
+        }
+
+        // Done iteration, check results.
+        assert_equals(count, 7, 'Expected all 7 records to be stored.');
+        assert_equals(keys.length, 2, 'Expected exactly two index entries.');
+        assert_array_equals(keys[0], [100, 1, 0]);
+        assert_object_equals(keys[1], [101, 2, [0]]);
+        t.done();
+      });
+    },
+    "Auto-Increment Primary Key - invalid key values elsewhere"
+  );
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/import-maps/imported/parsing-schema.tentative-expected.txt b/third_party/blink/web_tests/external/wpt/import-maps/imported/parsing-schema.tentative-expected.txt
index 61cafd01..afb5a364 100644
--- a/third_party/blink/web_tests/external/wpt/import-maps/imported/parsing-schema.tentative-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/import-maps/imported/parsing-schema.tentative-expected.txt
@@ -1,7 +1,7 @@
 This is a testharness.js-based test.
-FAIL Invalid JSON assert_throws: function "() => parseFromString('{ imports: {} }', 'https://base.example/')" did not throw
-FAIL Mismatching the top-level schema / should throw for top-level non-objects assert_throws: function "() => parseFromString(input, baseURL)" did not throw
-FAIL Mismatching the top-level schema / should throw if imports is a non-object assert_throws: function "() => parseFromString(input, baseURL)" did not throw
+PASS Invalid JSON
+PASS Mismatching the top-level schema / should throw for top-level non-objects
+PASS Mismatching the top-level schema / should throw if imports is a non-object
 FAIL Mismatching the top-level schema / should throw if scopes is a non-object assert_throws: function "() => parseFromString(input, baseURL)" did not throw
 FAIL Mismatching the top-level schema / should ignore unspecified top-level entries assert_object_equals: expected property "0" missing
 PASS Mismatching the specifier map schema / should ignore entries where the address is not a string, array, or null
diff --git a/third_party/blink/web_tests/external/wpt/import-maps/resources/jest-test-helper.js b/third_party/blink/web_tests/external/wpt/import-maps/resources/jest-test-helper.js
index 86556ed..8d9236a 100644
--- a/third_party/blink/web_tests/external/wpt/import-maps/resources/jest-test-helper.js
+++ b/third_party/blink/web_tests/external/wpt/import-maps/resources/jest-test-helper.js
@@ -80,16 +80,28 @@
   iframe.contentDocument.write(`
     <base href="${mapBaseURL}">
     <script>
-    let isError = false;
-    function onError() {
-      isError = true;
+    var scriptError;
+    var windowError;
+    function onScriptError(event) {
+      scriptError = event.error;
     }
+    function onWindowError(event) {
+      windowError = event.error;
+      return false;
+    }
+    window.addEventListener('error', onWindowError);
     </sc` + `ript>
-    <script type="importmap" onerror="onError()">
+    <script type="importmap" onerror="onScriptError(event)">
     ${mapString}
     </sc` + `ript>
   `);
   iframe.contentDocument.close();
+
+  // Rethrow window's error event.
+  if (iframe.contentWindow.windowError) {
+    throw iframe.contentWindow.windowError;
+  }
+
   return iframe;
 }
 
diff --git a/tools/clang/plugins/tests/virtual_specifiers.cpp b/tools/clang/plugins/tests/virtual_specifiers.cpp
index f566ac4..5724498 100644
--- a/tools/clang/plugins/tests/virtual_specifiers.cpp
+++ b/tools/clang/plugins/tests/virtual_specifiers.cpp
@@ -27,7 +27,7 @@
   void F() OVERRIDE {}
 };
 
-class CorrectFinal : public CorrectOverride {
+class CorrectFinal FINAL : public CorrectOverride {
  public:
   ~CorrectFinal() FINAL {}
   void F() FINAL {}
@@ -47,19 +47,19 @@
   virtual void F() OVERRIDE {}
 };
 
-class VirtualAndFinal : public Base {
+class VirtualAndFinal FINAL : public Base {
  public:
   virtual ~VirtualAndFinal() FINAL {}
   virtual void F() FINAL {}
 };
 
-class VirtualAndOverrideFinal : public Base {
+class VirtualAndOverrideFinal FINAL : public Base {
  public:
   virtual ~VirtualAndOverrideFinal() OVERRIDE FINAL {}
   virtual void F() OVERRIDE FINAL {}
 };
 
-class OverrideAndFinal : public Base {
+class OverrideAndFinal FINAL : public Base {
  public:
   ~OverrideAndFinal() OVERRIDE FINAL {}
   void F() OVERRIDE FINAL {}
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 75daa7c..aeda7b4 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -13154,7 +13154,8 @@
   <int value="2" label="Desk-switch keyboard shortcut"/>
   <int value="3" label="Mini_view button press"/>
   <int value="4" label="Window on desk activated"/>
-  <int value="5" label="Desk-switch 4-finger touchpad swipe"/>
+  <int value="5" label="Desk-switch 3-finger touchpad swipe"/>
+  <int value="6" label="User switch in a multi-profile session"/>
 </enum>
 
 <enum name="DesktopCaptureCounters">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index cded103f..2da64be 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -171462,6 +171462,15 @@
   <affected-histogram name="SafeBrowsing.WebSocket.Elapsed"/>
 </histogram_suffixes>
 
+<histogram_suffixes name="SafetyTip" separator=".">
+  <suffix name="SafetyTip_BadReputation" label="Bad reputation Safety Tip"/>
+  <suffix name="SafetyTip_Lookalike" label="Lookalike Safety Tip"/>
+  <suffix name="SafetyTip_None" label="No Safety Tip"/>
+  <suffix name="SafetyTip_Unknown" label="Unknown Safety Tip status"/>
+  <affected-histogram name="Security.PageEndReason"/>
+  <affected-histogram name="Security.TimeOnPage2"/>
+</histogram_suffixes>
+
 <histogram_suffixes name="SameVersionStartupCounts" separator=".">
   <suffix name="1" label="1st startup with same version"/>
   <suffix name="2" label="2nd startup with same version"/>
diff --git a/ui/file_manager/externs/background/duplicate_finder.js b/ui/file_manager/externs/background/duplicate_finder.js
new file mode 100644
index 0000000..811e092
--- /dev/null
+++ b/ui/file_manager/externs/background/duplicate_finder.js
@@ -0,0 +1,30 @@
+// Copyright 2019 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.
+
+// Namespace
+var importer = importer || {};
+
+/**
+ * Declare DispositionChecker class.
+ * @interface
+ */
+importer.DispositionChecker = class {
+  /**
+   * Factory for a function that returns a file entry's content disposition.
+   *
+   * @param {!importer.HistoryLoader} historyLoader
+   *
+   * @return {!importer.DispositionChecker.CheckerFunction}
+   */
+  static createChecker(historyLoader) {}
+};
+
+/**
+ * Define a function type that returns a Promise that resolves the content
+ * disposition of an entry.
+ *
+ * @typedef {function(!FileEntry, !importer.Destination, !importer.ScanMode):
+ *     !Promise<!importer.Disposition>}
+ */
+importer.DispositionChecker.CheckerFunction;
diff --git a/ui/file_manager/externs/background/import_history.js b/ui/file_manager/externs/background/import_history.js
index dfe5d02..0b55b21 100644
--- a/ui/file_manager/externs/background/import_history.js
+++ b/ui/file_manager/externs/background/import_history.js
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 // Namespace
-var importer;
+var importer = importer || {};
 
 /**
  * A persistent data store for Cloud Import history information.
diff --git a/ui/file_manager/externs/background/import_runner.js b/ui/file_manager/externs/background/import_runner.js
index 9042bd51..e10514d7 100644
--- a/ui/file_manager/externs/background/import_runner.js
+++ b/ui/file_manager/externs/background/import_runner.js
@@ -3,22 +3,22 @@
 // found in the LICENSE file.
 
 // Namespace
-var importer;
+var importer = importer || {};
 
 /**
  * Interface providing access to information about active import processes.
  *
  * @interface
  */
-importer.ImportRunner = function() {};
-
-/**
- * Imports all media identified by a scanResult.
- *
- * @param {!importer.ScanResult} scanResult
- * @param {!importer.Destination} destination
- * @param {!Promise<!DirectoryEntry>} directoryPromise
- *
- * @return {!importer.MediaImportHandler.ImportTask} The media import task.
- */
-importer.ImportRunner.prototype.importFromScanResult;
+importer.ImportRunner = class {
+  /**
+   * Imports all media identified by a scanResult.
+   *
+   * @param {!importer.ScanResult} scanResult
+   * @param {!importer.Destination} destination
+   * @param {!Promise<!DirectoryEntry>} directoryPromise
+   *
+   * @return {!importer.MediaImportHandler.ImportTask} The media import task.
+   */
+  importFromScanResult(scanResult, destination, directoryPromise) {}
+};
diff --git a/ui/file_manager/externs/background/media_import_handler.js b/ui/file_manager/externs/background/media_import_handler.js
index 744e194..6abbca2 100644
--- a/ui/file_manager/externs/background/media_import_handler.js
+++ b/ui/file_manager/externs/background/media_import_handler.js
@@ -3,74 +3,29 @@
 // found in the LICENSE file.
 
 // Namespace
-var importer;
+var importer = importer || {};
 
 /*
- * Classes MediaImportHandler needs are not currently defined in externs to
- * allow for Closure compilation of its media import unittest.
- *
- * Rectify this situation by forward declaring needed classes, and defining
- * their constructor signatures, to enable Closure type checks in all users
- * of the media import handler class, including unittests.
+ * Externs definition for  MediaImportHandler to allow for Closure compilation
+ * of its media import unittest and caller sites.
  */
 
 /**
- * Define TaskQueue constructor.
- * @constructor
- * @struct
- */
-importer.TaskQueue = function() {};
-
-/**
- * Declare TaskQueue.Task interface.
- * @interface
- */
-importer.TaskQueue.Task = function() {};
-
-/**
- * Define TaskQueue.BaseTask constructor.
- * @constructor
- * @implements {importer.TaskQueue.Task}
- * @param {string} taskId
- */
-importer.TaskQueue.BaseTask = function(taskId) {};
-
-/**
- * Declare DispositionChecker class.
- * @struct
- */
-importer.DispositionChecker;
-
-/**
- * Define a function type that returns a Promise that resolves the content
- * disposition of an entry.
- *
- * @typedef {function(!FileEntry, !importer.Destination, !importer.ScanMode):
- *     !Promise<!importer.Disposition>}
- */
-importer.DispositionChecker.CheckerFunction;
-
-/**
  * Define MediaImportHandler constructor: handler for importing media from
  * removable devices into the user's Drive.
  *
- * @constructor
- * @implements {importer.ImportRunner}
- * @struct
- * @param {!ProgressCenter} progressCenter
- * @param {!importer.HistoryLoader} historyLoader
- * @param {!importer.DispositionChecker.CheckerFunction} dispositionChecker
- * @param {!DriveSyncHandler} driveSyncHandler
+ * @interface
  */
-importer.MediaImportHandler = function(
-    progressCenter, historyLoader, dispositionChecker, driveSyncHandler) {};
-
-/**
- * Define importer.ImportRunner.importFromScanResult override.
- * @override
- * @return {!importer.MediaImportHandler.ImportTask} The media import task.
- */
-importer.MediaImportHandler.prototype.importFromScanResult;
+importer.MediaImportHandler = class extends importer.ImportRunner {
+  /**
+   * @param {!ProgressCenter} progressCenter
+   * @param {!importer.HistoryLoader} historyLoader
+   * @param {!importer.DispositionChecker.CheckerFunction} dispositionChecker
+   * @param {!DriveSyncHandler} driveSyncHandler
+   */
+  constructor(
+      progressCenter, historyLoader, dispositionChecker, driveSyncHandler) {}
+};
 
 /**
  * Define MediaImportHandler.ImportTask.
@@ -79,29 +34,40 @@
  * the FileOperationManager (and thus *spawns* an associated
  * FileOperationManager.CopyTask) but this is a temporary state of affairs.
  *
- * @constructor
  * @extends {importer.TaskQueue.BaseTask}
- * @struct
- * @param {string} taskId
- * @param {!importer.HistoryLoader} historyLoader
- * @param {!importer.ScanResult} scanResult
- * @param {!Promise<!DirectoryEntry>} directoryPromise
- * @param {!importer.Destination} destination The logical destination.
- * @param {!importer.DispositionChecker.CheckerFunction} dispositionChecker
+ * @interface
  */
-importer.MediaImportHandler.ImportTask = function(
-    taskId, historyLoader, scanResult, directoryPromise, destination,
-    dispositionChecker) {};
+importer.MediaImportHandler.ImportTask = class {
+  /**
+   * @param {string} taskId
+   * @param {!importer.HistoryLoader} historyLoader
+   * @param {!importer.ScanResult} scanResult
+   * @param {!Promise<!DirectoryEntry>} directoryPromise
+   * @param {!importer.Destination} destination The logical destination.
+   * @param {!importer.DispositionChecker.CheckerFunction} dispositionChecker
+   */
+  constructor(
+      taskId, historyLoader, scanResult, directoryPromise, destination,
+      dispositionChecker) {}
 
-/** @struct */
-importer.MediaImportHandler.ImportTask.prototype = {
-  /** @return {!Promise} Resolves when task
-      is complete, or cancelled, rejects on error. */
+  /**
+   * @return {!Promise} Resolves when task is complete, or cancelled, rejects
+   *     on error.
+   */
   get whenFinished() {}
+
+  /**
+   * Requests cancellation of this task: an update will be sent to all observers
+   * of this task when the task is actually cancelled.
+   */
+  requestCancel() {}
 };
 
 /**
- * Requests cancellation of this task: an update will be sent to all observers
- * of this task when the task is actually cancelled.
+ * Auxiliary info for ENTRY_CHANGED notifications.
+ * @typedef {{
+ *   sourceUrl: string,
+ *   destination: !Entry
+ * }}
  */
-importer.MediaImportHandler.ImportTask.prototype.requestCancel = function() {};
+importer.MediaImportHandler.ImportTask.EntryChangedInfo;
diff --git a/ui/file_manager/externs/background/media_scanner.js b/ui/file_manager/externs/background/media_scanner.js
index 0b4fe9b2..d754953 100644
--- a/ui/file_manager/externs/background/media_scanner.js
+++ b/ui/file_manager/externs/background/media_scanner.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-var importer;
+var importer = importer || {};
 
 /**
  * Class representing the results of a scan operation.
diff --git a/ui/file_manager/externs/background/progress_center.js b/ui/file_manager/externs/background/progress_center.js
index 9186d8a..e36fdfb 100644
--- a/ui/file_manager/externs/background/progress_center.js
+++ b/ui/file_manager/externs/background/progress_center.js
@@ -22,13 +22,13 @@
 
   /**
    * Adds a panel UI to the notification center.
-   * @param {ProgressCenterPanel} panel Panel UI.
+   * @param {ProgressCenterPanelInterface} panel Panel UI.
    */
   addPanel(panel) {}
 
   /**
    * Removes a panel UI from the notification center.
-   * @param {ProgressCenterPanel} panel Panel UI.
+   * @param {ProgressCenterPanelInterface} panel Panel UI.
    */
   removePanel(panel) {}
 
diff --git a/ui/file_manager/externs/background/task_queue.js b/ui/file_manager/externs/background/task_queue.js
new file mode 100644
index 0000000..c1f8dd75
--- /dev/null
+++ b/ui/file_manager/externs/background/task_queue.js
@@ -0,0 +1,97 @@
+// Copyright 2019 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.
+
+// Namespace
+var importer = importer || {};
+
+/**
+ * import.TaskQueue.
+ * @interface
+ */
+importer.TaskQueue = class {
+  /**
+   * @param {!importer.TaskQueue.Task} task
+   */
+  queueTask(task) {}
+
+  /**
+   * Sets a callback to be triggered when a task updates.
+   * @param {function(string, !importer.TaskQueue.Task)} callback
+   */
+  addUpdateCallback(callback) {}
+
+  /**
+   * Sets a callback that is triggered each time the queue goes from an idle
+   * (i.e. empty with no running tasks) to an active (i.e. having a running
+   * task) state.
+   * @param {function()} callback
+   */
+  setActiveCallback(callback) {}
+
+  /**
+   * Sets a callback that is triggered each time the queue goes from an active
+   * to an idle state.  Also see #setActiveCallback.
+   * @param {function()} callback
+   */
+  setIdleCallback(callback) {}
+};
+
+/**
+ * Interface for any Task that is to run on the TaskQueue.
+ * @interface
+ */
+importer.TaskQueue.Task = class {
+  constructor() {}
+
+  /**
+   * Sets the TaskQueue that will own this task.  The TaskQueue must call this
+   * prior to enqueuing a Task.
+   * @param {!importer.TaskQueue.Task.Observer} observer A callback that
+   *     will be triggered each time the task has a status update.
+   */
+  addObserver(observer) {}
+
+  /**
+   * Performs the actual work of the Task.  Child classes should implement this.
+   */
+  run() {}
+};
+
+/**
+ * Base class for importer tasks.
+ * @interface
+ */
+importer.TaskQueue.BaseTask = class extends importer.TaskQueue.Task {
+  /**
+   * @param {string} taskId
+   */
+  constructor(taskId) {}
+
+  /** @return {string} The task ID. */
+  get taskId() {}
+
+  /**
+   * @return {!Promise<!importer.TaskQueue.UpdateType>} Resolves when task
+   *     is complete, or cancelled, rejects on error.
+   */
+  get whenFinished() {}
+
+  /**
+   * @param {importer.TaskQueue.UpdateType} updateType
+   * @param {Object=} opt_data
+   * @protected
+   */
+  notify(updateType, opt_data) {}
+};
+
+/**
+ * A callback that is triggered whenever an update is reported on the observed
+ * task.  The first argument is a string specifying the type of the update.
+ * Standard values used by all tasks are enumerated in
+ * importer.TaskQueue.UpdateType, but child classes may add supplementary update
+ * types of their own.  The second argument is an Object containing
+ * supplementary information pertaining to the update.
+ * @typedef {function(!importer.TaskQueue.UpdateType, Object=)}
+ */
+importer.TaskQueue.Task.Observer;
diff --git a/ui/file_manager/externs/progress_center_panel.js b/ui/file_manager/externs/progress_center_panel.js
new file mode 100644
index 0000000..2ac32919
--- /dev/null
+++ b/ui/file_manager/externs/progress_center_panel.js
@@ -0,0 +1,39 @@
+// Copyright 2019 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.
+
+/**
+ * Interface implemented in foreground page that the background page uses to
+ * send progress event updates to the foreground page, and to receive cancel
+ * and dismiss events from the foreground page.
+ * @interface
+ */
+class ProgressCenterPanelInterface {
+  constructor() {
+    /**
+     * Callback to be called with the ID of the progress item when the cancel
+     * button is clicked.
+     * @public {?function(string)}
+     */
+    this.cancelCallback;
+
+    /**
+     * Callback to be called with the ID of the error item when user pressed
+     * dismiss button of it.
+     * @public {?function(string)}
+     */
+    this.dismissErrorItemCallback;
+  }
+
+  /**
+   * Updates an item to the progress center panel.
+   * @param {!ProgressCenterItem} item Item including new contents.
+   */
+  updateItem(item) {}
+
+  /**
+   * Requests all item groups to dismiss an error item.
+   * @param {string} id Item id.
+   */
+  dismissErrorItem(id) {}
+}
diff --git a/ui/file_manager/file_manager/background/js/BUILD.gn b/ui/file_manager/file_manager/background/js/BUILD.gn
index b2e3b16..98b68cb 100644
--- a/ui/file_manager/file_manager/background/js/BUILD.gn
+++ b/ui/file_manager/file_manager/background/js/BUILD.gn
@@ -98,6 +98,9 @@
     "../../../externs/foreground_window.js",
     "../../../externs/launcher_search_provider.js",
     "../../../externs/platform.js",
+    "//ui/file_manager/externs/progress_center_panel.js",
+    "//ui/file_manager/externs/background/task_queue.js",
+    "//ui/file_manager/externs/background/duplicate_finder.js",
   ]
 }
 
@@ -230,6 +233,7 @@
     "../../common/js:lru_cache",
     "../../common/js:metrics",
   ]
+  externs_list = [ "//ui/file_manager/externs/background/duplicate_finder.js" ]
 }
 
 js_unittest("duplicate_finder_unittest") {
@@ -354,7 +358,12 @@
     "../../common/js:importer_common",
     "../../common/js:metrics",
   ]
-  externs_list = [ "//ui/file_manager/externs/background/import_runner.js" ]
+  externs_list = [
+    "//ui/file_manager/externs/background/import_runner.js",
+    "//ui/file_manager/externs/background/duplicate_finder.js",
+    "//ui/file_manager/externs/background/task_queue.js",
+    "//ui/file_manager/externs/background/media_import_handler.js",
+  ]
 }
 
 js_unittest("media_import_handler_unittest") {
@@ -416,7 +425,6 @@
     ":progress_center",
     "//ui/webui/resources/js/cr:event_target",
   ]
-  externs_list = [ "//ui/file_manager/externs/background/progress_center.js" ]
 }
 
 js_library("progress_center") {
@@ -424,29 +432,33 @@
     "../../common/js:async_util",
     "../../common/js:progress_center_common",
     "../../common/js:util",
-    "../../foreground/js/ui:progress_center_panel",
     "//ui/webui/resources/js/cr:event_target",
   ]
-  externs_list = [ "//ui/file_manager/externs/background/progress_center.js" ]
+  externs_list = [
+    "//ui/file_manager/externs/background/progress_center.js",
+    "//ui/file_manager/externs/progress_center_panel.js",
+  ]
 }
 
 js_library("task_queue") {
   deps = [
-    ":duplicate_finder",
     "../../common/js:importer_common",
   ]
+  externs_list = [ "//ui/file_manager/externs/background/task_queue.js" ]
 }
 
 js_unittest("task_queue_unittest") {
   deps = [
     ":task_queue",
     "../../common/js:importer_common",
+    "../../common/js:progress_center_common",
     "//ui/file_manager/base/js:test_error_reporting",
     "//ui/file_manager/base/js:volume_manager_types",
     "//ui/webui/resources/js:assert",
     "//ui/webui/resources/js:cr",
     "//ui/webui/resources/js/cr:event_target",
   ]
+  externs_list = [ "//ui/file_manager/externs/background/task_queue.js" ]
 }
 
 js_library("test_util_base") {
diff --git a/ui/file_manager/file_manager/background/js/background.js b/ui/file_manager/file_manager/background/js/background.js
index 4a5530e..1fd8f33 100644
--- a/ui/file_manager/file_manager/background/js/background.js
+++ b/ui/file_manager/file_manager/background/js/background.js
@@ -61,7 +61,7 @@
    * @type {!importer.DispositionChecker.CheckerFunction}
    */
   this.dispositionChecker_ =
-      importer.DispositionChecker.createChecker(this.historyLoader);
+      importer.DispositionCheckerImpl.createChecker(this.historyLoader);
 
   /**
    * Provides support for scaning media devices as part of Cloud Import.
@@ -76,7 +76,7 @@
    * devices.
    * @type {!importer.MediaImportHandler}
    */
-  this.mediaImportHandler = new importer.MediaImportHandler(
+  this.mediaImportHandler = new importer.MediaImportHandlerImpl(
       this.progressCenter, this.historyLoader, this.dispositionChecker_,
       this.driveSyncHandler);
 
diff --git a/ui/file_manager/file_manager/background/js/duplicate_finder.js b/ui/file_manager/file_manager/background/js/duplicate_finder.js
index 0fefc49..27b6e7ca 100644
--- a/ui/file_manager/file_manager/background/js/duplicate_finder.js
+++ b/ui/file_manager/file_manager/background/js/duplicate_finder.js
@@ -174,8 +174,9 @@
  * primary source for duplicate checking (with the exception
  * of in-scan deduplication, where duplicate results that
  * are within the scan are ignored).
+ * @implements {importer.DispositionChecker}
  */
-importer.DispositionChecker = class DispositionChecker {
+importer.DispositionCheckerImpl = class {
   /**
    * @param {!importer.HistoryLoader} historyLoader
    * @param {!importer.DriveDuplicateFinder} contentMatcher
@@ -267,17 +268,8 @@
    * @return {!importer.DispositionChecker.CheckerFunction}
    */
   static createChecker(historyLoader) {
-    const checker = new importer.DispositionChecker(
+    const checker = new importer.DispositionCheckerImpl(
         historyLoader, new importer.DriveDuplicateFinder());
     return checker.getDisposition.bind(checker);
   }
 };
-
-/**
- * Define a function type that returns a Promise that resolves the content
- * disposition of an entry.
- *
- * @typedef {function(!FileEntry, !importer.Destination, !importer.ScanMode):
- *     !Promise<!importer.Disposition>}
- */
-importer.DispositionChecker.CheckerFunction;
diff --git a/ui/file_manager/file_manager/background/js/duplicate_finder_unittest.js b/ui/file_manager/file_manager/background/js/duplicate_finder_unittest.js
index eb3a37a..bb9cda66 100644
--- a/ui/file_manager/file_manager/background/js/duplicate_finder_unittest.js
+++ b/ui/file_manager/file_manager/background/js/duplicate_finder_unittest.js
@@ -76,7 +76,7 @@
 
   testHistory = new importer.TestImportHistory();
   duplicateFinder = new importer.DriveDuplicateFinder();
-  getDisposition = importer.DispositionChecker.createChecker(testHistory);
+  getDisposition = importer.DispositionCheckerImpl.createChecker(testHistory);
 }
 
 // Verifies the correct result when a duplicate exists.
diff --git a/ui/file_manager/file_manager/background/js/media_import_handler.js b/ui/file_manager/file_manager/background/js/media_import_handler.js
index ebebb1d0..3194f1a 100644
--- a/ui/file_manager/file_manager/background/js/media_import_handler.js
+++ b/ui/file_manager/file_manager/background/js/media_import_handler.js
@@ -5,50 +5,9 @@
 // Namespace
 var importer = importer || {};
 
-/**
- * Handler for importing media from removable devices into the user's Drive.
- *
- * @constructor
- * @implements {importer.ImportRunner}
- * @struct
- * @param {!ProgressCenter} progressCenter
- * @param {!importer.HistoryLoader} historyLoader
- * @param {!importer.DispositionChecker.CheckerFunction} dispositionChecker
- * @param {!DriveSyncHandler} driveSyncHandler
- * @return undefined
- */
-importer.MediaImportHandler = function(
-    progressCenter, historyLoader, dispositionChecker, driveSyncHandler) {
-  /** @private {!ProgressCenter} */
-  this.progressCenter_ = progressCenter;
-
-  /** @private {!importer.HistoryLoader} */
-  this.historyLoader_ = historyLoader;
-
-  /** @private {!importer.TaskQueue} */
-  this.queue_ = new importer.TaskQueue();
-
-  // Prevent the system from sleeping while imports are active.
-  this.queue_.setActiveCallback(() => {
-    chrome.power.requestKeepAwake('system');
-  });
-  this.queue_.setIdleCallback(() => {
-    chrome.power.releaseKeepAwake();
-  });
-
-  /** @private {number} */
-  this.nextTaskId_ = 0;
-
-  /** @private {!importer.DispositionChecker.CheckerFunction} */
-  this.getDisposition_ = dispositionChecker;
-
-  /** @private {!DriveSyncHandler} */
-  this.driveSyncHandler_ = driveSyncHandler;
-
-  if (this.driveSyncHandler_.getCompletedEventName() !== 'completed') {
-    throw new Error('invalid drive sync completed event name');
-  }
-};
+importer.MediaImportHandler = importer.MediaImportHandler || {};
+importer.MediaImportHandler.ImportTask =
+    importer.MediaImportHandler.ImportTask || {};
 
 // The name of the Drive property used to tag imported files.  Used to look up
 // the property later.
@@ -59,158 +18,203 @@
 // files start being imported.
 importer.MediaImportHandler.IMPORTS_TAG_VALUE = 'media';
 
-/** @override */
-importer.MediaImportHandler.prototype.importFromScanResult = function(
-    scanResult, destination, directoryPromise) {
-  const task = new importer.MediaImportHandler.ImportTask(
-      this.generateTaskId_(), this.historyLoader_, scanResult, directoryPromise,
-      destination, this.getDisposition_);
-
-  task.addObserver(this.onTaskProgress_.bind(this, task));
-  task.addObserver(this.onFileImported_.bind(this, task));
-
-  // Schedule the task when it is initialized.
-  scanResult.whenFinal()
-      .then(task.initialize_.bind(task))
-      .then(function(scanResult, task) {
-        task.importEntries = scanResult.getFileEntries();
-        this.queue_.queueTask(task);
-      }.bind(this, scanResult, task));
-
-  return task;
-};
-
 /**
- * Generates unique task IDs.
- * @private
- */
-importer.MediaImportHandler.prototype.generateTaskId_ = function() {
-  return 'media-import' + this.nextTaskId_++;
-};
-
-/**
- * Sends updates to the ProgressCenter when an import is happening.
+ * Handler for importing media from removable devices into the user's Drive.
  *
- * @param {!importer.MediaImportHandler.ImportTask} task
- * @param {string} updateType
- * @private
+ * @implements {importer.ImportRunner}
+ * @implements {importer.MediaImportHandler}
  */
-importer.MediaImportHandler.prototype.onTaskProgress_ = function(
-    task, updateType) {
-  const UpdateType = importer.TaskQueue.UpdateType;
+importer.MediaImportHandlerImpl = class {
+  /**
+   * @param {!ProgressCenter} progressCenter
+   * @param {!importer.HistoryLoader} historyLoader
+   * @param {!importer.DispositionChecker.CheckerFunction} dispositionChecker
+   * @param {!DriveSyncHandler} driveSyncHandler
+   */
+  constructor(
+      progressCenter, historyLoader, dispositionChecker, driveSyncHandler) {
+    /** @private {!ProgressCenter} */
+    this.progressCenter_ = progressCenter;
 
-  let item = this.progressCenter_.getItemById(task.taskId);
-  if (!item) {
-    item = new ProgressCenterItem();
-    item.id = task.taskId;
-    // TODO(kenobi): Might need a different progress item type here.
-    item.type = ProgressItemType.COPY;
-    item.progressMax = task.totalBytes;
-    item.cancelCallback = () => {
-      task.requestCancel();
-    };
+    /** @private {!importer.HistoryLoader} */
+    this.historyLoader_ = historyLoader;
+
+    /** @private {!importer.TaskQueue} */
+    this.queue_ = new importer.TaskQueueImpl();
+
+    // Prevent the system from sleeping while imports are active.
+    this.queue_.setActiveCallback(() => {
+      chrome.power.requestKeepAwake('system');
+    });
+    this.queue_.setIdleCallback(() => {
+      chrome.power.releaseKeepAwake();
+    });
+
+    /** @private {number} */
+    this.nextTaskId_ = 0;
+
+    /** @private {!importer.DispositionChecker.CheckerFunction} */
+    this.getDisposition_ = dispositionChecker;
+
+    /** @private {!DriveSyncHandler} */
+    this.driveSyncHandler_ = driveSyncHandler;
+
+    if (this.driveSyncHandler_.getCompletedEventName() !== 'completed') {
+      throw new Error('invalid drive sync completed event name');
+    }
   }
 
-  switch (updateType) {
-    case UpdateType.PROGRESS:
-      item.message =
-          strf('CLOUD_IMPORT_ITEMS_REMAINING', task.remainingFilesCount);
-      item.progressValue = task.processedBytes;
-      item.state = ProgressItemState.PROGRESSING;
-      break;
+  /** @override */
+  importFromScanResult(scanResult, destination, directoryPromise) {
+    const task = new importer.MediaImportHandler.ImportTaskImpl(
+        this.generateTaskId_(), this.historyLoader_, scanResult,
+        directoryPromise, destination, this.getDisposition_);
 
-    case UpdateType.COMPLETE:
-      // Remove the event handler that gets attached for retries.
-      this.driveSyncHandler_.removeEventListener(
-          this.driveSyncHandler_.getCompletedEventName(), task.driveListener_);
+    task.addObserver(this.onTaskProgress_.bind(this, task));
+    task.addObserver(this.onFileImported_.bind(this, task));
 
-      if (task.failedEntries.length > 0 &&
-          task.failedEntries.length < task.importEntries.length) {
-        // If there are failed entries but at least one entry succeeded on the
-        // last run, there is a chance of more succeeding when retrying.
-        this.retryTaskFailedEntries_(task);
-      } else {
-        // Otherwise, finish progress bar.
-        // Display all errors.
-        let errorIdCounter = 0;
-        task.failedEntries.forEach(entry => {
-          const errorItem = new ProgressCenterItem();
-          errorItem.id = task.taskId_ + '-' + (errorIdCounter++);
-          errorItem.type = ProgressItemType.COPY;
-          errorItem.quiet = true;
-          errorItem.state = ProgressItemState.ERROR;
-          errorItem.message = strf('CLOUD_IMPORT_ERROR_ITEM', entry.name);
-          this.progressCenter_.updateItem(item);
-        });
+    // Schedule the task when it is initialized.
+    scanResult.whenFinal()
+        .then(task.initialize_.bind(task))
+        .then(function(scanResult, task) {
+          task.importEntries = scanResult.getFileEntries();
+          this.queue_.queueTask(task);
+        }.bind(this, scanResult, task));
 
-        // Complete progress bar.
-        item.message = '';
-        item.progressValue = item.progressMax;
-        item.state = ProgressItemState.COMPLETED;
-
-        task.sendImportStats_();
-      }
-
-      break;
-
-    case UpdateType.CANCELED:
-      item.message = '';
-      item.state = ProgressItemState.CANCELED;
-      break;
+    return task;
   }
 
-  this.progressCenter_.updateItem(item);
-};
-
-/**
- * Restarts a task with failed entries.
- * @param {!importer.TaskQueue.Task} task
- */
-importer.MediaImportHandler.prototype.retryTaskFailedEntries_ = function(task) {
-  // Reset the entry lists.
-  task.importEntries = task.failedEntries;
-  task.failedEntries = [];
-
-  // When Drive is done syncing, it will mark the synced files as eligible
-  // for cache eviction, enabling files that failed to be imported because
-  // of not having enough local space to succeed on retry.
-  task.driveListener_ = function(task) {
-    this.queue_.queueTask(task);
-  }.bind(this, task);
-  this.driveSyncHandler_.addEventListener(
-      this.driveSyncHandler_.getCompletedEventName(), task.driveListener_);
-};
-
-/**
- * Tags newly-imported files with a Drive property.
- * @param {!importer.TaskQueue.Task} task
- * @param {string} updateType
- * @param {Object=} updateInfo
- */
-importer.MediaImportHandler.prototype
-    .onFileImported_ = (task, updateType, updateInfo) => {
-  if (updateType !==
-      importer.MediaImportHandler.ImportTask.UpdateType.ENTRY_CHANGED) {
-    return;
+  /**
+   * Generates unique task IDs.
+   * @private
+   */
+  generateTaskId_() {
+    return 'media-import' + this.nextTaskId_++;
   }
-  // Update info must exist for ENTRY_CHANGED notifications.
-  console.assert(updateInfo && updateInfo.destination);
-  const info =
-      /** @type {!importer.MediaImportHandler.ImportTask.EntryChangedInfo} */ (
-          updateInfo);
 
-  // Tag the import with a private drive property.
-  chrome.fileManagerPrivate.setEntryTag(
-      info.destination,
-      'private',  // Scoped to just this app.
-      importer.MediaImportHandler.IMPORTS_TAG_KEY,
-      importer.MediaImportHandler.IMPORTS_TAG_VALUE, () => {
-        if (chrome.runtime.lastError) {
-          console.error(
-              'Unable to tag imported media: ' +
-              chrome.runtime.lastError.message);
+  /**
+   * Sends updates to the ProgressCenter when an import is happening.
+   *
+   * @param {!importer.MediaImportHandler.ImportTaskImpl} task
+   * @param {string} updateType
+   * @private
+   */
+  onTaskProgress_(task, updateType) {
+    const UpdateType = importer.TaskQueue.UpdateType;
+
+    let item = this.progressCenter_.getItemById(task.taskId);
+    if (!item) {
+      item = new ProgressCenterItem();
+      item.id = task.taskId;
+      // TODO(kenobi): Might need a different progress item type here.
+      item.type = ProgressItemType.COPY;
+      item.progressMax = task.totalBytes;
+      item.cancelCallback = () => {
+        task.requestCancel();
+      };
+    }
+
+    switch (updateType) {
+      case UpdateType.PROGRESS:
+        item.message =
+            strf('CLOUD_IMPORT_ITEMS_REMAINING', task.remainingFilesCount);
+        item.progressValue = task.processedBytes;
+        item.state = ProgressItemState.PROGRESSING;
+        break;
+
+      case UpdateType.COMPLETE:
+        // Remove the event handler that gets attached for retries.
+        this.driveSyncHandler_.removeEventListener(
+            this.driveSyncHandler_.getCompletedEventName(),
+            task.driveListener_);
+
+        if (task.failedEntries.length > 0 &&
+            task.failedEntries.length < task.importEntries.length) {
+          // If there are failed entries but at least one entry succeeded on the
+          // last run, there is a chance of more succeeding when retrying.
+          this.retryTaskFailedEntries_(task);
+        } else {
+          // Otherwise, finish progress bar.
+          // Display all errors.
+          let errorIdCounter = 0;
+          task.failedEntries.forEach(entry => {
+            const errorItem = new ProgressCenterItem();
+            errorItem.id = task.taskId_ + '-' + (errorIdCounter++);
+            errorItem.type = ProgressItemType.COPY;
+            errorItem.quiet = true;
+            errorItem.state = ProgressItemState.ERROR;
+            errorItem.message = strf('CLOUD_IMPORT_ERROR_ITEM', entry.name);
+            this.progressCenter_.updateItem(item);
+          });
+
+          // Complete progress bar.
+          item.message = '';
+          item.progressValue = item.progressMax;
+          item.state = ProgressItemState.COMPLETED;
+
+          task.sendImportStats_();
         }
-      });
+
+        break;
+
+      case UpdateType.CANCELED:
+        item.message = '';
+        item.state = ProgressItemState.CANCELED;
+        break;
+    }
+
+    this.progressCenter_.updateItem(item);
+  }
+
+  /**
+   * Restarts a task with failed entries.
+   * @param {!importer.MediaImportHandler.ImportTaskImpl} task
+   */
+  retryTaskFailedEntries_(task) {
+    // Reset the entry lists.
+    task.importEntries = task.failedEntries;
+    task.failedEntries = [];
+
+    // When Drive is done syncing, it will mark the synced files as eligible
+    // for cache eviction, enabling files that failed to be imported because
+    // of not having enough local space to succeed on retry.
+    task.driveListener_ = () => {
+      this.queue_.queueTask(task);
+    };
+    this.driveSyncHandler_.addEventListener(
+        this.driveSyncHandler_.getCompletedEventName(), task.driveListener_);
+  }
+
+  /**
+   * Tags newly-imported files with a Drive property.
+   * @param {!importer.TaskQueue.Task} task
+   * @param {string} updateType
+   * @param {Object=} updateInfo
+   */
+  onFileImported_(task, updateType, updateInfo) {
+    if (updateType !==
+        importer.MediaImportHandler.ImportTask.UpdateType.ENTRY_CHANGED) {
+      return;
+    }
+    // Update info must exist for ENTRY_CHANGED notifications.
+    console.assert(updateInfo && updateInfo.destination);
+    const info =
+        /** @type {!importer.MediaImportHandler.ImportTask.EntryChangedInfo} */
+        (updateInfo);
+
+    // Tag the import with a private drive property.
+    chrome.fileManagerPrivate.setEntryTag(
+        info.destination,
+        'private',  // Scoped to just this app.
+        importer.MediaImportHandler.IMPORTS_TAG_KEY,
+        importer.MediaImportHandler.IMPORTS_TAG_VALUE, () => {
+          if (chrome.runtime.lastError) {
+            console.error(
+                'Unable to tag imported media: ' +
+                chrome.runtime.lastError.message);
+          }
+        });
+  }
 };
 
 /**
@@ -218,121 +222,400 @@
  * the FileOperationManager (and thus *spawns* an associated
  * FileOperationManager.CopyTask) but this is a temporary state of affairs.
  *
- * @constructor
- * @extends {importer.TaskQueue.BaseTask}
- * @struct
- * @param {string} taskId
- * @param {!importer.HistoryLoader} historyLoader
- * @param {!importer.ScanResult} scanResult
- * @param {!Promise<!DirectoryEntry>} directoryPromise
- * @param {!importer.Destination} destination The logical destination.
- * @param {!importer.DispositionChecker.CheckerFunction} dispositionChecker
- * @return undefined
+ * @implements {importer.MediaImportHandler.ImportTask}
  */
-importer.MediaImportHandler.ImportTask = function(
-    taskId, historyLoader, scanResult, directoryPromise, destination,
-    dispositionChecker) {
-  /** @extends {importer.TaskQueue.BaseTask} */
-  importer.TaskQueue.BaseTask.call(this, taskId);
-
-  /** @protected {string} */
-  this.taskId_ = taskId;
-
-  /** @private {!importer.Destination} */
-  this.destination_ = destination;
-
-  /** @private {!Promise<!DirectoryEntry>} */
-  this.directoryPromise_ = directoryPromise;
-
-  /** @private {!importer.ScanResult} */
-  this.scanResult_ = scanResult;
-
-  /** @private {!importer.HistoryLoader} */
-  this.historyLoader_ = historyLoader;
-
-  /** @private {number} */
-  this.totalBytes_ = 0;
-
-  /** @private {number} */
-  this.processedBytes_ = 0;
-
+importer.MediaImportHandler.ImportTaskImpl =
+    class extends importer.TaskQueue.BaseTaskImpl {
   /**
-   * Number of duplicate files found by the content hash check.
-   * @private {number}
+   * @param {string} taskId
+   * @param {!importer.HistoryLoader} historyLoader
+   * @param {!importer.ScanResult} scanResult
+   * @param {!Promise<!DirectoryEntry>} directoryPromise
+   * @param {!importer.Destination} destination The logical destination.
+   * @param {!importer.DispositionChecker.CheckerFunction} dispositionChecker
    */
-  this.duplicateFilesCount_ = 0;
+  constructor(
+      taskId, historyLoader, scanResult, directoryPromise, destination,
+      dispositionChecker) {
+    super(taskId);
 
-  /** @private {number} */
-  this.remainingFilesCount_ = 0;
+    /** @protected {string} */
+    this.taskId_ = taskId;
 
-  /** @private {?function()} */
-  this.cancelCallback_ = null;
+    /** @private {!importer.Destination} */
+    this.destination_ = destination;
 
-  /** @private {boolean} Indicates whether this task was canceled. */
-  this.canceled_ = false;
+    /** @private {!Promise<!DirectoryEntry>} */
+    this.directoryPromise_ = directoryPromise;
 
-  /** @private {number} */
-  this.errorCount_ = 0;
+    /** @private {!importer.ScanResult} */
+    this.scanResult_ = scanResult;
 
-  /** @private {!importer.DispositionChecker.CheckerFunction} */
-  this.getDisposition_ = dispositionChecker;
+    /** @private {!importer.HistoryLoader} */
+    this.historyLoader_ = historyLoader;
 
-  /**
-   * The entries to be imported.
-   * @private {!Array<!FileEntry>}
-   */
-  this.importEntries_ = [];
+    /** @private {number} */
+    this.totalBytes_ = 0;
 
-  /**
-   * The failed entries.
-   * @private {!Array<!FileEntry>}
-   */
-  this.failedEntries_ = [];
+    /** @private {number} */
+    this.processedBytes_ = 0;
 
-  /**
-   * A placeholder for identifying the appropriate retry function for a given
-   * task.
-   * @private {EventListener}
-   */
-  this.driveListener_ = null;
-};
+    /**
+     * Number of duplicate files found by the content hash check.
+     * @private {number}
+     */
+    this.duplicateFilesCount_ = 0;
 
-/** @struct */
-importer.MediaImportHandler.ImportTask.prototype = {
+    /** @private {number} */
+    this.remainingFilesCount_ = 0;
+
+    /** @private {?function()} */
+    this.cancelCallback_ = null;
+
+    /** @private {boolean} Indicates whether this task was canceled. */
+    this.canceled_ = false;
+
+    /** @private {number} */
+    this.errorCount_ = 0;
+
+    /** @private {!importer.DispositionChecker.CheckerFunction} */
+    this.getDisposition_ = dispositionChecker;
+
+    /**
+     * The entries to be imported.
+     * @private {!Array<!FileEntry>}
+     */
+    this.importEntries_ = [];
+
+    /**
+     * The failed entries.
+     * @private {!Array<!FileEntry>}
+     */
+    this.failedEntries_ = [];
+
+    /**
+     * A placeholder for identifying the appropriate retry function for a given
+     * task.
+     * @private {EventListener|function(!Event)}
+     */
+    this.driveListener_ = null;
+  }
+
   /** @return {number} Number of imported bytes */
   get processedBytes() {
     return this.processedBytes_;
-  },
+  }
 
   /** @return {number} Total number of bytes to import */
   get totalBytes() {
     return this.totalBytes_;
-  },
+  }
 
   /** @return {number} Number of files left to import */
   get remainingFilesCount() {
     return this.remainingFilesCount_;
-  },
+  }
 
   /** @return {!Array<!FileEntry>} The files to be imported */
   get importEntries() {
     return this.importEntries_;
-  },
+  }
 
   /** @param {!Array<!FileEntry>} entries The files to be imported */
   set importEntries(entries) {
     this.importEntries_ = entries.slice();
-  },
+  }
 
   /** @return {!Array<!FileEntry>} The files that couldn't be imported */
   get failedEntries() {
     return this.failedEntries_;
-  },
+  }
 
   /** @param {!Array<!FileEntry>} entries The files that couldn't be imported */
   set failedEntries(entries) {
     this.failedEntries_ = entries.slice();
-  },
+  }
+
+  /** @override */
+  run() {
+    // Wait for the scan to finish, then get the destination entry, then start
+    // the import.
+    this.importScanEntries_()
+        .then(this.markDuplicatesImported_.bind(this))
+        .then(this.onSuccess_.bind(this))
+        .catch(importer.getLogger().catcher('import-task-run'));
+  }
+
+  /**
+   * Request cancellation of this task.  An update will be sent to observers
+   * once the task is actually cancelled.
+   */
+  requestCancel() {
+    this.canceled_ = true;
+    setTimeout(() => {
+      this.notify(importer.TaskQueue.UpdateType.CANCELED);
+      this.sendImportStats_();
+    });
+    if (this.cancelCallback_) {
+      // Reset the callback before calling it, as the callback might do anything
+      // (including calling #requestCancel again).
+      const cancelCallback = this.cancelCallback_;
+      this.cancelCallback_ = null;
+      cancelCallback();
+    }
+  }
+
+  /** @private */
+  initialize_() {
+    const stats = this.scanResult_.getStatistics();
+    this.remainingFilesCount_ = stats.newFileCount;
+    this.totalBytes_ = stats.sizeBytes;
+
+    metrics.recordBoolean('MediaImport.Started', true);
+  }
+
+  /**
+   * Initiates an import to the given location.  This should only be called once
+   * the scan result indicates that it is ready.
+   *
+   * @private
+   */
+  importScanEntries_() {
+    const resolver = new importer.Resolver();
+    this.directoryPromise_.then(destinationDirectory => {
+      AsyncUtil.forEach(
+          this.importEntries_, this.importOne_.bind(this, destinationDirectory),
+          resolver.resolve);
+    });
+    return resolver.promise;
+  }
+
+  /**
+   * Marks all duplicate entries as imported.
+   *
+   * @private
+   */
+  markDuplicatesImported_() {
+    this.historyLoader_.getHistory()
+        .then(
+            /**
+             * @param {!importer.ImportHistory} history
+             */
+            history => {
+              this.scanResult_.getDuplicateFileEntries().forEach(
+                  /**
+                   * @param {!FileEntry} entry
+                   * @this {importer.MediaImportHandler.ImportTask}
+                   */
+                  entry => {
+                    history.markImported(entry, this.destination_);
+                  });
+            })
+        .catch(importer.getLogger().catcher('import-task-mark-dupes-imported'));
+  }
+
+  /**
+   * Imports one file. If the file already exist in Drive, marks as imported.
+   *
+   * @param {!DirectoryEntry} destinationDirectory
+   * @param {function()} completionCallback Called after this operation is
+   *     complete.
+   * @param {!FileEntry} entry The entry to import.
+   * @param {number} index The index of the entry.
+   * @param {Array<!FileEntry>} all All the entries.
+   * @private
+   */
+  importOne_(destinationDirectory, completionCallback, entry, index, all) {
+    if (this.canceled_) {
+      metrics.recordBoolean('MediaImport.Cancelled', true);
+      return;
+    }
+
+    this.getDisposition_(
+            entry, importer.Destination.GOOGLE_DRIVE, importer.ScanMode.CONTENT)
+        .then(/**
+               * @param {!importer.Disposition} disposition The disposition
+               *     of the entry. Either some sort of dupe, or an original.
+               */
+              disposition => {
+                if (disposition === importer.Disposition.ORIGINAL) {
+                  return this.copy_(entry, destinationDirectory);
+                }
+                this.duplicateFilesCount_++;
+                this.markAsImported_(entry);
+              })
+        // Regardless of the result of this copy, push on to the next file.
+        .then(completionCallback)
+        .catch(/** @param {*} error */
+               error => {
+                 importer.getLogger().catcher('import-task-import-one')(error);
+                 // TODO(oka): Retry copies only when failed due to
+                 // insufficient disk space. crbug.com/788692.
+                 this.failedEntries_.push(entry);
+                 completionCallback();
+               });
+  }
+
+  /**
+   * @param {!FileEntry} entry The file to copy.
+   * @param {!DirectoryEntry} destinationDirectory The destination directory.
+   * @return {!Promise<FileEntry>} Resolves to the destination file when the
+   *     copy is complete.  The FileEntry may be null if the import was
+   *     cancelled.  The promise will reject if an error occurs.
+   * @private
+   */
+  copy_(entry, destinationDirectory) {
+    // A count of the current number of processed bytes for this entry.
+    let currentBytes = 0;
+
+    const resolver = new importer.Resolver();
+
+    /**
+     * Updates the task when the copy code reports progress.
+     * @param {string} sourceUrl
+     * @param {number} processedBytes
+     * @this {importer.MediaImportHandler.ImportTask}
+     */
+    const onProgress = (sourceUrl, processedBytes) => {
+      // Update the running total, then send a progress update.
+      this.processedBytes_ -= currentBytes;
+      this.processedBytes_ += processedBytes;
+      currentBytes = processedBytes;
+      this.notify(importer.TaskQueue.UpdateType.PROGRESS);
+    };
+
+    /**
+     * Updates the task when the new file has been created.
+     * @param {string} sourceUrl
+     * @param {Entry} destinationEntry
+     * @this {importer.MediaImportHandler.ImportTask}
+     */
+    const onEntryChanged = (sourceUrl, destinationEntry) => {
+      this.processedBytes_ -= currentBytes;
+      this.processedBytes_ += entry.size;
+      destinationEntry.size = entry.size;
+      this.notify(
+          /** @type {importer.TaskQueue.UpdateType} */
+          (importer.MediaImportHandler.ImportTask.UpdateType.ENTRY_CHANGED), {
+            sourceUrl: sourceUrl,
+            destination: destinationEntry,
+          });
+      this.notify(importer.TaskQueue.UpdateType.PROGRESS);
+    };
+
+    /**
+     * @param {Entry} destinationEntry The new destination entry.
+     * @this {importer.MediaImportHandler.ImportTask}
+     */
+    const onComplete = destinationEntry => {
+      this.cancelCallback_ = null;
+      this.markAsCopied_(entry, /** @type {!FileEntry} */ (destinationEntry));
+      this.notify(importer.TaskQueue.UpdateType.PROGRESS);
+      resolver.resolve(destinationEntry);
+    };
+
+    /** @this {importer.MediaImportHandler.ImportTask} */
+    const onError = error => {
+      this.cancelCallback_ = null;
+      if (error.name === util.FileError.ABORT_ERR) {
+        // Task cancellations result in the error callback being triggered with
+        // an ABORT_ERR, but we want to ignore these errors.
+        this.notify(importer.TaskQueue.UpdateType.PROGRESS);
+        resolver.resolve(null);
+      } else {
+        this.errorCount_++;
+        this.notify(importer.TaskQueue.UpdateType.ERROR);
+        resolver.reject(error);
+      }
+    };
+
+    fileOperationUtil.deduplicatePath(destinationDirectory, entry.name)
+        .then(
+            /**
+             * Performs the copy using the given deduped filename.
+             * @param {string} destinationFilename
+             */
+            destinationFilename => {
+              this.cancelCallback_ = fileOperationUtil.copyTo(
+                  entry, destinationDirectory, destinationFilename,
+                  onEntryChanged, onProgress, onComplete, onError);
+            },
+            resolver.reject)
+        .catch(importer.getLogger().catcher('import-task-copy'));
+
+    return resolver.promise;
+  }
+
+  /**
+   * @param {!FileEntry} entry
+   * @param {!FileEntry} destinationEntry
+   */
+  markAsCopied_(entry, destinationEntry) {
+    this.remainingFilesCount_--;
+    this.historyLoader_.getHistory()
+        .then(history => {
+          history.markCopied(
+              entry, this.destination_, destinationEntry.toURL());
+        })
+        .catch(importer.getLogger().catcher('import-task-mark-as-copied'));
+  }
+
+  /**
+   * @param {!FileEntry} entry
+   * @private
+   */
+  markAsImported_(entry) {
+    this.remainingFilesCount_--;
+    this.historyLoader_.getHistory()
+        .then(
+            /** @param {!importer.ImportHistory} history */
+            history => {
+              history.markImported(entry, this.destination_);
+            })
+        .catch(importer.getLogger().catcher('import-task-mark-as-imported'));
+  }
+
+  /** @private */
+  onSuccess_() {
+    this.notify(importer.TaskQueue.UpdateType.COMPLETE);
+  }
+
+  /**
+   * Sends import statistics to analytics.
+   */
+  sendImportStats_() {
+    const scanStats = this.scanResult_.getStatistics();
+
+    metrics.recordMediumCount(
+        'MediaImport.ImportMB',
+        Math.floor(this.processedBytes_ / (1024 * 1024)));
+
+    metrics.recordMediumCount(
+        'MediaImport.ImportCount',
+        // Subtract the remaining files, in case the task was cancelled.
+        scanStats.newFileCount - this.remainingFilesCount_);
+
+    if (this.errorCount_ > 0) {
+      metrics.recordMediumCount('MediaImport.ErrorCount', this.errorCount_);
+    }
+
+    // Finally we want to report on the number of duplicates
+    // that were identified during scanning.
+    let totalDeduped = 0;
+    // The scan is run without content duplicate check.
+    // Instead, report the number of duplicated files found at import.
+    assert(scanStats.duplicates[importer.Disposition.CONTENT_DUPLICATE] === 0);
+    scanStats.duplicates[importer.Disposition.CONTENT_DUPLICATE] =
+        this.duplicateFilesCount_;
+
+    Object.keys(scanStats.duplicates).forEach(disposition => {
+      const count = scanStats.duplicates[
+          /** @type {!importer.Disposition} */ (disposition)];
+      totalDeduped += count;
+    }, this);
+
+    metrics.recordMediumCount('MediaImport.Duplicates', totalDeduped);
+  }
 };
 
 /**
@@ -343,303 +626,3 @@
 importer.MediaImportHandler.ImportTask.UpdateType = {
   ENTRY_CHANGED: 'ENTRY_CHANGED'
 };
-
-/**
- * Auxilliary info for ENTRY_CHANGED notifications.
- * @typedef {{
- *   sourceUrl: string,
- *   destination: !Entry
- * }}
- */
-importer.MediaImportHandler.ImportTask.EntryChangedInfo;
-
-/**
- * Extends importer.TaskQueue.Task
- */
-importer.MediaImportHandler.ImportTask.prototype.__proto__ =
-    importer.TaskQueue.BaseTask.prototype;
-
-/** @override */
-importer.MediaImportHandler.ImportTask.prototype.run = function() {
-  // Wait for the scan to finish, then get the destination entry, then start the
-  // import.
-  this.importScanEntries_()
-      .then(this.markDuplicatesImported_.bind(this))
-      .then(this.onSuccess_.bind(this))
-      .catch(importer.getLogger().catcher('import-task-run'));
-};
-
-/**
- * Request cancellation of this task.  An update will be sent to observers once
- * the task is actually cancelled.
- */
-importer.MediaImportHandler.ImportTask.prototype.requestCancel = function() {
-  this.canceled_ = true;
-  setTimeout(() => {
-    this.notify(importer.TaskQueue.UpdateType.CANCELED);
-    this.sendImportStats_();
-  });
-  if (this.cancelCallback_) {
-    // Reset the callback before calling it, as the callback might do anything
-    // (including calling #requestCancel again).
-    const cancelCallback = this.cancelCallback_;
-    this.cancelCallback_ = null;
-    cancelCallback();
-  }
-};
-
-/** @private */
-importer.MediaImportHandler.ImportTask.prototype.initialize_ = function() {
-  const stats = this.scanResult_.getStatistics();
-  this.remainingFilesCount_ = stats.newFileCount;
-  this.totalBytes_ = stats.sizeBytes;
-
-  metrics.recordBoolean('MediaImport.Started', true);
-};
-
-/**
- * Initiates an import to the given location.  This should only be called once
- * the scan result indicates that it is ready.
- *
- * @private
- */
-importer.MediaImportHandler.ImportTask.prototype.importScanEntries_ =
-    function() {
-  const resolver = new importer.Resolver();
-  this.directoryPromise_.then(destinationDirectory => {
-    AsyncUtil.forEach(
-        this.importEntries_, this.importOne_.bind(this, destinationDirectory),
-        resolver.resolve);
-  });
-  return resolver.promise;
-};
-
-/**
- * Marks all duplicate entries as imported.
- *
- * @private
- */
-importer.MediaImportHandler.ImportTask.prototype.markDuplicatesImported_ =
-    function() {
-  this.historyLoader_.getHistory()
-      .then(
-          /**
-           * @param {!importer.ImportHistory} history
-           */
-          history => {
-            this.scanResult_.getDuplicateFileEntries().forEach(
-                /**
-                 * @param {!FileEntry} entry
-                 * @this {importer.MediaImportHandler.ImportTask}
-                 */
-                entry => {
-                  history.markImported(entry, this.destination_);
-                });
-          })
-      .catch(importer.getLogger().catcher('import-task-mark-dupes-imported'));
-};
-
-/**
- * Imports one file. If the file already exist in Drive, marks as imported.
- *
- * @param {!DirectoryEntry} destinationDirectory
- * @param {function()} completionCallback Called after this operation is
- *     complete.
- * @param {!FileEntry} entry The entry to import.
- * @param {number} index The index of the entry.
- * @param {Array<!FileEntry>} all All the entries.
- * @private
- */
-importer.MediaImportHandler.ImportTask.prototype.importOne_ = function(
-    destinationDirectory, completionCallback, entry, index, all) {
-  if (this.canceled_) {
-    metrics.recordBoolean('MediaImport.Cancelled', true);
-    return;
-  }
-
-  this.getDisposition_(
-          entry, importer.Destination.GOOGLE_DRIVE, importer.ScanMode.CONTENT)
-      .then(/**
-             * @param {!importer.Disposition} disposition The disposition
-             *     of the entry. Either some sort of dupe, or an original.
-             */
-            disposition => {
-              if (disposition === importer.Disposition.ORIGINAL) {
-                return this.copy_(entry, destinationDirectory);
-              }
-              this.duplicateFilesCount_++;
-              this.markAsImported_(entry);
-            })
-      // Regardless of the result of this copy, push on to the next file.
-      .then(completionCallback)
-      .catch(/** @param {*} error */
-             error => {
-               importer.getLogger().catcher('import-task-import-one')(error);
-               // TODO(oka): Retry copies only when failed due to
-               // insufficient disk space. crbug.com/788692.
-               this.failedEntries_.push(entry);
-               completionCallback();
-             });
-};
-
-/**
- * @param {!FileEntry} entry The file to copy.
- * @param {!DirectoryEntry} destinationDirectory The destination directory.
- * @return {!Promise<FileEntry>} Resolves to the destination file when the copy
- *     is complete.  The FileEntry may be null if the import was cancelled.  The
- *     promise will reject if an error occurs.
- * @private
- */
-importer.MediaImportHandler.ImportTask.prototype.copy_ = function(
-    entry, destinationDirectory) {
-  // A count of the current number of processed bytes for this entry.
-  let currentBytes = 0;
-
-  const resolver = new importer.Resolver();
-
-  /**
-   * Updates the task when the copy code reports progress.
-   * @param {string} sourceUrl
-   * @param {number} processedBytes
-   * @this {importer.MediaImportHandler.ImportTask}
-   */
-  const onProgress = (sourceUrl, processedBytes) => {
-    // Update the running total, then send a progress update.
-    this.processedBytes_ -= currentBytes;
-    this.processedBytes_ += processedBytes;
-    currentBytes = processedBytes;
-    this.notify(importer.TaskQueue.UpdateType.PROGRESS);
-  };
-
-  /**
-   * Updates the task when the new file has been created.
-   * @param {string} sourceUrl
-   * @param {Entry} destinationEntry
-   * @this {importer.MediaImportHandler.ImportTask}
-   */
-  const onEntryChanged = (sourceUrl, destinationEntry) => {
-    this.processedBytes_ -= currentBytes;
-    this.processedBytes_ += entry.size;
-    destinationEntry.size = entry.size;
-    this.notify(
-        /** @type {importer.TaskQueue.UpdateType} */
-        (importer.MediaImportHandler.ImportTask.UpdateType.ENTRY_CHANGED), {
-          sourceUrl: sourceUrl,
-          destination: destinationEntry,
-        });
-    this.notify(importer.TaskQueue.UpdateType.PROGRESS);
-  };
-
-  /**
-   * @param {Entry} destinationEntry The new destination entry.
-   * @this {importer.MediaImportHandler.ImportTask}
-   */
-  const onComplete = destinationEntry => {
-    this.cancelCallback_ = null;
-    this.markAsCopied_(entry, /** @type {!FileEntry} */ (destinationEntry));
-    this.notify(importer.TaskQueue.UpdateType.PROGRESS);
-    resolver.resolve(destinationEntry);
-  };
-
-  /** @this {importer.MediaImportHandler.ImportTask} */
-  const onError = error => {
-    this.cancelCallback_ = null;
-    if (error.name === util.FileError.ABORT_ERR) {
-      // Task cancellations result in the error callback being triggered with an
-      // ABORT_ERR, but we want to ignore these errors.
-      this.notify(importer.TaskQueue.UpdateType.PROGRESS);
-      resolver.resolve(null);
-    } else {
-      this.errorCount_++;
-      this.notify(importer.TaskQueue.UpdateType.ERROR);
-      resolver.reject(error);
-    }
-  };
-
-  fileOperationUtil.deduplicatePath(destinationDirectory, entry.name)
-      .then(
-          /**
-           * Performs the copy using the given deduped filename.
-           * @param {string} destinationFilename
-           */
-          destinationFilename => {
-            this.cancelCallback_ = fileOperationUtil.copyTo(
-                entry, destinationDirectory, destinationFilename,
-                onEntryChanged, onProgress, onComplete, onError);
-          },
-          resolver.reject)
-      .catch(importer.getLogger().catcher('import-task-copy'));
-
-  return resolver.promise;
-};
-
-/**
- * @param {!FileEntry} entry
- * @param {!FileEntry} destinationEntry
- */
-importer.MediaImportHandler.ImportTask.prototype.markAsCopied_ = function(
-    entry, destinationEntry) {
-  this.remainingFilesCount_--;
-  this.historyLoader_.getHistory()
-      .then(history => {
-        history.markCopied(entry, this.destination_, destinationEntry.toURL());
-      })
-      .catch(importer.getLogger().catcher('import-task-mark-as-copied'));
-};
-
-/**
- * @param {!FileEntry} entry
- * @private
- */
-importer.MediaImportHandler.ImportTask.prototype.markAsImported_ = function(
-    entry) {
-  this.remainingFilesCount_--;
-  this.historyLoader_.getHistory()
-      .then(
-          /** @param {!importer.ImportHistory} history */
-          history => {
-            history.markImported(entry, this.destination_);
-          })
-      .catch(importer.getLogger().catcher('import-task-mark-as-imported'));
-};
-
-/** @private */
-importer.MediaImportHandler.ImportTask.prototype.onSuccess_ = function() {
-  this.notify(importer.TaskQueue.UpdateType.COMPLETE);
-};
-
-/**
- * Sends import statistics to analytics.
- */
-importer.MediaImportHandler.ImportTask.prototype.sendImportStats_ = function() {
-  const scanStats = this.scanResult_.getStatistics();
-
-  metrics.recordMediumCount(
-      'MediaImport.ImportMB', Math.floor(this.processedBytes_ / (1024 * 1024)));
-
-  metrics.recordMediumCount(
-      'MediaImport.ImportCount',
-      // Substract the remaining files, in case the task was cancelled.
-      scanStats.newFileCount - this.remainingFilesCount_);
-
-  if (this.errorCount_ > 0) {
-    metrics.recordMediumCount('MediaImport.ErrorCount', this.errorCount_);
-  }
-
-  // Finally we want to report on the number of duplicates
-  // that were identified during scanning.
-  let totalDeduped = 0;
-  // The scan is run without content duplicate check.
-  // Instead, report the number of duplicated files found at import.
-  assert(scanStats.duplicates[importer.Disposition.CONTENT_DUPLICATE] === 0);
-  scanStats.duplicates[importer.Disposition.CONTENT_DUPLICATE] =
-      this.duplicateFilesCount_;
-
-  Object.keys(scanStats.duplicates).forEach(disposition => {
-    const count = scanStats.duplicates[
-        /** @type {!importer.Disposition} */ (disposition)];
-    totalDeduped += count;
-  }, this);
-
-  metrics.recordMediumCount('MediaImport.Duplicates', totalDeduped);
-};
diff --git a/ui/file_manager/file_manager/background/js/media_import_handler_unittest.js b/ui/file_manager/file_manager/background/js/media_import_handler_unittest.js
index 90ed9657a..f2d77aa 100644
--- a/ui/file_manager/file_manager/background/js/media_import_handler_unittest.js
+++ b/ui/file_manager/file_manager/background/js/media_import_handler_unittest.js
@@ -97,7 +97,7 @@
   importHistory = new importer.TestImportHistory();
   driveSyncHandler = new MockDriveSyncHandler();
   importer.setupTestLogger();
-  mediaImporter = new importer.MediaImportHandler(
+  mediaImporter = new importer.MediaImportHandlerImpl(
       progressCenter, importHistory, dispositionChecker, driveSyncHandler);
 
   // Setup the copy destination.
@@ -176,7 +176,7 @@
     }
     return Promise.resolve(importer.Disposition.ORIGINAL);
   };
-  mediaImporter = new importer.MediaImportHandler(
+  mediaImporter = new importer.MediaImportHandlerImpl(
       progressCenter, importHistory, dispositionChecker, driveSyncHandler);
   const scanResult = new TestScanResult(media);
   const importTask = mediaImporter.importFromScanResult(
@@ -602,23 +602,72 @@
 
 /**
  * Replaces fileOperationUtil.copyTo with a mock for testing.
- * @constructor
  */
-function MockCopyTo() {
-  /** @type {!Array<!MockCopyTo.CopyInfo>} */
-  this.copiedFiles = [];
+class MockCopyTo {
+  constructor() {
+    /** @type {!Array<!MockCopyTo.CopyInfo>} */
+    this.copiedFiles = [];
 
-  // Replace fileOperationUtil.copyTo with our mock test function.
-  fileOperationUtil.copyTo =
-      /** @type {function(*)} */ (this.copyTo_.bind(this));
+    // Replace fileOperationUtil.copyTo with our mock test function.
+    fileOperationUtil.copyTo =
+        /** @type {function(*)} */ (this.copyTo_.bind(this));
 
-  /** @private {boolean} */
-  this.simulateError_ = false;
+    /** @private {boolean} */
+    this.simulateError_ = false;
 
-  this.entryChangedCallback_ = null;
-  this.progressCallback_ = null;
-  this.successCallback_ = null;
-  this.errorCallback_ = null;
+    this.entryChangedCallback_ = null;
+    this.progressCallback_ = null;
+    this.successCallback_ = null;
+    this.errorCallback_ = null;
+  }
+
+  /**
+   * Makes the mock copier simulate an error the next time copyTo_ is called.
+   */
+  simulateOneError() {
+    this.simulateError_ = true;
+  }
+
+  /**
+   * A mock to replace fileOperationUtil.copyTo.  See the original for details.
+   * @param {!Entry} source
+   * @param {!DirectoryEntry} parent
+   * @param {string} newName
+   * @param {function(string, Entry)} entryChangedCallback
+   * @param {function(string, number)} progressCallback
+   * @param {function(Entry)} successCallback
+   * @param {function(Error)} errorCallback
+   */
+  copyTo_(
+      source, parent, newName, entryChangedCallback, progressCallback,
+      successCallback, errorCallback) {
+    this.entryChangedCallback_ = entryChangedCallback;
+    this.progressCallback_ = progressCallback;
+    this.successCallback_ = successCallback;
+    this.errorCallback_ = errorCallback;
+
+    if (this.simulateError_) {
+      this.simulateError_ = false;
+      const error = new Error('test error');
+      this.errorCallback_(error);
+      return;
+    }
+
+    // Log the copy details.
+    this.copiedFiles.push(/** @type {!MockCopyTo.CopyInfo} */ ({
+      source: source,
+      destination: parent,
+      newName: newName,
+    }));
+
+    // Copy the file.
+    const copyErrorCallback = /** @type {!function(FileError):*} */
+        (this.errorCallback_.bind(this));
+    source.copyTo(parent, newName, newEntry => {
+      this.entryChangedCallback_(source.toURL(), parent);
+      this.successCallback_(newEntry);
+    }, copyErrorCallback);
+  }
 }
 
 /**
@@ -629,51 +678,3 @@
  * }}
  */
 MockCopyTo.CopyInfo;
-
-/**
- * Makes the mock copier simulate an error the next time copyTo_ is called.
- */
-MockCopyTo.prototype.simulateOneError = function() {
-  this.simulateError_ = true;
-};
-
-/**
- * A mock to replace fileOperationUtil.copyTo.  See the original for details.
- * @param {!Entry} source
- * @param {!DirectoryEntry} parent
- * @param {string} newName
- * @param {function(string, Entry)} entryChangedCallback
- * @param {function(string, number)} progressCallback
- * @param {function(Entry)} successCallback
- * @param {function(Error)} errorCallback
- */
-MockCopyTo.prototype.copyTo_ = function(
-    source, parent, newName, entryChangedCallback, progressCallback,
-    successCallback, errorCallback) {
-  this.entryChangedCallback_ = entryChangedCallback;
-  this.progressCallback_ = progressCallback;
-  this.successCallback_ = successCallback;
-  this.errorCallback_ = errorCallback;
-
-  if (this.simulateError_) {
-    this.simulateError_ = false;
-    const error = new Error('test error');
-    this.errorCallback_(error);
-    return;
-  }
-
-  // Log the copy details.
-  this.copiedFiles.push(/** @type {!MockCopyTo.CopyInfo} */ ({
-    source: source,
-    destination: parent,
-    newName: newName,
-  }));
-
-  // Copy the file.
-  const copyErrorCallback = /** @type {!function(FileError):*} */
-      (this.errorCallback_.bind(this));
-  source.copyTo(parent, newName, newEntry => {
-    this.entryChangedCallback_(source.toURL(), parent);
-    this.successCallback_(newEntry);
-  }, copyErrorCallback);
-};
diff --git a/ui/file_manager/file_manager/background/js/progress_center.js b/ui/file_manager/file_manager/background/js/progress_center.js
index 1cc9446d..eb04303 100644
--- a/ui/file_manager/file_manager/background/js/progress_center.js
+++ b/ui/file_manager/file_manager/background/js/progress_center.js
@@ -25,7 +25,7 @@
 
     /**
      * List of panel UI managed by the progress center.
-     * @private @const {!Array<ProgressCenterPanel>}
+     * @private @const {!Array<ProgressCenterPanelInterface>}
      */
     this.panels_ = [];
   }
@@ -86,7 +86,7 @@
 
   /**
    * Adds a panel UI to the notification center.
-   * @param {ProgressCenterPanel} panel Panel UI.
+   * @param {ProgressCenterPanelInterface} panel Panel UI.
    */
   addPanel(panel) {
     if (this.panels_.indexOf(panel) !== -1) {
@@ -110,7 +110,7 @@
 
   /**
    * Removes a panel UI from the notification center.
-   * @param {ProgressCenterPanel} panel Panel UI.
+   * @param {ProgressCenterPanelInterface} panel Panel UI.
    */
   removePanel(panel) {
     const index = this.panels_.indexOf(panel);
diff --git a/ui/file_manager/file_manager/background/js/task_queue.js b/ui/file_manager/file_manager/background/js/task_queue.js
index 3e22b5e..b8abce1 100644
--- a/ui/file_manager/file_manager/background/js/task_queue.js
+++ b/ui/file_manager/file_manager/background/js/task_queue.js
@@ -5,6 +5,8 @@
 // Namespace
 var importer = importer || {};
 
+importer.TaskQueue = importer.TaskQueue || {};
+
 /**
  * A queue of tasks.  Tasks (subclasses of TaskQueue.Task) can be pushed onto
  * the queue.  The queue becomes active whenever it is not empty, and it will
@@ -15,189 +17,148 @@
  * be triggered whenever the queue transitions between the active and idle
  * states.
  *
- * @constructor
- * @struct
- * @return undefined
+ * @implements {importer.TaskQueue}
  */
-importer.TaskQueue = function() {
-  /** @private {!Array<!importer.TaskQueue.Task>} */
-  this.tasks_ = [];
+importer.TaskQueueImpl = class {
+  constructor() {
+    /** @private {!Array<!importer.TaskQueue.Task>} */
+    this.tasks_ = [];
 
-  /** @private {!Array<!function(string, !importer.TaskQueue.Task)>} */
-  this.updateCallbacks_ = [];
+    /** @private {!Array<!function(string, !importer.TaskQueue.Task)>} */
+    this.updateCallbacks_ = [];
 
-  /** @private {?function()} */
-  this.activeCallback_ = null;
+    /** @private {?function()} */
+    this.activeCallback_ = null;
 
-  /** @private {?function()} */
-  this.idleCallback_ = null;
+    /** @private {?function()} */
+    this.idleCallback_ = null;
 
-  /** @private {boolean} */
-  this.active_ = false;
-};
+    /** @private {boolean} */
+    this.active_ = false;
+  }
 
-/**
- * @enum {string}
- */
-importer.TaskQueue.UpdateType = {
-  PROGRESS: 'PROGRESS',
-  COMPLETE: 'COMPLETE',
-  ERROR: 'ERROR',
-  CANCELED: 'CANCELED'
-};
+  /**
+   * @param {!importer.TaskQueue.Task} task
+   */
+  queueTask(task) {
+    // The Tasks that are pushed onto the queue aren't required to be inherently
+    // asynchronous.  This code force task execution to occur asynchronously.
+    Promise.resolve().then(() => {
+      task.addObserver(this.onTaskUpdate_.bind(this, task));
+      this.tasks_.push(task);
+      // If more than one task is queued, then the queue is already running.
+      if (this.tasks_.length === 1) {
+        this.runPending_();
+      }
+    });
+  }
 
-/**
- * @param {!importer.TaskQueue.Task} task
- */
-importer.TaskQueue.prototype.queueTask = function(task) {
-  // The Tasks that are pushed onto the queue aren't required to be inherently
-  // asynchronous.  This code force task execution to occur asynchronously.
-  Promise.resolve().then(() => {
-    task.addObserver(this.onTaskUpdate_.bind(this, task));
-    this.tasks_.push(task);
-    // If more than one task is queued, then the queue is already running.
-    if (this.tasks_.length === 1) {
+  /**
+   * Sets a callback to be triggered when a task updates.
+   * @param {function(string, !importer.TaskQueue.Task)} callback
+   */
+  addUpdateCallback(callback) {
+    this.updateCallbacks_.push(callback);
+  }
+
+  /**
+   * Sets a callback that is triggered each time the queue goes from an idle
+   * (i.e. empty with no running tasks) to an active (i.e. having a running
+   * task) state.
+   * @param {function()} callback
+   */
+  setActiveCallback(callback) {
+    this.activeCallback_ = callback;
+  }
+
+  /**
+   * Sets a callback that is triggered each time the queue goes from an active
+   * to an idle state.  Also see #setActiveCallback.
+   * @param {function()} callback
+   */
+  setIdleCallback(callback) {
+    this.idleCallback_ = callback;
+  }
+
+  /**
+   * Sends out notifications when a task updates.  This is meant to be called by
+   * the running tasks owned by this queue.
+   * @param {!importer.TaskQueue.Task} task
+   * @param {!importer.TaskQueue.UpdateType} updateType
+   * @private
+   */
+  onTaskUpdate_(task, updateType) {
+    // Send a task update to clients.
+    this.updateCallbacks_.forEach(callback => {
+      callback.call(null, updateType, task);
+    });
+
+    // If the task update is a terminal one, move on to the next task.
+    const UpdateType = importer.TaskQueue.UpdateType;
+    if (updateType === UpdateType.COMPLETE ||
+        updateType === UpdateType.CANCELED) {
+      // Assumption: the currently running task is at the head of the queue.
+      console.assert(
+          this.tasks_[0] === task,
+          'Only tasks that are at the head of the queue should be active');
+      // Remove the completed task from the queue.
+      this.tasks_.shift();
+      // Run the next thing in the queue.
       this.runPending_();
     }
-  });
-};
-
-/**
- * Sets a callback to be triggered when a task updates.
- * @param {function(string, !importer.TaskQueue.Task)} callback
- */
-importer.TaskQueue.prototype.addUpdateCallback = function(callback) {
-  this.updateCallbacks_.push(callback);
-};
-
-/**
- * Sets a callback that is triggered each time the queue goes from an idle
- * (i.e. empty with no running tasks) to an active (i.e. having a running task)
- * state.
- * @param {function()} callback
- */
-importer.TaskQueue.prototype.setActiveCallback = function(callback) {
-  this.activeCallback_ = callback;
-};
-
-/**
- * Sets a callback that is triggered each time the queue goes from an active to
- * an idle state.  Also see #setActiveCallback.
- * @param {function()} callback
- */
-importer.TaskQueue.prototype.setIdleCallback = function(callback) {
-  this.idleCallback_ = callback;
-};
-
-/**
- * Sends out notifications when a task updates.  This is meant to be called by
- * the running tasks owned by this queue.
- * @param {!importer.TaskQueue.Task} task
- * @param {!importer.TaskQueue.UpdateType} updateType
- * @private
- */
-importer.TaskQueue.prototype.onTaskUpdate_ = function(task, updateType) {
-  // Send a task update to clients.
-  this.updateCallbacks_.forEach(callback => {
-    callback.call(null, updateType, task);
-  });
-
-  // If the task update is a terminal one, move on to the next task.
-  const UpdateType = importer.TaskQueue.UpdateType;
-  if (updateType === UpdateType.COMPLETE ||
-      updateType === UpdateType.CANCELED) {
-    // Assumption: the currently running task is at the head of the queue.
-    console.assert(
-        this.tasks_[0] === task,
-        'Only tasks that are at the head of the queue should be active');
-    // Remove the completed task from the queue.
-    this.tasks_.shift();
-    // Run the next thing in the queue.
-    this.runPending_();
   }
-};
 
-/**
- * Wakes the task queue up and runs the next pending task, or makes the queue go
- * back to sleep if no tasks are pending.
- * @private
- */
-importer.TaskQueue.prototype.runPending_ = function() {
-  if (this.tasks_.length === 0) {
-    // All done - go back to idle.
-    this.active_ = false;
-    if (this.idleCallback_) {
-      this.idleCallback_();
+  /**
+   * Wakes the task queue up and runs the next pending task, or makes the queue
+   * go back to sleep if no tasks are pending.
+   * @private
+   */
+  runPending_() {
+    if (this.tasks_.length === 0) {
+      // All done - go back to idle.
+      this.active_ = false;
+      if (this.idleCallback_) {
+        this.idleCallback_();
+      }
+      return;
     }
-    return;
-  }
 
-  if (!this.active_) {
-    // If the queue is currently idle, transition to active state.
-    this.active_ = true;
-    if (this.activeCallback_) {
-      this.activeCallback_();
+    if (!this.active_) {
+      // If the queue is currently idle, transition to active state.
+      this.active_ = true;
+      if (this.activeCallback_) {
+        this.activeCallback_();
+      }
     }
-  }
 
-  const nextTask = this.tasks_[0];
-  nextTask.run();
+    const nextTask = this.tasks_[0];
+    nextTask.run();
+  }
 };
 
-/**
- * Interface for any Task that is to run on the TaskQueue.
- * @interface
- */
-importer.TaskQueue.Task = function() {};
-
-/**
- * A callback that is triggered whenever an update is reported on the observed
- * task.  The first argument is a string specifying the type of the update.
- * Standard values used by all tasks are enumerated in
- * importer.TaskQueue.UpdateType, but child classes may add supplementary update
- * types of their own.  The second argument is an Object containing
- * supplementary information pertaining to the update.
- * @typedef {function(!importer.TaskQueue.UpdateType, Object=)}
- */
-importer.TaskQueue.Task.Observer;
-
-/**
- * Sets the TaskQueue that will own this task.  The TaskQueue must call this
- * prior to enqueuing a Task.
- * @param {!importer.TaskQueue.Task.Observer} observer A callback that
- *     will be triggered each time the task has a status update.
- */
-importer.TaskQueue.Task.prototype.addObserver;
-
-/**
- * Performs the actual work of the Task.  Child classes should implement this.
- */
-importer.TaskQueue.Task.prototype.run;
 
 /**
  * Base class for importer tasks.
- * @constructor
  * @implements {importer.TaskQueue.Task}
- *
- * @param {string} taskId
  */
-importer.TaskQueue.BaseTask = function(taskId) {
-  /** @protected {string} */
-  this.taskId_ = taskId;
+importer.TaskQueue.BaseTaskImpl = class {
+  /**
+   * @param {string} taskId
+   */
+  constructor(taskId) {
+    /** @protected {string} */
+    this.taskId_ = taskId;
 
-  /** @private {!Array<!importer.TaskQueue.Task.Observer>} */
-  this.observers_ = [];
+    /** @private {!Array<!importer.TaskQueue.Task.Observer>} */
+    this.observers_ = [];
 
-  /** @private {!importer.Resolver<!importer.TaskQueue.UpdateType>} */
-  this.finishedResolver_ = new importer.Resolver();
-};
-
-/** @struct */
-importer.TaskQueue.BaseTask.prototype = {
+    /** @private {!importer.Resolver<!importer.TaskQueue.UpdateType>} */
+    this.finishedResolver_ = new importer.Resolver();
+  }
   /** @return {string} The task ID. */
   get taskId() {
     return this.taskId_;
-  },
+  }
 
   /**
    * @return {!Promise<!importer.TaskQueue.UpdateType>} Resolves when task
@@ -206,29 +167,29 @@
   get whenFinished() {
     return this.finishedResolver_.promise;
   }
-};
 
-/** @override */
-importer.TaskQueue.BaseTask.prototype.addObserver = function(observer) {
-  this.observers_.push(observer);
-};
-
-/** @override */
-importer.TaskQueue.BaseTask.prototype.run = () => {};
-
-/**
- * @param {importer.TaskQueue.UpdateType} updateType
- * @param {Object=} opt_data
- * @protected
- */
-importer.TaskQueue.BaseTask.prototype.notify = function(updateType, opt_data) {
-  switch (updateType) {
-    case importer.TaskQueue.UpdateType.CANCELED:
-    case importer.TaskQueue.UpdateType.COMPLETE:
-      this.finishedResolver_.resolve(updateType);
+  /** @override */
+  addObserver(observer) {
+    this.observers_.push(observer);
   }
 
-  this.observers_.forEach(callback => {
-    callback.call(null, updateType, opt_data);
-  });
+  /** @override */
+  run() {}
+
+  /**
+   * @param {importer.TaskQueue.UpdateType} updateType
+   * @param {Object=} opt_data
+   * @protected
+   */
+  notify(updateType, opt_data) {
+    switch (updateType) {
+      case importer.TaskQueue.UpdateType.CANCELED:
+      case importer.TaskQueue.UpdateType.COMPLETE:
+        this.finishedResolver_.resolve(updateType);
+    }
+
+    this.observers_.forEach(callback => {
+      callback.call(null, updateType, opt_data);
+    });
+  }
 };
diff --git a/ui/file_manager/file_manager/background/js/task_queue_unittest.js b/ui/file_manager/file_manager/background/js/task_queue_unittest.js
index 78ecb850..022d09c 100644
--- a/ui/file_manager/file_manager/background/js/task_queue_unittest.js
+++ b/ui/file_manager/file_manager/background/js/task_queue_unittest.js
@@ -9,7 +9,7 @@
 const updates = {};
 
 function setUp() {
-  queue = new importer.TaskQueue();
+  queue = new importer.TaskQueueImpl();
 
   // Set up a callback to log updates from running tasks.
   for (const updateType in importer.TaskQueue.UpdateType) {
@@ -26,58 +26,58 @@
 
 /**
  * A Task subclass for testing.
- * @constructor
- * @extends {importer.TaskQueue.BaseTask}
- *
- * @param {string} taskId
  */
-const TestTask = function(taskId) {
-  importer.TaskQueue.BaseTask.call(this, taskId);
-
-  /** @type {boolean} */
-  this.wasRun = false;
-
+class TestTask extends importer.TaskQueue.BaseTaskImpl {
   /**
-   * @private {Function}
+   * @param {string} taskId
    */
-  this.runResolver_ = null;
+  constructor(taskId) {
+    super(taskId);
 
-  this.runPromise_ = new Promise(resolve => {
-    this.runResolver_ = resolve;
-  });
-};
-TestTask.prototype.__proto__ = importer.TaskQueue.BaseTask.prototype;
+    /** @type {boolean} */
+    this.wasRun = false;
 
-/** @override */
-TestTask.prototype.run = function() {
-  this.wasRun = true;
-  this.runResolver_(this);
-};
+    /**
+     * @private {Function}
+     */
+    this.runResolver_ = null;
 
-/** Sends a quick error notification. */
-TestTask.prototype.notifyError = function() {
-  this.notify(importer.TaskQueue.UpdateType.ERROR);
-};
+    this.runPromise_ = new Promise(resolve => {
+      this.runResolver_ = resolve;
+    });
+  }
 
-/** Sends a quick completion notification. */
-TestTask.prototype.notifyComplete = function() {
-  this.notify(importer.TaskQueue.UpdateType.COMPLETE);
-};
+  /** @override */
+  run() {
+    this.wasRun = true;
+    this.runResolver_(this);
+  }
 
-/** Sends a quick cancelled notification. */
-TestTask.prototype.notifyCanceled = function() {
-  this.notify(importer.TaskQueue.UpdateType.CANCELED);
-};
+  /** Sends a quick error notification. */
+  notifyError() {
+    this.notify(importer.TaskQueue.UpdateType.ERROR);
+  }
 
-/** Sends a quick progress notification. */
-TestTask.prototype.notifyProgress = function() {
-  this.notify(importer.TaskQueue.UpdateType.PROGRESS);
-};
+  /** Sends a quick completion notification. */
+  notifyComplete() {
+    this.notify(importer.TaskQueue.UpdateType.COMPLETE);
+  }
 
-/** @return {!Promise} A promise that settles once #run is called. */
-TestTask.prototype.whenRun = function() {
-  return this.runPromise_;
-};
+  /** Sends a quick cancelled notification. */
+  notifyCanceled() {
+    this.notify(importer.TaskQueue.UpdateType.CANCELED);
+  }
+
+  /** Sends a quick progress notification. */
+  notifyProgress() {
+    this.notify(importer.TaskQueue.UpdateType.PROGRESS);
+  }
+
+  /** @return {!Promise} A promise that settles once #run is called. */
+  whenRun() {
+    return this.runPromise_;
+  }
+}
 
 // Verifies that a queued task gets run.
 function testRunsTask(callback) {
diff --git a/ui/file_manager/file_manager/common/js/importer_common.js b/ui/file_manager/file_manager/common/js/importer_common.js
index 9c7c31c..e1c3958 100644
--- a/ui/file_manager/file_manager/common/js/importer_common.js
+++ b/ui/file_manager/file_manager/common/js/importer_common.js
@@ -2,9 +2,21 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Shared cloud importer namespace
+// Namespace
 var importer = importer || {};
 
+importer.TaskQueue = importer.TaskQueue || {};
+
+/**
+ * @enum {string}
+ */
+importer.TaskQueue.UpdateType = {
+  PROGRESS: 'PROGRESS',
+  COMPLETE: 'COMPLETE',
+  ERROR: 'ERROR',
+  CANCELED: 'CANCELED'
+};
+
 /** @enum {string} */
 importer.ScanEvent = {
   FINALIZED: 'finalized',
diff --git a/ui/file_manager/file_manager/foreground/js/BUILD.gn b/ui/file_manager/file_manager/foreground/js/BUILD.gn
index 94bd9499..4c1c1563f 100644
--- a/ui/file_manager/file_manager/foreground/js/BUILD.gn
+++ b/ui/file_manager/file_manager/foreground/js/BUILD.gn
@@ -91,6 +91,8 @@
     "../../../externs/background/file_operation_manager.js",
     "../../../externs/background/import_runner.js",
     "../../../externs/background/media_import_handler.js",
+    "../../../externs/background/task_queue.js",
+    "../../../externs/background/duplicate_finder.js",
     "../../../externs/background/media_scanner.js",
     "../../../externs/background/progress_center.js",
     "../../../externs/background_window.js",
@@ -501,6 +503,8 @@
   externs_list = [
     "//ui/file_manager/externs/background/import_runner.js",
     "//ui/file_manager/externs/background/media_import_handler.js",
+    "//ui/file_manager/externs/background/duplicate_finder.js",
+    "//ui/file_manager/externs/background/task_queue.js",
     "//ui/file_manager/externs/command_handler_deps.js",
   ]
 }
diff --git a/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn b/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn
index cf21d33..1752748 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn
+++ b/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn
@@ -443,6 +443,7 @@
     "..:progress_center_item_group",
     "../../../common/js:progress_center_common",
   ]
+  externs_list = [ "//ui/file_manager/externs/progress_center_panel.js" ]
 }
 
 js_library("providers_menu") {
diff --git a/ui/file_manager/file_manager/foreground/js/ui/progress_center_panel.js b/ui/file_manager/file_manager/foreground/js/ui/progress_center_panel.js
index ec60218b..39f4d6f4 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/progress_center_panel.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/progress_center_panel.js
@@ -187,7 +187,7 @@
 
 /**
  * Progress center panel.
- *
+ * @implements {ProgressCenterPanelInterface}
  */
 class ProgressCenterPanel {
   /**
diff --git a/ui/file_manager/file_manager/test/BUILD.gn b/ui/file_manager/file_manager/test/BUILD.gn
index b233a5c7..afd1ad49 100644
--- a/ui/file_manager/file_manager/test/BUILD.gn
+++ b/ui/file_manager/file_manager/test/BUILD.gn
@@ -58,6 +58,7 @@
     "$externs_path/metrics_private.js",
     "//ui/file_manager/externs/background/file_browser_background.js",
     "//ui/file_manager/externs/background/progress_center.js",
+    "//ui/file_manager/externs/progress_center_panel.js",
     "//ui/file_manager/externs/background/crostini.js",
     "//ui/file_manager/externs/entry_location.js",
     "//ui/file_manager/externs/volume_info.js",
diff --git a/ui/ozone/platform/cast/ozone_platform_cast.cc b/ui/ozone/platform/cast/ozone_platform_cast.cc
index 3240ff37..8bf10ff 100644
--- a/ui/ozone/platform/cast/ozone_platform_cast.cc
+++ b/ui/ozone/platform/cast/ozone_platform_cast.cc
@@ -116,10 +116,12 @@
 
   void InitializeUI(const InitParams& params) override {
     device_manager_ = CreateDeviceManager();
-    overlay_manager_ = std::make_unique<OverlayManagerCast>();
     cursor_factory_ = std::make_unique<CursorFactoryOzone>();
     gpu_platform_support_host_.reset(CreateStubGpuPlatformSupportHost());
 
+    if (!params.viz_display_compositor)
+      overlay_manager_ = std::make_unique<OverlayManagerCast>();
+
     // Enable dummy software rendering support if GPU process disabled
     // or if we're an audio-only build.
     // Note: switch is kDisableGpu from content/public/common/content_switches.h
@@ -141,6 +143,9 @@
       surface_factory_ = std::make_unique<SurfaceFactoryCast>();
   }
   void InitializeGPU(const InitParams& params) override {
+    if (params.viz_display_compositor) {
+      overlay_manager_ = std::make_unique<OverlayManagerCast>();
+    }
     surface_factory_ =
         std::make_unique<SurfaceFactoryCast>(std::move(egl_platform_));
   }
diff --git a/ui/ozone/platform/drm/common/drm_util.cc b/ui/ozone/platform/drm/common/drm_util.cc
index be2ea762..a8fc1d9 100644
--- a/ui/ozone/platform/drm/common/drm_util.cc
+++ b/ui/ozone/platform/drm/common/drm_util.cc
@@ -402,8 +402,14 @@
     if (info->crtc()->mode_valid && SameMode(info->crtc()->mode, mode))
       *out_current_mode = modes.back().get();
 
-    if (mode.type & DRM_MODE_TYPE_PREFERRED)
-      *out_native_mode = modes.back().get();
+    if (mode.type & DRM_MODE_TYPE_PREFERRED) {
+      if (*out_native_mode == nullptr) {
+        *out_native_mode = modes.back().get();
+      } else {
+        LOG(WARNING) << "Found more than one preferred modes. The first one "
+                        "will be used.";
+      }
+    }
   }
 
   // If we couldn't find a preferred mode, then try to find a mode that has the
diff --git a/ui/ozone/platform/drm/common/drm_util_unittest.cc b/ui/ozone/platform/drm/common/drm_util_unittest.cc
index 916e1556..1340d3d 100644
--- a/ui/ozone/platform/drm/common/drm_util_unittest.cc
+++ b/ui/ozone/platform/drm/common/drm_util_unittest.cc
@@ -615,6 +615,15 @@
   EXPECT_EQ(extracted_modes[0].get(), current_mode);
   EXPECT_EQ(extracted_modes[2].get(), native_mode);
   EXPECT_EQ(gfx::Size(800, 600), native_mode->size());
+
+  // While KMS specification says there should be at most one preferred mode per
+  // connector, we found monitors with more than one preferred mode. With this
+  // test we make sure the first one is the one used for native_mode.
+  modes_ptr[1].type |= DRM_MODE_TYPE_PREFERRED;
+  extracted_modes = ExtractDisplayModes(&info, active_pixel_size, &current_mode,
+                                        &native_mode);
+  ASSERT_EQ(5u, extracted_modes.size());
+  EXPECT_EQ(extracted_modes[1].get(), native_mode);
 }
 
 }  // namespace ui