diff --git a/DEPS b/DEPS
index ec02f6f..c840c25 100644
--- a/DEPS
+++ b/DEPS
@@ -138,7 +138,7 @@
   # 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': '9893f8e15152e731c602278e529fde2e43091c9e',
+  'skia_revision': '82310316135997d5a0c3d9750b72dbc184c18829',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
@@ -150,15 +150,15 @@
   # 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': '55ca3a5174f2281d656a08a10cbff9bfff57c595',
+  'angle_revision': 'ea49f6f5d4e3fda8003beb43a689a61c64b990b1',
   # 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': '7e95471ae492b057ae3fa48f9ecb2f12a277ec94',
+  'swiftshader_revision': '8ac0bd6cc3e5aaabb904ffe01639ecea4b7b5fde',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': '950a410cdea658a83be9942139a41c3b193f49e5',
+  'pdfium_revision': '3ff3ecc72ae4d9fe90494085cc3f51c49c20e77e',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling BoringSSL
   # and whatever else without interference from each other.
@@ -257,7 +257,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'spv_tools_revision': '43fb2403a679ede45157aac6ea90f16700560700',
+  'spv_tools_revision': 'a8ae579f7a8f4d84be86fe7263d1b6be0e18129f',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -273,7 +273,7 @@
   # 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': '2d4b5294432f254c8ab093ff399cdf9aa59260a6',
+  'dawn_revision': 'fa7228a1fa63163a6f27b9b0a9036d1be27c6dd6',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -436,7 +436,7 @@
     Var('chromium_git') + '/external/github.com/toji/webvr.info.git' + '@' + 'c58ae99b9ff9e2aa4c524633519570bf33536248',
 
   'src/ios/third_party/earl_grey/src': {
-      'url': Var('chromium_git') + '/external/github.com/google/EarlGrey.git' + '@' + '87ffa7ac2517cc8931e4e6ba11714961cbac6dd7',
+      'url': Var('chromium_git') + '/external/github.com/google/EarlGrey.git' + '@' + 'fb25165a5ec573ba31389b16fd43d56ccf7da9c9',
       'condition': 'checkout_ios',
   },
 
@@ -1187,7 +1187,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' +  'a0af62e20b0a6ee8f399da7e4331d22ee3dc1697',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' +  'b4697aa45589d116d9db40a21de69d1365dd7e1c',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1396,7 +1396,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@13d57683aff767f3bd928f252a202502e05c6f7e',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@104f3fc6931f2aeb29ad8445345d513b0259dfb8',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index b124f7b..deeb43a4 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -350,8 +350,8 @@
     "keyboard/virtual_keyboard_controller.h",
     "kiosk_next/kiosk_next_home_controller.cc",
     "kiosk_next/kiosk_next_home_controller.h",
-    "kiosk_next/kiosk_next_shell_controller.cc",
-    "kiosk_next/kiosk_next_shell_controller.h",
+    "kiosk_next/kiosk_next_shell_controller_impl.cc",
+    "kiosk_next/kiosk_next_shell_controller_impl.h",
     "kiosk_next/kiosk_next_shell_observer.h",
     "laser/laser_pointer_controller.cc",
     "laser/laser_pointer_controller.h",
diff --git a/ash/accelerators/accelerator_controller_impl.cc b/ash/accelerators/accelerator_controller_impl.cc
index a99d0468..cdc09042 100644
--- a/ash/accelerators/accelerator_controller_impl.cc
+++ b/ash/accelerators/accelerator_controller_impl.cc
@@ -25,7 +25,7 @@
 #include "ash/ime/ime_controller.h"
 #include "ash/ime/ime_switch_type.h"
 #include "ash/keyboard/ui/keyboard_controller.h"
-#include "ash/kiosk_next/kiosk_next_shell_controller.h"
+#include "ash/kiosk_next/kiosk_next_shell_controller_impl.h"
 #include "ash/magnifier/docked_magnifier_controller_impl.h"
 #include "ash/magnifier/magnification_controller.h"
 #include "ash/media/media_controller_impl.h"
diff --git a/ash/accessibility/accessibility_controller.cc b/ash/accessibility/accessibility_controller.cc
index b50e6df..213c151d 100644
--- a/ash/accessibility/accessibility_controller.cc
+++ b/ash/accessibility/accessibility_controller.cc
@@ -1282,12 +1282,10 @@
 }
 
 void AccessibilityController::SetVirtualKeyboardVisible(bool is_visible) {
-  if (is_visible) {
+  if (is_visible)
     Shell::Get()->ash_keyboard_controller()->ShowKeyboard();
-  } else {
-    Shell::Get()->ash_keyboard_controller()->HideKeyboard(
-        mojom::HideReason::kUser);
-  }
+  else
+    Shell::Get()->ash_keyboard_controller()->HideKeyboard(HideReason::kUser);
 }
 
 }  // namespace ash
diff --git a/ash/app_list/app_list_controller_impl_unittest.cc b/ash/app_list/app_list_controller_impl_unittest.cc
index 3ecb981b..89a4a3a 100644
--- a/ash/app_list/app_list_controller_impl_unittest.cc
+++ b/ash/app_list/app_list_controller_impl_unittest.cc
@@ -143,7 +143,7 @@
 // (https://crbug.com/942084).
 TEST_F(AppListControllerImplTest, HideRoundingCorners) {
   Shell::Get()->ash_keyboard_controller()->SetEnableFlag(
-      keyboard::mojom::KeyboardEnableFlag::kShelfEnabled);
+      keyboard::KeyboardEnableFlag::kShelfEnabled);
 
   // Show the app list view and click on the search box with mouse. So the
   // VirtualKeyboard is shown.
@@ -185,7 +185,7 @@
 // https://crbug.com/944233).
 TEST_F(AppListControllerImplTest, CheckAppListViewBoundsWhenVKeyboardEnabled) {
   Shell::Get()->ash_keyboard_controller()->SetEnableFlag(
-      keyboard::mojom::KeyboardEnableFlag::kShelfEnabled);
+      keyboard::KeyboardEnableFlag::kShelfEnabled);
 
   // Show the AppListView and click on the search box with mouse. So the
   // VirtualKeyboard is shown. Wait until the virtual keyboard shows.
@@ -218,7 +218,7 @@
 // virtual keyboard is dismissed (see https://crbug.com/944133).
 TEST_F(AppListControllerImplTest, CheckAppListViewBoundsWhenDismissVKeyboard) {
   Shell::Get()->ash_keyboard_controller()->SetEnableFlag(
-      keyboard::mojom::KeyboardEnableFlag::kShelfEnabled);
+      keyboard::KeyboardEnableFlag::kShelfEnabled);
 
   // Show the AppListView and click on the search box with mouse so the
   // VirtualKeyboard is shown. Wait until the virtual keyboard shows.
@@ -233,8 +233,7 @@
   EXPECT_TRUE(GetVirtualKeyboardWindow()->IsVisible());
 
   // Close the virtual keyboard. Wait until it is hidden.
-  Shell::Get()->ash_keyboard_controller()->HideKeyboard(
-      mojom::HideReason::kUser);
+  Shell::Get()->ash_keyboard_controller()->HideKeyboard(HideReason::kUser);
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(nullptr, GetVirtualKeyboardWindow());
 
diff --git a/ash/ash_prefs.cc b/ash/ash_prefs.cc
index ade78c0e..ba0d08e 100644
--- a/ash/ash_prefs.cc
+++ b/ash/ash_prefs.cc
@@ -9,7 +9,7 @@
 #include "ash/assistant/assistant_controller.h"
 #include "ash/detachable_base/detachable_base_handler.h"
 #include "ash/display/display_prefs.h"
-#include "ash/kiosk_next/kiosk_next_shell_controller.h"
+#include "ash/kiosk_next/kiosk_next_shell_controller_impl.h"
 #include "ash/login/login_screen_controller.h"
 #include "ash/magnifier/docked_magnifier_controller_impl.h"
 #include "ash/shelf/shelf_controller.h"
@@ -37,7 +37,7 @@
   BluetoothPowerController::RegisterProfilePrefs(registry);
   CapsLockNotificationController::RegisterProfilePrefs(registry, for_test);
   DockedMagnifierControllerImpl::RegisterProfilePrefs(registry, for_test);
-  KioskNextShellController::RegisterProfilePrefs(registry, for_test);
+  KioskNextShellControllerImpl::RegisterProfilePrefs(registry, for_test);
   LoginScreenController::RegisterProfilePrefs(registry, for_test);
   LogoutButtonTray::RegisterProfilePrefs(registry);
   MessageCenterController::RegisterProfilePrefs(registry);
diff --git a/ash/display/screen_orientation_controller_unittest.cc b/ash/display/screen_orientation_controller_unittest.cc
index f5c4c21..844ce6f 100644
--- a/ash/display/screen_orientation_controller_unittest.cc
+++ b/ash/display/screen_orientation_controller_unittest.cc
@@ -745,10 +745,11 @@
     set_start_session(false);
     AshTestBase::SetUp();
 
-    client_ = BindMockKioskNextShellClient();
+    client_ = std::make_unique<MockKioskNextShellClient>();
   }
 
   void TearDown() override {
+    client_.reset();
     home_screen_window_.reset();
     AshTestBase::TearDown();
   }
diff --git a/ash/home_screen/home_screen_presenter.cc b/ash/home_screen/home_screen_presenter.cc
index 2011c9f..ff2b478 100644
--- a/ash/home_screen/home_screen_presenter.cc
+++ b/ash/home_screen/home_screen_presenter.cc
@@ -8,7 +8,7 @@
 
 #include "ash/home_screen/home_screen_controller.h"
 #include "ash/home_screen/home_screen_delegate.h"
-#include "ash/kiosk_next/kiosk_next_shell_controller.h"
+#include "ash/kiosk_next/kiosk_next_shell_controller_impl.h"
 #include "ash/shell.h"
 #include "base/bind.h"
 #include "base/bind_helpers.h"
diff --git a/ash/keyboard/ash_keyboard_controller.cc b/ash/keyboard/ash_keyboard_controller.cc
index 1768166..0e603de 100644
--- a/ash/keyboard/ash_keyboard_controller.cc
+++ b/ash/keyboard/ash_keyboard_controller.cc
@@ -17,9 +17,8 @@
 #include "ui/gfx/geometry/rect.h"
 #include "ui/wm/core/coordinate_conversion.h"
 
-using keyboard::mojom::KeyboardConfig;
-using keyboard::mojom::KeyboardConfigPtr;
-using keyboard::mojom::KeyboardEnableFlag;
+using keyboard::KeyboardConfig;
+using keyboard::KeyboardEnableFlag;
 
 namespace ash {
 
@@ -38,11 +37,6 @@
     session_controller_->RemoveObserver(this);
 }
 
-void AshKeyboardController::BindRequest(
-    mojom::KeyboardControllerRequest request) {
-  bindings_.AddBinding(this, std::move(request));
-}
-
 void AshKeyboardController::CreateVirtualKeyboard(
     std::unique_ptr<keyboard::KeyboardUIFactory> keyboard_ui_factory) {
   DCHECK(keyboard_ui_factory);
@@ -65,26 +59,21 @@
 void AshKeyboardController::SendOnKeyboardVisibleBoundsChanged(
     const gfx::Rect& screen_bounds) {
   DVLOG(1) << "OnKeyboardVisibleBoundsChanged: " << screen_bounds.ToString();
-  // Pass the bounds in screen coordinates over mojo.
-  observers_.ForAllPtrs(
-      [&screen_bounds](mojom::KeyboardControllerObserver* observer) {
-        observer->OnKeyboardVisibleBoundsChanged(screen_bounds);
-      });
+  for (auto& observer : observers_)
+    observer.OnKeyboardVisibleBoundsChanged(screen_bounds);
 }
 
 void AshKeyboardController::SendOnLoadKeyboardContentsRequested() {
-  observers_.ForAllPtrs([](mojom::KeyboardControllerObserver* observer) {
-    observer->OnLoadKeyboardContentsRequested();
-  });
+  for (auto& observer : observers_)
+    observer.OnLoadKeyboardContentsRequested();
 }
 
 void AshKeyboardController::SendOnKeyboardUIDestroyed() {
-  observers_.ForAllPtrs([](mojom::KeyboardControllerObserver* observer) {
-    observer->OnKeyboardUIDestroyed();
-  });
+  for (auto& observer : observers_)
+    observer.OnKeyboardUIDestroyed();
 }
 
-// mojom::KeyboardController
+// ash::KeyboardController
 
 void AshKeyboardController::KeyboardContentsLoaded(
     const gfx::Size& size) {
@@ -93,13 +82,12 @@
 
 void AshKeyboardController::GetKeyboardConfig(
     GetKeyboardConfigCallback callback) {
-  std::move(callback).Run(
-      KeyboardConfig::New(keyboard_controller_->keyboard_config()));
+  std::move(callback).Run(keyboard_controller_->keyboard_config());
 }
 
 void AshKeyboardController::SetKeyboardConfig(
-    KeyboardConfigPtr keyboard_config) {
-  keyboard_controller_->UpdateKeyboardConfig(*keyboard_config);
+    const KeyboardConfig& keyboard_config) {
+  keyboard_controller_->UpdateKeyboardConfig(keyboard_config);
 }
 
 void AshKeyboardController::IsKeyboardEnabled(
@@ -116,10 +104,10 @@
 }
 
 void AshKeyboardController::GetEnableFlags(GetEnableFlagsCallback callback) {
-  const std::set<keyboard::mojom::KeyboardEnableFlag>& keyboard_enable_flags =
+  const std::set<keyboard::KeyboardEnableFlag>& keyboard_enable_flags =
       keyboard_controller_->keyboard_enable_flags();
-  std::vector<keyboard::mojom::KeyboardEnableFlag> flags(
-      keyboard_enable_flags.begin(), keyboard_enable_flags.end());
+  std::vector<keyboard::KeyboardEnableFlag> flags(keyboard_enable_flags.begin(),
+                                                  keyboard_enable_flags.end());
   std::move(callback).Run(std::move(flags));
 }
 
@@ -144,21 +132,21 @@
     keyboard_controller_->ShowKeyboard(false /* lock */);
 }
 
-void AshKeyboardController::HideKeyboard(mojom::HideReason reason) {
+void AshKeyboardController::HideKeyboard(HideReason reason) {
   if (!keyboard_controller_->IsEnabled())
     return;
   switch (reason) {
-    case mojom::HideReason::kUser:
+    case HideReason::kUser:
       keyboard_controller_->HideKeyboardByUser();
       break;
-    case mojom::HideReason::kSystem:
+    case HideReason::kSystem:
       keyboard_controller_->HideKeyboardExplicitlyBySystem();
       break;
   }
 }
 
 void AshKeyboardController::SetContainerType(
-    keyboard::mojom::ContainerType container_type,
+    keyboard::ContainerType container_type,
     const base::Optional<gfx::Rect>& target_bounds,
     SetContainerTypeCallback callback) {
   keyboard_controller_->SetContainerType(container_type, target_bounds,
@@ -187,10 +175,8 @@
 }
 
 void AshKeyboardController::AddObserver(
-    mojom::KeyboardControllerObserverAssociatedPtrInfo observer) {
-  mojom::KeyboardControllerObserverAssociatedPtr observer_ptr;
-  observer_ptr.Bind(std::move(observer));
-  observers_.AddPtr(std::move(observer_ptr));
+    ash::KeyboardControllerObserver* observer) {
+  observers_.AddObserver(observer);
 }
 
 // SessionObserver
@@ -226,18 +212,14 @@
 }
 
 void AshKeyboardController::OnKeyboardConfigChanged() {
-  KeyboardConfigPtr config =
-      KeyboardConfig::New(keyboard_controller_->keyboard_config());
-  observers_.ForAllPtrs([&config](mojom::KeyboardControllerObserver* observer) {
-    observer->OnKeyboardConfigChanged(config.Clone());
-  });
+  KeyboardConfig config = keyboard_controller_->keyboard_config();
+  for (auto& observer : observers_)
+    observer.OnKeyboardConfigChanged(config);
 }
 
 void AshKeyboardController::OnKeyboardVisibilityStateChanged(bool is_visible) {
-  observers_.ForAllPtrs(
-      [is_visible](mojom::KeyboardControllerObserver* observer) {
-        observer->OnKeyboardVisibilityChanged(is_visible);
-      });
+  for (auto& observer : observers_)
+    observer.OnKeyboardVisibilityChanged(is_visible);
 }
 
 void AshKeyboardController::OnKeyboardVisibleBoundsChanged(
@@ -248,27 +230,22 @@
 void AshKeyboardController::OnKeyboardWorkspaceOccludedBoundsChanged(
     const gfx::Rect& screen_bounds) {
   DVLOG(1) << "OnKeyboardOccludedBoundsChanged: " << screen_bounds.ToString();
-  // Pass the bounds in screen coordinates over mojo.
-  observers_.ForAllPtrs(
-      [&screen_bounds](mojom::KeyboardControllerObserver* observer) {
-        observer->OnKeyboardOccludedBoundsChanged(screen_bounds);
-      });
+  for (auto& observer : observers_)
+    observer.OnKeyboardOccludedBoundsChanged(screen_bounds);
 }
 
 void AshKeyboardController::OnKeyboardEnableFlagsChanged(
-    std::set<keyboard::mojom::KeyboardEnableFlag>& keyboard_enable_flags) {
-  std::vector<keyboard::mojom::KeyboardEnableFlag> flags(
-      keyboard_enable_flags.begin(), keyboard_enable_flags.end());
-  observers_.ForAllPtrs([&flags](mojom::KeyboardControllerObserver* observer) {
-    observer->OnKeyboardEnableFlagsChanged(flags);
-  });
+    const std::set<keyboard::KeyboardEnableFlag>& keyboard_enable_flags) {
+  std::vector<keyboard::KeyboardEnableFlag> flags(keyboard_enable_flags.begin(),
+                                                  keyboard_enable_flags.end());
+  for (auto& observer : observers_) {
+    observer.OnKeyboardEnableFlagsChanged(flags);
+  }
 }
 
 void AshKeyboardController::OnKeyboardEnabledChanged(bool is_enabled) {
-  observers_.ForAllPtrs(
-      [is_enabled](mojom::KeyboardControllerObserver* observer) {
-        observer->OnKeyboardEnabledChanged(is_enabled);
-      });
+  for (auto& observer : observers_)
+    observer.OnKeyboardEnabledChanged(is_enabled);
 }
 
 }  // namespace ash
diff --git a/ash/keyboard/ash_keyboard_controller.h b/ash/keyboard/ash_keyboard_controller.h
index 8132fcf2..24a4bb1 100644
--- a/ash/keyboard/ash_keyboard_controller.h
+++ b/ash/keyboard/ash_keyboard_controller.h
@@ -9,11 +9,9 @@
 
 #include "ash/ash_export.h"
 #include "ash/keyboard/ui/keyboard_controller_observer.h"
-#include "ash/public/interfaces/keyboard_controller.mojom.h"
+#include "ash/public/cpp/keyboard/keyboard_controller.h"
 #include "ash/session/session_observer.h"
 #include "base/macros.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
-#include "mojo/public/cpp/bindings/interface_ptr_set.h"
 
 namespace gfx {
 class Rect;
@@ -30,11 +28,12 @@
 class VirtualKeyboardController;
 
 // Contains and observes a keyboard::KeyboardController instance. Ash specific
-// behavior, including implementing the mojo interface, is implemented in this
-// class. TODO(stevenjb): Consider re-factoring keyboard::KeyboardController so
-// that this can inherit from that class instead.
+// behavior, including implementing the public interface, is implemented in this
+// class. TODO(shend): Consider re-factoring keyboard::KeyboardController so
+// that this can inherit from that class instead. Rename this to
+// KeyboardControllerImpl.
 class ASH_EXPORT AshKeyboardController
-    : public mojom::KeyboardController,
+    : public ash::KeyboardController,
       public keyboard::KeyboardControllerObserver,
       public SessionObserver {
  public:
@@ -42,9 +41,6 @@
   explicit AshKeyboardController(SessionControllerImpl* session_controller);
   ~AshKeyboardController() override;
 
-  // Called from RegisterInterfaces to bind this to the Ash service.
-  void BindRequest(mojom::KeyboardControllerRequest request);
-
   // Create or destroy the virtual keyboard. Called from Shell. TODO(stevenjb):
   // Fix dependencies so that the virtual keyboard can be created with the
   // keyboard controller.
@@ -52,34 +48,33 @@
       std::unique_ptr<keyboard::KeyboardUIFactory> keyboard_ui_factory);
   void DestroyVirtualKeyboard();
 
-  // Forwards events to mojo observers.
+  // Forwards events to observers.
   void SendOnKeyboardVisibleBoundsChanged(const gfx::Rect& screen_bounds);
   void SendOnLoadKeyboardContentsRequested();
   void SendOnKeyboardUIDestroyed();
 
-  // mojom::KeyboardController:
+  // ash::KeyboardController:
   void KeyboardContentsLoaded(const gfx::Size& size) override;
   void GetKeyboardConfig(GetKeyboardConfigCallback callback) override;
   void SetKeyboardConfig(
-      keyboard::mojom::KeyboardConfigPtr keyboard_config) override;
+      const keyboard::KeyboardConfig& keyboard_config) override;
   void IsKeyboardEnabled(IsKeyboardEnabledCallback callback) override;
-  void SetEnableFlag(keyboard::mojom::KeyboardEnableFlag flag) override;
-  void ClearEnableFlag(keyboard::mojom::KeyboardEnableFlag flag) override;
+  void SetEnableFlag(keyboard::KeyboardEnableFlag flag) override;
+  void ClearEnableFlag(keyboard::KeyboardEnableFlag flag) override;
   void GetEnableFlags(GetEnableFlagsCallback callback) override;
   void ReloadKeyboardIfNeeded() override;
   void RebuildKeyboardIfEnabled() override;
   void IsKeyboardVisible(IsKeyboardVisibleCallback callback) override;
   void ShowKeyboard() override;
-  void HideKeyboard(mojom::HideReason reason) override;
-  void SetContainerType(keyboard::mojom::ContainerType container_type,
+  void HideKeyboard(HideReason reason) override;
+  void SetContainerType(keyboard::ContainerType container_type,
                         const base::Optional<gfx::Rect>& target_bounds,
                         SetContainerTypeCallback callback) override;
   void SetKeyboardLocked(bool locked) override;
   void SetOccludedBounds(const std::vector<gfx::Rect>& bounds) override;
   void SetHitTestBounds(const std::vector<gfx::Rect>& bounds) override;
   void SetDraggableArea(const gfx::Rect& bounds) override;
-  void AddObserver(
-      mojom::KeyboardControllerObserverAssociatedPtrInfo observer) override;
+  void AddObserver(ash::KeyboardControllerObserver* observer) override;
 
   // SessionObserver:
   void OnSessionStateChanged(session_manager::SessionState state) override;
@@ -105,15 +100,14 @@
   void OnKeyboardWorkspaceOccludedBoundsChanged(
       const gfx::Rect& screen_bounds) override;
   void OnKeyboardEnableFlagsChanged(
-      std::set<keyboard::mojom::KeyboardEnableFlag>& keyboard_enable_flags)
+      const std::set<keyboard::KeyboardEnableFlag>& keyboard_enable_flags)
       override;
   void OnKeyboardEnabledChanged(bool is_enabled) override;
 
   SessionControllerImpl* session_controller_;  // unowned
   std::unique_ptr<keyboard::KeyboardController> keyboard_controller_;
   std::unique_ptr<VirtualKeyboardController> virtual_keyboard_controller_;
-  mojo::BindingSet<mojom::KeyboardController> bindings_;
-  mojo::AssociatedInterfacePtrSet<mojom::KeyboardControllerObserver> observers_;
+  base::ObserverList<ash::KeyboardControllerObserver>::Unchecked observers_;
 
   DISALLOW_COPY_AND_ASSIGN(AshKeyboardController);
 };
diff --git a/ash/keyboard/ash_keyboard_controller_unittest.cc b/ash/keyboard/ash_keyboard_controller_unittest.cc
index 70d8a12..9ac42c1 100644
--- a/ash/keyboard/ash_keyboard_controller_unittest.cc
+++ b/ash/keyboard/ash_keyboard_controller_unittest.cc
@@ -10,8 +10,8 @@
 #include "ash/keyboard/ui/container_behavior.h"
 #include "ash/keyboard/ui/keyboard_controller.h"
 #include "ash/keyboard/ui/test/keyboard_test_util.h"
+#include "ash/public/cpp/keyboard/keyboard_controller.h"
 #include "ash/public/cpp/test/test_keyboard_controller_observer.h"
-#include "ash/public/interfaces/keyboard_controller.mojom.h"
 #include "ash/shell.h"
 #include "ash/test/ash_test_base.h"
 #include "ash/test/ash_test_helper.h"
@@ -19,63 +19,55 @@
 #include "base/run_loop.h"
 #include "base/stl_util.h"
 #include "base/test/scoped_task_environment.h"
-#include "mojo/public/cpp/bindings/associated_binding.h"
-#include "services/service_manager/public/cpp/connector.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/aura/window.h"
 #include "ui/display/manager/display_manager.h"
 
-using keyboard::mojom::KeyboardConfig;
-using keyboard::mojom::KeyboardConfigPtr;
-using keyboard::mojom::KeyboardEnableFlag;
+using keyboard::KeyboardConfig;
+using keyboard::KeyboardEnableFlag;
 
 namespace ash {
 
 namespace {
 
+// TODO(shend): Remove this as AshKeyboardController no longer uses mojo.
 class TestClient {
  public:
-  explicit TestClient(service_manager::Connector* connector) {
-    connector->BindInterface("test", &keyboard_controller_ptr_);
-  }
+  explicit TestClient()
+      : keyboard_controller_(Shell::Get()->ash_keyboard_controller()) {}
 
   ~TestClient() = default;
 
   bool IsKeyboardEnabled() {
-    keyboard_controller_ptr_->IsKeyboardEnabled(base::BindOnce(
+    keyboard_controller_->IsKeyboardEnabled(base::BindOnce(
         &TestClient::OnIsKeyboardEnabled, base::Unretained(this)));
-    keyboard_controller_ptr_.FlushForTesting();
     return is_enabled_;
   }
 
   void GetKeyboardConfig() {
-    keyboard_controller_ptr_->GetKeyboardConfig(base::BindOnce(
+    keyboard_controller_->GetKeyboardConfig(base::BindOnce(
         &TestClient::OnGetKeyboardConfig, base::Unretained(this)));
-    keyboard_controller_ptr_.FlushForTesting();
   }
 
-  void SetKeyboardConfig(KeyboardConfigPtr config) {
-    keyboard_controller_ptr_->SetKeyboardConfig(std::move(config));
-    keyboard_controller_ptr_.FlushForTesting();
+  void SetKeyboardConfig(KeyboardConfig config) {
+    keyboard_controller_->SetKeyboardConfig(std::move(config));
   }
 
   void SetEnableFlag(KeyboardEnableFlag flag) {
-    keyboard_controller_ptr_->SetEnableFlag(flag);
-    keyboard_controller_ptr_.FlushForTesting();
+    keyboard_controller_->SetEnableFlag(flag);
   }
 
   void ClearEnableFlag(KeyboardEnableFlag flag) {
-    keyboard_controller_ptr_->ClearEnableFlag(flag);
-    keyboard_controller_ptr_.FlushForTesting();
+    keyboard_controller_->ClearEnableFlag(flag);
   }
 
-  std::vector<keyboard::mojom::KeyboardEnableFlag> GetEnableFlags() {
-    std::vector<keyboard::mojom::KeyboardEnableFlag> enable_flags;
+  std::vector<keyboard::KeyboardEnableFlag> GetEnableFlags() {
+    std::vector<keyboard::KeyboardEnableFlag> enable_flags;
     base::RunLoop run_loop;
-    keyboard_controller_ptr_->GetEnableFlags(base::BindOnce(
-        [](std::vector<keyboard::mojom::KeyboardEnableFlag>* enable_flags,
+    keyboard_controller_->GetEnableFlags(base::BindOnce(
+        [](std::vector<keyboard::KeyboardEnableFlag>* enable_flags,
            base::OnceClosure callback,
-           const std::vector<keyboard::mojom::KeyboardEnableFlag>& flags) {
+           const std::vector<keyboard::KeyboardEnableFlag>& flags) {
           *enable_flags = flags;
           std::move(callback).Run();
         },
@@ -85,32 +77,24 @@
   }
 
   void RebuildKeyboardIfEnabled() {
-    keyboard_controller_ptr_->RebuildKeyboardIfEnabled();
-    keyboard_controller_ptr_.FlushForTesting();
+    keyboard_controller_->RebuildKeyboardIfEnabled();
   }
 
   bool IsKeyboardVisible() {
-    keyboard_controller_ptr_->IsKeyboardVisible(base::BindOnce(
+    keyboard_controller_->IsKeyboardVisible(base::BindOnce(
         &TestClient::OnIsKeyboardVisible, base::Unretained(this)));
-    keyboard_controller_ptr_.FlushForTesting();
     return is_visible_;
   }
 
-  void ShowKeyboard() {
-    keyboard_controller_ptr_->ShowKeyboard();
-    keyboard_controller_ptr_.FlushForTesting();
-  }
+  void ShowKeyboard() { keyboard_controller_->ShowKeyboard(); }
 
-  void HideKeyboard() {
-    keyboard_controller_ptr_->HideKeyboard(mojom::HideReason::kUser);
-    keyboard_controller_ptr_.FlushForTesting();
-  }
+  void HideKeyboard() { keyboard_controller_->HideKeyboard(HideReason::kUser); }
 
-  bool SetContainerType(keyboard::mojom::ContainerType container_type,
+  bool SetContainerType(keyboard::ContainerType container_type,
                         const base::Optional<gfx::Rect>& target_bounds) {
     bool result;
     base::RunLoop run_loop;
-    keyboard_controller_ptr_->SetContainerType(
+    keyboard_controller_->SetContainerType(
         container_type, target_bounds,
         base::BindOnce(
             [](bool* result_ptr, base::OnceClosure callback, bool result) {
@@ -123,27 +107,21 @@
   }
 
   void SetKeyboardLocked(bool locked) {
-    keyboard_controller_ptr_->SetKeyboardLocked(locked);
-    keyboard_controller_ptr_.FlushForTesting();
+    keyboard_controller_->SetKeyboardLocked(locked);
   }
 
   void SetOccludedBounds(const std::vector<gfx::Rect>& bounds) {
-    keyboard_controller_ptr_->SetOccludedBounds(bounds);
-    keyboard_controller_ptr_.FlushForTesting();
+    keyboard_controller_->SetOccludedBounds(bounds);
   }
 
   void SetHitTestBounds(const std::vector<gfx::Rect>& bounds) {
-    keyboard_controller_ptr_->SetHitTestBounds(bounds);
-    keyboard_controller_ptr_.FlushForTesting();
+    keyboard_controller_->SetHitTestBounds(bounds);
   }
 
   void SetDraggableArea(const gfx::Rect& bounds) {
-    keyboard_controller_ptr_->SetDraggableArea(bounds);
-    keyboard_controller_ptr_.FlushForTesting();
+    keyboard_controller_->SetDraggableArea(bounds);
   }
 
-  void FlushMojoForTesting() { keyboard_controller_ptr_.FlushForTesting(); }
-
   int got_keyboard_config_count() const { return got_keyboard_config_count_; }
   const KeyboardConfig& keyboard_config() const { return keyboard_config_; }
 
@@ -151,16 +129,16 @@
   void OnIsKeyboardEnabled(bool enabled) { is_enabled_ = enabled; }
   void OnIsKeyboardVisible(bool visible) { is_visible_ = visible; }
 
-  void OnGetKeyboardConfig(KeyboardConfigPtr config) {
+  void OnGetKeyboardConfig(const KeyboardConfig& config) {
     ++got_keyboard_config_count_;
-    keyboard_config_ = *config;
+    keyboard_config_ = config;
   }
 
+  KeyboardController* keyboard_controller_ = nullptr;
   bool is_enabled_ = false;
   bool is_visible_ = false;
   int got_keyboard_config_count_ = 0;
   KeyboardConfig keyboard_config_;
-  mojom::KeyboardControllerPtr keyboard_controller_ptr_;
 };
 
 class TestContainerBehavior : public keyboard::ContainerBehavior {
@@ -198,7 +176,7 @@
     return false;
   }
 
-  keyboard::mojom::ContainerType GetType() const override { return type_; }
+  keyboard::ContainerType GetType() const override { return type_; }
 
   bool TextBlurHidesKeyboard() const override { return false; }
 
@@ -221,8 +199,7 @@
   const gfx::Rect& draggable_area() const { return draggable_area_; }
 
  private:
-  keyboard::mojom::ContainerType type_ =
-      keyboard::mojom::ContainerType::kFullWidth;
+  keyboard::ContainerType type_ = keyboard::ContainerType::kFullWidth;
   gfx::Rect occluded_bounds_;
   gfx::Rect draggable_area_;
 };
@@ -235,21 +212,7 @@
   void SetUp() override {
     AshTestBase::SetUp();
 
-    // Create a local service manager connector to handle requests to
-    // mojom::KeyboardController.
-    service_manager::mojom::ConnectorRequest request;
-    connector_ = service_manager::Connector::Create(&request);
-
-    service_manager::Connector::TestApi test_api(connector_.get());
-    test_api.OverrideBinderForTesting(
-        service_manager::ServiceFilter::ByName("test"),
-        mojom::KeyboardController::Name_,
-        base::BindRepeating(
-            &AshKeyboardControllerTest::AddKeyboardControllerBinding,
-            base::Unretained(this)));
-    base::RunLoop().RunUntilIdle();
-
-    test_client_ = std::make_unique<TestClient>(connector_.get());
+    test_client_ = std::make_unique<TestClient>();
 
     // Set the initial observer config to the client (default) config.
     test_observer()->set_config(test_client()->keyboard_config());
@@ -260,11 +223,6 @@
     AshTestBase::TearDown();
   }
 
-  void AddKeyboardControllerBinding(mojo::ScopedMessagePipeHandle handle) {
-    Shell::Get()->ash_keyboard_controller()->BindRequest(
-        mojom::KeyboardControllerRequest(std::move(handle)));
-  }
-
   keyboard::KeyboardController* keyboard_controller() {
     return Shell::Get()->ash_keyboard_controller()->keyboard_controller();
   }
@@ -274,7 +232,6 @@
   }
 
  private:
-  std::unique_ptr<service_manager::Connector> connector_;
   std::unique_ptr<TestClient> test_client_;
 
   DISALLOW_COPY_AND_ASSIGN(AshKeyboardControllerTest);
@@ -293,14 +250,13 @@
 
   test_client()->GetKeyboardConfig();
   EXPECT_EQ(1, test_client()->got_keyboard_config_count());
-  KeyboardConfigPtr config =
-      KeyboardConfig::New(test_client()->keyboard_config());
+  KeyboardConfig config = test_client()->keyboard_config();
   // Set the observer config to the client (default) config.
-  test_observer()->set_config(*config);
+  test_observer()->set_config(config);
 
   // Change the keyboard config.
-  bool old_auto_complete = config->auto_complete;
-  config->auto_complete = !config->auto_complete;
+  bool old_auto_complete = config.auto_complete;
+  config.auto_complete = !config.auto_complete;
   test_client()->SetKeyboardConfig(std::move(config));
 
   // Test that the config changes.
@@ -315,7 +271,7 @@
   EXPECT_FALSE(test_client()->IsKeyboardEnabled());
   // Enable the keyboard.
   test_client()->SetEnableFlag(KeyboardEnableFlag::kExtensionEnabled);
-  std::vector<keyboard::mojom::KeyboardEnableFlag> enable_flags =
+  std::vector<keyboard::KeyboardEnableFlag> enable_flags =
       test_client()->GetEnableFlags();
   EXPECT_TRUE(
       base::Contains(enable_flags, KeyboardEnableFlag::kExtensionEnabled));
@@ -366,9 +322,13 @@
 TEST_F(AshKeyboardControllerTest, ShowAndHideKeyboard) {
   // Enable the keyboard. This will create the keyboard window but not show it.
   test_client()->SetEnableFlag(KeyboardEnableFlag::kExtensionEnabled);
+
   ASSERT_TRUE(keyboard_controller()->GetKeyboardWindow());
   EXPECT_FALSE(keyboard_controller()->GetKeyboardWindow()->IsVisible());
 
+  // The keyboard needs to be in a loaded state before being shown.
+  ASSERT_TRUE(keyboard::test::WaitUntilLoaded());
+
   test_client()->ShowKeyboard();
   EXPECT_TRUE(keyboard_controller()->GetKeyboardWindow()->IsVisible());
 
@@ -382,14 +342,14 @@
 TEST_F(AshKeyboardControllerTest, SetContainerType) {
   // Enable the keyboard.
   test_client()->SetEnableFlag(KeyboardEnableFlag::kExtensionEnabled);
-  const auto default_behavior = keyboard::mojom::ContainerType::kFullWidth;
+  const auto default_behavior = keyboard::ContainerType::kFullWidth;
   EXPECT_EQ(default_behavior, keyboard_controller()->GetActiveContainerType());
 
   gfx::Rect target_bounds(0, 0, 10, 10);
   // Set the container type to kFloating.
   EXPECT_TRUE(test_client()->SetContainerType(
-      keyboard::mojom::ContainerType::kFloating, target_bounds));
-  EXPECT_EQ(keyboard::mojom::ContainerType::kFloating,
+      keyboard::ContainerType::kFloating, target_bounds));
+  EXPECT_EQ(keyboard::ContainerType::kFloating,
             keyboard_controller()->GetActiveContainerType());
   // Ensure that the window size is correct (position is determined by Ash).
   EXPECT_EQ(
@@ -398,8 +358,8 @@
 
   // Setting the container type to the current type should fail.
   EXPECT_FALSE(test_client()->SetContainerType(
-      keyboard::mojom::ContainerType::kFloating, base::nullopt));
-  EXPECT_EQ(keyboard::mojom::ContainerType::kFloating,
+      keyboard::ContainerType::kFloating, base::nullopt));
+  EXPECT_EQ(keyboard::ContainerType::kFloating,
             keyboard_controller()->GetActiveContainerType());
 }
 
@@ -459,13 +419,11 @@
   // user profile.
   Shell::Get()->ash_keyboard_controller()->OnSessionStateChanged(
       session_manager::SessionState::LOGGED_IN_NOT_ACTIVE);
-  test_client()->FlushMojoForTesting();
   EXPECT_EQ(1, test_observer()->destroyed_count());
 
   // ACTIVE session state also needs to rebuild keyboard for guest user profile.
   Shell::Get()->ash_keyboard_controller()->OnSessionStateChanged(
       session_manager::SessionState::ACTIVE);
-  test_client()->FlushMojoForTesting();
   EXPECT_EQ(2, test_observer()->destroyed_count());
 }
 
diff --git a/ash/keyboard/ui/container_behavior.h b/ash/keyboard/ui/container_behavior.h
index 2c8d097..a5c84ae4 100644
--- a/ash/keyboard/ui/container_behavior.h
+++ b/ash/keyboard/ui/container_behavior.h
@@ -6,7 +6,7 @@
 #define ASH_KEYBOARD_UI_CONTAINER_BEHAVIOR_H_
 
 #include "ash/keyboard/ui/keyboard_export.h"
-#include "ash/public/interfaces/keyboard_controller_types.mojom.h"
+#include "ash/public/cpp/keyboard/keyboard_types.h"
 #include "ui/display/display.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/vector2d.h"
@@ -86,7 +86,7 @@
   virtual bool HandlePointerEvent(const ui::LocatedEvent& event,
                                   const display::Display& current_display) = 0;
 
-  virtual mojom::ContainerType GetType() const = 0;
+  virtual ContainerType GetType() const = 0;
 
   // Removing focus from a text field should cause the keyboard to be dismissed.
   virtual bool TextBlurHidesKeyboard() const = 0;
diff --git a/ash/keyboard/ui/container_floating_behavior.cc b/ash/keyboard/ui/container_floating_behavior.cc
index a6b3fc6e..af4a3a1 100644
--- a/ash/keyboard/ui/container_floating_behavior.cc
+++ b/ash/keyboard/ui/container_floating_behavior.cc
@@ -27,8 +27,8 @@
 
 ContainerFloatingBehavior::~ContainerFloatingBehavior() = default;
 
-mojom::ContainerType ContainerFloatingBehavior::GetType() const {
-  return mojom::ContainerType::kFloating;
+ContainerType ContainerFloatingBehavior::GetType() const {
+  return ContainerType::kFloating;
 }
 
 void ContainerFloatingBehavior::DoHidingAnimation(
diff --git a/ash/keyboard/ui/container_floating_behavior.h b/ash/keyboard/ui/container_floating_behavior.h
index 07b7f7c..83c678f 100644
--- a/ash/keyboard/ui/container_floating_behavior.h
+++ b/ash/keyboard/ui/container_floating_behavior.h
@@ -41,7 +41,7 @@
                           const display::Display& current_display) override;
   void SetCanonicalBounds(aura::Window* container,
                           const gfx::Rect& display_bounds) override;
-  mojom::ContainerType GetType() const override;
+  ContainerType GetType() const override;
   bool TextBlurHidesKeyboard() const override;
   gfx::Rect GetOccludedBounds(
       const gfx::Rect& visual_bounds_in_screen) const override;
diff --git a/ash/keyboard/ui/container_full_width_behavior.cc b/ash/keyboard/ui/container_full_width_behavior.cc
index 6541df2c..e9a88be 100644
--- a/ash/keyboard/ui/container_full_width_behavior.cc
+++ b/ash/keyboard/ui/container_full_width_behavior.cc
@@ -19,8 +19,8 @@
 
 ContainerFullWidthBehavior::~ContainerFullWidthBehavior() {}
 
-mojom::ContainerType ContainerFullWidthBehavior::GetType() const {
-  return mojom::ContainerType::kFullWidth;
+ContainerType ContainerFullWidthBehavior::GetType() const {
+  return ContainerType::kFullWidth;
 }
 
 void ContainerFullWidthBehavior::DoHidingAnimation(
diff --git a/ash/keyboard/ui/container_full_width_behavior.h b/ash/keyboard/ui/container_full_width_behavior.h
index 999e69f..0be24f8 100644
--- a/ash/keyboard/ui/container_full_width_behavior.h
+++ b/ash/keyboard/ui/container_full_width_behavior.h
@@ -37,7 +37,7 @@
                           const display::Display& current_display) override;
   void SetCanonicalBounds(aura::Window* container,
                           const gfx::Rect& display_bounds) override;
-  mojom::ContainerType GetType() const override;
+  ContainerType GetType() const override;
   bool TextBlurHidesKeyboard() const override;
   void SetOccludedBounds(const gfx::Rect& occluded_bounds_in_window) override;
   gfx::Rect GetOccludedBounds(
diff --git a/ash/keyboard/ui/keyboard_controller.cc b/ash/keyboard/ui/keyboard_controller.cc
index c116fb3..9f0207d7 100644
--- a/ash/keyboard/ui/keyboard_controller.cc
+++ b/ash/keyboard/ui/keyboard_controller.cc
@@ -221,7 +221,7 @@
   keyboard_locked_ = false;
   DCHECK_EQ(model_.state(), KeyboardUIState::kInitial);
   ui_->SetController(this);
-  SetContainerBehaviorInternal(mojom::ContainerType::kFullWidth);
+  SetContainerBehaviorInternal(ContainerType::kFullWidth);
   visual_bounds_in_root_ = gfx::Rect();
   time_of_last_blur_ = base::Time::UnixEpoch();
   UpdateInputMethodObserver();
@@ -405,9 +405,8 @@
   observer_list_.RemoveObserver(observer);
 }
 
-bool KeyboardController::UpdateKeyboardConfig(
-    const mojom::KeyboardConfig& config) {
-  if (config.Equals(keyboard_config_))
+bool KeyboardController::UpdateKeyboardConfig(const KeyboardConfig& config) {
+  if (config == keyboard_config_)
     return false;
   keyboard_config_ = config;
   if (IsEnabled())
@@ -415,12 +414,11 @@
   return true;
 }
 
-void KeyboardController::SetEnableFlag(mojom::KeyboardEnableFlag flag) {
+void KeyboardController::SetEnableFlag(KeyboardEnableFlag flag) {
   if (!base::Contains(keyboard_enable_flags_, flag))
     keyboard_enable_flags_.insert(flag);
 
   // If there is a flag that is mutually exclusive with |flag|, clear it.
-  using mojom::KeyboardEnableFlag;
   switch (flag) {
     case KeyboardEnableFlag::kPolicyEnabled:
       keyboard_enable_flags_.erase(KeyboardEnableFlag::kPolicyDisabled);
@@ -443,7 +441,7 @@
   UpdateKeyboardAsRequestedBy(flag);
 }
 
-void KeyboardController::ClearEnableFlag(mojom::KeyboardEnableFlag flag) {
+void KeyboardController::ClearEnableFlag(KeyboardEnableFlag flag) {
   if (!IsEnableFlagSet(flag))
     return;
 
@@ -454,12 +452,11 @@
   UpdateKeyboardAsRequestedBy(flag);
 }
 
-bool KeyboardController::IsEnableFlagSet(mojom::KeyboardEnableFlag flag) const {
+bool KeyboardController::IsEnableFlagSet(KeyboardEnableFlag flag) const {
   return base::Contains(keyboard_enable_flags_, flag);
 }
 
 bool KeyboardController::IsKeyboardEnableRequested() const {
-  using mojom::KeyboardEnableFlag;
   // Accessibility setting prioritized over policy/arc overrides.
   if (IsEnableFlagSet(KeyboardEnableFlag::kAccessibilityEnabled))
     return true;
@@ -486,8 +483,7 @@
          IsEnableFlagSet(KeyboardEnableFlag::kTouchEnabled);
 }
 
-void KeyboardController::UpdateKeyboardAsRequestedBy(
-    mojom::KeyboardEnableFlag flag) {
+void KeyboardController::UpdateKeyboardAsRequestedBy(KeyboardEnableFlag flag) {
   if (IsKeyboardEnableRequested()) {
     // Note that there are two versions of the on-screen keyboard. A full layout
     // is provided for accessibility, which includes sticky modifier keys to
@@ -496,7 +492,7 @@
     // event that the a11y keyboard is being disabled, an on-screen keyboard
     // might still be enabled and a forced reset is required to pick up the
     // layout change.
-    if (IsEnabled() && flag == mojom::KeyboardEnableFlag::kAccessibilityEnabled)
+    if (IsEnabled() && flag == KeyboardEnableFlag::kAccessibilityEnabled)
       RebuildKeyboardIfEnabled();
     else
       EnableKeyboard();
@@ -517,9 +513,9 @@
   // If overscroll enabled behavior is set, use it instead. Currently
   // login / out-of-box disable keyboard overscroll. http://crbug.com/363635
   if (keyboard_config_.overscroll_behavior !=
-      mojom::KeyboardOverscrollBehavior::kDefault) {
+      KeyboardOverscrollBehavior::kDefault) {
     return keyboard_config_.overscroll_behavior ==
-           mojom::KeyboardOverscrollBehavior::kEnabled;
+           KeyboardOverscrollBehavior::kEnabled;
   }
 
   return true;
@@ -664,18 +660,17 @@
 }
 
 // private
-void KeyboardController::SetContainerBehaviorInternal(
-    mojom::ContainerType type) {
+void KeyboardController::SetContainerBehaviorInternal(ContainerType type) {
   // Reset the hit test event targeter because the hit test bounds will
   // be wrong when container type changes and may cause the UI to be unusable.
   if (GetKeyboardWindow())
     GetKeyboardWindow()->SetEventTargeter(nullptr);
 
   switch (type) {
-    case mojom::ContainerType::kFullWidth:
+    case ContainerType::kFullWidth:
       container_behavior_ = std::make_unique<ContainerFullWidthBehavior>(this);
       break;
-    case mojom::ContainerType::kFloating:
+    case ContainerType::kFloating:
       container_behavior_ = std::make_unique<ContainerFloatingBehavior>(this);
       break;
   }
@@ -973,7 +968,7 @@
   // temporarily overridden by a static field in certain lock screen contexts.
   // Furthermore, floating keyboard should never affect layout.
   if (!IsKeyboardOverscrollEnabled() &&
-      container_behavior_->GetType() != mojom::ContainerType::kFloating) {
+      container_behavior_->GetType() != ContainerType::kFloating) {
     return visual_bounds_in_root_;
   }
   return gfx::Rect();
@@ -1014,7 +1009,7 @@
 }
 
 void KeyboardController::SetContainerType(
-    mojom::ContainerType type,
+    ContainerType type,
     const base::Optional<gfx::Rect>& target_bounds_in_root,
     base::OnceCallback<void(bool)> callback) {
   if (container_behavior_->GetType() == type) {
diff --git a/ash/keyboard/ui/keyboard_controller.h b/ash/keyboard/ui/keyboard_controller.h
index a18377b..80fd6d6 100644
--- a/ash/keyboard/ui/keyboard_controller.h
+++ b/ash/keyboard/ui/keyboard_controller.h
@@ -19,8 +19,8 @@
 #include "ash/keyboard/ui/notification_manager.h"
 #include "ash/keyboard/ui/queued_container_type.h"
 #include "ash/keyboard/ui/queued_display_change.h"
-#include "ash/public/interfaces/keyboard_config.mojom.h"
-#include "ash/public/interfaces/keyboard_controller_types.mojom.h"
+#include "ash/public/cpp/keyboard/keyboard_config.h"
+#include "ash/public/cpp/keyboard/keyboard_types.h"
 #include "base/macros.h"
 #include "base/observer_list.h"
 #include "base/scoped_observer.h"
@@ -106,14 +106,14 @@
 
   // Updates |keyboard_config_| with |config|. Returns |false| if there is no
   // change, otherwise returns true and notifies observers if this is enabled.
-  bool UpdateKeyboardConfig(const mojom::KeyboardConfig& config);
-  const mojom::KeyboardConfig& keyboard_config() { return keyboard_config_; }
+  bool UpdateKeyboardConfig(const KeyboardConfig& config);
+  const KeyboardConfig& keyboard_config() { return keyboard_config_; }
 
   // Sets and clears |keyboard_enable_flags_| entries.
-  void SetEnableFlag(mojom::KeyboardEnableFlag flag);
-  void ClearEnableFlag(mojom::KeyboardEnableFlag flag);
-  bool IsEnableFlagSet(mojom::KeyboardEnableFlag flag) const;
-  const std::set<mojom::KeyboardEnableFlag>& keyboard_enable_flags() const {
+  void SetEnableFlag(KeyboardEnableFlag flag);
+  void ClearEnableFlag(KeyboardEnableFlag flag);
+  bool IsEnableFlagSet(KeyboardEnableFlag flag) const;
+  const std::set<KeyboardEnableFlag>& keyboard_enable_flags() const {
     return keyboard_enable_flags_;
   }
 
@@ -183,7 +183,7 @@
   // the keyboard window.
   void SetHitTestBounds(const std::vector<gfx::Rect>& bounds_in_window);
 
-  mojom::ContainerType GetActiveContainerType() const {
+  ContainerType GetActiveContainerType() const {
     return container_behavior_->GetType();
   }
 
@@ -208,7 +208,7 @@
   // Sets the active container type. If the keyboard is currently shown, this
   // will trigger a hide animation and a subsequent show animation. Otherwise
   // the ContainerBehavior change is synchronous.
-  void SetContainerType(mojom::ContainerType type,
+  void SetContainerType(ContainerType type,
                         const base::Optional<gfx::Rect>& target_bounds_in_root,
                         base::OnceCallback<void(bool)> callback);
 
@@ -308,7 +308,7 @@
 
   // Enables or disables the keyboard based on |IsKeyboardEnableRequested|,
   // as requested by |flag|.
-  void UpdateKeyboardAsRequestedBy(mojom::KeyboardEnableFlag flag);
+  void UpdateKeyboardAsRequestedBy(KeyboardEnableFlag flag);
 
   // Attach the keyboard window as a child of the given parent window.
   // Can only be called when the keyboard is not activated. |parent| must not
@@ -366,7 +366,7 @@
   // time ago.
   void ShowKeyboardIfWithinTransientBlurThreshold();
 
-  void SetContainerBehaviorInternal(mojom::ContainerType type);
+  void SetContainerBehaviorInternal(ContainerType type);
 
   // Records that keyboard was shown on the currently focused UKM source.
   void RecordUkmKeyboardShown();
@@ -428,11 +428,11 @@
   gfx::Rect visual_bounds_in_root_;
 
   // Keyboard configuration associated with the controller.
-  mojom::KeyboardConfig keyboard_config_;
+  KeyboardConfig keyboard_config_;
 
   // Set of active enabled request flags. Used to determine whether the keyboard
   // should be enabled.
-  std::set<mojom::KeyboardEnableFlag> keyboard_enable_flags_;
+  std::set<KeyboardEnableFlag> keyboard_enable_flags_;
 
   NotificationManager notification_manager_;
 
diff --git a/ash/keyboard/ui/keyboard_controller_observer.h b/ash/keyboard/ui/keyboard_controller_observer.h
index 1625351..6f5ba09 100644
--- a/ash/keyboard/ui/keyboard_controller_observer.h
+++ b/ash/keyboard/ui/keyboard_controller_observer.h
@@ -69,7 +69,7 @@
 
   // Called when an enable flag affecting the requested enabled state changes.
   virtual void OnKeyboardEnableFlagsChanged(
-      std::set<mojom::KeyboardEnableFlag>& keyboard_enable_flags) {}
+      const std::set<KeyboardEnableFlag>& keyboard_enable_flags) {}
 
   // Called when the keyboard is enabled or disabled. NOTE: This is called
   // when Enabled() or Disabled() is called, not when the requested enabled
diff --git a/ash/keyboard/ui/keyboard_controller_unittest.cc b/ash/keyboard/ui/keyboard_controller_unittest.cc
index 46935beb7..bb7dddf 100644
--- a/ash/keyboard/ui/keyboard_controller_unittest.cc
+++ b/ash/keyboard/ui/keyboard_controller_unittest.cc
@@ -579,7 +579,7 @@
   EXPECT_FALSE(notified_is_visible());
 
   SetModeCallbackInvocationCounter invocation_counter;
-  controller().SetContainerType(mojom::ContainerType::kFloating, base::nullopt,
+  controller().SetContainerType(ContainerType::kFloating, base::nullopt,
                                 invocation_counter.GetInvocationCallback());
   EXPECT_EQ(1, invocation_counter.invocation_count_for_status(true));
   EXPECT_EQ(0, invocation_counter.invocation_count_for_status(false));
@@ -595,7 +595,7 @@
   // callback should do nothing when container mode is set to the current active
   // container type. An unnecessary call gets registered synchronously as a
   // failure status to the callback.
-  controller().SetContainerType(mojom::ContainerType::kFloating, base::nullopt,
+  controller().SetContainerType(ContainerType::kFloating, base::nullopt,
                                 invocation_counter.GetInvocationCallback());
   EXPECT_EQ(1, invocation_counter.invocation_count_for_status(true));
   EXPECT_EQ(1, invocation_counter.invocation_count_for_status(false));
@@ -607,13 +607,12 @@
   ui::Layer* layer = keyboard_window()->layer();
   ShowKeyboard();
   RunAnimationForLayer(layer);
-  EXPECT_EQ(mojom::ContainerType::kFullWidth,
-            controller().GetActiveContainerType());
+  EXPECT_EQ(ContainerType::kFullWidth, controller().GetActiveContainerType());
   EXPECT_TRUE(keyboard_window()->IsVisible());
 
   // Changing the mode to another mode invokes hiding + showing.
   const gfx::Rect target_bounds(0, 0, 1200, 600);
-  controller().SetContainerType(mojom::ContainerType::kFloating,
+  controller().SetContainerType(ContainerType::kFloating,
                                 base::make_optional(target_bounds),
                                 invocation_counter.GetInvocationCallback());
   // The container window shouldn't be resized until it's hidden even if the
@@ -710,10 +709,9 @@
   MockTextInputClient mock_input_client;
   EXPECT_CALL(mock_input_client, EnsureCaretNotInRect(gfx::Rect())).Times(1);
 
-  controller().SetContainerType(mojom::ContainerType::kFloating, base::nullopt,
+  controller().SetContainerType(ContainerType::kFloating, base::nullopt,
                                 base::DoNothing());
-  ASSERT_EQ(mojom::ContainerType::kFloating,
-            controller().GetActiveContainerType());
+  ASSERT_EQ(ContainerType::kFloating, controller().GetActiveContainerType());
 
   // Ensure keyboard ui is populated
   ui::Layer* layer = keyboard_window()->layer();
diff --git a/ash/keyboard/ui/keyboard_ui_model.h b/ash/keyboard/ui/keyboard_ui_model.h
index 7a5497b..84fb147 100644
--- a/ash/keyboard/ui/keyboard_ui_model.h
+++ b/ash/keyboard/ui/keyboard_ui_model.h
@@ -8,7 +8,7 @@
 #include <string>
 
 #include "ash/keyboard/ui/keyboard_export.h"
-#include "ash/public/interfaces/keyboard_config.mojom.h"
+#include "ash/public/cpp/keyboard/keyboard_config.h"
 #include "base/macros.h"
 
 namespace keyboard {
diff --git a/ash/keyboard/ui/keyboard_util.cc b/ash/keyboard/ui/keyboard_util.cc
index 1068975..dae4caf9 100644
--- a/ash/keyboard/ui/keyboard_util.cc
+++ b/ash/keyboard/ui/keyboard_util.cc
@@ -20,13 +20,13 @@
 // TODO(stevenjb): Remove remaining calls from src/chrome.
 // https://crbug.com/84332.
 
-bool GetFlag(mojom::KeyboardEnableFlag flag) {
+bool GetFlag(KeyboardEnableFlag flag) {
   return KeyboardController::HasInstance()
              ? KeyboardController::Get()->IsEnableFlagSet(flag)
              : false;
 }
 
-void SetOrClearEnableFlag(mojom::KeyboardEnableFlag flag, bool enabled) {
+void SetOrClearEnableFlag(KeyboardEnableFlag flag, bool enabled) {
   auto* controller = KeyboardController::Get();
   if (!controller)
     return;
@@ -39,28 +39,27 @@
 }  // namespace
 
 void SetAccessibilityKeyboardEnabled(bool enabled) {
-  SetOrClearEnableFlag(mojom::KeyboardEnableFlag::kAccessibilityEnabled,
-                       enabled);
+  SetOrClearEnableFlag(KeyboardEnableFlag::kAccessibilityEnabled, enabled);
 }
 
 bool GetAccessibilityKeyboardEnabled() {
-  return GetFlag(mojom::KeyboardEnableFlag::kAccessibilityEnabled);
+  return GetFlag(KeyboardEnableFlag::kAccessibilityEnabled);
 }
 
 void SetKeyboardEnabledFromShelf(bool enabled) {
-  SetOrClearEnableFlag(mojom::KeyboardEnableFlag::kShelfEnabled, enabled);
+  SetOrClearEnableFlag(KeyboardEnableFlag::kShelfEnabled, enabled);
 }
 
 bool GetKeyboardEnabledFromShelf() {
-  return GetFlag(mojom::KeyboardEnableFlag::kShelfEnabled);
+  return GetFlag(KeyboardEnableFlag::kShelfEnabled);
 }
 
 void SetTouchKeyboardEnabled(bool enabled) {
-  SetOrClearEnableFlag(mojom::KeyboardEnableFlag::kTouchEnabled, enabled);
+  SetOrClearEnableFlag(KeyboardEnableFlag::kTouchEnabled, enabled);
 }
 
 bool GetTouchKeyboardEnabled() {
-  return GetFlag(mojom::KeyboardEnableFlag::kTouchEnabled);
+  return GetFlag(KeyboardEnableFlag::kTouchEnabled);
 }
 
 bool IsKeyboardEnabled() {
diff --git a/ash/keyboard/ui/keyboard_util_unittest.cc b/ash/keyboard/ui/keyboard_util_unittest.cc
index d5df60adb..ee8626d 100644
--- a/ash/keyboard/ui/keyboard_util_unittest.cc
+++ b/ash/keyboard/ui/keyboard_util_unittest.cc
@@ -30,8 +30,8 @@
     ResetAllFlags();
     keyboard::SetAccessibilityKeyboardEnabled(false);
     keyboard::SetTouchKeyboardEnabled(false);
-    SetEnableFlag(mojom::KeyboardEnableFlag::kPolicyDisabled);
-    SetEnableFlag(mojom::KeyboardEnableFlag::kExtensionDisabled);
+    SetEnableFlag(KeyboardEnableFlag::kPolicyDisabled);
+    SetEnableFlag(KeyboardEnableFlag::kExtensionDisabled);
   }
 
   // Sets all flags controlling whether the keyboard should be shown to
@@ -40,8 +40,8 @@
     ResetAllFlags();
     keyboard::SetAccessibilityKeyboardEnabled(true);
     keyboard::SetTouchKeyboardEnabled(true);
-    SetEnableFlag(mojom::KeyboardEnableFlag::kPolicyEnabled);
-    SetEnableFlag(mojom::KeyboardEnableFlag::kExtensionEnabled);
+    SetEnableFlag(KeyboardEnableFlag::kPolicyEnabled);
+    SetEnableFlag(KeyboardEnableFlag::kExtensionEnabled);
   }
 
   // Sets all flags controlling whether the keyboard should be shown to
@@ -49,10 +49,10 @@
   void ResetAllFlags() {
     keyboard::SetAccessibilityKeyboardEnabled(false);
     keyboard::SetTouchKeyboardEnabled(false);
-    ClearEnableFlag(mojom::KeyboardEnableFlag::kPolicyDisabled);
-    ClearEnableFlag(mojom::KeyboardEnableFlag::kExtensionDisabled);
-    ClearEnableFlag(mojom::KeyboardEnableFlag::kPolicyEnabled);
-    ClearEnableFlag(mojom::KeyboardEnableFlag::kExtensionEnabled);
+    ClearEnableFlag(KeyboardEnableFlag::kPolicyDisabled);
+    ClearEnableFlag(KeyboardEnableFlag::kExtensionDisabled);
+    ClearEnableFlag(KeyboardEnableFlag::kPolicyEnabled);
+    ClearEnableFlag(KeyboardEnableFlag::kExtensionEnabled);
   }
 
   void SetUp() override {
@@ -74,11 +74,11 @@
   }
 
  protected:
-  void SetEnableFlag(mojom::KeyboardEnableFlag flag) {
+  void SetEnableFlag(KeyboardEnableFlag flag) {
     keyboard_controller_.SetEnableFlag(flag);
   }
 
-  void ClearEnableFlag(mojom::KeyboardEnableFlag flag) {
+  void ClearEnableFlag(KeyboardEnableFlag flag) {
     keyboard_controller_.ClearEnableFlag(flag);
   }
 
@@ -108,7 +108,7 @@
   EXPECT_FALSE(keyboard::IsKeyboardEnabled());
   // If policy is enabled, should ignore other flag values.
   DisableAllFlags();
-  SetEnableFlag(mojom::KeyboardEnableFlag::kPolicyEnabled);
+  SetEnableFlag(KeyboardEnableFlag::kPolicyEnabled);
   EXPECT_TRUE(keyboard::IsKeyboardEnabled());
 }
 
@@ -120,7 +120,7 @@
   keyboard::SetAccessibilityKeyboardEnabled(false);
   EXPECT_TRUE(keyboard::IsKeyboardEnabled());
   // Disable policy. Keyboard should be disabled.
-  SetEnableFlag(mojom::KeyboardEnableFlag::kPolicyDisabled);
+  SetEnableFlag(KeyboardEnableFlag::kPolicyDisabled);
   EXPECT_FALSE(keyboard::IsKeyboardEnabled());
 }
 
@@ -129,10 +129,10 @@
 TEST_F(KeyboardUtilTest, ShowKeyboardWhenRequested) {
   DisableAllFlags();
   // Remove device policy, which has higher precedence than us.
-  ClearEnableFlag(mojom::KeyboardEnableFlag::kPolicyDisabled);
+  ClearEnableFlag(KeyboardEnableFlag::kPolicyDisabled);
   EXPECT_FALSE(keyboard::IsKeyboardEnabled());
   // Requested should have higher precedence than all the remaining flags.
-  SetEnableFlag(mojom::KeyboardEnableFlag::kExtensionEnabled);
+  SetEnableFlag(KeyboardEnableFlag::kExtensionEnabled);
   EXPECT_TRUE(keyboard::IsKeyboardEnabled());
 }
 
@@ -141,11 +141,11 @@
 TEST_F(KeyboardUtilTest, HideKeyboardWhenRequested) {
   EnableAllFlags();
   // Remove higher precedence flags.
-  ClearEnableFlag(mojom::KeyboardEnableFlag::kPolicyEnabled);
+  ClearEnableFlag(KeyboardEnableFlag::kPolicyEnabled);
   keyboard::SetAccessibilityKeyboardEnabled(false);
   EXPECT_TRUE(keyboard::IsKeyboardEnabled());
   // Set requested flag to disable. Keyboard should disable.
-  SetEnableFlag(mojom::KeyboardEnableFlag::kExtensionDisabled);
+  SetEnableFlag(KeyboardEnableFlag::kExtensionDisabled);
   EXPECT_FALSE(keyboard::IsKeyboardEnabled());
 }
 
@@ -160,7 +160,7 @@
 
 TEST_F(KeyboardUtilTest, UpdateKeyboardConfig) {
   ResetAllFlags();
-  mojom::KeyboardConfig config = keyboard_controller_.keyboard_config();
+  KeyboardConfig config = keyboard_controller_.keyboard_config();
   EXPECT_TRUE(config.spell_check);
   EXPECT_FALSE(keyboard_controller_.UpdateKeyboardConfig(config));
 
@@ -182,15 +182,13 @@
   EXPECT_TRUE(keyboard_controller_.IsKeyboardOverscrollEnabled());
 
   // Set overscroll enabled flag.
-  mojom::KeyboardConfig config = keyboard_controller_.keyboard_config();
-  config.overscroll_behavior =
-      keyboard::mojom::KeyboardOverscrollBehavior::kDisabled;
+  KeyboardConfig config = keyboard_controller_.keyboard_config();
+  config.overscroll_behavior = keyboard::KeyboardOverscrollBehavior::kDisabled;
   keyboard_controller_.UpdateKeyboardConfig(config);
   EXPECT_FALSE(keyboard_controller_.IsKeyboardOverscrollEnabled());
 
   // Set default overscroll flag.
-  config.overscroll_behavior =
-      keyboard::mojom::KeyboardOverscrollBehavior::kDefault;
+  config.overscroll_behavior = keyboard::KeyboardOverscrollBehavior::kDefault;
   keyboard_controller_.UpdateKeyboardConfig(config);
   EXPECT_TRUE(keyboard_controller_.IsKeyboardOverscrollEnabled());
 
diff --git a/ash/keyboard/ui/queued_container_type.cc b/ash/keyboard/ui/queued_container_type.cc
index 331874c..bf3917d 100644
--- a/ash/keyboard/ui/queued_container_type.cc
+++ b/ash/keyboard/ui/queued_container_type.cc
@@ -9,7 +9,7 @@
 
 QueuedContainerType::QueuedContainerType(
     KeyboardController* controller,
-    mojom::ContainerType container_type,
+    ContainerType container_type,
     base::Optional<gfx::Rect> bounds,
     base::OnceCallback<void(bool success)> callback)
     : controller_(controller),
diff --git a/ash/keyboard/ui/queued_container_type.h b/ash/keyboard/ui/queued_container_type.h
index 53b29d5..e3e843f 100644
--- a/ash/keyboard/ui/queued_container_type.h
+++ b/ash/keyboard/ui/queued_container_type.h
@@ -5,7 +5,7 @@
 #ifndef ASH_KEYBOARD_UI_QUEUED_CONTAINER_TYPE_H_
 #define ASH_KEYBOARD_UI_QUEUED_CONTAINER_TYPE_H_
 
-#include "ash/public/interfaces/keyboard_controller_types.mojom.h"
+#include "ash/public/cpp/keyboard/keyboard_types.h"
 #include "base/bind.h"
 #include "base/optional.h"
 #include "ui/gfx/geometry/rect.h"
@@ -23,16 +23,16 @@
 class QueuedContainerType {
  public:
   QueuedContainerType(KeyboardController* controller,
-                      mojom::ContainerType container_type,
+                      ContainerType container_type,
                       base::Optional<gfx::Rect> bounds,
                       base::OnceCallback<void(bool success)> callback);
   ~QueuedContainerType();
-  mojom::ContainerType container_type() { return container_type_; }
+  ContainerType container_type() { return container_type_; }
   base::Optional<gfx::Rect> target_bounds() { return bounds_; }
 
  private:
   KeyboardController* controller_;
-  mojom::ContainerType container_type_;
+  ContainerType container_type_;
   base::Optional<gfx::Rect> bounds_;
   base::OnceCallback<void(bool success)> callback_;
 };
diff --git a/ash/keyboard/virtual_keyboard_controller_unittest.cc b/ash/keyboard/virtual_keyboard_controller_unittest.cc
index 3ea25905..dc71660e 100644
--- a/ash/keyboard/virtual_keyboard_controller_unittest.cc
+++ b/ash/keyboard/virtual_keyboard_controller_unittest.cc
@@ -26,7 +26,7 @@
 #include "ui/events/devices/input_device.h"
 #include "ui/events/devices/touchscreen_device.h"
 
-using keyboard::mojom::KeyboardEnableFlag;
+using keyboard::KeyboardEnableFlag;
 
 namespace ash {
 
diff --git a/ash/keyboard/virtual_keyboard_unittest.cc b/ash/keyboard/virtual_keyboard_unittest.cc
index 8e331a6..602e4492 100644
--- a/ash/keyboard/virtual_keyboard_unittest.cc
+++ b/ash/keyboard/virtual_keyboard_unittest.cc
@@ -112,9 +112,8 @@
   // Change the container behavior, which should reset the hit test bounds to
   // the whole keyboard window.
   keyboard_controller->HideKeyboardExplicitlyBySystem();
-  keyboard_controller->SetContainerType(
-      keyboard::mojom::ContainerType::kFloating, base::nullopt,
-      base::DoNothing());
+  keyboard_controller->SetContainerType(keyboard::ContainerType::kFloating,
+                                        base::nullopt, base::DoNothing());
   keyboard_controller->ShowKeyboard(false);
 
   // (0, 0) should no longer pass through the keyboard window.
diff --git a/ash/kiosk_next/kiosk_next_home_controller_unittest.cc b/ash/kiosk_next/kiosk_next_home_controller_unittest.cc
index 2cd7c988..10ec17c 100644
--- a/ash/kiosk_next/kiosk_next_home_controller_unittest.cc
+++ b/ash/kiosk_next/kiosk_next_home_controller_unittest.cc
@@ -32,15 +32,15 @@
     scoped_feature_list_.InitAndEnableFeature(features::kKioskNextShell);
     set_start_session(false);
     AshTestBase::SetUp();
-    client_ = BindMockKioskNextShellClient();
+    client_ = std::make_unique<MockKioskNextShellClient>();
     LogInKioskNextUser(GetSessionControllerClient());
     SetUpHomeWindow();
   }
 
   void TearDown() override {
     home_screen_window_.reset();
-    AshTestBase::TearDown();
     client_.reset();
+    AshTestBase::TearDown();
   }
 
   void SetUpHomeWindow() {
diff --git a/ash/kiosk_next/kiosk_next_shell_controller.cc b/ash/kiosk_next/kiosk_next_shell_controller_impl.cc
similarity index 78%
rename from ash/kiosk_next/kiosk_next_shell_controller.cc
rename to ash/kiosk_next/kiosk_next_shell_controller_impl.cc
index d4623aad..51ca121 100644
--- a/ash/kiosk_next/kiosk_next_shell_controller.cc
+++ b/ash/kiosk_next/kiosk_next_shell_controller_impl.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 "ash/kiosk_next/kiosk_next_shell_controller.h"
+#include "ash/kiosk_next/kiosk_next_shell_controller_impl.h"
 
 #include <memory>
 #include <utility>
@@ -52,12 +52,12 @@
 
 }  // namespace
 
-KioskNextShellController::KioskNextShellController() = default;
+KioskNextShellControllerImpl::KioskNextShellControllerImpl() = default;
 
-KioskNextShellController::~KioskNextShellController() = default;
+KioskNextShellControllerImpl::~KioskNextShellControllerImpl() = default;
 
 // static
-void KioskNextShellController::RegisterProfilePrefs(
+void KioskNextShellControllerImpl::RegisterProfilePrefs(
     PrefRegistrySimple* registry,
     bool for_test) {
   if (for_test) {
@@ -67,43 +67,40 @@
   }
 }
 
-void KioskNextShellController::BindRequest(
-    mojom::KioskNextShellControllerRequest request) {
-  bindings_.AddBinding(this, std::move(request));
+void KioskNextShellControllerImpl::SetClientAndLaunchSession(
+    KioskNextShellClient* client) {
+  DCHECK_NE(!!client, !!client_);
+  client_ = client;
+  LaunchKioskNextShellIfEnabled();
 }
 
-bool KioskNextShellController::IsEnabled() {
+bool KioskNextShellControllerImpl::IsEnabled() {
   return kiosk_next_enabled_;
 }
 
-void KioskNextShellController::AddObserver(KioskNextShellObserver* observer) {
+void KioskNextShellControllerImpl::AddObserver(
+    KioskNextShellObserver* observer) {
   observer_list_.AddObserver(observer);
 }
 
-void KioskNextShellController::RemoveObserver(
+void KioskNextShellControllerImpl::RemoveObserver(
     KioskNextShellObserver* observer) {
   observer_list_.RemoveObserver(observer);
 }
 
-void KioskNextShellController::SetClient(
-    mojom::KioskNextShellClientPtr client) {
-  kiosk_next_shell_client_ = std::move(client);
-  LaunchKioskNextShellIfEnabled();
-}
-
-void KioskNextShellController::OnActiveUserPrefServiceChanged(
+void KioskNextShellControllerImpl::OnActiveUserPrefServiceChanged(
     PrefService* pref_service) {
   LaunchKioskNextShellIfEnabled();
 }
 
-void KioskNextShellController::LaunchKioskNextShellIfEnabled() {
+void KioskNextShellControllerImpl::LaunchKioskNextShellIfEnabled() {
   SessionControllerImpl* session_controller =
       Shell::Get()->session_controller();
   PrefService* pref_service = session_controller->GetPrimaryUserPrefService();
   if (!pref_service)
     return;
 
-  if (!kiosk_next_shell_client_.is_bound())
+  if (!client_)
     return;
 
   bool prev_kiosk_next_enabled = kiosk_next_enabled_;
@@ -119,7 +116,7 @@
       kiosk_next_home_controller_.get());
   Shell::Get()->RemoveAppListController();
 
-  kiosk_next_shell_client_->LaunchKioskNextShell(
+  client_->LaunchKioskNextShell(
       session_controller->GetPrimaryUserSession()->user_info.account_id);
   UMA_HISTOGRAM_BOOLEAN("KioskNextShell.Launched", true);
 
diff --git a/ash/kiosk_next/kiosk_next_shell_controller.h b/ash/kiosk_next/kiosk_next_shell_controller_impl.h
similarity index 61%
rename from ash/kiosk_next/kiosk_next_shell_controller.h
rename to ash/kiosk_next/kiosk_next_shell_controller_impl.h
index 6de77c06..acb5c9b2 100644
--- a/ash/kiosk_next/kiosk_next_shell_controller.h
+++ b/ash/kiosk_next/kiosk_next_shell_controller_impl.h
@@ -2,18 +2,17 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef ASH_KIOSK_NEXT_KIOSK_NEXT_SHELL_CONTROLLER_H_
-#define ASH_KIOSK_NEXT_KIOSK_NEXT_SHELL_CONTROLLER_H_
+#ifndef ASH_KIOSK_NEXT_KIOSK_NEXT_SHELL_CONTROLLER_IMPL_H_
+#define ASH_KIOSK_NEXT_KIOSK_NEXT_SHELL_CONTROLLER_IMPL_H_
 
 #include <memory>
 
 #include "ash/ash_export.h"
 #include "ash/kiosk_next/kiosk_next_shell_observer.h"
-#include "ash/public/interfaces/kiosk_next_shell.mojom.h"
+#include "ash/public/cpp/kiosk_next_shell.h"
 #include "ash/session/session_observer.h"
 #include "base/macros.h"
 #include "base/observer_list.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
 
 class PrefRegistrySimple;
 
@@ -22,21 +21,20 @@
 class KioskNextHomeController;
 class ShelfModel;
 
-// KioskNextShellController allows an ash consumer to manage a Kiosk Next
+// KioskNextShellControllerImpl allows an ash consumer to manage a Kiosk Next
 // session. During this session most system functions are disabled and we launch
 // a specific app (Kiosk Next Home) that takes the whole screen.
-class ASH_EXPORT KioskNextShellController
-    : public mojom::KioskNextShellController,
-      public SessionObserver {
+class ASH_EXPORT KioskNextShellControllerImpl : public KioskNextShellController,
+                                                public SessionObserver {
  public:
-  KioskNextShellController();
-  ~KioskNextShellController() override;
+  KioskNextShellControllerImpl();
+  ~KioskNextShellControllerImpl() override;
 
   // Register prefs related to the Kiosk Next Shell.
   static void RegisterProfilePrefs(PrefRegistrySimple* registry, bool for_test);
 
-  // Binds the mojom::KioskNextShellController interface to this object.
-  void BindRequest(mojom::KioskNextShellControllerRequest request);
+  // KioskNextShellController:
+  void SetClientAndLaunchSession(KioskNextShellClient* client) override;
 
   // Returns if the Kiosk Next Shell is enabled for the current user. If there's
   // no signed-in user, this returns false.
@@ -45,9 +43,6 @@
   void AddObserver(KioskNextShellObserver* observer);
   void RemoveObserver(KioskNextShellObserver* observer);
 
-  // mojom::KioskNextShellController:
-  void SetClient(mojom::KioskNextShellClientPtr client) override;
-
   // SessionObserver:
   void OnActiveUserPrefServiceChanged(PrefService* pref_service) override;
 
@@ -58,8 +53,8 @@
   // available.
   void LaunchKioskNextShellIfEnabled();
 
-  mojom::KioskNextShellClientPtr kiosk_next_shell_client_;
-  mojo::BindingSet<mojom::KioskNextShellController> bindings_;
+  KioskNextShellClient* client_ = nullptr;
+
   base::ObserverList<KioskNextShellObserver> observer_list_;
   ScopedSessionObserver session_observer_{this};
   bool kiosk_next_enabled_ = false;
@@ -68,13 +63,13 @@
   std::unique_ptr<KioskNextHomeController> kiosk_next_home_controller_;
 
   // When KioskNextShell is enabled, only the home button and back button are
-  // made visible on the Shelf. KioskNextShellController therefore hosts its own
-  // ShelfModel to control the entries visible on the shelf.
+  // made visible on the Shelf. KioskNextShellControllerImpl therefore hosts its
+  // own ShelfModel to control the entries visible on the shelf.
   std::unique_ptr<ShelfModel> shelf_model_;
 
-  DISALLOW_COPY_AND_ASSIGN(KioskNextShellController);
+  DISALLOW_COPY_AND_ASSIGN(KioskNextShellControllerImpl);
 };
 
 }  // namespace ash
 
-#endif  // ASH_KIOSK_NEXT_KIOSK_NEXT_SHELL_CONTROLLER_H_
+#endif  // ASH_KIOSK_NEXT_KIOSK_NEXT_SHELL_CONTROLLER_IMPL_H_
diff --git a/ash/kiosk_next/kiosk_next_shell_controller_unittest.cc b/ash/kiosk_next/kiosk_next_shell_controller_unittest.cc
index df5d7400..bfb966a 100644
--- a/ash/kiosk_next/kiosk_next_shell_controller_unittest.cc
+++ b/ash/kiosk_next/kiosk_next_shell_controller_unittest.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 "ash/kiosk_next/kiosk_next_shell_controller.h"
+#include "ash/kiosk_next/kiosk_next_shell_controller_impl.h"
 
 #include <memory>
 
@@ -18,7 +18,7 @@
 namespace ash {
 namespace {
 
-KioskNextShellController* GetKioskNextShellController() {
+KioskNextShellControllerImpl* GetKioskNextShellController() {
   return Shell::Get()->kiosk_next_shell_controller();
 }
 
@@ -42,13 +42,13 @@
   void SetUp() override {
     set_start_session(false);
     AshTestBase::SetUp();
-    client_ = BindMockKioskNextShellClient();
+    client_ = std::make_unique<MockKioskNextShellClient>();
     scoped_feature_list_.InitAndEnableFeature(features::kKioskNextShell);
   }
 
   void TearDown() override {
-    AshTestBase::TearDown();
     client_.reset();
+    AshTestBase::TearDown();
   }
 
  protected:
diff --git a/ash/kiosk_next/mock_kiosk_next_shell_client.cc b/ash/kiosk_next/mock_kiosk_next_shell_client.cc
index 405e707..f9f78b7 100644
--- a/ash/kiosk_next/mock_kiosk_next_shell_client.cc
+++ b/ash/kiosk_next/mock_kiosk_next_shell_client.cc
@@ -4,27 +4,14 @@
 
 #include "ash/kiosk_next/mock_kiosk_next_shell_client.h"
 
-#include "ash/kiosk_next/kiosk_next_shell_controller.h"
-#include "ash/shell.h"
-
 namespace ash {
 
-MockKioskNextShellClient::MockKioskNextShellClient() = default;
-
-MockKioskNextShellClient::~MockKioskNextShellClient() = default;
-
-mojom::KioskNextShellClientPtr
-MockKioskNextShellClient::CreateInterfacePtrAndBind() {
-  mojom::KioskNextShellClientPtr ptr;
-  binding_.Bind(mojo::MakeRequest(&ptr));
-  return ptr;
+MockKioskNextShellClient::MockKioskNextShellClient() {
+  KioskNextShellController::Get()->SetClientAndLaunchSession(this);
 }
 
-std::unique_ptr<MockKioskNextShellClient> BindMockKioskNextShellClient() {
-  auto client = std::make_unique<MockKioskNextShellClient>();
-  Shell::Get()->kiosk_next_shell_controller()->SetClient(
-      client->CreateInterfacePtrAndBind());
-  return client;
+MockKioskNextShellClient::~MockKioskNextShellClient() {
+  KioskNextShellController::Get()->SetClientAndLaunchSession(nullptr);
 }
 
 }  // namespace ash
diff --git a/ash/kiosk_next/mock_kiosk_next_shell_client.h b/ash/kiosk_next/mock_kiosk_next_shell_client.h
index 6e3b5a56..9830ac0 100644
--- a/ash/kiosk_next/mock_kiosk_next_shell_client.h
+++ b/ash/kiosk_next/mock_kiosk_next_shell_client.h
@@ -5,36 +5,25 @@
 #ifndef ASH_KIOSK_NEXT_MOCK_KIOSK_NEXT_SHELL_CLIENT_H_
 #define ASH_KIOSK_NEXT_MOCK_KIOSK_NEXT_SHELL_CLIENT_H_
 
-#include <memory>
-
-#include "ash/public/interfaces/kiosk_next_shell.mojom.h"
+#include "ash/public/cpp/kiosk_next_shell.h"
 #include "base/macros.h"
 #include "components/account_id/account_id.h"
-#include "mojo/public/cpp/bindings/binding.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
 namespace ash {
 
-class MockKioskNextShellClient : public mojom::KioskNextShellClient {
+class MockKioskNextShellClient : public KioskNextShellClient {
  public:
   MockKioskNextShellClient();
   ~MockKioskNextShellClient() override;
 
-  mojom::KioskNextShellClientPtr CreateInterfacePtrAndBind();
-
-  // mojom::KioskNextShellClient:
+  // KioskNextShellClient:
   MOCK_METHOD1(LaunchKioskNextShell, void(const AccountId& account_id));
 
  private:
-  mojo::Binding<mojom::KioskNextShellClient> binding_{this};
-
   DISALLOW_COPY_AND_ASSIGN(MockKioskNextShellClient);
 };
 
-// Helper function to bind a KioskNextShellClient so that it receives mojo
-// calls.
-std::unique_ptr<MockKioskNextShellClient> BindMockKioskNextShellClient();
-
 }  // namespace ash
 
 #endif  // ASH_KIOSK_NEXT_MOCK_KIOSK_NEXT_SHELL_CLIENT_H_
diff --git a/ash/login/login_screen_controller.cc b/ash/login/login_screen_controller.cc
index 39a078f..2014f2c 100644
--- a/ash/login/login_screen_controller.cc
+++ b/ash/login/login_screen_controller.cc
@@ -11,6 +11,7 @@
 #include "ash/login/ui/login_data_dispatcher.h"
 #include "ash/login/ui/parent_access_widget.h"
 #include "ash/public/cpp/ash_pref_names.h"
+#include "ash/public/cpp/login_screen_client.h"
 #include "ash/root_window_controller.h"
 #include "ash/session/session_controller_impl.h"
 #include "ash/shelf/login_shelf_view.h"
@@ -80,10 +81,6 @@
   }
 }
 
-void LoginScreenController::BindRequest(mojom::LoginScreenRequest request) {
-  bindings_.AddBinding(this, std::move(request));
-}
-
 bool LoginScreenController::IsAuthenticating() const {
   return authentication_stage_ != AuthenticationStage::kIdle;
 }
@@ -99,7 +96,7 @@
       << "Duplicate authentication attempt; current authentication stage is "
       << static_cast<int>(authentication_stage_);
 
-  if (!login_screen_client_) {
+  if (!client_) {
     std::move(callback).Run(base::nullopt);
     return;
   }
@@ -130,7 +127,7 @@
   int dummy_value;
   bool is_pin =
       authenticated_by_pin && base::StringToInt(password, &dummy_value);
-  login_screen_client_->AuthenticateUserWithPasswordOrPin(
+  client_->AuthenticateUserWithPasswordOrPin(
       account_id, password, is_pin,
       base::BindOnce(&LoginScreenController::OnAuthenticateComplete,
                      weak_factory_.GetWeakPtr(), base::Passed(&callback)));
@@ -145,13 +142,13 @@
       << "Duplicate authentication attempt; current authentication stage is "
       << static_cast<int>(authentication_stage_);
 
-  if (!login_screen_client_) {
+  if (!client_) {
     std::move(callback).Run(base::nullopt);
     return;
   }
 
   authentication_stage_ = AuthenticationStage::kDoAuthenticate;
-  login_screen_client_->AuthenticateUserWithExternalBinary(
+  client_->AuthenticateUserWithExternalBinary(
       account_id,
       base::BindOnce(&LoginScreenController::OnAuthenticateComplete,
                      weak_factory_.GetWeakPtr(), std::move(callback)));
@@ -159,12 +156,12 @@
 
 void LoginScreenController::EnrollUserWithExternalBinary(
     OnAuthenticateCallback callback) {
-  if (!login_screen_client_) {
+  if (!client_) {
     std::move(callback).Run(base::nullopt);
     return;
   }
 
-  login_screen_client_->EnrollUserWithExternalBinary(base::BindOnce(
+  client_->EnrollUserWithExternalBinary(base::BindOnce(
       [](OnAuthenticateCallback callback, bool success) {
         std::move(callback).Run(base::make_optional<bool>(success));
       },
@@ -175,126 +172,119 @@
     const AccountId& account_id) {
   // TODO(jdufault): integrate this into authenticate stage after mojom is
   // refactored to use a callback.
-  if (!login_screen_client_)
+  if (!client_)
     return;
-  login_screen_client_->AuthenticateUserWithEasyUnlock(account_id);
+  client_->AuthenticateUserWithEasyUnlock(account_id);
 }
 
-void LoginScreenController::ValidateParentAccessCode(
+bool LoginScreenController::ValidateParentAccessCode(
     const AccountId& account_id,
-    const std::string& code,
-    OnParentAccessValidation callback) {
-  if (!login_screen_client_) {
-    std::move(callback).Run(base::nullopt);
-    return;
-  }
+    const std::string& code) {
+  if (!client_)
+    return false;
 
-  login_screen_client_->ValidateParentAccessCode(
-      account_id, code,
-      base::BindOnce(&LoginScreenController::OnParentAccessValidationComplete,
-                     weak_factory_.GetWeakPtr(), std::move(callback)));
+  return client_->ValidateParentAccessCode(account_id, code);
 }
 
 void LoginScreenController::HardlockPod(const AccountId& account_id) {
-  if (!login_screen_client_)
+  if (!client_)
     return;
-  login_screen_client_->HardlockPod(account_id);
+  client_->HardlockPod(account_id);
 }
 
 void LoginScreenController::OnFocusPod(const AccountId& account_id) {
-  if (!login_screen_client_)
+  if (!client_)
     return;
-  login_screen_client_->OnFocusPod(account_id);
+  client_->OnFocusPod(account_id);
 }
 
 void LoginScreenController::OnNoPodFocused() {
-  if (!login_screen_client_)
+  if (!client_)
     return;
-  login_screen_client_->OnNoPodFocused();
+  client_->OnNoPodFocused();
 }
 
 void LoginScreenController::LoadWallpaper(const AccountId& account_id) {
-  if (!login_screen_client_)
+  if (!client_)
     return;
-  login_screen_client_->LoadWallpaper(account_id);
+  client_->LoadWallpaper(account_id);
 }
 
 void LoginScreenController::SignOutUser() {
-  if (!login_screen_client_)
+  if (!client_)
     return;
-  login_screen_client_->SignOutUser();
+  client_->SignOutUser();
 }
 
 void LoginScreenController::CancelAddUser() {
-  if (!login_screen_client_)
+  if (!client_)
     return;
-  login_screen_client_->CancelAddUser();
+  client_->CancelAddUser();
 }
 
 void LoginScreenController::LoginAsGuest() {
-  if (!login_screen_client_)
+  if (!client_)
     return;
-  login_screen_client_->LoginAsGuest();
+  client_->LoginAsGuest();
 }
 
 void LoginScreenController::OnMaxIncorrectPasswordAttempted(
     const AccountId& account_id) {
-  if (!login_screen_client_)
+  if (!client_)
     return;
-  login_screen_client_->OnMaxIncorrectPasswordAttempted(account_id);
+  client_->OnMaxIncorrectPasswordAttempted(account_id);
 }
 
 void LoginScreenController::FocusLockScreenApps(bool reverse) {
-  if (!login_screen_client_)
+  if (!client_)
     return;
-  login_screen_client_->FocusLockScreenApps(reverse);
+  client_->FocusLockScreenApps(reverse);
 }
 
-void LoginScreenController::ShowGaiaSignin(
-    bool can_close,
-    const base::Optional<AccountId>& prefilled_account) {
-  if (!login_screen_client_)
+void LoginScreenController::ShowGaiaSignin(bool can_close,
+                                           const AccountId& prefilled_account) {
+  if (!client_)
     return;
-  login_screen_client_->ShowGaiaSignin(can_close, prefilled_account);
+  client_->ShowGaiaSignin(can_close, prefilled_account);
 }
 
 void LoginScreenController::OnRemoveUserWarningShown() {
-  if (!login_screen_client_)
+  if (!client_)
     return;
-  login_screen_client_->OnRemoveUserWarningShown();
+  client_->OnRemoveUserWarningShown();
 }
 
 void LoginScreenController::RemoveUser(const AccountId& account_id) {
-  if (!login_screen_client_)
+  if (!client_)
     return;
-  login_screen_client_->RemoveUser(account_id);
+  client_->RemoveUser(account_id);
 }
 
 void LoginScreenController::LaunchPublicSession(
     const AccountId& account_id,
     const std::string& locale,
     const std::string& input_method) {
-  if (!login_screen_client_)
+  if (!client_)
     return;
-  login_screen_client_->LaunchPublicSession(account_id, locale, input_method);
+  client_->LaunchPublicSession(account_id, locale, input_method);
 }
 
 void LoginScreenController::RequestPublicSessionKeyboardLayouts(
     const AccountId& account_id,
     const std::string& locale) {
-  if (!login_screen_client_)
+  if (!client_)
     return;
-  login_screen_client_->RequestPublicSessionKeyboardLayouts(account_id, locale);
+  client_->RequestPublicSessionKeyboardLayouts(account_id, locale);
 }
 
 void LoginScreenController::ShowFeedback() {
-  if (!login_screen_client_)
+  if (!client_)
     return;
-  login_screen_client_->ShowFeedback();
+  client_->ShowFeedback();
 }
 
-void LoginScreenController::FlushForTesting() {
-  login_screen_client_.FlushForTesting();
+void LoginScreenController::SetClient(LoginScreenClient* client) {
+  client_ = client;
 }
 
 LoginScreenModel* LoginScreenController::GetModel() {
@@ -372,31 +362,22 @@
       ->SetAllowLoginAsGuest(allow_guest);
 }
 
-void LoginScreenController::SetClient(mojom::LoginScreenClientPtr client) {
-  login_screen_client_ = std::move(client);
-}
-
-void LoginScreenController::ShowLockScreen(ShowLockScreenCallback on_shown) {
+void LoginScreenController::ShowLockScreen() {
   OnShow();
   LockScreen::Show(LockScreen::ScreenType::kLock);
-  std::move(on_shown).Run(true);
 }
 
-void LoginScreenController::ShowLoginScreen(ShowLoginScreenCallback on_shown) {
+void LoginScreenController::ShowLoginScreen() {
   // Login screen can only be used during login.
-  if (Shell::Get()->session_controller()->GetSessionState() !=
-      session_manager::SessionState::LOGIN_PRIMARY) {
-    LOG(ERROR) << "Not showing login screen since session state is "
-               << static_cast<int>(
-                      Shell::Get()->session_controller()->GetSessionState());
-    std::move(on_shown).Run(false);
-    return;
-  }
+  CHECK_EQ(session_manager::SessionState::LOGIN_PRIMARY,
+           Shell::Get()->session_controller()->GetSessionState())
+      << "Not showing login screen since session state is "
+      << static_cast<int>(
+             Shell::Get()->session_controller()->GetSessionState());
 
   OnShow();
   // TODO(jdufault): rename LockScreen to LoginScreen.
   LockScreen::Show(LockScreen::ScreenType::kLogin);
-  std::move(on_shown).Run(true);
 }
 
 void LoginScreenController::SetKioskApps(
@@ -409,23 +390,23 @@
 }
 
 void LoginScreenController::ShowResetScreen() {
-  login_screen_client_->ShowResetScreen();
+  client_->ShowResetScreen();
 }
 
 void LoginScreenController::ShowAccountAccessHelpApp() {
-  login_screen_client_->ShowAccountAccessHelpApp();
+  client_->ShowAccountAccessHelpApp();
 }
 
 void LoginScreenController::FocusOobeDialog() {
-  if (!login_screen_client_)
+  if (!client_)
     return;
-  login_screen_client_->FocusOobeDialog();
+  client_->FocusOobeDialog();
 }
 
 void LoginScreenController::NotifyUserActivity() {
-  if (!login_screen_client_)
+  if (!client_)
     return;
-  login_screen_client_->OnUserActivity();
+  client_->OnUserActivity();
 }
 
 void LoginScreenController::OnAuthenticateComplete(
@@ -436,12 +417,6 @@
   authentication_stage_ = AuthenticationStage::kIdle;
 }
 
-void LoginScreenController::OnParentAccessValidationComplete(
-    OnParentAccessValidation callback,
-    bool success) {
-  std::move(callback).Run(base::make_optional<bool>(success));
-}
-
 void LoginScreenController::OnShow() {
   SetSystemTrayVisibility(SystemTrayVisibility::kPrimary);
   if (authentication_stage_ != AuthenticationStage::kIdle) {
@@ -453,9 +428,9 @@
 }
 
 void LoginScreenController::OnFocusLeavingSystemTray(bool reverse) {
-  if (!login_screen_client_)
+  if (!client_)
     return;
-  login_screen_client_->OnFocusLeavingSystemTray(reverse);
+  client_->OnFocusLeavingSystemTray(reverse);
 }
 
 }  // namespace ash
diff --git a/ash/login/login_screen_controller.h b/ash/login/login_screen_controller.h
index ca42704..3f90718 100644
--- a/ash/login/login_screen_controller.h
+++ b/ash/login/login_screen_controller.h
@@ -12,7 +12,6 @@
 #include "ash/public/cpp/kiosk_app_menu.h"
 #include "ash/public/cpp/login_screen.h"
 #include "ash/public/cpp/system_tray_focus_observer.h"
-#include "ash/public/interfaces/login_screen.mojom.h"
 #include "base/macros.h"
 #include "base/optional.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
@@ -24,13 +23,12 @@
 class ParentAccessWidget;
 class SystemTrayNotifier;
 
-// LoginScreenController implements mojom::LoginScreen and wraps the
-// mojom::LoginScreenClient interface. This lets a consumer of ash provide a
-// LoginScreenClient, which we will dispatch to if one has been provided to us.
-// This could send requests to LoginScreenClient and also handle requests from
-// LoginScreenClient through mojo.
-class ASH_EXPORT LoginScreenController : public mojom::LoginScreen,
-                                         public LoginScreen,
+// LoginScreenController implements LoginScreen and wraps the LoginScreenClient
+// interface. This lets a consumer of ash provide a LoginScreenClient, which we
+// will dispatch to if one has been provided to us. This could send requests to
+// LoginScreenClient and also handle requests from the consumer via the
+// LoginScreen interface.
+class ASH_EXPORT LoginScreenController : public LoginScreen,
                                          public KioskAppMenu,
                                          public SystemTrayFocusObserver {
  public:
@@ -57,9 +55,6 @@
 
   static void RegisterProfilePrefs(PrefRegistrySimple* registry, bool for_test);
 
-  // Binds the mojom::LoginScreen interface to this object.
-  void BindRequest(mojom::LoginScreenRequest request);
-
   // Check to see if an authentication attempt is in-progress.
   bool IsAuthenticating() const;
 
@@ -75,9 +70,8 @@
                                           OnAuthenticateCallback callback);
   void EnrollUserWithExternalBinary(OnAuthenticateCallback callback);
   void AuthenticateUserWithEasyUnlock(const AccountId& account_id);
-  void ValidateParentAccessCode(const AccountId& account_id,
-                                const std::string& code,
-                                OnParentAccessValidation callback);
+  bool ValidateParentAccessCode(const AccountId& account_id,
+                                const std::string& code);
   void HardlockPod(const AccountId& account_id);
   void OnFocusPod(const AccountId& account_id);
   void OnNoPodFocused();
@@ -87,8 +81,7 @@
   void LoginAsGuest();
   void OnMaxIncorrectPasswordAttempted(const AccountId& account_id);
   void FocusLockScreenApps(bool reverse);
-  void ShowGaiaSignin(bool can_close,
-                      const base::Optional<AccountId>& prefilled_account);
+  void ShowGaiaSignin(bool can_close, const AccountId& prefilled_account);
   void OnRemoveUserWarningShown();
   void RemoveUser(const AccountId& account_id);
   void LaunchPublicSession(const AccountId& account_id,
@@ -109,7 +102,10 @@
   }
 
   // LoginScreen:
+  void SetClient(LoginScreenClient* client) override;
   LoginScreenModel* GetModel() override;
+  void ShowLockScreen() override;
+  void ShowLoginScreen() override;
   void ShowKioskAppError(const std::string& message) override;
   void FocusLoginShelf(bool reverse) override;
   bool IsReadyForPassword() override;
@@ -122,20 +118,12 @@
       base::RepeatingCallback<void(bool success)> callback) override;
   void SetAllowLoginAsGuest(bool allow_guest) override;
 
-  // mojom::LoginScreen:
-  void SetClient(mojom::LoginScreenClientPtr client) override;
-  void ShowLockScreen(ShowLockScreenCallback on_shown) override;
-  void ShowLoginScreen(ShowLoginScreenCallback on_shown) override;
-
   // KioskAppMenu:
   void SetKioskApps(
       const std::vector<KioskAppMenuEntry>& kiosk_apps,
       const base::RepeatingCallback<void(const KioskAppMenuEntry&)>& launch_app)
       override;
 
-  // Flushes the mojo pipes - to be used in tests.
-  void FlushForTesting();
-
   AuthenticationStage authentication_stage() const {
     return authentication_stage_;
   }
@@ -144,8 +132,6 @@
 
  private:
   void OnAuthenticateComplete(OnAuthenticateCallback callback, bool success);
-  void OnParentAccessValidationComplete(OnParentAccessValidation callback,
-                                        bool success);
 
   // Common code that is called when the login/lock screen is shown.
   void OnShow();
@@ -155,11 +141,7 @@
 
   LoginDataDispatcher login_data_dispatcher_;
 
-  // Client interface in chrome browser. May be null in tests.
-  mojom::LoginScreenClientPtr login_screen_client_;
-
-  // Bindings for users of the LockScreen interface.
-  mojo::BindingSet<mojom::LoginScreen> bindings_;
+  LoginScreenClient* client_ = nullptr;
 
   AuthenticationStage authentication_stage_ = AuthenticationStage::kIdle;
 
diff --git a/ash/login/login_screen_controller_unittest.cc b/ash/login/login_screen_controller_unittest.cc
index d4c93af..3d1f2e5d 100644
--- a/ash/login/login_screen_controller_unittest.cc
+++ b/ash/login/login_screen_controller_unittest.cc
@@ -43,7 +43,7 @@
 
 TEST_F(LoginScreenControllerTest, RequestAuthentication) {
   LoginScreenController* controller = Shell::Get()->login_screen_controller();
-  std::unique_ptr<MockLoginScreenClient> client = BindMockLoginScreenClient();
+  auto client = std::make_unique<MockLoginScreenClient>();
 
   AccountId id = AccountId::FromUserEmail("user1@test.com");
 
@@ -87,7 +87,7 @@
 
 TEST_F(LoginScreenControllerTest, RequestEasyUnlock) {
   LoginScreenController* controller = Shell::Get()->login_screen_controller();
-  std::unique_ptr<MockLoginScreenClient> client = BindMockLoginScreenClient();
+  auto client = std::make_unique<MockLoginScreenClient>();
 
   AccountId id = AccountId::FromUserEmail("user1@test.com");
 
@@ -104,7 +104,7 @@
 
 TEST_F(LoginScreenControllerTest, RequestUserPodFocus) {
   LoginScreenController* controller = Shell::Get()->login_screen_controller();
-  std::unique_ptr<MockLoginScreenClient> client = BindMockLoginScreenClient();
+  auto client = std::make_unique<MockLoginScreenClient>();
 
   AccountId id = AccountId::FromUserEmail("user1@test.com");
 
@@ -119,46 +119,6 @@
   base::RunLoop().RunUntilIdle();
 }
 
-TEST_F(LoginScreenControllerTest,
-       ShowLoginScreenRequiresLoginPrimarySessionState) {
-  auto show_login = [&](session_manager::SessionState state) {
-    EXPECT_FALSE(ash::LockScreen::HasInstance());
-
-    LoginScreenController* controller = Shell::Get()->login_screen_controller();
-
-    GetSessionControllerClient()->SetSessionState(state);
-    base::Optional<bool> result;
-    base::RunLoop run_loop;
-    controller->ShowLoginScreen(base::BindOnce(
-        [](base::Optional<bool>* result, base::RunLoop* run_loop,
-           bool did_show) {
-          *result = did_show;
-          run_loop->Quit();
-        },
-        &result, &run_loop));
-    run_loop.Run();
-
-    EXPECT_TRUE(result.has_value());
-
-    // Verify result matches actual ash::LockScreen state.
-    EXPECT_EQ(*result, ash::LockScreen::HasInstance());
-
-    // Destroy login if we created it.
-    if (*result)
-      ash::LockScreen::Get()->Destroy();
-
-    return *result;
-  };
-
-  EXPECT_FALSE(show_login(session_manager::SessionState::UNKNOWN));
-  EXPECT_FALSE(show_login(session_manager::SessionState::OOBE));
-  EXPECT_TRUE(show_login(session_manager::SessionState::LOGIN_PRIMARY));
-  EXPECT_FALSE(show_login(session_manager::SessionState::LOGGED_IN_NOT_ACTIVE));
-  EXPECT_FALSE(show_login(session_manager::SessionState::ACTIVE));
-  EXPECT_FALSE(show_login(session_manager::SessionState::LOCKED));
-  EXPECT_FALSE(show_login(session_manager::SessionState::LOGIN_SECONDARY));
-}
-
 TEST_F(LoginScreenControllerNoSessionTest, ShowSystemTrayOnPrimaryLoginScreen) {
   // Create setup with 2 displays primary and secondary.
   UpdateDisplay("800x600,800x600");
@@ -171,23 +131,13 @@
 
   // Show login screen.
   GetSessionControllerClient()->SetSessionState(SessionState::LOGIN_PRIMARY);
-  base::Optional<bool> result;
-  base::RunLoop run_loop;
-  Shell::Get()->login_screen_controller()->ShowLoginScreen(base::BindOnce(
-      [](base::Optional<bool>* result, base::RunLoop* run_loop, bool did_show) {
-        *result = did_show;
-        run_loop->Quit();
-      },
-      &result, &run_loop));
-  run_loop.Run();
-  EXPECT_TRUE(result.has_value());
+  Shell::Get()->login_screen_controller()->ShowLoginScreen();
 
   EXPECT_TRUE(ash::LockScreen::HasInstance());
   EXPECT_TRUE(IsSystemTrayForWindowVisible(WindowType::kPrimary));
   EXPECT_FALSE(IsSystemTrayForWindowVisible(WindowType::kSecondary));
 
-  if (*result)
-    ash::LockScreen::Get()->Destroy();
+  ash::LockScreen::Get()->Destroy();
 }
 
 TEST_F(LoginScreenControllerTest, ShowSystemTrayOnPrimaryLockScreen) {
@@ -203,34 +153,20 @@
 
   // Show lock screen.
   GetSessionControllerClient()->SetSessionState(SessionState::LOCKED);
-  base::Optional<bool> result;
-  base::RunLoop run_loop;
-  Shell::Get()->login_screen_controller()->ShowLockScreen(base::BindOnce(
-      [](base::Optional<bool>* result, base::RunLoop* run_loop, bool did_show) {
-        *result = did_show;
-        run_loop->Quit();
-      },
-      &result, &run_loop));
-  run_loop.Run();
-  EXPECT_TRUE(result.has_value());
+  Shell::Get()->login_screen_controller()->ShowLockScreen();
 
   EXPECT_TRUE(ash::LockScreen::HasInstance());
   EXPECT_TRUE(IsSystemTrayForWindowVisible(WindowType::kPrimary));
   EXPECT_FALSE(IsSystemTrayForWindowVisible(WindowType::kSecondary));
 
-  if (*result)
-    ash::LockScreen::Get()->Destroy();
+  ash::LockScreen::Get()->Destroy();
 }
 
 TEST_F(LoginScreenControllerTest, ShowLoginScreenRequiresWallpaper) {
   // Show login screen.
   EXPECT_FALSE(ash::LockScreen::HasInstance());
   GetSessionControllerClient()->SetSessionState(SessionState::LOGIN_PRIMARY);
-  base::RunLoop run_loop;
-  Shell::Get()->login_screen_controller()->ShowLoginScreen(base::BindOnce(
-      [](base::RunLoop* run_loop, bool did_show) { run_loop->Quit(); },
-      &run_loop));
-  run_loop.Run();
+  Shell::Get()->login_screen_controller()->ShowLoginScreen();
 
   // Verify the instance has been created, but the login screen is not actually
   // shown yet because there's no wallpaper.
@@ -246,15 +182,13 @@
 }
 
 TEST_F(LoginScreenControllerTest, SystemTrayFocus) {
-  std::unique_ptr<MockLoginScreenClient> client = BindMockLoginScreenClient();
+  auto client = std::make_unique<MockLoginScreenClient>();
 
   EXPECT_CALL(*client, OnFocusLeavingSystemTray(true)).Times(1);
   Shell::Get()->system_tray_notifier()->NotifyFocusOut(true);
-  Shell::Get()->login_screen_controller()->FlushForTesting();
 
   EXPECT_CALL(*client, OnFocusLeavingSystemTray(false)).Times(1);
   Shell::Get()->system_tray_notifier()->NotifyFocusOut(false);
-  Shell::Get()->login_screen_controller()->FlushForTesting();
 }
 
 }  // namespace
diff --git a/ash/login/mock_login_screen_client.cc b/ash/login/mock_login_screen_client.cc
index 282c753..727d910 100644
--- a/ash/login/mock_login_screen_client.cc
+++ b/ash/login/mock_login_screen_client.cc
@@ -12,21 +12,17 @@
 
 namespace ash {
 
-MockLoginScreenClient::MockLoginScreenClient() : binding_(this) {}
+MockLoginScreenClient::MockLoginScreenClient() {
+  Shell::Get()->login_screen_controller()->SetClient(this);
+}
 
 MockLoginScreenClient::~MockLoginScreenClient() = default;
 
-mojom::LoginScreenClientPtr MockLoginScreenClient::CreateInterfacePtrAndBind() {
-  mojom::LoginScreenClientPtr ptr;
-  binding_.Bind(mojo::MakeRequest(&ptr));
-  return ptr;
-}
-
 void MockLoginScreenClient::AuthenticateUserWithPasswordOrPin(
     const AccountId& account_id,
     const std::string& password,
     bool authenticated_by_pin,
-    AuthenticateUserWithPasswordOrPinCallback callback) {
+    base::OnceCallback<void(bool)> callback) {
   AuthenticateUserWithPasswordOrPin_(account_id, password, authenticated_by_pin,
                                      callback);
   if (authenticate_user_with_password_or_pin_callback_storage_) {
@@ -39,7 +35,7 @@
 
 void MockLoginScreenClient::AuthenticateUserWithExternalBinary(
     const AccountId& account_id,
-    AuthenticateUserWithExternalBinaryCallback callback) {
+    base::OnceCallback<void(bool)> callback) {
   AuthenticateUserWithExternalBinary_(account_id, callback);
   if (authenticate_user_with_external_binary_callback_storage_) {
     *authenticate_user_with_external_binary_callback_storage_ =
@@ -50,7 +46,7 @@
 }
 
 void MockLoginScreenClient::EnrollUserWithExternalBinary(
-    EnrollUserWithExternalBinaryCallback callback) {
+    base::OnceCallback<void(bool)> callback) {
   EnrollUserWithExternalBinary_(callback);
   if (enroll_user_with_external_binary_callback_storage_) {
     *enroll_user_with_external_binary_callback_storage_ = std::move(callback);
@@ -59,19 +55,11 @@
   }
 }
 
-void MockLoginScreenClient::ValidateParentAccessCode(
+bool MockLoginScreenClient::ValidateParentAccessCode(
     const AccountId& account_id,
-    const std::string& code,
-    ValidateParentAccessCodeCallback callback) {
-  ValidateParentAccessCode_(account_id, code, callback);
-  std::move(callback).Run(validate_parent_access_code_result_);
-}
-
-std::unique_ptr<MockLoginScreenClient> BindMockLoginScreenClient() {
-  auto client = std::make_unique<MockLoginScreenClient>();
-  Shell::Get()->login_screen_controller()->SetClient(
-      client->CreateInterfacePtrAndBind());
-  return client;
+    const std::string& code) {
+  ValidateParentAccessCode_(account_id, code);
+  return validate_parent_access_code_result_;
 }
 
 }  // namespace ash
diff --git a/ash/login/mock_login_screen_client.h b/ash/login/mock_login_screen_client.h
index a88525f..fff6e222 100644
--- a/ash/login/mock_login_screen_client.h
+++ b/ash/login/mock_login_screen_client.h
@@ -5,34 +5,30 @@
 #ifndef ASH_LOGIN_MOCK_LOGIN_SCREEN_CLIENT_H_
 #define ASH_LOGIN_MOCK_LOGIN_SCREEN_CLIENT_H_
 
-#include "ash/public/interfaces/login_screen.mojom.h"
+#include "ash/public/cpp/login_screen_client.h"
 #include "components/password_manager/core/browser/hash_password_manager.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
 namespace ash {
 
-class MockLoginScreenClient : public mojom::LoginScreenClient {
+class MockLoginScreenClient : public LoginScreenClient {
  public:
   MockLoginScreenClient();
   ~MockLoginScreenClient() override;
 
-  mojom::LoginScreenClientPtr CreateInterfacePtrAndBind();
-
   MOCK_METHOD4(AuthenticateUserWithPasswordOrPin_,
                void(const AccountId& account_id,
                     const std::string& password,
                     bool authenticated_by_pin,
-                    AuthenticateUserWithPasswordOrPinCallback& callback));
+                    base::OnceCallback<void(bool)>& callback));
   MOCK_METHOD2(AuthenticateUserWithExternalBinary_,
                void(const AccountId& account_id,
-                    AuthenticateUserWithExternalBinaryCallback& callback));
+                    base::OnceCallback<void(bool)>& callback));
   MOCK_METHOD1(EnrollUserWithExternalBinary_,
-               void(EnrollUserWithExternalBinaryCallback& callback));
-  MOCK_METHOD3(ValidateParentAccessCode_,
-               void(const AccountId& account_id,
-                    const std::string& access_code,
-                    ValidateParentAccessCodeCallback& callback));
+               void(base::OnceCallback<void(bool)>& callback));
+  MOCK_METHOD2(ValidateParentAccessCode_,
+               bool(const AccountId& account_id,
+                    const std::string& access_code));
 
   // Set the result that should be passed to |callback| in
   // |AuthenticateUserWithPasswordOrPin| or
@@ -50,33 +46,31 @@
   // If set to non-null, when |AuthenticateUser| is called the callback will be
   // stored in |storage| instead of being executed.
   void set_authenticate_user_with_password_or_pin_callback_storage(
-      AuthenticateUserWithPasswordOrPinCallback* storage) {
+      base::OnceCallback<void(bool)>* storage) {
     authenticate_user_with_password_or_pin_callback_storage_ = storage;
   }
   void set_authenticate_user_with_external_binary_storage(
-      AuthenticateUserWithPasswordOrPinCallback* storage) {
+      base::OnceCallback<void(bool)>* storage) {
     authenticate_user_with_external_binary_callback_storage_ = storage;
   }
   void set_enroll_user_with_external_binary_storage(
-      EnrollUserWithExternalBinaryCallback* storage) {
+      base::OnceCallback<void(bool)>* storage) {
     enroll_user_with_external_binary_callback_storage_ = storage;
   }
 
-  // mojom::LoginScreenClient:
+  // LoginScreenClient:
   void AuthenticateUserWithPasswordOrPin(
       const AccountId& account_id,
       const std::string& password,
       bool authenticated_by_pin,
-      AuthenticateUserWithPasswordOrPinCallback callback) override;
+      base::OnceCallback<void(bool)> callback) override;
   void AuthenticateUserWithExternalBinary(
       const AccountId& account_id,
-      AuthenticateUserWithExternalBinaryCallback callback) override;
+      base::OnceCallback<void(bool)> callback) override;
   void EnrollUserWithExternalBinary(
-      EnrollUserWithExternalBinaryCallback callback) override;
-  void ValidateParentAccessCode(
-      const AccountId& account_id,
-      const std::string& code,
-      ValidateParentAccessCodeCallback callback) override;
+      base::OnceCallback<void(bool)> callback) override;
+  bool ValidateParentAccessCode(const AccountId& account_id,
+                                const std::string& code) override;
   MOCK_METHOD1(AuthenticateUserWithEasyUnlock,
                void(const AccountId& account_id));
   MOCK_METHOD1(HardlockPod, void(const AccountId& account_id));
@@ -90,8 +84,7 @@
                void(const AccountId& account_id));
   MOCK_METHOD1(FocusLockScreenApps, void(bool reverse));
   MOCK_METHOD2(ShowGaiaSignin,
-               void(bool can_close,
-                    const base::Optional<AccountId>& prefilled_account));
+               void(bool can_close, const AccountId& prefilled_account));
   MOCK_METHOD0(OnRemoveUserWarningShown, void());
   MOCK_METHOD1(RemoveUser, void(const AccountId& account_id));
   MOCK_METHOD3(LaunchPublicSession,
@@ -110,21 +103,16 @@
  private:
   bool authenticate_user_callback_result_ = true;
   bool validate_parent_access_code_result_ = true;
-  AuthenticateUserWithPasswordOrPinCallback*
+  base::OnceCallback<void(bool)>*
       authenticate_user_with_password_or_pin_callback_storage_ = nullptr;
-  AuthenticateUserWithExternalBinaryCallback*
+  base::OnceCallback<void(bool)>*
       authenticate_user_with_external_binary_callback_storage_ = nullptr;
-  EnrollUserWithExternalBinaryCallback*
+  base::OnceCallback<void(bool)>*
       enroll_user_with_external_binary_callback_storage_ = nullptr;
 
-  mojo::Binding<mojom::LoginScreenClient> binding_;
-
   DISALLOW_COPY_AND_ASSIGN(MockLoginScreenClient);
 };
 
-// Helper method to bind a login screen client so it receives all mojo calls.
-std::unique_ptr<MockLoginScreenClient> BindMockLoginScreenClient();
-
 }  // namespace ash
 
 #endif  // ASH_LOGIN_MOCK_LOGIN_SCREEN_CLIENT_H_
diff --git a/ash/login/ui/lock_contents_view.cc b/ash/login/ui/lock_contents_view.cc
index f40661a..36208324 100644
--- a/ash/login/ui/lock_contents_view.cc
+++ b/ash/login/ui/lock_contents_view.cc
@@ -641,7 +641,7 @@
     LOG_IF(FATAL, screen_type_ != LockScreen::ScreenType::kLogin)
         << "Empty user list received";
     Shell::Get()->login_screen_controller()->ShowGaiaSignin(
-        false /*can_close*/, base::nullopt /*prefilled_account*/);
+        false /*can_close*/, EmptyAccountId() /*prefilled_account*/);
     return;
   }
 
diff --git a/ash/login/ui/lock_contents_view.h b/ash/login/ui/lock_contents_view.h
index ccfcac3c..6211b18b 100644
--- a/ash/login/ui/lock_contents_view.h
+++ b/ash/login/ui/lock_contents_view.h
@@ -21,7 +21,6 @@
 #include "ash/login/ui/non_accessible_view.h"
 #include "ash/public/cpp/login_types.h"
 #include "ash/public/cpp/system_tray_focus_observer.h"
-#include "ash/public/interfaces/login_screen.mojom.h"
 #include "ash/session/session_observer.h"
 #include "base/macros.h"
 #include "base/optional.h"
diff --git a/ash/login/ui/lock_contents_view_unittest.cc b/ash/login/ui/lock_contents_view_unittest.cc
index e7a22a5..bc7f59b 100644
--- a/ash/login/ui/lock_contents_view_unittest.cc
+++ b/ash/login/ui/lock_contents_view_unittest.cc
@@ -27,7 +27,6 @@
 #include "ash/login/ui/login_user_view.h"
 #include "ash/login/ui/scrollable_users_list_view.h"
 #include "ash/login/ui/views_utils.h"
-#include "ash/public/interfaces/login_screen.mojom.h"
 #include "ash/public/interfaces/tray_action.mojom.h"
 #include "ash/root_window_controller.h"
 #include "ash/shell.h"
@@ -848,7 +847,7 @@
   LockContentsView::TestApi test_api(contents);
 
   // Password submit runs mojo.
-  std::unique_ptr<MockLoginScreenClient> client = BindMockLoginScreenClient();
+  auto client = std::make_unique<MockLoginScreenClient>();
   client->set_authenticate_user_callback_result(false);
   EXPECT_CALL(*client, AuthenticateUserWithPasswordOrPin_(
                            users()[0].basic_user_info.account_id, _, false, _));
@@ -879,7 +878,7 @@
   LockContentsView::TestApi test_api(contents);
 
   // Password submit runs mojo.
-  std::unique_ptr<MockLoginScreenClient> client = BindMockLoginScreenClient();
+  auto client = std::make_unique<MockLoginScreenClient>();
   client->set_authenticate_user_callback_result(false);
   EXPECT_CALL(*client, AuthenticateUserWithPasswordOrPin_(
                            users()[0].basic_user_info.account_id, _, false, _));
@@ -907,7 +906,6 @@
   // Should result in ShowAccountAccessHelpApp().
   generator->MoveMouseTo(button->GetBoundsInScreen().CenterPoint());
   generator->ClickLeftButton();
-  Shell::Get()->login_screen_controller()->FlushForTesting();
 
   // AuthErrorButton should go away after button press.
   EXPECT_FALSE(test_api.auth_error_bubble()->GetVisible());
@@ -923,7 +921,7 @@
   SetUserCount(1);
   SetWidget(CreateWidgetWithContent(contents));
 
-  std::unique_ptr<MockLoginScreenClient> client = BindMockLoginScreenClient();
+  auto client = std::make_unique<MockLoginScreenClient>();
   client->set_authenticate_user_callback_result(false);
 
   auto submit_password = [&]() {
@@ -949,7 +947,7 @@
   SetUserCount(1);
   SetWidget(CreateWidgetWithContent(contents));
 
-  std::unique_ptr<MockLoginScreenClient> client = BindMockLoginScreenClient();
+  auto client = std::make_unique<MockLoginScreenClient>();
   client->set_authenticate_user_callback_result(false);
 
   auto submit_password = [&]() {
@@ -966,10 +964,8 @@
   Mock::VerifyAndClearExpectations(client.get());
 
   // The final attempt triggers ShowGaiaSignin.
-  EXPECT_CALL(*client,
-              ShowGaiaSignin(true /*can_close*/,
-                             base::Optional<AccountId>(
-                                 users()[0].basic_user_info.account_id)))
+  EXPECT_CALL(*client, ShowGaiaSignin(true /*can_close*/,
+                                      users()[0].basic_user_info.account_id))
       .Times(1);
   submit_password();
   Mock::VerifyAndClearExpectations(client.get());
@@ -1039,7 +1035,7 @@
 
   // The current detachable base should be set as the last used one by the user
   // after they authenticate - test for this.
-  std::unique_ptr<MockLoginScreenClient> client = BindMockLoginScreenClient();
+  auto client = std::make_unique<MockLoginScreenClient>();
   client->set_authenticate_user_callback_result(true);
   EXPECT_CALL(*client, AuthenticateUserWithPasswordOrPin_(kFirstUserAccountId,
                                                           _, false, _));
@@ -1100,7 +1096,7 @@
 
   // The last trusted detachable used by the user should not be overriden by
   // user authentication.
-  std::unique_ptr<MockLoginScreenClient> client = BindMockLoginScreenClient();
+  auto client = std::make_unique<MockLoginScreenClient>();
   client->set_authenticate_user_callback_result(true);
   EXPECT_CALL(*client, AuthenticateUserWithPasswordOrPin_(kSecondUserAccountId,
                                                           _, false, _));
@@ -1180,7 +1176,7 @@
   EXPECT_FALSE(test_api.detachable_base_error_bubble()->GetVisible());
 
   // Attempt and fail user auth - an auth error is expected to be shown.
-  std::unique_ptr<MockLoginScreenClient> client = BindMockLoginScreenClient();
+  auto client = std::make_unique<MockLoginScreenClient>();
   client->set_authenticate_user_callback_result(false);
   EXPECT_CALL(*client,
               AuthenticateUserWithPasswordOrPin_(kUserAccountId, _, false, _));
@@ -1240,7 +1236,7 @@
 
   // Attempt and fail user auth - an auth error is expected to be shown.
   // Detachable base error should not be hidden.
-  std::unique_ptr<MockLoginScreenClient> client = BindMockLoginScreenClient();
+  auto client = std::make_unique<MockLoginScreenClient>();
   client->set_authenticate_user_callback_result(false);
   EXPECT_CALL(*client,
               AuthenticateUserWithPasswordOrPin_(kUserAccountId, _, false, _));
@@ -1407,7 +1403,7 @@
 
   // Require that AuthenticateUser is called with authenticated_by_pin set to
   // true.
-  auto client = BindMockLoginScreenClient();
+  auto client = std::make_unique<MockLoginScreenClient>();
   EXPECT_CALL(*client, AuthenticateUserWithPasswordOrPin_(
                            _, "1111", true /*authenticated_by_pin*/, _));
 
@@ -1775,7 +1771,7 @@
             primary_id);
 
   // Expect LanuchPublicSession mojo call when the submit button is clicked.
-  std::unique_ptr<MockLoginScreenClient> client = BindMockLoginScreenClient();
+  auto client = std::make_unique<MockLoginScreenClient>();
   EXPECT_CALL(*client, LaunchPublicSession(primary_id, _, _));
 
   // Click on the submit button.
@@ -2111,7 +2107,7 @@
   SetUserCount(1);
   SetWidget(CreateWidgetWithContent(contents));
 
-  std::unique_ptr<MockLoginScreenClient> client = BindMockLoginScreenClient();
+  auto client = std::make_unique<MockLoginScreenClient>();
   EXPECT_CALL(*client, ShowResetScreen());
 
   ui::test::EventGenerator* generator = GetEventGenerator();
@@ -2175,7 +2171,7 @@
 
   // Attempt and fail user auth - an auth error is expected to be shown.
   // The warning banner should not be hidden.
-  std::unique_ptr<MockLoginScreenClient> client = BindMockLoginScreenClient();
+  auto client = std::make_unique<MockLoginScreenClient>();
   client->set_authenticate_user_callback_result(false);
   EXPECT_CALL(*client,
               AuthenticateUserWithPasswordOrPin_(kUserAccountId, _, false, _));
@@ -2326,12 +2322,11 @@
   SetWidget(CreateWidgetWithContent(lock));
 
   // FocusOobeDialog called when OOBE dialog visible.
-  std::unique_ptr<MockLoginScreenClient> client = BindMockLoginScreenClient();
+  auto client = std::make_unique<MockLoginScreenClient>();
   EXPECT_CALL(*client, FocusOobeDialog()).Times(1);
 
   DataDispatcher()->NotifyOobeDialogState(OobeDialogState::GAIA_SIGNIN);
   lock->OnFocusLeavingSystemTray(false /* reverse */);
-  Shell::Get()->login_screen_controller()->FlushForTesting();
 }
 
 TEST_F(LockContentsViewUnitTest, OnFocusLeavingSystemTrayWithOobeDialogClosed) {
@@ -2342,12 +2337,11 @@
   SetWidget(CreateWidgetWithContent(lock));
 
   // FocusOobeDialog not called when OOBE dialog not visible.
-  std::unique_ptr<MockLoginScreenClient> client = BindMockLoginScreenClient();
+  auto client = std::make_unique<MockLoginScreenClient>();
   EXPECT_CALL(*client, FocusOobeDialog()).Times(0);
 
   DataDispatcher()->NotifyOobeDialogState(OobeDialogState::HIDDEN);
   lock->OnFocusLeavingSystemTray(false /* reverse */);
-  Shell::Get()->login_screen_controller()->FlushForTesting();
 }
 
 TEST_F(LockContentsViewUnitTest, LoginNotReactingOnEventsWithOobeDialogShown) {
diff --git a/ash/login/ui/lock_screen_sanity_unittest.cc b/ash/login/ui/lock_screen_sanity_unittest.cc
index 7756cf6..63596f85 100644
--- a/ash/login/ui/lock_screen_sanity_unittest.cc
+++ b/ash/login/ui/lock_screen_sanity_unittest.cc
@@ -105,7 +105,7 @@
   std::unique_ptr<views::Widget> widget = CreateWidgetWithContent(contents);
 
   // Password submit runs mojo.
-  std::unique_ptr<MockLoginScreenClient> client = BindMockLoginScreenClient();
+  auto client = std::make_unique<MockLoginScreenClient>();
   client->set_authenticate_user_callback_result(false);
   EXPECT_CALL(*client, AuthenticateUserWithPasswordOrPin_(
                            users()[0].basic_user_info.account_id, _, false, _));
@@ -119,7 +119,7 @@
 // authentication request is complete and the auth fails.
 TEST_F(LockScreenSanityTest,
        PasswordSubmitClearsPasswordAfterFailedAuthentication) {
-  std::unique_ptr<MockLoginScreenClient> client = BindMockLoginScreenClient();
+  auto client = std::make_unique<MockLoginScreenClient>();
 
   auto* contents = new LockContentsView(
       mojom::TrayActionState::kAvailable, LockScreen::ScreenType::kLock,
@@ -130,7 +130,7 @@
   LoginPasswordView::TestApi password_test_api =
       MakeLoginPasswordTestApi(contents, AuthTarget::kPrimary);
 
-  MockLoginScreenClient::AuthenticateUserWithPasswordOrPinCallback callback;
+  base::OnceCallback<void(bool)> callback;
   auto submit_password = [&]() {
     // Capture the authentication callback.
     client->set_authenticate_user_with_password_or_pin_callback_storage(
@@ -172,7 +172,7 @@
 // Verifies that tabbing from the lock screen will eventually focus the shelf.
 // Then, a shift+tab will bring focus back to the lock screen.
 TEST_F(LockScreenSanityTest, TabGoesFromLockToShelfAndBackToLock) {
-  std::unique_ptr<MockLoginScreenClient> client = BindMockLoginScreenClient();
+  auto client = std::make_unique<MockLoginScreenClient>();
   // Make lock screen shelf visible.
   GetSessionControllerClient()->SetSessionState(
       session_manager::SessionState::LOCKED);
@@ -258,8 +258,6 @@
           ->GetStatusAreaWidget()
           ->GetContentsView();
 
-  LoginScreenController* controller = Shell::Get()->login_screen_controller();
-
   // Initialize lock screen action state.
   DataDispatcher()->SetLockScreenNoteState(mojom::TrayActionState::kActive);
 
@@ -273,7 +271,7 @@
   // Lock screen app focus is requested using lock screen mojo client - set up
   // the mock client.
   LockScreenAppFocuser app_widget_focuser(app_widget.get());
-  std::unique_ptr<MockLoginScreenClient> client = BindMockLoginScreenClient();
+  auto client = std::make_unique<MockLoginScreenClient>();
   EXPECT_CALL(*client, FocusLockScreenApps(_))
       .WillRepeatedly(Invoke(&app_widget_focuser,
                              &LockScreenAppFocuser::FocusLockScreenApp));
@@ -286,8 +284,6 @@
 
   // Reversing focus should bring focus back to the lock screen app.
   GetEventGenerator()->PressKey(ui::KeyboardCode::VKEY_TAB, ui::EF_SHIFT_DOWN);
-  // Focus is passed to lock screen apps via mojo - flush the request.
-  controller->FlushForTesting();
   EXPECT_TRUE(VerifyFocused(lock_screen_app));
   EXPECT_TRUE(app_widget_focuser.reversed_tab_order());
 
@@ -299,8 +295,6 @@
   // Tabbing out of the status area (in default order) should focus the lock
   // screen app again.
   GetEventGenerator()->PressKey(ui::KeyboardCode::VKEY_TAB, 0);
-  // Focus is passed to lock screen apps via mojo - flush the request.
-  controller->FlushForTesting();
   EXPECT_TRUE(VerifyFocused(lock_screen_app));
   EXPECT_FALSE(app_widget_focuser.reversed_tab_order());
 
@@ -349,9 +343,7 @@
 }
 
 TEST_F(LockScreenSanityTest, RemoveUser) {
-  std::unique_ptr<MockLoginScreenClient> client = BindMockLoginScreenClient();
-  LoginScreenController* controller =
-      ash::Shell::Get()->login_screen_controller();
+  auto client = std::make_unique<MockLoginScreenClient>();
 
   auto* contents = new LockContentsView(
       mojom::TrayActionState::kAvailable, LockScreen::ScreenType::kLock,
@@ -378,7 +370,6 @@
   // Fires a return and validates that mock expectations have been satisfied.
   auto submit = [&]() {
     GetEventGenerator()->PressKey(ui::VKEY_RETURN, 0);
-    controller->FlushForTesting();
     testing::Mock::VerifyAndClearExpectations(client.get());
   };
   auto focus_and_submit = [&](views::View* view) {
diff --git a/ash/login/ui/login_auth_user_view_unittest.cc b/ash/login/ui/login_auth_user_view_unittest.cc
index 28eef7f..6cd0df5 100644
--- a/ash/login/ui/login_auth_user_view_unittest.cc
+++ b/ash/login/ui/login_auth_user_view_unittest.cc
@@ -104,7 +104,7 @@
 // Verifies that pressing return with an empty password field when tap-to-unlock
 // is enabled attempts unlock.
 TEST_F(LoginAuthUserViewUnittest, PressReturnWithTapToUnlockEnabled) {
-  std::unique_ptr<MockLoginScreenClient> client = BindMockLoginScreenClient();
+  auto client = std::make_unique<MockLoginScreenClient>();
 
   ui::test::EventGenerator* generator = GetEventGenerator();
 
@@ -126,7 +126,7 @@
 }
 
 TEST_F(LoginAuthUserViewUnittest, OnlineSignInMessage) {
-  std::unique_ptr<MockLoginScreenClient> client = BindMockLoginScreenClient();
+  auto client = std::make_unique<MockLoginScreenClient>();
   LoginAuthUserView::TestApi test_auth_user_view(view_);
   views::Button* online_sign_in_message(
       test_auth_user_view.online_sign_in_message());
@@ -142,11 +142,10 @@
   EXPECT_FALSE(pin_view->GetVisible());
 
   // Clicking the message triggers |ShowGaiaSignin|.
-  EXPECT_CALL(*client,
-              ShowGaiaSignin(
-                  true /*can_close*/,
-                  base::Optional<AccountId>(
-                      user_view->current_user().basic_user_info.account_id)));
+  EXPECT_CALL(
+      *client,
+      ShowGaiaSignin(true /*can_close*/,
+                     user_view->current_user().basic_user_info.account_id));
   const ui::MouseEvent event(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
                              ui::EventTimeForNow(), 0, 0);
   view_->ButtonPressed(online_sign_in_message, event);
@@ -193,7 +192,7 @@
 
 TEST_F(LoginAuthUserViewUnittest, AttemptsUnlockOnLidOpen) {
   LoginAuthUserView::TestApi test_auth_user_view(view_);
-  std::unique_ptr<MockLoginScreenClient> client = BindMockLoginScreenClient();
+  auto client = std::make_unique<MockLoginScreenClient>();
 
   SetAuthMethods(LoginAuthUserView::AUTH_EXTERNAL_BINARY);
 
diff --git a/ash/login/ui/login_data_dispatcher.h b/ash/login/ui/login_data_dispatcher.h
index 64f8dad..6bb59eed 100644
--- a/ash/login/ui/login_data_dispatcher.h
+++ b/ash/login/ui/login_data_dispatcher.h
@@ -12,7 +12,6 @@
 #include "ash/ash_export.h"
 #include "ash/detachable_base/detachable_base_pairing_status.h"
 #include "ash/public/cpp/login_screen_model.h"
-#include "ash/public/interfaces/login_screen.mojom.h"
 #include "ash/public/interfaces/tray_action.mojom.h"
 #include "base/macros.h"
 #include "base/observer_list.h"
diff --git a/ash/login/ui/login_expanded_public_account_view_unittest.cc b/ash/login/ui/login_expanded_public_account_view_unittest.cc
index 3eca940..9eacf64 100644
--- a/ash/login/ui/login_expanded_public_account_view_unittest.cc
+++ b/ash/login/ui/login_expanded_public_account_view_unittest.cc
@@ -200,7 +200,7 @@
   EXPECT_EQ(selected_keyboard, kKeyboardIdForItem2);
 
   // Expect LanuchPublicSession mojo call when the submit button is clicked.
-  std::unique_ptr<MockLoginScreenClient> client = BindMockLoginScreenClient();
+  auto client = std::make_unique<MockLoginScreenClient>();
   EXPECT_CALL(*client,
               LaunchPublicSession(user_.basic_user_info.account_id,
                                   selected_language, selected_keyboard));
@@ -266,7 +266,7 @@
   // 2. Selected language item will change.
   // 3. Expect RequestPublicSessionKeyboardLayouts mojo call with the selected
   // language item.
-  std::unique_ptr<MockLoginScreenClient> client = BindMockLoginScreenClient();
+  auto client = std::make_unique<MockLoginScreenClient>();
   EXPECT_CALL(*client,
               RequestPublicSessionKeyboardLayouts(
                   user_.basic_user_info.account_id, kFrenchLanguageCode));
diff --git a/ash/login/ui/login_test_base.cc b/ash/login/ui/login_test_base.cc
index 86c34440..f3cec94f 100644
--- a/ash/login/ui/login_test_base.cc
+++ b/ash/login/ui/login_test_base.cc
@@ -14,7 +14,6 @@
 #include "ash/session/test_session_controller_client.h"
 #include "ash/shell.h"
 #include "ash/wallpaper/wallpaper_controller_impl.h"
-#include "base/bind.h"
 #include "base/strings/strcat.h"
 #include "ui/views/widget/widget.h"
 #include "ui/views/widget/widget_delegate.h"
@@ -50,14 +49,9 @@
       session_manager::SessionState::LOCKED);
   // The lock screen can't be shown without a wallpaper.
   Shell::Get()->wallpaper_controller()->ShowDefaultWallpaperForTesting();
-
-  base::Optional<bool> result;
-  Shell::Get()->login_screen_controller()->ShowLockScreen(base::BindOnce(
-      [](base::Optional<bool>* result, bool did_show) { *result = did_show; },
-      &result));
+  Shell::Get()->login_screen_controller()->ShowLockScreen();
+  // Allow focus to reach the appropriate View.
   base::RunLoop().RunUntilIdle();
-  ASSERT_TRUE(result.has_value());
-  ASSERT_EQ(*result, true);
 }
 
 void LoginTestBase::ShowLoginScreen() {
@@ -65,14 +59,9 @@
       session_manager::SessionState::LOGIN_PRIMARY);
   // The login screen can't be shown without a wallpaper.
   Shell::Get()->wallpaper_controller()->ShowDefaultWallpaperForTesting();
-
-  base::Optional<bool> result;
-  Shell::Get()->login_screen_controller()->ShowLoginScreen(base::BindOnce(
-      [](base::Optional<bool>* result, bool did_show) { *result = did_show; },
-      &result));
+  Shell::Get()->login_screen_controller()->ShowLoginScreen();
+  // Allow focus to reach the appropriate View.
   base::RunLoop().RunUntilIdle();
-  ASSERT_TRUE(result.has_value());
-  ASSERT_EQ(*result, true);
 }
 
 void LoginTestBase::SetWidget(std::unique_ptr<views::Widget> widget) {
@@ -151,9 +140,7 @@
 }
 
 LoginDataDispatcher* LoginTestBase::DataDispatcher() {
-  return LockScreen::HasInstance()
-             ? Shell::Get()->login_screen_controller()->data_dispatcher()
-             : &data_dispatcher_;
+  return Shell::Get()->login_screen_controller()->data_dispatcher();
 }
 
 void LoginTestBase::TearDown() {
diff --git a/ash/login/ui/login_test_base.h b/ash/login/ui/login_test_base.h
index d634a2a..57f1798f 100644
--- a/ash/login/ui/login_test_base.h
+++ b/ash/login/ui/login_test_base.h
@@ -7,7 +7,7 @@
 
 #include <memory>
 
-#include "ash/login/ui/login_data_dispatcher.h"
+#include "ash/public/cpp/login_types.h"
 #include "ash/test/ash_test_base.h"
 #include "base/macros.h"
 
@@ -18,6 +18,8 @@
 
 namespace ash {
 
+class LoginDataDispatcher;
+
 // Base test fixture for testing the views-based login and lock screens. This
 // class provides easy access to types which the login/lock frequently need.
 class LoginTestBase : public AshTestBase {
@@ -67,8 +69,7 @@
 
   const std::vector<LoginUserInfo>& users() const { return users_; }
 
-  // If the LockScreen is instantiated, returns its data dispatcher. Otherwise,
-  // returns a standalone instance.
+  // Returns the singleton LoginDataDispatcher.
   LoginDataDispatcher* DataDispatcher();
 
   // AshTestBase:
@@ -82,8 +83,6 @@
 
   std::vector<LoginUserInfo> users_;
 
-  LoginDataDispatcher data_dispatcher_;
-
   DISALLOW_COPY_AND_ASSIGN(LoginTestBase);
 };
 
diff --git a/ash/login/ui/parent_access_view.cc b/ash/login/ui/parent_access_view.cc
index 2847265..1efe760 100644
--- a/ash/login/ui/parent_access_view.cc
+++ b/ash/login/ui/parent_access_view.cc
@@ -623,10 +623,18 @@
   base::Optional<std::string> code = access_code_view_->GetCode();
   DCHECK(code.has_value());
 
-  Shell::Get()->login_screen_controller()->ValidateParentAccessCode(
-      account_id_, *code,
-      base::BindOnce(&ParentAccessView::OnValidationResult,
-                     weak_ptr_factory_.GetWeakPtr()));
+  bool result =
+      Shell::Get()->login_screen_controller()->ValidateParentAccessCode(
+          account_id_, *code);
+
+  if (result) {
+    VLOG(1) << "Parent access code successfully validated";
+    callbacks_.on_finished.Run(true);
+    return;
+  }
+
+  VLOG(1) << "Invalid parent access code entered";
+  UpdateState(State::kError);
 }
 
 void ParentAccessView::UpdateState(State state) {
@@ -658,17 +666,6 @@
   SetPreferredSize(CalculatePreferredSize());
 }
 
-void ParentAccessView::OnValidationResult(base::Optional<bool> result) {
-  if (result.has_value() && *result) {
-    VLOG(1) << "Parent access code successfully validated";
-    callbacks_.on_finished.Run(true);
-    return;
-  }
-
-  VLOG(1) << "Invalid parent access code entered";
-  UpdateState(State::kError);
-}
-
 void ParentAccessView::OnInputChange(bool complete) {
   if (state_ == State::kError)
     UpdateState(State::kNormal);
diff --git a/ash/login/ui/parent_access_view.h b/ash/login/ui/parent_access_view.h
index a6ccb8f..ef21b82 100644
--- a/ash/login/ui/parent_access_view.h
+++ b/ash/login/ui/parent_access_view.h
@@ -13,7 +13,6 @@
 #include "ash/wm/tablet_mode/tablet_mode_observer.h"
 #include "base/callback.h"
 #include "base/macros.h"
-#include "base/memory/weak_ptr.h"
 #include "base/optional.h"
 #include "base/scoped_observer.h"
 #include "components/account_id/account_id.h"
@@ -113,10 +112,6 @@
   // whether current input code is complete.
   void OnInputChange(bool complete);
 
-  // To be called when parent access code validation was completed. Result of
-  // the validation is available in |result| if validation was performed.
-  void OnValidationResult(base::Optional<bool> result);
-
   // Callbacks to be called when user performs certain actions.
   const Callbacks callbacks_;
 
@@ -138,8 +133,6 @@
   ScopedObserver<TabletModeController, TabletModeObserver>
       tablet_mode_observer_{this};
 
-  base::WeakPtrFactory<ParentAccessView> weak_ptr_factory_{this};
-
   DISALLOW_COPY_AND_ASSIGN(ParentAccessView);
 };
 
diff --git a/ash/login/ui/parent_access_view_unittest.cc b/ash/login/ui/parent_access_view_unittest.cc
index fc3a427..fc6f6da 100644
--- a/ash/login/ui/parent_access_view_unittest.cc
+++ b/ash/login/ui/parent_access_view_unittest.cc
@@ -47,7 +47,7 @@
     view_ = new ParentAccessView(account_id_, callbacks);
     SetWidget(CreateWidgetWithContent(view_));
 
-    login_client_ = BindMockLoginScreenClient();
+    login_client_ = std::make_unique<MockLoginScreenClient>();
   }
 
   // Simulates mouse press event on a |button|.
@@ -111,8 +111,7 @@
   EXPECT_TRUE(test_api.submit_button()->GetEnabled());
 
   login_client_->set_validate_parent_access_code_result(true);
-  EXPECT_CALL(*login_client_,
-              ValidateParentAccessCode_(account_id_, "012345", testing::_))
+  EXPECT_CALL(*login_client_, ValidateParentAccessCode_(account_id_, "012345"))
       .Times(1);
 
   SimulateButtonPress(test_api.submit_button());
@@ -130,8 +129,7 @@
   EXPECT_TRUE(test_api.submit_button()->GetEnabled());
 
   login_client_->set_validate_parent_access_code_result(true);
-  EXPECT_CALL(*login_client_,
-              ValidateParentAccessCode_(account_id_, "012345", testing::_))
+  EXPECT_CALL(*login_client_, ValidateParentAccessCode_(account_id_, "012345"))
       .Times(1);
 
   SimulateButtonPress(test_api.submit_button());
@@ -152,8 +150,7 @@
   EXPECT_TRUE(test_api.submit_button()->GetEnabled());
 
   login_client_->set_validate_parent_access_code_result(true);
-  EXPECT_CALL(*login_client_,
-              ValidateParentAccessCode_(account_id_, "012345", testing::_))
+  EXPECT_CALL(*login_client_, ValidateParentAccessCode_(account_id_, "012345"))
       .Times(1);
 
   generator->PressKey(ui::KeyboardCode::VKEY_RETURN, ui::EF_NONE);
@@ -187,8 +184,7 @@
   EXPECT_TRUE(test_api.submit_button()->GetEnabled());
 
   login_client_->set_validate_parent_access_code_result(true);
-  EXPECT_CALL(*login_client_,
-              ValidateParentAccessCode_(account_id_, "012349", testing::_))
+  EXPECT_CALL(*login_client_, ValidateParentAccessCode_(account_id_, "012349"))
       .Times(1);
 
   // Now the code should be submitted with enter key.
@@ -225,8 +221,7 @@
   EXPECT_TRUE(test_api.submit_button()->GetEnabled());
 
   login_client_->set_validate_parent_access_code_result(true);
-  EXPECT_CALL(*login_client_,
-              ValidateParentAccessCode_(account_id_, "111123", testing::_))
+  EXPECT_CALL(*login_client_, ValidateParentAccessCode_(account_id_, "111123"))
       .Times(1);
 
   SimulateButtonPress(test_api.submit_button());
@@ -247,8 +242,7 @@
   EXPECT_TRUE(test_api.submit_button()->GetEnabled());
 
   login_client_->set_validate_parent_access_code_result(true);
-  EXPECT_CALL(*login_client_,
-              ValidateParentAccessCode_(account_id_, "012345", testing::_))
+  EXPECT_CALL(*login_client_, ValidateParentAccessCode_(account_id_, "012345"))
       .Times(1);
 
   SimulateButtonPress(test_api.submit_button());
@@ -282,8 +276,7 @@
 
   // Error should be shown after unsuccessful validation.
   login_client_->set_validate_parent_access_code_result(false);
-  EXPECT_CALL(*login_client_,
-              ValidateParentAccessCode_(account_id_, "012345", testing::_))
+  EXPECT_CALL(*login_client_, ValidateParentAccessCode_(account_id_, "012345"))
       .Times(1);
 
   SimulateButtonPress(test_api.submit_button());
@@ -296,8 +289,7 @@
   EXPECT_EQ(ParentAccessView::State::kNormal, test_api.state());
 
   login_client_->set_validate_parent_access_code_result(true);
-  EXPECT_CALL(*login_client_,
-              ValidateParentAccessCode_(account_id_, "012346", testing::_))
+  EXPECT_CALL(*login_client_, ValidateParentAccessCode_(account_id_, "012346"))
       .Times(1);
 
   SimulateButtonPress(test_api.submit_button());
diff --git a/ash/magnifier/magnification_controller.cc b/ash/magnifier/magnification_controller.cc
index a9e6ed6..42db7ad3 100644
--- a/ash/magnifier/magnification_controller.cc
+++ b/ash/magnifier/magnification_controller.cc
@@ -179,8 +179,8 @@
   // TODO(spqchan): Fix the keyboard overscroll issues.
   auto config = keyboard::KeyboardController::Get()->keyboard_config();
   config.overscroll_behavior =
-      is_enabled_ ? keyboard::mojom::KeyboardOverscrollBehavior::kDisabled
-                  : keyboard::mojom::KeyboardOverscrollBehavior::kDefault;
+      is_enabled_ ? keyboard::KeyboardOverscrollBehavior::kDisabled
+                  : keyboard::KeyboardOverscrollBehavior::kDefault;
   keyboard::KeyboardController::Get()->UpdateKeyboardConfig(config);
 }
 
diff --git a/ash/mojo_interface_factory.cc b/ash/mojo_interface_factory.cc
index ce9103597..52602bd 100644
--- a/ash/mojo_interface_factory.cc
+++ b/ash/mojo_interface_factory.cc
@@ -17,9 +17,6 @@
 #include "ash/autotest/shelf_integration_test_api.h"
 #include "ash/display/cros_display_config.h"
 #include "ash/ime/ime_controller.h"
-#include "ash/keyboard/ash_keyboard_controller.h"
-#include "ash/keyboard/ui/keyboard_controller.h"
-#include "ash/kiosk_next/kiosk_next_shell_controller.h"
 #include "ash/login/login_screen_controller.h"
 #include "ash/media/media_controller_impl.h"
 #include "ash/public/cpp/ash_features.h"
@@ -99,20 +96,6 @@
   Shell::Get()->ime_controller()->BindRequest(std::move(request));
 }
 
-void BindKeyboardControllerRequestOnMainThread(
-    mojom::KeyboardControllerRequest request) {
-  Shell::Get()->ash_keyboard_controller()->BindRequest(std::move(request));
-}
-
-void BindKioskNextShellControllerRequestOnMainThread(
-    mojom::KioskNextShellControllerRequest request) {
-  Shell::Get()->kiosk_next_shell_controller()->BindRequest(std::move(request));
-}
-
-void BindLockScreenRequestOnMainThread(mojom::LoginScreenRequest request) {
-  Shell::Get()->login_screen_controller()->BindRequest(std::move(request));
-}
-
 void BindNightLightControllerRequestOnMainThread(
     mojom::NightLightControllerRequest request) {
   Shell::Get()->night_light_controller()->BindRequest(std::move(request));
@@ -174,21 +157,10 @@
   registry->AddInterface(
       base::BindRepeating(&BindAshMessageCenterControllerRequestOnMainThread),
       main_thread_task_runner);
-  if (base::FeatureList::IsEnabled(features::kKioskNextShell)) {
-    registry->AddInterface(
-        base::BindRepeating(&BindKioskNextShellControllerRequestOnMainThread),
-        main_thread_task_runner);
-  }
   registry->AddInterface(
       base::BindRepeating(&BindImeControllerRequestOnMainThread),
       main_thread_task_runner);
   registry->AddInterface(
-      base::BindRepeating(&BindKeyboardControllerRequestOnMainThread),
-      main_thread_task_runner);
-  registry->AddInterface(
-      base::BindRepeating(&BindLockScreenRequestOnMainThread),
-      main_thread_task_runner);
-  registry->AddInterface(
       base::BindRepeating(&BindNightLightControllerRequestOnMainThread),
       main_thread_task_runner);
   registry->AddInterface(
diff --git a/ash/public/cpp/BUILD.gn b/ash/public/cpp/BUILD.gn
index 8473d9f..ecf5389 100644
--- a/ash/public/cpp/BUILD.gn
+++ b/ash/public/cpp/BUILD.gn
@@ -87,11 +87,17 @@
     "immersive/immersive_fullscreen_controller_delegate.h",
     "immersive/immersive_revealed_lock.cc",
     "immersive/immersive_revealed_lock.h",
+    "keyboard/keyboard_config.h",
+    "keyboard/keyboard_controller.cc",
+    "keyboard/keyboard_controller.h",
     "keyboard/keyboard_switches.cc",
     "keyboard/keyboard_switches.h",
+    "keyboard/keyboard_types.h",
     "keyboard_shortcut_viewer.h",
     "kiosk_app_menu.cc",
     "kiosk_app_menu.h",
+    "kiosk_next_shell.cc",
+    "kiosk_next_shell.h",
     "locale_update_controller.cc",
     "locale_update_controller.h",
     "lock_screen_widget_factory.cc",
@@ -99,6 +105,7 @@
     "login_constants.h",
     "login_screen.cc",
     "login_screen.h",
+    "login_screen_client.h",
     "login_screen_model.cc",
     "login_screen_model.h",
     "login_types.cc",
diff --git a/ash/public/cpp/keyboard/keyboard_config.h b/ash/public/cpp/keyboard/keyboard_config.h
new file mode 100644
index 0000000..10de33ca
--- /dev/null
+++ b/ash/public/cpp/keyboard/keyboard_config.h
@@ -0,0 +1,64 @@
+// 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 ASH_PUBLIC_CPP_KEYBOARD_KEYBOARD_CONFIG_H_
+#define ASH_PUBLIC_CPP_KEYBOARD_KEYBOARD_CONFIG_H_
+
+#include <tuple>
+
+#include "ash/public/cpp/ash_public_export.h"
+
+namespace keyboard {
+
+// Determines how the keyboard overscroll enabled state is set.
+enum class KeyboardOverscrollBehavior {
+  // Use the default behavior.
+  kDefault,
+
+  // Enable keyboard overscroll if allowed.
+  kEnabled,
+
+  // Do not enable keyboard overscroll.
+  kDisabled,
+};
+
+struct KeyboardConfig {
+  // Whether the virtual keyboard can provide auto-complete.
+  bool auto_complete = true;
+
+  // Whether the virtual keyboard can provide auto-correct.
+  bool auto_correct = true;
+
+  // Whether the virtual keyboard can provide auto-capitalization.
+  bool auto_capitalize = true;
+
+  // Whether the virtual keyboard can provide input via handwriting recognition.
+  bool handwriting = true;
+
+  // Whether the virtual keyboard can provide spell-check.
+  bool spell_check = true;
+
+  // Whether the virtual keyboard can provide voice input.
+  bool voice_input = true;
+
+  // Whether overscroll is currently allowed by the active keyboard container.
+  KeyboardOverscrollBehavior overscroll_behavior =
+      KeyboardOverscrollBehavior::kDefault;
+
+  bool operator==(const KeyboardConfig& other) const {
+    return std::tie(auto_complete, auto_correct, auto_capitalize, handwriting,
+                    spell_check, voice_input, overscroll_behavior) ==
+           std::tie(other.auto_complete, other.auto_correct,
+                    other.auto_capitalize, other.handwriting, other.spell_check,
+                    other.voice_input, other.overscroll_behavior);
+  }
+
+  bool operator!=(const KeyboardConfig& other) const {
+    return !(*this == other);
+  }
+};
+
+}  // namespace keyboard
+
+#endif  // ASH_PUBLIC_CPP_KEYBOARD_KEYBOARD_CONFIG_H_
diff --git a/ash/public/cpp/keyboard/keyboard_controller.cc b/ash/public/cpp/keyboard/keyboard_controller.cc
new file mode 100644
index 0000000..e42fc02
--- /dev/null
+++ b/ash/public/cpp/keyboard/keyboard_controller.cc
@@ -0,0 +1,27 @@
+// 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 "ash/public/cpp/keyboard/keyboard_controller.h"
+
+namespace ash {
+
+// static
+KeyboardController* KeyboardController::Get() {
+  return g_instance_;
+}
+
+KeyboardController::KeyboardController() {
+  DCHECK(!g_instance_);
+  g_instance_ = this;
+}
+
+KeyboardController::~KeyboardController() {
+  DCHECK_EQ(g_instance_, this);
+  g_instance_ = nullptr;
+}
+
+// static
+KeyboardController* KeyboardController::g_instance_ = nullptr;
+
+}  // namespace ash
diff --git a/ash/public/cpp/keyboard/keyboard_controller.h b/ash/public/cpp/keyboard/keyboard_controller.h
new file mode 100644
index 0000000..79fdf01
--- /dev/null
+++ b/ash/public/cpp/keyboard/keyboard_controller.h
@@ -0,0 +1,155 @@
+// 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 ASH_PUBLIC_CPP_KEYBOARD_KEYBOARD_CONTROLLER_H_
+#define ASH_PUBLIC_CPP_KEYBOARD_KEYBOARD_CONTROLLER_H_
+
+#include "ash/public/cpp/ash_public_export.h"
+#include "ash/public/cpp/keyboard/keyboard_config.h"
+#include "ash/public/cpp/keyboard/keyboard_types.h"
+#include "base/optional.h"
+#include "ui/gfx/geometry/rect.h"
+
+namespace ash {
+
+enum class HideReason {
+  // Hide requested by an explicit user action.
+  kUser,
+
+  // Hide requested due to a system event (e.g. because it would interfere with
+  // a menu or other on screen UI).
+  kSystem,
+};
+
+class KeyboardControllerObserver {
+ public:
+  virtual ~KeyboardControllerObserver() {}
+
+  // Called when a keyboard enable flag changes.
+  virtual void OnKeyboardEnableFlagsChanged(
+      const std::vector<keyboard::KeyboardEnableFlag>& flags) = 0;
+
+  // Called when the keyboard is enabled or disabled. If ReloadKeyboard() is
+  // called or other code enables the keyboard while already enabled, this will
+  // be called twice, once when the keyboard is disabled and again when it is
+  // re-enabled.
+  virtual void OnKeyboardEnabledChanged(bool is_enabled) = 0;
+
+  // Called when the virtual keyboard configuration changes.
+  virtual void OnKeyboardConfigChanged(
+      const keyboard::KeyboardConfig& config) = 0;
+
+  // Called when the visibility of the virtual keyboard changes, e.g. an input
+  // field is focused or blurred, or the user hides the keyboard.
+  virtual void OnKeyboardVisibilityChanged(bool visible) = 0;
+
+  // Called when the keyboard bounds change. |screen_bounds| is in screen
+  // coordinates.
+  virtual void OnKeyboardVisibleBoundsChanged(
+      const gfx::Rect& screen_bounds) = 0;
+
+  // Called when the keyboard occluded bounds change. |screen_bounds| is in
+  // screen coordinates.
+  virtual void OnKeyboardOccludedBoundsChanged(
+      const gfx::Rect& screen_bounds) = 0;
+
+  // Signals a request to load the keyboard contents. If the contents are
+  // already loaded, requests a reload. Once the contents have loaded,
+  // KeyboardController.KeyboardContentsLoaded is expected to be called by the
+  // client implementation.
+  virtual void OnLoadKeyboardContentsRequested() = 0;
+
+  // Called when the UI has been destroyed so that the client can reset the
+  // embedded contents and handle.
+  virtual void OnKeyboardUIDestroyed() = 0;
+};
+
+class ASH_PUBLIC_EXPORT KeyboardController {
+ public:
+  using GetKeyboardConfigCallback =
+      base::OnceCallback<void(const keyboard::KeyboardConfig&)>;
+  using IsKeyboardEnabledCallback = base::OnceCallback<void(bool)>;
+  using GetEnableFlagsCallback = base::OnceCallback<void(
+      const std::vector<keyboard::KeyboardEnableFlag>&)>;
+  using IsKeyboardVisibleCallback = base::OnceCallback<void(bool)>;
+  using SetContainerTypeCallback = base::OnceCallback<void(bool)>;
+
+  static KeyboardController* Get();
+
+  // Sets the global KeyboardController instance to |this|.
+  KeyboardController();
+
+  virtual ~KeyboardController();
+
+  // Informs the controller that the keyboard contents have loaded.
+  virtual void KeyboardContentsLoaded(const gfx::Size& size) = 0;
+
+  // Retrieves the current keyboard configuration.
+  virtual void GetKeyboardConfig(GetKeyboardConfigCallback callback) = 0;
+
+  // Sets the current keyboard configuration.
+  virtual void SetKeyboardConfig(const keyboard::KeyboardConfig& config) = 0;
+
+  // Returns whether the virtual keyboard has been enabled.
+  virtual void IsKeyboardEnabled(IsKeyboardVisibleCallback callback) = 0;
+
+  // Sets the provided keyboard enable flag. If the computed enabled state
+  // changes, enables or disables the keyboard to match the new state.
+  virtual void SetEnableFlag(keyboard::KeyboardEnableFlag flag) = 0;
+
+  // Clears the provided keyboard enable flag. If the computed enabled state
+  // changes, enables or disables the keyboard to match the new state.
+  virtual void ClearEnableFlag(keyboard::KeyboardEnableFlag flag) = 0;
+
+  // Gets the current set of keyboard enable flags.
+  virtual void GetEnableFlags(GetEnableFlagsCallback callback) = 0;
+
+  // Reloads the virtual keyboard if it is enabled and the URL has changed, e.g.
+  // the focus has switched from one type of field to another.
+  virtual void ReloadKeyboardIfNeeded() = 0;
+
+  // Rebuilds (disables and re-enables) the virtual keyboard if it is enabled.
+  // This is used to force a reload of the virtual keyboard when preferences or
+  // other configuration that affects loading the keyboard may have changed.
+  virtual void RebuildKeyboardIfEnabled() = 0;
+
+  // Returns whether the virtual keyboard is visible.
+  virtual void IsKeyboardVisible(IsKeyboardVisibleCallback callback) = 0;
+
+  // Shows the virtual keyboard on the current display if it is enabled.
+  virtual void ShowKeyboard() = 0;
+
+  // Hides the virtual keyboard if it is visible.
+  virtual void HideKeyboard(HideReason reason) = 0;
+
+  // Sets the keyboard container type. If non empty, |target_bounds| provides
+  // the container size. Returns whether the transition succeeded once the
+  // container type changes (or fails to change).
+  virtual void SetContainerType(keyboard::ContainerType container_type,
+                                const base::Optional<gfx::Rect>& target_bounds,
+                                SetContainerTypeCallback callback) = 0;
+
+  // If |locked| is true, the keyboard remains visible even when no window has
+  // input focus.
+  virtual void SetKeyboardLocked(bool locked) = 0;
+
+  // Sets the regions of the keyboard window that occlude whatever is behind it.
+  virtual void SetOccludedBounds(const std::vector<gfx::Rect>& bounds) = 0;
+
+  // Sets the regions of the keyboard window where events should be handled.
+  virtual void SetHitTestBounds(const std::vector<gfx::Rect>& bounds) = 0;
+
+  // Sets the region of the keyboard window that can be used as a drag handle.
+  virtual void SetDraggableArea(const gfx::Rect& bounds) = 0;
+
+  // Adds a KeyboardControllerObserver.
+  virtual void AddObserver(KeyboardControllerObserver* observer) = 0;
+
+ protected:
+  static KeyboardController* g_instance_;
+};
+
+}  // namespace ash
+
+#endif  // ASH_PUBLIC_CPP_KEYBOARD_KEYBOARD_CONTROLLER_H_
diff --git a/ash/public/interfaces/keyboard_controller_types.mojom b/ash/public/cpp/keyboard/keyboard_types.h
similarity index 76%
rename from ash/public/interfaces/keyboard_controller_types.mojom
rename to ash/public/cpp/keyboard/keyboard_types.h
index dfa41cf..6c30203 100644
--- a/ash/public/interfaces/keyboard_controller_types.mojom
+++ b/ash/public/cpp/keyboard/keyboard_types.h
@@ -1,14 +1,19 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
+// 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.
 
-module keyboard.mojom;
+#ifndef ASH_PUBLIC_CPP_KEYBOARD_KEYBOARD_TYPES_H_
+#define ASH_PUBLIC_CPP_KEYBOARD_KEYBOARD_TYPES_H_
+
+#include "ash/public/cpp/ash_public_export.h"
+
+namespace keyboard {
 
 // Flags that affect whether or not the virtual keyboard should be enabled.
 // Enabled/Disabled flag pairs are mutually exclusive, but flags from multiple
 // sources may be set. Precedence is determined by the implementation in
 // KeyboardController::IsKeyboardEnableRequested.
-enum KeyboardEnableFlag {
+enum class KeyboardEnableFlag {
   // Enabled by policy.
   kPolicyEnabled,
 
@@ -40,7 +45,7 @@
 
 // Container types used to set and identify container behavior. Used in UMA
 // stats gathering, so values should never be changed or reused.
-enum ContainerType {
+enum class ContainerType {
   // Corresponds to a ContainerFullWidthBehavior.
   kFullWidth = 0,
 
@@ -49,4 +54,10 @@
 
   // Corresponds to a ContainerFullscreenBehavior.
   // kFullscreen = 2,  // Deprecated; feature was abandoned.
+
+  kMaxValue = ContainerType::kFloating,
 };
+
+}  // namespace keyboard
+
+#endif  // ASH_PUBLIC_CPP_KEYBOARD_KEYBOARD_TYPES_H_
diff --git a/ash/public/cpp/kiosk_next_shell.cc b/ash/public/cpp/kiosk_next_shell.cc
new file mode 100644
index 0000000..cb9d503f
--- /dev/null
+++ b/ash/public/cpp/kiosk_next_shell.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 "ash/public/cpp/kiosk_next_shell.h"
+
+#include "base/logging.h"
+
+namespace ash {
+
+namespace {
+KioskNextShellController* g_instance = nullptr;
+}
+
+// static
+KioskNextShellController* KioskNextShellController::Get() {
+  return g_instance;
+}
+
+KioskNextShellController::KioskNextShellController() {
+  DCHECK_EQ(nullptr, g_instance);
+  g_instance = this;
+}
+
+KioskNextShellController::~KioskNextShellController() {
+  DCHECK_EQ(this, g_instance);
+  g_instance = nullptr;
+}
+
+}  // namespace ash
diff --git a/ash/public/cpp/kiosk_next_shell.h b/ash/public/cpp/kiosk_next_shell.h
new file mode 100644
index 0000000..7011e6c
--- /dev/null
+++ b/ash/public/cpp/kiosk_next_shell.h
@@ -0,0 +1,42 @@
+// 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 ASH_PUBLIC_CPP_KIOSK_NEXT_SHELL_H_
+#define ASH_PUBLIC_CPP_KIOSK_NEXT_SHELL_H_
+
+#include "ash/public/cpp/ash_public_export.h"
+
+class AccountId;
+
+namespace ash {
+
+// Performs browser-side functionality for Kiosk Next, e.g. launching the
+// KioskNextShell.
+class ASH_PUBLIC_EXPORT KioskNextShellClient {
+ public:
+  // Launch the Kiosk Next Shell for the user identified by |account_id|.
+  virtual void LaunchKioskNextShell(const AccountId& account_id) = 0;
+
+ protected:
+  virtual ~KioskNextShellClient() = default;
+};
+
+// Interface that allows Chrome to notify Ash when the KioskNextShellClient is
+// ready.
+class ASH_PUBLIC_EXPORT KioskNextShellController {
+ public:
+  static KioskNextShellController* Get();
+
+  // Registers the client, and if non-null, launches the Kiosk Next Shell
+  // session.
+  virtual void SetClientAndLaunchSession(KioskNextShellClient* client) = 0;
+
+ protected:
+  KioskNextShellController();
+  virtual ~KioskNextShellController();
+};
+
+}  // namespace ash
+
+#endif  // ASH_PUBLIC_CPP_KIOSK_NEXT_SHELL_H_
diff --git a/ash/public/cpp/login_screen.h b/ash/public/cpp/login_screen.h
index c9795c3..b63dc66e 100644
--- a/ash/public/cpp/login_screen.h
+++ b/ash/public/cpp/login_screen.h
@@ -14,6 +14,7 @@
 
 namespace ash {
 
+class LoginScreenClient;
 class LoginScreenModel;
 
 // Allows clients (e.g. the browser process) to send messages to the ash
@@ -24,8 +25,16 @@
   // Returns the singleton instance.
   static LoginScreen* Get();
 
+  virtual void SetClient(LoginScreenClient* client) = 0;
+
   virtual LoginScreenModel* GetModel() = 0;
 
+  // Displays the lock screen.
+  virtual void ShowLockScreen() = 0;
+
+  // Displays the login screen.
+  virtual void ShowLoginScreen() = 0;
+
   // Display a toast describing the latest kiosk app launch error.
   virtual void ShowKioskAppError(const std::string& message) = 0;
 
diff --git a/ash/public/cpp/login_screen_client.h b/ash/public/cpp/login_screen_client.h
new file mode 100644
index 0000000..f86e60c
--- /dev/null
+++ b/ash/public/cpp/login_screen_client.h
@@ -0,0 +1,157 @@
+// 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 ASH_PUBLIC_CPP_LOGIN_SCREEN_CLIENT_H_
+#define ASH_PUBLIC_CPP_LOGIN_SCREEN_CLIENT_H_
+
+#include <string>
+
+#include "ash/public/cpp/ash_public_export.h"
+#include "base/callback_forward.h"
+
+class AccountId;
+
+namespace ash {
+
+// An interface allows Ash to trigger certain login steps that Chrome is
+// responsible for.
+class ASH_PUBLIC_EXPORT LoginScreenClient {
+ public:
+  // Attempt to authenticate a user with a password or PIN.
+  //
+  // If auth succeeds:
+  // chrome will hide the lock screen and clear any displayed error messages.
+  // If auth fails:
+  // chrome will request lock screen to show error messages.
+  // |account_id|: The AccountId to authenticate against.
+  // |password|: The submitted password.
+  // |authenticated_by_pin|: True if we are using pin to authenticate.
+  //
+  // The result will be set to true if auth was successful, false if not.
+  //
+  // TODO(jdufault): Extract authenticated_by_pin into a separate method,
+  //                 similar to the other Authenticate* methods
+  virtual void AuthenticateUserWithPasswordOrPin(
+      const AccountId& account_id,
+      const std::string& password,
+      bool authenticated_by_pin,
+      base::OnceCallback<void(bool)> callback) = 0;
+
+  // Attempt to authenticate the user with with an external binary.
+  virtual void AuthenticateUserWithExternalBinary(
+      const AccountId& account_id,
+      base::OnceCallback<void(bool)> callback) = 0;
+
+  // Attempt to enroll a user in the external binary authentication system.
+  virtual void EnrollUserWithExternalBinary(
+      base::OnceCallback<void(bool)> callback) = 0;
+
+  // Try to authenticate |account_id| using easy unlock. This can be used on the
+  // login or lock screen.
+  // |account_id|: The account id of the user we are authenticating.
+  //
+  // TODO(jdufault): Refactor this method to return an auth_success, similar to
+  // the other auth methods above.
+  virtual void AuthenticateUserWithEasyUnlock(const AccountId& account_id) = 0;
+
+  // Validates parent access code for the user identified by |account_id|. When
+  // |account_id| is empty it tries to validate the access code for any child
+  // that is signed in the device. Returns validation result.
+  // Note: This should only be used for child user, it will always return false
+  // when a non-child id is used.
+  // TODO(crbug.com/965479): move this to a more appropriate place.
+  virtual bool ValidateParentAccessCode(const AccountId& account_id,
+                                        const std::string& access_code) = 0;
+
+  // Request to hard lock the user pod.
+  // |account_id|:    The account id of the user in the user pod.
+  virtual void HardlockPod(const AccountId& account_id) = 0;
+
+  // Focus user pod of user with |account_id|.
+  virtual void OnFocusPod(const AccountId& account_id) = 0;
+
+  // Notify that no user pod is focused.
+  virtual void OnNoPodFocused() = 0;
+
+  // Load wallpaper of user with |account_id|.
+  virtual void LoadWallpaper(const AccountId& account_id) = 0;
+
+  // Sign out current user.
+  virtual void SignOutUser() = 0;
+
+  // Close add user screen.
+  virtual void CancelAddUser() = 0;
+
+  // Launches guest mode.
+  virtual void LoginAsGuest() = 0;
+
+  // User with |account_id| has reached maximum incorrect password attempts.
+  virtual void OnMaxIncorrectPasswordAttempted(const AccountId& account_id) = 0;
+
+  // Should pass the focus to the active lock screen app window, if there is
+  // one. This is called when a lock screen app is reported to be active (using
+  // tray_action mojo interface), and is next in the tab order.
+  // |HandleFocusLeavingLockScreenApps| should be called to return focus to the
+  // lock screen.
+  // |reverse|:   Whether the tab order is reversed.
+  virtual void FocusLockScreenApps(bool reverse) = 0;
+
+  // Passes focus to the OOBE dialog if it is showing. No-op otherwise.
+  virtual void FocusOobeDialog() = 0;
+
+  // Show the gaia sign-in dialog. If |can_close| is true, the dialog can be
+  // closed. The value in |prefilled_account| will be used to prefill the
+  // sign-in dialog so the user does not need to type the account email.
+  virtual void ShowGaiaSignin(bool can_close,
+                              const AccountId& prefilled_account) = 0;
+
+  // Notification that the remove user warning was shown.
+  virtual void OnRemoveUserWarningShown() = 0;
+
+  // Try to remove |account_id|.
+  virtual void RemoveUser(const AccountId& account_id) = 0;
+
+  // Launch a public session for user with |account_id|.
+  // |locale|:       Locale for this user.
+  //                 The value is language code like "en-US", "zh-CN"
+  // |input_method|: Input method for this user.
+  //                 This is the id of InputMethodDescriptor like
+  //                 "t:latn-post", "pinyin".
+  virtual void LaunchPublicSession(const AccountId& account_id,
+                                   const std::string& locale,
+                                   const std::string& input_method) = 0;
+
+  // Request public session keyboard layouts for user with |account_id|.
+  // This function send a request to chrome and the result will be returned by
+  // SetPublicSessionKeyboardLayouts.
+  // |locale|: Request a list of keyboard layouts that can be used by this
+  //           locale.
+  virtual void RequestPublicSessionKeyboardLayouts(
+      const AccountId& account_id,
+      const std::string& locale) = 0;
+
+  // Request to show a feedback report dialog in chrome.
+  virtual void ShowFeedback() = 0;
+
+  // Show the powerwash (device reset) dialog.
+  virtual void ShowResetScreen() = 0;
+
+  // Show the help app for when users have trouble signing in to their account.
+  virtual void ShowAccountAccessHelpApp() = 0;
+
+  // Called when the keyboard focus is about to leave from the system tray in
+  // the login screen / OOBE. |reverse| is true when the focus moves in the
+  // reversed direction.
+  virtual void OnFocusLeavingSystemTray(bool reverse) = 0;
+
+  // Used by Ash to signal that user activity occurred on the login screen.
+  virtual void OnUserActivity() = 0;
+
+ protected:
+  virtual ~LoginScreenClient() = default;
+};
+
+}  // namespace ash
+
+#endif  // ASH_PUBLIC_CPP_LOGIN_SCREEN_CLIENT_H_
diff --git a/ash/public/cpp/login_types.h b/ash/public/cpp/login_types.h
index 0434503..575b5ac8 100644
--- a/ash/public/cpp/login_types.h
+++ b/ash/public/cpp/login_types.h
@@ -130,7 +130,7 @@
   // If true, clicking the easy unlock icon should fire a hardlock event which
   // will disable easy unlock. The hardlock event will request a new icon
   // display via a separate EasyUnlockIconsOption update. See
-  // login_screen.mojom::HardlockPod.
+  // LoginScreenClient::HardlockPod.
   bool hardlock_on_click = false;
 };
 
diff --git a/ash/public/cpp/manifest.cc b/ash/public/cpp/manifest.cc
index 6a9a773..de4c58e 100644
--- a/ash/public/cpp/manifest.cc
+++ b/ash/public/cpp/manifest.cc
@@ -12,9 +12,6 @@
 #include "ash/public/interfaces/constants.mojom.h"
 #include "ash/public/interfaces/cros_display_config.mojom.h"
 #include "ash/public/interfaces/ime_controller.mojom.h"
-#include "ash/public/interfaces/keyboard_controller.mojom.h"
-#include "ash/public/interfaces/kiosk_next_shell.mojom.h"
-#include "ash/public/interfaces/login_screen.mojom.h"
 #include "ash/public/interfaces/night_light_controller.mojom.h"
 #include "ash/public/interfaces/shelf_integration_test_api.mojom.h"
 #include "ash/public/interfaces/tray_action.mojom.h"
@@ -59,9 +56,7 @@
                   mojom::AssistantNotificationController,
                   mojom::AssistantScreenContextController,
                   mojom::AssistantVolumeControl,
-                  mojom::KioskNextShellController,
                   mojom::CrosDisplayConfigController, mojom::ImeController,
-                  mojom::KeyboardController, mojom::LoginScreen,
                   mojom::NightLightController, mojom::TrayAction,
                   mojom::VoiceInteractionController, mojom::VpnList>())
           .ExposeCapability("test", service_manager::Manifest::InterfaceList<
diff --git a/ash/public/cpp/test/test_keyboard_controller_observer.cc b/ash/public/cpp/test/test_keyboard_controller_observer.cc
index 4d31b3f..906c147 100644
--- a/ash/public/cpp/test/test_keyboard_controller_observer.cc
+++ b/ash/public/cpp/test/test_keyboard_controller_observer.cc
@@ -9,17 +9,15 @@
 namespace ash {
 
 TestKeyboardControllerObserver::TestKeyboardControllerObserver(
-    mojom::KeyboardController* controller)
+    KeyboardController* controller)
     : controller_(controller) {
-  keyboard_controller_observer_binding_.Bind(
-      mojo::MakeRequestAssociatedWithDedicatedPipe(&ptr_));
-  controller_->AddObserver(ptr_.PassInterface());
+  controller_->AddObserver(this);
 }
 
 TestKeyboardControllerObserver::~TestKeyboardControllerObserver() = default;
 
 void TestKeyboardControllerObserver::OnKeyboardEnableFlagsChanged(
-    const std::vector<keyboard::mojom::KeyboardEnableFlag>& flags) {
+    const std::vector<keyboard::KeyboardEnableFlag>& flags) {
   enable_flags_ = flags;
 }
 
@@ -29,8 +27,8 @@
 }
 
 void TestKeyboardControllerObserver::OnKeyboardConfigChanged(
-    keyboard::mojom::KeyboardConfigPtr config) {
-  config_ = *config;
+    const keyboard::KeyboardConfig& config) {
+  config_ = config;
 }
 
 void TestKeyboardControllerObserver::OnKeyboardVisibilityChanged(bool visible) {
diff --git a/ash/public/cpp/test/test_keyboard_controller_observer.h b/ash/public/cpp/test/test_keyboard_controller_observer.h
index 9f9988a4..e089225 100644
--- a/ash/public/cpp/test/test_keyboard_controller_observer.h
+++ b/ash/public/cpp/test/test_keyboard_controller_observer.h
@@ -5,51 +5,42 @@
 #ifndef ASH_PUBLIC_CPP_TEST_TEST_KEYBOARD_CONTROLLER_OBSERVER_H_
 #define ASH_PUBLIC_CPP_TEST_TEST_KEYBOARD_CONTROLLER_OBSERVER_H_
 
-#include "ash/public/interfaces/keyboard_config.mojom.h"
-#include "ash/public/interfaces/keyboard_controller.mojom.h"
-#include "mojo/public/cpp/bindings/associated_binding.h"
+#include "ash/public/cpp/keyboard/keyboard_config.h"
+#include "ash/public/cpp/keyboard/keyboard_controller.h"
 
 namespace ash {
 
-// mojom::KeyboardControllerObserver implementation for tests. This class
+// :KeyboardControllerObserver implementation for tests. This class
 // implements a test client observer for tests running with the Window Service.
 
-class TestKeyboardControllerObserver
-    : public mojom::KeyboardControllerObserver {
+class TestKeyboardControllerObserver : public KeyboardControllerObserver {
  public:
-  explicit TestKeyboardControllerObserver(
-      mojom::KeyboardController* controller);
+  explicit TestKeyboardControllerObserver(KeyboardController* controller);
   ~TestKeyboardControllerObserver() override;
 
-  // mojom::KeyboardControllerObserver
+  // KeyboardControllerObserver:
   void OnKeyboardEnableFlagsChanged(
-      const std::vector<keyboard::mojom::KeyboardEnableFlag>& flags) override;
+      const std::vector<keyboard::KeyboardEnableFlag>& flags) override;
   void OnKeyboardEnabledChanged(bool enabled) override;
-  void OnKeyboardConfigChanged(
-      keyboard::mojom::KeyboardConfigPtr config) override;
+  void OnKeyboardConfigChanged(const keyboard::KeyboardConfig& config) override;
   void OnKeyboardVisibilityChanged(bool visible) override;
   void OnKeyboardVisibleBoundsChanged(const gfx::Rect& bounds) override;
   void OnKeyboardOccludedBoundsChanged(const gfx::Rect& bounds) override;
   void OnLoadKeyboardContentsRequested() override;
   void OnKeyboardUIDestroyed() override;
 
-  const keyboard::mojom::KeyboardConfig& config() const { return config_; }
-  void set_config(const keyboard::mojom::KeyboardConfig& config) {
-    config_ = config;
-  }
-  const std::vector<keyboard::mojom::KeyboardEnableFlag>& enable_flags() const {
+  const keyboard::KeyboardConfig& config() const { return config_; }
+  void set_config(const keyboard::KeyboardConfig& config) { config_ = config; }
+  const std::vector<keyboard::KeyboardEnableFlag>& enable_flags() const {
     return enable_flags_;
   }
   int destroyed_count() const { return destroyed_count_; }
 
  private:
-  mojom::KeyboardController* controller_;
-  mojom::KeyboardControllerObserverAssociatedPtr ptr_;
-  std::vector<keyboard::mojom::KeyboardEnableFlag> enable_flags_;
-  keyboard::mojom::KeyboardConfig config_;
+  KeyboardController* controller_;
+  std::vector<keyboard::KeyboardEnableFlag> enable_flags_;
+  keyboard::KeyboardConfig config_;
   int destroyed_count_ = 0;
-  mojo::AssociatedBinding<mojom::KeyboardControllerObserver>
-      keyboard_controller_observer_binding_{this};
 
   DISALLOW_COPY_AND_ASSIGN(TestKeyboardControllerObserver);
 };
diff --git a/ash/public/interfaces/BUILD.gn b/ash/public/interfaces/BUILD.gn
index d273c8af..6fc0e57 100644
--- a/ash/public/interfaces/BUILD.gn
+++ b/ash/public/interfaces/BUILD.gn
@@ -26,11 +26,6 @@
     "cros_display_config.mojom",
     "ime_controller.mojom",
     "ime_info.mojom",
-    "keyboard_config.mojom",
-    "keyboard_controller.mojom",
-    "keyboard_controller_types.mojom",
-    "kiosk_next_shell.mojom",
-    "login_screen.mojom",
     "night_light_controller.mojom",
     "shelf_integration_test_api.mojom",
     "tray_action.mojom",
diff --git a/ash/public/interfaces/keyboard_config.mojom b/ash/public/interfaces/keyboard_config.mojom
deleted file mode 100644
index 737671d..0000000
--- a/ash/public/interfaces/keyboard_config.mojom
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2018 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.
-
-module keyboard.mojom;
-
-// Determines how the keyboard overscroll enabled state is set.
-enum KeyboardOverscrollBehavior {
-  // Use the default behavior.
-  kDefault,
-
-  // Enable keyboard overscroll if allowed.
-  kEnabled,
-
-  // Do not enable keyboard overscroll.
-  kDisabled,
-};
-
-struct KeyboardConfig {
-  // Whether the virtual keyboard can provide auto-complete.
-  bool auto_complete = true;
-
-  // Whether the virtual keyboard can provide auto-correct.
-  bool auto_correct = true;
-
-  // Whether the virtual keyboard can provide auto-capitalization.
-  bool auto_capitalize = true;
-
-  // Whether the virtual keyboard can provide input via handwriting recognition.
-  bool handwriting = true;
-
-  // Whether the virtual keyboard can provide spell-check.
-  bool spell_check = true;
-
-  // Whether the virtual keyboard can provide voice input.
-  bool voice_input = true;
-
-  // Whether overscroll is currently allowed by the active keyboard container.
-  KeyboardOverscrollBehavior overscroll_behavior = kDefault;
-};
diff --git a/ash/public/interfaces/keyboard_controller.mojom b/ash/public/interfaces/keyboard_controller.mojom
deleted file mode 100644
index a27418c..0000000
--- a/ash/public/interfaces/keyboard_controller.mojom
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright 2018 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.
-
-module ash.mojom;
-
-import "ash/public/interfaces/keyboard_config.mojom";
-import "ash/public/interfaces/keyboard_controller_types.mojom";
-import "ui/gfx/geometry/mojo/geometry.mojom";
-
-enum HideReason {
-  // Hide requested by an explicit user action.
-  kUser,
-
-  // Hide requested due to a system event (e.g. because it would interfere with
-  // a menu or other on screen UI).
-  kSystem,
-};
-
-interface KeyboardControllerObserver {
-  // Called when a keyboard enable flag changes.
-  OnKeyboardEnableFlagsChanged(array<keyboard.mojom.KeyboardEnableFlag> flags);
-
-  // Called when the keyboard is enabled or disabled. If ReloadKeyboard() is
-  // called or other code enables the keyboard while already enabled, this will
-  // be called twice, once when the keyboard is disabled and again when it is
-  // re-enabled.
-  OnKeyboardEnabledChanged(bool is_enabled);
-
-  // Called when the virtual keyboard configuration changes.
-  OnKeyboardConfigChanged(keyboard.mojom.KeyboardConfig config);
-
-  // Called when the visibility of the virtual keyboard changes, e.g. an input
-  // field is focused or blurred, or the user hides the keyboard.
-  OnKeyboardVisibilityChanged(bool visible);
-
-  // Called when the keyboard bounds change. |screen_bounds| is in screen
-  // coordinates.
-  OnKeyboardVisibleBoundsChanged(gfx.mojom.Rect screen_bounds);
-
-  // Called when the keyboard occluded bounds change. |screen_bounds| is in
-  // screen coordinates.
-  OnKeyboardOccludedBoundsChanged(gfx.mojom.Rect screen_bounds);
-
-  // Signals a request to load the keyboard contents. If the contents are
-  // already loaded, requests a reload. Once the contents have loaded,
-  // KeyboardController.KeyboardContentsLoaded is expected to be called by the
-  // client implementation.
-  OnLoadKeyboardContentsRequested();
-
-  // Called when the UI has been destroyed so that the client can reset the
-  // embedded contents and handle.
-  OnKeyboardUIDestroyed();
-};
-
-interface KeyboardController {
-  // Informs the controller that the keyboard contents have loaded.
-  KeyboardContentsLoaded(gfx.mojom.Size size);
-
-  // Retrieves the current keyboard configuration.
-  GetKeyboardConfig() => (keyboard.mojom.KeyboardConfig config);
-
-  // Sets the current keyboard configuration.
-  SetKeyboardConfig(keyboard.mojom.KeyboardConfig config);
-
-  // Returns whether the virtual keyboard has been enabled.
-  IsKeyboardEnabled() => (bool enabled);
-
-  // Sets the provided keyboard enable flag. If the computed enabled state
-  // changes, enables or disables the keyboard to match the new state.
-  SetEnableFlag(keyboard.mojom.KeyboardEnableFlag flag);
-
-  // Clears the provided keyboard enable flag. If the computed enabled state
-  // changes, enables or disables the keyboard to match the new state.
-  ClearEnableFlag(keyboard.mojom.KeyboardEnableFlag flag);
-
-  // Gets the current set of keyboard enable flags.
-  GetEnableFlags() => (array<keyboard.mojom.KeyboardEnableFlag> flags);
-
-  // Reloads the virtual keyboard if it is enabled and the URL has changed, e.g.
-  // the focus has switched from one type of field to another.
-  ReloadKeyboardIfNeeded();
-
-  // Rebuilds (disables and re-enables) the virtual keyboard if it is enabled.
-  // This is used to force a reload of the virtual keyboard when preferences or
-  // other configuration that affects loading the keyboard may have changed.
-  RebuildKeyboardIfEnabled();
-
-  // Returns whether the virtual keyboard is visible.
-  IsKeyboardVisible() => (bool visible);
-
-  // Shows the virtual keyboard on the current display if it is enabled.
-  ShowKeyboard();
-
-  // Hides the virtual keyboard if it is visible.
-  HideKeyboard(HideReason reason);
-
-  // Sets the keyboard container type. If non empty, |target_bounds| provides
-  // the container size. Returns whether the transition succeeded once the
-  // container type changes (or fails to change).
-  SetContainerType(keyboard.mojom.ContainerType container_type,
-                   gfx.mojom.Rect? target_bounds) => (bool result);
-
-  // If |locked| is true, the keyboard remains visible even when no window has
-  // input focus.
-  SetKeyboardLocked(bool locked);
-
-  // Sets the regions of the keyboard window that occlude whatever is behind it.
-  SetOccludedBounds(array<gfx.mojom.Rect> bounds);
-
-  // Sets the regions of the keyboard window where events should be handled.
-  SetHitTestBounds(array<gfx.mojom.Rect> bounds);
-
-  // Sets the region of the keyboard window that can be used as a drag handle.
-  SetDraggableArea(gfx.mojom.Rect bounds);
-
-  // Adds a KeyboardControllerObserver.
-  AddObserver(associated KeyboardControllerObserver observer);
-};
diff --git a/ash/public/interfaces/kiosk_next_shell.mojom b/ash/public/interfaces/kiosk_next_shell.mojom
deleted file mode 100644
index a9ec5d2..0000000
--- a/ash/public/interfaces/kiosk_next_shell.mojom
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2018 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.
-
-module ash.mojom;
-
-import "components/account_id/interfaces/account_id.mojom";
-
-// Performs browser-side functionality for Kiosk Next, e.g. launching the
-// KioskNextShell.
-interface KioskNextShellClient {
-  // Launch the Kiosk Next Shell for the user identified by |account_id|.
-  LaunchKioskNextShell(signin.mojom.AccountId account_id);
-};
-
-// Allows Ash and its consumers to interact with Kiosk Next.
-// These requests are forwarded to the KioskNextShellClient when necessary.
-interface KioskNextShellController {
-  // Provides a client for dispatching requests.
-  SetClient(KioskNextShellClient client);
-};
diff --git a/ash/public/interfaces/login_screen.mojom b/ash/public/interfaces/login_screen.mojom
deleted file mode 100644
index 5964774..0000000
--- a/ash/public/interfaces/login_screen.mojom
+++ /dev/null
@@ -1,156 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-module ash.mojom;
-
-import "components/account_id/interfaces/account_id.mojom";
-import "mojo/public/mojom/base/string16.mojom";
-import "mojo/public/mojom/base/time.mojom";
-
-// Allows clients (e.g. the browser process) to send messages to the ash
-// login/lock/user-add screens.
-// TODO(estade): this is in the process of being migrated off Mojo. Methods will
-// move to ash::LoginScreen or ash::LoginScreenModel.
-interface LoginScreen {
-  // Sets the client interface.
-  SetClient(LoginScreenClient client);
-
-  // Displays the lock screen. |did_show| is true iff the lock UI was
-  // successfully displayed.
-  ShowLockScreen() => (bool did_show);
-
-  // Displays the login screen. |did_show| is true iff the login UI was
-  // successfully displayed.
-  ShowLoginScreen() => (bool did_show);
-};
-
-// Allows ash lock screen to control a client (e.g. Chrome browser). Requests
-// often involve preferences or talk to cryptohome that is not available to ash.
-interface LoginScreenClient {
-  // Attempt to authenticate a user with a password or PIN.
-  //
-  // If auth succeeds:
-  // chrome will hide the lock screen and clear any displayed error messages.
-  // If auth fails:
-  // chrome will request lock screen to show error messages.
-  // |account_id|: The AccountId to authenticate against.
-  // |password|: The submitted password.
-  // |authenticated_by_pin|: True if we are using pin to authenticate.
-  //
-  // The result will be set to true if auth was successful, false if not.
-  //
-  // TODO(jdufault): Extract authenticated_by_pin into a separate mojom method,
-  //                 similar to the other Authenticate* methods
-  AuthenticateUserWithPasswordOrPin(
-      signin.mojom.AccountId account_id,
-      string password,
-      bool authenticated_by_pin) => (bool auth_success);
-
-  // Attempt to authenticate the user with with an external binary.
-  AuthenticateUserWithExternalBinary(signin.mojom.AccountId account_id)
-      => (bool auth_success);
-
-  // Attempt to enroll a user in the external binary authentication system.
-  EnrollUserWithExternalBinary() => (bool enrollment_success);
-
-  // Try to authenticate |account_id| using easy unlock. This can be used on the
-  // login or lock screen.
-  // |account_id|: The account id of the user we are authenticating.
-  //
-  // TODO(jdufault): Refactor this method to return an auth_success, similar to
-  // the other auth methods above.
-  AuthenticateUserWithEasyUnlock(signin.mojom.AccountId account_id);
-
-  // Validates parent access code for the user identified by |account_id|. When
-  // |account_id| is empty it tries to validate the access code for any child
-  // that is signed in the device. Passes validation result in the callback.
-  // Note: This should only be used for child user, it will always return false
-  // when a non-child id is used.
-  // TODO(crbug.com/965479): move this to a more appropriate place.
-  ValidateParentAccessCode(
-    signin.mojom.AccountId account_id,
-    string access_code) => (bool access_code_valid);
-
-  // Request to hard lock the user pod.
-  // |account_id|:    The account id of the user in the user pod.
-  HardlockPod(signin.mojom.AccountId account_id);
-
-  // Focus user pod of user with |account_id|.
-  OnFocusPod(signin.mojom.AccountId account_id);
-
-  // Notify that no user pod is focused.
-  OnNoPodFocused();
-
-  // Load wallpaper of user with |account_id|.
-  LoadWallpaper(signin.mojom.AccountId account_id);
-
-  // Sign out current user.
-  SignOutUser();
-
-  // Close add user screen.
-  CancelAddUser();
-
-  // Launches guest mode.
-  LoginAsGuest();
-
-  // User with |account_id| has reached maximum incorrect password attempts.
-  OnMaxIncorrectPasswordAttempted(signin.mojom.AccountId account_id);
-
-  // Should pass the focus to the active lock screen app window, if there is
-  // one. This is called when a lock screen app is reported to be active (using
-  // tray_action mojo interface), and is next in the tab order.
-  // |HandleFocusLeavingLockScreenApps| should be called to return focus to the
-  // lock screen.
-  // |reverse|:   Whether the tab order is reversed.
-  FocusLockScreenApps(bool reverse);
-
-  // Passes focus to the OOBE dialog if it is showing. No-op otherwise.
-  FocusOobeDialog();
-
-  // Show the gaia sign-in dialog. If |can_close| is true, the dialog can be
-  // closed. The value in |prefilled_account| will be used to prefill the
-  // sign-in dialog so the user does not need to type the account email.
-  ShowGaiaSignin(bool can_close, signin.mojom.AccountId? prefilled_account);
-
-  // Notification that the remove user warning was shown.
-  OnRemoveUserWarningShown();
-
-  // Try to remove |account_id|.
-  RemoveUser(signin.mojom.AccountId account_id);
-
-  // Launch a public session for user with |account_id|.
-  // |locale|:       Locale for this user.
-  //                 The value is language code like "en-US", "zh-CN"
-  // |input_method|: Input method for this user.
-  //                 This is the id of InputMethodDescriptor like
-  //                 "t:latn-post", "pinyin".
-  LaunchPublicSession(signin.mojom.AccountId account_id,
-                      string locale,
-                      string input_method);
-
-  // Request public session keyboard layouts for user with |account_id|.
-  // This function send a request to chrome and the result will be returned by
-  // SetPublicSessionKeyboardLayouts.
-  // |locale|: Request a list of keyboard layouts that can be used by this
-  //           locale.
-  RequestPublicSessionKeyboardLayouts(signin.mojom.AccountId account_id,
-                                      string locale);
-
-  // Request to show a feedback report dialog in chrome.
-  ShowFeedback();
-
-  // Show the powerwash (device reset) dialog.
-  ShowResetScreen();
-
-  // Show the help app for when users have trouble signing in to their account.
-  ShowAccountAccessHelpApp();
-
-  // Called when the keyboard focus is about to leave from the sytem tray in
-  // the login screen / OOBE. |reverse| is true when the focus moves in the
-  // reversed direction.
-  OnFocusLeavingSystemTray(bool reverse);
-
-  // Used by Ash to signal that user activity occurred on the login screen.
-  OnUserActivity();
-};
diff --git a/ash/shelf/app_list_button_unittest.cc b/ash/shelf/app_list_button_unittest.cc
index 1ecad65..5939d49 100644
--- a/ash/shelf/app_list_button_unittest.cc
+++ b/ash/shelf/app_list_button_unittest.cc
@@ -285,7 +285,12 @@
   void SetUp() override {
     set_start_session(false);
     AppListButtonTest::SetUp();
-    client_ = BindMockKioskNextShellClient();
+    client_ = std::make_unique<MockKioskNextShellClient>();
+  }
+
+  void TearDown() override {
+    client_.reset();
+    AppListButtonTest::TearDown();
   }
 
  private:
diff --git a/ash/shelf/back_button_unittest.cc b/ash/shelf/back_button_unittest.cc
index 0dc6d41..1322bab 100644
--- a/ash/shelf/back_button_unittest.cc
+++ b/ash/shelf/back_button_unittest.cc
@@ -133,7 +133,12 @@
   void SetUp() override {
     set_start_session(false);
     BackButtonTest::SetUp();
-    client_ = BindMockKioskNextShellClient();
+    client_ = std::make_unique<MockKioskNextShellClient>();
+  }
+
+  void TearDown() override {
+    client_.reset();
+    BackButtonTest::TearDown();
   }
 
   void SimulateKioskNextSession() {
diff --git a/ash/shelf/home_button_delegate.cc b/ash/shelf/home_button_delegate.cc
index 739049f..f65b4199 100644
--- a/ash/shelf/home_button_delegate.cc
+++ b/ash/shelf/home_button_delegate.cc
@@ -8,7 +8,7 @@
 
 #include "ash/app_list/app_list_controller_impl.h"
 #include "ash/home_screen/home_screen_controller.h"
-#include "ash/kiosk_next/kiosk_next_shell_controller.h"
+#include "ash/kiosk_next/kiosk_next_shell_controller_impl.h"
 #include "ash/public/cpp/shelf_model.h"
 #include "ash/shell.h"
 #include "base/logging.h"
diff --git a/ash/shelf/login_shelf_view.cc b/ash/shelf/login_shelf_view.cc
index 663ef2a..153a9ac 100644
--- a/ash/shelf/login_shelf_view.cc
+++ b/ash/shelf/login_shelf_view.cc
@@ -224,7 +224,7 @@
 
 void StartAddUser() {
   Shell::Get()->login_screen_controller()->ShowGaiaSignin(
-      true /*can_close*/, base::nullopt /*prefilled_account*/);
+      true /*can_close*/, EmptyAccountId() /*prefilled_account*/);
 }
 
 }  // namespace
diff --git a/ash/shelf/login_shelf_view.h b/ash/shelf/login_shelf_view.h
index 7bd2ef4..26ec6d1 100644
--- a/ash/shelf/login_shelf_view.h
+++ b/ash/shelf/login_shelf_view.h
@@ -14,7 +14,6 @@
 #include "ash/login/ui/login_data_dispatcher.h"
 #include "ash/public/cpp/kiosk_app_menu.h"
 #include "ash/public/cpp/login_types.h"
-#include "ash/public/interfaces/login_screen.mojom.h"
 #include "ash/shutdown_controller_impl.h"
 #include "ash/system/locale/locale_update_controller_impl.h"
 #include "ash/tray_action/tray_action_observer.h"
diff --git a/ash/shelf/login_shelf_view_unittest.cc b/ash/shelf/login_shelf_view_unittest.cc
index c4d3f29..7dd1fbe7 100644
--- a/ash/shelf/login_shelf_view_unittest.cc
+++ b/ash/shelf/login_shelf_view_unittest.cc
@@ -305,7 +305,6 @@
   login_shelf_view_->SetAllowLoginAsGuest(true /*allow_guest*/);
   // The conditions in this test should only hold while there are user pods on
   // the signin screen.
-  DataDispatcher()->AddObserver(login_shelf_view_);
   AddUsers(1);
 
   NotifySessionStateChanged(SessionState::LOGIN_PRIMARY);
@@ -373,7 +372,6 @@
 
 TEST_F(LoginShelfViewTest, ShouldShowGuestButtonWhenNoUserPods) {
   login_shelf_view_->SetAllowLoginAsGuest(true /*allow_guest*/);
-  DataDispatcher()->AddObserver(login_shelf_view_);
   SetUserCount(0);
 
   NotifySessionStateChanged(SessionState::LOGIN_PRIMARY);
@@ -426,13 +424,13 @@
 }
 
 TEST_F(LoginShelfViewTest, ClickCancelButton) {
-  std::unique_ptr<MockLoginScreenClient> client = BindMockLoginScreenClient();
+  auto client = std::make_unique<MockLoginScreenClient>();
   EXPECT_CALL(*client, CancelAddUser());
   Click(LoginShelfView::kCancel);
 }
 
 TEST_F(LoginShelfViewTest, ClickBrowseAsGuestButton) {
-  std::unique_ptr<MockLoginScreenClient> client = BindMockLoginScreenClient();
+  auto client = std::make_unique<MockLoginScreenClient>();
   EXPECT_CALL(*client, LoginAsGuest());
   Click(LoginShelfView::kBrowseAsGuest);
 }
diff --git a/ash/shelf/shelf_view_unittest.cc b/ash/shelf/shelf_view_unittest.cc
index e9cb7e7..bf32e17 100644
--- a/ash/shelf/shelf_view_unittest.cc
+++ b/ash/shelf/shelf_view_unittest.cc
@@ -15,7 +15,7 @@
 #include "ash/display/screen_orientation_controller_test_api.h"
 #include "ash/focus_cycler.h"
 #include "ash/ime/ime_controller.h"
-#include "ash/kiosk_next/kiosk_next_shell_controller.h"
+#include "ash/kiosk_next/kiosk_next_shell_controller_impl.h"
 #include "ash/kiosk_next/kiosk_next_shell_test_util.h"
 #include "ash/kiosk_next/mock_kiosk_next_shell_client.h"
 #include "ash/public/cpp/ash_features.h"
@@ -3944,7 +3944,12 @@
   void SetUp() override {
     set_start_session(false);
     ShelfViewTest::SetUp();
-    client_ = BindMockKioskNextShellClient();
+    client_ = std::make_unique<MockKioskNextShellClient>();
+  }
+
+  void TearDown() override {
+    client_.reset();
+    ShelfViewTest::TearDown();
   }
 
  protected:
diff --git a/ash/shelf/shelf_widget.cc b/ash/shelf/shelf_widget.cc
index 4612824..851c7e5 100644
--- a/ash/shelf/shelf_widget.cc
+++ b/ash/shelf/shelf_widget.cc
@@ -9,7 +9,7 @@
 #include "ash/animation/animation_change_type.h"
 #include "ash/focus_cycler.h"
 #include "ash/keyboard/ui/keyboard_controller.h"
-#include "ash/kiosk_next/kiosk_next_shell_controller.h"
+#include "ash/kiosk_next/kiosk_next_shell_controller_impl.h"
 #include "ash/public/cpp/ash_features.h"
 #include "ash/public/cpp/ash_switches.h"
 #include "ash/public/cpp/shelf_model.h"
diff --git a/ash/shelf/shelf_widget_unittest.cc b/ash/shelf/shelf_widget_unittest.cc
index aba25caf..0123790 100644
--- a/ash/shelf/shelf_widget_unittest.cc
+++ b/ash/shelf/shelf_widget_unittest.cc
@@ -527,9 +527,8 @@
     // These tests only apply to the floating virtual keyboard, as it is the
     // only case where both the virtual keyboard and the shelf are visible.
     const gfx::Rect keyboard_bounds(0, 0, 1, 1);
-    keyboard_controller()->SetContainerType(
-        keyboard::mojom::ContainerType::kFloating, keyboard_bounds,
-        base::DoNothing());
+    keyboard_controller()->SetContainerType(keyboard::ContainerType::kFloating,
+                                            keyboard_bounds, base::DoNothing());
   }
 
   keyboard::KeyboardController* keyboard_controller() {
diff --git a/ash/shell.cc b/ash/shell.cc
index 1525f83..dafd4b6b 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -55,7 +55,7 @@
 #include "ash/ime/ime_controller.h"
 #include "ash/keyboard/ash_keyboard_controller.h"
 #include "ash/keyboard/ui/keyboard_ui_factory.h"
-#include "ash/kiosk_next/kiosk_next_shell_controller.h"
+#include "ash/kiosk_next/kiosk_next_shell_controller_impl.h"
 #include "ash/laser/laser_pointer_controller.h"
 #include "ash/login/login_screen_controller.h"
 #include "ash/login_status.h"
@@ -893,7 +893,8 @@
         std::make_unique<MultiDeviceNotificationPresenter>(
             message_center::MessageCenter::Get(), connector_);
   }
-  kiosk_next_shell_controller_ = std::make_unique<KioskNextShellController>();
+  kiosk_next_shell_controller_ =
+      std::make_unique<KioskNextShellControllerImpl>();
   tablet_mode_controller_ = std::make_unique<TabletModeController>();
 
   accessibility_focus_ring_controller_ =
diff --git a/ash/shell.h b/ash/shell.h
index f9358ea..662747ad 100644
--- a/ash/shell.h
+++ b/ash/shell.h
@@ -127,7 +127,7 @@
 class ImmersiveContext;
 class KeyAccessibilityEnabler;
 class KeyboardBrightnessControlDelegate;
-class KioskNextShellController;
+class KioskNextShellControllerImpl;
 class AshKeyboardController;
 class LaserPointerController;
 class LocaleUpdateControllerImpl;
@@ -378,7 +378,7 @@
   KeyboardBrightnessControlDelegate* keyboard_brightness_control_delegate() {
     return keyboard_brightness_control_delegate_.get();
   }
-  KioskNextShellController* kiosk_next_shell_controller() {
+  KioskNextShellControllerImpl* kiosk_next_shell_controller() {
     return kiosk_next_shell_controller_.get();
   }
   AshKeyboardController* ash_keyboard_controller() {
@@ -661,7 +661,7 @@
   std::unique_ptr<ImmersiveContext> immersive_context_;
   std::unique_ptr<KeyboardBrightnessControlDelegate>
       keyboard_brightness_control_delegate_;
-  std::unique_ptr<KioskNextShellController> kiosk_next_shell_controller_;
+  std::unique_ptr<KioskNextShellControllerImpl> kiosk_next_shell_controller_;
   std::unique_ptr<LocaleUpdateControllerImpl> locale_update_controller_;
   std::unique_ptr<LoginScreenController> login_screen_controller_;
   std::unique_ptr<LogoutConfirmationController> logout_confirmation_controller_;
diff --git a/ash/shell_test_api.cc b/ash/shell_test_api.cc
index 6281d86c..cb2323f26 100644
--- a/ash/shell_test_api.cc
+++ b/ash/shell_test_api.cc
@@ -187,7 +187,7 @@
 
 void ShellTestApi::EnableVirtualKeyboard() {
   shell_->ash_keyboard_controller()->SetEnableFlag(
-      keyboard::mojom::KeyboardEnableFlag::kCommandLineEnabled);
+      keyboard::KeyboardEnableFlag::kCommandLineEnabled);
 }
 
 void ShellTestApi::ToggleFullscreen() {
diff --git a/ash/system/ime_menu/ime_menu_tray.cc b/ash/system/ime_menu/ime_menu_tray.cc
index 0fbd3e6..2323d441 100644
--- a/ash/system/ime_menu/ime_menu_tray.cc
+++ b/ash/system/ime_menu/ime_menu_tray.cc
@@ -9,7 +9,7 @@
 #include "ash/keyboard/ash_keyboard_controller.h"
 #include "ash/keyboard/ui/keyboard_controller.h"
 #include "ash/keyboard/virtual_keyboard_controller.h"
-#include "ash/kiosk_next/kiosk_next_shell_controller.h"
+#include "ash/kiosk_next/kiosk_next_shell_controller_impl.h"
 #include "ash/public/cpp/ash_constants.h"
 #include "ash/public/cpp/system_tray_client.h"
 #include "ash/resources/vector_icons/vector_icons.h"
diff --git a/ash/system/ime_menu/ime_menu_tray_unittest.cc b/ash/system/ime_menu/ime_menu_tray_unittest.cc
index 9f4db4a0..f09fa0e 100644
--- a/ash/system/ime_menu/ime_menu_tray_unittest.cc
+++ b/ash/system/ime_menu/ime_menu_tray_unittest.cc
@@ -368,7 +368,12 @@
   void SetUp() override {
     set_start_session(false);
     ImeMenuTrayTest::SetUp();
-    client_ = BindMockKioskNextShellClient();
+    client_ = std::make_unique<MockKioskNextShellClient>();
+  }
+
+  void TearDown() override {
+    client_.reset();
+    ImeMenuTrayTest::TearDown();
   }
 
  private:
diff --git a/ash/system/overview/overview_button_tray.cc b/ash/system/overview/overview_button_tray.cc
index da5f478..4572bdf 100644
--- a/ash/system/overview/overview_button_tray.cc
+++ b/ash/system/overview/overview_button_tray.cc
@@ -4,7 +4,7 @@
 
 #include "ash/system/overview/overview_button_tray.h"
 
-#include "ash/kiosk_next/kiosk_next_shell_controller.h"
+#include "ash/kiosk_next/kiosk_next_shell_controller_impl.h"
 #include "ash/metrics/user_metrics_recorder.h"
 #include "ash/resources/vector_icons/vector_icons.h"
 #include "ash/session/session_controller_impl.h"
diff --git a/ash/system/overview/overview_button_tray_unittest.cc b/ash/system/overview/overview_button_tray_unittest.cc
index d619967..ceb1cf5 100644
--- a/ash/system/overview/overview_button_tray_unittest.cc
+++ b/ash/system/overview/overview_button_tray_unittest.cc
@@ -400,7 +400,12 @@
   void SetUp() override {
     set_start_session(false);
     OverviewButtonTrayTest::SetUp();
-    client_ = BindMockKioskNextShellClient();
+    client_ = std::make_unique<MockKioskNextShellClient>();
+  }
+
+  void TearDown() override {
+    client_.reset();
+    OverviewButtonTrayTest::TearDown();
   }
 
  private:
diff --git a/ash/system/palette/palette_tray.cc b/ash/system/palette/palette_tray.cc
index 7da1b778..f1998614b 100644
--- a/ash/system/palette/palette_tray.cc
+++ b/ash/system/palette/palette_tray.cc
@@ -7,7 +7,7 @@
 #include <memory>
 
 #include "ash/accessibility/accessibility_controller.h"
-#include "ash/kiosk_next/kiosk_next_shell_controller.h"
+#include "ash/kiosk_next/kiosk_next_shell_controller_impl.h"
 #include "ash/public/cpp/ash_pref_names.h"
 #include "ash/public/cpp/stylus_utils.h"
 #include "ash/public/cpp/system_tray_client.h"
diff --git a/ash/system/palette/palette_tray_unittest.cc b/ash/system/palette/palette_tray_unittest.cc
index a98387f..89d000aec 100644
--- a/ash/system/palette/palette_tray_unittest.cc
+++ b/ash/system/palette/palette_tray_unittest.cc
@@ -775,7 +775,12 @@
   void SetUp() override {
     set_start_session(false);
     PaletteTrayTest::SetUp();
-    client_ = BindMockKioskNextShellClient();
+    client_ = std::make_unique<MockKioskNextShellClient>();
+  }
+
+  void TearDown() override {
+    client_.reset();
+    PaletteTrayTest::TearDown();
   }
 
  private:
diff --git a/ash/system/palette/palette_welcome_bubble.cc b/ash/system/palette/palette_welcome_bubble.cc
index 3e171c30..b21770d37 100644
--- a/ash/system/palette/palette_welcome_bubble.cc
+++ b/ash/system/palette/palette_welcome_bubble.cc
@@ -6,7 +6,7 @@
 
 #include <memory>
 
-#include "ash/kiosk_next/kiosk_next_shell_controller.h"
+#include "ash/kiosk_next/kiosk_next_shell_controller_impl.h"
 #include "ash/public/cpp/ash_pref_names.h"
 #include "ash/public/cpp/shell_window_ids.h"
 #include "ash/session/session_controller_impl.h"
diff --git a/ash/system/session/logout_button_tray.cc b/ash/system/session/logout_button_tray.cc
index c13275a9..2808a1b 100644
--- a/ash/system/session/logout_button_tray.cc
+++ b/ash/system/session/logout_button_tray.cc
@@ -6,7 +6,7 @@
 
 #include <memory>
 
-#include "ash/kiosk_next/kiosk_next_shell_controller.h"
+#include "ash/kiosk_next/kiosk_next_shell_controller_impl.h"
 #include "ash/public/cpp/ash_pref_names.h"
 #include "ash/public/cpp/ash_typography.h"
 #include "ash/resources/vector_icons/vector_icons.h"
diff --git a/ash/system/session/logout_button_tray_unittest.cc b/ash/system/session/logout_button_tray_unittest.cc
index f4e6550..e100b20 100644
--- a/ash/system/session/logout_button_tray_unittest.cc
+++ b/ash/system/session/logout_button_tray_unittest.cc
@@ -150,7 +150,12 @@
 
   void SetUp() override {
     LogoutButtonTrayTest::SetUp();
-    client_ = BindMockKioskNextShellClient();
+    client_ = std::make_unique<MockKioskNextShellClient>();
+  }
+
+  void TearDown() override {
+    client_.reset();
+    LogoutButtonTrayTest::TearDown();
   }
 
  private:
diff --git a/ash/system/status_area_widget.cc b/ash/system/status_area_widget.cc
index f1d61d6..6f938c6 100644
--- a/ash/system/status_area_widget.cc
+++ b/ash/system/status_area_widget.cc
@@ -4,7 +4,7 @@
 
 #include "ash/system/status_area_widget.h"
 
-#include "ash/kiosk_next/kiosk_next_shell_controller.h"
+#include "ash/kiosk_next/kiosk_next_shell_controller_impl.h"
 #include "ash/session/session_controller_impl.h"
 #include "ash/shelf/shelf.h"
 #include "ash/shell.h"
diff --git a/ash/system/status_area_widget_unittest.cc b/ash/system/status_area_widget_unittest.cc
index 4036229..f7d61ac1 100644
--- a/ash/system/status_area_widget_unittest.cc
+++ b/ash/system/status_area_widget_unittest.cc
@@ -259,9 +259,8 @@
     // These tests only apply to the floating virtual keyboard, as it is the
     // only case where both the virtual keyboard and the shelf are visible.
     const gfx::Rect keyboard_bounds(0, 0, 1, 1);
-    keyboard_controller()->SetContainerType(
-        keyboard::mojom::ContainerType::kFloating, keyboard_bounds,
-        base::DoNothing());
+    keyboard_controller()->SetContainerType(keyboard::ContainerType::kFloating,
+                                            keyboard_bounds, base::DoNothing());
   }
 
   keyboard::KeyboardController* keyboard_controller() {
diff --git a/ash/system/unified/top_shortcuts_view.cc b/ash/system/unified/top_shortcuts_view.cc
index 0b5ff81..155c5ec 100644
--- a/ash/system/unified/top_shortcuts_view.cc
+++ b/ash/system/unified/top_shortcuts_view.cc
@@ -7,7 +7,7 @@
 #include <numeric>
 
 #include "ash/accessibility/accessibility_controller.h"
-#include "ash/kiosk_next/kiosk_next_shell_controller.h"
+#include "ash/kiosk_next/kiosk_next_shell_controller_impl.h"
 #include "ash/public/cpp/ash_view_ids.h"
 #include "ash/resources/vector_icons/vector_icons.h"
 #include "ash/session/session_controller_impl.h"
diff --git a/ash/system/unified/top_shortcuts_view_unittest.cc b/ash/system/unified/top_shortcuts_view_unittest.cc
index a105e62..8f72a2af 100644
--- a/ash/system/unified/top_shortcuts_view_unittest.cc
+++ b/ash/system/unified/top_shortcuts_view_unittest.cc
@@ -35,6 +35,7 @@
   }
 
   void TearDown() override {
+    kiosk_next_shell_client_.reset();
     controller_.reset();
     top_shortcuts_view_.reset();
     model_.reset();
@@ -47,7 +48,7 @@
   }
 
   void CreateKioskNextSession() {
-    kiosk_next_shell_client_ = BindMockKioskNextShellClient();
+    kiosk_next_shell_client_ = std::make_unique<MockKioskNextShellClient>();
     LogInKioskNextUser(GetSessionControllerClient());
   }
 
diff --git a/ash/system/unified/unified_system_tray_controller.cc b/ash/system/unified/unified_system_tray_controller.cc
index d4e0d712..5136282 100644
--- a/ash/system/unified/unified_system_tray_controller.cc
+++ b/ash/system/unified/unified_system_tray_controller.cc
@@ -4,7 +4,7 @@
 
 #include "ash/system/unified/unified_system_tray_controller.h"
 
-#include "ash/kiosk_next/kiosk_next_shell_controller.h"
+#include "ash/kiosk_next/kiosk_next_shell_controller_impl.h"
 #include "ash/metrics/user_metrics_action.h"
 #include "ash/metrics/user_metrics_recorder.h"
 #include "ash/public/cpp/system_tray_client.h"
@@ -104,7 +104,6 @@
 void UnifiedSystemTrayController::HandleLockAction() {
   Shell::Get()->metrics()->RecordUserMetricsAction(UMA_TRAY_LOCK_SCREEN);
   Shell::Get()->session_controller()->LockScreen();
-  CloseBubble();
 }
 
 void UnifiedSystemTrayController::HandleSettingsAction() {
diff --git a/ash/system/virtual_keyboard/virtual_keyboard_tray.cc b/ash/system/virtual_keyboard/virtual_keyboard_tray.cc
index 56c3628e9..3266ad0 100644
--- a/ash/system/virtual_keyboard/virtual_keyboard_tray.cc
+++ b/ash/system/virtual_keyboard/virtual_keyboard_tray.cc
@@ -8,7 +8,7 @@
 
 #include "ash/accessibility/accessibility_controller.h"
 #include "ash/keyboard/ui/keyboard_controller.h"
-#include "ash/kiosk_next/kiosk_next_shell_controller.h"
+#include "ash/kiosk_next/kiosk_next_shell_controller_impl.h"
 #include "ash/resources/vector_icons/vector_icons.h"
 #include "ash/session/session_controller_impl.h"
 #include "ash/shelf/shelf.h"
diff --git a/ash/system/virtual_keyboard/virtual_keyboard_tray_unittest.cc b/ash/system/virtual_keyboard/virtual_keyboard_tray_unittest.cc
index 22fd00ba..37eb137 100644
--- a/ash/system/virtual_keyboard/virtual_keyboard_tray_unittest.cc
+++ b/ash/system/virtual_keyboard/virtual_keyboard_tray_unittest.cc
@@ -37,9 +37,8 @@
 
     // These tests only apply to the floating virtual keyboard, as it is the
     // only case where both the virtual keyboard and the shelf are visible.
-    keyboard_controller()->SetContainerType(
-        keyboard::mojom::ContainerType::kFloating, base::nullopt,
-        base::DoNothing());
+    keyboard_controller()->SetContainerType(keyboard::ContainerType::kFloating,
+                                            base::nullopt, base::DoNothing());
   }
 
   keyboard::KeyboardController* keyboard_controller() {
@@ -76,7 +75,12 @@
   void SetUp() override {
     set_start_session(false);
     AshTestBase::SetUp();
-    client_ = BindMockKioskNextShellClient();
+    client_ = std::make_unique<MockKioskNextShellClient>();
+  }
+
+  void TearDown() override {
+    client_.reset();
+    AshTestBase::TearDown();
   }
 
   void EnableVirtualKeyboardForActiveUser() {
diff --git a/ash/test/ash_test_base.cc b/ash/test/ash_test_base.cc
index 03cdff8..5e3b9b7 100644
--- a/ash/test/ash_test_base.cc
+++ b/ash/test/ash_test_base.cc
@@ -459,7 +459,7 @@
 }
 
 void AshTestBase::SetTouchKeyboardEnabled(bool enabled) {
-  auto flag = keyboard::mojom::KeyboardEnableFlag::kTouchEnabled;
+  auto flag = keyboard::KeyboardEnableFlag::kTouchEnabled;
   if (enabled)
     Shell::Get()->ash_keyboard_controller()->SetEnableFlag(flag);
   else
diff --git a/ash/test/ash_test_helper.cc b/ash/test/ash_test_helper.cc
index e87e1da..c8c0c10 100644
--- a/ash/test/ash_test_helper.cc
+++ b/ash/test/ash_test_helper.cc
@@ -184,12 +184,14 @@
 }
 
 void AshTestHelper::TearDown() {
-  test_keyboard_controller_observer_.reset();
   app_list_test_helper_.reset();
 
   Shell::DeleteInstance();
   new_window_delegate_.reset();
 
+  // Needs to be reset after Shell::Get()->ash_keyboard_controller() is deleted.
+  test_keyboard_controller_observer_.reset();
+
   // Suspend the tear down until all resources are returned via
   // CompositorFrameSinkClient::ReclaimResources()
   base::RunLoop().RunUntilIdle();
diff --git a/ash/wm/collision_detection/collision_detection_utils.cc b/ash/wm/collision_detection/collision_detection_utils.cc
index d7314e60..80928dd 100644
--- a/ash/wm/collision_detection/collision_detection_utils.cc
+++ b/ash/wm/collision_detection/collision_detection_utils.cc
@@ -104,7 +104,7 @@
   auto* keyboard_controller = keyboard::KeyboardController::Get();
   if (keyboard_controller->IsEnabled() &&
       keyboard_controller->GetActiveContainerType() ==
-          keyboard::mojom::ContainerType::kFloating &&
+          keyboard::ContainerType::kFloating &&
       keyboard_controller->GetRootWindow() == root_window &&
       !keyboard_controller->GetVisualBoundsInScreen().IsEmpty() &&
       !ShouldIgnoreWindowForCollision(keyboard_controller->GetKeyboardWindow(),
diff --git a/ash/wm/collision_detection/collision_detection_utils_unittest.cc b/ash/wm/collision_detection/collision_detection_utils_unittest.cc
index 0f20f552..4e4564b 100644
--- a/ash/wm/collision_detection/collision_detection_utils_unittest.cc
+++ b/ash/wm/collision_detection/collision_detection_utils_unittest.cc
@@ -221,9 +221,8 @@
   auto display = GetDisplay();
 
   auto* keyboard_controller = keyboard::KeyboardController::Get();
-  keyboard_controller->SetContainerType(
-      keyboard::mojom::ContainerType::kFloating, base::nullopt,
-      base::DoNothing());
+  keyboard_controller->SetContainerType(keyboard::ContainerType::kFloating,
+                                        base::nullopt, base::DoNothing());
   keyboard_controller->ShowKeyboardInDisplay(display);
   ASSERT_TRUE(keyboard::WaitUntilShown());
   aura::Window* keyboard_window = keyboard_controller->GetKeyboardWindow();
diff --git a/ash/wm/lock_layout_manager.cc b/ash/wm/lock_layout_manager.cc
index e937bc4c..9dd55075 100644
--- a/ash/wm/lock_layout_manager.cc
+++ b/ash/wm/lock_layout_manager.cc
@@ -57,10 +57,9 @@
 
   // Disable virtual keyboard overscroll because it interferes with scrolling
   // login/lock content. See crbug.com/363635.
-  keyboard::mojom::KeyboardConfig config =
+  keyboard::KeyboardConfig config =
       keyboard::KeyboardController::Get()->keyboard_config();
-  config.overscroll_behavior =
-      keyboard::mojom::KeyboardOverscrollBehavior::kDisabled;
+  config.overscroll_behavior = keyboard::KeyboardOverscrollBehavior::kDisabled;
   keyboard::KeyboardController::Get()->UpdateKeyboardConfig(config);
 }
 
@@ -69,10 +68,9 @@
 }
 
 void LockLayoutManager::OnWindowRemovedFromLayout(aura::Window* child) {
-  keyboard::mojom::KeyboardConfig config =
+  keyboard::KeyboardConfig config =
       keyboard::KeyboardController::Get()->keyboard_config();
-  config.overscroll_behavior =
-      keyboard::mojom::KeyboardOverscrollBehavior::kDefault;
+  config.overscroll_behavior = keyboard::KeyboardOverscrollBehavior::kDefault;
   keyboard::KeyboardController::Get()->UpdateKeyboardConfig(config);
 }
 
diff --git a/ash/wm/lock_layout_manager_unittest.cc b/ash/wm/lock_layout_manager_unittest.cc
index 506427b..3ac0f9f9 100644
--- a/ash/wm/lock_layout_manager_unittest.cc
+++ b/ash/wm/lock_layout_manager_unittest.cc
@@ -95,7 +95,7 @@
   }
 
   void SetKeyboardOverscrollBehavior(
-      keyboard::mojom::KeyboardOverscrollBehavior overscroll_behavior) {
+      keyboard::KeyboardOverscrollBehavior overscroll_behavior) {
     auto config = keyboard::KeyboardController::Get()->keyboard_config();
     config.overscroll_behavior = overscroll_behavior;
     keyboard::KeyboardController::Get()->UpdateKeyboardConfig(config);
@@ -230,8 +230,7 @@
   // When virtual keyboard overscroll is enabled keyboard bounds should not
   // affect window bounds.
   keyboard::KeyboardController* keyboard = keyboard::KeyboardController::Get();
-  SetKeyboardOverscrollBehavior(
-      keyboard::mojom::KeyboardOverscrollBehavior::kEnabled);
+  SetKeyboardOverscrollBehavior(keyboard::KeyboardOverscrollBehavior::kEnabled);
   ShowKeyboard(true);
   EXPECT_EQ(screen_bounds.ToString(), window->GetBoundsInScreen().ToString());
   gfx::Rect keyboard_bounds = keyboard->GetVisualBoundsInScreen();
@@ -244,7 +243,7 @@
   // 1. Set up login screen defaults: VK overscroll disabled
   // 2. Show/hide keyboard, make sure that no stale keyboard bounds are cached.
   SetKeyboardOverscrollBehavior(
-      keyboard::mojom::KeyboardOverscrollBehavior::kDisabled);
+      keyboard::KeyboardOverscrollBehavior::kDisabled);
   ShowKeyboard(true);
   ShowKeyboard(false);
   display_manager()->SetDisplayRotation(
@@ -260,7 +259,7 @@
   // When virtual keyboard overscroll is disabled keyboard bounds do
   // affect window bounds.
   SetKeyboardOverscrollBehavior(
-      keyboard::mojom::KeyboardOverscrollBehavior::kDisabled);
+      keyboard::KeyboardOverscrollBehavior::kDisabled);
   ShowKeyboard(true);
 
   primary_display = display::Screen::GetScreen()->GetPrimaryDisplay();
@@ -271,10 +270,9 @@
   EXPECT_EQ(target_bounds.ToString(), window->GetBoundsInScreen().ToString());
   ShowKeyboard(false);
 
-  SetKeyboardOverscrollBehavior(
-      keyboard::mojom::KeyboardOverscrollBehavior::kDefault);
+  SetKeyboardOverscrollBehavior(keyboard::KeyboardOverscrollBehavior::kDefault);
 
-  keyboard->SetContainerType(keyboard::mojom::ContainerType::kFloating,
+  keyboard->SetContainerType(keyboard::ContainerType::kFloating,
                              base::nullopt /* target_bounds */,
                              base::BindOnce([](bool success) {}));
   ShowKeyboard(true);
diff --git a/ash/wm/overview/overview_grid.cc b/ash/wm/overview/overview_grid.cc
index 1a9042b..5bcd3ebf 100644
--- a/ash/wm/overview/overview_grid.cc
+++ b/ash/wm/overview/overview_grid.cc
@@ -8,7 +8,7 @@
 #include <functional>
 #include <utility>
 
-#include "ash/kiosk_next/kiosk_next_shell_controller.h"
+#include "ash/kiosk_next/kiosk_next_shell_controller_impl.h"
 #include "ash/metrics/histogram_macros.h"
 #include "ash/public/cpp/ash_features.h"
 #include "ash/public/cpp/fps_counter.h"
diff --git a/ash/wm/pip/pip_window_resizer_unittest.cc b/ash/wm/pip/pip_window_resizer_unittest.cc
index b9ec671..e084aff 100644
--- a/ash/wm/pip/pip_window_resizer_unittest.cc
+++ b/ash/wm/pip/pip_window_resizer_unittest.cc
@@ -505,9 +505,9 @@
   PreparePipWindow(gfx::Rect(200, 200, 75, 75));
 
   auto* keyboard_controller = keyboard::KeyboardController::Get();
-  keyboard_controller->SetContainerType(
-      keyboard::mojom::ContainerType::kFloating, gfx::Rect(0, 0, 1, 1),
-      base::DoNothing());
+  keyboard_controller->SetContainerType(keyboard::ContainerType::kFloating,
+                                        gfx::Rect(0, 0, 1, 1),
+                                        base::DoNothing());
   keyboard_controller->ShowKeyboardInDisplay(
       wm::GetWindowState(window())->GetDisplay());
   ASSERT_TRUE(keyboard::WaitUntilShown());
diff --git a/ash/wm/splitview/split_view_controller_unittest.cc b/ash/wm/splitview/split_view_controller_unittest.cc
index 6106051..02e89b8 100644
--- a/ash/wm/splitview/split_view_controller_unittest.cc
+++ b/ash/wm/splitview/split_view_controller_unittest.cc
@@ -4615,10 +4615,15 @@
 
     SplitViewAppDraggingTest::SetUp();
 
-    client_ = BindMockKioskNextShellClient();
+    client_ = std::make_unique<MockKioskNextShellClient>();
     LogInKioskNextUser(GetSessionControllerClient());
   }
 
+  void TearDown() override {
+    client_.reset();
+    SplitViewAppDraggingTest::TearDown();
+  }
+
  private:
   base::test::ScopedFeatureList scoped_feature_list_;
   std::unique_ptr<MockKioskNextShellClient> client_;
diff --git a/ash/wm/splitview/split_view_utils.cc b/ash/wm/splitview/split_view_utils.cc
index b9fb0d5c..0a63faf2 100644
--- a/ash/wm/splitview/split_view_utils.cc
+++ b/ash/wm/splitview/split_view_utils.cc
@@ -6,7 +6,7 @@
 
 #include "ash/accessibility/accessibility_controller.h"
 #include "ash/display/screen_orientation_controller.h"
-#include "ash/kiosk_next/kiosk_next_shell_controller.h"
+#include "ash/kiosk_next/kiosk_next_shell_controller_impl.h"
 #include "ash/public/cpp/ash_features.h"
 #include "ash/public/cpp/ash_switches.h"
 #include "ash/screen_util.h"
diff --git a/ash/wm/tablet_mode/tablet_mode_controller.cc b/ash/wm/tablet_mode/tablet_mode_controller.cc
index cb2e6298..f02a8a8 100644
--- a/ash/wm/tablet_mode/tablet_mode_controller.cc
+++ b/ash/wm/tablet_mode/tablet_mode_controller.cc
@@ -8,7 +8,7 @@
 #include <string>
 #include <utility>
 
-#include "ash/kiosk_next/kiosk_next_shell_controller.h"
+#include "ash/kiosk_next/kiosk_next_shell_controller_impl.h"
 #include "ash/public/cpp/ash_switches.h"
 #include "ash/public/cpp/fps_counter.h"
 #include "ash/public/cpp/tablet_mode.h"
diff --git a/ash/wm/work_area_insets.cc b/ash/wm/work_area_insets.cc
index 6c50d65e..8fc729f 100644
--- a/ash/wm/work_area_insets.cc
+++ b/ash/wm/work_area_insets.cc
@@ -73,7 +73,7 @@
   return CalculateWorkAreaBounds(
       GetAccessibilityInsets(),
       root_window_controller_->shelf()->GetIdealBounds(),
-      keyboard_occluded_bounds_, root_window_controller_->GetRootWindow());
+      keyboard_displaced_bounds_, root_window_controller_->GetRootWindow());
 }
 
 bool WorkAreaInsets::IsKeyboardShown() const {
diff --git a/ash/wm/workspace/workspace_layout_manager_unittest.cc b/ash/wm/workspace/workspace_layout_manager_unittest.cc
index ed010e5..75b08b7 100644
--- a/ash/wm/workspace/workspace_layout_manager_unittest.cc
+++ b/ash/wm/workspace/workspace_layout_manager_unittest.cc
@@ -2006,15 +2006,13 @@
   EXPECT_GE(test_state()->num_system_ui_area_changes(), 1);
   test_state()->reset_num_system_ui_area_changes();
 
-  keyboard_controller->SetContainerType(
-      keyboard::mojom::ContainerType::kFloating, base::nullopt,
-      base::DoNothing());
+  keyboard_controller->SetContainerType(keyboard::ContainerType::kFloating,
+                                        base::nullopt, base::DoNothing());
   EXPECT_GE(test_state()->num_system_ui_area_changes(), 1);
   test_state()->reset_num_system_ui_area_changes();
 
-  keyboard_controller->SetContainerType(
-      keyboard::mojom::ContainerType::kFullWidth, base::nullopt,
-      base::DoNothing());
+  keyboard_controller->SetContainerType(keyboard::ContainerType::kFullWidth,
+                                        base::nullopt, base::DoNothing());
   EXPECT_GE(test_state()->num_system_ui_area_changes(), 1);
 }
 
diff --git a/base/metrics/histogram_functions.h b/base/metrics/histogram_functions.h
index 16e1d7e0..55b7513 100644
--- a/base/metrics/histogram_functions.h
+++ b/base/metrics/histogram_functions.h
@@ -46,38 +46,15 @@
 // Sample usage:
 //   // These values are persisted to logs. Entries should not be renumbered and
 //   // numeric values should never be reused.
-//   enum class MyEnum {
-//     FIRST_VALUE = 0,
-//     SECOND_VALUE = 1,
-//     ...
-//     FINAL_VALUE = N,
-//     COUNT
+//   enum class NewTabPageAction {
+//     kUseOmnibox = 0,
+//     kClickTitle = 1,
+//     // kUseSearchbox = 2,  // no longer used, combined into omnibox
+//     kOpenBookmark = 3,
+//     kMaxValue = kOpenBookmark,
 //   };
 //   base::UmaHistogramEnumeration("My.Enumeration",
-//                                 MyEnum::SOME_VALUE, MyEnum::COUNT);
-//
-// Note: The value in |sample| must be strictly less than |enum_size|.
-template <typename T>
-void UmaHistogramEnumeration(const std::string& name, T sample, T enum_size) {
-  static_assert(std::is_enum<T>::value,
-                "Non enum passed to UmaHistogramEnumeration");
-  DCHECK_LE(static_cast<uintmax_t>(enum_size), static_cast<uintmax_t>(INT_MAX));
-  DCHECK_LT(static_cast<uintmax_t>(sample), static_cast<uintmax_t>(enum_size));
-  return UmaHistogramExactLinear(name, static_cast<int>(sample),
-                                 static_cast<int>(enum_size));
-}
-template <typename T>
-void UmaHistogramEnumeration(const char* name, T sample, T enum_size) {
-  static_assert(std::is_enum<T>::value,
-                "Non enum passed to UmaHistogramEnumeration");
-  DCHECK_LE(static_cast<uintmax_t>(enum_size), static_cast<uintmax_t>(INT_MAX));
-  DCHECK_LT(static_cast<uintmax_t>(sample), static_cast<uintmax_t>(enum_size));
-  return UmaHistogramExactLinear(name, static_cast<int>(sample),
-                                 static_cast<int>(enum_size));
-}
-
-// Same as above, but uses T::kMaxValue as the inclusive maximum value of the
-// enum.
+//                                 NewTabPageAction::kUseSearchbox);
 template <typename T>
 void UmaHistogramEnumeration(const std::string& name, T sample) {
   static_assert(std::is_enum<T>::value,
@@ -101,6 +78,41 @@
                                  static_cast<int>(T::kMaxValue) + 1);
 }
 
+// Some legacy histograms may manually specify a max value, with a kCount,
+// COUNT, kMaxValue, or MAX_VALUE sentinel like so:
+//   // These values are persisted to logs. Entries should not be renumbered and
+//   // numeric values should never be reused.
+//   enum class NewTabPageAction {
+//     kUseOmnibox = 0,
+//     kClickTitle = 1,
+//     // kUseSearchbox = 2,  // no longer used, combined into omnibox
+//     kOpenBookmark = 3,
+//     kMaxValue,
+//   };
+//   base::UmaHistogramEnumeration("My.Enumeration",
+//                                 NewTabPageAction::kUseSearchbox,
+//                                 kMaxValue);
+// Note: The value in |sample| must be strictly less than |kMaxValue|. This is
+// otherwise functionally equivalent to the above.
+template <typename T>
+void UmaHistogramEnumeration(const std::string& name, T sample, T enum_size) {
+  static_assert(std::is_enum<T>::value,
+                "Non enum passed to UmaHistogramEnumeration");
+  DCHECK_LE(static_cast<uintmax_t>(enum_size), static_cast<uintmax_t>(INT_MAX));
+  DCHECK_LT(static_cast<uintmax_t>(sample), static_cast<uintmax_t>(enum_size));
+  return UmaHistogramExactLinear(name, static_cast<int>(sample),
+                                 static_cast<int>(enum_size));
+}
+template <typename T>
+void UmaHistogramEnumeration(const char* name, T sample, T enum_size) {
+  static_assert(std::is_enum<T>::value,
+                "Non enum passed to UmaHistogramEnumeration");
+  DCHECK_LE(static_cast<uintmax_t>(enum_size), static_cast<uintmax_t>(INT_MAX));
+  DCHECK_LT(static_cast<uintmax_t>(sample), static_cast<uintmax_t>(enum_size));
+  return UmaHistogramExactLinear(name, static_cast<int>(sample),
+                                 static_cast<int>(enum_size));
+}
+
 // For adding boolean sample to histogram.
 // Sample usage:
 //   base::UmaHistogramBoolean("My.Boolean", true)
diff --git a/build/toolchain/mac/BUILD.gn b/build/toolchain/mac/BUILD.gn
index 9cf25a9..3de0b92 100644
--- a/build/toolchain/mac/BUILD.gn
+++ b/build/toolchain/mac/BUILD.gn
@@ -148,13 +148,6 @@
         "TOOL_VERSION=${tool_versions.linker_driver} " +
         rebase_path("//build/toolchain/mac/linker_driver.py", root_build_dir)
 
-    if (!use_system_xcode) {
-      _dsymutilpath = "$hermetic_xcode_path/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/dsymutil"
-      linker_driver += " -Wcrl,dsymutilpath," + _dsymutilpath
-      _strippath = "$hermetic_xcode_path/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/strip"
-      linker_driver += " -Wcrl,strippath," + _strippath
-    }
-
     # On iOS, the final applications are assembled using lipo (to support fat
     # builds). The correct flags are passed to the linker_driver.py script
     # directly during the lipo call.
diff --git a/build/toolchain/mac/linker_driver.py b/build/toolchain/mac/linker_driver.py
index 4f4a13d..10bbda02 100755
--- a/build/toolchain/mac/linker_driver.py
+++ b/build/toolchain/mac/linker_driver.py
@@ -11,7 +11,6 @@
 import sys
 
 DSYMUTIL_INVOKE = ['xcrun', 'dsymutil']
-STRIP_INVOKE = ['xcrun', 'strip']
 
 # The linker_driver.py is responsible for forwarding a linker invocation to
 # the compiler driver, while processing special arguments itself.
@@ -46,10 +45,6 @@
 #       After invoking the linker, and optionally dsymutil, this will run
 #       the strip command on the linker's output. strip_arguments are
 #       comma-separated arguments to be passed to the strip command.
-#
-#   -Wcrl,strippath,<strip_path>
-#       Sets the path to the strip to run with -Wcrl,strip, in which case
-#       `xcrun` is not used to invoke it.
 
 def Main(args):
   """Main function for the linker driver. Separates out the arguments for
@@ -209,7 +204,7 @@
   Returns:
       list of string, Build step outputs.
   """
-  strip_command = list(STRIP_INVOKE)
+  strip_command = ['xcrun', 'strip']
   if len(strip_args_string) > 0:
     strip_command += strip_args_string.split(',')
   strip_command.append(_FindLinkerOutput(full_args))
@@ -217,25 +212,6 @@
   return []
 
 
-def SetStripPath(strip_path, full_args):
-  """Linker driver action for -Wcrl,strippath,<strip_path>.
-
-  Sets the invocation command for strip, which allows the caller to specify
-  an alternate strip. This action is always processed before the RunStrip
-  action.
-
-  Args:
-    strip_path: string, The path to the strip binary to run
-    full_args: list of string, Full argument list for the linker driver.
-
-  Returns:
-    No output - this step is run purely for its side-effect.
-  """
-  global STRIP_INVOKE
-  STRIP_INVOKE = [strip_path]
-  return []
-
-
 def _FindLinkerOutput(full_args):
   """Finds the output of the linker by looking for the output flag in its
   argument list. As this is a required linker argument, raises an error if it
@@ -272,7 +248,6 @@
     ('dsym,', RunDsymUtil),
     ('unstripped,', RunSaveUnstripped),
     ('strip,', RunStrip),
-    ('strippath,', SetStripPath),
 ]
 
 
diff --git a/chrome/VERSION b/chrome/VERSION
index 3a448d02..e776d5b 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=77
 MINOR=0
-BUILD=3817
+BUILD=3818
 PATCH=0
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/SilenceLintErrors.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/SilenceLintErrors.java
index f183a1e..47ae33c 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/SilenceLintErrors.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/SilenceLintErrors.java
@@ -33,6 +33,7 @@
             R.string.accessibility_unselect_tab,
             R.string.undo_bar_group_tabs_message,
             R.string.menu_group_tabs,
+            R.string.tab_grid_dialog_remove_from_group,
     };
 
     private SilenceLintErrors() {}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionProcessor.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionProcessor.java
index c3ed89f..e3b2b6f1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionProcessor.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionProcessor.java
@@ -8,7 +8,6 @@
 import android.graphics.Bitmap;
 import android.graphics.Color;
 import android.support.annotation.VisibleForTesting;
-import android.support.v4.content.ContextCompat;
 import android.text.TextUtils;
 
 import org.chromium.base.Log;
@@ -113,8 +112,7 @@
 
     @VisibleForTesting
     public void applyImageDominantColor(String colorSpec, PropertyModel model) {
-        int color = ContextCompat.getColor(mContext, R.color.modern_secondary_color);
-
+        int color = EntitySuggestionViewBinder.NO_DOMINANT_COLOR;
         if (!TextUtils.isEmpty(colorSpec)) {
             try {
                 color = Color.parseColor(colorSpec);
@@ -127,6 +125,12 @@
 
     @Override
     public void populateModel(OmniboxSuggestion suggestion, PropertyModel model, int position) {
+        // Note: to avoid flickering and unnecessary updates, ModelListAdapter re-uses values from
+        // previously bound model if the view is being re-used. This means our model may, and likely
+        // will not be empty at this point. Make sure we explicitly specify values to avoid using
+        // stale ones.
+        model.set(EntitySuggestionViewProperties.IMAGE_BITMAP, null);
+
         SuggestionViewDelegate delegate =
                 mSuggestionHost.createSuggestionViewDelegate(suggestion, position);
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionView.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionView.java
index 7572be5e..c29704f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionView.java
@@ -5,9 +5,8 @@
 package org.chromium.chrome.browser.omnibox.suggestions.entity;
 
 import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.drawable.ColorDrawable;
-import android.support.annotation.ColorInt;
+import android.graphics.drawable.Drawable;
+import android.support.v4.graphics.drawable.DrawableCompat;
 import android.util.AttributeSet;
 import android.view.MotionEvent;
 import android.view.View;
@@ -16,6 +15,8 @@
 import android.widget.TextView;
 
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.util.ColorUtils;
+import org.chromium.chrome.browser.widget.TintedDrawable;
 
 /**
  * Container view for omnibox entity suggestions.
@@ -50,6 +51,8 @@
     private TextView mDescriptionText;
     private ImageView mEntityImageView;
     private ImageView mRefineView;
+    private boolean mUseDarkColors;
+    private boolean mUseSuggestionImage;
 
     /**
      * Container view for omnibox suggestions allowing soft focus from keyboard.
@@ -79,6 +82,8 @@
         mEntityImageView = findViewById(R.id.omnibox_entity_image);
         mEntityView = findViewById(R.id.omnibox_entity);
         mRefineView = findViewById(R.id.omnibox_entity_refine_icon);
+
+        showSearchIcon();
     }
 
     @Override
@@ -110,6 +115,20 @@
     }
 
     /**
+     * Toggles theme.
+     * @param useDarkColors specifies whether UI should use dark theme.
+     */
+    void setUseDarkColors(boolean useDarkColors) {
+        Drawable drawable = mRefineView.getDrawable();
+        DrawableCompat.setTint(
+                drawable, ColorUtils.getIconTint(getContext(), !useDarkColors).getDefaultColor());
+        mUseDarkColors = useDarkColors;
+        if (!mUseSuggestionImage) {
+            showSearchIcon();
+        }
+    }
+
+    /**
      * Specifies the text to be displayed as subject name.
      * @param text Text to be displayed.
      */
@@ -126,18 +145,28 @@
     }
 
     /**
-     * Specify image bitmap to be shown beside suggestion text.
-     * @param bitmap Bitmap to be rendered.
+     * Specify image to be shown beside suggestion text.
+     * @param drawable Image to be rendered.
      */
-    void setImageBitmap(Bitmap bitmap) {
-        mEntityImageView.setImageBitmap(bitmap);
+    void setSuggestionImage(Drawable drawable) {
+        mUseSuggestionImage = true;
+        mEntityImageView.setImageDrawable(drawable);
+        mEntityImageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
     }
 
     /**
-     * Specify a solid color to be rendered in place of a suggestion icon.
-     * @param color Color to be used.
+     * Clear suggestion image and present (fallback) magnifying glass instead.
      */
-    void setImageColor(@ColorInt int color) {
-        mEntityImageView.setImageDrawable(new ColorDrawable(color));
+    void clearSuggestionImage() {
+        mUseSuggestionImage = false;
+        showSearchIcon();
+    }
+
+    private void showSearchIcon() {
+        mEntityImageView.setImageDrawable(TintedDrawable.constructTintedDrawable(getContext(),
+                R.drawable.ic_suggestion_magnifier,
+                mUseDarkColors ? R.color.default_icon_color_secondary_list
+                               : R.color.white_mode_tint));
+        mEntityImageView.setScaleType(ImageView.ScaleType.CENTER);
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionViewBinder.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionViewBinder.java
index d5226357..bb544c67f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionViewBinder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionViewBinder.java
@@ -5,15 +5,22 @@
 package org.chromium.chrome.browser.omnibox.suggestions.entity;
 
 import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.ColorDrawable;
 import android.os.Handler;
 import android.view.MotionEvent;
 
+import org.chromium.chrome.browser.omnibox.suggestions.SuggestionCommonProperties;
 import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionViewDelegate;
 import org.chromium.ui.modelutil.PropertyKey;
 import org.chromium.ui.modelutil.PropertyModel;
 
 /** A mechanism binding EntitySuggestion properties to its view. */
 public class EntitySuggestionViewBinder {
+    /** IMAGE_DOMINANT_COLOR Value indicating no fallback color for suggestion. */
+    static final int NO_DOMINANT_COLOR = Color.TRANSPARENT;
+
     private static final class EventListener implements EntitySuggestionView.EventListener {
         final Handler mHandler;
         final SuggestionViewDelegate mDelegate;
@@ -68,13 +75,15 @@
 
     private static void applySuggestionImage(PropertyModel model, EntitySuggestionView view) {
         Bitmap bitmap = model.get(EntitySuggestionViewProperties.IMAGE_BITMAP);
-        if (bitmap != null) {
-            view.setImageBitmap(bitmap);
-            return;
-        }
-
         int color = model.get(EntitySuggestionViewProperties.IMAGE_DOMINANT_COLOR);
-        view.setImageColor(color);
+
+        if (bitmap != null) {
+            view.setSuggestionImage(new BitmapDrawable(bitmap));
+        } else if (color != NO_DOMINANT_COLOR) {
+            view.setSuggestionImage(new ColorDrawable(color));
+        } else {
+            view.clearSuggestionImage();
+        }
     }
 
     /** @see PropertyModelChangeProcessor.ViewBinder#bind(Object, Object, Object) */
@@ -90,6 +99,8 @@
         } else if (EntitySuggestionViewProperties.IMAGE_BITMAP.equals(propertyKey)
                 || EntitySuggestionViewProperties.IMAGE_DOMINANT_COLOR.equals(propertyKey)) {
             applySuggestionImage(model, view);
+        } else if (SuggestionCommonProperties.USE_DARK_COLORS.equals(propertyKey)) {
+            view.setUseDarkColors(model.get(SuggestionCommonProperties.USE_DARK_COLORS));
         }
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListLayout.java
index 8c2ea9ca..631acd7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListLayout.java
@@ -72,29 +72,25 @@
         @Override
         public void onChanged() {
             super.onChanged();
-            updateEmptyViewVisibility();
-            if (mAdapter.getItemCount() == 0) {
-                mRecyclerView.setVisibility(View.GONE);
-            } else {
-                mRecyclerView.setVisibility(View.VISIBLE);
-            }
+            updateLayout();
             // At inflation, the RecyclerView is set to gone, and the loading view is visible. As
             // long as the adapter data changes, we show the recycler view, and hide loading view.
             mLoadingView.hideLoadingUI();
-
-            mToolbar.setSearchEnabled(mAdapter.getItemCount() != 0);
         }
 
         @Override
         public void onItemRangeInserted(int positionStart, int itemCount) {
             super.onItemRangeInserted(positionStart, itemCount);
-            updateEmptyViewVisibility();
+            updateLayout();
+            // At inflation, the RecyclerView is set to gone, and the loading view is visible. As
+            // long as the adapter data changes, we show the recycler view, and hide loading view.
+            mLoadingView.hideLoadingUI();
         }
 
         @Override
         public void onItemRangeRemoved(int positionStart, int itemCount) {
             super.onItemRangeRemoved(positionStart, itemCount);
-            updateEmptyViewVisibility();
+            updateLayout();
         }
     };
 
@@ -360,6 +356,17 @@
         mEmptyViewWrapper.setVisibility(visible);
     }
 
+    private void updateLayout() {
+        updateEmptyViewVisibility();
+        if (mAdapter.getItemCount() == 0) {
+            mRecyclerView.setVisibility(View.GONE);
+        } else {
+            mRecyclerView.setVisibility(View.VISIBLE);
+        }
+
+        mToolbar.setSearchEnabled(mAdapter.getItemCount() != 0);
+    }
+
     @VisibleForTesting
     public View getToolbarShadowForTests() {
         return mToolbarShadow;
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd
index 33f6a88d..47be3b0f 100644
--- a/chrome/android/java/strings/android_chrome_strings.grd
+++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -4084,6 +4084,11 @@
         Un-select <ph name="TAB_TITLE">%1$s<ex>Google</ex></ph> tab.
       </message>
 
+      <!-- Tab Grid Dialog strings -->
+      <message name="IDS_TAB_GRID_DIALOG_REMOVE_FROM_GROUP" desc="This text shows on the ungroup bar in TabGridDialog. When user drags a tab and drops it on the ungroup bar, this tab will be moved out of the group.">
+        Remove from group
+      </message>
+
       <message name="IDS_AUTOFILL_ASSISTANT_MODULE_TITLE"
   desc="Text shown when the Foo module is referenced in install start, success,
         failure UI (e.g. in IDS_MODULE_INSTALL_START_TEXT, which will expand to
diff --git a/chrome/android/java/strings/android_chrome_strings_grd/IDS_TAB_GRID_DIALOG_REMOVE_FROM_GROUP.png.sha1 b/chrome/android/java/strings/android_chrome_strings_grd/IDS_TAB_GRID_DIALOG_REMOVE_FROM_GROUP.png.sha1
new file mode 100644
index 0000000..d56d9fe
--- /dev/null
+++ b/chrome/android/java/strings/android_chrome_strings_grd/IDS_TAB_GRID_DIALOG_REMOVE_FROM_GROUP.png.sha1
@@ -0,0 +1 @@
+29704ec6f30b4dc5b59889def7fac516e9a5cf6e
\ No newline at end of file
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebVrTestFramework.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebVrTestFramework.java
index 3a4404e..bace7ab 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebVrTestFramework.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebVrTestFramework.java
@@ -15,6 +15,7 @@
 public class WebVrTestFramework extends WebXrVrTestFramework {
     public WebVrTestFramework(ChromeActivityTestRule rule) {
         super(rule);
+        mShouldExpectConsentDialog = false;
     }
 
     /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrTestFramework.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrTestFramework.java
index 718f905..d31bd90 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrTestFramework.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrTestFramework.java
@@ -16,6 +16,9 @@
  * Extension of VrTestFramework containing WebXR for VR-specific functionality.
  */
 public class WebXrVrTestFramework extends WebXrTestFramework {
+    // If set, a consent dialog is expected on all enterSessionWithUserGesture* methods.
+    protected boolean mShouldExpectConsentDialog = true;
+
     public WebXrVrTestFramework(ChromeActivityTestRule rule) {
         super(rule);
         if (!TestVrShellDelegate.isOnStandalone()) {
@@ -39,6 +42,10 @@
             VrShellDelegateUtils.getDelegateInstance().setExpectingBroadcast();
         }
         super.enterSessionWithUserGesture(webContents);
+
+        if (!mShouldExpectConsentDialog) return;
+        PermissionUtils.waitForConsentPrompt(getRule().getActivity());
+        PermissionUtils.acceptConsentPrompt(getRule().getActivity());
     }
 
     /**
@@ -52,9 +59,6 @@
                 "sessionTypeToRequest = sessionTypes.IMMERSIVE", POLL_TIMEOUT_LONG_MS, webContents);
         enterSessionWithUserGesture(webContents);
 
-        PermissionUtils.waitForConsentPrompt(getRule().getActivity());
-        PermissionUtils.acceptConsentPrompt(getRule().getActivity());
-
         pollJavaScriptBooleanOrFail("sessionInfos[sessionTypes.IMMERSIVE].currentSession != null",
                 POLL_TIMEOUT_LONG_MS, webContents);
         Assert.assertTrue("Immersive session started, but VR Shell not in presentation mode",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrTransitionTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrTransitionTest.java
index b1d59c7..cdd01eb 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrTransitionTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrTransitionTest.java
@@ -38,7 +38,6 @@
 import org.chromium.base.test.params.ParameterSet;
 import org.chromium.base.test.params.ParameterizedRunner;
 import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.MinAndroidSdkLevel;
 import org.chromium.base.test.util.Restriction;
 import org.chromium.base.test.util.UrlUtils;
@@ -207,7 +206,6 @@
     @LargeTest
     @Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM)
     @XrActivityRestriction({XrActivityRestriction.SupportedActivity.ALL})
-    @DisabledTest(message = "https://crbug.com/969024")
     public void testNfcFiresVrdisplayactivate() throws InterruptedException {
         mWebVrTestFramework.loadUrlAndAwaitInitialization(
                 WebVrTestFramework.getFileUrlForHtmlTestFile("test_nfc_fires_vrdisplayactivate"),
@@ -288,7 +286,6 @@
     @MediumTest
     @Restriction({RESTRICTION_TYPE_DEVICE_DAYDREAM, RESTRICTION_TYPE_VR_SETTINGS_SERVICE})
     @VrSettingsFile(VrSettingsServiceUtils.FILE_DDVIEW_DONENABLED)
-    @DisabledTest(message = "https://crbug.com/969024")
     @CommandLineFlags
             .Remove({"enable-webvr"})
             @CommandLineFlags.Add({"enable-features=WebXR"})
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionProcessorTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionProcessorTest.java
index 05ae047..995c1a4 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionProcessorTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionProcessorTest.java
@@ -4,7 +4,6 @@
 
 package org.chromium.chrome.browser.omnibox.suggestions.entity;
 
-import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.doReturn;
 
 import android.content.Context;
@@ -29,8 +28,6 @@
 @RunWith(LocalRobolectricTestRunner.class)
 @Config(manifest = Config.NONE)
 public class EntitySuggestionProcessorTest {
-    private static final int FALLBACK_COLOR = 0x00DEFC01;
-
     private EntitySuggestionProcessor mProcessor;
     private PropertyModel mModel;
 
@@ -47,10 +44,7 @@
         doReturn(mResources).when(mContext).getResources();
 
         mProcessor = new EntitySuggestionProcessor(mContext, mSuggestionHost);
-        mModel = new PropertyModel(EntitySuggestionViewProperties.ALL_KEYS);
-
-        doReturn(FALLBACK_COLOR).when(mResources).getColor(anyInt());
-        doReturn(FALLBACK_COLOR).when(mContext).getColor(anyInt());
+        mModel = mProcessor.createModelForSuggestion(null);
     }
 
     @Test
@@ -67,16 +61,16 @@
     @Test
     public void applyImageDominantColor_InvalidSpecs() {
         mProcessor.applyImageDominantColor("", mModel);
-        Assert.assertEquals(
-                mModel.get(EntitySuggestionViewProperties.IMAGE_DOMINANT_COLOR), FALLBACK_COLOR);
+        Assert.assertEquals(mModel.get(EntitySuggestionViewProperties.IMAGE_DOMINANT_COLOR),
+                EntitySuggestionViewBinder.NO_DOMINANT_COLOR);
         mProcessor.applyImageDominantColor("#", mModel);
-        Assert.assertEquals(
-                mModel.get(EntitySuggestionViewProperties.IMAGE_DOMINANT_COLOR), FALLBACK_COLOR);
+        Assert.assertEquals(mModel.get(EntitySuggestionViewProperties.IMAGE_DOMINANT_COLOR),
+                EntitySuggestionViewBinder.NO_DOMINANT_COLOR);
         mProcessor.applyImageDominantColor(null, mModel);
-        Assert.assertEquals(
-                mModel.get(EntitySuggestionViewProperties.IMAGE_DOMINANT_COLOR), FALLBACK_COLOR);
+        Assert.assertEquals(mModel.get(EntitySuggestionViewProperties.IMAGE_DOMINANT_COLOR),
+                EntitySuggestionViewBinder.NO_DOMINANT_COLOR);
         mProcessor.applyImageDominantColor("not a color", mModel);
-        Assert.assertEquals(
-                mModel.get(EntitySuggestionViewProperties.IMAGE_DOMINANT_COLOR), FALLBACK_COLOR);
+        Assert.assertEquals(mModel.get(EntitySuggestionViewProperties.IMAGE_DOMINANT_COLOR),
+                EntitySuggestionViewBinder.NO_DOMINANT_COLOR);
     }
 }
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 9098eb5e..1ef8995 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -2935,6 +2935,8 @@
       "first_run/upgrade_util_win.h",
       "font_family_cache.cc",
       "font_family_cache.h",
+      "hid/chrome_hid_delegate.cc",
+      "hid/chrome_hid_delegate.h",
       "hid/hid_chooser_context.cc",
       "hid/hid_chooser_context.h",
       "hid/hid_chooser_context_factory.cc",
@@ -3350,8 +3352,6 @@
       "task_manager/sampling/task_group_sampler.h",
       "task_manager/sampling/task_manager_impl.cc",
       "task_manager/sampling/task_manager_impl.h",
-      "task_manager/sampling/task_manager_io_thread_helper.cc",
-      "task_manager/sampling/task_manager_io_thread_helper.h",
       "task_manager/task_manager_interface.cc",
       "task_manager/task_manager_interface.h",
       "task_manager/task_manager_observer.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index c7a225c..e12102d 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -153,6 +153,7 @@
 #include "ui/android/buildflags.h"
 #else  // OS_ANDROID
 #include "chrome/browser/media/router/media_router_feature.h"
+#include "components/mirroring/service/features.h"
 #endif  // OS_ANDROID
 
 #if defined(OS_CHROMEOS)
@@ -845,31 +846,6 @@
      kMarkHttpAsWarningAndDangerousOnFormEdits,
      base::size(kMarkHttpAsWarningAndDangerousOnFormEdits), nullptr}};
 
-const FeatureEntry::FeatureParam kSimplifyHttpsIndicatorEvToSecure[] = {
-    {OmniboxFieldTrial::kSimplifyHttpsIndicatorParameterName,
-     OmniboxFieldTrial::kSimplifyHttpsIndicatorParameterEvToSecure}};
-const FeatureEntry::FeatureParam kSimplifyHttpsIndicatorSecureToLock[] = {
-    {OmniboxFieldTrial::kSimplifyHttpsIndicatorParameterName,
-     OmniboxFieldTrial::kSimplifyHttpsIndicatorParameterSecureToLock}};
-const FeatureEntry::FeatureParam kSimplifyHttpsIndicatorBothToLock[] = {
-    {OmniboxFieldTrial::kSimplifyHttpsIndicatorParameterName,
-     OmniboxFieldTrial::kSimplifyHttpsIndicatorParameterBothToLock}};
-const FeatureEntry::FeatureParam kSimplifyHttpsIndicatorKeepSecureChip[] = {
-    {OmniboxFieldTrial::kSimplifyHttpsIndicatorParameterName,
-     OmniboxFieldTrial::kSimplifyHttpsIndicatorParameterKeepSecureChip}};
-
-const FeatureEntry::FeatureVariation kSimplifyHttpsIndicatorVariations[] = {
-    {"(show Secure chip for EV pages)", kSimplifyHttpsIndicatorEvToSecure,
-     base::size(kSimplifyHttpsIndicatorEvToSecure), nullptr},
-    {"(show Lock icon for non-EV HTTPS pages)",
-     kSimplifyHttpsIndicatorSecureToLock,
-     base::size(kSimplifyHttpsIndicatorSecureToLock), nullptr},
-    {"(show Lock icon for all HTTPS pages)", kSimplifyHttpsIndicatorBothToLock,
-     base::size(kSimplifyHttpsIndicatorBothToLock), nullptr},
-    {"(show Secure chip for non-EV HTTPS pages)",
-     kSimplifyHttpsIndicatorKeepSecureChip,
-     base::size(kSimplifyHttpsIndicatorKeepSecureChip), nullptr}};
-
 #if defined(OS_ANDROID)
 const FeatureEntry::FeatureParam kTranslateForceTriggerOnEnglishHeuristic[] = {
     {language::kOverrideModelKey, language::kOverrideModelHeuristicValue},
@@ -1813,6 +1789,17 @@
      flag_descriptions::kMediaRouterCastAllowAllIPsName,
      flag_descriptions::kMediaRouterCastAllowAllIPsDescription, kOsDesktop,
      FEATURE_VALUE_TYPE(media_router::kCastAllowAllIPsFeature)},
+    {"cast-media-route-provider",
+     flag_descriptions::kCastMediaRouteProviderName,
+     flag_descriptions::kCastMediaRouteProviderDescription, kOsDesktop,
+     FEATURE_VALUE_TYPE(media_router::kCastMediaRouteProvider)},
+    {"dial-media-route-provider",
+     flag_descriptions::kDialMediaRouteProviderName,
+     flag_descriptions::kDialMediaRouteProviderDescription, kOsDesktop,
+     FEATURE_VALUE_TYPE(media_router::kDialMediaRouteProvider)},
+    {"mirroring-service", flag_descriptions::kMirroringServiceName,
+     flag_descriptions::kMirroringServiceDescription, kOsDesktop,
+     FEATURE_VALUE_TYPE(mirroring::features::kMirroringService)},
 #endif  // !OS_ANDROID
 #if defined(OS_ANDROID)
     {"autofill-keyboard-accessory-view",
@@ -2874,9 +2861,7 @@
 
     {"simplify-https-indicator", flag_descriptions::kSimplifyHttpsIndicatorName,
      flag_descriptions::kSimplifyHttpsIndicatorDescription, kOsDesktop,
-     FEATURE_WITH_PARAMS_VALUE_TYPE(omnibox::kSimplifyHttpsIndicator,
-                                    kSimplifyHttpsIndicatorVariations,
-                                    "SimplifyHttpsIndicator")},
+     FEATURE_VALUE_TYPE(omnibox::kSimplifyHttpsIndicator)},
 
 #if defined(OS_WIN)
     {"enable-gpu-appcontainer", flag_descriptions::kEnableGpuAppcontainerName,
diff --git a/chrome/browser/android/vr/gvr_input_delegate.cc b/chrome/browser/android/vr/gvr_input_delegate.cc
index ec322425..fcb5c45 100644
--- a/chrome/browser/android/vr/gvr_input_delegate.cc
+++ b/chrome/browser/android/vr/gvr_input_delegate.cc
@@ -19,17 +19,6 @@
 namespace {
 constexpr gfx::Vector3dF kForwardVector = {0.0f, 0.0f, -1.0f};
 
-// TODO(https://crbug.com/957806): Copies of this function live in device/vr and
-// device/gamepad, which will be consolidated. Is there a way to also remove
-// this duplicate even though this is in under chrome/browser instead of device?
-void CopyToUString(const base::string16& src,
-                   base::char16* dest,
-                   size_t dest_length) {
-  const size_t copy_char_count = std::min(src.size(), dest_length - 1);
-  src.copy(dest, copy_char_count);
-  std::fill(dest + copy_char_count, dest + dest_length, 0);
-}
-
 device::Gamepad CreateGamepad(const device::GvrGamepadData& data) {
   device::Gamepad gamepad;
 
@@ -42,8 +31,7 @@
 
   // TODO(https://crbug.com/942201): Get correct ID string once WebXR spec issue
   // #550 (https://github.com/immersive-web/webxr/issues/550) is resolved.
-  CopyToUString(base::UTF8ToUTF16("daydream-controller"), gamepad.id,
-                base::size(gamepad.id));
+  gamepad.SetID(base::UTF8ToUTF16("daydream-controller"));
 
   gamepad.hand = data.right_handed ? device::GamepadHand::kRight
                                    : device::GamepadHand::kLeft;
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 90cb368..4c39dea 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -60,6 +60,7 @@
 #include "chrome/browser/download/download_prefs.h"
 #include "chrome/browser/external_protocol/external_protocol_handler.h"
 #include "chrome/browser/font_family_cache.h"
+#include "chrome/browser/hid/chrome_hid_delegate.h"
 #include "chrome/browser/language/translate_frame_binder.h"
 #include "chrome/browser/lifetime/browser_shutdown.h"
 #include "chrome/browser/lookalikes/lookalike_url_navigation_throttle.h"
@@ -5112,6 +5113,12 @@
     serial_delegate_ = std::make_unique<ChromeSerialDelegate>();
   return serial_delegate_.get();
 }
+
+content::HidDelegate* ChromeContentBrowserClient::GetHidDelegate() {
+  if (!hid_delegate_)
+    hid_delegate_ = std::make_unique<ChromeHidDelegate>();
+  return hid_delegate_.get();
+}
 #endif
 
 std::unique_ptr<content::AuthenticatorRequestClientDelegate>
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h
index 499af0b6..d45a206 100644
--- a/chrome/browser/chrome_content_browser_client.h
+++ b/chrome/browser/chrome_content_browser_client.h
@@ -77,6 +77,7 @@
 class Origin;
 }
 
+class ChromeHidDelegate;
 class ChromeSerialDelegate;
 
 // Returns the user agent of Chrome.
@@ -512,6 +513,7 @@
       mojo::InterfaceRequest<blink::mojom::WebUsbService> request) override;
 #if !defined(OS_ANDROID)
   content::SerialDelegate* GetSerialDelegate() override;
+  content::HidDelegate* GetHidDelegate() override;
 #endif
   bool ShowPaymentHandlerWindow(
       content::BrowserContext* browser_context,
@@ -716,6 +718,7 @@
 
 #if !defined(OS_ANDROID)
   std::unique_ptr<ChromeSerialDelegate> serial_delegate_;
+  std::unique_ptr<ChromeHidDelegate> hid_delegate_;
 #endif
 
   base::WeakPtrFactory<ChromeContentBrowserClient> weak_factory_;
diff --git a/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service.cc b/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service.cc
index b686009..b6a56b0 100644
--- a/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service.cc
+++ b/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service.cc
@@ -75,10 +75,10 @@
 void SetKeyboardDisabled(bool disabled) {
   if (disabled) {
     ChromeKeyboardControllerClient::Get()->SetEnableFlag(
-        keyboard::mojom::KeyboardEnableFlag::kAndroidDisabled);
+        keyboard::KeyboardEnableFlag::kAndroidDisabled);
   } else {
     ChromeKeyboardControllerClient::Get()->ClearEnableFlag(
-        keyboard::mojom::KeyboardEnableFlag::kAndroidDisabled);
+        keyboard::KeyboardEnableFlag::kAndroidDisabled);
   }
 }
 
diff --git a/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service_unittest.cc b/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service_unittest.cc
index c3fe806..edb1828c 100644
--- a/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service_unittest.cc
+++ b/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service_unittest.cc
@@ -210,11 +210,14 @@
   void TearDown() override {
     test_bridge_ = nullptr;
     service_->Shutdown();
-    chrome_keyboard_controller_client_test_helper_.reset();
     profile_.reset();
     chromeos::input_method::InputMethodManager::Shutdown();
     ui::IMEBridge::Shutdown();
     ChromeAshTestBase::TearDown();
+    // Needs to be after ash::Shell is destroyed, as
+    // |chrome_keyboard_controller_client_test_helper_| observes the keyboard
+    // destruction.
+    chrome_keyboard_controller_client_test_helper_.reset();
     // To match ChromeBrowserMainExtraPartsAsh, shut down the TabletModeClient
     // after Shell.
     tablet_mode_client_.reset();
@@ -755,27 +758,23 @@
 
   // Enable Chrome OS virtual keyboard
   auto* client = ChromeKeyboardControllerClient::Get();
-  client->ClearEnableFlag(
-      keyboard::mojom::KeyboardEnableFlag::kAndroidDisabled);
-  client->SetEnableFlag(keyboard::mojom::KeyboardEnableFlag::kTouchEnabled);
-  client->FlushForTesting();
+  client->ClearEnableFlag(keyboard::KeyboardEnableFlag::kAndroidDisabled);
+  client->SetEnableFlag(keyboard::KeyboardEnableFlag::kTouchEnabled);
   base::RunLoop().RunUntilIdle();  // Allow observers to fire and process.
-  ASSERT_FALSE(client->IsEnableFlagSet(
-      keyboard::mojom::KeyboardEnableFlag::kAndroidDisabled));
+  ASSERT_FALSE(
+      client->IsEnableFlagSet(keyboard::KeyboardEnableFlag::kAndroidDisabled));
 
   // It's disabled when the ARC IME is activated.
   imm()->state()->SetActiveInputMethod(arc_ime_id);
   service()->InputMethodChanged(imm(), profile(), false);
-  client->FlushForTesting();
-  EXPECT_TRUE(client->IsEnableFlagSet(
-      keyboard::mojom::KeyboardEnableFlag::kAndroidDisabled));
+  EXPECT_TRUE(
+      client->IsEnableFlagSet(keyboard::KeyboardEnableFlag::kAndroidDisabled));
 
   // It's re-enabled when the ARC IME is deactivated.
   imm()->state()->SetActiveInputMethod(component_extension_ime_id);
   service()->InputMethodChanged(imm(), profile(), false);
-  client->FlushForTesting();
-  EXPECT_FALSE(client->IsEnableFlagSet(
-      keyboard::mojom::KeyboardEnableFlag::kAndroidDisabled));
+  EXPECT_FALSE(
+      client->IsEnableFlagSet(keyboard::KeyboardEnableFlag::kAndroidDisabled));
 }
 
 TEST_F(ArcInputMethodManagerServiceTest, ShowVirtualKeyboard) {
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
index 427e1a694..591ed4c 100644
--- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
+++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
@@ -12,6 +12,7 @@
 
 #include "ash/keyboard/ui/resources/keyboard_resource_util.h"
 #include "ash/public/cpp/event_rewriter_controller.h"
+#include "ash/public/cpp/keyboard/keyboard_controller.h"
 #include "ash/shell.h"
 #include "ash/sticky_keys/sticky_keys_controller.h"
 #include "base/bind.h"
@@ -722,8 +723,7 @@
 
   // keyboard::KeyboardController initializes ChromeKeyboardUI which depends
   // on ChromeKeyboardControllerClient.
-  chrome_keyboard_controller_client_ = ChromeKeyboardControllerClient::Create(
-      content::ServiceManagerConnection::GetForProcess()->GetConnector());
+  chrome_keyboard_controller_client_ = ChromeKeyboardControllerClient::Create();
 
   // ProfileHelper has to be initialized after UserManager instance is created.
   ProfileHelper::Get()->Initialize();
@@ -789,6 +789,9 @@
   // ash::Shell.
   ChromeBrowserMainPartsLinux::PreProfileInit();
 
+  // Needs to be initialized after ash::Shell.
+  chrome_keyboard_controller_client_->Init(ash::KeyboardController::Get());
+
   // Initialize the keyboard before any session state changes (i.e. before
   // loading the default profile).
   keyboard::InitializeKeyboardResources();
diff --git a/chrome/browser/chromeos/extensions/default_keyboard_extension_browser_test.cc b/chrome/browser/chromeos/extensions/default_keyboard_extension_browser_test.cc
index 7d240e4..baa03c9 100644
--- a/chrome/browser/chromeos/extensions/default_keyboard_extension_browser_test.cc
+++ b/chrome/browser/chromeos/extensions/default_keyboard_extension_browser_test.cc
@@ -94,9 +94,8 @@
     const std::string& id) {
   // Ensure the keyboard is shown.
   auto* client = ChromeKeyboardControllerClient::Get();
-  client->SetEnableFlag(keyboard::mojom::KeyboardEnableFlag::kExtensionEnabled);
+  client->SetEnableFlag(keyboard::KeyboardEnableFlag::kExtensionEnabled);
   client->ShowKeyboard();
-  client->FlushForTesting();
 
   GURL url = extensions::Extension::GetBaseURLFromExtensionId(id);
   std::unique_ptr<content::RenderWidgetHostIterator> widgets(
diff --git a/chrome/browser/chromeos/input_method/input_method_engine.cc b/chrome/browser/chromeos/input_method/input_method_engine.cc
index 011d92b..27a4edd 100644
--- a/chrome/browser/chromeos/input_method/input_method_engine.cc
+++ b/chrome/browser/chromeos/input_method/input_method_engine.cc
@@ -254,7 +254,7 @@
 void InputMethodEngine::HideInputView() {
   auto* keyboard_client = ChromeKeyboardControllerClient::Get();
   if (keyboard_client->is_keyboard_enabled())
-    keyboard_client->HideKeyboard(ash::mojom::HideReason::kUser);
+    keyboard_client->HideKeyboard(ash::HideReason::kUser);
 }
 
 void InputMethodEngine::UpdateComposition(
diff --git a/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc b/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc
index 1c97762..8bc7c90 100644
--- a/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc
+++ b/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc
@@ -136,13 +136,9 @@
       : delegate_(nullptr),
         candidate_window_controller_(nullptr),
         keyboard_(nullptr) {
-    chrome_keyboard_controller_client_test_helper_ =
-        ChromeKeyboardControllerClientTestHelper::InitializeWithFake();
   }
 
-  ~InputMethodManagerImplTest() override {
-    chrome_keyboard_controller_client_test_helper_.reset();
-  }
+  ~InputMethodManagerImplTest() override = default;
 
   void SetUp() override {
     ui::InitializeInputMethodForTesting();
@@ -165,6 +161,10 @@
     InitImeList();
 
     BrowserWithTestWindowTest::SetUp();
+
+    // Needs ash::Shell keyboard to be created first.
+    chrome_keyboard_controller_client_test_helper_ =
+        ChromeKeyboardControllerClientTestHelper::InitializeForAsh();
   }
 
   void TearDown() override {
@@ -176,6 +176,9 @@
     candidate_window_controller_ = nullptr;
     keyboard_ = nullptr;
     manager_.reset();
+
+    // Needs to destroyed after ash::Shell keyboard.
+    chrome_keyboard_controller_client_test_helper_.reset();
   }
 
   scoped_refptr<InputMethodManagerImpl::StateImpl> GetActiveIMEState() {
diff --git a/chrome/browser/chromeos/login/lock/screen_locker.cc b/chrome/browser/chromeos/login/lock/screen_locker.cc
index fd4c87cb..acbc38b2 100644
--- a/chrome/browser/chromeos/login/lock/screen_locker.cc
+++ b/chrome/browser/chromeos/login/lock/screen_locker.cc
@@ -204,20 +204,14 @@
 
   // Create and display lock screen.
   CHECK(LoginScreenClient::HasInstance());
-  LoginScreenClient::Get()->login_screen()->ShowLockScreen(base::BindOnce(
-      [](ViewsScreenLocker* screen_locker, bool did_show) {
-        CHECK(did_show);
-        screen_locker->OnLockScreenReady();
-
-        content::NotificationService::current()->Notify(
-            chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
-            content::NotificationService::AllSources(),
-            content::NotificationService::NoDetails());
-      },
-      views_screen_locker_.get()));
-
+  ash::LoginScreen::Get()->ShowLockScreen();
   views_screen_locker_->Init();
 
+  content::NotificationService::current()->Notify(
+      chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
+      content::NotificationService::AllSources(),
+      content::NotificationService::NoDetails());
+
   // Start locking on ash side.
   SessionControllerClientImpl::Get()->StartLock(base::BindOnce(
       &ScreenLocker::OnStartLockCallback, weak_factory_.GetWeakPtr()));
diff --git a/chrome/browser/chromeos/login/lock/views_screen_locker.cc b/chrome/browser/chromeos/login/lock/views_screen_locker.cc
index 838050e..05629bc 100644
--- a/chrome/browser/chromeos/login/lock/views_screen_locker.cc
+++ b/chrome/browser/chromeos/login/lock/views_screen_locker.cc
@@ -86,12 +86,6 @@
       std::make_unique<ChromeUserSelectionScreen>(kLockDisplay);
   user_selection_screen_->SetView(user_board_view_mojo_.get());
 
-  allowed_input_methods_subscription_ =
-      CrosSettings::Get()->AddSettingsObserver(
-          kDeviceLoginScreenInputMethods,
-          base::Bind(&ViewsScreenLocker::OnAllowedInputMethodsChanged,
-                     base::Unretained(this)));
-
   if (base::FeatureList::IsEnabled(ash::features::kUnlockWithExternalBinary))
     scoped_observer_.Add(media_analytics_client_);
 }
@@ -120,10 +114,6 @@
   }
 
   system_info_updater_->StartRequest();
-}
-
-void ViewsScreenLocker::OnLockScreenReady() {
-  lock_screen_ready_ = true;
 
   ash::LoginScreen::Get()->GetModel()->SetUserList(
       user_selection_screen_->UpdateAndReturnUserListForAsh());
@@ -134,6 +124,12 @@
                       base::TimeTicks::Now() - lock_time_);
   screen_locker_->ScreenLockReady();
   lock_screen_apps::StateController::Get()->SetFocusCyclerDelegate(this);
+
+  allowed_input_methods_subscription_ =
+      CrosSettings::Get()->AddSettingsObserver(
+          kDeviceLoginScreenInputMethods,
+          base::Bind(&ViewsScreenLocker::OnAllowedInputMethodsChanged,
+                     base::Unretained(this)));
   OnAllowedInputMethodsChanged();
 }
 
@@ -156,7 +152,7 @@
     const AccountId& account_id,
     const std::string& password,
     bool authenticated_by_pin,
-    AuthenticateUserWithPasswordOrPinCallback callback) {
+    base::OnceCallback<void(bool)> callback) {
   DCHECK_EQ(account_id.GetUserEmail(),
             gaia::SanitizeEmail(account_id.GetUserEmail()));
   const user_manager::User* const user =
@@ -182,7 +178,7 @@
 
 void ViewsScreenLocker::HandleAuthenticateUserWithExternalBinary(
     const AccountId& account_id,
-    AuthenticateUserWithExternalBinaryCallback callback) {
+    base::OnceCallback<void(bool)> callback) {
   authenticate_with_external_binary_callback_ = std::move(callback);
   external_binary_timer_.Start(
       FROM_HERE, kExternalBinaryAuthTimeout,
@@ -193,7 +189,7 @@
 }
 
 void ViewsScreenLocker::HandleEnrollUserWithExternalBinary(
-    EnrollUserWithExternalBinaryCallback callback) {
+    base::OnceCallback<void(bool)> callback) {
   enroll_user_with_external_binary_callback_ = std::move(callback);
   external_binary_timer_.Start(
       FROM_HERE, kExternalBinaryAuthTimeout,
@@ -320,9 +316,6 @@
 }
 
 void ViewsScreenLocker::OnAllowedInputMethodsChanged() {
-  if (!lock_screen_ready_)
-    return;
-
   if (focused_pod_account_id_) {
     std::string user_input_method = lock_screen_utils::GetUserLastInputMethod(
         focused_pod_account_id_->GetUserEmail());
diff --git a/chrome/browser/chromeos/login/lock/views_screen_locker.h b/chrome/browser/chromeos/login/lock/views_screen_locker.h
index 23d740d0..11495a15 100644
--- a/chrome/browser/chromeos/login/lock/views_screen_locker.h
+++ b/chrome/browser/chromeos/login/lock/views_screen_locker.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_CHROMEOS_LOGIN_LOCK_VIEWS_SCREEN_LOCKER_H_
 #define CHROME_BROWSER_CHROMEOS_LOGIN_LOCK_VIEWS_SCREEN_LOCKER_H_
 
+#include "base/callback_forward.h"
 #include "base/memory/weak_ptr.h"
 #include "base/scoped_observer.h"
 #include "base/timer/timer.h"
@@ -36,7 +37,6 @@
   ~ViewsScreenLocker() override;
 
   void Init();
-  void OnLockScreenReady();
 
   // ScreenLocker::Delegate:
   void ShowErrorMessage(int error_msg_id,
@@ -49,12 +49,12 @@
       const AccountId& account_id,
       const std::string& password,
       bool authenticated_by_pin,
-      AuthenticateUserWithPasswordOrPinCallback callback) override;
+      base::OnceCallback<void(bool)> callback) override;
   void HandleAuthenticateUserWithExternalBinary(
       const AccountId& account_id,
-      AuthenticateUserWithExternalBinaryCallback callback) override;
+      base::OnceCallback<void(bool)> callback) override;
   void HandleEnrollUserWithExternalBinary(
-      EnrollUserWithExternalBinaryCallback) override;
+      base::OnceCallback<void(bool)> callback) override;
   void HandleAuthenticateUserWithEasyUnlock(
       const AccountId& account_id) override;
   void HandleHardlockPod(const AccountId& account_id) override;
@@ -102,13 +102,9 @@
   std::unique_ptr<CrosSettings::ObserverSubscription>
       allowed_input_methods_subscription_;
 
-  bool lock_screen_ready_ = false;
+  base::OnceCallback<void(bool)> authenticate_with_external_binary_callback_;
 
-  AuthenticateUserWithExternalBinaryCallback
-      authenticate_with_external_binary_callback_;
-
-  EnrollUserWithExternalBinaryCallback
-      enroll_user_with_external_binary_callback_;
+  base::OnceCallback<void(bool)> enroll_user_with_external_binary_callback_;
 
   // Callback registered as a lock screen apps focus handler - it should be
   // called to hand focus over to lock screen apps.
diff --git a/chrome/browser/chromeos/login/ui/fake_login_display_host.cc b/chrome/browser/chromeos/login/ui/fake_login_display_host.cc
index 813d625b..b9bed168 100644
--- a/chrome/browser/chromeos/login/ui/fake_login_display_host.cc
+++ b/chrome/browser/chromeos/login/ui/fake_login_display_host.cc
@@ -112,9 +112,8 @@
   return false;
 }
 
-void FakeLoginDisplayHost::ShowGaiaDialog(
-    bool can_close,
-    const base::Optional<AccountId>& prefilled_account) {}
+void FakeLoginDisplayHost::ShowGaiaDialog(bool can_close,
+                                          const AccountId& prefilled_account) {}
 
 void FakeLoginDisplayHost::HideOobeDialog() {}
 
diff --git a/chrome/browser/chromeos/login/ui/fake_login_display_host.h b/chrome/browser/chromeos/login/ui/fake_login_display_host.h
index 80fc4e1..57b22315 100644
--- a/chrome/browser/chromeos/login/ui/fake_login_display_host.h
+++ b/chrome/browser/chromeos/login/ui/fake_login_display_host.h
@@ -53,9 +53,8 @@
   void LoadWallpaper(const AccountId& account_id) override;
   void LoadSigninWallpaper() override;
   bool IsUserWhitelisted(const AccountId& account_id) override;
-  void ShowGaiaDialog(
-      bool can_close,
-      const base::Optional<AccountId>& prefilled_account) override;
+  void ShowGaiaDialog(bool can_close,
+                      const AccountId& prefilled_account) override;
   void HideOobeDialog() override;
   void UpdateOobeDialogSize(int width, int height) override;
   void UpdateOobeDialogState(ash::OobeDialogState state) override;
diff --git a/chrome/browser/chromeos/login/ui/login_display_host.h b/chrome/browser/chromeos/login/ui/login_display_host.h
index 03b7f6b..c877021 100644
--- a/chrome/browser/chromeos/login/ui/login_display_host.h
+++ b/chrome/browser/chromeos/login/ui/login_display_host.h
@@ -52,9 +52,8 @@
 // - LoginDisplayHostCommon is UI-agnostic code shared between the views and
 //   webui hosts.
 // - MockLoginDisplayHost is for tests.
-// - LoginDisplayHostMojo is for the login screen which is a mojo controller
-//   (ie, ash/public/interfaces/login_screen.mojom,
-//    ash/login/login_screen_controller.h).
+// - LoginDisplayHostMojo is for the login screen which is implemented in Ash.
+//   TODO(estade): rename LoginDisplayHostMojo since it no longer uses Mojo.
 // - LoginDisplayHostWebUI is for OOBE, which is written in HTML/JS/CSS.
 class LoginDisplayHost {
  public:
@@ -134,9 +133,8 @@
 
   // Show the gaia dialog. |can_close| determines if the user is allowed to
   // close the dialog. If available, |account| is preloaded in the gaia dialog.
-  virtual void ShowGaiaDialog(
-      bool can_close,
-      const base::Optional<AccountId>& prefilled_account) = 0;
+  virtual void ShowGaiaDialog(bool can_close,
+                              const AccountId& prefilled_account) = 0;
 
   // Hide any visible oobe dialog.
   virtual void HideOobeDialog() = 0;
diff --git a/chrome/browser/chromeos/login/ui/login_display_host_common.cc b/chrome/browser/chromeos/login/ui/login_display_host_common.cc
index fa094b4b..ae9dbe8c 100644
--- a/chrome/browser/chromeos/login/ui/login_display_host_common.cc
+++ b/chrome/browser/chromeos/login/ui/login_display_host_common.cc
@@ -273,19 +273,21 @@
 }
 
 void LoginDisplayHostCommon::ShowGaiaDialogCommon(
-    const base::Optional<AccountId>& prefilled_account) {
+    const AccountId& prefilled_account) {
   DCHECK(GetOobeUI());
 
-  if (prefilled_account) {
+  if (prefilled_account.is_valid()) {
     // Make sure gaia displays |account| if requested.
     if (!GetLoginDisplay()->delegate()->IsSigninInProgress()) {
       GetOobeUI()->GetView<GaiaScreenHandler>()->ShowGaiaAsync(
           prefilled_account);
     }
-    LoadWallpaper(*prefilled_account);
+    LoadWallpaper(prefilled_account);
   } else {
-    if (GetOobeUI()->current_screen() != GaiaView::kScreenId)
-      GetOobeUI()->GetView<GaiaScreenHandler>()->ShowGaiaAsync(base::nullopt);
+    if (GetOobeUI()->current_screen() != GaiaView::kScreenId) {
+      GetOobeUI()->GetView<GaiaScreenHandler>()->ShowGaiaAsync(
+          EmptyAccountId());
+    }
     LoadSigninWallpaper();
   }
 }
diff --git a/chrome/browser/chromeos/login/ui/login_display_host_common.h b/chrome/browser/chromeos/login/ui/login_display_host_common.h
index f734830..765d08630 100644
--- a/chrome/browser/chromeos/login/ui/login_display_host_common.h
+++ b/chrome/browser/chromeos/login/ui/login_display_host_common.h
@@ -79,7 +79,7 @@
   void OnStartSignInScreenCommon();
 
   // Common code for ShowGaiaDialog() call above.
-  void ShowGaiaDialogCommon(const base::Optional<AccountId>& prefilled_account);
+  void ShowGaiaDialogCommon(const AccountId& prefilled_account);
 
   // Active instance of authentication prewarmer.
   std::unique_ptr<AuthPrewarmer> auth_prewarmer_;
diff --git a/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc b/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc
index 6e57f58..45dc21c 100644
--- a/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc
+++ b/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc
@@ -36,7 +36,7 @@
 
 LoginDisplayHostMojo::AuthState::AuthState(
     AccountId account_id,
-    AuthenticateUserWithPasswordOrPinCallback callback)
+    base::OnceCallback<void(bool)> callback)
     : account_id(account_id), callback(std::move(callback)) {}
 
 LoginDisplayHostMojo::AuthState::~AuthState() = default;
@@ -191,7 +191,7 @@
     // If we already have a signin screen instance, just reset the state of the
     // oobe dialog.
     HideOobeDialog();
-    GetOobeUI()->GetView<GaiaScreenHandler>()->ShowGaiaAsync(base::nullopt);
+    GetOobeUI()->GetView<GaiaScreenHandler>()->ShowGaiaAsync(EmptyAccountId());
     return;
   }
 
@@ -232,9 +232,8 @@
   NOTIMPLEMENTED();
 }
 
-void LoginDisplayHostMojo::ShowGaiaDialog(
-    bool can_close,
-    const base::Optional<AccountId>& prefilled_account) {
+void LoginDisplayHostMojo::ShowGaiaDialog(bool can_close,
+                                          const AccountId& prefilled_account) {
   DCHECK(GetOobeUI());
   can_close_dialog_ = can_close;
 
@@ -256,7 +255,7 @@
   // The dialog can not be hidden if there are no users on the login screen.
   // Reload it instead.
   if (!login_display_->IsSigninInProgress() && users_.empty()) {
-    GetOobeUI()->GetView<GaiaScreenHandler>()->ShowGaiaAsync(base::nullopt);
+    GetOobeUI()->GetView<GaiaScreenHandler>()->ShowGaiaAsync(EmptyAccountId());
     return;
   }
 
@@ -302,7 +301,7 @@
     const AccountId& account_id,
     const std::string& password,
     bool authenticated_by_pin,
-    AuthenticateUserWithPasswordOrPinCallback callback) {
+    base::OnceCallback<void(bool)> callback) {
   DCHECK_EQ(account_id.GetUserEmail(),
             gaia::SanitizeEmail(account_id.GetUserEmail()));
 
@@ -344,13 +343,13 @@
 
 void LoginDisplayHostMojo::HandleAuthenticateUserWithExternalBinary(
     const AccountId& account_id,
-    AuthenticateUserWithExternalBinaryCallback callback) {
+    base::OnceCallback<void(bool)> callback) {
   // Authenticating with an external binary is not supported for login.
   std::move(callback).Run(false);
 }
 
 void LoginDisplayHostMojo::HandleEnrollUserWithExternalBinary(
-    EnrollUserWithExternalBinaryCallback callback) {
+    base::OnceCallback<void(bool)> callback) {
   // Enroll in external binary auth system is not supported for login.
   std::move(callback).Run(false);
 }
diff --git a/chrome/browser/chromeos/login/ui/login_display_host_mojo.h b/chrome/browser/chromeos/login/ui/login_display_host_mojo.h
index 899b3fc..af5b79a6 100644
--- a/chrome/browser/chromeos/login/ui/login_display_host_mojo.h
+++ b/chrome/browser/chromeos/login/ui/login_display_host_mojo.h
@@ -78,9 +78,8 @@
   void OnStartAppLaunch() override;
   void OnStartArcKiosk() override;
   void OnBrowserCreated() override;
-  void ShowGaiaDialog(
-      bool can_close,
-      const base::Optional<AccountId>& prefilled_account) override;
+  void ShowGaiaDialog(bool can_close,
+                      const AccountId& prefilled_account) override;
   void HideOobeDialog() override;
   void UpdateOobeDialogSize(int width, int height) override;
   void UpdateOobeDialogState(ash::OobeDialogState state) override;
@@ -96,12 +95,12 @@
       const AccountId& account_id,
       const std::string& password,
       bool authenticated_by_pin,
-      AuthenticateUserWithPasswordOrPinCallback callback) override;
+      base::OnceCallback<void(bool)> callback) override;
   void HandleAuthenticateUserWithExternalBinary(
       const AccountId& account_id,
-      AuthenticateUserWithExternalBinaryCallback callback) override;
+      base::OnceCallback<void(bool)> callback) override;
   void HandleEnrollUserWithExternalBinary(
-      EnrollUserWithExternalBinaryCallback callback) override;
+      base::OnceCallback<void(bool)> callback) override;
   void HandleAuthenticateUserWithEasyUnlock(
       const AccountId& account_id) override;
   void HandleHardlockPod(const AccountId& account_id) override;
@@ -125,14 +124,13 @@
 
   // State associated with a pending authentication attempt.
   struct AuthState {
-    AuthState(AccountId account_id,
-              AuthenticateUserWithPasswordOrPinCallback callback);
+    AuthState(AccountId account_id, base::OnceCallback<void(bool)> callback);
     ~AuthState();
 
     // Account that is being authenticated.
     AccountId account_id;
     // Callback that should be executed the authentication result is available.
-    AuthenticateUserWithPasswordOrPinCallback callback;
+    base::OnceCallback<void(bool)> callback;
   };
   std::unique_ptr<AuthState> pending_auth_state_;
 
diff --git a/chrome/browser/chromeos/login/ui/login_display_host_webui.cc b/chrome/browser/chromeos/login/ui/login_display_host_webui.cc
index d0a43139..5b14c05 100644
--- a/chrome/browser/chromeos/login/ui/login_display_host_webui.cc
+++ b/chrome/browser/chromeos/login/ui/login_display_host_webui.cc
@@ -293,17 +293,15 @@
 // into view on JS side when virtual keyboard is shown.
 void DisableKeyboardOverscroll() {
   auto* client = ChromeKeyboardControllerClient::Get();
-  keyboard::mojom::KeyboardConfig config = client->GetKeyboardConfig();
-  config.overscroll_behavior =
-      keyboard::mojom::KeyboardOverscrollBehavior::kDisabled;
+  keyboard::KeyboardConfig config = client->GetKeyboardConfig();
+  config.overscroll_behavior = keyboard::KeyboardOverscrollBehavior::kDisabled;
   client->SetKeyboardConfig(config);
 }
 
 void ResetKeyboardOverscrollBehavior() {
   auto* client = ChromeKeyboardControllerClient::Get();
-  keyboard::mojom::KeyboardConfig config = client->GetKeyboardConfig();
-  config.overscroll_behavior =
-      keyboard::mojom::KeyboardOverscrollBehavior::kDefault;
+  keyboard::KeyboardConfig config = client->GetKeyboardConfig();
+  config.overscroll_behavior = keyboard::KeyboardOverscrollBehavior::kDefault;
   client->SetKeyboardConfig(config);
 }
 
@@ -1079,9 +1077,8 @@
   }
 }
 
-void LoginDisplayHostWebUI::ShowGaiaDialog(
-    bool can_close,
-    const base::Optional<AccountId>& prefilled_account) {
+void LoginDisplayHostWebUI::ShowGaiaDialog(bool can_close,
+                                           const AccountId& prefilled_account) {
   // This is a special case, when WebUI sign-in screen shown with Views-based
   // launch bar. Then "Add user" button will be Views-based, and user click
   // will result in this call.
diff --git a/chrome/browser/chromeos/login/ui/login_display_host_webui.h b/chrome/browser/chromeos/login/ui/login_display_host_webui.h
index 55f8f55..a1ac3310 100644
--- a/chrome/browser/chromeos/login/ui/login_display_host_webui.h
+++ b/chrome/browser/chromeos/login/ui/login_display_host_webui.h
@@ -76,9 +76,8 @@
   void OnStartAppLaunch() override;
   void OnStartArcKiosk() override;
   void OnBrowserCreated() override;
-  void ShowGaiaDialog(
-      bool can_close,
-      const base::Optional<AccountId>& prefilled_account) override;
+  void ShowGaiaDialog(bool can_close,
+                      const AccountId& prefilled_account) override;
   void HideOobeDialog() override;
   void UpdateOobeDialogSize(int width, int height) override;
   void UpdateOobeDialogState(ash::OobeDialogState state) override;
diff --git a/chrome/browser/chromeos/login/ui/login_display_mojo.cc b/chrome/browser/chromeos/login/ui/login_display_mojo.cc
index 61fef3e..aae0761 100644
--- a/chrome/browser/chromeos/login/ui/login_display_mojo.cc
+++ b/chrome/browser/chromeos/login/ui/login_display_mojo.cc
@@ -60,19 +60,13 @@
   // login screen multiple times. Views-login only supports initialization once.
   if (!initialized_) {
     client->SetDelegate(host_);
-    client->login_screen()->ShowLoginScreen(
-        base::BindOnce(&LoginDisplayMojo::OnLoginScreenShown,
-                       weak_factory_.GetWeakPtr(), filtered_users.empty()));
+    ash::LoginScreen::Get()->ShowLoginScreen();
   }
 
   UserSelectionScreen* user_selection_screen = host_->user_selection_screen();
   user_selection_screen->Init(filtered_users);
-  // The login screen will not be ready for the user list until
-  // ShowLoginScreen() is finished.
-  if (ash::LoginScreen::Get()->GetModel()) {
-    ash::LoginScreen::Get()->GetModel()->SetUserList(
-        user_selection_screen->UpdateAndReturnUserListForAsh());
-  }
+  ash::LoginScreen::Get()->GetModel()->SetUserList(
+      user_selection_screen->UpdateAndReturnUserListForAsh());
   ash::LoginScreen::Get()->SetAllowLoginAsGuest(show_guest);
   user_selection_screen->SetUsersLoaded(true /*loaded*/);
 
@@ -83,7 +77,38 @@
     }
   }
 
-  initialized_ = true;
+  if (!initialized_) {
+    initialized_ = true;
+
+    // login-prompt-visible is recorded and tracked to verify boot performance
+    // does not regress. Autotests may also depend on it (ie,
+    // login_SameSessionTwice).
+    VLOG(1) << "Emitting login-prompt-visible";
+    SessionManagerClient::Get()->EmitLoginPromptVisible();
+
+    content::NotificationService::current()->Notify(
+        chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
+        content::NotificationService::AllSources(),
+        content::NotificationService::NoDetails());
+
+    // If there no available users exist, delay showing the dialogs until after
+    // GAIA dialog is shown (GAIA dialog will check these local state values,
+    // too). Login UI will show GAIA dialog if no user are registered, which
+    // might hide any UI shown here.
+    if (filtered_users.empty())
+      return;
+
+    // Check whether factory reset or debugging feature have been requested in
+    // prior session, and start reset or enable debugging wizard as needed.
+    // This has to happen after login-prompt-visible, as some reset dialog
+    // features (TPM firmware update) depend on system services running, which
+    // is in turn blocked on the 'login-prompt-visible' signal.
+    PrefService* local_state = g_browser_process->local_state();
+    if (local_state->GetBoolean(prefs::kFactoryResetRequested))
+      host_->StartWizard(ResetView::kScreenId);
+    else if (local_state->GetBoolean(prefs::kDebuggingFeaturesRequested))
+      host_->StartWizard(EnableDebuggingScreenView::kScreenId);
+  }
 }
 
 void LoginDisplayMojo::OnPreferencesChanged() {
@@ -268,43 +293,6 @@
       UserSelectionScreen::BuildAshUserAvatarForUser(user));
 }
 
-void LoginDisplayMojo::OnLoginScreenShown(bool users_empty, bool did_show) {
-  CHECK(did_show);
-
-  ash::LoginScreen::Get()->GetModel()->SetUserList(
-      host_->user_selection_screen()->UpdateAndReturnUserListForAsh());
-
-  // login-prompt-visible is recorded and tracked to verify boot performance
-  // does not regress. Autotests may also depend on it (ie,
-  // login_SameSessionTwice).
-  VLOG(1) << "Emitting login-prompt-visible";
-  SessionManagerClient::Get()->EmitLoginPromptVisible();
-
-  content::NotificationService::current()->Notify(
-      chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
-      content::NotificationService::AllSources(),
-      content::NotificationService::NoDetails());
-
-  // If there no available users exist, delay showing the dialogs until after
-  // GAIA dialog is shown (GAIA dialog will check these local state values,
-  // too). Login UI will show GAIA dialog if no user are registered, which might
-  // hide any UI shown here.
-  if (users_empty)
-    return;
-
-  // Check whether factory reset or debugging feature have been requested in
-  // prior session, and start reset or enable debugging wizard as needed.
-  // This has to happen after login-prompt-visible, as some reset dialog
-  // features (TPM firmware update) depend on system services running, which is
-  // in turn blocked on the 'login-prompt-visible' signal.
-  PrefService* local_state = g_browser_process->local_state();
-  if (local_state->GetBoolean(prefs::kFactoryResetRequested)) {
-    host_->StartWizard(ResetView::kScreenId);
-  } else if (local_state->GetBoolean(prefs::kDebuggingFeaturesRequested)) {
-    host_->StartWizard(EnableDebuggingScreenView::kScreenId);
-  }
-}
-
 void LoginDisplayMojo::OnPinCanAuthenticate(const AccountId& account_id,
                                             bool can_authenticate) {
   ash::LoginScreen::Get()->GetModel()->SetPinEnabledForUser(account_id,
diff --git a/chrome/browser/chromeos/login/ui/login_display_mojo.h b/chrome/browser/chromeos/login/ui/login_display_mojo.h
index 52b7b25..6ba39f3 100644
--- a/chrome/browser/chromeos/login/ui/login_display_mojo.h
+++ b/chrome/browser/chromeos/login/ui/login_display_mojo.h
@@ -75,11 +75,6 @@
   void OnUserImageChanged(const user_manager::User& user) override;
 
  private:
-  // Callback to ShowLoginScreen request.
-  // |users_empty| - whether the login screen was initialized with no users.
-  // |did_show| - whether the screen was successfully shown.
-  void OnLoginScreenShown(bool users_empty, bool did_show);
-
   void OnPinCanAuthenticate(const AccountId& account_id, bool can_authenticate);
 
   bool initialized_ = false;
diff --git a/chrome/browser/chromeos/login/ui/mock_login_display_host.h b/chrome/browser/chromeos/login/ui/mock_login_display_host.h
index bf2c2cd..600d983 100644
--- a/chrome/browser/chromeos/login/ui/mock_login_display_host.h
+++ b/chrome/browser/chromeos/login/ui/mock_login_display_host.h
@@ -51,11 +51,9 @@
   MOCK_METHOD3(StartAppLaunch, void(const std::string&, bool, bool));
   MOCK_METHOD0(StartDemoAppLaunch, void(void));
   MOCK_METHOD1(StartArcKiosk, void(const AccountId&));
-  MOCK_METHOD2(ShowGaiaDialog,
-               void(bool can_close,
-                    const base::Optional<AccountId>& prefilled_account));
+  MOCK_METHOD2(ShowGaiaDialog, void(bool, const AccountId&));
   MOCK_METHOD0(HideOobeDialog, void());
-  MOCK_METHOD2(UpdateOobeDialogSize, void(int width, int height));
+  MOCK_METHOD2(UpdateOobeDialogSize, void(int, int));
   MOCK_METHOD1(UpdateOobeDialogState, void(ash::OobeDialogState state));
   MOCK_METHOD0(GetUsers, const user_manager::UserList(void));
 
diff --git a/chrome/browser/extensions/active_tab_apitest.cc b/chrome/browser/extensions/active_tab_apitest.cc
index ce868d38..34a2bd2 100644
--- a/chrome/browser/extensions/active_tab_apitest.cc
+++ b/chrome/browser/extensions/active_tab_apitest.cc
@@ -8,6 +8,7 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
 #include "base/test/scoped_feature_list.h"
 #include "chrome/browser/extensions/extension_action_runner.h"
 #include "chrome/browser/extensions/extension_apitest.h"
@@ -176,6 +177,38 @@
   }
 }
 
+IN_PROC_BROWSER_TEST_P(ExtensionActiveTabTest, ActiveTabCors) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
+
+  ExtensionTestMessageListener background_page_ready("ready",
+                                                     false /*will_reply*/);
+  const Extension* extension =
+      LoadExtension(test_data_dir_.AppendASCII("active_tab_cors"));
+  ASSERT_TRUE(extension);
+  ASSERT_TRUE(background_page_ready.WaitUntilSatisfied());
+
+  {
+    ui_test_utils::NavigateToURL(
+        browser(),
+        embedded_test_server()->GetURL(
+            "google.com", "/extensions/api_test/active_tab_cors/page.html"));
+    base::string16 title = base::ASCIIToUTF16("page");
+    content::TitleWatcher watcher(
+        browser()->tab_strip_model()->GetActiveWebContents(), title);
+    ASSERT_EQ(title, watcher.WaitAndGetTitle());
+  }
+
+  {
+    // The injected content script has an access to page's origin without
+    // explicit permissions other than "activeTab".
+    ResultCatcher catcher;
+    ExtensionActionRunner::GetForWebContents(
+        browser()->tab_strip_model()->GetActiveWebContents())
+        ->RunAction(extension, true);
+    EXPECT_TRUE(catcher.GetNextResult()) << message_;
+  }
+}
+
 INSTANTIATE_TEST_SUITE_P(WithBlinkCors,
                          ExtensionActiveTabTest,
                          testing::Values(TestMode::kWithBlinkCors));
diff --git a/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc b/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc
index d4dc455..b3d868b 100644
--- a/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc
+++ b/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc
@@ -9,7 +9,7 @@
 #include <memory>
 #include <utility>
 
-#include "ash/public/interfaces/keyboard_config.mojom.h"
+#include "ash/public/cpp/keyboard/keyboard_config.h"
 #include "base/feature_list.h"
 #include "base/macros.h"
 #include "chrome/browser/chromeos/input_method/input_method_engine.h"
@@ -91,7 +91,7 @@
   out->enabled = input.enabled ? *input.enabled : true;
 }
 
-keyboard::mojom::KeyboardConfig GetKeyboardConfig() {
+keyboard::KeyboardConfig GetKeyboardConfig() {
   return ChromeKeyboardControllerClient::Get()->GetKeyboardConfig();
 }
 
diff --git a/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc b/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc
index 812e63a..f067d4c 100644
--- a/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc
+++ b/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc
@@ -9,7 +9,7 @@
 #include <utility>
 
 #include "ash/public/cpp/keyboard/keyboard_switches.h"
-#include "ash/public/interfaces/keyboard_controller_types.mojom.h"
+#include "ash/public/cpp/keyboard/keyboard_types.h"
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/feature_list.h"
@@ -58,16 +58,16 @@
   return feature + (enabled ? "-enabled" : "-disabled");
 }
 
-keyboard::mojom::ContainerType ConvertKeyboardModeToContainerType(int mode) {
+keyboard::ContainerType ConvertKeyboardModeToContainerType(int mode) {
   switch (mode) {
     case keyboard_api::KEYBOARD_MODE_FULL_WIDTH:
-      return keyboard::mojom::ContainerType::kFullWidth;
+      return keyboard::ContainerType::kFullWidth;
     case keyboard_api::KEYBOARD_MODE_FLOATING:
-      return keyboard::mojom::ContainerType::kFloating;
+      return keyboard::ContainerType::kFloating;
   }
 
   NOTREACHED();
-  return keyboard::mojom::ContainerType::kFullWidth;
+  return keyboard::ContainerType::kFullWidth;
 }
 
 // Returns the ui::TextInputClient of the active InputMethod or nullptr.
@@ -152,7 +152,7 @@
   // TODO(bshe): layout string is currently hard coded. We should use more
   // standard keyboard layouts.
   return ChromeKeyboardControllerClient::Get()->IsEnableFlagSet(
-             keyboard::mojom::KeyboardEnableFlag::kAccessibilityEnabled)
+             keyboard::KeyboardEnableFlag::kAccessibilityEnabled)
              ? "system-qwerty"
              : "qwerty";
 }
@@ -196,7 +196,7 @@
 
   // Pass HIDE_REASON_MANUAL since calls to HideKeyboard as part of this API
   // would be user generated.
-  keyboard_client->HideKeyboard(ash::mojom::HideReason::kUser);
+  keyboard_client->HideKeyboard(ash::HideReason::kUser);
   return true;
 }
 
@@ -254,7 +254,7 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   auto* keyboard_client = ChromeKeyboardControllerClient::Get();
   if (keyboard_client->is_keyboard_enabled())
-    keyboard_client->HideKeyboard(ash::mojom::HideReason::kUser);
+    keyboard_client->HideKeyboard(ash::HideReason::kUser);
 
   base::RecordAction(base::UserMetricsAction("OpenLanguageOptionsDialog"));
   chrome::ShowSettingsSubPageForProfile(ProfileManager::GetActiveUserProfile(),
@@ -310,7 +310,7 @@
 }
 
 bool ChromeVirtualKeyboardDelegate::SetRequestedKeyboardState(int state_enum) {
-  using keyboard::mojom::KeyboardEnableFlag;
+  using keyboard::KeyboardEnableFlag;
   auto* client = ChromeKeyboardControllerClient::Get();
   keyboard_api::KeyboardState state =
       static_cast<keyboard_api::KeyboardState>(state_enum);
@@ -348,10 +348,9 @@
 
   // TODO(bshe): Consolidate a11y, hotrod and normal mode into a mode enum. See
   // crbug.com/529474.
-  results->SetBoolean(
-      "a11ymode",
-      keyboard_client->IsEnableFlagSet(
-          keyboard::mojom::KeyboardEnableFlag::kAccessibilityEnabled));
+  results->SetBoolean("a11ymode",
+                      keyboard_client->IsEnableFlagSet(
+                          keyboard::KeyboardEnableFlag::kAccessibilityEnabled));
   results->SetBoolean("hotrodmode", g_hotrod_keyboard_enabled);
   std::unique_ptr<base::ListValue> features(new base::ListValue());
 
@@ -365,7 +364,7 @@
   features->AppendString(GenerateFeatureFlag("virtualkeyboardmdui", true));
   features->AppendString(GenerateFeatureFlag("imeservice", true));
 
-  keyboard::mojom::KeyboardConfig config = keyboard_client->GetKeyboardConfig();
+  keyboard::KeyboardConfig config = keyboard_client->GetKeyboardConfig();
   // TODO(oka): Change this to use config.voice_input.
   features->AppendString(GenerateFeatureFlag(
       "voiceinput", has_audio_input_devices && config.voice_input));
@@ -412,9 +411,9 @@
   const api::virtual_keyboard::FeatureRestrictions& restrictions =
       params.restrictions;
   api::virtual_keyboard::FeatureRestrictions update;
-  keyboard::mojom::KeyboardConfig current_config =
+  keyboard::KeyboardConfig current_config =
       ChromeKeyboardControllerClient::Get()->GetKeyboardConfig();
-  keyboard::mojom::KeyboardConfig config(current_config);
+  keyboard::KeyboardConfig config(current_config);
   if (restrictions.spell_check_enabled &&
       config.spell_check != *restrictions.spell_check_enabled) {
     update.spell_check_enabled =
@@ -446,7 +445,7 @@
     config.handwriting = *restrictions.handwriting_enabled;
   }
 
-  if (!config.Equals(current_config)) {
+  if (config != current_config) {
     ChromeKeyboardControllerClient::Get()->SetKeyboardConfig(config);
     // This reloads virtual keyboard even if it exists. This ensures virtual
     // keyboard gets the correct state through
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index ad311dbb..070333c 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -346,6 +346,11 @@
     "expiry_milestone": 76
   },
   {
+    "name": "cast-media-route-provider",
+    "owners": [ "mfoltz", "takumif" ],
+    "expiry_milestone": 83
+  },
+  {
     "name": "cct-module",
     "owners": [ "mvanouwerkerk", "//chrome/android/java/src/org/chromium/chrome/browser/customtabs/OWNERS" ],
     "expiry_milestone": 76
@@ -534,6 +539,11 @@
     "expiry_milestone": 78
   },
   {
+    "name": "dial-media-route-provider",
+    "owners": [ "mfoltz", "takumif" ],
+    "expiry_milestone": 83
+  },
+  {
     "name": "direct-manipulation-stylus",
     "owners": [ "lanwei", "input-dev" ],
     "expiry_milestone": 76
@@ -2261,6 +2271,11 @@
     "expiry_milestone": 80
   },
   {
+    "name": "mirroring-service",
+    "owners": [ "mfoltz", "takumif" ],
+    "expiry_milestone": 83
+  },
+  {
     "name": "mobile-identity-consistency",
     "owners": [ "bsazonov", "droger", "msarda" ],
     "expiry_milestone": 80
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index ef44bd4..6d8ce15 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -2533,10 +2533,20 @@
 const char kAppManagementDescription[] =
     "Shows the new app management page at chrome://apps.";
 
+const char kCastMediaRouteProviderName[] = "Cast Media Route Provider";
+const char kCastMediaRouteProviderDescription[] =
+    "Enables the native Cast Media Route Provider implementation to be used "
+    "instead of the implementation in the Media Router component extension.";
+
 const char kChromeColorsName[] = "Chrome Colors menu";
 const char kChromeColorsDescription[] =
     "Show Chrome Colors menu in the NTP customization menu.";
 
+const char kDialMediaRouteProviderName[] = "DIAL Media Route Provider";
+const char kDialMediaRouteProviderDescription[] =
+    "Enables the native DIAL Media Route Provider implementation to be used "
+    "instead of the implementation in the Media Router component extension.";
+
 const char kGridLayoutForNtpShortcutsName[] =
     "Enable grid layout for NTP shortcuts";
 const char kGridLayoutForNtpShortcutsDescription[] =
@@ -2595,6 +2605,11 @@
 const char kKernelnextVMsDescription[] =
     "Enables VM support on devices running experimental kernel versions.";
 
+const char kMirroringServiceName[] = "Mirroring Service";
+const char kMirroringServiceDescription[] =
+    "Enables the native Mirroring Service for mirroring tabs or desktop to "
+    "Chromecast.  Requires AudioServiceAudioStreams to also be enabled.";
+
 const char kOmniboxDriveSuggestionsName[] =
     "Omnibox Google Drive Document suggestions";
 const char kOmniboxDriveSuggestionsDescriptions[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 4c6309c..9b98c2b 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -1496,9 +1496,15 @@
 extern const char kAutofillDropdownLayoutName[];
 extern const char kAutofillDropdownLayoutDescription[];
 
+extern const char kCastMediaRouteProviderName[];
+extern const char kCastMediaRouteProviderDescription[];
+
 extern const char kChromeColorsName[];
 extern const char kChromeColorsDescription[];
 
+extern const char kDialMediaRouteProviderName[];
+extern const char kDialMediaRouteProviderDescription[];
+
 extern const char kGridLayoutForNtpShortcutsName[];
 extern const char kGridLayoutForNtpShortcutsDescription[];
 
@@ -1532,6 +1538,9 @@
 extern const char kKernelnextVMsName[];
 extern const char kKernelnextVMsDescription[];
 
+extern const char kMirroringServiceName[];
+extern const char kMirroringServiceDescription[];
+
 extern const char kOmniboxDriveSuggestionsName[];
 extern const char kOmniboxDriveSuggestionsDescriptions[];
 
diff --git a/chrome/browser/hid/chrome_hid_delegate.cc b/chrome/browser/hid/chrome_hid_delegate.cc
new file mode 100644
index 0000000..8f178a5
--- /dev/null
+++ b/chrome/browser/hid/chrome_hid_delegate.cc
@@ -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.
+
+#include "chrome/browser/hid/chrome_hid_delegate.h"
+
+#include <utility>
+
+#include "chrome/browser/hid/hid_chooser_context.h"
+#include "chrome/browser/hid/hid_chooser_context_factory.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/chrome_bubble_manager.h"
+#include "chrome/browser/ui/hid/hid_chooser.h"
+#include "chrome/browser/ui/hid/hid_chooser_controller.h"
+#include "chrome/browser/ui/permission_bubble/chooser_bubble_delegate.h"
+#include "chrome/browser/usb/usb_blocklist.h"
+#include "content/public/browser/web_contents.h"
+
+ChromeHidDelegate::ChromeHidDelegate() = default;
+
+ChromeHidDelegate::~ChromeHidDelegate() = default;
+
+std::unique_ptr<content::HidChooser> ChromeHidDelegate::RunChooser(
+    content::RenderFrameHost* frame,
+    content::HidChooser::Callback callback) {
+  Browser* browser = chrome::FindBrowserWithWebContents(
+      content::WebContents::FromRenderFrameHost(frame));
+  if (!browser) {
+    std::move(callback).Run(nullptr);
+    return nullptr;
+  }
+
+  auto chooser_controller =
+      std::make_unique<HidChooserController>(frame, std::move(callback));
+  auto chooser_bubble_delegate = std::make_unique<ChooserBubbleDelegate>(
+      frame, std::move(chooser_controller));
+  BubbleReference bubble_reference = browser->GetBubbleManager()->ShowBubble(
+      std::move(chooser_bubble_delegate));
+  return std::make_unique<HidChooser>(std::move(bubble_reference));
+}
+
+bool ChromeHidDelegate::CanRequestDevicePermission(
+    content::RenderFrameHost* frame) {
+  auto* web_contents = content::WebContents::FromRenderFrameHost(frame);
+  auto* profile =
+      Profile::FromBrowserContext(web_contents->GetBrowserContext());
+  auto* chooser_context = HidChooserContextFactory::GetForProfile(profile);
+  return chooser_context->CanRequestObjectPermission(
+      frame->GetLastCommittedOrigin(),
+      web_contents->GetMainFrame()->GetLastCommittedOrigin());
+}
+
+bool ChromeHidDelegate::HasDevicePermission(
+    content::RenderFrameHost* frame,
+    const device::mojom::HidDeviceInfo& device) {
+  auto* web_contents = content::WebContents::FromRenderFrameHost(frame);
+  auto* profile =
+      Profile::FromBrowserContext(web_contents->GetBrowserContext());
+  auto* chooser_context = HidChooserContextFactory::GetForProfile(profile);
+  return chooser_context->HasDevicePermission(
+      frame->GetLastCommittedOrigin(),
+      web_contents->GetMainFrame()->GetLastCommittedOrigin(), device);
+}
+
+device::mojom::HidManager* ChromeHidDelegate::GetHidManager(
+    content::RenderFrameHost* frame) {
+  auto* web_contents = content::WebContents::FromRenderFrameHost(frame);
+  auto* profile =
+      Profile::FromBrowserContext(web_contents->GetBrowserContext());
+  auto* chooser_context = HidChooserContextFactory::GetForProfile(profile);
+  return chooser_context->GetHidManager();
+}
diff --git a/chrome/browser/hid/chrome_hid_delegate.h b/chrome/browser/hid/chrome_hid_delegate.h
new file mode 100644
index 0000000..0e9c0275
--- /dev/null
+++ b/chrome/browser/hid/chrome_hid_delegate.h
@@ -0,0 +1,31 @@
+// 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_HID_CHROME_HID_DELEGATE_H_
+#define CHROME_BROWSER_HID_CHROME_HID_DELEGATE_H_
+
+#include <memory>
+#include <vector>
+
+#include "content/public/browser/hid_delegate.h"
+
+class ChromeHidDelegate : public content::HidDelegate {
+ public:
+  ChromeHidDelegate();
+  ~ChromeHidDelegate() override;
+
+  std::unique_ptr<content::HidChooser> RunChooser(
+      content::RenderFrameHost* frame,
+      content::HidChooser::Callback callback) override;
+  bool CanRequestDevicePermission(content::RenderFrameHost* frame) override;
+  bool HasDevicePermission(content::RenderFrameHost* frame,
+                           const device::mojom::HidDeviceInfo& device) override;
+  device::mojom::HidManager* GetHidManager(
+      content::RenderFrameHost* frame) override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ChromeHidDelegate);
+};
+
+#endif  // CHROME_BROWSER_HID_CHROME_HID_DELEGATE_H_
diff --git a/chrome/browser/media/router/media_router_feature.cc b/chrome/browser/media/router/media_router_feature.cc
index 5d7b8ea0..64b703b 100644
--- a/chrome/browser/media/router/media_router_feature.cc
+++ b/chrome/browser/media/router/media_router_feature.cc
@@ -130,7 +130,11 @@
 }
 
 bool ShouldUseMirroringService() {
-  return base::FeatureList::IsEnabled(mirroring::features::kMirroringService) &&
+  // The native Cast MRP requires the mirroring service to do mirroring, so try
+  // to enable the service if the native Cast MRP is being used.
+  return (base::FeatureList::IsEnabled(
+              mirroring::features::kMirroringService) ||
+          base::FeatureList::IsEnabled(kCastMediaRouteProvider)) &&
          base::FeatureList::IsEnabled(features::kAudioServiceAudioStreams) &&
          base::FeatureList::IsEnabled(network::features::kNetworkService);
 }
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc
index 52bb56b..17d06fe1 100644
--- a/chrome/browser/policy/policy_browsertest.cc
+++ b/chrome/browser/policy/policy_browsertest.cc
@@ -1010,16 +1010,14 @@
   }
 
 #if defined(OS_CHROMEOS)
-  void SetEnableFlag(const keyboard::mojom::KeyboardEnableFlag& flag) {
+  void SetEnableFlag(const keyboard::KeyboardEnableFlag& flag) {
     auto* keyboard_client = ChromeKeyboardControllerClient::Get();
     keyboard_client->SetEnableFlag(flag);
-    keyboard_client->FlushForTesting();
   }
 
-  void ClearEnableFlag(const keyboard::mojom::KeyboardEnableFlag& flag) {
+  void ClearEnableFlag(const keyboard::KeyboardEnableFlag& flag) {
     auto* keyboard_client = ChromeKeyboardControllerClient::Get();
     keyboard_client->ClearEnableFlag(flag);
-    keyboard_client->FlushForTesting();
   }
 #endif
 
@@ -4049,9 +4047,9 @@
   EXPECT_FALSE(keyboard_client->is_keyboard_enabled());
 
   // Verify keyboard can be toggled by default.
-  SetEnableFlag(keyboard::mojom::KeyboardEnableFlag::kTouchEnabled);
+  SetEnableFlag(keyboard::KeyboardEnableFlag::kTouchEnabled);
   EXPECT_TRUE(keyboard_client->is_keyboard_enabled());
-  ClearEnableFlag(keyboard::mojom::KeyboardEnableFlag::kTouchEnabled);
+  ClearEnableFlag(keyboard::KeyboardEnableFlag::kTouchEnabled);
   EXPECT_FALSE(keyboard_client->is_keyboard_enabled());
 
   // Verify enabling the policy takes effect immediately and that that user
@@ -4061,9 +4059,8 @@
                POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
                std::make_unique<base::Value>(true), nullptr);
   UpdateProviderPolicy(policies);
-  keyboard_client->FlushForTesting();
   EXPECT_TRUE(keyboard_client->is_keyboard_enabled());
-  ClearEnableFlag(keyboard::mojom::KeyboardEnableFlag::kTouchEnabled);
+  ClearEnableFlag(keyboard::KeyboardEnableFlag::kTouchEnabled);
   EXPECT_TRUE(keyboard_client->is_keyboard_enabled());
 
   // Verify that disabling the policy takes effect immediately and that the user
@@ -4072,9 +4069,8 @@
                POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
                std::make_unique<base::Value>(false), nullptr);
   UpdateProviderPolicy(policies);
-  keyboard_client->FlushForTesting();
   EXPECT_FALSE(keyboard_client->is_keyboard_enabled());
-  SetEnableFlag(keyboard::mojom::KeyboardEnableFlag::kTouchEnabled);
+  SetEnableFlag(keyboard::KeyboardEnableFlag::kTouchEnabled);
   EXPECT_FALSE(keyboard_client->is_keyboard_enabled());
 }
 
diff --git a/chrome/browser/resources/chromeos/zip_archiver/js/compressor.js b/chrome/browser/resources/chromeos/zip_archiver/js/compressor.js
index b5ceda9..73adf4c5 100644
--- a/chrome/browser/resources/chromeos/zip_archiver/js/compressor.js
+++ b/chrome/browser/resources/chromeos/zip_archiver/js/compressor.js
@@ -219,7 +219,7 @@
               });
         })
         .catch((error) => {
-          console.error('failed to create a ZIP file', error);
+          console.error('failed to create a ZIP file: ' + error.code);
           this.onErrorInternal_();
         });
   };
diff --git a/chrome/browser/resources/history/history_list.html b/chrome/browser/resources/history/history_list.html
index e193467..cbd4f20 100644
--- a/chrome/browser/resources/history/history_list.html
+++ b/chrome/browser/resources/history/history_list.html
@@ -1,7 +1,6 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
 <link rel="import" href="chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.html">
-<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_style_css.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-a11y-announcer/iron-a11y-announcer.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html">
@@ -11,11 +10,11 @@
 <link rel="import" href="history_item.html">
 <link rel="import" href="shared_style.html">
 
-<!-- Lazy loaded: cr-dialog, cr-action-menu, paper-button. -->
+<!-- Lazy loaded: cr-dialog, cr-action-menu, cr-button. -->
 
 <dom-module id="history-list">
   <template>
-    <style include="shared-style cr-shared-style paper-button-style">
+    <style include="shared-style cr-shared-style">
       :host {
         box-sizing: border-box;
         display: block;
@@ -65,12 +64,12 @@
           <div slot="title">$i18n{removeSelected}</div>
           <div slot="body">$i18n{deleteWarning}</div>
           <div slot="button-container">
-            <paper-button class="cancel-button" on-click="onDialogCancelTap_">
+            <cr-button class="cancel-button" on-click="onDialogCancelTap_">
               $i18n{cancel}
-            </paper-button>
-            <paper-button class="action-button" on-click="onDialogConfirmTap_">
+            </cr-button>
+            <cr-button class="action-button" on-click="onDialogConfirmTap_">
               $i18n{deleteConfirm}
-            </paper-button>
+            </cr-button>
           </div>
         </cr-dialog>
       </template>
diff --git a/chrome/browser/resources/history/lazy_load.html b/chrome/browser/resources/history/lazy_load.html
index 53567c5..567691b1 100644
--- a/chrome/browser/resources/history/lazy_load.html
+++ b/chrome/browser/resources/history/lazy_load.html
@@ -3,11 +3,11 @@
 <body>
   <link rel="import" href="synced_device_manager.html">
   <link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html">
+  <link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
   <link rel="import" href="chrome://resources/cr_elements/cr_checkbox/cr_checkbox.html">
   <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
   <link rel="import" href="chrome://resources/cr_elements/cr_drawer/cr_drawer.html">
   <link rel="import" href="chrome://resources/cr_elements/cr_icon_button/cr_icon_button.html">
   <link rel="import" href="chrome://resources/cr_elements/cr_toolbar/cr_toolbar_selection_overlay.html">
-  <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 </body>
 </html>
diff --git a/chrome/browser/resources/history/synced_device_manager.html b/chrome/browser/resources/history/synced_device_manager.html
index 0d077c9..c35ce9b3 100644
--- a/chrome/browser/resources/history/synced_device_manager.html
+++ b/chrome/browser/resources/history/synced_device_manager.html
@@ -2,10 +2,9 @@
 
 <link rel="import" href="chrome://resources/html/cr/ui/focus_grid.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.html">
-<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_style_css.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="shared_style.html">
@@ -14,7 +13,7 @@
 
 <dom-module id="history-synced-device-manager">
   <template>
-    <style include="shared-style cr-shared-style paper-button-style">
+    <style include="shared-style cr-shared-style">
       :host {
         display: block;
         overflow: auto;
@@ -86,10 +85,10 @@
       <div id="illustration"></div>
       <div id="sign-in-promo">$i18n{signInPromo}</div>
       <div id="sign-in-promo-desc">$i18n{signInPromoDesc}</div>
-      <paper-button id="sign-in-button" class="action-button"
+      <cr-button id="sign-in-button" class="action-button"
           on-click="onSignInTap_">
         $i18n{signInButton}
-      </paper-button>
+      </cr-button>
     </div>
 
     <cr-lazy-render id="menu">
diff --git a/chrome/browser/resources/pdf/elements/viewer-page-indicator/viewer-page-indicator.html b/chrome/browser/resources/pdf/elements/viewer-page-indicator/viewer-page-indicator.html
index e815e1cb..70ad257 100644
--- a/chrome/browser/resources/pdf/elements/viewer-page-indicator/viewer-page-indicator.html
+++ b/chrome/browser/resources/pdf/elements/viewer-page-indicator/viewer-page-indicator.html
@@ -7,6 +7,7 @@
     <style>
       :host {
         display: flex;
+        opacity: 0;
         pointer-events: none;
         position: fixed;
         right: 0;
diff --git a/chrome/browser/resources/pdf/elements/viewer-page-indicator/viewer-page-indicator.js b/chrome/browser/resources/pdf/elements/viewer-page-indicator/viewer-page-indicator.js
index c0a3e0b..50ad4f4 100644
--- a/chrome/browser/resources/pdf/elements/viewer-page-indicator/viewer-page-indicator.js
+++ b/chrome/browser/resources/pdf/elements/viewer-page-indicator/viewer-page-indicator.js
@@ -18,18 +18,14 @@
 
   /** @override */
   ready: function() {
-    const callback = this.fadeIn.bind(this, 2000);
+    const callback = this.fadeIn_.bind(this);
     window.addEventListener('scroll', function() {
       requestAnimationFrame(callback);
     });
   },
 
-  initialFadeIn: function() {
-    this.fadeIn(6000);
-  },
-
-  /** @param {number} displayTime */
-  fadeIn: function(displayTime) {
+  /** @private */
+  fadeIn_: function() {
     const percent = window.scrollY /
         (document.scrollingElement.scrollHeight -
          document.documentElement.clientHeight);
@@ -55,7 +51,7 @@
     this.timerId = setTimeout(() => {
       this.style.opacity = 0;
       this.timerId = undefined;
-    }, displayTime);
+    }, 2000);
   },
 
   pageLabelsChanged: function() {
diff --git a/chrome/browser/resources/pdf/pdf_viewer.js b/chrome/browser/resources/pdf/pdf_viewer.js
index 942761c0..ffe73802 100644
--- a/chrome/browser/resources/pdf/pdf_viewer.js
+++ b/chrome/browser/resources/pdf/pdf_viewer.js
@@ -1091,10 +1091,6 @@
       this.passwordScreen_.close();
     }
 
-    if (this.pageIndicator_) {
-      this.pageIndicator_.initialFadeIn();
-    }
-
     if (this.toolbar_) {
       this.toolbar_.docLength = this.documentDimensions_.pageDimensions.length;
     }
diff --git a/chrome/browser/resources/print_preview/cloud_print_interface.js b/chrome/browser/resources/print_preview/cloud_print_interface.js
index 7fb4b8d..8fb44136 100644
--- a/chrome/browser/resources/print_preview/cloud_print_interface.js
+++ b/chrome/browser/resources/print_preview/cloud_print_interface.js
@@ -89,6 +89,12 @@
     search(opt_account, opt_origin) {}
 
     /**
+     * Sets the currently active users.
+     * @param {!Array<string>} users
+     */
+    setUsers(users) {}
+
+    /**
      * Sends Google Cloud Print printer sharing invitations API requests.
      * @param {string} account Account the request is sent for.
      */
diff --git a/chrome/browser/resources/print_preview/cloud_print_interface_js.js b/chrome/browser/resources/print_preview/cloud_print_interface_js.js
index 8ede13af..553a082 100644
--- a/chrome/browser/resources/print_preview/cloud_print_interface_js.js
+++ b/chrome/browser/resources/print_preview/cloud_print_interface_js.js
@@ -325,10 +325,15 @@
     setUsers_(request) {
       if (request.origin == print_preview.DestinationOrigin.COOKIES) {
         const users = request.result['request']['users'] || [];
-        this.userSessionIndex_ = {};
-        for (let i = 0; i < users.length; i++) {
-          this.userSessionIndex_[users[i]] = i;
-        }
+        this.setUsers(users);
+      }
+    }
+
+    /** @param {!Array<string>} users */
+    setUsers(users) {
+      this.userSessionIndex_ = {};
+      for (let i = 0; i < users.length; i++) {
+        this.userSessionIndex_[users[i]] = i;
       }
     }
 
@@ -551,13 +556,13 @@
       // this point, whether printer was found or not.
       if (request.origin == print_preview.DestinationOrigin.COOKIES &&
           request.result && request.result['request']['user'] &&
-          request.result['request']['users'] &&
-          request.account != request.result['request']['user']) {
+          request.result['request']['users']) {
         const users = request.result['request']['users'];
         this.setUsers_(request);
         // In case the user account is known, but not the primary one,
         // activate it.
-        if (this.userSessionIndex_[request.account] > 0 && request.account) {
+        if (request.account != request.result['request']['user'] &&
+            this.userSessionIndex_[request.account] > 0 && request.account) {
           this.dispatchUserUpdateEvent_(request.account, users);
           // Repeat the request for the newly activated account.
           this.printer(
diff --git a/chrome/browser/resources/print_preview/cloud_print_interface_native.js b/chrome/browser/resources/print_preview/cloud_print_interface_native.js
index 5455aabb..c12f284 100644
--- a/chrome/browser/resources/print_preview/cloud_print_interface_native.js
+++ b/chrome/browser/resources/print_preview/cloud_print_interface_native.js
@@ -19,6 +19,9 @@
     search(opt_account, opt_origin) {}
 
     /** @override */
+    setUsers(users) {}
+
+    /** @override */
     invites(account) {}
 
     /** @override */
diff --git a/chrome/browser/resources/print_preview/data/destination_store.js b/chrome/browser/resources/print_preview/data/destination_store.js
index 2d92b167..20449f32 100644
--- a/chrome/browser/resources/print_preview/data/destination_store.js
+++ b/chrome/browser/resources/print_preview/data/destination_store.js
@@ -280,8 +280,6 @@
           loadTimeData.getBoolean('useSystemDefaultPrinter');
 
       addListenerCallback('printers-added', this.onPrintersAdded_.bind(this));
-      addListenerCallback(
-          'user-accounts-updated', this.onDestinationsReload.bind(this));
     }
 
     /**
@@ -291,12 +289,10 @@
      *     accessible by the {@code account}.
      */
     destinations(opt_account) {
-      if (opt_account) {
-        return this.destinations_.filter(function(destination) {
-          return !destination.account || destination.account == opt_account;
-        });
-      }
-      return this.destinations_.slice(0);
+      return this.destinations_.filter(function(destination) {
+        return !destination.account ||
+            (!!opt_account && destination.account == opt_account);
+      });
     }
 
     /**
@@ -806,9 +802,8 @@
      * Attempts to select system default destination with a fallback to the
      * 'Save to PDF' destination and a final fallback to the first destination
      * in the store.
-     * @private
      */
-    selectDefaultDestination_() {
+    selectDefaultDestination() {
       // Try the system default, if it isn't the destination that was
       // supposed to be autoselected and failed.
       if (this.autoSelectMatchingDestination_ &&
@@ -1083,7 +1078,7 @@
           this.autoSelectMatchingDestination_.matchOrigin(
               print_preview.DestinationOrigin.EXTENSION) &&
           this.selectedDestination_ && this.selectedDestination_.isExtension) {
-        this.selectDefaultDestination_();
+        this.selectDefaultDestination();
       }
     }
 
@@ -1137,29 +1132,11 @@
     startAutoSelectTimeout_() {
       clearTimeout(this.autoSelectTimeout_);
       this.autoSelectTimeout_ = setTimeout(
-          this.selectDefaultDestination_.bind(this),
+          this.selectDefaultDestination.bind(this),
           DestinationStore.AUTO_SELECT_TIMEOUT_);
     }
 
     /**
-     * Resets the state of the destination store to its initial state.
-     * @private
-     */
-    reset_() {
-      this.destinations_ = [];
-      this.destinationMap_.clear();
-      this.inFlightCloudPrintRequests_.clear();
-      this.loadedCloudOrigins_.clear();
-      this.destinationSearchStatus_.forEach((status, type) => {
-        this.destinationSearchStatus_.set(
-            type, print_preview.DestinationStorePrinterSearchStatus.START);
-      });
-      this.startAutoSelectTimeout_();
-      this.dispatchEvent(
-          new CustomEvent(DestinationStore.EventType.DESTINATIONS_RESET));
-    }
-
-    /**
      * Called when destination search is complete for some type of printer.
      * @param {!print_preview.PrinterType} type The type of printers that are
      *     done being retreived.
@@ -1240,7 +1217,7 @@
       if (this.autoSelectMatchingDestination_ &&
           this.autoSelectMatchingDestination_.matchIdAndOrigin(
               destinationId, origin)) {
-        this.selectDefaultDestination_();
+        this.selectDefaultDestination();
       }
     }
 
@@ -1326,7 +1303,7 @@
         console.warn(
             'Failed to fetch last used printer caps: ' +
             event.detail.destinationId);
-        this.selectDefaultDestination_();
+        this.selectDefaultDestination();
       } else {
         // Log the failure
         console.warn(
@@ -1367,18 +1344,6 @@
         this.selectFirstDestination_ = false;
       }
     }
-
-    /**
-     * Called from print preview after the user was requested to sign in, and
-     * did so successfully.
-     */
-    onDestinationsReload() {
-      this.reset_();
-      this.autoSelectMatchingDestination_ =
-          this.convertPreselectedToDestinationMatch_();
-      this.createLocalPdfPrintDestination_();
-      this.startLoadAllDestinations();
-    }
   }
 
   /**
@@ -1391,7 +1356,6 @@
     DESTINATION_SELECT: 'print_preview.DestinationStore.DESTINATION_SELECT',
     DESTINATIONS_INSERTED:
         'print_preview.DestinationStore.DESTINATIONS_INSERTED',
-    DESTINATIONS_RESET: 'print_preview.DestinationStore.DESTINATIONS_RESET',
     ERROR: 'print_preview.DestinationStore.ERROR',
     SELECTED_DESTINATION_CAPABILITIES_READY: 'print_preview.DestinationStore' +
         '.SELECTED_DESTINATION_CAPABILITIES_READY',
diff --git a/chrome/browser/resources/print_preview/data/user_manager.js b/chrome/browser/resources/print_preview/data/user_manager.js
index ac2814d7..8124cad 100644
--- a/chrome/browser/resources/print_preview/data/user_manager.js
+++ b/chrome/browser/resources/print_preview/data/user_manager.js
@@ -32,6 +32,12 @@
       notify: true,
     },
 
+    /** @type {?cloudprint.CloudPrintInterface} */
+    cloudPrintInterface: {
+      type: Object,
+      observer: 'onCloudPrintInterfaceSet_',
+    },
+
     /** @type {?print_preview.DestinationStore} */
     destinationStore: Object,
 
@@ -93,19 +99,22 @@
     }
   },
 
-  /** @param {!cloudprint.CloudPrintInterface} cloudPrintInterface */
-  setCloudPrintInterface: function(cloudPrintInterface) {
+  /** @private */
+  onCloudPrintInterfaceSet_: function() {
     this.tracker_.add(
-        cloudPrintInterface.getEventTarget(),
+        this.cloudPrintInterface.getEventTarget(),
         cloudprint.CloudPrintInterfaceEventType.UPDATE_USERS,
         this.onCloudPrintUpdateUsers_.bind(this));
     [cloudprint.CloudPrintInterfaceEventType.SEARCH_FAILED,
      cloudprint.CloudPrintInterfaceEventType.PRINTER_FAILED,
     ].forEach(eventType => {
       this.tracker_.add(
-          cloudPrintInterface.getEventTarget(), eventType,
+          this.cloudPrintInterface.getEventTarget(), eventType,
           this.checkCloudPrintStatus_.bind(this));
     });
+    if (this.users.length > 0) {
+      this.cloudPrintInterface.setUsers(this.users);
+    }
     assert(this.cloudPrintDisabled);
     this.cloudPrintDisabled = false;
   },
@@ -149,6 +158,9 @@
     const updateActiveUser = (users.length > 0 && this.users.length === 0) ||
         !users.includes(this.activeUser);
     this.users = users;
+    if (this.cloudPrintInterface) {
+      this.cloudPrintInterface.setUsers(users);
+    }
     if (updateActiveUser) {
       this.updateActiveUser(this.users[0] || '');
     }
diff --git a/chrome/browser/resources/print_preview/ui/advanced_options_settings.html b/chrome/browser/resources/print_preview/ui/advanced_options_settings.html
index 180b598..4cffcd9 100644
--- a/chrome/browser/resources/print_preview/ui/advanced_options_settings.html
+++ b/chrome/browser/resources/print_preview/ui/advanced_options_settings.html
@@ -1,7 +1,6 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
-<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="../data/destination.html">
 <link rel="import" href="advanced_settings_dialog.html">
 <link rel="import" href="print_preview_shared_css.html">
@@ -9,8 +8,8 @@
 
 <dom-module id="print-preview-advanced-options-settings">
   <template>
-    <style include="print-preview-shared paper-button-style">
-      paper-button {
+    <style include="print-preview-shared">
+      cr-button {
         min-height: 32px;
         text-align: center;
         width: calc(100% - 2 * var(--print-preview-sidebar-margin));
@@ -19,10 +18,10 @@
     <print-preview-settings-section>
       <span slot="title"></span>
       <div slot="controls">
-        <paper-button id="button" disabled$="[[disabled]]"
+        <cr-button id="button" disabled$="[[disabled]]"
             on-click="onButtonClick_">
           $i18n{newShowAdvancedOptions}
-        </paper-button>
+        </cr-button>
       </div>
     </print-preview-settings-section>
     <template is="dom-if" if="[[showAdvancedDialog_]]" restamp>
diff --git a/chrome/browser/resources/print_preview/ui/advanced_settings_dialog.html b/chrome/browser/resources/print_preview/ui/advanced_settings_dialog.html
index 36b3dbd..3ce7f148 100644
--- a/chrome/browser/resources/print_preview/ui/advanced_settings_dialog.html
+++ b/chrome/browser/resources/print_preview/ui/advanced_settings_dialog.html
@@ -1,10 +1,9 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
-<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../metrics.html">
 <link rel="import" href="../data/destination.html">
 <link rel="import" href="advanced_settings_item.html">
@@ -16,7 +15,7 @@
 
 <dom-module id="print-preview-advanced-settings-dialog">
   <template>
-    <style include="print-preview-shared paper-button-style cr-hidden-style">
+    <style include="print-preview-shared cr-hidden-style">
       #dialog {
         --cr-dialog-native: {
           height: -webkit-fit-content;
@@ -54,12 +53,12 @@
         </div>
       </div>
       <div slot="button-container">
-        <paper-button class="cancel-button" on-click="onCancelButtonClick_">
+        <cr-button class="cancel-button" on-click="onCancelButtonClick_">
           $i18n{cancel}
-        </paper-button>
-        <paper-button class="action-button" on-click="onApplyButtonClick_">
+        </cr-button>
+        <cr-button class="action-button" on-click="onApplyButtonClick_">
           $i18n{advancedSettingsDialogConfirm}
-        </paper-button>
+        </cr-button>
       </div>
     </cr-dialog>
   </template>
diff --git a/chrome/browser/resources/print_preview/ui/app.js b/chrome/browser/resources/print_preview/ui/app.js
index 3b6c9e67..545a5bf6 100644
--- a/chrome/browser/resources/print_preview/ui/app.js
+++ b/chrome/browser/resources/print_preview/ui/app.js
@@ -209,7 +209,7 @@
         this.state === print_preview.State.READY &&
         this.openDialogs_.length === 0) {
       const activeElementTag = e.path[0].tagName;
-      if (['PAPER-BUTTON', 'BUTTON', 'SELECT', 'A', 'CR-CHECKBOX'].includes(
+      if (['CR-BUTTON', 'BUTTON', 'SELECT', 'A', 'CR-CHECKBOX'].includes(
               activeElementTag)) {
         return;
       }
diff --git a/chrome/browser/resources/print_preview/ui/button_strip.html b/chrome/browser/resources/print_preview/ui/button_strip.html
index c0dda930..3602997 100644
--- a/chrome/browser/resources/print_preview/ui/button_strip.html
+++ b/chrome/browser/resources/print_preview/ui/button_strip.html
@@ -1,17 +1,16 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
-<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/html/assert.html">
 <link rel="import" href="chrome://resources/html/cr.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../data/destination.html">
 <link rel="import" href="../data/state.html">
 <link rel="import" href="strings.html">
 
 <dom-module id="print-preview-button-strip">
   <template>
-    <style include="paper-button-style">
+    <style>
       :host {
         display: flex;
         flex-direction: row;
@@ -25,27 +24,27 @@
         background-color: white;
       }
 
-      :host paper-button:not(:last-child) {
+      :host cr-button:not(:last-child) {
         margin-inline-end: 8px;
       }
 
-      :host paper-button:last-child {
+      :host cr-button:last-child {
         margin-inline-end: 0;
       }
     </style>
 <if expr="not is_win">
-    <paper-button class="cancel-button" on-click="onCancelClick_">
+    <cr-button class="cancel-button" on-click="onCancelClick_">
       $i18n{cancel}
-    </paper-button>
+    </cr-button>
 </if>
-    <paper-button class="action-button" on-click="onPrintClick_"
+    <cr-button class="action-button" on-click="onPrintClick_"
         disabled$="[[!printButtonEnabled_]]">
       [[printButtonLabel_]]
-    </paper-button>
+    </cr-button>
 <if expr="is_win">
-    <paper-button class="cancel-button" on-click="onCancelClick_">
+    <cr-button class="cancel-button" on-click="onCancelClick_">
       $i18n{cancel}
-    </paper-button>
+    </cr-button>
 </if>
   </template>
   <script src="button_strip.js"></script>
diff --git a/chrome/browser/resources/print_preview/ui/button_strip.js b/chrome/browser/resources/print_preview/ui/button_strip.js
index ffcfb2e..debcc7d 100644
--- a/chrome/browser/resources/print_preview/ui/button_strip.js
+++ b/chrome/browser/resources/print_preview/ui/button_strip.js
@@ -74,7 +74,7 @@
         if (this.lastState_ != this.state &&
             (document.activeElement == null ||
              document.activeElement == document.body)) {
-          this.$$('paper-button.action-button').focus();
+          this.$$('cr-button.action-button').focus();
         }
         break;
       default:
diff --git a/chrome/browser/resources/print_preview/ui/destination_dialog.html b/chrome/browser/resources/print_preview/ui/destination_dialog.html
index 5dd7ab58..58a65d5 100644
--- a/chrome/browser/resources/print_preview/ui/destination_dialog.html
+++ b/chrome/browser/resources/print_preview/ui/destination_dialog.html
@@ -1,10 +1,10 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_icon_button/cr_icon_button.html">
 <link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
 <link rel="import" href="chrome://resources/cr_elements/icons.html">
-<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <!-- The imports below are needed as an action-link is added to the promo-text
   div to create the cloud print "Sign in" link when this element is
@@ -16,7 +16,6 @@
 <link rel="import" href="chrome://resources/html/list_property_update_behavior.html">
 <link rel="import" href="chrome://resources/html/md_select_css.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../icons.html">
 <link rel="import" href="../metrics.html">
 <link rel="import" href="../native_layer.html">
@@ -36,7 +35,7 @@
 <dom-module id="print-preview-destination-dialog">
   <template>
     <style include="print-preview-shared action-link md-select cr-hidden-style
-        throbber paper-button-style">
+        throbber">
       #dialog {
         --cr-dialog-native: {
           height: calc(100vh - 2 * var(--print-preview-dialog-margin));
@@ -79,7 +78,7 @@
         justify-content: space-between;
       }
 
-      paper-button {
+      cr-button {
         font-size: calc(12 / 13 * 1em);
       }
 
@@ -131,11 +130,11 @@
         padding: 12px 0;
       }
 
-      #invitationPromo paper-button {
+      #invitationPromo cr-button {
         margin: 0 4px;
       }
 
-      :host-context(html:not([dark])) #invitationPromo paper-button {
+      :host-context(html:not([dark])) #invitationPromo cr-button {
         background-color: white;
       }
 
@@ -155,8 +154,7 @@
           <select class="md-select account-select"
               aria-labelledby="accountSelectLabel" on-change="onUserChange_">
             <template is="dom-repeat" items="[[users]]">
-              <option selected="[[isSelected_(item, activeUser)]]"
-                  value="[[item]]">
+              <option value="[[item]]">
                 [[item]]
               </option>
             </template>
@@ -181,12 +179,12 @@
         </print-preview-provisional-destination-resolver>
       </div>
       <div slot="button-container">
-        <paper-button on-click="onOpenSettingsPrintPage_">
+        <cr-button on-click="onOpenSettingsPrintPage_">
           $i18n{manage}
-        </paper-button>
-        <paper-button class="cancel-button" on-click="onCancelButtonClick_">
+        </cr-button>
+        <cr-button class="cancel-button" on-click="onCancelButtonClick_">
           $i18n{cancel}
-        </paper-button>
+        </cr-button>
       </div>
       <div id="promos" slot="footer" hidden="[[!shouldShowFooter_(
           shouldShowCloudPrintPromo_, invitation_)]]">
@@ -200,12 +198,12 @@
         <div class="promo" id="invitationPromo" hidden="[[!invitation_]]">
           <div inner-h-t-m-l="[[getInvitationText_(invitation_)]]"></div>
           <div class="invitation-buttons">
-            <paper-button on-click="onInvitationAcceptClick_">
+            <cr-button on-click="onInvitationAcceptClick_">
               [[getAcceptButtonText_(invitation_)]]
-            </paper-button>
-            <paper-button on-click="onInvitationRejectClick_">
+            </cr-button>
+            <cr-button on-click="onInvitationRejectClick_">
               $i18n{reject}
-            </paper-button>
+            </cr-button>
             <div id="invitation-process-throbber" class="throbber" hidden></div>
           </div>
           <div class="invitation-details">
diff --git a/chrome/browser/resources/print_preview/ui/destination_dialog.js b/chrome/browser/resources/print_preview/ui/destination_dialog.js
index bf05c1a..16556ec 100644
--- a/chrome/browser/resources/print_preview/ui/destination_dialog.js
+++ b/chrome/browser/resources/print_preview/ui/destination_dialog.js
@@ -22,7 +22,7 @@
 
     activeUser: {
       type: String,
-      observer: 'updateDestinationsAndInvitations_',
+      observer: 'onActiveUserChange_',
     },
 
     currentDestinationAccount: String,
@@ -138,10 +138,6 @@
         this.updateDestinations_.bind(this));
     this.tracker_.add(
         destinationStore,
-        print_preview.DestinationStore.EventType.DESTINATIONS_RESET,
-        () => this.destinations_ = []);
-    this.tracker_.add(
-        destinationStore,
         print_preview.DestinationStore.EventType.DESTINATION_SEARCH_DONE,
         this.updateDestinationsAndInvitations_.bind(this));
     this.initialized_ = true;
@@ -161,6 +157,15 @@
   },
 
   /** @private */
+  onActiveUserChange_: function() {
+    if (this.activeUser) {
+      this.$$('select').value = this.activeUser;
+    }
+
+    this.updateDestinationsAndInvitations_();
+  },
+
+  /** @private */
   updateDestinationsAndInvitations_: function() {
     if (!this.initialized_) {
       return;
@@ -286,6 +291,11 @@
         this.destinationStore.isPrintDestinationSearchInProgress;
     this.metrics_.record(
         print_preview.Metrics.DestinationSearchBucket.DESTINATION_SHOWN);
+    if (this.activeUser) {
+      Polymer.RenderStatus.beforeNextRender(assert(this.$$('select')), () => {
+        this.$$('select').value = this.activeUser;
+      });
+    }
     this.$.printList.forceIronResize();
   },
 
@@ -295,11 +305,6 @@
   },
 
   /** @private */
-  isSelected_: function(account) {
-    return account == this.activeUser;
-  },
-
-  /** @private */
   onSignInClick_: function() {
     this.metrics_.record(
         print_preview.Metrics.DestinationSearchBucket.SIGNIN_TRIGGERED);
@@ -387,19 +392,12 @@
     const account = select.value;
     if (account) {
       this.loadingDestinations_ = true;
-      this.destinations_ = [];
       this.fire('account-change', account);
       this.metrics_.record(
           print_preview.Metrics.DestinationSearchBucket.ACCOUNT_CHANGED);
     } else {
+      select.value = this.activeUser;
       print_preview.NativeLayer.getInstance().signIn(true);
-      const options = select.querySelectorAll('option');
-      for (let i = 0; i < options.length; i++) {
-        if (options[i].value == this.activeUser) {
-          select.selectedIndex = i;
-          break;
-        }
-      }
       this.metrics_.record(
           print_preview.Metrics.DestinationSearchBucket.ADD_ACCOUNT_SELECTED);
     }
diff --git a/chrome/browser/resources/print_preview/ui/destination_list.js b/chrome/browser/resources/print_preview/ui/destination_list.js
index 59ee859..3b4d1cc 100644
--- a/chrome/browser/resources/print_preview/ui/destination_list.js
+++ b/chrome/browser/resources/print_preview/ui/destination_list.js
@@ -69,8 +69,7 @@
 
     this.updateList(
         'matchingDestinations_',
-        destination => destination.origin + '/' + destination.id + '/' +
-            destination.connectionStatusText,
+        destination => destination.key + '/' + destination.connectionStatusText,
         this.searchQuery ?
             this.destinations.filter(
                 d => d.matches(/** @type {!RegExp} */ (this.searchQuery))) :
diff --git a/chrome/browser/resources/print_preview/ui/destination_settings.html b/chrome/browser/resources/print_preview/ui/destination_settings.html
index a24b038..96c34177 100644
--- a/chrome/browser/resources/print_preview/ui/destination_settings.html
+++ b/chrome/browser/resources/print_preview/ui/destination_settings.html
@@ -61,6 +61,7 @@
     <print-preview-user-manager id="userManager" active-user="{{activeUser_}}"
         app-kiosk-mode="[[appKioskMode]]"
         cloud-print-disabled="{{cloudPrintDisabled_}}"
+        cloud-print-interface="[[cloudPrintInterface]]"
         users="{{users_}}" destination-store="[[destinationStore_]]"
         invitation-store="[[invitationStore_]]"
         should-reload-cookies="[[isDialogOpen_]]">
diff --git a/chrome/browser/resources/print_preview/ui/destination_settings.js b/chrome/browser/resources/print_preview/ui/destination_settings.js
index 0701852..c7db23c9 100644
--- a/chrome/browser/resources/print_preview/ui/destination_settings.js
+++ b/chrome/browser/resources/print_preview/ui/destination_settings.js
@@ -126,6 +126,9 @@
     users_: Array,
   },
 
+  /** @private {string} */
+  lastUser_: '',
+
   /** @private {!EventTracker} */
   tracker_: new EventTracker(),
 
@@ -167,11 +170,61 @@
   /** @private */
   onCloudPrintInterfaceSet_: function() {
     const cloudPrintInterface = assert(this.cloudPrintInterface);
-    this.$.userManager.setCloudPrintInterface(cloudPrintInterface);
     this.destinationStore_.setCloudPrintInterface(cloudPrintInterface);
     this.invitationStore_.setCloudPrintInterface(cloudPrintInterface);
   },
 
+  /** @private */
+  onActiveUserChanged_: function() {
+    // Re-filter the dropdown destinations for the new account.
+    if (!this.isDialogOpen_) {
+      // Don't update the destination settings UI while the dialog is open in
+      // front of it.
+      this.updateDropdownDestinations_();
+    }
+
+    if (!this.destination ||
+        this.destination.origin !== print_preview.DestinationOrigin.COOKIES) {
+      // Active user changing doesn't impact non-cookie based destinations.
+      return;
+    }
+
+    if (this.destination.account === this.activeUser_) {
+      // If the current destination belongs to the new account and the dialog
+      // was waiting for sign in, update the state.
+      if (this.destinationState === print_preview.DestinationState.SELECTED) {
+        this.destinationState = this.destination.capabilities ?
+            print_preview.DestinationState.UPDATED :
+            print_preview.DestinationState.SET;
+      }
+      return;
+    }
+
+    if (this.isDialogOpen_) {
+      // Do not update the selected destination if the dialog is open, as this
+      // will change the destination settings UI behind the dialog, and the user
+      // may be selecting a new destination in the dialog anyway. Wait for the
+      // user to select a destination or cancel.
+      return;
+    }
+
+    // Destination belongs to a different account. Reset the destination to the
+    // most recent destination associated with the new account, or the default.
+    const recent = this.displayedDestinations_.find(d => {
+      return d.origin !== print_preview.DestinationOrigin.COOKIES ||
+          d.account === this.activeUser_;
+    });
+    if (recent) {
+      const success = this.destinationStore_.selectRecentDestinationByKey(
+          print_preview.createRecentDestinationKey(recent),
+          this.displayedDestinations_);
+      if (success) {
+        return;
+      }
+    }
+    this.destinationStore_.selectDefaultDestination();
+  },
+
   /**
    * @param {string} defaultPrinter The system default printer ID.
    * @param {string} serializedDefaultDestinationRulesStr String with rules for
@@ -192,27 +245,18 @@
   },
 
   /** @private */
-  onActiveUserChanged_: function() {
-    if (!this.activeUser_ || !this.destination) {
-      return;
-    }
-
-    if (this.destinationState === print_preview.DestinationState.SELECTED &&
-        this.destination.origin === print_preview.DestinationOrigin.COOKIES) {
-      // Adjust states if the destination is now ready to be printed to.
-      this.destinationState = this.destination.capabilities ?
-          print_preview.DestinationState.UPDATED :
-          print_preview.DestinationState.SET;
-    }
-    this.updateDropdownDestinations_();
-  },
-
-  /** @private */
   onDestinationSelect_: function() {
+    // If the user selected a destination in the dialog after changing the
+    // active user, do the UI updates that were previously deferred.
+    if (this.isDialogOpen_ && this.lastUser_ !== this.activeUser_) {
+      this.updateDropdownDestinations_();
+    }
+
     if (this.state === print_preview.State.FATAL_ERROR) {
       // Don't let anything reset if there is a fatal error.
       return;
     }
+
     const destination = this.destinationStore_.selectedDestination;
     if (!!this.activeUser_ ||
         destination.origin !== print_preview.DestinationOrigin.COOKIES) {
@@ -392,6 +436,7 @@
         this.invitationStore_.startLoadingInvitations(this.activeUser_);
       }
       this.$.destinationDialog.get().show();
+      this.lastUser_ = this.activeUser_;
       this.isDialogOpen_ = true;
     } else {
       const success = this.destinationStore_.selectRecentDestinationByKey(
@@ -415,6 +460,9 @@
   onDialogClose_: function() {
     // Reset the select value if the user dismissed the dialog without
     // selecting a new destination.
+    if (this.lastUser_ != this.activeUser_) {
+      this.updateDropdownDestinations_();
+    }
     this.updateDestinationSelect_();
     this.$.destinationSelect.focus();
     this.isDialogOpen_ = false;
diff --git a/chrome/browser/resources/print_preview/ui/header.html b/chrome/browser/resources/print_preview/ui/header.html
index 4a88f67..d46497d 100644
--- a/chrome/browser/resources/print_preview/ui/header.html
+++ b/chrome/browser/resources/print_preview/ui/header.html
@@ -1,10 +1,9 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
-<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/html/cr.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../data/destination.html">
 <link rel="import" href="../data/state.html">
 <link rel="import" href="../icons.html">
@@ -14,7 +13,7 @@
 
 <dom-module id="print-preview-header">
   <template>
-    <style include="paper-button-style">
+    <style>
       :host {
         border-bottom: var(--print-preview-settings-border);
         display: block;
@@ -56,11 +55,11 @@
         padding-top: 16px;
       }
 
-      #button-strip paper-button:first-child {
+      #button-strip cr-button:first-child {
         margin-inline-end: 8px;
       }
 
-      #button-strip paper-button:last-child {
+      #button-strip cr-button:last-child {
         margin-inline-end: 0;
       }
 
@@ -83,18 +82,18 @@
     </span>
     <div id="button-strip">
 <if expr="not is_win">
-      <paper-button class="cancel-button" on-click="onCancelClick_">
+      <cr-button class="cancel-button" on-click="onCancelClick_">
         $i18n{cancel}
-      </paper-button>
+      </cr-button>
 </if>
-      <paper-button class="action-button" on-click="onPrintClick_"
+      <cr-button class="action-button" on-click="onPrintClick_"
           disabled$="[[!printButtonEnabled_]]">
         [[printButtonLabel_]]
-      </paper-button>
+      </cr-button>
 <if expr="is_win">
-      <paper-button class="cancel-button" on-click="onCancelClick_">
+      <cr-button class="cancel-button" on-click="onCancelClick_">
         $i18n{cancel}
-      </paper-button>
+      </cr-button>
 </if>
     </div>
   </template>
diff --git a/chrome/browser/resources/print_preview/ui/header.js b/chrome/browser/resources/print_preview/ui/header.js
index 2731225..0a4a5da3 100644
--- a/chrome/browser/resources/print_preview/ui/header.js
+++ b/chrome/browser/resources/print_preview/ui/header.js
@@ -147,7 +147,7 @@
         if (this.lastState_ != this.state &&
             (document.activeElement == null ||
              document.activeElement == document.body)) {
-          this.$$('paper-button.action-button').focus();
+          this.$$('cr-button.action-button').focus();
         }
         break;
       case (print_preview.State.FATAL_ERROR):
diff --git a/chrome/browser/resources/print_preview/ui/preview_area.html b/chrome/browser/resources/print_preview/ui/preview_area.html
index b67043fa..e09779c5 100644
--- a/chrome/browser/resources/print_preview/ui/preview_area.html
+++ b/chrome/browser/resources/print_preview/ui/preview_area.html
@@ -1,7 +1,6 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
 <link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
-<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/html/cr.html">
 <link rel="import" href="chrome://resources/html/dark_mode.html">
diff --git a/chrome/browser/resources/print_preview/ui/provisional_destination_resolver.html b/chrome/browser/resources/print_preview/ui/provisional_destination_resolver.html
index 1fad552..ad16a11 100644
--- a/chrome/browser/resources/print_preview/ui/provisional_destination_resolver.html
+++ b/chrome/browser/resources/print_preview/ui/provisional_destination_resolver.html
@@ -1,12 +1,11 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
-<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/html/cr.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../data/destination.html">
 <link rel="import" href="../data/destination_store.html">
 <link rel="import" href="print_preview_shared_css.html">
@@ -16,8 +15,7 @@
 
 <dom-module id="print-preview-provisional-destination-resolver">
   <template>
-    <style include="print-preview-shared paper-button-style cr-hidden-style
-        throbber">
+    <style include="print-preview-shared cr-hidden-style throbber">
       #dialog {
         --cr-dialog-native: {
           height: -webkit-fit-content;
@@ -82,15 +80,15 @@
         </div>
       </div>
       <div slot="button-container" id="buttons">
-        <paper-button class="cancel-button" on-click="onCancelClick_">
+        <cr-button class="cancel-button" on-click="onCancelClick_">
           $i18n{goBackButton}
-        </paper-button>
-        <paper-button class="action-button"
+        </cr-button>
+        <cr-button class="action-button"
             hidden="[[isInErrorState_(state_)]]"
             disabled="[[!isInActiveState_(state_)]]"
             on-click="startResolveDestination_">
           $i18n{selectButton}
-        </paper-button>
+        </cr-button>
       </div>
     </cr-dialog>
   </template>
diff --git a/chrome/browser/resources/settings/a11y_page/tts_subpage.html b/chrome/browser/resources/settings/a11y_page/tts_subpage.html
index 5866fcc..dcf7a58 100644
--- a/chrome/browser/resources/settings/a11y_page/tts_subpage.html
+++ b/chrome/browser/resources/settings/a11y_page/tts_subpage.html
@@ -1,12 +1,12 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_expand_button/cr_expand_button.html">
-<link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html"
+<link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/html/md_select_css.html">
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../controls/settings_slider.html">
 <link rel="import" href="../i18n_setup.html">
 <link rel="import" href="../languages_page/languages_browser_proxy.html">
@@ -31,7 +31,7 @@
         --cr-input-error-display: none;
       }
 
-      #previewInput paper-button {
+      #previewInput cr-button {
         margin-inline-start: 8px;
       }
     </style>
@@ -90,12 +90,12 @@
       <cr-input id="previewInput" label="$i18n{textToSpeechPreviewInputLabel}"
           value="{{previewText_}}"
           disabled="[[isPreviewing_]]">
-        <paper-button on-click="onPreviewTtsClick_"
+        <cr-button on-click="onPreviewTtsClick_"
             disabled$="[[!enablePreviewButton_(allVoices, isPreviewing_,
                          previewText_)]]"
             slot="suffix">
           $i18n{textToSpeechPreviewPlay}
-        </paper-button>
+        </cr-button>
       </cr-input>
     </div>
 
@@ -150,11 +150,11 @@
         <div id="extension_name_[[index]]" class="start">
           [[extension.name]]
         </div>
-        <paper-button on-click="onEngineSettingsTap_"
+        <cr-button on-click="onEngineSettingsTap_"
             aria-describedby$="extension_name_[[index]]"
             hidden$="[[!extension.optionsPage]]">
           $i18n{settings}
-        </paper-button>
+        </cr-button>
       </div>
     </template>
   </template>
diff --git a/chrome/browser/resources/settings/about_page/about_page.html b/chrome/browser/resources/settings/about_page/about_page.html
index 9c777d1..8bec0a04 100644
--- a/chrome/browser/resources/settings/about_page/about_page.html
+++ b/chrome/browser/resources/settings/about_page/about_page.html
@@ -11,6 +11,7 @@
 <link rel="import" href="../settings_page/settings_section.html">
 <link rel="import" href="../settings_page_css.html">
 <link rel="import" href="../settings_shared_css.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_icon_button/cr_icon_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_link_row/cr_link_row.html">
 <link rel="import" href="chrome://resources/cr_elements/icons.html">
@@ -18,7 +19,6 @@
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 
 <if expr="chromeos">
 <link rel="import" href="detailed_build_info.html">
@@ -72,7 +72,7 @@
         overflow-x: auto;
       }
 
-      paper-button {
+      cr-button {
         white-space: nowrap;
       }
 
@@ -157,21 +157,20 @@
             </div>
             <div class="separator" hidden="[[!showButtonContainer_]]"></div>
             <span id="buttonContainer" hidden="[[!showButtonContainer_]]">
-              <paper-button id="relaunch" class="secondary-button"
-                  hidden="[[!showRelaunch_]]" on-click="onRelaunchTap_">
+              <cr-button id="relaunch" hidden="[[!showRelaunch_]]"
+                  on-click="onRelaunchTap_">
                 $i18n{aboutRelaunch}
-              </paper-button>
+              </cr-button>
 <if expr="chromeos">
-              <paper-button id="relaunchAndPowerwash" class="secondary-button"
+              <cr-button id="relaunchAndPowerwash"
                   hidden="[[!showRelaunchAndPowerwash_]]"
                   on-click="onRelaunchAndPowerwashTap_">
                 $i18n{aboutRelaunchAndPowerwash}
-              </paper-button>
-              <paper-button id="checkForUpdates" class="secondary-button"
-                  hidden="[[!showCheckUpdates_]]"
+              </cr-button>
+              <cr-button id="checkForUpdates" hidden="[[!showCheckUpdates_]]"
                   on-click="onCheckUpdatesTap_">
                 $i18n{aboutCheckForUpdates}
-              </paper-button>
+              </cr-button>
 </if>
             </span>
           </div>
diff --git a/chrome/browser/resources/settings/about_page/channel_switcher_dialog.html b/chrome/browser/resources/settings/about_page/channel_switcher_dialog.html
index 8dcad3fd..dbcddde0 100644
--- a/chrome/browser/resources/settings/about_page/channel_switcher_dialog.html
+++ b/chrome/browser/resources/settings/about_page/channel_switcher_dialog.html
@@ -1,10 +1,10 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_radio_button/cr_radio_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_radio_group/cr_radio_group.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-selector/iron-selector.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="about_page_browser_proxy.html">
 <link rel="import" href="../settings_shared_css.html">
 
@@ -52,18 +52,18 @@
         </iron-selector>
       </div>
       <div slot="button-container">
-        <paper-button class="cancel-button" on-click="onCancelTap_"
-            id="cancel">$i18n{cancel}</paper-button>
-        <paper-button id="changeChannel" class="action-button"
+        <cr-button class="cancel-button" on-click="onCancelTap_"
+            id="cancel">$i18n{cancel}</cr-button>
+        <cr-button id="changeChannel" class="action-button"
             on-click="onChangeChannelTap_"
             hidden="[[!shouldShowButtons_.changeChannel]]">
           $i18n{aboutChangeChannel}
-        </paper-button>
-        <paper-button id="changeChannelAndPowerwash" class="action-button"
+        </cr-button>
+        <cr-button id="changeChannelAndPowerwash" class="action-button"
             on-click="onChangeChannelAndPowerwashTap_"
             hidden="[[!shouldShowButtons_.changeChannelAndPowerwash]]">
           $i18n{aboutChangeChannelAndPowerwash}
-        </paper-button>
+        </cr-button>
       </div>
     </cr-dialog>
   </template>
diff --git a/chrome/browser/resources/settings/about_page/detailed_build_info.html b/chrome/browser/resources/settings/about_page/detailed_build_info.html
index dd300b5..2369486 100644
--- a/chrome/browser/resources/settings/about_page/detailed_build_info.html
+++ b/chrome/browser/resources/settings/about_page/detailed_build_info.html
@@ -6,9 +6,9 @@
 <link rel="import" href="channel_switcher_dialog.html">
 <link rel="import" href="../i18n_setup.html">
 <link rel="import" href="../settings_shared_css.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_indicator.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 
 <dom-module id="settings-detailed-build-info">
   <template>
@@ -39,10 +39,10 @@
         <div class="secondary">[[currentlyOnChannelText_]]</div>
       </div>
       <div class="separator"></div>
-      <paper-button on-click="onChangeChannelTap_"
+      <cr-button on-click="onChangeChannelTap_"
           disabled="[[!canChangeChannel_]]">
         $i18n{aboutChangeChannel}
-      </paper-button>
+      </cr-button>
       <template is="dom-if" if="[[!canChangeChannel_]]">
         <cr-policy-indicator
             indicator-source-name="[[getChangeChannelIndicatorSourceName_(
diff --git a/chrome/browser/resources/settings/about_page/detailed_build_info.js b/chrome/browser/resources/settings/about_page/detailed_build_info.js
index e63021e..18ad3b2 100644
--- a/chrome/browser/resources/settings/about_page/detailed_build_info.js
+++ b/chrome/browser/resources/settings/about_page/detailed_build_info.js
@@ -96,7 +96,7 @@
   /** @private */
   onChannelSwitcherDialogClosed_: function() {
     this.showChannelSwitcherDialog_ = false;
-    cr.ui.focusWithoutInk(assert(this.$$('paper-button')));
+    cr.ui.focusWithoutInk(assert(this.$$('cr-button')));
     this.updateChannelInfo_();
   },
 });
diff --git a/chrome/browser/resources/settings/about_page/update_warning_dialog.html b/chrome/browser/resources/settings/about_page/update_warning_dialog.html
index 73621cfe..26b6871 100644
--- a/chrome/browser/resources/settings/about_page/update_warning_dialog.html
+++ b/chrome/browser/resources/settings/about_page/update_warning_dialog.html
@@ -1,8 +1,8 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="about_page_browser_proxy.html">
 <link rel="import" href="../settings_shared_css.html">
 
@@ -15,12 +15,12 @@
         <div id="update-warning-message"></div>
       </div>
       <div slot="button-container">
-        <paper-button id="cancel" class="cancel-button"
-            on-click="onCancelTap_">$i18n{cancel}</paper-button>
-        <paper-button id="continue" class="action-button"
+        <cr-button id="cancel" class="cancel-button"
+            on-click="onCancelTap_">$i18n{cancel}</cr-button>
+        <cr-button id="continue" class="action-button"
             on-click="onContinueTap_">
           $i18n{aboutUpdateWarningContinue}
-        </paper-button>
+        </cr-button>
       </div>
     </cr-dialog>
   </template>
diff --git a/chrome/browser/resources/settings/android_apps_page/android_apps_page.html b/chrome/browser/resources/settings/android_apps_page/android_apps_page.html
index bccb0f2..8447265 100644
--- a/chrome/browser/resources/settings/android_apps_page/android_apps_page.html
+++ b/chrome/browser/resources/settings/android_apps_page/android_apps_page.html
@@ -1,10 +1,10 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_icon_button/cr_icon_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_link_row/cr_link_row.html">
 <link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_pref_indicator.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../i18n_setup.html">
 <link rel="import" href="../prefs/prefs_behavior.html">
 <link rel="import" href="../settings_page/settings_animated_pages.html">
@@ -40,13 +40,13 @@
             </template>
             <template is="dom-if" if="[[!androidAppsInfo.playStoreEnabled]]">
               <div class="separator"></div>
-              <paper-button id="enable" class="secondary-button"
+              <cr-button id="enable"
                   disabled="[[isEnforced_(prefs.arc.enabled)]]"
                   on-click="onEnableTap_"
                   aria-label="$i18n{androidAppsPageTitle}"
                   aria-describedby="secondaryText">
                 $i18n{androidAppsEnable}
-              </paper-button>
+              </cr-button>
             </template>
           </div>
         </template>
diff --git a/chrome/browser/resources/settings/android_apps_page/android_apps_subpage.html b/chrome/browser/resources/settings/android_apps_page/android_apps_subpage.html
index f27ac89..b0d86e2 100644
--- a/chrome/browser/resources/settings/android_apps_page/android_apps_subpage.html
+++ b/chrome/browser/resources/settings/android_apps_page/android_apps_subpage.html
@@ -1,11 +1,11 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_link_row/cr_link_row.html">
 <link rel="import" href="chrome://resources/html/assert.html">
 <link rel="import" href="chrome://resources/html/cr/ui/focus_without_ink.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="android_apps_browser_proxy.html">
 <link rel="import" href="../i18n_setup.html">
 <link rel="import" href="../prefs/prefs_behavior.html">
@@ -34,14 +34,14 @@
       <div slot="title">$i18n{androidAppsDisableDialogTitle}</div>
       <div slot="body" inner-h-t-m-l="[[dialogBody_]]"></div>
       <div slot="button-container">
-        <paper-button class="cancel-button"
+        <cr-button class="cancel-button"
             on-click="onConfirmDisableDialogCancel_">
           $i18n{cancel}
-        </paper-button>
-        <paper-button class="action-button"
+        </cr-button>
+        <cr-button class="action-button"
             on-click="onConfirmDisableDialogConfirm_">
           $i18n{androidAppsDisableDialogRemove}
-        </paper-button>
+        </cr-button>
       </div>
     </cr-dialog>
 
diff --git a/chrome/browser/resources/settings/appearance_page/appearance_page.html b/chrome/browser/resources/settings/appearance_page/appearance_page.html
index e9797c97..f06a9f69 100644
--- a/chrome/browser/resources/settings/appearance_page/appearance_page.html
+++ b/chrome/browser/resources/settings/appearance_page/appearance_page.html
@@ -1,9 +1,9 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_link_row/cr_link_row.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/html/md_select_css.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="appearance_browser_proxy.html">
 <link rel="import" href="../controls/controlled_radio_button.html">
 <link rel="import" href="../controls/extension_controlled_indicator.html">
@@ -31,10 +31,10 @@
         align-items: start;
       }
 
-      /* The theme mixes a link and a paper-button divided by a separator with
+      /* The theme mixes a link and a cr-button divided by a separator with
        * grit expressions and dom-if templates. That leads to a tricky thing
        * to style correctly, these are a workaround. */
-      #themeRow paper-button {
+      #themeRow cr-button {
         margin-inline-end: 20px;
       }
 
@@ -67,10 +67,9 @@
 <if expr="not is_linux or chromeos">
           <template is="dom-if" if="[[prefs.extensions.theme.id.value]]">
             <div class="separator"></div>
-            <paper-button id="useDefault" on-click="onUseDefaultTap_"
-                class="secondary-button">
+            <cr-button id="useDefault" on-click="onUseDefaultTap_">
               $i18n{resetToDefaultTheme}
-            </paper-button>
+            </cr-button>
           </template>
 </if>
 <if expr="is_linux and not chromeos">
@@ -81,17 +80,15 @@
             <div class="separator"></div>
             <template is="dom-if" if="[[showUseClassic_(
                 prefs.extensions.theme.id.value, useSystemTheme_)]]" restamp>
-              <paper-button id="useDefault" on-click="onUseDefaultTap_"
-                  class="secondary-button">
+              <cr-button id="useDefault" on-click="onUseDefaultTap_">
                 $i18n{useClassicTheme}
-              </paper-button>
+              </cr-button>
             </template>
             <template is="dom-if" if="[[showUseSystem_(
                 prefs.extensions.theme.id.value, useSystemTheme_)]]" restamp>
-              <paper-button id="useSystem" on-click="onUseSystemTap_"
-                  class="secondary-button">
+              <cr-button id="useSystem" on-click="onUseSystemTap_">
                 $i18n{useSystemTheme}
-              </paper-button>
+              </cr-button>
             </template>
           </div>
 </if>
diff --git a/chrome/browser/resources/settings/autofill_page/address_edit_dialog.html b/chrome/browser/resources/settings/autofill_page/address_edit_dialog.html
index fb0eafae..71a72d6 100644
--- a/chrome/browser/resources/settings/autofill_page/address_edit_dialog.html
+++ b/chrome/browser/resources/settings/autofill_page/address_edit_dialog.html
@@ -1,5 +1,6 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
@@ -120,14 +121,14 @@
         </div>
       </div>
       <div slot="button-container">
-        <paper-button id="cancelButton" class="cancel-button"
+        <cr-button id="cancelButton" class="cancel-button"
             on-click="onCancelTap_">
           $i18n{cancel}
-        </paper-button>
-        <paper-button id="saveButton" class="action-button"
+        </cr-button>
+        <cr-button id="saveButton" class="action-button"
             disabled="[[!canSave_]]" on-click="onSaveButtonTap_">
           $i18n{save}
-        </paper-button>
+        </cr-button>
       </div>
     </cr-dialog>
   </template>
diff --git a/chrome/browser/resources/settings/autofill_page/autofill_section.html b/chrome/browser/resources/settings/autofill_page/autofill_section.html
index 8853eaa..d781462 100644
--- a/chrome/browser/resources/settings/autofill_page/autofill_section.html
+++ b/chrome/browser/resources/settings/autofill_page/autofill_section.html
@@ -1,6 +1,7 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
 <link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_icon_button/cr_icon_button.html">
 <link rel="import" href="chrome://resources/html/assert.html">
 <link rel="import" href="chrome://resources/html/cr/ui/focus_without_ink.html">
@@ -46,12 +47,11 @@
     </template>
     <div class="settings-box continuation">
       <h2 class="start">$i18n{addresses}</h2>
-      <paper-button id="addAddress"
-          class="secondary-button header-aligned-button"
+      <cr-button id="addAddress" class="header-aligned-button"
           on-click="onAddAddressTap_"
           hidden$="[[!prefs.autofill.profile_enabled.value]]">
         $i18n{add}
-      </paper-button>
+      </cr-button>
     </div>
     <div class="list-frame">
       <div id="addressList" class="vertical-list">
diff --git a/chrome/browser/resources/settings/autofill_page/credit_card_edit_dialog.html b/chrome/browser/resources/settings/autofill_page/credit_card_edit_dialog.html
index 304471f..54ea0d6 100644
--- a/chrome/browser/resources/settings/autofill_page/credit_card_edit_dialog.html
+++ b/chrome/browser/resources/settings/autofill_page/credit_card_edit_dialog.html
@@ -1,11 +1,11 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/html/md_select_css.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../settings_shared_css.html">
 <link rel="import" href="../settings_vars_css.html">
 
@@ -95,10 +95,10 @@
         </div>
       </div>
       <div slot="button-container">
-        <paper-button id="cancelButton" class="cancel-button"
-            on-click="onCancelButtonTap_">$i18n{cancel}</paper-button>
-        <paper-button id="saveButton" class="action-button"
-            on-click="onSaveButtonTap_" disabled>$i18n{save}</paper-button>
+        <cr-button id="cancelButton" class="cancel-button"
+            on-click="onCancelButtonTap_">$i18n{cancel}</cr-button>
+        <cr-button id="saveButton" class="action-button"
+            on-click="onSaveButtonTap_" disabled>$i18n{save}</cr-button>
       </div>
     </cr-dialog>
   </template>
diff --git a/chrome/browser/resources/settings/autofill_page/password_edit_dialog.html b/chrome/browser/resources/settings/autofill_page/password_edit_dialog.html
index b10ede5..6e8a3ab 100644
--- a/chrome/browser/resources/settings/autofill_page/password_edit_dialog.html
+++ b/chrome/browser/resources/settings/autofill_page/password_edit_dialog.html
@@ -1,11 +1,11 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_icon_button/cr_icon_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_icons_css.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../icons.html">
 <link rel="import" href="../settings_shared_css.html">
 <link rel="import" href="../settings_vars_css.html">
@@ -77,9 +77,9 @@
         </cr-input>
       </div>
       <div slot="button-container">
-        <paper-button class="action-button" on-click="onActionButtonTap_">
+        <cr-button class="action-button" on-click="onActionButtonTap_">
           $i18n{done}
-        </paper-button>
+        </cr-button>
       </div>
     </cr-dialog>
   </template>
diff --git a/chrome/browser/resources/settings/autofill_page/passwords_export_dialog.html b/chrome/browser/resources/settings/autofill_page/passwords_export_dialog.html
index ab305896..79c23ab 100644
--- a/chrome/browser/resources/settings/autofill_page/passwords_export_dialog.html
+++ b/chrome/browser/resources/settings/autofill_page/passwords_export_dialog.html
@@ -1,9 +1,9 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-progress/paper-progress.html">
 <link rel="import" href="../settings_shared_css.html">
 <if expr="chromeos">
@@ -38,14 +38,14 @@
           </div>
         </div>
         <div slot="button-container">
-          <paper-button class="secondary-button header-aligned-button"
+          <cr-button class="secondary-button header-aligned-button"
               on-click="onCancelButtonTap_" id="cancelButton">
             $i18n{cancel}
-          </paper-button>
-          <paper-button class="action-button header-aligned-button"
+          </cr-button>
+          <cr-button class="action-button header-aligned-button"
               on-click="onExportTap_" id="exportPasswordsButton">
             $i18n{exportPasswords}
-          </paper-button>
+          </cr-button>
         </div>
       </cr-dialog>
     </template>
@@ -57,11 +57,10 @@
           <paper-progress indeterminate class="blue"></paper-progress>
         </div>
         <div slot="button-container">
-          <paper-button id="cancel_progress_button"
-              class="secondary-button header-aligned-button"
+          <cr-button id="cancel_progress_button" class="header-aligned-button"
               on-click="onCancelProgressButtonTap_">
             $i18n{cancel}
-          </paper-button>
+          </cr-button>
         </div>
       </cr-dialog>
     </template>
@@ -77,14 +76,14 @@
           </ul>
         </div>
         <div slot="button-container">
-          <paper-button class="secondary-button header-aligned-button"
-              on-click="onCancelButtonTap_" id="cancelErrorButton">
+          <cr-button class="header-aligned-button" on-click="onCancelButtonTap_"
+              id="cancelErrorButton">
             $i18n{cancel}
-          </paper-button>
-          <paper-button class="action-button header-aligned-button"
+          </cr-button>
+          <cr-button class="action-button header-aligned-button"
               on-click="onExportTap_" id="tryAgainButton">
             $i18n{exportPasswordsTryAgain}
-          </paper-button>
+          </cr-button>
         </div>
       </cr-dialog>
     </template>
diff --git a/chrome/browser/resources/settings/autofill_page/passwords_section.html b/chrome/browser/resources/settings/autofill_page/passwords_section.html
index 2f65256..1e7b792 100644
--- a/chrome/browser/resources/settings/autofill_page/passwords_section.html
+++ b/chrome/browser/resources/settings/autofill_page/passwords_section.html
@@ -1,6 +1,7 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
 <link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_icon_button/cr_icon_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_toast/cr_toast.html">
 <link rel="import" href="chrome://resources/cr_elements/icons.html">
@@ -164,9 +165,9 @@
 </if>
     <cr-toast id="undoToast" duration="[[toastDuration_]]">
       <div id="undoLabel">$i18n{passwordDeleted}</div>
-      <paper-button on-click="onUndoButtonTap_">
+      <cr-button on-click="onUndoButtonTap_">
         $i18n{undoRemovePassword}
-      </paper-button>
+      </cr-button>
     </cr-toast>
     <div class="settings-box block first">
       <h2>$i18n{passwordExceptionsHeading}</h2>
diff --git a/chrome/browser/resources/settings/autofill_page/payments_section.html b/chrome/browser/resources/settings/autofill_page/payments_section.html
index 8fcf019..5836b23 100644
--- a/chrome/browser/resources/settings/autofill_page/payments_section.html
+++ b/chrome/browser/resources/settings/autofill_page/payments_section.html
@@ -1,6 +1,7 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
 <link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_link_row/cr_link_row.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/html/assert.html">
@@ -61,12 +62,11 @@
 
     <div class="settings-box continuation">
       <h2 class="start">$i18n{creditCards}</h2>
-      <paper-button id="addCreditCard"
-          class="secondary-button header-aligned-button"
+      <cr-button id="addCreditCard" class="header-aligned-button"
           on-click="onAddCreditCardTap_"
           hidden$="[[!prefs.autofill.credit_card_enabled.value]]">
         $i18n{add}
-      </paper-button>
+      </cr-button>
     </div>
     <cr-link-row id="migrateCreditCards"
         hidden$="[[!checkIfMigratable_(creditCards,
diff --git a/chrome/browser/resources/settings/basic_page/basic_page.html b/chrome/browser/resources/settings/basic_page/basic_page.html
index 2c42c0e..2f3d131 100644
--- a/chrome/browser/resources/settings/basic_page/basic_page.html
+++ b/chrome/browser/resources/settings/basic_page/basic_page.html
@@ -1,5 +1,6 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
@@ -46,13 +47,22 @@
 
       #advancedToggle {
         @apply --cr-actionable;
+        --ink-color: currentColor;
         align-items: center;
+        background: transparent;
+        border: none;
+        box-shadow: none;
+        color: currentColor;
         display: flex;
+        font-weight: 400;
         margin-bottom: 3px;
         margin-top: 12px;  /* Part of a 48px spacer (33px + 12px + 3px). */
         min-height: 32px;
         padding: 0 12px;
-        text-transform: none;
+      }
+
+      :host-context(.focus-outline-visible) #advancedToggle:focus {
+        font-weight: 500;
       }
 
       #secondaryUserBanner {
@@ -254,12 +264,12 @@
           inSearchMode, hasExpandedSection_)]]">
         <div id="toggleSpacer"></div>
         <h2 id="toggleContainer">
-          <paper-button id="advancedToggle" on-click="advancedToggleClicked_"
+          <cr-button id="advancedToggle" on-click="advancedToggleClicked_"
               aria-expanded$="[[boolToString_(advancedToggleExpanded)]]">
             <span>$i18n{advancedPageTitle}</span>
             <iron-icon icon="[[getArrowIcon_(advancedToggleExpanded)]]">
             </iron-icon>
-          </paper-button>
+          </cr-button>
         </h2>
       </template>
 
diff --git a/chrome/browser/resources/settings/change_password_page/change_password_page.html b/chrome/browser/resources/settings/change_password_page/change_password_page.html
index 50554b2..a1e2b67 100644
--- a/chrome/browser/resources/settings/change_password_page/change_password_page.html
+++ b/chrome/browser/resources/settings/change_password_page/change_password_page.html
@@ -2,10 +2,10 @@
 
 <link rel="import" href="../settings_shared_css.html">
 <link rel="import" href="change_password_browser_proxy.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/icons.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 
 <dom-module id="settings-change-password-page">
   <template>
@@ -40,10 +40,10 @@
         </div>
       </div>
       <div class="separator"></div>
-      <paper-button class="action-button" id="changePassword"
+      <cr-button class="action-button" id="changePassword"
           on-click="changePassword_">
         $i18n{changePasswordPageButton}
-      </paper-button>
+      </cr-button>
     </div>
   </template>
   <script src="change_password_page.js"></script>
diff --git a/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.html b/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.html
index ceae8b2..8f991df 100644
--- a/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.html
+++ b/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.html
@@ -1,10 +1,10 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_expand_button/cr_expand_button.html">
 <link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_pref_indicator.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-collapse/iron-collapse.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-spinner/paper-spinner-lite.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
@@ -60,10 +60,10 @@
         <cr-policy-pref-indicator pref="[[prefs.software_reporter.enabled]]">
         </cr-policy-pref-indicator>
         <div class="separator"></div>
-        <paper-button id="action-button" class="action-button"
+        <cr-button id="action-button" class="action-button"
             disabled$="[[!cleanupEnabled_]]" on-click="proceed_">
           [[actionButtonLabel_]]
-        </paper-button>
+        </cr-button>
       </template>
     </div>
     <div class="settings-box continuation">
diff --git a/chrome/browser/resources/settings/chromeos/os_downloads_page/smb_shares_page.html b/chrome/browser/resources/settings/chromeos/os_downloads_page/smb_shares_page.html
index 615ccc8..0370a60 100644
--- a/chrome/browser/resources/settings/chromeos/os_downloads_page/smb_shares_page.html
+++ b/chrome/browser/resources/settings/chromeos/os_downloads_page/smb_shares_page.html
@@ -1,11 +1,11 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
 <link rel="import" href="chrome://resources/cr_components/chromeos/smb_shares/add_smb_share_dialog.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_pref_indicator.html">
 <link rel="import" href="chrome://resources/html/action_link.html">
 <link rel="import" href="chrome://resources/html/action_link_css.html">
 <link rel="import" href="chrome://resources/html/assert.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../../route.html">
 <link rel="import" href="../../settings_shared_css.html">
 <link rel="import" href="../../settings_vars_css.html">
@@ -27,11 +27,11 @@
             icon-aria-label="$i18n{smbSharesTitle}">
         </cr-policy-pref-indicator>
       </template>
-      <paper-button class="action-button" id="addShare"
+      <cr-button class="action-button" id="addShare"
           on-click="onAddShareTap_"
           disabled="[[!prefs.network_file_shares.allowed.value]]">
         $i18n{addSmbShare}
-      </paper-button>
+      </cr-button>
     </div>
     <template is="dom-if" if="[[showAddSmbDialog_]]" restamp>
       <add-smb-share-dialog on-close="onAddSmbDialogClosed_"
diff --git a/chrome/browser/resources/settings/chromeos/os_reset_page/os_powerwash_dialog.html b/chrome/browser/resources/settings/chromeos/os_reset_page/os_powerwash_dialog.html
index def6b50f..c021575 100644
--- a/chrome/browser/resources/settings/chromeos/os_reset_page/os_powerwash_dialog.html
+++ b/chrome/browser/resources/settings/chromeos/os_reset_page/os_powerwash_dialog.html
@@ -1,7 +1,7 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="reset_os_proxy.html">
 <link rel="import" href="../../lifetime_browser_proxy.html">
 <link rel="import" href="../../settings_shared_css.html">
@@ -21,10 +21,10 @@
         </span>
       </div>
       <div slot="button-container">
-        <paper-button class="cancel-button" on-click="onCancelTap_"
-            id="cancel">$i18n{cancel}</paper-button>
-        <paper-button class="action-button" id="powerwash"
-            on-click="onRestartTap_">$i18n{powerwashDialogButton}</paper-button>
+        <cr-button class="cancel-button" on-click="onCancelTap_"
+            id="cancel">$i18n{cancel}</cr-button>
+        <cr-button class="action-button" id="powerwash"
+            on-click="onRestartTap_">$i18n{powerwashDialogButton}</cr-button>
       </div>
     </cr-dialog>
   </template>
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_main/os_settings_main.html b/chrome/browser/resources/settings/chromeos/os_settings_main/os_settings_main.html
index b25d393..6ccb073 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings_main/os_settings_main.html
+++ b/chrome/browser/resources/settings/chromeos/os_settings_main/os_settings_main.html
@@ -7,7 +7,6 @@
 <link rel="import" href="chrome://resources/html/promise_resolver.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-a11y-announcer/iron-a11y-announcer.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../os_settings_page/os_settings_page.html">
 <link rel="import" href="../../i18n_setup.html">
 <link rel="import" href="../../prefs/prefs.html">
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.html b/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.html
index 60d8471..1a341a9 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.html
+++ b/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.html
@@ -1,11 +1,11 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/icons.html">
 <link rel="import" href="chrome://resources/html/assert.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-collapse/iron-collapse.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-selector/iron-selector.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../../icons.html">
 <link rel="import" href="../../route.html">
 <link rel="import" href="../../settings_shared_css.html">
@@ -53,8 +53,11 @@
       }
 
       #advancedButton {
+        --ink-color: var(--settings-nav-item-color);
+        background: none;
         border: none;
         border-radius: initial;
+        box-shadow: none;
         height: unset;
         margin-top: 8px;
         padding-inline-end: 0;
@@ -62,11 +65,10 @@
       }
 
       #advancedButton:focus {
-        box-shadow: none;
         outline: none;
       }
 
-      #advancedButton.keyboard-focus:focus {
+      :host-context(.focus-outline-visible) #advancedButton:focus {
         outline: auto 5px -webkit-focus-ring-color;
       }
 
@@ -146,12 +148,12 @@
         <iron-icon icon="settings:plugin-vm"></iron-icon>
         $i18n{pluginVmPageTitle}
       </a>
-      <paper-button toggles id="advancedButton"
-          aria-active-attribute="aria-expanded" active="{{advancedOpened}}"
+      <cr-button id="advancedButton" aria-active-attribute="aria-expanded"
+          on-click="onAdvancedButtonToggle_"
           hidden="[[!pageVisibility.advancedSettings]]">
         <span>$i18n{advancedPageTitle}</span>
         <iron-icon icon="[[arrowState_(advancedOpened)]]">
-        </iron-icon></paper-button>
+        </iron-icon></cr-button>
       <iron-collapse id="advancedSubmenu" opened="[[advancedOpened]]"
           hidden="[[!pageVisibility.advancedSettings]]">
         <iron-selector id="subMenu" selectable="a" attr-for-selected="href"
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.js b/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.js
index bb79403..3bb51f7e 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.js
+++ b/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.js
@@ -14,6 +14,7 @@
   properties: {
     advancedOpened: {
       type: Boolean,
+      value: false,
       notify: true,
     },
 
@@ -40,6 +41,11 @@
     this.setSelectedUrl_('');  // Nothing is selected.
   },
 
+  /** @private */
+  onAdvancedButtonToggle_: function() {
+    this.advancedOpened = !this.advancedOpened;
+  },
+
   /**
    * Prevent clicks on sidebar items from navigating. These are only links for
    * accessibility purposes, taps are handled separately by <iron-selector>.
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.html b/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.html
index b45a7962..5a7ac911 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.html
+++ b/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.html
@@ -1,5 +1,6 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
@@ -34,14 +35,22 @@
       }
 
       #advancedToggle {
-        @apply --cr-actionable;
+        --ink-color: currentColor;
         align-items: center;
+        background: transparent;
+        border: none;
+        box-shadow: none;
+        color: currentColor;
         display: flex;
+        font-weight: 400;
         margin-bottom: 3px;
         margin-top: 12px;  /* Part of a 48px spacer (33px + 12px + 3px). */
         min-height: 32px;
         padding: 0 12px;
-        text-transform: none;
+      }
+
+      :host-context(.focus-outline-visible) #advancedToggle:focus {
+        font-weight: 500;
       }
 
       #secondaryUserBanner {
@@ -207,12 +216,12 @@
           inSearchMode, hasExpandedSection_)]]">
         <div id="toggleSpacer"></div>
         <h2 id="toggleContainer">
-          <paper-button id="advancedToggle" on-click="advancedToggleClicked_"
+          <cr-button id="advancedToggle" on-click="advancedToggleClicked_"
               aria-expanded$="[[boolToString_(advancedToggleExpanded)]]">
             <span>$i18n{advancedPageTitle}</span>
             <iron-icon icon="[[getArrowIcon_(advancedToggleExpanded)]]">
             </iron-icon>
-          </paper-button>
+          </cr-button>
         </h2>
       </template>
 
diff --git a/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.html b/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.html
index a1acb22..483b025 100644
--- a/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.html
+++ b/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.html
@@ -1,11 +1,11 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_tabs/cr_tabs.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-pages/iron-pages.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-spinner/paper-spinner-lite.html">
 <link rel="import" href="../i18n_setup.html">
 <link rel="import" href="clear_browsing_data_browser_proxy.html">
@@ -244,14 +244,14 @@
       <div slot="button-container">
         <paper-spinner-lite active="[[clearingInProgress_]]">
         </paper-spinner-lite>
-        <paper-button class="cancel-button" disabled="[[clearingInProgress_]]"
-            on-click="onCancelTap_">$i18n{cancel}</paper-button>
-        <paper-button id="clearBrowsingDataConfirm"
+        <cr-button class="cancel-button" disabled="[[clearingInProgress_]]"
+            on-click="onCancelTap_">$i18n{cancel}</cr-button>
+        <cr-button id="clearBrowsingDataConfirm"
             class="action-button" on-click="clearBrowsingData_"
             disabled="[[isClearButtonDisabled_(clearingInProgress_,
                                                clearButtonDisabled_)]]">
             $i18n{clearData}
-        </paper-button>
+        </cr-button>
       </div>
       <div slot="footer"
           hidden="[[!shouldShowFooter_(syncStatus.signedIn, diceEnabled_)]]">
diff --git a/chrome/browser/resources/settings/clear_browsing_data_dialog/history_deletion_dialog.html b/chrome/browser/resources/settings/clear_browsing_data_dialog/history_deletion_dialog.html
index 5ca1761..7dad800 100644
--- a/chrome/browser/resources/settings/clear_browsing_data_dialog/history_deletion_dialog.html
+++ b/chrome/browser/resources/settings/clear_browsing_data_dialog/history_deletion_dialog.html
@@ -1,5 +1,6 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="../settings_shared_css.html">
 
@@ -11,9 +12,9 @@
       <div slot="title">$i18n{historyDeletionDialogTitle}</div>
       <div slot="body">$i18nRaw{historyDeletionDialogBody}</div>
       <div slot="button-container">
-        <paper-button class="action-button" on-click="onOkTap_">
+        <cr-button class="action-button" on-click="onOkTap_">
           $i18n{historyDeletionDialogOK}
-        </paper-button>
+        </cr-button>
       </div>
     </cr-dialog>
   </template>
diff --git a/chrome/browser/resources/settings/controls/controlled_button.html b/chrome/browser/resources/settings/controls/controlled_button.html
index 062e4c2..af32809 100644
--- a/chrome/browser/resources/settings/controls/controlled_button.html
+++ b/chrome/browser/resources/settings/controls/controlled_button.html
@@ -1,7 +1,7 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
 <link rel="import" href="chrome://resources/html/assert.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_pref_behavior.html">
 <link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_pref_indicator.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
@@ -42,10 +42,10 @@
       }
     </style>
 
-    <paper-button class$="[[getClass_(actionButton)]]"
+    <cr-button class$="[[getClass_(actionButton)]]"
       disabled="[[!buttonEnabled_(enforced_, disabled)]]">
       [[label]]
-    </paper-button>
+    </cr-button>
 
     <template is="dom-if" if="[[hasPrefPolicyIndicator(pref.*)]]" restamp>
       <cr-policy-pref-indicator pref="[[pref]]" on-click="onIndicatorTap_"
diff --git a/chrome/browser/resources/settings/controls/controlled_button.js b/chrome/browser/resources/settings/controls/controlled_button.js
index eef06452..43f07fd3 100644
--- a/chrome/browser/resources/settings/controls/controlled_button.js
+++ b/chrome/browser/resources/settings/controls/controlled_button.js
@@ -50,11 +50,11 @@
 
   /**
    * @param {!boolean} actionButton
-   * @return {string} Class of the paper-button.
+   * @return {string} Class of the cr-button.
    * @private
    */
   getClass_: function(actionButton) {
-    return actionButton ? "action-button" : "";
+    return actionButton ? 'action-button' : '';
   },
 
   /**
diff --git a/chrome/browser/resources/settings/controls/extension_controlled_indicator.html b/chrome/browser/resources/settings/controls/extension_controlled_indicator.html
index 15be87a..e09561aa 100644
--- a/chrome/browser/resources/settings/controls/extension_controlled_indicator.html
+++ b/chrome/browser/resources/settings/controls/extension_controlled_indicator.html
@@ -1,7 +1,7 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../extension_control_browser_proxy.html">
 <link rel="import" href="../i18n_setup.html">
 <link rel="import" href="../settings_shared_css.html">
@@ -32,9 +32,7 @@
     <img role="presentation" src="chrome://extension-icon/[[extensionId]]/40/1">
     <span inner-h-t-m-l="[[getLabel_(extensionId, extensionName)]]"></span>
     <template is="dom-if" if="[[extensionCanBeDisabled]]" restamp>
-      <paper-button class="secondary-button" on-click="onDisableTap_">
-        $i18n{disable}
-      </paper-button>
+      <cr-button on-click="onDisableTap_">$i18n{disable}</cr-button>
     </template>
   </template>
 </dom-module>
diff --git a/chrome/browser/resources/settings/controls/password_prompt_dialog.html b/chrome/browser/resources/settings/controls/password_prompt_dialog.html
index b8afbd0..d58fddd 100644
--- a/chrome/browser/resources/settings/controls/password_prompt_dialog.html
+++ b/chrome/browser/resources/settings/controls/password_prompt_dialog.html
@@ -1,8 +1,8 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../settings_shared_css.html">
 
 <dom-module id="settings-password-prompt-dialog">
@@ -32,15 +32,15 @@
         </cr-input>
       </div>
       <div slot="button-container">
-        <paper-button class="cancel-button" on-click="onCancelTap_">
+        <cr-button class="cancel-button" on-click="onCancelTap_">
           $i18n{cancel}
-        </paper-button>
+        </cr-button>
 
-        <paper-button id="confirmButton" class="action-button"
+        <cr-button id="confirmButton" class="action-button"
             disabled$="[[!isConfirmEnabled_(inputValue_, passwordInvalid_)]]"
             on-click="submitPassword_">
           $i18n{confirm}
-        </paper-button>
+        </cr-button>
       </div>
     </cr-dialog>
   </template>
diff --git a/chrome/browser/resources/settings/crostini_page/crostini_export_import.html b/chrome/browser/resources/settings/crostini_page/crostini_export_import.html
index 930c0d8d..608984f 100644
--- a/chrome/browser/resources/settings/crostini_page/crostini_export_import.html
+++ b/chrome/browser/resources/settings/crostini_page/crostini_export_import.html
@@ -1,7 +1,7 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="crostini_browser_proxy.html">
 <link rel="import" href="../i18n_setup.html">
 <link rel="import" href="../settings_shared_css.html">
@@ -14,19 +14,19 @@
         <div id="exportCrostiniLabel" class="start secondary">
           $i18n{crostiniExportLabel}
         </div>
-        <paper-button on-click="onExportClick_"
+        <cr-button on-click="onExportClick_"
           aria-labelledby="exportCrostiniLabel">
            $i18n{crostiniExport}
-        </paper-button>
+        </cr-button>
       </div>
       <div id="import" class="list-item">
         <div id="importCrostiniLabel" class="start secondary">
           $i18n{crostiniImportLabel}
         </div>
-        <paper-button on-click="onImportClick_"
+        <cr-button on-click="onImportClick_"
           aria-labelledby="importCrostiniLabel">
            $i18n{crostiniImport}
-        </paper-button>
+        </cr-button>
       </div>
     </div>
   </template>
diff --git a/chrome/browser/resources/settings/crostini_page/crostini_page.html b/chrome/browser/resources/settings/crostini_page/crostini_page.html
index 0b910ea..1949eb2 100644
--- a/chrome/browser/resources/settings/crostini_page/crostini_page.html
+++ b/chrome/browser/resources/settings/crostini_page/crostini_page.html
@@ -1,9 +1,9 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_icon_button/cr_icon_button.html">
 <link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_indicator.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../i18n_setup.html">
 <link rel="import" href="../prefs/prefs_behavior.html">
 <link rel="import" href="../settings_page/settings_animated_pages.html">
@@ -42,13 +42,13 @@
           </template>
           <template is="dom-if" if="[[!prefs.crostini.enabled.value]]">
             <div class="separator"></div>
-            <paper-button id="enable"
+            <cr-button id="enable"
                 disabled="[[!allowCrostini]]"
                 on-click="onEnableTap_"
                 aria-label="$i18n{crostiniPageTitle}"
                 aria-describedby="secondaryText">
               $i18n{crostiniEnable}
-            </paper-button>
+            </cr-button>
           </template>
         </div>
       </div>
diff --git a/chrome/browser/resources/settings/crostini_page/crostini_subpage.html b/chrome/browser/resources/settings/crostini_page/crostini_subpage.html
index 5cc3458..125be381 100644
--- a/chrome/browser/resources/settings/crostini_page/crostini_subpage.html
+++ b/chrome/browser/resources/settings/crostini_page/crostini_subpage.html
@@ -1,8 +1,8 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_link_row/cr_link_row.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="crostini_browser_proxy.html">
 <link rel="import" href="../i18n_setup.html">
 <link rel="import" href="../prefs/prefs_behavior.html">
@@ -36,10 +36,10 @@
     <template is="dom-if" if="[[!hideCrostiniUninstall_]]">
       <div id="remove" class="settings-box">
         <div id="removeCrostiniLabel" class="start">$i18n{crostiniRemove}</div>
-        <paper-button on-click="onRemoveClick_"
+        <cr-button on-click="onRemoveClick_"
           aria-labelledby="removeCrostiniLabel">
            $i18n{crostiniRemoveButton}
-        </paper-button>
+        </cr-button>
       </div>
     </template>
   </template>
diff --git a/chrome/browser/resources/settings/default_browser_page/default_browser_page.html b/chrome/browser/resources/settings/default_browser_page/default_browser_page.html
index c24783b..df6b0a87 100644
--- a/chrome/browser/resources/settings/default_browser_page/default_browser_page.html
+++ b/chrome/browser/resources/settings/default_browser_page/default_browser_page.html
@@ -1,5 +1,6 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
 <link rel="import" href="default_browser_browser_proxy.html">
 <link rel="import" href="../icons.html">
@@ -16,10 +17,9 @@
           <div class="secondary">$i18n{defaultBrowserMakeDefault}</div>
         </div>
         <div class="separator"></div>
-        <paper-button class="secondary-button"
-            on-click="onSetDefaultBrowserTap_">
+        <cr-button on-click="onSetDefaultBrowserTap_">
           $i18n{defaultBrowserMakeDefaultButton}
-        </paper-button>
+        </cr-button>
       </div>
     </template>
     <template is="dom-if" if="[[!maySetDefaultBrowser_]]">
diff --git a/chrome/browser/resources/settings/device_page/display.html b/chrome/browser/resources/settings/device_page/display.html
index 9d3fbdf0..d5f461a 100644
--- a/chrome/browser/resources/settings/device_page/display.html
+++ b/chrome/browser/resources/settings/device_page/display.html
@@ -10,7 +10,6 @@
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/html/md_select_css.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="display_layout.html">
 <link rel="import" href="display_overscan_dialog.html">
 <link rel="import" href="night_light_slider.html">
@@ -49,7 +48,7 @@
         margin: 10px 0;
       }
 
-      .settings-box > paper-button:first-child {
+      .settings-box > cr-button:first-child {
         padding-inline-start: 0
       }
 
diff --git a/chrome/browser/resources/settings/device_page/display_overscan_dialog.html b/chrome/browser/resources/settings/device_page/display_overscan_dialog.html
index c5b2d74..514f8d7 100644
--- a/chrome/browser/resources/settings/device_page/display_overscan_dialog.html
+++ b/chrome/browser/resources/settings/device_page/display_overscan_dialog.html
@@ -1,10 +1,10 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="chrome://resources/cr_elements/icons.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../icons.html">
 <link rel="import" href="../settings_shared_css.html">
 
@@ -74,12 +74,12 @@
         </div>
       </div>
       <div slot="button-container">
-        <paper-button id="reset" class="cancel-button" on-click="onResetTap_">
+        <cr-button id="reset" class="cancel-button" on-click="onResetTap_">
           $i18n{displayOverscanReset}
-        </paper-button>
-        <paper-button class="action-button" on-click="onSaveTap_">
+        </cr-button>
+        <cr-button class="action-button" on-click="onSaveTap_">
           $i18n{ok}
-        </paper-button>
+        </cr-button>
       </div>
     </cr-dialog>
   </template>
diff --git a/chrome/browser/resources/settings/device_page/drive_cache_dialog.html b/chrome/browser/resources/settings/device_page/drive_cache_dialog.html
index c493176b..00e43a4 100644
--- a/chrome/browser/resources/settings/device_page/drive_cache_dialog.html
+++ b/chrome/browser/resources/settings/device_page/drive_cache_dialog.html
@@ -1,8 +1,8 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../settings_shared_css.html">
 
 <dom-module id="settings-drive-cache-dialog">
@@ -16,14 +16,14 @@
         <span>$i18n{storageClearDriveCacheDialogDescription}</span>
       </div>
       <div slot="button-container">
-        <paper-button id="cancelButton" class="cancel-button"
+        <cr-button id="cancelButton" class="cancel-button"
             on-click="onCancelTap_">
           $i18n{cancel}
-        </paper-button>
-        <paper-button id="deleteButton" class="action-button"
+        </cr-button>
+        <cr-button id="deleteButton" class="action-button"
             on-click="onDeleteTap_">
           $i18n{storageDeleteAllButtonTitle}
-        </paper-button>
+        </cr-button>
       </div>
     </cr-dialog>
   </template>
diff --git a/chrome/browser/resources/settings/downloads_page/downloads_page.html b/chrome/browser/resources/settings/downloads_page/downloads_page.html
index 3e3dac9e..fcb8191 100644
--- a/chrome/browser/resources/settings/downloads_page/downloads_page.html
+++ b/chrome/browser/resources/settings/downloads_page/downloads_page.html
@@ -1,5 +1,6 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_link_row/cr_link_row.html">
 <link rel="import" href="chrome://resources/html/util.html">
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
@@ -36,7 +37,7 @@
           </div>
         </div>
         <div class="separator"></div>
-        <controlled-button class="secondary-button" id="changeDownloadsPath"
+        <controlled-button id="changeDownloadsPath"
             label="$i18n{changeDownloadLocation}"
             on-click="selectDownloadLocation_"
             pref="[[prefs.download.default_directory]]"
@@ -63,10 +64,10 @@
             $i18n{openFileTypesAutomatically}
           </div>
           <div class="separator"></div>
-          <paper-button id="resetAutoOpenFileTypes" class="secondary-button"
+          <cr-button id="resetAutoOpenFileTypes"
               on-click="onClearAutoOpenFileTypesTap_">
             $i18n{clear}
-          </paper-button>
+          </cr-button>
         </div>
       </template>
     </div>
diff --git a/chrome/browser/resources/settings/downloads_page/smb_shares_page.html b/chrome/browser/resources/settings/downloads_page/smb_shares_page.html
index 5b702b3e..6ab41385 100644
--- a/chrome/browser/resources/settings/downloads_page/smb_shares_page.html
+++ b/chrome/browser/resources/settings/downloads_page/smb_shares_page.html
@@ -1,11 +1,11 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
 <link rel="import" href="chrome://resources/cr_components/chromeos/smb_shares/add_smb_share_dialog.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_pref_indicator.html">
 <link rel="import" href="chrome://resources/html/action_link.html">
 <link rel="import" href="chrome://resources/html/action_link_css.html">
 <link rel="import" href="chrome://resources/html/assert.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../route.html">
 <link rel="import" href="../settings_shared_css.html">
 <link rel="import" href="../settings_vars_css.html">
@@ -27,11 +27,11 @@
             icon-aria-label="$i18n{smbSharesTitle}">
         </cr-policy-pref-indicator>
       </template>
-      <paper-button class="action-button" id="addShare"
+      <cr-button class="action-button" id="addShare"
           on-click="onAddShareTap_"
           disabled="[[!prefs.network_file_shares.allowed.value]]">
         $i18n{addSmbShare}
-      </paper-button>
+      </cr-button>
     </div>
     <template is="dom-if" if="[[showAddSmbDialog_]]" restamp>
       <add-smb-share-dialog on-close="onAddSmbDialogClosed_"
diff --git a/chrome/browser/resources/settings/google_assistant_page/google_assistant_page.html b/chrome/browser/resources/settings/google_assistant_page/google_assistant_page.html
index ddc49a6..b6f30b7 100644
--- a/chrome/browser/resources/settings/google_assistant_page/google_assistant_page.html
+++ b/chrome/browser/resources/settings/google_assistant_page/google_assistant_page.html
@@ -95,7 +95,7 @@
                 $i18n{googleAssistantVoiceSettingsDescription}
               </div>
             </div>
-            <controlled-button id="retrain-voice-model" class="secondary-button"
+            <controlled-button id="retrain-voice-model"
                 on-click="onRetrainVoiceModelTapped_"
                 label="$i18n{googleAssistantVoiceSettingsRetrainButton}"
                 pref="{{prefs.settings.voice_interaction.hotword.enabled}}">
diff --git a/chrome/browser/resources/settings/incompatible_applications_page/incompatible_application_item.html b/chrome/browser/resources/settings/incompatible_applications_page/incompatible_application_item.html
index 98ab469..ad5b501 100644
--- a/chrome/browser/resources/settings/incompatible_applications_page/incompatible_application_item.html
+++ b/chrome/browser/resources/settings/incompatible_applications_page/incompatible_application_item.html
@@ -1,8 +1,8 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/html/assert.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../settings_shared_css.html">
 <link rel="import" href="incompatible_applications_browser_proxy.html">
 
@@ -16,9 +16,9 @@
     <div class="list-item">
       <div class="start">[[applicationName]]</div>
       <div class="separator"></div>
-      <paper-button class="action-button" on-click="onActionTap_">
+      <cr-button class="action-button" on-click="onActionTap_">
         [[getActionName_(actionType)]]
-      </paper-button>
+      </cr-button>
     </div>
   </template>
   <script src="incompatible_application_item.js"></script>
diff --git a/chrome/browser/resources/settings/internet_page/internet_config.html b/chrome/browser/resources/settings/internet_page/internet_config.html
index 7f92474..8294c7c 100644
--- a/chrome/browser/resources/settings/internet_page/internet_config.html
+++ b/chrome/browser/resources/settings/internet_page/internet_config.html
@@ -2,10 +2,10 @@
 
 <link rel="import" href="chrome://resources/cr_components/chromeos/network/network_config.html">
 <link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_onc_types.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="internet_shared_css.html">
 
 <dom-module id="internet-config">
@@ -44,20 +44,20 @@
         <template is="dom-if" if="[[error_]]" restamp>
           <div class="flex error">[[getError_(error_)]]</div>
         </template>
-        <paper-button class="cancel-button" on-click="onCancelTap_">
+        <cr-button class="cancel-button" on-click="onCancelTap_">
           $i18n{cancel}
-        </paper-button>
+        </cr-button>
         <template is="dom-if" if="[[!showConnect]]">
-          <paper-button class="action-button" on-click="onSaveTap_"
+          <cr-button class="action-button" on-click="onSaveTap_"
               disabled="[[!enableSave_]]">
             $i18n{save}
-          </paper-button>
+          </cr-button>
         </template>
         <template is="dom-if" if="[[showConnect]]">
-          <paper-button class="action-button" on-click="onConnectTap_"
+          <cr-button class="action-button" on-click="onConnectTap_"
               disabled="[[!enableConnect_]]">
             $i18n{networkButtonConnect}
-          </paper-button>
+          </cr-button>
         </template>
       </div>
 
diff --git a/chrome/browser/resources/settings/internet_page/internet_detail_page.html b/chrome/browser/resources/settings/internet_page/internet_detail_page.html
index 941598f..580c567 100644
--- a/chrome/browser/resources/settings/internet_page/internet_detail_page.html
+++ b/chrome/browser/resources/settings/internet_page/internet_detail_page.html
@@ -8,6 +8,7 @@
 <link rel="import" href="chrome://resources/cr_components/chromeos/network/network_siminfo.html">
 <link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_network_icon.html">
 <link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_onc_types.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_expand_button/cr_expand_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html">
 <link rel="import" href="chrome://resources/cr_elements/icons.html">
@@ -18,7 +19,6 @@
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-collapse/iron-collapse.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-spinner/paper-spinner-lite.html">
 <link rel="import" href="../controls/controlled_button.html">
 <link rel="import" href="../controls/settings_toggle_button.html">
@@ -90,27 +90,27 @@
           </cr-policy-indicator>
         </template>
       </div>
-      <paper-button on-click="onForgetTap_"
+      <cr-button on-click="onForgetTap_"
           hidden$="[[!showForget_(networkProperties_)]]"
           disabled="[[disableForget_(networkProperties_,
               prefs.vpn_config_allowed)]]">
         $i18n{networkButtonForget}
-      </paper-button>
-      <paper-button on-click="onViewAccountTap_"
+      </cr-button>
+      <cr-button on-click="onViewAccountTap_"
           hidden$="[[!showViewAccount_(networkProperties_)]]">
         $i18n{networkButtonViewAccount}
-      </paper-button>
-      <paper-button on-click="onActivateTap_"
+      </cr-button>
+      <cr-button on-click="onActivateTap_"
           hidden$="[[!showActivate_(networkProperties_)]]">
         $i18n{networkButtonActivate}
-      </paper-button>
-      <paper-button on-click="onConfigureTap_"
+      </cr-button>
+      <cr-button on-click="onConfigureTap_"
           hidden$="[[!showConfigure_(networkProperties_, globalPolicy,
               managedNetworkAvailable)]]"
           disabled="[[disableConfigure_(networkProperties_,
               prefs.vpn_config_allowed)]]">
         $i18n{networkButtonConfigure}
-      </paper-button>
+      </cr-button>
       <!-- Use policy properties from vpn_config_allowed to indicate when that
            pref disables buttons in this row. -->
       <controlled-button id="connect" action-button on-click="onConnectTap_"
diff --git a/chrome/browser/resources/settings/internet_page/internet_detail_page.js b/chrome/browser/resources/settings/internet_page/internet_detail_page.js
index 2b24a907..18d8fafd 100644
--- a/chrome/browser/resources/settings/internet_page/internet_detail_page.js
+++ b/chrome/browser/resources/settings/internet_page/internet_detail_page.js
@@ -314,7 +314,7 @@
       // Focus a button once the initial state is set.
       this.didSetFocus_ = true;
       const button = this.$$('#titleDiv .action-button:not([hidden])') ||
-          this.$$('#titleDiv paper-button:not([hidden])');
+          this.$$('#titleDiv cr-button:not([hidden])');
       if (button) {
         setTimeout(() => button.focus());
       }
diff --git a/chrome/browser/resources/settings/internet_page/network_proxy_section.html b/chrome/browser/resources/settings/internet_page/network_proxy_section.html
index c267bacc..c1e7309 100644
--- a/chrome/browser/resources/settings/internet_page/network_proxy_section.html
+++ b/chrome/browser/resources/settings/internet_page/network_proxy_section.html
@@ -2,6 +2,7 @@
 
 <link rel="import" href="chrome://resources/cr_components/chromeos/network/network_proxy.html">
 <link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_onc_types.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
 <link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_network_behavior.html">
@@ -10,7 +11,6 @@
 <link rel="import" href="chrome://resources/html/cr/ui/focus_without_ink.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../controls/extension_controlled_indicator.html">
 <link rel="import" href="../controls/settings_toggle_button.html">
 <link rel="import" href="../i18n_setup.html">
@@ -90,14 +90,14 @@
         $i18n{networkProxyAllowSharedWarningMessage}
       </div>
       <div slot="button-container">
-        <paper-button class="cancel-button"
+        <cr-button class="cancel-button"
             on-click="onAllowSharedDialogCancel_">
           $i18n{cancel}
-        </paper-button>
-        <paper-button class="action-button"
+        </cr-button>
+        <cr-button class="action-button"
             on-click="onAllowSharedDialogConfirm_">
           $i18n{confirm}
-        </paper-button>
+        </cr-button>
       </div>
     </cr-dialog>
   </template>
diff --git a/chrome/browser/resources/settings/internet_page/tether_connection_dialog.html b/chrome/browser/resources/settings/internet_page/tether_connection_dialog.html
index 2d9a2c9..8e8b914 100644
--- a/chrome/browser/resources/settings/internet_page/tether_connection_dialog.html
+++ b/chrome/browser/resources/settings/internet_page/tether_connection_dialog.html
@@ -1,11 +1,11 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 <link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_network_icon.html">
 <link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_onc_types.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../icons.html">
 <link rel="import" href="../route.html">
 <link rel="import" href="../settings_shared_css.html">
@@ -109,13 +109,13 @@
         </ul>
       </div>
       <div slot="button-container">
-        <paper-button class="cancel-button" on-click="onNotNowTap_">
+        <cr-button class="cancel-button" on-click="onNotNowTap_">
           $i18n{tetherConnectionNotNowButton}
-        </paper-button>
-        <paper-button id="connectButton" class="action-button"
+        </cr-button>
+        <cr-button id="connectButton" class="action-button"
             on-click="onConnectTap_" disabled="[[outOfRange]]">
           $i18n{tetherConnectionConnectButton}
-        </paper-button>
+        </cr-button>
       </div>
     </cr-dialog>
   </template>
diff --git a/chrome/browser/resources/settings/kiosk_next_shell_page/kiosk_next_shell_confirmation_dialog.html b/chrome/browser/resources/settings/kiosk_next_shell_page/kiosk_next_shell_confirmation_dialog.html
index 1d1d0624..2c4f065 100644
--- a/chrome/browser/resources/settings/kiosk_next_shell_page/kiosk_next_shell_confirmation_dialog.html
+++ b/chrome/browser/resources/settings/kiosk_next_shell_page/kiosk_next_shell_confirmation_dialog.html
@@ -1,7 +1,7 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../lifetime_browser_proxy.html">
 <link rel="import" href="../prefs/prefs_behavior.html">
 <link rel="import" href="../settings_shared_css.html">
@@ -17,16 +17,16 @@
         [[getBodyText_(prefs.ash.kiosk_next_shell.enabled.value)]]
       </div>
       <div slot="button-container">
-        <paper-button class="cancel-button"
+        <cr-button class="cancel-button"
             on-click="onCancelClick_"
             id="cancel">
           $i18n{cancel}
-        </paper-button>
-        <paper-button class="action-button"
+        </cr-button>
+        <cr-button class="action-button"
             id="confirm"
             on-click="onConfirmClick_">
           [[getConfirmationText_(prefs.ash.kiosk_next_shell.enabled.value)]]
-        </paper-button>
+        </cr-button>
       </div>
     </cr-dialog>
   </template>
diff --git a/chrome/browser/resources/settings/kiosk_next_shell_page/kiosk_next_shell_page.html b/chrome/browser/resources/settings/kiosk_next_shell_page/kiosk_next_shell_page.html
index db08f3a..caff569 100644
--- a/chrome/browser/resources/settings/kiosk_next_shell_page/kiosk_next_shell_page.html
+++ b/chrome/browser/resources/settings/kiosk_next_shell_page/kiosk_next_shell_page.html
@@ -1,6 +1,6 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="../i18n_setup.html">
 <link rel="import" href="../prefs/prefs_behavior.html">
 <link rel="import" href="../settings_shared_css.html">
@@ -24,12 +24,12 @@
         </div>
       </div>
       <div class="separator"></div>
-      <paper-button
+      <cr-button
           on-click="onToggleButtonClick_"
           aria-label="$i18n{kioskNextShellPageTitle}"
           aria-describedby="secondaryText">
         [[getButtonLabel_(prefs.ash.kiosk_next_shell.enabled.value)]]
-      </paper-button>
+      </cr-button>
     </div>
   </template>
   <script src="kiosk_next_shell_page.js"></script>
diff --git a/chrome/browser/resources/settings/languages_page/add_languages_dialog.html b/chrome/browser/resources/settings/languages_page/add_languages_dialog.html
index b8fb95c4..1485626 100644
--- a/chrome/browser/resources/settings/languages_page/add_languages_dialog.html
+++ b/chrome/browser/resources/settings/languages_page/add_languages_dialog.html
@@ -1,13 +1,13 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_checkbox/cr_checkbox.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_scrollable_behavior.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_search_field/cr_search_field.html">
-<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/html/find_shortcut_behavior.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="languages.html">
 <link rel="import" href="../settings_shared_css.html">
 
@@ -64,13 +64,13 @@
         </iron-list>
       </div>
       <div slot="button-container">
-        <paper-button class="cancel-button" on-click="onCancelButtonTap_">
+        <cr-button class="cancel-button" on-click="onCancelButtonTap_">
           $i18n{cancel}
-        </paper-button>
-        <paper-button class="action-button" on-click="onActionButtonTap_"
+        </cr-button>
+        <cr-button class="action-button" on-click="onActionButtonTap_"
             disabled="[[disableActionButton_]]">
           $i18n{add}
-        </paper-button>
+        </cr-button>
       </div>
     </cr-dialog>
   </template>
diff --git a/chrome/browser/resources/settings/languages_page/edit_dictionary_page.html b/chrome/browser/resources/settings/languages_page/edit_dictionary_page.html
index 9d01835..5c35676 100644
--- a/chrome/browser/resources/settings/languages_page/edit_dictionary_page.html
+++ b/chrome/browser/resources/settings/languages_page/edit_dictionary_page.html
@@ -1,11 +1,11 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_icon_button/cr_icon_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html">
 <link rel="import" href="chrome://resources/cr_elements/icons.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-a11y-keys/iron-a11y-keys.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../global_scroll_target_behavior.html">
 <link rel="import" href="../prefs/prefs.html">
 <link rel="import" href="../prefs/prefs_behavior.html">
@@ -39,11 +39,11 @@
               '$i18nPolymer{addDictionaryWordDuplicateError}',
               '$i18nPolymer{addDictionaryWordLengthError}')]]"
           spellcheck="false">
-        <paper-button class="secondary-button" on-click="onAddWordTap_"
+        <cr-button on-click="onAddWordTap_"
             disabled="[[disableAddButton_(newWordValue_)]]" id="addWord"
             slot="suffix">
           $i18n{addDictionaryWordButton}
-        </paper-button>
+        </cr-button>
       </cr-input>
     </div>
     <div class="settings-box continuation block">
diff --git a/chrome/browser/resources/settings/languages_page/languages_page.html b/chrome/browser/resources/settings/languages_page/languages_page.html
index 0cd54256..e6453138 100644
--- a/chrome/browser/resources/settings/languages_page/languages_page.html
+++ b/chrome/browser/resources/settings/languages_page/languages_page.html
@@ -1,8 +1,15 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_checkbox/cr_checkbox.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_expand_button/cr_expand_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_icon_button/cr_icon_button.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_link_row/cr_link_row.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html">
+<link rel="import" href="chrome://resources/cr_elements/icons.html">
+<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_pref_indicator.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/html/action_link.html">
 <link rel="import" href="chrome://resources/html/action_link_css.html">
@@ -12,12 +19,6 @@
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-collapse/iron-collapse.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
-<link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html">
-<link rel="import" href="chrome://resources/cr_elements/cr_expand_button/cr_expand_button.html">
-<link rel="import" href="chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.html">
-<link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html">
-<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_pref_indicator.html">
-<link rel="import" href="chrome://resources/cr_elements/icons.html">
 <link rel="import" href="add_languages_dialog.html">
 <link rel="import" href="languages.html">
 <link rel="import" href="../controls/controlled_radio_button.html">
@@ -224,9 +225,9 @@
 <if expr="chromeos or is_win">
                 <template is="dom-if" if="[[isRestartRequired_(
                         item.language.code, languages.prospectiveUILanguage)]]">
-                  <paper-button class="restart-button" on-click="onRestartTap_">
+                  <cr-button class="restart-button" on-click="onRestartTap_">
                     $i18n{restart}
-                  </paper-button>
+                  </cr-button>
                 </template>
 </if>
                 <cr-icon-button class="icon-more-vert"
@@ -350,11 +351,11 @@
                       $i18n{languagesDictionaryDownloadErrorHelp}
                     </div>
                   </div>
-                  <paper-button on-click="onRetryDictionaryDownloadClick_"
+                  <cr-button on-click="onRetryDictionaryDownloadClick_"
                       hidden="[[!errorsGreaterThan_(
                           item.downloadDictionaryFailureCount, 0)]]">
                     $i18n{retry}
-                  </paper-button>
+                  </cr-button>
                   <template is="dom-if" if="[[!item.isManaged]]">
                     <cr-toggle on-change="onSpellCheckLanguageChange_"
                         disabled="[[!item.language.supportsSpellcheck]]"
diff --git a/chrome/browser/resources/settings/multidevice_page/multidevice_page.html b/chrome/browser/resources/settings/multidevice_page/multidevice_page.html
index 5e59df3..b7891ce 100644
--- a/chrome/browser/resources/settings/multidevice_page/multidevice_page.html
+++ b/chrome/browser/resources/settings/multidevice_page/multidevice_page.html
@@ -1,12 +1,12 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
-<link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_icon_button/cr_icon_button.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html">
 <link rel="import" href="chrome://resources/html/cr.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../i18n_setup.html">
 <link rel="import" href="../icons.html">
 <link rel="import" href="../route.html">
@@ -73,10 +73,9 @@
           <template is="dom-if"
               if="[[shouldShowButton_(pageContentData)]]"
               restamp>
-            <paper-button class="secondary-button"
-                on-click="handleButtonClick_">
+            <cr-button on-click="handleButtonClick_">
               [[getButtonText_(pageContentData)]]
-            </paper-button>
+            </cr-button>
           </template>
           <template is="dom-if"
               if="[[shouldShowToggle_(pageContentData)]]"
diff --git a/chrome/browser/resources/settings/multidevice_page/multidevice_subpage.html b/chrome/browser/resources/settings/multidevice_page/multidevice_subpage.html
index e621471..2e75dd9 100644
--- a/chrome/browser/resources/settings/multidevice_page/multidevice_subpage.html
+++ b/chrome/browser/resources/settings/multidevice_page/multidevice_subpage.html
@@ -1,11 +1,11 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
 <link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_network_listener_behavior.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_link_row/cr_link_row.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/html/cr.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../i18n_setup.html">
 <link rel="import" href="../route.html">
 <link rel="import" href="../settings_shared_css.html">
@@ -44,9 +44,9 @@
       </div>
         <template is="dom-if" if="[[shouldShowVerifyButton_(pageContentData)]]"
             restamp>
-          <paper-button on-click="handleVerifyButtonClick_">
+          <cr-button on-click="handleVerifyButtonClick_">
             $i18n{multideviceVerifyButton}
-          </paper-button>
+          </cr-button>
         </template>
         <template is="dom-if" if="[[shouldShowSuiteToggle_(pageContentData)]]"
             restamp>
@@ -88,12 +88,12 @@
             <template is="dom-if"
                 if="[[doesAndroidMessagesRequireSetUp_(pageContentData)]]"
                 restamp>
-              <paper-button disabled$="[[isAndroidMessagesSetupButtonDisabled_(
+              <cr-button disabled$="[[isAndroidMessagesSetupButtonDisabled_(
                                        pageContentData)]]"
                 on-click="handleAndroidMessagesButtonClick_"
                   slot="feature-controller">
                 $i18n{multideviceSetupButton}
-              </paper-button>
+              </cr-button>
             </template>
           </settings-multidevice-feature-item>
         </template>
@@ -113,15 +113,15 @@
         </div>
       </div>
       <div slot="button-container">
-        <paper-button class="cancel-button"
+        <cr-button class="cancel-button"
             on-click="onForgetDeviceDialogCancelClick_">
           $i18n{cancel}
-        </paper-button>
-        <paper-button id="confirmButton"
+        </cr-button>
+        <cr-button id="confirmButton"
             class="action-button"
             on-click="onForgetDeviceDialogConfirmClick_">
           $i18n{confirm}
-        </paper-button>
+        </cr-button>
       </div>
     </cr-dialog>
   </template>
diff --git a/chrome/browser/resources/settings/on_startup_page/startup_url_dialog.html b/chrome/browser/resources/settings/on_startup_page/startup_url_dialog.html
index 206a93ff..e658300 100644
--- a/chrome/browser/resources/settings/on_startup_page/startup_url_dialog.html
+++ b/chrome/browser/resources/settings/on_startup_page/startup_url_dialog.html
@@ -1,8 +1,8 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../i18n_setup.html">
 <link rel="import" href="../settings_shared_css.html">
 <link rel="import" href="startup_urls_page_browser_proxy.html">
@@ -21,10 +21,10 @@
         </cr-input>
       </div>
       <div slot="button-container">
-        <paper-button class="cancel-button" on-click="onCancelTap_"
-            id="cancel">$i18n{cancel}</paper-button>
-        <paper-button id="actionButton" class="action-button"
-            on-click="onActionButtonTap_">[[actionButtonText_]]</paper-button>
+        <cr-button class="cancel-button" on-click="onCancelTap_"
+            id="cancel">$i18n{cancel}</cr-button>
+        <cr-button id="actionButton" class="action-button"
+            on-click="onActionButtonTap_">[[actionButtonText_]]</cr-button>
       </div>
     </cr-dialog>
   </template>
diff --git a/chrome/browser/resources/settings/parental_controls_page/parental_controls_page.html b/chrome/browser/resources/settings/parental_controls_page/parental_controls_page.html
index 9107417..35f8563e 100644
--- a/chrome/browser/resources/settings/parental_controls_page/parental_controls_page.html
+++ b/chrome/browser/resources/settings/parental_controls_page/parental_controls_page.html
@@ -1,9 +1,9 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/icons.html">
 <link rel="import" href="chrome://resources/html/cr.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="parental_controls_browser_proxy.html">
 <link rel="import" href="../i18n_setup.html">
 <link rel="import" href="../icons.html">
@@ -45,10 +45,9 @@
           </div>
         </div>
         <div class="separator"></div>
-        <paper-button class="secondary-button"
-            on-click="handleSetupButtonClick_" disabled$="[[!online_]]">
+        <cr-button on-click="handleSetupButtonClick_" disabled$="[[!online_]]">
           $i18n{parentalControlsSetUpButtonLabel}
-        </paper-button>
+        </cr-button>
       </template>
     </div>
   </template>
diff --git a/chrome/browser/resources/settings/people_page/account_manager.html b/chrome/browser/resources/settings/people_page/account_manager.html
index e3ded337..9efc576 100644
--- a/chrome/browser/resources/settings/people_page/account_manager.html
+++ b/chrome/browser/resources/settings/people_page/account_manager.html
@@ -1,6 +1,7 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
 <link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_icon_button/cr_icon_button.html">
 <link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_indicator.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
@@ -101,11 +102,11 @@
           hidden="[[isSecondaryGoogleAccountSigninAllowed_()]]"
           indicator-type="userPolicy">
       </cr-policy-indicator>
-      <paper-button disabled="[[!isSecondaryGoogleAccountSigninAllowed_()]]"
+      <cr-button disabled="[[!isSecondaryGoogleAccountSigninAllowed_()]]"
           id="add-account-button" on-tap="addAccount_">
         <div id="add-account-icon"></div>
         $i18n{addAccountLabel}
-      </paper-button>
+      </cr-button>
     </div>
 
     <div id="outer" class="layout vertical nowrap">
@@ -138,10 +139,10 @@
 
           <template is="dom-if"
               if="[[shouldShowReauthenticationButton_(item)]]">
-            <paper-button class="reauth-button"
+            <cr-button class="reauth-button"
                 on-click="onReauthenticationTap_">
               [[getAccountManagerSignedOutLabel_(item.unmigrated)]]
-            </paper-button>
+            </cr-button>
           </template>
 
           <!-- If this is the Device Account, display the management status -->
diff --git a/chrome/browser/resources/settings/people_page/fingerprint_list.html b/chrome/browser/resources/settings/people_page/fingerprint_list.html
index 998a9714..37db70a 100644
--- a/chrome/browser/resources/settings/people_page/fingerprint_list.html
+++ b/chrome/browser/resources/settings/people_page/fingerprint_list.html
@@ -1,5 +1,6 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_icon_button/cr_icon_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html">
 <link rel="import" href="chrome://resources/cr_elements/icons.html">
@@ -9,7 +10,6 @@
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-ripple/paper-ripple.html">
 <link rel="import" href="fingerprint_browser_proxy.html">
 <link rel="import" href="setup_fingerprint_dialog.html">
@@ -61,10 +61,10 @@
         </template>
       </iron-list>
       <div class="continuation">
-        <paper-button id="addFingerprint" class="add-link action-button"
+        <cr-button id="addFingerprint" class="add-link action-button"
             on-click="openAddFingerprintDialog_">
           $i18n{lockScreenAddFingerprint}
-        </paper-button>
+        </cr-button>
       </div>
     </div>
     <i class="settings-box continuation">$i18n{lockScreenFingerprintWarning}</i>
diff --git a/chrome/browser/resources/settings/people_page/import_data_dialog.html b/chrome/browser/resources/settings/people_page/import_data_dialog.html
index 8ba8062..1dedfd5 100644
--- a/chrome/browser/resources/settings/people_page/import_data_dialog.html
+++ b/chrome/browser/resources/settings/people_page/import_data_dialog.html
@@ -1,11 +1,11 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/html/md_select_css.html">
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-spinner/paper-spinner-lite.html">
 <link rel="import" href="../controls/settings_checkbox.html">
 <link rel="import" href="../controls/settings_toggle_button.html">
@@ -102,27 +102,27 @@
             hidden="[[hasImportStatus_(
                 importStatusEnum_.SUCCEEDED, importStatus_)]]">
         </paper-spinner-lite>
-        <paper-button id="cancel" class="cancel-button"
+        <cr-button id="cancel" class="cancel-button"
             hidden="[[hasImportStatus_(
                 importStatusEnum_.SUCCEEDED, importStatus_)]]"
             disabled="[[hasImportStatus_(
                 importStatusEnum_.IN_PROGRESS, importStatus_)]]"
             on-click="closeDialog_">
           $i18n{cancel}
-        </paper-button>
-        <paper-button id="import" class="action-button"
+        </cr-button>
+        <cr-button id="import" class="action-button"
             hidden="[[hasImportStatus_(
                 importStatusEnum_.SUCCEEDED, importStatus_)]]"
             disabled="[[shouldDisableImport_(
                 importStatus_, noImportDataTypeSelected_)]]"
             on-click="onActionButtonTap_">
           [[getActionButtonText_(selected_)]]
-        </paper-button>
+        </cr-button>
 
-        <paper-button id="done" class="action-button"
+        <cr-button id="done" class="action-button"
             hidden$="[[!hasImportStatus_(
                 importStatusEnum_.SUCCEEDED, importStatus_)]]"
-            on-click="closeDialog_">$i18n{done}</paper-button>
+            on-click="closeDialog_">$i18n{done}</cr-button>
       </div>
     </cr-dialog>
   </template>
diff --git a/chrome/browser/resources/settings/people_page/kerberos_accounts.html b/chrome/browser/resources/settings/people_page/kerberos_accounts.html
index f20559b..7bd2f03b 100644
--- a/chrome/browser/resources/settings/people_page/kerberos_accounts.html
+++ b/chrome/browser/resources/settings/people_page/kerberos_accounts.html
@@ -1,13 +1,12 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
 <link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_icon_button/cr_icon_button.html">
-<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
 <link rel="import" href="chrome://resources/html/icon.html">
 <link rel="import" href="chrome://resources/html/util.html">
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../i18n_setup.html">
 <link rel="import" href="../route.html">
 <link rel="import" href="../settings_shared_css.html">
@@ -16,8 +15,7 @@
 
 <dom-module id="settings-kerberos-accounts">
   <template>
-    <style include="settings-shared iron-flex iron-flex-alignment
-        paper-button-style">
+    <style include="settings-shared iron-flex iron-flex-alignment">
       .profile-icon {
         background: center / cover no-repeat;
         border-radius: 20px;
@@ -65,10 +63,10 @@
       <div id="account-list-header" class="flex">
         <h2>$i18n{kerberosAccountsListHeader}</h2>
       </div>
-      <paper-button id="add-account-button" on-click="onAddAccountClick_">
+      <cr-button id="add-account-button" on-click="onAddAccountClick_">
         <div id="add-account-icon"></div>
         $i18n{kerberosAccountsAddAccountLabel}
-      </paper-button>
+      </cr-button>
     </div>
 
     <div id="outer" class="layout vertical nowrap">
@@ -94,10 +92,10 @@
             </div>
           </div>
 
-          <paper-button class="reauth-button" hidden$="[[item.isSignedIn]]"
+          <cr-button class="reauth-button" hidden$="[[item.isSignedIn]]"
               on-click="onReauthenticationClick_">
             $i18n{kerberosAccountsReauthenticationLabel}
-          </paper-button>
+          </cr-button>
 
           <!-- Hamburger menu -->
           <cr-icon-button class="icon-more-vert" title="$i18n{moreActions}"
diff --git a/chrome/browser/resources/settings/people_page/kerberos_add_account_dialog.html b/chrome/browser/resources/settings/people_page/kerberos_add_account_dialog.html
index c6a15532..ad49076b 100644
--- a/chrome/browser/resources/settings/people_page/kerberos_add_account_dialog.html
+++ b/chrome/browser/resources/settings/people_page/kerberos_add_account_dialog.html
@@ -1,20 +1,19 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html">
 <link rel="import" href="chrome://resources/cr_elements/icons.html">
-<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/html/load_time_data.html">
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="kerberos_accounts_browser_proxy.html">
 
 <dom-module id="kerberos-add-account-dialog">
   <template>
-    <style include="paper-button-style">
+    <style>
       .label {
         @apply --cr-form-field-label;
       }
@@ -49,13 +48,13 @@
         </div>
       </div>
       <div slot="button-container">
-        <paper-button class="cancel-button" on-click="onCancel_" id="cancel">
+        <cr-button class="cancel-button" on-click="onCancel_" id="cancel">
           $i18n{cancel}
-        </paper-button>
-        <paper-button class="action-button" on-click="onAdd_"
+        </cr-button>
+        <cr-button class="action-button" on-click="onAdd_"
             disabled="[[inProgress_]]">
           $i18n{add}
-        </paper-button>
+        </cr-button>
       </div>
     </cr-dialog>
   </template>
diff --git a/chrome/browser/resources/settings/people_page/lock_screen.html b/chrome/browser/resources/settings/people_page/lock_screen.html
index 5947726..47204b8e 100644
--- a/chrome/browser/resources/settings/people_page/lock_screen.html
+++ b/chrome/browser/resources/settings/people_page/lock_screen.html
@@ -1,6 +1,7 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
 <link rel="import" href="chrome://resources/cr_components/chromeos/quick_unlock/lock_screen_constants.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_radio_button/cr_radio_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_radio_group/cr_radio_group.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
@@ -96,11 +97,10 @@
                     <!-- Use stop-keyboard-event-propagation to prevent
                          triggering this when focused after closing the
                          dialog. -->
-                    <paper-button id="setupPinButton" class="secondary-button"
-                        on-click="onConfigurePin_"
+                    <cr-button id="setupPinButton" on-click="onConfigurePin_"
                         stop-keyboard-event-propagation>
                       [[getSetupPinText_(hasPin)]]
-                    </paper-button>
+                    </cr-button>
                   </div>
                 </template>
               </cr-radio-button>
@@ -145,12 +145,11 @@
           </div>
           <div class="separator"></div>
           <div class="secondary-action">
-            <paper-button class="secondary-button"
-                on-click="onEditFingerprints_"
+            <cr-button on-click="onEditFingerprints_"
                 aria-label="$i18n{lockScreenEditFingerprints}"
                 aria-descibedby="lockScreenEditFingerprintsSecondary">
               $i18n{lockScreenSetupFingerprintButton}
-            </paper-button>
+            </cr-button>
           </div>
         </div>
       </template>
diff --git a/chrome/browser/resources/settings/people_page/people_page.html b/chrome/browser/resources/settings/people_page/people_page.html
index 95a0b61..e5ab526 100644
--- a/chrome/browser/resources/settings/people_page/people_page.html
+++ b/chrome/browser/resources/settings/people_page/people_page.html
@@ -1,5 +1,6 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_icon_button/cr_icon_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_link_row/cr_link_row.html">
 <link rel="import" href="chrome://resources/cr_elements/icons.html">
@@ -11,7 +12,6 @@
 <link rel="import" href="chrome://resources/html/util.html">
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../controls/settings_toggle_button.html">
 <link rel="import" href="profile_info_browser_proxy.html">
 <link rel="import" href="sync_browser_proxy.html">
@@ -177,18 +177,17 @@
 <if expr="not chromeos">
               <template is="dom-if" if="[[showSignin_(syncStatus)]]">
                 <div class="separator"></div>
-                <paper-button class="action-button" on-click="onSigninTap_"
+                <cr-button class="action-button" on-click="onSigninTap_"
                     disabled="[[syncStatus.firstSetupInProgress]]">
                   $i18n{syncSignin}
-                </paper-button>
+                </cr-button>
               </template>
               <template is="dom-if" if="[[syncStatus.signedIn]]">
                 <div class="separator"></div>
-                <paper-button id="disconnectButton" class="secondary-button"
-                    on-click="onDisconnectTap_"
+                <cr-button id="disconnectButton" on-click="onDisconnectTap_"
                     disabled="[[syncStatus.firstSetupInProgress]]">
                   $i18n{syncDisconnect}
-                </paper-button>
+                </cr-button>
               </template>
 </if>
             </template>
diff --git a/chrome/browser/resources/settings/people_page/setup_fingerprint_dialog.html b/chrome/browser/resources/settings/people_page/setup_fingerprint_dialog.html
index 4274c2b..9ba6b52 100644
--- a/chrome/browser/resources/settings/people_page/setup_fingerprint_dialog.html
+++ b/chrome/browser/resources/settings/people_page/setup_fingerprint_dialog.html
@@ -1,11 +1,11 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
 <link rel="import" href="chrome://resources/cr_elements/chromeos/fingerprint/cr_fingerprint_progress_arc.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="chrome://resources/cr_elements/icons.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-iconset-svg/iron-iconset-svg.html">
 <link rel="import" href="../icons.html">
@@ -73,15 +73,15 @@
         </cr-fingerprint-progress-arc>
       </div>
       <div slot="button-container">
-        <paper-button id="addAnotherButton" on-click="onAddAnotherFingerprint_"
+        <cr-button id="addAnotherButton" on-click="onAddAnotherFingerprint_"
             hidden$="[[hideAddAnother_(step_, allowAddAnotherFinger)]]">
           $i18n{configureFingerprintAddAnotherButton}
-        </paper-button>
+        </cr-button>
 
-        <paper-button id="closeButton"
+        <cr-button id="closeButton"
             class$="[[getCloseButtonClass_(step_)]]" on-click="onClose_">
           [[getCloseButtonText_(step_)]]
-        </paper-button>
+        </cr-button>
       </div>
     </cr-dialog>
   </template>
diff --git a/chrome/browser/resources/settings/people_page/setup_pin_dialog.html b/chrome/browser/resources/settings/people_page/setup_pin_dialog.html
index 9cfa9f13..ec1fb78 100644
--- a/chrome/browser/resources/settings/people_page/setup_pin_dialog.html
+++ b/chrome/browser/resources/settings/people_page/setup_pin_dialog.html
@@ -1,10 +1,10 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
 <link rel="import" href="chrome://resources/cr_components/chromeos/quick_unlock/setup_pin_keyboard.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="chrome://resources/html/assert.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../i18n_setup.html">
 <link rel="import" href="../settings_shared_css.html">
 
@@ -33,13 +33,13 @@
         </div>
       </div>
       <div slot="button-container">
-        <paper-button class="cancel-button" on-click="onCancelTap_">
+        <cr-button class="cancel-button" on-click="onCancelTap_">
           $i18n{cancel}
-        </paper-button>
-        <paper-button class="action-button" on-click="onPinSubmit_"
+        </cr-button>
+        <cr-button class="action-button" on-click="onPinSubmit_"
             disabled$="[[!enableSubmit_]]">
           <span>[[getContinueMessage_(isConfirmStep_)]]</span>
-        </paper-button>
+        </cr-button>
       </div>
     </cr-dialog>
   </template>
diff --git a/chrome/browser/resources/settings/people_page/signout_dialog.html b/chrome/browser/resources/settings/people_page/signout_dialog.html
index 4a93842..18054bd 100644
--- a/chrome/browser/resources/settings/people_page/signout_dialog.html
+++ b/chrome/browser/resources/settings/people_page/signout_dialog.html
@@ -1,11 +1,11 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_checkbox/cr_checkbox.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_expand_button/cr_expand_button.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-collapse/iron-collapse.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="profile_info_browser_proxy.html">
 <link rel="import" href="sync_browser_proxy.html">
 <link rel="import" href="../settings_shared_css.html">
@@ -46,19 +46,19 @@
         </div>
       </div>
       <div slot="button-container">
-        <paper-button id="disconnectCancel" class="cancel-button"
+        <cr-button id="disconnectCancel" class="cancel-button"
             on-click="onDisconnectCancel_" >
           $i18n{cancel}
-        </paper-button>
-        <paper-button id="disconnectConfirm" class="action-button"
+        </cr-button>
+        <cr-button id="disconnectConfirm" class="action-button"
             hidden="[[syncStatus.domain]]" on-click="onDisconnectConfirm_">
           $i18n{syncDisconnect}
-        </paper-button>
-        <paper-button id="disconnectManagedProfileConfirm"
+        </cr-button>
+        <cr-button id="disconnectManagedProfileConfirm"
             class="action-button" hidden="[[!syncStatus.domain]]"
             on-click="onDisconnectConfirm_">
           $i18n{syncDisconnectConfirm}
-        </paper-button>
+        </cr-button>
       </div>
 <if expr="(not chromeos and is_posix) or is_win or is_macosx">
       <template is="dom-if" if="[[!syncStatus.domain]]">
diff --git a/chrome/browser/resources/settings/people_page/sync_account_control.html b/chrome/browser/resources/settings/people_page/sync_account_control.html
index 1bc6162d..dd59852 100644
--- a/chrome/browser/resources/settings/people_page/sync_account_control.html
+++ b/chrome/browser/resources/settings/people_page/sync_account_control.html
@@ -1,12 +1,12 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
 <link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_icon_button/cr_icon_button.html">
 <link rel="import" href="chrome://resources/cr_elements/icons.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="profile_info_browser_proxy.html">
 <link rel="import" href="sync_browser_proxy.html">
 <link rel="import" href="../i18n_setup.html">
@@ -152,11 +152,11 @@
         </div>
         <div class="secondary">[[subLabel_]]</div>
       </div>
-      <paper-button class="action-button" on-click="onSigninTap_"
+      <cr-button class="action-button" on-click="onSigninTap_"
           disabled="[[syncStatus.firstSetupInProgress]]" id="sign-in"
           hidden="[[shouldShowAvatarRow_]]">
         $i18n{peopleSignIn}
-      </paper-button>
+      </cr-button>
     </div>
     <template is="dom-if" if="[[shouldShowAvatarRow_]]">
       <div class="settings-box first two-line" id="avatar-row">
@@ -194,32 +194,30 @@
             id="dropdown-arrow" aria-label="$i18n{useAnotherAccount}">
         </cr-icon-button>
         <div class="separator" hidden="[[syncStatus.signedIn]]"></div>
-        <paper-button id="sync-button" class="action-button"
+        <cr-button id="sync-button" class="action-button"
             hidden="[[syncStatus.signedIn]]" on-click="onSyncButtonTap_"
             disabled="[[syncStatus.firstSetupInProgress]]">
           $i18n{peopleSignIn}
-        </paper-button>
-        <paper-button id="turn-off" class="secondary-button"
+        </cr-button>
+        <cr-button id="turn-off"
             hidden="[[!shouldShowTurnOffButton_(syncStatus.signedIn,
                 showSetupButtons_)]]"
             on-click="onTurnOffButtonTap_"
             disabled="[[syncStatus.firstSetupInProgress]]">
           $i18n{turnOffSync}
-        </paper-button>
-        <paper-button id="sync-error-button" class="action-button"
+        </cr-button>
+        <cr-button id="sync-error-button" class="action-button"
             hidden="[[!shouldShowErrorActionButton_(syncStatus,
                 showSetupButtons_)]]"
             on-click="onErrorButtonTap_"
             disabled="[[syncStatus.firstSetupInProgress]]">
           [[syncStatus.statusActionText]]
-        </paper-button>
+        </cr-button>
         <div id="setup-buttons" hidden="[[!showSetupButtons_]]">
-          <paper-button class="secondary-button" on-click="onSetupCancel_">
-            $i18n{cancel}
-          </paper-button>
-          <paper-button class="action-button" on-click="onSetupConfirm_">
+          <cr-button on-click="onSetupCancel_">$i18n{cancel}</cr-button>
+          <cr-button class="action-button" on-click="onSetupConfirm_">
             $i18n{confirm}
-          </paper-button>
+          </cr-button>
         </div>
       </div>
       <template is="dom-if" if="[[!syncStatus.signedIn]]" restamp>
diff --git a/chrome/browser/resources/settings/people_page/sync_page.html b/chrome/browser/resources/settings/people_page/sync_page.html
index 7bf0489..7054c941 100644
--- a/chrome/browser/resources/settings/people_page/sync_page.html
+++ b/chrome/browser/resources/settings/people_page/sync_page.html
@@ -4,6 +4,7 @@
 <link rel="import" href="chrome://resources/html/util.html">
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_icon_button/cr_icon_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_radio_button/cr_radio_button.html">
@@ -11,7 +12,6 @@
 <link rel="import" href="chrome://resources/cr_elements/icons.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="sync_browser_proxy.html">
 <link rel="import" href="sync_controls.html">
 <link rel="import" href="../privacy_page/personalization_options.html">
@@ -137,11 +137,11 @@
               placeholder="$i18n{passphrasePlaceholder}"
               error-message="$i18n{incorrectPassphraseError}"
               on-keypress="onSubmitExistingPassphraseTap_">
-            <paper-button id="submitExistingPassphrase" slot="suffix"
+            <cr-button id="submitExistingPassphrase" slot="suffix"
                 on-click="onSubmitExistingPassphraseTap_"
                 class="action-button" disabled="[[!existingPassphrase_]]">
               $i18n{submitPassphraseButton}
-            </paper-button>
+            </cr-button>
           </cr-input>
         </div>
         <div id="passphraseRecoverHint" class="list-item">
@@ -184,11 +184,11 @@
                   placeholder="$i18n{passphrasePlaceholder}"
                   error-message="$i18n{incorrectPassphraseError}"
                   on-keypress="onSubmitExistingPassphraseTap_">
-                <paper-button id="submitExistingPassphrase" slot="suffix"
+                <cr-button id="submitExistingPassphrase" slot="suffix"
                     on-click="onSubmitExistingPassphraseTap_"
                     class="action-button" disabled="[[!existingPassphrase_]]">
                   $i18n{submitPassphraseButton}
-                </paper-button>
+                </cr-button>
               </cr-input>
             </div>
             <div id="passphraseRecoverHint" class="list-item">
@@ -306,12 +306,12 @@
                     placeholder="$i18n{passphraseConfirmationPlaceholder}"
                     error-message="$i18n{mismatchedPassphraseError}">
                 </cr-input>
-                <paper-button id="saveNewPassphrase"
+                <cr-button id="saveNewPassphrase"
                     on-click="onSaveNewPassphraseTap_" class="action-button"
                     disabled="[[!isSaveNewPassphraseEnabled_(passphrase_,
                                                              confirmation_)]]">
                   $i18n{save}
-                </paper-button>
+                </cr-button>
               </div>
             </div>
           </template>
@@ -337,14 +337,14 @@
         <div slot="title">$i18n{syncSetupCancelDialogTitle}</div>
         <div slot="body">$i18n{syncSetupCancelDialogBody}</div>
         <div slot="button-container">
-          <paper-button class="cancel-button"
+          <cr-button class="cancel-button"
               on-click="onSetupCancelDialogBack_">
             $i18n{back}
-          </paper-button>
-          <paper-button class="action-button"
+          </cr-button>
+          <cr-button class="action-button"
               on-click="onSetupCancelDialogConfirm_">
             $i18n{cancelSync}
-          </paper-button>
+          </cr-button>
         </div>
       </cr-dialog>
     </template>
@@ -352,9 +352,9 @@
     <template is="dom-if" if="[[!unifiedConsentEnabled]]">
       <cr-toast id="toast" open="[[syncStatus.firstSetupInProgress]]">
         <div>$i18n{syncWillStart}</div>
-        <paper-button on-click="onSyncSetupCancel_">
+        <cr-button on-click="onSyncSetupCancel_">
           $i18n{cancelSync}
-        </paper-button>
+        </cr-button>
       </cr-toast>
     </template>
 </if>
diff --git a/chrome/browser/resources/settings/people_page/sync_page.js b/chrome/browser/resources/settings/people_page/sync_page.js
index f1f13ad..fd28dad6 100644
--- a/chrome/browser/resources/settings/people_page/sync_page.js
+++ b/chrome/browser/resources/settings/people_page/sync_page.js
@@ -444,7 +444,7 @@
     assert(this.creatingNewPassphrase_);
 
     // Ignore events on irrelevant elements or with irrelevant keys.
-    if (e.target.tagName != 'PAPER-BUTTON' && e.target.tagName != 'CR-INPUT') {
+    if (e.target.tagName != 'CR-BUTTON' && e.target.tagName != 'CR-INPUT') {
       return;
     }
     if (e.type == 'keypress' && e.key != 'Enter') {
diff --git a/chrome/browser/resources/settings/people_page/users_add_user_dialog.html b/chrome/browser/resources/settings/people_page/users_add_user_dialog.html
index 7915b03..e1caa97f 100644
--- a/chrome/browser/resources/settings/people_page/users_add_user_dialog.html
+++ b/chrome/browser/resources/settings/people_page/users_add_user_dialog.html
@@ -1,9 +1,9 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html">
 <link rel="import" href="chrome://resources/html/assert.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../settings_shared_css.html">
 <link rel="import" href="../settings_vars_css.html">
 
@@ -24,13 +24,13 @@
         </cr-input>
       </div>
       <div slot="button-container">
-        <paper-button class="cancel-button" on-click="onCancelTap_">
+        <cr-button class="cancel-button" on-click="onCancelTap_">
           $i18n{cancel}
-        </paper-button>
-        <paper-button on-click="addUser_" class="action-button"
+        </cr-button>
+        <cr-button on-click="addUser_" class="action-button"
             disabled$="[[!canAddUser_(isEmail_, isEmpty_)]]">
           $i18n{add}
-        </paper-button>
+        </cr-button>
       </div>
     </cr-dialog>
   </template>
diff --git a/chrome/browser/resources/settings/people_page/users_page.html b/chrome/browser/resources/settings/people_page/users_page.html
index afdbbe7d..51495c44 100644
--- a/chrome/browser/resources/settings/people_page/users_page.html
+++ b/chrome/browser/resources/settings/people_page/users_page.html
@@ -5,7 +5,6 @@
 <link rel="import" href="chrome://resources/html/action_link.html">
 <link rel="import" href="chrome://resources/html/assert.html">
 <link rel="import" href="chrome://resources/html/cr/ui/focus_without_ink.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../controls/settings_toggle_button.html">
 <link rel="import" href="../settings_shared_css.html">
 <link rel="import" href="user_list.html">
diff --git a/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.html b/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.html
index 388d17cbe..3e9bba6f 100644
--- a/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.html
+++ b/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.html
@@ -1,10 +1,10 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.html">
 <link rel="import" href="chrome://resources/html/md_select_css.html">
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-spinner/paper-spinner-lite.html">
 <link rel="import" href="../i18n_setup.html">
 <link rel="import" href="cups_add_printer_dialog_elements.html">
@@ -52,21 +52,20 @@
       </div>
       <div slot="dialog-buttons">
         <div>  <!-- Left group -->
-          <paper-button id="manuallyAddPrinterButton" class="secondary-button"
+          <cr-button id="manuallyAddPrinterButton"
               on-click="switchToManualAddDialog_">
             $i18n{manuallyAddPrinterButtonText}
-          </paper-button>
+          </cr-button>
         </div>
         <div>  <!-- Right group -->
-          <paper-button class="cancel-button secondary-button"
-              on-click="onCancelTap_">
+          <cr-button class="cancel-button" on-click="onCancelTap_">
             $i18n{cancel}
-          </paper-button>
-          <paper-button class="action-button" id="addPrinterButton"
+          </cr-button>
+          <cr-button class="action-button" id="addPrinterButton"
               disabled="[[!canAddPrinter_(selectedPrinter)]]"
               on-click="switchToConfiguringDialog_">
             $i18n{addPrinterButtonText}
-          </paper-button>
+          </cr-button>
         </div>
       </div>
     </add-printer-dialog>
@@ -116,21 +115,19 @@
       </div>
       <div slot="dialog-buttons">
         <div>  <!-- Left group -->
-          <paper-button class="secondary-button"
-              on-click="switchToDiscoveryDialog_">
+          <cr-button on-click="switchToDiscoveryDialog_">
             $i18n{discoverPrintersButtonText}
-          </paper-button>
+          </cr-button>
         </div>
         <div>  <!-- Right group -->
-          <paper-button class="cancel-button secondary-button"
-              on-click="onCancelTap_">
+          <cr-button class="cancel-button" on-click="onCancelTap_">
             $i18n{cancel}
-          </paper-button>
-          <paper-button id="addPrinterButton" class="action-button"
+          </cr-button>
+          <cr-button id="addPrinterButton" class="action-button"
               on-click="addPressed_"
               disabled="[[!canAddPrinter_(newPrinter.*)]]">
             $i18n{addPrinterButtonText}
-          </paper-button>
+          </cr-button>
         </div>
       </div>
     </add-printer-dialog>
@@ -181,26 +178,25 @@
               aria-labelledby="ppdLabel" invalid="[[invalidPPD_]]"
               error-message="$i18n{selectDriverErrorMessage}" tabindex="-1">
           </cr-input>
-          <paper-button class="browse-button" on-click="onBrowseFile_">
+          <cr-button class="browse-button" on-click="onBrowseFile_">
             $i18n{selectDriverButtonText}
-          </paper-button>
+          </cr-button>
         </div>
         <div class="eula" id="eulaUrl" hidden="[[!eulaUrl_]]">
           <a href="[[eulaUrl_]]" target="_blank">$i18n{printerEulaNotice}</a>
         </div>
       </div>
       <div slot="dialog-buttons">
-        <paper-button class="cancel-button secondary-button"
-            on-click="onCancelTap_">
+        <cr-button class="cancel-button" on-click="onCancelTap_">
           $i18n{cancel}
-        </paper-button>
-        <paper-button class="action-button" id="addPrinterButton"
+        </cr-button>
+        <cr-button class="action-button" id="addPrinterButton"
             disabled="[[!canAddPrinter_(activePrinter.ppdManufacturer,
                                         activePrinter.ppdModel,
                                         activePrinter.printerPPDPath)]]"
             on-click="switchToConfiguringDialog_">
           $i18n{addPrinterButtonText}
-        </paper-button>
+        </cr-button>
       </div>
     </add-printer-dialog>
   </template>
@@ -221,10 +217,9 @@
         <div id="configuringMessage">$i18n{printerConfiguringMessage}</div>
       </div>
       <div slot="dialog-buttons">
-        <paper-button class="cancel-button secondary-button"
-            on-click="onCloseConfiguringTap_">
+        <cr-button class="cancel-button" on-click="onCloseConfiguringTap_">
           $i18n{close}
-        </paper-button>
+        </cr-button>
       </div>
     </add-printer-dialog>
   </template>
diff --git a/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_elements.html b/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_elements.html
index 83e2e90..b46c8ca 100644
--- a/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_elements.html
+++ b/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_elements.html
@@ -2,7 +2,6 @@
 
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="chrome://resources/cr_elements/icons.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="cups_printer_shared_css.html">
 <link rel="import" href="cups_printers_browser_proxy.html">
 
diff --git a/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.html b/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.html
index 8947b67a..70c6c2d 100644
--- a/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.html
+++ b/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.html
@@ -1,9 +1,9 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_scrollable_behavior.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../i18n_setup.html">
 <link rel="import" href="cups_add_printer_dialog_elements.html">
 <link rel="import" href="cups_printer_dialog_util.html">
@@ -109,24 +109,23 @@
               error-message="$i18n{selectDriverErrorMessage}"
               invalid="[[invalidPPD_]]">
           </cr-input>
-          <paper-button class="browse-button" on-click="onBrowseFile_">
+          <cr-button class="browse-button" on-click="onBrowseFile_">
             $i18n{selectDriverButtonText}
-          </paper-button>
+          </cr-button>
         </div>
         <div class="eula" id="eulaUrl" hidden="[[!eulaUrl_]]">
           <a href="[[eulaUrl_]]" target="_blank">$i18n{printerEulaNotice}</a>
         </div>
       </div>
       <div slot="dialog-buttons">
-        <paper-button class="cancel-button secondary-button"
-            on-click="onCancelTap_">
+        <cr-button class="cancel-button" on-click="onCancelTap_">
           $i18n{cancel}
-        </paper-button>
-        <paper-button class="action-button" on-click="onSaveTap_"
+        </cr-button>
+        <cr-button class="action-button" on-click="onSaveTap_"
             disabled="[[!canSavePrinter_(pendingPrinter_.*,
                                          printerInfoChanged_)]]">
           $i18n{editPrinterButtonText}
-        </paper-button>
+        </cr-button>
       </div>
     </add-printer-dialog>
   </template>
diff --git a/chrome/browser/resources/settings/printing_page/cups_printers.html b/chrome/browser/resources/settings/printing_page/cups_printers.html
index 1e36dfa..7bb83da 100644
--- a/chrome/browser/resources/settings/printing_page/cups_printers.html
+++ b/chrome/browser/resources/settings/printing_page/cups_printers.html
@@ -1,12 +1,12 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
-<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_pref_indicator.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_toast/cr_toast.html">
+<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_pref_indicator.html">
 <link rel="import" href="chrome://resources/html/action_link.html">
 <link rel="import" href="chrome://resources/html/action_link_css.html">
 <link rel="import" href="chrome://resources/html/assert.html">
 <link rel="import" href="chrome://resources/html/cr/ui/focus_without_ink.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="cups_add_printer_dialog.html">
 <link rel="import" href="cups_edit_printer_dialog.html">
 <link rel="import" href="cups_printer_shared_css.html">
@@ -41,12 +41,12 @@
             icon-aria-label="$i18n{printingPageTitle}">
         </cr-policy-pref-indicator>
       </template>
-      <paper-button class="action-button" id="addPrinter"
+      <cr-button class="action-button" id="addPrinter"
           on-click="onAddPrinterTap_"
           disabled="[[!addPrinterButtonActive_(canAddPrinter_,
               prefs.native_printing.user_native_printers_allowed.value)]]">
         $i18n{addCupsPrinter}
-      </paper-button>
+      </cr-button>
     </div>
 
     <settings-cups-add-printer-dialog id="addPrinterDialog"
diff --git a/chrome/browser/resources/settings/printing_page/printing_page.html b/chrome/browser/resources/settings/printing_page/printing_page.html
index 3d892798..2e96cf2 100644
--- a/chrome/browser/resources/settings/printing_page/printing_page.html
+++ b/chrome/browser/resources/settings/printing_page/printing_page.html
@@ -24,7 +24,7 @@
 </if>
 <if expr="not chromeos">
         <cr-link-row label="$i18n{localPrintersTitle}"
-            on-click="onTapLocalPrinters_"></cr-link-row>
+            on-click="onTapLocalPrinters_" external></cr-link-row>
 </if>
         <cr-link-row class="hr" id="cloudPrinters"
             label="$i18n{cloudPrintersTitle}" on-click="onTapCloudPrinters_">
diff --git a/chrome/browser/resources/settings/privacy_page/personalization_options.html b/chrome/browser/resources/settings/privacy_page/personalization_options.html
index 7efe994e..491eff1b 100644
--- a/chrome/browser/resources/settings/privacy_page/personalization_options.html
+++ b/chrome/browser/resources/settings/privacy_page/personalization_options.html
@@ -1,8 +1,8 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html">
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../controls/settings_toggle_button.html">
 <link rel="import" href="../lifetime_browser_proxy.html">
 <link rel="import" href="../people_page/sync_browser_proxy.html">
@@ -61,10 +61,10 @@
         sub-label="$i18n{enableLoggingDesc}" no-set-pref
         on-settings-boolean-control-change="onMetricsReportingChange_">
       <template is="dom-if" if="[[showRestart_]]" restamp>
-        <paper-button on-click="onRestartTap_" id="restart"
+        <cr-button on-click="onRestartTap_" id="restart"
             slot="more-actions">
           $i18n{restart}
-        </paper-button>
+        </cr-button>
       </template>
     </settings-toggle-button>
 </if><!-- not chromeos -->
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_page.html b/chrome/browser/resources/settings/privacy_page/privacy_page.html
index 41fce3a..5715752 100644
--- a/chrome/browser/resources/settings/privacy_page/privacy_page.html
+++ b/chrome/browser/resources/settings/privacy_page/privacy_page.html
@@ -1,13 +1,13 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
-<link rel="import" href="chrome://resources/cr_elements/cr_link_row/cr_link_row.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_icon_button/cr_icon_button.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_link_row/cr_link_row.html">
 <link rel="import" href="chrome://resources/html/assert.html">
 <link rel="import" href="chrome://resources/html/cr/ui/focus_without_ink.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="security_keys_subpage.html">
 <link rel="import" href="../clear_browsing_data_dialog/clear_browsing_data_dialog.html">
 <link rel="import" href="../controls/settings_toggle_button.html">
@@ -69,14 +69,14 @@
         <div slot="title">$i18n{doNotTrackDialogTitle}</div>
         <div slot="body">$i18nRaw{doNotTrackDialogMessage}</div>
         <div slot="button-container">
-          <paper-button class="cancel-button"
+          <cr-button class="cancel-button"
               on-click="onDoNotTrackDialogCancel_">
             $i18n{cancel}
-          </paper-button>
-          <paper-button class="action-button"
+          </cr-button>
+          <cr-button class="action-button"
               on-click="onDoNotTrackDialogConfirm_">
             $i18n{confirm}
-          </paper-button>
+          </cr-button>
         </div>
       </cr-dialog>
     </template>
@@ -567,10 +567,10 @@
       </template>
       <template is="dom-if" route-path="/cookies/detail" no-search>
         <settings-subpage page-title="[[pageTitle]]">
-          <paper-button slot="subpage-title-extra" class="secondary-button"
+          <cr-button slot="subpage-title-extra"
               on-click="onRemoveAllCookiesFromSite_">
             $i18n{siteSettingsCookieRemoveAll}
-          </paper-button>
+          </cr-button>
           <site-data-details-subpage page-title="{{pageTitle}}">
           </site-data-details-subpage>
         </settings-subpage>
@@ -678,9 +678,9 @@
 <if expr="not chromeos">
     <cr-toast id="toast" open="[[showRestart_]]">
       <div>$i18n{restartToApplyChanges}</div>
-      <paper-button on-click="onRestartTap_">
+      <cr-button on-click="onRestartTap_">
         $i18n{restart}
-      </paper-button>
+      </cr-button>
     </cr-toast>
 </if>
   </template>
diff --git a/chrome/browser/resources/settings/privacy_page/security_keys_reset_dialog.html b/chrome/browser/resources/settings/privacy_page/security_keys_reset_dialog.html
index fdec7c89..108da71 100644
--- a/chrome/browser/resources/settings/privacy_page/security_keys_reset_dialog.html
+++ b/chrome/browser/resources/settings/privacy_page/security_keys_reset_dialog.html
@@ -1,9 +1,9 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-pages/iron-pages.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-spinner/paper-spinner-lite.html">
 <link rel="import" href="../i18n_setup.html">
 <link rel="import" href="../settings_shared_css.html">
@@ -48,10 +48,10 @@
         </iron-pages>
       </div>
       <div slot="button-container">
-        <paper-button id="button" class$="[[maybeActionButton_(complete_)]]"
+        <cr-button id="button" class$="[[maybeActionButton_(complete_)]]"
              on-click="closeDialog_">
           [[closeText_(complete_)]]
-        </paper-button>
+        </cr-button>
       </div>
     </cr-dialog>
   </template>
diff --git a/chrome/browser/resources/settings/privacy_page/security_keys_set_pin_dialog.html b/chrome/browser/resources/settings/privacy_page/security_keys_set_pin_dialog.html
index 96abaa0..3abd68a 100644
--- a/chrome/browser/resources/settings/privacy_page/security_keys_set_pin_dialog.html
+++ b/chrome/browser/resources/settings/privacy_page/security_keys_set_pin_dialog.html
@@ -1,10 +1,10 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-pages/iron-pages.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-spinner/paper-spinner-lite.html">
 <link rel="import" href="../i18n_setup.html">
 <link rel="import" href="../settings_shared_css.html">
@@ -90,16 +90,16 @@
       </div>
 
       <div slot="button-container">
-        <paper-button id="closeButton"
+        <cr-button id="closeButton"
             class$="[[maybeActionButton_(complete_)]]"
             on-click="closeDialog_">
           [[closeText_(complete_)]]
-        </paper-button>
-        <paper-button id="pinSubmit" class="action-button"
+        </cr-button>
+        <cr-button id="pinSubmit" class="action-button"
             on-click="pinSubmitNew_" disabled="[[!setPINButtonValid_]]"
             hidden="[[complete_]]">
           $i18n{securityKeysSetPINConfirm}
-        </paper-button>
+        </cr-button>
       </div>
     </cr-dialog>
   </template>
diff --git a/chrome/browser/resources/settings/reset_page/powerwash_dialog.html b/chrome/browser/resources/settings/reset_page/powerwash_dialog.html
index 90e2a121..965e35f 100644
--- a/chrome/browser/resources/settings/reset_page/powerwash_dialog.html
+++ b/chrome/browser/resources/settings/reset_page/powerwash_dialog.html
@@ -1,7 +1,7 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../lifetime_browser_proxy.html">
 <link rel="import" href="reset_browser_proxy.html">
 <link rel="import" href="../settings_shared_css.html">
@@ -22,10 +22,10 @@
         </span>
       </div>
       <div slot="button-container">
-        <paper-button class="cancel-button" on-click="onCancelTap_"
-            id="cancel">$i18n{cancel}</paper-button>
-        <paper-button class="action-button" id="powerwash"
-            on-click="onRestartTap_">$i18n{powerwashDialogButton}</paper-button>
+        <cr-button class="cancel-button" on-click="onCancelTap_"
+            id="cancel">$i18n{cancel}</cr-button>
+        <cr-button class="action-button" id="powerwash"
+            on-click="onRestartTap_">$i18n{powerwashDialogButton}</cr-button>
       </div>
     </cr-dialog>
   </template>
diff --git a/chrome/browser/resources/settings/reset_page/reset_profile_banner.html b/chrome/browser/resources/settings/reset_page/reset_profile_banner.html
index 3eaaf42..57fdf7a 100644
--- a/chrome/browser/resources/settings/reset_page/reset_profile_banner.html
+++ b/chrome/browser/resources/settings/reset_page/reset_profile_banner.html
@@ -1,7 +1,7 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="reset_browser_proxy.html">
 <link rel="import" href="../route.html">
 
@@ -19,12 +19,12 @@
         </span>
       </div>
       <div slot="button-container">
-        <paper-button class="cancel-button" on-click="onOkTap_" id="ok">
+        <cr-button class="cancel-button" on-click="onOkTap_" id="ok">
           $i18n{ok}
-        </paper-button>
-        <paper-button class="action-button" on-click="onResetTap_" id="reset">
+        </cr-button>
+        <cr-button class="action-button" on-click="onResetTap_" id="reset">
           $i18n{resetProfileBannerButton}
-        </paper-button>
+        </cr-button>
       </div>
     </cr-dialog>
   </template>
diff --git a/chrome/browser/resources/settings/reset_page/reset_profile_dialog.html b/chrome/browser/resources/settings/reset_page/reset_profile_dialog.html
index fc3b752..cbe026e6 100644
--- a/chrome/browser/resources/settings/reset_page/reset_profile_dialog.html
+++ b/chrome/browser/resources/settings/reset_page/reset_profile_dialog.html
@@ -1,11 +1,11 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_checkbox/cr_checkbox.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="chrome://resources/html/action_link.html">
 <link rel="import" href="chrome://resources/html/action_link_css.html">
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-spinner/paper-spinner-lite.html">
 <link rel="import" href="reset_browser_proxy.html">
 <link rel="import" href="../i18n_setup.html">
@@ -42,14 +42,14 @@
       <div slot="button-container">
         <paper-spinner-lite id="resetSpinner" active="[[clearingInProgress_]]">
         </paper-spinner-lite>
-        <paper-button class="cancel-button" on-click="onCancelTap_"
+        <cr-button class="cancel-button" on-click="onCancelTap_"
             id="cancel" disabled="[[clearingInProgress_]]">
           $i18n{cancel}
-        </paper-button>
-        <paper-button class="action-button" on-click="onResetTap_"
+        </cr-button>
+        <cr-button class="action-button" on-click="onResetTap_"
             id="reset" disabled="[[clearingInProgress_]]">
           $i18n{resetDialogCommit}
-        </paper-button>
+        </cr-button>
       </div>
       <div slot="footer">
         <cr-checkbox id="sendSettings" checked>
diff --git a/chrome/browser/resources/settings/route.js b/chrome/browser/resources/settings/route.js
index 1019e13..35d3786 100644
--- a/chrome/browser/resources/settings/route.js
+++ b/chrome/browser/resources/settings/route.js
@@ -66,6 +66,7 @@
  *   PARENTAL_CONTROLS: (undefined|!settings.Route),
  *   PAYMENTS: (undefined|!settings.Route),
  *   PEOPLE: (undefined|!settings.Route),
+ *   PERSONALIZATION: (undefined|!settings.Route),
  *   PLUGIN_VM: (undefined|!settings.Route),
  *   PLUGIN_VM_DETAILS: (undefined|!settings.Route),
  *   PLUGIN_VM_SHARED_PATHS: (undefined|!settings.Route),
@@ -260,6 +261,13 @@
       r.PARENTAL_CONTROLS =
           r.BASIC.createSection('/parentalControls', 'parentalControls');
     }
+
+    // TODO(hsuregan): Remove once this file is forked.
+    if (loadTimeData.valueExists('showOSSettings') &&
+        loadTimeData.getBoolean('showOSSettings')) {
+      r.PERSONALIZATION =
+          r.BASIC.createSection('/personalization', 'personalization');
+    }
     // </if>
 
     if (pageVisibility.appearance !== false) {
diff --git a/chrome/browser/resources/settings/search_engines_page/search_engine_dialog.html b/chrome/browser/resources/settings/search_engines_page/search_engine_dialog.html
index fff9623..a71de985 100644
--- a/chrome/browser/resources/settings/search_engines_page/search_engine_dialog.html
+++ b/chrome/browser/resources/settings/search_engines_page/search_engine_dialog.html
@@ -1,9 +1,9 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html">
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../i18n_setup.html">
 <link rel="import" href="search_engines_browser_proxy.html">
 
@@ -33,12 +33,12 @@
         </cr-input>
       </div>
       <div slot="button-container">
-        <paper-button class="cancel-button" on-click="cancel_" id="cancel">
-            $i18n{cancel}</paper-button>
-        <paper-button id="actionButton" class="action-button"
+        <cr-button class="cancel-button" on-click="cancel_" id="cancel">
+            $i18n{cancel}</cr-button>
+        <cr-button id="actionButton" class="action-button"
             on-click="onActionButtonTap_">
           [[actionButtonText_]]
-        </paper-button>
+        </cr-button>
       </div>
     </cr-dialog>
   </template>
diff --git a/chrome/browser/resources/settings/search_engines_page/search_engines_page.html b/chrome/browser/resources/settings/search_engines_page/search_engines_page.html
index 4229a16..b275f05 100644
--- a/chrome/browser/resources/settings/search_engines_page/search_engines_page.html
+++ b/chrome/browser/resources/settings/search_engines_page/search_engines_page.html
@@ -1,5 +1,6 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/html/action_link.html">
 <link rel="import" href="chrome://resources/html/action_link_css.html">
@@ -46,10 +47,10 @@
 
     <div class="settings-box first">
       <h2 class="start">$i18n{searchEnginesOther}</h2>
-      <paper-button class="secondary-button header-aligned-button"
+      <cr-button class="secondary-button header-aligned-button"
           on-click="onAddSearchEngineTap_" id="addSearchEngine">
         $i18n{add}
-      </paper-button>
+      </cr-button>
     </div>
     <div id="noOtherEngines" hidden="[[otherEngines.length]]">
       $i18n{searchEnginesNoOtherEngines}
diff --git a/chrome/browser/resources/settings/settings_main/settings_main.html b/chrome/browser/resources/settings/settings_main/settings_main.html
index ac626d19..0a3d392f 100644
--- a/chrome/browser/resources/settings/settings_main/settings_main.html
+++ b/chrome/browser/resources/settings/settings_main/settings_main.html
@@ -7,7 +7,6 @@
 <link rel="import" href="chrome://resources/html/promise_resolver.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-a11y-announcer/iron-a11y-announcer.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../about_page/about_page.html">
 <link rel="import" href="../basic_page/basic_page.html">
 <link rel="import" href="../i18n_setup.html">
diff --git a/chrome/browser/resources/settings/settings_menu/settings_menu.html b/chrome/browser/resources/settings/settings_menu/settings_menu.html
index 480e4d34..64ae043 100644
--- a/chrome/browser/resources/settings/settings_menu/settings_menu.html
+++ b/chrome/browser/resources/settings/settings_menu/settings_menu.html
@@ -1,11 +1,11 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/icons.html">
 <link rel="import" href="chrome://resources/html/assert.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-collapse/iron-collapse.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-selector/iron-selector.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../icons.html">
 <link rel="import" href="../route.html">
 <link rel="import" href="../settings_shared_css.html">
@@ -53,8 +53,11 @@
       }
 
       #advancedButton {
+        --ink-color: var(--settings-nav-item-color);
+        background: none;
         border: none;
         border-radius: initial;
+        box-shadow: none;
         height: unset;
         margin-top: 8px;
         padding-inline-end: 0;
@@ -62,11 +65,10 @@
       }
 
       #advancedButton:focus {
-        box-shadow: none;
         outline: none;
       }
 
-      #advancedButton.keyboard-focus:focus {
+      :host-context(.focus-outline-visible) #advancedButton:focus {
         outline: auto 5px -webkit-focus-ring-color;
       }
 
@@ -172,12 +174,12 @@
         <iron-icon icon="settings:power-settings-new"></iron-icon>
         $i18n{onStartup}
       </a>
-      <paper-button toggles id="advancedButton"
-          aria-active-attribute="aria-expanded" active="{{advancedOpened}}"
+      <cr-button id="advancedButton" aria-active-attribute="aria-expanded"
+          on-click="onAdvancedButtonToggle_"
           hidden="[[!pageVisibility.advancedSettings]]">
         <span>$i18n{advancedPageTitle}</span>
         <iron-icon icon="[[arrowState_(advancedOpened)]]">
-        </iron-icon></paper-button>
+        </iron-icon></cr-button>
       <iron-collapse id="advancedSubmenu" opened="[[advancedOpened]]"
           hidden="[[!pageVisibility.advancedSettings]]">
         <iron-selector id="subMenu" selectable="a" attr-for-selected="href"
diff --git a/chrome/browser/resources/settings/settings_menu/settings_menu.js b/chrome/browser/resources/settings/settings_menu/settings_menu.js
index a28c773..38bce70 100644
--- a/chrome/browser/resources/settings/settings_menu/settings_menu.js
+++ b/chrome/browser/resources/settings/settings_menu/settings_menu.js
@@ -14,6 +14,7 @@
   properties: {
     advancedOpened: {
       type: Boolean,
+      value: false,
       notify: true,
     },
 
@@ -40,6 +41,11 @@
     this.setSelectedUrl_('');  // Nothing is selected.
   },
 
+  /** @private */
+  onAdvancedButtonToggle_: function() {
+    this.advancedOpened = !this.advancedOpened;
+  },
+
   /**
    * Prevent clicks on sidebar items from navigating. These are only links for
    * accessibility purposes, taps are handled separately by <iron-selector>.
diff --git a/chrome/browser/resources/settings/settings_shared_css.html b/chrome/browser/resources/settings/settings_shared_css.html
index 7c31479..ea4c88e6 100644
--- a/chrome/browser/resources/settings/settings_shared_css.html
+++ b/chrome/browser/resources/settings/settings_shared_css.html
@@ -1,4 +1,3 @@
-<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
 <link rel="import" href="chrome://resources/cr_elements/search_highlight_style_css.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_style_css.html">
@@ -9,8 +8,7 @@
 <!-- Common styles for Material Design settings. -->
 <dom-module id="settings-shared">
   <template>
-    <style include="settings-icons paper-button-style cr-shared-style
-        search-highlight-style">
+    <style include="settings-icons cr-shared-style search-highlight-style">
       /* Prevent action-links from being selected to avoid accidental
        * selection when trying to click it. */
       a[is=action-link] {
@@ -62,15 +60,15 @@
       }
 
       /* Special case for buttons inside of toggle-buttons. */
-      .settings-box settings-toggle-button paper-button:last-of-type {
+      .settings-box settings-toggle-button cr-button:last-of-type {
         margin-inline-end: 16px;
       }
 
       /* Space out multiple buttons in the same row. */
-      .settings-box paper-button + paper-button,
-      .settings-box paper-button + controlled-button,
+      .settings-box cr-button + cr-button,
+      .settings-box cr-button + controlled-button,
       .settings-box controlled-button + controlled-button,
-      .settings-box controlled-button + paper-button {
+      .settings-box controlled-button + cr-button {
         margin-inline-start: 8px;
       }
 
@@ -132,7 +130,7 @@
       }
 
       .header-aligned-button {
-        margin-top: 12px;  /* Align paper-button with <h2>. */
+        margin-top: 12px;  /* Align cr-button with <h2>. */
       }
 
       /* A list-frame is an outer container for list-items. It is intended to be
@@ -317,7 +315,7 @@
       .separator {
         border-inline-start: var(--cr-separator-line);
         flex-shrink: 0;
-        /* Match paper-button's default height. */
+        /* Match cr-button's default height. */
         height: 32px;
         margin: 0 16px;
       }
diff --git a/chrome/browser/resources/settings/site_settings/add_site_dialog.html b/chrome/browser/resources/settings/site_settings/add_site_dialog.html
index 3b2ddf0f..938cfeb 100644
--- a/chrome/browser/resources/settings/site_settings/add_site_dialog.html
+++ b/chrome/browser/resources/settings/site_settings/add_site_dialog.html
@@ -1,10 +1,10 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_checkbox/cr_checkbox.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html">
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../i18n_setup.html">
 <link rel="import" href="../settings_shared_css.html">
 <link rel="import" href="constants.html">
@@ -32,13 +32,13 @@
         </cr-checkbox>
       </div>
       <div slot="button-container">
-        <paper-button class="cancel-button" on-click="onCancelTap_">
+        <cr-button class="cancel-button" on-click="onCancelTap_">
           $i18n{cancel}
-        </paper-button>
-        <paper-button class="action-button" id="add" on-click="onSubmit_"
+        </cr-button>
+        <cr-button class="action-button" id="add" on-click="onSubmit_"
             disabled>
           $i18n{add}
-        </paper-button>
+        </cr-button>
       </div>
     </cr-dialog>
   </template>
diff --git a/chrome/browser/resources/settings/site_settings/all_sites.html b/chrome/browser/resources/settings/site_settings/all_sites.html
index eb14758..2b9d1a5c 100644
--- a/chrome/browser/resources/settings/site_settings/all_sites.html
+++ b/chrome/browser/resources/settings/site_settings/all_sites.html
@@ -1,5 +1,6 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_search_field/cr_search_field.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/html/md_select_css.html">
@@ -97,12 +98,12 @@
                 actionMenuModel_.item.etldPlus1)]]
           </div>
           <div slot="button-container">
-            <paper-button class="cancel-button" on-click="onCloseDialog_">
+            <cr-button class="cancel-button" on-click="onCloseDialog_">
               $i18n{cancel}
-            </paper-button>
-            <paper-button class="action-button" on-click="onResetSettings_">
+            </cr-button>
+            <cr-button class="action-button" on-click="onResetSettings_">
               $i18n{siteSettingsSiteResetAll}
-            </paper-button>
+            </cr-button>
           </div>
         </cr-dialog>
       </template>
@@ -121,12 +122,12 @@
                 actionMenuModel_.item.etldPlus1)]]
           </div>
           <div slot="button-container">
-            <paper-button class="cancel-button" on-click="onCloseDialog_">
+            <cr-button class="cancel-button" on-click="onCloseDialog_">
               $i18n{cancel}
-            </paper-button>
-            <paper-button class="action-button" on-click="onClearData_">
+            </cr-button>
+            <cr-button class="action-button" on-click="onClearData_">
               $i18n{siteSettingsSiteClearStorage}
-            </paper-button>
+            </cr-button>
           </div>
         </cr-dialog>
       </template>
diff --git a/chrome/browser/resources/settings/site_settings/edit_exception_dialog.html b/chrome/browser/resources/settings/site_settings/edit_exception_dialog.html
index 3c4e934..2bc85d2 100644
--- a/chrome/browser/resources/settings/site_settings/edit_exception_dialog.html
+++ b/chrome/browser/resources/settings/site_settings/edit_exception_dialog.html
@@ -1,8 +1,8 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../i18n_setup.html">
 <link rel="import" href="site_settings_prefs_browser_proxy.html">
 
@@ -19,12 +19,12 @@
         </cr-input>
       </div>
       <div slot="button-container">
-        <paper-button class="cancel-button" on-click="onCancelTap_"
-            id="cancel">$i18n{cancel}</paper-button>
-        <paper-button id="actionButton" class="action-button"
+        <cr-button class="cancel-button" on-click="onCancelTap_"
+            id="cancel">$i18n{cancel}</cr-button>
+        <cr-button id="actionButton" class="action-button"
             on-click="onActionButtonTap_" disabled="[[invalid_]]">
           $i18n{save}
-        </paper-button>
+        </cr-button>
       </div>
     </cr-dialog>
   </template>
diff --git a/chrome/browser/resources/settings/site_settings/site_data.html b/chrome/browser/resources/settings/site_settings/site_data.html
index ce8abf7..b3c8d9b 100644
--- a/chrome/browser/resources/settings/site_settings/site_data.html
+++ b/chrome/browser/resources/settings/site_settings/site_data.html
@@ -5,6 +5,7 @@
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/html/list_property_update_behavior.html">
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_search_field/cr_search_field.html">
 <link rel="import" href="chrome://resources/cr_elements/icons.html">
@@ -37,11 +38,10 @@
     </style>
     <div class="settings-box continuation">
       <paper-spinner-lite active="[[isLoading_]]"></paper-spinner-lite>
-      <paper-button class="secondary-button"
-          disabled$="[[isLoading_]]" id="removeShowingSites"
+      <cr-button disabled$="[[isLoading_]]" id="removeShowingSites"
           on-click="onRemoveShowingSitesTap_" hidden$="[[!sites.length]]">
         [[computeRemoveLabel_(filter)]]
-      </paper-button>
+      </cr-button>
     </div>
     <iron-list id="list" items="[[sites]]" preserve-focus
         scroll-target="[[subpageScrollTarget]]" class="cr-separators">
@@ -63,12 +63,12 @@
       </div>
       <div slot="body">$i18n{siteSettingsCookieRemoveMultipleConfirmation}</div>
       <div slot="button-container">
-        <paper-button class="cancel-button" on-click="onCloseDialog_">
+        <cr-button class="cancel-button" on-click="onCloseDialog_">
           $i18n{cancel}
-        </paper-button>
-        <paper-button class="action-button" on-click="onConfirmDelete_">
+        </cr-button>
+        <cr-button class="action-button" on-click="onConfirmDelete_">
           $i18n{siteSettingsCookiesClearAll}
-        </paper-button>
+        </cr-button>
       </div>
     </cr-dialog>
   </template>
diff --git a/chrome/browser/resources/settings/site_settings/site_details.html b/chrome/browser/resources/settings/site_settings/site_details.html
index aa91a404f..7c8025fc 100644
--- a/chrome/browser/resources/settings/site_settings/site_details.html
+++ b/chrome/browser/resources/settings/site_settings/site_details.html
@@ -6,6 +6,7 @@
 <link rel="import" href="chrome://resources/html/cr/ui/focus_without_ink.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_icon_button/cr_icon_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_link_row/cr_link_row.html">
 <link rel="import" href="chrome://resources/cr_elements/icons.html">
@@ -51,12 +52,12 @@
         [[i18n('siteSettingsSiteResetConfirmation', pageTitle)]]
       </div>
       <div slot="button-container">
-        <paper-button class="cancel-button" on-click="onCloseDialog_">
+        <cr-button class="cancel-button" on-click="onCloseDialog_">
           $i18n{cancel}
-        </paper-button>
-        <paper-button class="action-button" on-click="onResetSettings_">
+        </cr-button>
+        <cr-button class="action-button" on-click="onResetSettings_">
           $i18n{siteSettingsSiteResetAll}
-        </paper-button>
+        </cr-button>
       </div>
     </cr-dialog>
 
@@ -70,12 +71,12 @@
         [[i18n('siteSettingsSiteClearStorageConfirmation', pageTitle)]]
       </div>
       <div slot="button-container">
-        <paper-button class="cancel-button" on-click="onCloseDialog_">
+        <cr-button class="cancel-button" on-click="onCloseDialog_">
           $i18n{cancel}
-        </paper-button>
-        <paper-button class="action-button" on-click="onClearStorage_">
+        </cr-button>
+        <cr-button class="action-button" on-click="onClearStorage_">
           $i18n{siteSettingsSiteClearStorage}
-        </paper-button>
+        </cr-button>
       </div>
     </cr-dialog>
 
@@ -98,23 +99,22 @@
               </div>
               <div hidden$="[[!numCookies_]]">[[numCookies_]]</div>
             </div>
-            <paper-button class="secondary-button" id="clearStorage"
-                role="button" aria-disabled="false"
+            <cr-button id="clearStorage" role="button" aria-disabled="false"
                 on-click="onConfirmClearStorage_"
                 aria-label="$i18n{siteSettingsDelete}">
               $i18n{siteSettingsDelete}
-            </paper-button>
+            </cr-button>
           </div>
         </div>
       </div>
 
       <div class="settings-box first">
         <h2 class="start">$i18n{siteSettingsPermissions}</h2>
-        <paper-button id="resetSettingsButton"
-            class="secondary-button header-aligned-button" role="button"
-            aria-disabled="false" on-click="onConfirmClearSettings_">
+        <cr-button id="resetSettingsButton" class="header-aligned-button"
+            role="button" aria-disabled="false"
+            on-click="onConfirmClearSettings_">
           $i18n{siteSettingsReset}
-        </paper-button>
+        </cr-button>
       </div>
     </template>
     <div class$="list-frame [[permissionListClass_(enableSiteSettings_)]]">
diff --git a/chrome/browser/resources/settings/site_settings/site_list.html b/chrome/browser/resources/settings/site_settings/site_list.html
index 1d6af8c..a07b8c0 100644
--- a/chrome/browser/resources/settings/site_settings/site_list.html
+++ b/chrome/browser/resources/settings/site_settings/site_list.html
@@ -3,6 +3,7 @@
 <link rel="import" href="chrome://resources/html/assert.html">
 <link rel="import" href="chrome://resources/html/cr/ui/focus_without_ink.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_pref_indicator.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
@@ -31,11 +32,10 @@
     <div id="category">
       <div class="settings-box first">
         <h2 class="start">[[categoryHeader]]</h2>
-        <paper-button id="addSite"
-            class="secondary-button header-aligned-button"
+        <cr-button id="addSite" class="header-aligned-button"
             hidden="[[readOnlyList]]" on-click="onAddSiteTap_">
           $i18n{add}
-        </paper-button>
+        </cr-button>
       </div>
 
       <cr-action-menu>
diff --git a/chrome/browser/resources/settings/system_page/system_page.html b/chrome/browser/resources/settings/system_page/system_page.html
index 256673d..720015c 100644
--- a/chrome/browser/resources/settings/system_page/system_page.html
+++ b/chrome/browser/resources/settings/system_page/system_page.html
@@ -1,8 +1,8 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_icon_button/cr_icon_button.html">
 <link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_pref_indicator.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../controls/extension_controlled_indicator.html">
 <link rel="import" href="../controls/settings_toggle_button.html">
 <link rel="import" href="../lifetime_browser_proxy.html">
@@ -24,9 +24,9 @@
         label="$i18n{hardwareAccelerationLabel}">
       <template is="dom-if" if="[[shouldShowRestart_(
           prefs.hardware_acceleration_mode.enabled.value)]]">
-        <paper-button on-click="onRestartTap_" slot="more-actions">
+        <cr-button on-click="onRestartTap_" slot="more-actions">
           $i18n{restart}
-        </paper-button>
+        </cr-button>
       </template>
     </settings-toggle-button>
     <div id="proxy" class="settings-box" on-click="onProxyTap_"
diff --git a/chrome/browser/resources/usb_internals/descriptor_panel.js b/chrome/browser/resources/usb_internals/descriptor_panel.js
index 4bb19f0..ac18374b 100644
--- a/chrome/browser/resources/usb_internals/descriptor_panel.js
+++ b/chrome/browser/resources/usb_internals/descriptor_panel.js
@@ -132,104 +132,18 @@
     }
 
     /**
-     * Adds a display area which contains a tree view and a byte view.
-     * @param {string=} descriptorPanelTitle
-     * @return {{rawDataTreeRoot:!cr.ui.Tree,rawDataByteElement:!HTMLElement}}
-     * @private
-     */
-    addNewDescriptorDisplayElement_(descriptorPanelTitle = undefined) {
-      const descriptorPanelTemplate =
-          document.querySelector('#descriptor-panel-template');
-      const descriptorPanelClone =
-          document.importNode(descriptorPanelTemplate.content, true);
-
-      /** @private {!HTMLElement} */
-      const rawDataTreeRoot =
-          descriptorPanelClone.querySelector('.raw-data-tree-view');
-      /** @private {!HTMLElement} */
-      const rawDataByteElement =
-          descriptorPanelClone.querySelector('.raw-data-byte-view');
-
-      cr.ui.decorate(rawDataTreeRoot, cr.ui.Tree);
-      rawDataTreeRoot.detail = {payload: {}, children: {}};
-
-      if (descriptorPanelTitle) {
-        const descriptorPanelTitleTemplate =
-            document.querySelector('#descriptor-panel-title');
-        const clone =
-            document.importNode(descriptorPanelTitleTemplate.content, true)
-                .querySelector('descriptorpaneltitle');
-        clone.textContent = descriptorPanelTitle;
-        this.rootElement_.appendChild(clone);
-      }
-      this.rootElement_.appendChild(descriptorPanelClone);
-      return {rawDataTreeRoot, rawDataByteElement};
-    }
-
-    /**
      * Clears the data first before populating it with the new content.
      */
     clearView() {
       this.rootElement_.querySelectorAll('descriptorpanel')
           .forEach(el => el.remove());
       this.rootElement_.querySelectorAll('error').forEach(el => el.remove());
+      this.rootElement_.querySelectorAll('warn').forEach(el => el.remove());
       this.rootElement_.querySelectorAll('descriptorpaneltitle')
           .forEach(el => el.remove());
     }
 
     /**
-     * Renders a tree view to display the raw data in readable text.
-     * @param {!cr.ui.Tree|!cr.ui.TreeItem} root
-     * @param {!HTMLElement} rawDataByteElement
-     * @param {!Array<Object>} fields
-     * @param {!Uint8Array} rawData
-     * @param {number} offset The start offset of the descriptor structure that
-     *     want to be rendered.
-     * @param {...string} parentClassNames
-     * @return {number} The end offset of descriptor structure that want to be
-     *     rendered.
-     * @private
-     */
-    renderRawDataTree_(
-        root, rawDataByteElement, fields, rawData, offset,
-        ...parentClassNames) {
-      const rawDataByteElements = rawDataByteElement.querySelectorAll('span');
-
-      for (const field of fields) {
-        const className = `field-offset-${offset}`;
-        let item;
-        try {
-          item = customTreeItem(
-              `${field.label}${field.formatter(rawData, offset)}`, className);
-
-          for (let i = 0; i < field.size; i++) {
-            rawDataByteElements[offset + i].classList.add(className);
-            for (const parentClassName of parentClassNames) {
-              rawDataByteElements[offset + i].classList.add(parentClassName);
-            }
-          }
-        } catch (e) {
-          this.showError_(`Field at offset ${offset} is invalid.`);
-          break;
-        }
-
-        try {
-          if (field.extraTreeItemFormatter) {
-            field.extraTreeItemFormatter(rawData, offset, item, field.label);
-          }
-        } catch (e) {
-          this.showError_(
-              `Error at rendering field at index ${offset}: ${e.message}`);
-        }
-
-        root.add(item);
-        offset += field.size;
-      }
-
-      return offset;
-    }
-
-    /**
      * Adds a button for getting string descriptor to the string descriptor
      * index item, and adds an autocomplete value to the index input area in
      * the string descriptor panel.
@@ -243,7 +157,7 @@
       const index = rawData[offset];
       if (index > 0) {
         if (!this.stringDescriptorPanel_.stringDescriptorIndexes.has(index)) {
-          const optionElement = cr.doc.createElement('option');
+          const optionElement = document.createElement('option');
           optionElement.label = index;
           optionElement.value = index;
           this.stringDescriptorPanel_.indexesListElement.appendChild(
@@ -255,7 +169,7 @@
         const buttonTemplate = document.querySelector('#raw-data-tree-button');
         const button = document.importNode(buttonTemplate.content, true)
                            .querySelector('button');
-        item.querySelector('.tree-row').appendChild(button);
+        item.labelElement.appendChild(button);
         button.addEventListener('click', (event) => {
           event.stopPropagation();
           // Clear the previous string descriptors.
@@ -267,8 +181,10 @@
       } else if (index < 0) {
         // Delete the ': ' in fieldLabel.
         const fieldName = fieldLabel.slice(0, -2);
-        this.showError_(`Invalid String Descriptor occurs in field ${
-            fieldName} of this descriptor.`);
+        showError(
+            `Invalid String Descriptor occurs in field ${
+                fieldName} of this descriptor.`,
+            this.rootElement_);
       }
     }
 
@@ -324,7 +240,7 @@
       const buttonTemplate = document.querySelector('#raw-data-tree-button');
       const button = document.importNode(buttonTemplate.content, true)
                          .querySelector('button');
-      item.querySelector('.tree-row').appendChild(button);
+      item.labelElement.appendChild(button);
       button.addEventListener('click', async (event) => {
         event.stopPropagation();
         // Clear all the descriptor display elements except the first one, which
@@ -363,7 +279,7 @@
         const buttonTemplate = document.querySelector('#raw-data-tree-button');
         const button = document.importNode(buttonTemplate.content, true)
                            .querySelector('button');
-        item.querySelector('.tree-row').appendChild(button);
+        item.labelElement.appendChild(button);
         button.addEventListener('click', async (event) => {
           event.stopPropagation();
           await this.sendMsOs20DescriptorSetAltEnumCommand_(
@@ -415,79 +331,6 @@
     }
 
     /**
-     * Checks if the status of a control transfer indicates success.
-     * @param {number} status
-     * @param {string} defaultMessage
-     * @private
-     */
-    checkTransferSuccess_(status, defaultMessage) {
-      let failReason = '';
-      switch (status) {
-        case device.mojom.UsbTransferStatus.COMPLETED:
-          return;
-        case device.mojom.UsbTransferStatus.SHORT_PACKET:
-          this.showError_('Descriptor is too short.');
-          return;
-        case device.mojom.UsbTransferStatus.BABBLE:
-          this.showError_('Descriptor is too long.');
-          return;
-        case device.mojom.UsbTransferStatus.TRANSFER_ERROR:
-          failReason = 'Transfer Error';
-          break;
-        case device.mojom.UsbTransferStatus.TIMEOUT:
-          failReason = 'Timeout';
-          break;
-        case device.mojom.UsbTransferStatus.CANCELLED:
-          failReason = 'Transfer was cancelled';
-          break;
-        case device.mojom.UsbTransferStatus.STALLED:
-          failReason = 'Transfer Error';
-          break;
-        case device.mojom.UsbTransferStatus.DISCONNECT:
-          failReason = 'Transfer stalled';
-          break;
-        case device.mojom.UsbTransferStatus.PERMISSION_DENIED:
-          failReason = 'Permission denied';
-          break;
-      }
-      // Throws an error to stop rendering descriptor.
-      throw new Error(`${defaultMessage} (Reason: ${failReason})`);
-    }
-
-    /**
-     * Shows an error message if error occurs in getting or rendering
-     * descriptors.
-     * @param {string} message
-     * @private
-     */
-    showError_(message) {
-      const errorTemplate = document.querySelector('#error');
-
-      const clone = document.importNode(errorTemplate.content, true);
-
-      const errorText = clone.querySelector('error');
-      errorText.textContent = message;
-
-      this.rootElement_.prepend(clone);
-    }
-
-    /**
-     * Shows an warning message.
-     * @param {string} message
-     * @private
-     */
-    showWarn_(message) {
-      const warnTemplate = document.querySelector('#warn');
-
-      const clone = document.importNode(warnTemplate.content, true);
-
-      const warnText = clone.querySelector('warn');
-      warnText.textContent = message;
-
-      this.rootElement_.prepend(clone);
-    }
-
-    /**
      * Gets device descriptor of current device.
      * @return {!Uint8Array}
      * @private
@@ -507,8 +350,9 @@
           usbControlTransferParams, DEVICE_DESCRIPTOR_LENGTH,
           CONTROL_TRANSFER_TIMEOUT_MS);
 
-      this.checkTransferSuccess_(
-          response.status, 'Failed to read the device descriptor.');
+      checkTransferSuccess(
+          response.status, 'Failed to read the device descriptor.',
+          this.rootElement_);
 
       return new Uint8Array(response.data);
     }
@@ -523,7 +367,7 @@
         await this.usbDeviceProxy_.open();
         rawData = await this.getDeviceDescriptor_();
       } catch (e) {
-        this.showError_(e.message);
+        showError(e.message, this.rootElement_);
         // Stop rendering if failed to read the device descriptor.
         return;
       } finally {
@@ -606,7 +450,7 @@
         },
       ];
 
-      const displayElement = this.addNewDescriptorDisplayElement_();
+      const displayElement = addNewDescriptorDisplayElement(this.rootElement_);
       /** @type {!cr.ui.Tree} */
       const rawDataTreeRoot = displayElement.rawDataTreeRoot;
       /** @type {!HTMLElement} */
@@ -614,8 +458,9 @@
 
       renderRawDataBytes(rawDataByteElement, rawData);
 
-      this.renderRawDataTree_(
-          rawDataTreeRoot, rawDataByteElement, fields, rawData, 0);
+      renderRawDataTree(
+          rawDataTreeRoot, rawDataByteElement, fields, rawData, 0,
+          this.rootElement_);
 
       addMappingAction(rawDataTreeRoot, rawDataByteElement);
 
@@ -644,10 +489,11 @@
           usbControlTransferParams, CONFIGURATION_DESCRIPTOR_LENGTH,
           CONTROL_TRANSFER_TIMEOUT_MS);
 
-      this.checkTransferSuccess_(
+      checkTransferSuccess(
           response.status,
           'Failed to read the device configuration descriptor to determine ' +
-              'the total descriptor length.');
+              'the total descriptor length.',
+          this.rootElement_);
 
       const data = new DataView(new Uint8Array(response.data).buffer);
       const length =
@@ -656,9 +502,10 @@
       response = await this.usbDeviceProxy_.controlTransferIn(
           usbControlTransferParams, length, CONTROL_TRANSFER_TIMEOUT_MS);
 
-      this.checkTransferSuccess_(
+      checkTransferSuccess(
           response.status,
-          'Failed to read the complete configuration descriptor.');
+          'Failed to read the complete configuration descriptor.',
+          this.rootElement_);
 
       return new Uint8Array(response.data);
     }
@@ -673,7 +520,7 @@
         await this.usbDeviceProxy_.open();
         rawData = await this.getConfigurationDescriptor_();
       } catch (e) {
-        this.showError_(e.message);
+        showError(e.message, this.rootElement_);
         // Stop rendering if failed to read the configuration descriptor.
         return;
       } finally {
@@ -724,7 +571,7 @@
         },
       ];
 
-      const displayElement = this.addNewDescriptorDisplayElement_();
+      const displayElement = addNewDescriptorDisplayElement(this.rootElement_);
       /** @type {!cr.ui.Tree} */
       const rawDataTreeRoot = displayElement.rawDataTreeRoot;
       /** @type {!HTMLElement} */
@@ -735,12 +582,14 @@
       const expectNumInterfaces =
           rawData[CONFIGURATION_DESCRIPTOR_NUM_INTERFACES_OFFSET];
 
-      let offset = this.renderRawDataTree_(
-          rawDataTreeRoot, rawDataByteElement, fields, rawData, 0);
+      let offset = renderRawDataTree(
+          rawDataTreeRoot, rawDataByteElement, fields, rawData, 0,
+          this.rootElement_);
 
       if (offset !== CONFIGURATION_DESCRIPTOR_LENGTH) {
-        this.showError_(
-            'An error occurred while rendering configuration descriptor.');
+        showError(
+            'An error occurred while rendering configuration descriptor.',
+            this.rootElement_);
       }
 
       let indexInterface = 0;
@@ -775,15 +624,17 @@
       }
 
       if (expectNumInterfaces !== indexInterface) {
-        this.showError_(`Expected to find ${
-            expectNumInterfaces} interface descriptors but only encountered ${
-            indexInterface}.`);
+        showError(
+            `Expected to find ${expectNumInterfaces} interface descriptors ` +
+                `but only encountered ${indexInterface}.`,
+            this.rootElement_);
       }
 
       if (expectNumEndpoints !== indexEndpoint) {
-        this.showError_(`Expected to find ${
-            expectNumEndpoints} interface descriptors but only encountered ${
-            indexEndpoint}.`);
+        showError(
+            `Expected to find ${expectNumEndpoints} endpoint descriptors but` +
+                ` only encountered ${indexEndpoint}.`,
+            this.rootElement_);
       }
 
       addMappingAction(rawDataTreeRoot, rawDataByteElement);
@@ -806,8 +657,10 @@
         rawDataTreeRoot, rawDataByteElement, rawData, originalOffset,
         indexInterface, expectNumEndpoints) {
       if (originalOffset + INTERFACE_DESCRIPTOR_LENGTH > rawData.length) {
-        this.showError_(`Failed to read the interface descriptor at index ${
-            indexInterface}.`);
+        showError(
+            `Failed to read the interface descriptor at index ${
+                indexInterface}.`,
+            this.rootElement_);
       }
 
       const parentClassName = `descriptor-interface-${indexInterface}`;
@@ -867,14 +720,15 @@
       expectNumEndpoints +=
           rawData[originalOffset + INTERFACE_DESCRIPTOR_NUM_ENDPOINTS_OFFSET];
 
-      const offset = this.renderRawDataTree_(
+      const offset = renderRawDataTree(
           interfaceItem, rawDataByteElement, fields, rawData, originalOffset,
-          parentClassName);
+          this.rootElement_, parentClassName);
 
       if (offset !== originalOffset + INTERFACE_DESCRIPTOR_LENGTH) {
-        this.showError_(
+        showError(
             `An error occurred while rendering interface descriptor at index ${
-                indexInterface}.`);
+                indexInterface}.`,
+            this.rootElement_);
       }
 
       return [offset, expectNumEndpoints];
@@ -896,8 +750,9 @@
         rawDataTreeRoot, rawDataByteElement, rawData, originalOffset,
         indexEndpoint) {
       if (originalOffset + ENDPOINT_DESCRIPTOR_LENGTH > rawData.length) {
-        this.showError_(`Failed to read the endpoint descriptor at index ${
-            indexEndpoint}.`);
+        showError(
+            `Failed to read the endpoint descriptor at index ${indexEndpoint}.`,
+            this.rootElement_);
       }
 
       const parentClassName = `descriptor-endpoint-${indexEndpoint}`;
@@ -938,14 +793,15 @@
         },
       ];
 
-      const offset = this.renderRawDataTree_(
+      const offset = renderRawDataTree(
           endpointItem, rawDataByteElement, fields, rawData, originalOffset,
-          parentClassName);
+          this.rootElement_, parentClassName);
 
       if (offset !== originalOffset + ENDPOINT_DESCRIPTOR_LENGTH) {
-        this.showError_(
+        showError(
             `An error occurred while rendering endpoint descriptor at index ${
-                indexEndpoint}.`);
+                indexEndpoint}.`,
+            this.rootElement_);
       }
 
       return offset;
@@ -969,8 +825,9 @@
           rawData[originalOffset + STANDARD_DESCRIPTOR_LENGTH_OFFSET];
 
       if (originalOffset + length > rawData.length) {
-        this.showError_(
-            `Failed to read the unknown descriptor at index ${indexUnknown}.`);
+        showError(
+            `Failed to read the unknown descriptor at index ${indexUnknown}.`,
+            this.rootElement_);
         return;
       }
 
@@ -992,7 +849,7 @@
         },
       ];
 
-      let offset = this.renderRawDataTree_(
+      let offset = renderRawDataTree(
           unknownItem, rawDataByteElement, fields, rawData, originalOffset,
           parentClassName);
 
@@ -1031,12 +888,13 @@
             usbControlTransferParams, MAX_STRING_DESCRIPTOR_LENGTH,
             CONTROL_TRANSFER_TIMEOUT_MS);
 
-        this.checkTransferSuccess_(
+        checkTransferSuccess(
             response.status,
             'Failed to read the device string descriptor to determine ' +
-                'all supported languages.');
+                'all supported languages.',
+            this.rootElement_);
       } catch (e) {
-        this.showError_(e.message);
+        showError(e.message, this.rootElement_);
         // Stop rendering autocomplete datalist if failed to read the string
         // descriptor.
         return new Uint8Array();
@@ -1047,7 +905,7 @@
       const responseData = new Uint8Array(response.data);
       this.languageCodesListElement_.innerText = '';
 
-      const optionAllElement = cr.doc.createElement('option');
+      const optionAllElement = document.createElement('option');
       optionAllElement.value = 'All';
       this.languageCodesListElement_.appendChild(optionAllElement);
 
@@ -1056,7 +914,7 @@
       for (let i = 2; i < responseData.length; i += 2) {
         const languageCode = parseShort(responseData, i);
 
-        const optionElement = cr.doc.createElement('option');
+        const optionElement = document.createElement('option');
         optionElement.label = parseLanguageCode(languageCode);
         optionElement.value = `0x${toHex(languageCode, 4)}`;
 
@@ -1094,10 +952,11 @@
           CONTROL_TRANSFER_TIMEOUT_MS);
 
       const languageCodeStr = parseLanguageCode(languageCode);
-      this.checkTransferSuccess_(
+      checkTransferSuccess(
           response.status,
           `Failed to read the device string descriptor of index: ${
-              index}, language: ${languageCodeStr}.`);
+              index}, language: ${languageCodeStr}.`,
+          this.rootElement_);
 
       const rawData = new Uint8Array(response.data);
       return {languageCodeStr, rawData};
@@ -1122,7 +981,7 @@
         rawDataMap =
             await this.getStringDescriptorForLanguageCode_(index, languageCode);
       } catch (e) {
-        this.showError_(e.message);
+        showError(e.message, this.rootElement_);
         // Stop rendering if failed to read the string descriptor.
         return;
       } finally {
@@ -1134,8 +993,10 @@
 
       const length = rawData[STANDARD_DESCRIPTOR_LENGTH_OFFSET];
       if (length > rawData.length) {
-        this.showError_(`Failed to read the string descriptor at index ${
-            index} in ${languageStr}.`);
+        showError(
+            `Failed to read the string descriptor at index ${index} in ${
+                languageStr}.`,
+            this.rootElement_);
         return;
       }
 
@@ -1162,7 +1023,7 @@
         fields.push(field);
       }
 
-      const displayElement = this.addNewDescriptorDisplayElement_();
+      const displayElement = addNewDescriptorDisplayElement(this.rootElement_);
       /** @type {!cr.ui.Tree} */
       const rawDataTreeRoot = displayElement.rawDataTreeRoot;
       /** @type {!HTMLElement} */
@@ -1182,9 +1043,9 @@
 
       renderRawDataBytes(rawDataByteElement, rawData);
 
-      this.renderRawDataTree_(
+      renderRawDataTree(
           stringDescriptorItem, rawDataByteElement, fields, rawData, 0,
-          parentClassName);
+          this.rootElement_, parentClassName);
 
       addMappingAction(rawDataTreeRoot, rawDataByteElement);
     }
@@ -1276,10 +1137,11 @@
           usbControlTransferParams, BOS_DESCRIPTOR_HEADER_LENGTH,
           CONTROL_TRANSFER_TIMEOUT_MS);
 
-      this.checkTransferSuccess_(
+      checkTransferSuccess(
           response.status,
           'Failed to read the device BOS descriptor to determine ' +
-              'the total descriptor length.');
+              'the total descriptor length.',
+          this.rootElement_);
 
       const data = new DataView(new Uint8Array(response.data).buffer);
       const length = data.getUint16(BOS_DESCRIPTOR_TOTAL_LENGTH_OFFSET, true);
@@ -1288,8 +1150,9 @@
       response = await this.usbDeviceProxy_.controlTransferIn(
           usbControlTransferParams, length, CONTROL_TRANSFER_TIMEOUT_MS);
 
-      this.checkTransferSuccess_(
-          response.status, 'Failed to read the complete BOS descriptor.');
+      checkTransferSuccess(
+          response.status, 'Failed to read the complete BOS descriptor.',
+          this.rootElement_);
 
       return new Uint8Array(response.data);
     }
@@ -1304,7 +1167,7 @@
         await this.usbDeviceProxy_.open();
         rawData = await this.getBosDescriptor_();
       } catch (e) {
-        this.showError_(e.message);
+        showError(e.message, this.rootElement_);
         // Stop rendering if failed to read the BOS descriptor.
         return;
       } finally {
@@ -1334,7 +1197,7 @@
         },
       ];
 
-      const displayElement = this.addNewDescriptorDisplayElement_();
+      const displayElement = addNewDescriptorDisplayElement(this.rootElement_);
       /** @type {!cr.ui.Tree} */
       const rawDataTreeRoot = displayElement.rawDataTreeRoot;
       /** @type {!HTMLElement} */
@@ -1342,17 +1205,18 @@
 
       renderRawDataBytes(rawDataByteElement, rawData);
 
-      let offset = this.renderRawDataTree_(
+      let offset = renderRawDataTree(
           rawDataTreeRoot, rawDataByteElement, fields, rawData, 0);
 
       if (offset !== BOS_DESCRIPTOR_HEADER_LENGTH) {
-        this.showError_(
-            'An error occurred while rendering BOS descriptor header.');
+        showError(
+            'An error occurred while rendering BOS descriptor header.',
+            this.rootElement_);
       }
 
       let indexWebUsb = 0;
       let indexMsOs20 = 0;
-      let indexUnknownBos = 0;
+      let indexUnknownDevCapability = 0;
       // Continue parsing while there are still unparsed device capability
       // descriptors. Stop if accessing the device capability type would cause
       // us to read past the end of the buffer.
@@ -1379,20 +1243,21 @@
           default:
             offset = this.renderUnknownBosDescriptor_(
                 rawDataTreeRoot, rawDataByteElement, rawData, offset,
-                indexUnknownBos);
-            indexUnknownBos++;
+                indexUnknownDevCapability);
+            indexUnknownDevCapability++;
         }
       }
 
-      const expectNumBosDescriptors =
+      const expectNumDevCapabilityDescriptors =
           rawData[BOS_DESCRIPTOR_NUM_DEVICE_CAPABILITIES_OFFSET];
       const encounteredNumBosDescriptors =
-          indexWebUsb + indexMsOs20 + indexUnknownBos;
-      if (encounteredNumBosDescriptors !== expectNumBosDescriptors) {
-        this.showError_(
-            `Expected to find ${expectNumBosDescriptors} ` +
-            `interface descriptors but only encountered ` +
-            `${encounteredNumBosDescriptors}.`);
+          indexWebUsb + indexMsOs20 + indexUnknownDevCapability;
+      if (encounteredNumBosDescriptors !== expectNumDevCapabilityDescriptors) {
+        showError(
+            `Expected to find ${expectNumDevCapabilityDescriptors} ` +
+                `device capability Descriptors but only encountered ` +
+                `${encounteredNumBosDescriptors}.`,
+            this.rootElement_);
       }
 
       addMappingAction(rawDataTreeRoot, rawDataByteElement);
@@ -1414,8 +1279,9 @@
         rawDataTreeRoot, rawDataByteElement, rawData, originalOffset,
         indexWebUsb) {
       if (originalOffset + WEB_USB_DESCRIPTOR_LENGTH > rawData.length) {
-        this.showError_(
-            `Failed to read the WebUSB descriptor at index ${indexWebUsb}.`);
+        showError(
+            `Failed to read the WebUSB descriptor at index ${indexWebUsb}.`,
+            this.rootElement_);
       }
 
       const parentClassName = `descriptor-webusb-${indexWebUsb}`;
@@ -1469,14 +1335,15 @@
         },
       ];
 
-      const offset = this.renderRawDataTree_(
+      const offset = renderRawDataTree(
           webUsbItem, rawDataByteElement, fields, rawData, originalOffset,
-          parentClassName);
+          this.rootElement_, parentClassName);
 
       if (offset !== originalOffset + WEB_USB_DESCRIPTOR_LENGTH) {
-        this.showError_(
+        showError(
             `An error occurred while rendering WebUSB descriptor at index ${
-                indexWebUsb}.`);
+                indexWebUsb}.`,
+            this.rootElement_);
       }
 
       return offset;
@@ -1498,9 +1365,10 @@
         rawDataTreeRoot, rawDataByteElement, rawData, originalOffset,
         indexMsOs20) {
       if (originalOffset + PLATFORM_DESCRIPTOR_HEADER_LENGTH > rawData.length) {
-        this.showError_(
+        showError(
             `Failed to read the Microsoft OS 2.0 descriptor at index ${
-                indexMsOs20}.`);
+                indexMsOs20}.`,
+            this.rootElement_);
       }
 
       const parentClassName = `descriptor-ms-os-20-${indexMsOs20}`;
@@ -1538,14 +1406,15 @@
       const msOs20DescriptorLength =
           rawData[originalOffset + STANDARD_DESCRIPTOR_LENGTH_OFFSET];
 
-      let offset = this.renderRawDataTree_(
+      let offset = renderRawDataTree(
           msOs20Item, rawDataByteElement, fields, rawData, originalOffset,
-          parentClassName);
+          this.rootElement_, parentClassName);
 
       if (offset !== originalOffset + PLATFORM_DESCRIPTOR_HEADER_LENGTH) {
-        this.showError_(
+        showError(
             `An error occurred while rendering Microsoft OS 2.0 descriptor at` +
-            ` index ${indexMsOs20}.`);
+                ` index ${indexMsOs20}.`,
+            this.rootElement_);
       }
 
       let indexMsOs20DescriptorSetInfo = 0;
@@ -1562,9 +1431,10 @@
       }
 
       if (offset !== originalOffset + msOs20DescriptorLength) {
-        this.showError_(
+        showError(
             `An error occurred while rendering Microsoft OS 2.0 descriptor at` +
-            ` index ${indexMsOs20}.`);
+                ` index ${indexMsOs20}.`,
+            this.rootElement_);
       }
 
       return offset;
@@ -1588,9 +1458,10 @@
         indexMsOs20DescriptorSetInfo, indexMsOs20) {
       if (originalOffset + MS_OS_20_DESCRIPTOR_SET_INFORMATION_LENGTH >
           rawData.length) {
-        this.showError_(
+        showError(
             `Failed to read the Microsoft OS 2.0 descriptor set information ` +
-            `at index ${indexMsOs20DescriptorSetInfo}.`);
+                `at index ${indexMsOs20DescriptorSetInfo}.`,
+            this.rootElement_);
       }
 
       const parentClassName =
@@ -1630,39 +1501,42 @@
         },
       ];
 
-      const offset = this.renderRawDataTree_(
+      const offset = renderRawDataTree(
           msOs20SetInfoItem, rawDataByteElement, fields, rawData,
-          originalOffset, parentClassName,
+          originalOffset, this.rootElement_, parentClassName,
           `descriptor-ms-os-20-${indexMsOs20}`);
 
       if (offset !==
           originalOffset + MS_OS_20_DESCRIPTOR_SET_INFORMATION_LENGTH) {
-        this.showError_(
+        showError(
             `An error occurred while rendering Microsoft OS 2.0 descriptor ` +
-            `set information at index ${indexMsOs20DescriptorSetInfo}.`);
+                `set information at index ${indexMsOs20DescriptorSetInfo}.`,
+            this.rootElement_);
       }
 
       return offset;
     }
 
     /**
-     * Renders a tree item to display unknown BOS descriptor at indexUnknownBos
+     * Renders a tree item to display unknown device capability descriptor at
+     * indexUnknownDevCapability
      * @param {!cr.ui.Tree} rawDataTreeRoot
      * @param {!HTMLElement} rawDataByteElement
      * @param {!Uint8Array} rawData
      * @param {number} originalOffset The start offset of the unknown BOS
      *     descriptor.
-     * @param {number} indexUnknownBos
+     * @param {number} indexUnknownDevCapability
      * @return {number}
      * @private
      */
     renderUnknownBosDescriptor_(
         rawDataTreeRoot, rawDataByteElement, rawData, originalOffset,
-        indexUnknownBos) {
+        indexUnknownDevCapability) {
       const length =
           rawData[originalOffset + STANDARD_DESCRIPTOR_LENGTH_OFFSET];
 
-      const parentClassName = `descriptor-unknownbos-${indexUnknownBos}`;
+      const parentClassName =
+          `descriptor-unknownbos-${indexUnknownDevCapability}`;
       const unknownBosItem =
           customTreeItem(`Unknown BOS Descriptor`, parentClassName);
       rawDataTreeRoot.add(unknownBosItem);
@@ -1685,9 +1559,9 @@
         },
       ];
 
-      let offset = this.renderRawDataTree_(
+      let offset = renderRawDataTree(
           unknownBosItem, rawDataByteElement, fields, rawData, originalOffset,
-          parentClassName);
+          this.rootElement_, parentClassName);
 
       const rawDataByteElements = rawDataByteElement.querySelectorAll('span');
 
@@ -1727,10 +1601,11 @@
             usbControlTransferParams, MAX_URL_DESCRIPTOR_LENGTH,
             CONTROL_TRANSFER_TIMEOUT_MS);
 
-        this.checkTransferSuccess_(
-            urlResponse.status, 'Failed to read the device URL descriptor.');
+        checkTransferSuccess(
+            urlResponse.status, 'Failed to read the device URL descriptor.',
+            this.rootElement_);
       } catch (e) {
-        this.showError_(e.message);
+        showError(e.message, this.rootElement_);
         // Stops parsing to string format URL if failed to read the URL
         // descriptor.
         return '';
@@ -1786,11 +1661,12 @@
             usbControlTransferParams, msOs20DescriptorSetLength,
             CONTROL_TRANSFER_TIMEOUT_MS);
 
-        this.checkTransferSuccess_(
+        checkTransferSuccess(
             response.status,
-            'Failed to read the Microsoft OS 2.0 descriptor set.');
+            'Failed to read the Microsoft OS 2.0 descriptor set.',
+            this.rootElement_);
       } catch (e) {
-        this.showError_(e.message);
+        showError(e.message, this.rootElement_);
         // Returns an empty array if failed to read the Microsoft OS 2.0
         // descriptor set.
         return new Uint8Array();
@@ -1828,12 +1704,13 @@
         const response = await this.usbDeviceProxy_.controlTransferOut(
             usbControlTransferParams, [], CONTROL_TRANSFER_TIMEOUT_MS);
 
-        this.checkTransferSuccess_(
+        checkTransferSuccess(
             response.status,
-            'Failed to read the Microsoft OS 2.0 ' +
-                'descriptor alternate enumeration set.');
+            'Failed to read the Microsoft OS 2.0 descriptor ' +
+                'alternate enumeration set.',
+            this.rootElement_);
       } catch (e) {
-        this.showError_(e.message);
+        showError(e.message, this.rootElement_);
       } finally {
         await this.usbDeviceProxy_.close();
       }
@@ -1846,8 +1723,8 @@
      * @private
      */
     renderMsOs20DescriptorSet_(msOs20RawData) {
-      const displayElement = this.addNewDescriptorDisplayElement_(
-          'Microsoft OS 2.0 Descriptor Set');
+      const displayElement = addNewDescriptorDisplayElement(
+          this.rootElement_, 'Microsoft OS 2.0 Descriptor Set');
       /** @type {!cr.ui.Tree} */
       const rawDataTreeRoot = displayElement.rawDataTreeRoot;
       /** @type {!HTMLElement} */
@@ -1969,13 +1846,15 @@
         },
       ];
 
-      const offset = this.renderRawDataTree_(
-          rawDataTreeRoot, rawDataByteElement, fields, rawData, originalOffset);
+      const offset = renderRawDataTree(
+          rawDataTreeRoot, rawDataByteElement, fields, rawData, originalOffset,
+          this.rootElement_);
 
       if (offset !== originalOffset + length) {
-        this.showError_(
+        showError(
             'An error occurred while rendering Microsoft OS 2.0 Descriptor ' +
-            'Set header.');
+                'Set header.',
+            this.rootElement_);
       }
 
       return offset;
@@ -2034,14 +1913,15 @@
         },
       ];
 
-      const offset = this.renderRawDataTree_(
+      const offset = renderRawDataTree(
           item, rawDataByteElement, fields, rawData, originalOffset,
           parentClassName);
 
       if (offset !== originalOffset + length) {
-        this.showError_(
+        showError(
             'An error occurred while rendering Microsoft OS 2.0 ' +
-            'Configuration Subset Header.');
+                'Configuration Subset Header.',
+            this.rootElement_);
       }
 
       return offset;
@@ -2098,14 +1978,15 @@
         },
       ];
 
-      const offset = this.renderRawDataTree_(
+      const offset = renderRawDataTree(
           item, rawDataByteElement, fields, rawData, originalOffset,
           parentClassName);
 
       if (offset !== originalOffset + length) {
-        this.showError_(
+        showError(
             'An error occurred while rendering Microsoft OS 2.0 ' +
-            'Function Subset Header.');
+                'Function Subset Header.',
+            this.rootElement_);
       }
 
       return offset;
@@ -2157,14 +2038,15 @@
         },
       ];
 
-      const offset = this.renderRawDataTree_(
+      const offset = renderRawDataTree(
           item, rawDataByteElement, fields, rawData, originalOffset,
           parentClassName);
 
       if (offset !== originalOffset + length) {
-        this.showError_(
+        showError(
             'An error occurred while rendering Microsoft OS 2.0 ' +
-            'Compatible ID Descriptor.');
+                'Compatible ID Descriptor.',
+            this.rootElement_);
       }
 
       return offset;
@@ -2233,9 +2115,9 @@
         },
       ];
 
-      let offset = this.renderRawDataTree_(
+      let offset = renderRawDataTree(
           item, rawDataByteElement, fields, rawData, originalOffset,
-          parentClassName);
+          this.rootElement_, parentClassName);
 
       while (offset < originalOffset + length) {
         const propertyDataLength = data.getUint16(offset, true);
@@ -2255,15 +2137,16 @@
                     featureRegistryPropertyDataType, propertyDataLength),
           },
         ];
-        offset = this.renderRawDataTree_(
+        offset = renderRawDataTree(
             item, rawDataByteElement, propertyDataFields, rawData, offset,
-            parentClassName);
+            this.rootElement_, parentClassName);
       }
 
       if (offset !== originalOffset + length) {
-        this.showError_(
+        showError(
             'An error occurred while rendering Microsoft OS 2.0 ' +
-            'Registry Property Descriptor.');
+                'Registry Property Descriptor.',
+            this.rootElement_);
       }
 
       return offset;
@@ -2317,14 +2200,15 @@
         },
       ];
 
-      const offset = this.renderRawDataTree_(
+      const offset = renderRawDataTree(
           item, rawDataByteElement, fields, rawData, originalOffset,
           parentClassName);
 
       if (offset !== originalOffset + length) {
-        this.showError_(
+        showError(
             'An error occurred while rendering Microsoft OS 2.0 ' +
-            'Minimum USB Resume Time Descriptor.');
+                'Minimum USB Resume Time Descriptor.',
+            this.rootElement_);
       }
 
       return offset;
@@ -2371,14 +2255,15 @@
         },
       ];
 
-      const offset = this.renderRawDataTree_(
+      const offset = renderRawDataTree(
           item, rawDataByteElement, fields, rawData, originalOffset,
           parentClassName);
 
       if (offset !== originalOffset + length) {
-        this.showError_(
+        showError(
             'An error occurred while rendering Microsoft OS 2.0 ' +
-            'Model ID Descriptor.');
+                'Model ID Descriptor.',
+            this.rootElement_);
       }
 
       return offset;
@@ -2423,14 +2308,15 @@
         },
       ];
 
-      const offset = this.renderRawDataTree_(
+      const offset = renderRawDataTree(
           item, rawDataByteElement, fields, rawData, originalOffset,
           parentClassName);
 
       if (offset !== originalOffset + length) {
-        this.showError_(
+        showError(
             'An error occurred while rendering Microsoft OS 2.0 ' +
-            'CCGP Device Descriptor.');
+                'CCGP Device Descriptor.',
+            this.rootElement_);
       }
 
       return offset;
@@ -2478,14 +2364,15 @@
         },
       ];
 
-      const offset = this.renderRawDataTree_(
+      const offset = renderRawDataTree(
           item, rawDataByteElement, fields, rawData, originalOffset,
           parentClassName);
 
       if (offset !== originalOffset + length) {
-        this.showError_(
+        showError(
             'An error occurred while rendering Microsoft OS 2.0 ' +
-            'Vendor Revision Descriptor.');
+                'Vendor Revision Descriptor.',
+            this.rootElement_);
       }
 
       return offset;
@@ -2527,7 +2414,7 @@
         },
       ];
 
-      let offset = this.renderRawDataTree_(
+      let offset = renderRawDataTree(
           item, rawDataByteElement, fields, rawData, originalOffset,
           parentClassName);
 
@@ -2539,9 +2426,10 @@
       }
 
       if (offset !== originalOffset + length) {
-        this.showError_(
+        showError(
             'An error occurred while rendering Microsoft OS 2.0 ' +
-            'Unknown Descriptor.');
+                'Unknown Descriptor.',
+            this.rootElement_);
       }
 
       return offset;
@@ -2561,8 +2449,8 @@
         if (direction === 'Device-to-Host') {
           const response = await this.usbDeviceProxy_.controlTransferIn(
               usbControlTransferParams, length, CONTROL_TRANSFER_TIMEOUT_MS);
-          this.checkTransferSuccess_(
-              response.status, 'Failed to send request.');
+          checkTransferSuccess(
+              response.status, 'Failed to send request.', this.rootElement_);
           this.renderTestingData_(new Uint8Array(response.data));
         } else if (direction === 'Host-to-Device') {
           const dataString = this.rootElement_.querySelector('textarea').value;
@@ -2575,8 +2463,8 @@
           const response = await this.usbDeviceProxy_.controlTransferOut(
               usbControlTransferParams, new Uint8Array(data),
               CONTROL_TRANSFER_TIMEOUT_MS);
-          this.checkTransferSuccess_(
-              response.status, 'Failed to send request.');
+          checkTransferSuccess(
+              response.status, 'Failed to send request.', this.rootElement_);
         }
       } catch (e) {
         this.showError_(e.message);
@@ -2592,7 +2480,7 @@
      * @private
      */
     async renderTestingData_(rawData) {
-      const displayElement = this.addNewDescriptorDisplayElement_();
+      const displayElement = addNewDescriptorDisplayElement(this.rootElement_);
       /** @type {!cr.ui.Tree} */
       const rawDataTreeRoot = displayElement.rawDataTreeRoot;
       rawDataTreeRoot.style.display = 'none';
@@ -2605,9 +2493,10 @@
      * Initializes the testing tool panel for input and query functionality.
      */
     initialTestingToolPanel() {
-      this.showWarn_(
+      showWarn(
           'Warning: This tool can send arbitrary commands to the device. ' +
-          'Invalid commands may cause unexpected results.');
+              'Invalid commands may cause unexpected results.',
+          this.rootElement_);
       const inputTableRows =
           this.rootElement_.querySelector('tbody').querySelectorAll('tr');
       const buttons =
@@ -2708,7 +2597,7 @@
      */
     checkParamValid_(paramValue, paramName, min, max) {
       if (Number.isNaN(paramValue) || paramValue < min || paramValue > max) {
-        this.showError_(`Invalid ${paramName}.`);
+        showError(`Invalid ${paramName}.`, this.rootElement_);
         return false;
       }
       return true;
@@ -2726,7 +2615,7 @@
       if (enumObject[enumString] !== undefined) {
         return true;
       }
-      this.showError_(`Invalid ${paramName}`);
+      showError(`Invalid ${paramName}`, this.rootElement_);
       return false;
     }
   }
@@ -2883,6 +2772,64 @@
   }
 
   /**
+   * Adds a display area which contains a tree view and a byte view.
+   * @param {!HTMLElement} rootElement
+   * @param {string=} descriptorPanelTitle
+   * @return {{rawDataTreeRoot:!cr.ui.Tree,rawDataByteElement:!HTMLElement}}
+   */
+  function addNewDescriptorDisplayElement(
+      rootElement, descriptorPanelTitle = undefined) {
+    const descriptorPanelTemplate =
+        document.querySelector('#descriptor-panel-template');
+    const descriptorPanelClone =
+        document.importNode(descriptorPanelTemplate.content, true);
+
+    /** @type {!HTMLElement} */
+    const rawDataTreeRoot =
+        descriptorPanelClone.querySelector('.raw-data-tree-view');
+    /** @type {!HTMLElement} */
+    const rawDataByteElement =
+        descriptorPanelClone.querySelector('.raw-data-byte-view');
+
+    cr.ui.decorate(rawDataTreeRoot, cr.ui.Tree);
+    rawDataTreeRoot.detail = {payload: {}, children: {}};
+
+    if (descriptorPanelTitle) {
+      const descriptorPanelTitleTemplate =
+          document.querySelector('#descriptor-panel-title');
+      const clone =
+          document.importNode(descriptorPanelTitleTemplate.content, true)
+              .querySelector('descriptorpaneltitle');
+      clone.textContent = descriptorPanelTitle;
+      rootElement.appendChild(clone);
+    }
+    rootElement.appendChild(descriptorPanelClone);
+    return {rawDataTreeRoot, rawDataByteElement};
+  }
+
+  /**
+   * Shows an error message.
+   * @param {string} message
+   * @param {!HTMLElement} rootElement
+   */
+  function showError(message, rootElement) {
+    const errorElement = document.createElement('error');
+    errorElement.textContent = message;
+    rootElement.prepend(errorElement);
+  }
+
+  /**
+   * Shows a warning message.
+   * @param {string} message
+   * @param {!HTMLElement} rootElement
+   */
+  function showWarn(message, rootElement) {
+    const warnElement = document.createElement('warn');
+    warnElement.textContent = message;
+    rootElement.prepend(warnElement);
+  }
+
+  /**
    * Renders a customized TreeItem with the given content and class name.
    * @param {string} itemLabel
    * @param {string=} className
@@ -2894,7 +2841,7 @@
       icon: '',
     });
     if (className) {
-      item.querySelector('.tree-row').classList.add(className);
+      item.rowElement.classList.add(className);
     }
     return item;
   }
@@ -2980,6 +2927,58 @@
   }
 
   /**
+   * Renders a tree view to display the raw data in readable text.
+   * @param {!cr.ui.Tree|!cr.ui.TreeItem} root
+   * @param {!HTMLElement} rawDataByteElement
+   * @param {!Array<Object>} fields
+   * @param {!Uint8Array} rawData
+   * @param {number} offset The start offset of the descriptor structure that
+   *     want to be rendered.
+   * @param {!HTMLElement} rootElement
+   * @param {...string} parentClassNames
+   * @return {number} The end offset of descriptor structure that want to be
+   *     rendered.
+   */
+  function renderRawDataTree(
+      root, rawDataByteElement, fields, rawData, offset, rootElement,
+      ...parentClassNames) {
+    const rawDataByteElements = rawDataByteElement.querySelectorAll('span');
+
+    for (const field of fields) {
+      const className = `field-offset-${offset}`;
+      let item;
+      try {
+        item = customTreeItem(
+            `${field.label}${field.formatter(rawData, offset)}`, className);
+
+        for (let i = 0; i < field.size; i++) {
+          rawDataByteElements[offset + i].classList.add(className);
+          for (const parentClassName of parentClassNames) {
+            rawDataByteElements[offset + i].classList.add(parentClassName);
+          }
+        }
+      } catch (e) {
+        showError(`Field at offset ${offset} is invalid.`, rootElement);
+        break;
+      }
+
+      try {
+        if (field.extraTreeItemFormatter) {
+          field.extraTreeItemFormatter(rawData, offset, item, field.label);
+        }
+      } catch (e) {
+        showError(
+            `Error at rendering field at index ${offset}: ${e.message}`,
+            rootElement);
+      }
+
+      root.add(item);
+      offset += field.size;
+    }
+    return offset;
+  }
+
+  /**
    * Renders an element to display the raw data in hex, byte by byte.
    * @param {!HTMLElement} rawDataByteElement
    * @param {!Uint8Array} rawData
@@ -3006,6 +3005,47 @@
   }
 
   /**
+   * Checks if the status of a control transfer indicates success.
+   * @param {number} status
+   * @param {string} defaultMessage
+   * @param {!HTMLElement} rootElement
+   */
+  function checkTransferSuccess(status, defaultMessage, rootElement) {
+    let failReason = '';
+    switch (status) {
+      case device.mojom.UsbTransferStatus.COMPLETED:
+        return;
+      case device.mojom.UsbTransferStatus.SHORT_PACKET:
+        showError('Descriptor is too short.', rootElement);
+        return;
+      case device.mojom.UsbTransferStatus.BABBLE:
+        showError('Descriptor is too long.', rootElement);
+        return;
+      case device.mojom.UsbTransferStatus.TRANSFER_ERROR:
+        failReason = 'Transfer Error';
+        break;
+      case device.mojom.UsbTransferStatus.TIMEOUT:
+        failReason = 'Timeout';
+        break;
+      case device.mojom.UsbTransferStatus.CANCELLED:
+        failReason = 'Transfer was cancelled';
+        break;
+      case device.mojom.UsbTransferStatus.STALLED:
+        failReason = 'Transfer Error';
+        break;
+      case device.mojom.UsbTransferStatus.DISCONNECT:
+        failReason = 'Transfer stalled';
+        break;
+      case device.mojom.UsbTransferStatus.PERMISSION_DENIED:
+        failReason = 'Permission denied';
+        break;
+    }
+    // Response data will be null if |status| is neither COMPLETED, BABBLE, or
+    // SHORT_PACKET. Throws an error to stop rendering response data.
+    throw new Error(`${defaultMessage} (Reason: ${failReason})`);
+  }
+
+  /**
    * Converts a number to a hexadecimal string padded with zeros to the given
    * number of digits.
    * @param {number} number
diff --git a/chrome/browser/resources/usb_internals/usb_internals.html b/chrome/browser/resources/usb_internals/usb_internals.html
index e64eb5e..f709b1255 100644
--- a/chrome/browser/resources/usb_internals/usb_internals.html
+++ b/chrome/browser/resources/usb_internals/usb_internals.html
@@ -248,14 +248,6 @@
     <button>GET</button>
   </template>
 
-  <template id="error">
-    <error></error>
-  </template>
-
-  <template id="warn">
-    <warn></warn>
-  </template>
-
   <template id="descriptor-panel-title">
     <descriptorpaneltitle></descriptorpaneltitle>
   </template>
diff --git a/chrome/browser/resources/welcome/dice_welcome/welcome_app.html b/chrome/browser/resources/welcome/dice_welcome/welcome_app.html
index 6dc83f14..8f69d80 100644
--- a/chrome/browser/resources/welcome/dice_welcome/welcome_app.html
+++ b/chrome/browser/resources/welcome/dice_welcome/welcome_app.html
@@ -1,14 +1,13 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
-<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/html/cr.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
 <link rel="import" href="welcome_browser_proxy.html">
 
 <dom-module id="welcome-app">
   <template>
-    <style include="paper-button-style">
+    <style>
       @keyframes slideUpContent {
         from {
           transform: translateY(120px);
@@ -152,13 +151,13 @@
         margin-top: 2.5em;
       }
 
-      paper-button {
+      cr-button {
         min-width: 92px;
       }
     </style>
     <div class="slider">
       <div id="logoWrapper">
-        <div id="logo" on-tap="onLogoTap_"></div>
+        <div id="logo" on-click="onLogoTap_"></div>
       </div>
       <div class="heading-container">
         <div class="heading">$i18n{headerText}</div>
@@ -167,12 +166,12 @@
       <div class="signin">
         <div class="signin-description">$i18n{descriptionText}</div>
         <div class="signin-buttons">
-          <paper-button on-tap="onDecline_">
+          <cr-button on-click="onDecline_">
             $i18n{declineText}
-          </paper-button>
-          <paper-button class="action-button" on-tap="onAccept_">
+          </cr-button>
+          <cr-button class="action-button" on-click="onAccept_">
             $i18n{acceptText}
-          </paper-button>
+          </cr-button>
         </div>
       </div>
     </div>
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps.html b/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps.html
index 4416a947..e8dadb0 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps.html
+++ b/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps.html
@@ -1,14 +1,13 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/icons.html">
-<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/html/cr.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/html/util.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-a11y-announcer/iron-a11y-announcer.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../navigation_behavior.html">
 <link rel="import" href="../shared/animations_css.html">
 <link rel="import" href="../shared/bookmark_proxy.html">
@@ -20,7 +19,7 @@
 
 <dom-module id="nux-google-apps">
   <template>
-    <style include="animations chooser-shared-css paper-button-style">
+    <style include="animations chooser-shared-css">
       .apps-ask {
         text-align: center;
       }
@@ -196,15 +195,15 @@
         </div>
 
         <div class="button-bar">
-          <paper-button id="noThanksButton" on-click="onNoThanksClicked_">
+          <cr-button id="noThanksButton" on-click="onNoThanksClicked_">
             $i18n{skip}
-          </paper-button>
+          </cr-button>
           <step-indicator model="[[indicatorModel]]"></step-indicator>
-          <paper-button class="action-button" disabled$="[[!hasAppsSelected_]]"
+          <cr-button class="action-button" disabled$="[[!hasAppsSelected_]]"
               on-click="onGetStartedClicked_">
             $i18n{next}
             <iron-icon icon="cr:chevron-right"></iron-icon>
-          </paper-button>
+          </cr-button>
         </div>
       </div>
     </div>
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/landing_view.html b/chrome/browser/resources/welcome/onboarding_welcome/landing_view.html
index 891d217..2ae537d 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/landing_view.html
+++ b/chrome/browser/resources/welcome/onboarding_welcome/landing_view.html
@@ -1,7 +1,6 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
-<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
 <link rel="import" href="landing_view_proxy.html">
 <link rel="import" href="navigation_behavior.html">
@@ -13,9 +12,7 @@
 
 <dom-module id="landing-view">
   <template>
-    <style
-        include="animations paper-button-style action-link-style
-            splash-pages-shared-css">
+    <style include="animations action-link-style splash-pages-shared-css">
       onboarding-background {
         --animation-delay: 275ms;
       }
@@ -33,9 +30,9 @@
       <onboarding-background class="fade-in"></onboarding-background>
       <h2 class="fade-in">$i18n{landingDescription}</h2>
       <h1 class="fade-in" tabindex="-1">$i18n{landingTitle}</h1>
-      <paper-button class="action-button fade-in" on-click="onNewUserClick_">
+      <cr-button class="action-button fade-in" on-click="onNewUserClick_">
         $i18n{landingNewUser}
-      </paper-button>
+      </cr-button>
       <button class="action-link fade-in" on-click="onExistingUserClick_">
         <span hidden$="[[!signinAllowed_]]">$i18n{landingExistingUser}</span>
         <span hidden$="[[signinAllowed_]]">$i18n{skip}</span>
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/ntp_background/nux_ntp_background.html b/chrome/browser/resources/welcome/onboarding_welcome/ntp_background/nux_ntp_background.html
index 96b0b41..e6031c8 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/ntp_background/nux_ntp_background.html
+++ b/chrome/browser/resources/welcome/onboarding_welcome/ntp_background/nux_ntp_background.html
@@ -1,13 +1,12 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/icons.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
-<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
 <link rel="import" href="chrome://resources/html/cr.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/html/util.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../navigation_behavior.html">
 <link rel="import" href="../shared/animations_css.html">
 <link rel="import" href="../shared/chooser_shared_css.html">
@@ -18,7 +17,7 @@
 
 <dom-module id="nux-ntp-background">
   <template>
-    <style include="animations chooser-shared-css paper-button-style">
+    <style include="animations chooser-shared-css">
       :host {
         text-align: center;
       }
@@ -196,15 +195,14 @@
       </div>
 
       <div class="button-bar">
-        <paper-button id="skipButton" on-click="onSkipClicked_">
+        <cr-button id="skipButton" on-click="onSkipClicked_">
           $i18n{skip}
-        </paper-button>
+        </cr-button>
         <step-indicator model="[[indicatorModel]]"></step-indicator>
-        <paper-button class="action-button"
-            on-click="onNextClicked_">
+        <cr-button class="action-button" on-click="onNextClicked_">
           $i18n{next}
           <iron-icon icon="cr:chevron-right"></iron-icon>
-        </paper-button>
+        </cr-button>
       </div>
     </div>
   </template>
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.html b/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.html
index 306a4e3..7b81f69 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.html
+++ b/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.html
@@ -1,9 +1,8 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
-<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../navigation_behavior.html">
 <link rel="import" href="../shared/animations_css.html">
 <link rel="import" href="../shared/i18n_setup.html">
@@ -16,7 +15,7 @@
 
 <dom-module id="nux-set-as-default">
   <template>
-    <style include="animations paper-button-style">
+    <style include="animations">
       .container {
         text-align: center;
       }
@@ -84,16 +83,16 @@
       <h2>$i18n{setDefaultSubHeader}</h2>
       <div class="illustration slide-in" aria-hidden="true"></div>
       <div class="button-bar">
-        <paper-button id="decline-button" on-click="onDeclineClick_">
+        <cr-button id="decline-button" on-click="onDeclineClick_">
           $i18n{setDefaultSkip}
-        </paper-button>
+        </cr-button>
         <step-indicator model="[[indicatorModel]]"></step-indicator>
-        <paper-button class="action-button" on-click="onSetDefaultClick_">
+        <cr-button class="action-button" on-click="onSetDefaultClick_">
           $i18n{setDefaultConfirm}
 <if expr="is_win">
           <iron-icon icon="cr:open-in-new" hidden="[[!isWin10]]"></iron-icon>
 </if>
-        </paper-button>
+        </cr-button>
       </div>
     </div>
   </template>
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/shared/splash_pages_shared_css.html b/chrome/browser/resources/welcome/onboarding_welcome/shared/splash_pages_shared_css.html
index d213efc6..3d662b4 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/shared/splash_pages_shared_css.html
+++ b/chrome/browser/resources/welcome/onboarding_welcome/shared/splash_pages_shared_css.html
@@ -35,7 +35,7 @@
         text-align: center;
       }
 
-      paper-button {
+      cr-button {
         font-size: 1rem;
         height: 3rem;
         padding-bottom: 12px;
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/signin_view.html b/chrome/browser/resources/welcome/onboarding_welcome/signin_view.html
index 42e8387..d5fc11e6 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/signin_view.html
+++ b/chrome/browser/resources/welcome/onboarding_welcome/signin_view.html
@@ -1,7 +1,6 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
-<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
 <link rel="import" href="navigation_behavior.html">
 <link rel="import" href="shared/action_link_style_css.html">
@@ -14,9 +13,7 @@
 
 <dom-module id="signin-view">
   <template>
-    <style
-        include="animations paper-button-style action-link-style
-            splash-pages-shared-css">
+    <style include="animations action-link-style splash-pages-shared-css">
       onboarding-background {
         --animation-delay: 150ms;
       }
@@ -29,9 +26,9 @@
       <onboarding-background class="fade-in"></onboarding-background>
       <h2>$i18n{signInSubHeader}</h2>
       <h1 tabindex="-1">$i18n{signInHeader}</h1>
-      <paper-button class="action-button" on-click="onSignInClick_">
+      <cr-button class="action-button" on-click="onSignInClick_">
         $i18n{signIn}
-      </paper-button>
+      </cr-button>
       <button class="action-link" on-click="onNoThanksClick_">
         $i18n{noThanks}
       </button>
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/welcome_app.html b/chrome/browser/resources/welcome/onboarding_welcome/welcome_app.html
index cda34d4..c173035b 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/welcome_app.html
+++ b/chrome/browser/resources/welcome/onboarding_welcome/welcome_app.html
@@ -16,7 +16,7 @@
 
 <dom-module id="welcome-app">
   <template>
-    <style include="paper-button-style cr-hidden-style">
+    <style include="cr-hidden-style">
       #viewManager {
         display: flex;
         font-size: 100%;
diff --git a/chrome/browser/resources/welcome/welcome.html b/chrome/browser/resources/welcome/welcome.html
index 4aa0ce86..2426c26 100644
--- a/chrome/browser/resources/welcome/welcome.html
+++ b/chrome/browser/resources/welcome/welcome.html
@@ -6,11 +6,10 @@
 
   <link rel="import" href="chrome://resources/html/polymer.html">
 
-  <link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
+  <link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
   <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
   <link rel="import" href="chrome://resources/html/cr.html">
   <link rel="import" href="chrome://resources/html/util.html">
-  <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 
   <link rel="stylesheet" href="chrome://resources/css/md_colors.css">
   <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
@@ -24,7 +23,7 @@
 
   <dom-module id="welcome-app">
     <template>
-      <style include="paper-button-style">
+      <style>
         @keyframes slideUpContent {
           from {
             transform: translateY(186px);
@@ -195,9 +194,9 @@
           width: fit-content;
         }
 
-        paper-button {
+        cr-button {
           font-size: .8125em;
-          /* Makes sure the two paper-buttons are the same width since they're
+          /* Makes sure the two cr-button's are the same width since they're
              placed vertically. Requires parent to be "width: fit-content;". */
           width: 100%;
         }
@@ -220,12 +219,12 @@
           <div class="signin">
             <div class="signin-description">$i18n{descriptionText}</div>
             <div class="signin-buttons">
-              <paper-button class="action-button" on-tap="onAccept_">
+              <cr-button class="action-button" on-click="onAccept_">
                 $i18n{acceptText}
-              </paper-button>
-              <paper-button id="cancel" on-tap="onDecline_">
+              </cr-button>
+              <cr-button id="cancel" on-click="onDecline_">
                 $i18n{declineText}
-              </paper-button>
+              </cr-button>
             </div>
           </div>
         </div>
diff --git a/chrome/browser/resources/welcome/welcome_win10.html b/chrome/browser/resources/welcome/welcome_win10.html
index 8b7f82a..5321eb7 100644
--- a/chrome/browser/resources/welcome/welcome_win10.html
+++ b/chrome/browser/resources/welcome/welcome_win10.html
@@ -6,7 +6,7 @@
 
   <link rel="import" href="chrome://resources/html/polymer.html">
 
-  <link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
+  <link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
   <link rel="import" href="chrome://resources/cr_elements/icons.html">
   <link rel="import" href="chrome://resources/html/cr.html">
   <link rel="import" href="chrome://resources/html/load_time_data.html">
@@ -16,7 +16,6 @@
   <link rel="import" href="chrome://resources/html/action_link_css.html">
 
   <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
-  <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
   <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
 
   <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
@@ -26,7 +25,7 @@
 
   <dom-module id="welcome-win10">
     <template>
-      <style include="action-link paper-button-style">
+      <style include="action-link">
         :host {
           align-items: flex-start;
           display: inline-flex;
@@ -151,7 +150,7 @@
           visibility: visible;
         }
 
-        paper-button {
+        cr-button {
           font-size: .8125em;
         }
 
@@ -343,9 +342,9 @@
           </div>
         </template>
       </div>
-      <paper-button class="action-button" on-tap="onContinue">
+      <cr-button class="action-button" on-click="onContinue">
         $i18n{continueText}
-      </paper-button>
+      </cr-button>
     </template>
     <script src="/welcome_win10.js"></script>
   </dom-module>
diff --git a/chrome/browser/ssl/security_state_tab_helper.cc b/chrome/browser/ssl/security_state_tab_helper.cc
index 6ef33c5..83bfd274 100644
--- a/chrome/browser/ssl/security_state_tab_helper.cc
+++ b/chrome/browser/ssl/security_state_tab_helper.cc
@@ -128,34 +128,6 @@
     // the number of times it was available.
     UMA_HISTOGRAM_BOOLEAN("interstitial.ssl.visited_site_after_warning", true);
   }
-
-  // Security indicator UI study (https://crbug.com/803501): Show a message in
-  // the console to reduce developer confusion about the experimental UI
-  // treatments for HTTPS pages with EV certificates.
-  const std::string parameter =
-      base::FeatureList::IsEnabled(omnibox::kSimplifyHttpsIndicator)
-          ? base::GetFieldTrialParamValueByFeature(
-                omnibox::kSimplifyHttpsIndicator,
-                OmniboxFieldTrial::kSimplifyHttpsIndicatorParameterName)
-          : std::string();
-  if (GetSecurityLevel() == security_state::EV_SECURE) {
-    if (parameter ==
-        OmniboxFieldTrial::kSimplifyHttpsIndicatorParameterEvToSecure) {
-      web_contents()->GetMainFrame()->AddMessageToConsole(
-          blink::mojom::ConsoleMessageLevel::kInfo,
-          "As part of an experiment, Chrome temporarily shows only the "
-          "\"Secure\" text in the address bar. Your SSL certificate with "
-          "Extended Validation is still valid.");
-    }
-    if (parameter ==
-        OmniboxFieldTrial::kSimplifyHttpsIndicatorParameterBothToLock) {
-      web_contents()->GetMainFrame()->AddMessageToConsole(
-          blink::mojom::ConsoleMessageLevel::kInfo,
-          "As part of an experiment, Chrome temporarily shows only the lock "
-          "icon in the address bar. Your SSL certificate with Extended "
-          "Validation is still valid.");
-    }
-  }
 }
 
 void SecurityStateTabHelper::DidChangeVisibleSecurityState() {
diff --git a/chrome/browser/sync_file_system/drive_backend/drive_backend_sync_unittest.cc b/chrome/browser/sync_file_system/drive_backend/drive_backend_sync_unittest.cc
index 5e754d2b..96eb8f9 100644
--- a/chrome/browser/sync_file_system/drive_backend/drive_backend_sync_unittest.cc
+++ b/chrome/browser/sync_file_system/drive_backend/drive_backend_sync_unittest.cc
@@ -225,7 +225,7 @@
 
   SyncStatusCode RegisterApp(const std::string& app_id) {
     GURL origin = extensions::Extension::GetBaseURLFromExtensionId(app_id);
-    if (!base::ContainsKey(file_systems_, app_id)) {
+    if (!base::Contains(file_systems_, app_id)) {
       CannedSyncableFileSystem* file_system = new CannedSyncableFileSystem(
           origin, in_memory_env_.get(),
           io_task_runner_.get(), file_task_runner_.get());
@@ -259,7 +259,7 @@
 
   void AddLocalFolder(const std::string& app_id,
                       const base::FilePath::StringType& path) {
-    ASSERT_TRUE(base::ContainsKey(file_systems_, app_id));
+    ASSERT_TRUE(base::Contains(file_systems_, app_id));
     EXPECT_EQ(base::File::FILE_OK,
               file_systems_[app_id]->CreateDirectory(
                   CreateURL(app_id, path)));
@@ -269,7 +269,7 @@
                             const base::FilePath::StringType& path,
                             const std::string& content) {
     storage::FileSystemURL url(CreateURL(app_id, path));
-    ASSERT_TRUE(base::ContainsKey(file_systems_, app_id));
+    ASSERT_TRUE(base::Contains(file_systems_, app_id));
     EXPECT_EQ(base::File::FILE_OK, file_systems_[app_id]->CreateFile(url));
     int64_t bytes_written = file_systems_[app_id]->WriteString(url, content);
     EXPECT_EQ(static_cast<int64_t>(content.size()), bytes_written);
@@ -279,7 +279,7 @@
   void UpdateLocalFile(const std::string& app_id,
                        const base::FilePath::StringType& path,
                        const std::string& content) {
-    ASSERT_TRUE(base::ContainsKey(file_systems_, app_id));
+    ASSERT_TRUE(base::Contains(file_systems_, app_id));
     int64_t bytes_written =
         file_systems_[app_id]->WriteString(CreateURL(app_id, path), content);
     EXPECT_EQ(static_cast<int64_t>(content.size()), bytes_written);
@@ -288,7 +288,7 @@
 
   void RemoveLocal(const std::string& app_id,
                    const base::FilePath::StringType& path) {
-    ASSERT_TRUE(base::ContainsKey(file_systems_, app_id));
+    ASSERT_TRUE(base::Contains(file_systems_, app_id));
     EXPECT_EQ(base::File::FILE_OK,
               file_systems_[app_id]->Remove(
                   CreateURL(app_id, path),
@@ -413,7 +413,7 @@
                   sync_root_folder_id, &remote_entries));
     std::map<std::string, const google_apis::FileResource*> app_root_by_title;
     for (const auto& remote_entry : remote_entries) {
-      EXPECT_FALSE(base::ContainsKey(app_root_by_title, remote_entry->title()));
+      EXPECT_FALSE(base::Contains(app_root_by_title, remote_entry->title()));
       app_root_by_title[remote_entry->title()] = remote_entry.get();
     }
 
@@ -423,7 +423,7 @@
       const std::string& app_id = itr->first;
       SCOPED_TRACE(testing::Message() << "Verifying app: " << app_id);
       CannedSyncableFileSystem* file_system = itr->second;
-      ASSERT_TRUE(base::ContainsKey(app_root_by_title, app_id));
+      ASSERT_TRUE(base::Contains(app_root_by_title, app_id));
       VerifyConsistencyForFolder(
           app_id, base::FilePath(),
           app_root_by_title[app_id]->file_id(),
@@ -445,8 +445,7 @@
         remote_entry_by_title;
     for (size_t i = 0; i < remote_entries.size(); ++i) {
       google_apis::FileResource* remote_entry = remote_entries[i].get();
-      EXPECT_FALSE(
-          base::ContainsKey(remote_entry_by_title, remote_entry->title()))
+      EXPECT_FALSE(base::Contains(remote_entry_by_title, remote_entry->title()))
           << "title: " << remote_entry->title();
       remote_entry_by_title[remote_entry->title()] = remote_entry;
     }
@@ -462,7 +461,7 @@
           storage::VirtualPath::BaseName(entry_url.path()).AsUTF8Unsafe();
       SCOPED_TRACE(testing::Message() << "Verifying entry: " << title);
 
-      ASSERT_TRUE(base::ContainsKey(remote_entry_by_title, title));
+      ASSERT_TRUE(base::Contains(remote_entry_by_title, title));
       const google_apis::FileResource& remote_entry =
           *remote_entry_by_title[title];
       if (local_entry.type == filesystem::mojom::FsFileType::DIRECTORY) {
@@ -499,7 +498,7 @@
   }
 
   size_t CountLocalFile(const std::string& app_id) {
-    if (!base::ContainsKey(file_systems_, app_id))
+    if (!base::Contains(file_systems_, app_id))
       return 0;
 
     CannedSyncableFileSystem* file_system = file_systems_[app_id];
@@ -530,7 +529,7 @@
     SCOPED_TRACE(testing::Message() << "Verifying local file: "
                                     << "app_id = " << app_id
                                     << ", path = " << path);
-    ASSERT_TRUE(base::ContainsKey(file_systems_, app_id));
+    ASSERT_TRUE(base::Contains(file_systems_, app_id));
     EXPECT_EQ(base::File::FILE_OK,
               file_systems_[app_id]->VerifyFile(
                   CreateURL(app_id, path), content));
@@ -541,7 +540,7 @@
     SCOPED_TRACE(testing::Message() << "Verifying local file: "
                                     << "app_id = " << app_id
                                     << ", path = " << path);
-    ASSERT_TRUE(base::ContainsKey(file_systems_, app_id));
+    ASSERT_TRUE(base::Contains(file_systems_, app_id));
     EXPECT_EQ(base::File::FILE_OK,
               file_systems_[app_id]->DirectoryExists(CreateURL(app_id, path)));
   }
diff --git a/chrome/browser/sync_file_system/drive_backend/metadata_database.cc b/chrome/browser/sync_file_system/drive_backend/metadata_database.cc
index 28d531b..fc0ba964 100644
--- a/chrome/browser/sync_file_system/drive_backend/metadata_database.cc
+++ b/chrome/browser/sync_file_system/drive_backend/metadata_database.cc
@@ -1424,7 +1424,7 @@
       if (!parent_tracker.active())
         continue;
 
-      if (base::ContainsKey(parents_to_exclude, parent_tracker.tracker_id()))
+      if (base::Contains(parents_to_exclude, parent_tracker.tracker_id()))
         continue;
 
       CreateTrackerForParentAndFileMetadata(
diff --git a/chrome/browser/sync_file_system/drive_backend/metadata_database_index.cc b/chrome/browser/sync_file_system/drive_backend/metadata_database_index.cc
index 01aaa7b..02e535e6 100644
--- a/chrome/browser/sync_file_system/drive_backend/metadata_database_index.cc
+++ b/chrome/browser/sync_file_system/drive_backend/metadata_database_index.cc
@@ -172,7 +172,7 @@
   std::vector<std::unique_ptr<FileTracker>> reachable_trackers;
   for (size_t i = 0; i < contents->file_trackers.size(); ++i) {
     std::unique_ptr<FileTracker>& tracker = contents->file_trackers[i];
-    if (base::ContainsKey(visited_trackers, tracker->tracker_id())) {
+    if (base::Contains(visited_trackers, tracker->tracker_id())) {
       reachable_trackers.push_back(std::move(tracker));
     } else {
       PutFileTrackerDeletionToDB(tracker->tracker_id(), db);
@@ -189,7 +189,7 @@
   std::vector<std::unique_ptr<FileMetadata>> referred_file_metadata;
   for (size_t i = 0; i < contents->file_metadata.size(); ++i) {
     std::unique_ptr<FileMetadata>& metadata = contents->file_metadata[i];
-    if (base::ContainsKey(referred_file_ids, metadata->file_id())) {
+    if (base::Contains(referred_file_ids, metadata->file_id())) {
       referred_file_metadata.push_back(std::move(metadata));
     } else {
       PutFileMetadataDeletionToDB(metadata->file_id(), db);
@@ -520,7 +520,7 @@
   DVLOG(3) << "  Add to app_root_by_app_id_: " << new_tracker.app_id();
 
   DCHECK(new_tracker.active());
-  DCHECK(!base::ContainsKey(app_root_by_app_id_, new_tracker.app_id()));
+  DCHECK(!base::Contains(app_root_by_app_id_, new_tracker.app_id()));
   app_root_by_app_id_[new_tracker.app_id()] = new_tracker.tracker_id();
 }
 
@@ -532,7 +532,7 @@
   if (IsAppRoot(old_tracker) && !IsAppRoot(new_tracker)) {
     DCHECK(old_tracker.active());
     DCHECK(!new_tracker.active());
-    DCHECK(base::ContainsKey(app_root_by_app_id_, old_tracker.app_id()));
+    DCHECK(base::Contains(app_root_by_app_id_, old_tracker.app_id()));
 
     DVLOG(3) << "  Remove from app_root_by_app_id_: " << old_tracker.app_id();
 
@@ -540,7 +540,7 @@
   } else if (!IsAppRoot(old_tracker) && IsAppRoot(new_tracker)) {
     DCHECK(!old_tracker.active());
     DCHECK(new_tracker.active());
-    DCHECK(!base::ContainsKey(app_root_by_app_id_, new_tracker.app_id()));
+    DCHECK(!base::Contains(app_root_by_app_id_, new_tracker.app_id()));
 
     DVLOG(3) << "  Add to app_root_by_app_id_: " << new_tracker.app_id();
 
@@ -552,7 +552,7 @@
     const FileTracker& tracker) {
   if (IsAppRoot(tracker)) {
     DCHECK(tracker.active());
-    DCHECK(base::ContainsKey(app_root_by_app_id_, tracker.app_id()));
+    DCHECK(base::Contains(app_root_by_app_id_, tracker.app_id()));
 
     DVLOG(3) << "  Remove from app_root_by_app_id_: " << tracker.app_id();
 
@@ -567,8 +567,7 @@
   trackers_by_file_id_[new_tracker.file_id()].Insert(new_tracker);
 
   if (trackers_by_file_id_[new_tracker.file_id()].size() > 1) {
-    DVLOG_IF(3,
-             !base::ContainsKey(multi_tracker_file_ids_, new_tracker.file_id()))
+    DVLOG_IF(3, !base::Contains(multi_tracker_file_ids_, new_tracker.file_id()))
         << "  Add to multi_tracker_file_ids_: " << new_tracker.file_id();
     multi_tracker_file_ids_.insert(new_tracker.file_id());
   }
@@ -581,7 +580,7 @@
   DCHECK_EQ(old_tracker.file_id(), new_tracker.file_id());
 
   std::string file_id = new_tracker.file_id();
-  DCHECK(base::ContainsKey(trackers_by_file_id_, file_id));
+  DCHECK(base::Contains(trackers_by_file_id_, file_id));
 
   if (old_tracker.active() && !new_tracker.active())
     trackers_by_file_id_[file_id].Deactivate(new_tracker.tracker_id());
@@ -602,7 +601,7 @@
   found->second.Erase(tracker.tracker_id());
 
   if (trackers_by_file_id_[tracker.file_id()].size() <= 1) {
-    DVLOG_IF(3, base::ContainsKey(multi_tracker_file_ids_, tracker.file_id()))
+    DVLOG_IF(3, base::Contains(multi_tracker_file_ids_, tracker.file_id()))
         << "  Remove from multi_tracker_file_ids_: " << tracker.file_id();
     multi_tracker_file_ids_.erase(tracker.file_id());
   }
@@ -623,8 +622,8 @@
 
   if (trackers_by_parent_and_title_[parent][title].size() > 1 &&
       !title.empty()) {
-    DVLOG_IF(3, !base::ContainsKey(multi_backing_file_paths_,
-                                   ParentIDAndTitle(parent, title)))
+    DVLOG_IF(3, !base::Contains(multi_backing_file_paths_,
+                                ParentIDAndTitle(parent, title)))
         << "  Add to multi_backing_file_paths_: " << parent << " " << title;
     multi_backing_file_paths_.insert(ParentIDAndTitle(parent, title));
   }
@@ -665,8 +664,8 @@
 
     if (trackers_by_parent_and_title_[parent][old_title].size() <= 1 &&
         !old_title.empty()) {
-      DVLOG_IF(3, base::ContainsKey(multi_backing_file_paths_,
-                                    ParentIDAndTitle(parent, old_title)))
+      DVLOG_IF(3, base::Contains(multi_backing_file_paths_,
+                                 ParentIDAndTitle(parent, old_title)))
           << "  Remove from multi_backing_file_paths_: " << parent << " "
           << old_title;
       multi_backing_file_paths_.erase(ParentIDAndTitle(parent, old_title));
@@ -674,8 +673,8 @@
 
     if (trackers_by_parent_and_title_[parent][title].size() > 1 &&
         !title.empty()) {
-      DVLOG_IF(3, !base::ContainsKey(multi_backing_file_paths_,
-                                     ParentIDAndTitle(parent, title)))
+      DVLOG_IF(3, !base::Contains(multi_backing_file_paths_,
+                                  ParentIDAndTitle(parent, title)))
           << "  Add to multi_backing_file_paths_: " << parent << " " << title;
       multi_backing_file_paths_.insert(ParentIDAndTitle(parent, title));
     }
@@ -695,8 +694,8 @@
   int64_t parent = tracker.parent_tracker_id();
   std::string title = GetTrackerTitle(tracker);
 
-  DCHECK(base::ContainsKey(trackers_by_parent_and_title_, parent));
-  DCHECK(base::ContainsKey(trackers_by_parent_and_title_[parent], title));
+  DCHECK(base::Contains(trackers_by_parent_and_title_, parent));
+  DCHECK(base::Contains(trackers_by_parent_and_title_[parent], title));
 
   DVLOG(3) << "  Remove from trackers_by_parent_and_title_: "
            << parent << " " << title;
@@ -705,8 +704,8 @@
 
   if (trackers_by_parent_and_title_[parent][title].size() <= 1 &&
       !title.empty()) {
-    DVLOG_IF(3, base::ContainsKey(multi_backing_file_paths_,
-                                  ParentIDAndTitle(parent, title)))
+    DVLOG_IF(3, base::Contains(multi_backing_file_paths_,
+                               ParentIDAndTitle(parent, title)))
         << "  Remove from multi_backing_file_paths_: " << parent << " "
         << title;
     multi_backing_file_paths_.erase(ParentIDAndTitle(parent, title));
@@ -721,8 +720,8 @@
 
 void MetadataDatabaseIndex::AddToDirtyTrackerIndexes(
     const FileTracker& new_tracker) {
-  DCHECK(!base::ContainsKey(dirty_trackers_, new_tracker.tracker_id()));
-  DCHECK(!base::ContainsKey(demoted_dirty_trackers_, new_tracker.tracker_id()));
+  DCHECK(!base::Contains(dirty_trackers_, new_tracker.tracker_id()));
+  DCHECK(!base::Contains(demoted_dirty_trackers_, new_tracker.tracker_id()));
 
   if (new_tracker.dirty()) {
     DVLOG(3) << "  Add to dirty_trackers_: " << new_tracker.tracker_id();
@@ -737,16 +736,16 @@
 
   int64_t tracker_id = new_tracker.tracker_id();
   if (old_tracker.dirty() && !new_tracker.dirty()) {
-    DCHECK(base::ContainsKey(dirty_trackers_, tracker_id) ||
-           base::ContainsKey(demoted_dirty_trackers_, tracker_id));
+    DCHECK(base::Contains(dirty_trackers_, tracker_id) ||
+           base::Contains(demoted_dirty_trackers_, tracker_id));
 
     DVLOG(3) << "  Remove from dirty_trackers_: " << tracker_id;
 
     dirty_trackers_.erase(tracker_id);
     demoted_dirty_trackers_.erase(tracker_id);
   } else if (!old_tracker.dirty() && new_tracker.dirty()) {
-    DCHECK(!base::ContainsKey(dirty_trackers_, tracker_id));
-    DCHECK(!base::ContainsKey(demoted_dirty_trackers_, tracker_id));
+    DCHECK(!base::Contains(dirty_trackers_, tracker_id));
+    DCHECK(!base::Contains(demoted_dirty_trackers_, tracker_id));
 
     DVLOG(3) << "  Add to dirty_trackers_: " << tracker_id;
 
@@ -758,8 +757,8 @@
     const FileTracker& tracker) {
   if (tracker.dirty()) {
     int64_t tracker_id = tracker.tracker_id();
-    DCHECK(base::ContainsKey(dirty_trackers_, tracker_id) ||
-           base::ContainsKey(demoted_dirty_trackers_, tracker_id));
+    DCHECK(base::Contains(dirty_trackers_, tracker_id) ||
+           base::Contains(demoted_dirty_trackers_, tracker_id));
 
     DVLOG(3) << "  Remove from dirty_trackers_: " << tracker_id;
     dirty_trackers_.erase(tracker_id);
diff --git a/chrome/browser/sync_file_system/drive_backend/metadata_database_index_on_disk.cc b/chrome/browser/sync_file_system/drive_backend/metadata_database_index_on_disk.cc
index 91f9d15..14aa374 100644
--- a/chrome/browser/sync_file_system/drive_backend/metadata_database_index_on_disk.cc
+++ b/chrome/browser/sync_file_system/drive_backend/metadata_database_index_on_disk.cc
@@ -224,7 +224,7 @@
         continue;
       }
 
-      if (base::ContainsKey(visited_trackers, tracker->tracker_id())) {
+      if (base::Contains(visited_trackers, tracker->tracker_id())) {
         referred_file_ids.insert(tracker->file_id());
       } else {
         PutFileTrackerDeletionToDB(tracker->tracker_id(), db);
@@ -246,7 +246,7 @@
         continue;
       }
 
-      if (!base::ContainsKey(referred_file_ids, metadata->file_id()))
+      if (!base::Contains(referred_file_ids, metadata->file_id()))
         PutFileMetadataDeletionToDB(metadata->file_id(), db);
     }
   }
diff --git a/chrome/browser/sync_file_system/drive_backend/tracker_id_set.cc b/chrome/browser/sync_file_system/drive_backend/tracker_id_set.cc
index 5e039f924..646527a 100644
--- a/chrome/browser/sync_file_system/drive_backend/tracker_id_set.cc
+++ b/chrome/browser/sync_file_system/drive_backend/tracker_id_set.cc
@@ -40,7 +40,7 @@
 }
 
 void TrackerIDSet::Erase(int64_t tracker_id) {
-  DCHECK(base::ContainsKey(tracker_ids_, tracker_id));
+  DCHECK(base::Contains(tracker_ids_, tracker_id));
 
   if (active_tracker_ == tracker_id)
     active_tracker_ = 0;
@@ -49,13 +49,13 @@
 
 void TrackerIDSet::Activate(int64_t tracker_id) {
   DCHECK(!active_tracker_);
-  DCHECK(base::ContainsKey(tracker_ids_, tracker_id));
+  DCHECK(base::Contains(tracker_ids_, tracker_id));
   active_tracker_ = tracker_id;
 }
 
 void TrackerIDSet::Deactivate(int64_t tracker_id) {
   DCHECK_EQ(active_tracker_, tracker_id);
-  DCHECK(base::ContainsKey(tracker_ids_, tracker_id));
+  DCHECK(base::Contains(tracker_ids_, tracker_id));
   active_tracker_ = 0;
 }
 
diff --git a/chrome/browser/sync_file_system/local/local_file_change_tracker.cc b/chrome/browser/sync_file_system/local/local_file_change_tracker.cc
index f1aaca3..b0f1cdb 100644
--- a/chrome/browser/sync_file_system/local/local_file_change_tracker.cc
+++ b/chrome/browser/sync_file_system/local/local_file_change_tracker.cc
@@ -93,8 +93,7 @@
 
 void LocalFileChangeTracker::OnStartUpdate(const FileSystemURL& url) {
   DCHECK(file_task_runner_->RunsTasksInCurrentSequence());
-  if (base::ContainsKey(changes_, url) ||
-      base::ContainsKey(demoted_changes_, url)) {
+  if (base::Contains(changes_, url) || base::Contains(demoted_changes_, url)) {
     return;
   }
   // TODO(nhiroki): propagate the error code (see http://crbug.com/152127).
@@ -180,7 +179,7 @@
 void LocalFileChangeTracker::CreateFreshMirrorForURL(
     const storage::FileSystemURL& url) {
   DCHECK(file_task_runner_->RunsTasksInCurrentSequence());
-  DCHECK(!base::ContainsKey(mirror_changes_, url));
+  DCHECK(!base::Contains(mirror_changes_, url));
   mirror_changes_[url] = ChangeInfo();
 }
 
@@ -192,8 +191,7 @@
     return;
   mirror_changes_.erase(found);
 
-  if (base::ContainsKey(changes_, url) ||
-      base::ContainsKey(demoted_changes_, url)) {
+  if (base::Contains(changes_, url) || base::Contains(demoted_changes_, url)) {
     MarkDirtyOnDatabase(url);
   } else {
     ClearDirtyOnDatabase(url);
@@ -210,11 +208,11 @@
     return;
   }
   const ChangeInfo& info = found->second;
-  if (base::ContainsKey(demoted_changes_, url)) {
-    DCHECK(!base::ContainsKey(changes_, url));
+  if (base::Contains(demoted_changes_, url)) {
+    DCHECK(!base::Contains(changes_, url));
     demoted_changes_[url] = info;
   } else {
-    DCHECK(!base::ContainsKey(demoted_changes_, url));
+    DCHECK(!base::Contains(demoted_changes_, url));
     change_seqs_[info.change_seq] = url;
     changes_[url] = info;
   }
@@ -228,7 +226,7 @@
   auto found = changes_.find(url);
   if (found == changes_.end())
     return;
-  DCHECK(!base::ContainsKey(demoted_changes_, url));
+  DCHECK(!base::Contains(demoted_changes_, url));
   change_seqs_.erase(found->second.change_seq);
   demoted_changes_.insert(*found);
   changes_.erase(found);
@@ -245,8 +243,8 @@
 
   FileChangeList::List change_list = iter->second.change_list.list();
   // Make sure that this URL is in no queues.
-  DCHECK(!base::ContainsKey(change_seqs_, iter->second.change_seq));
-  DCHECK(!base::ContainsKey(changes_, url));
+  DCHECK(!base::Contains(change_seqs_, iter->second.change_seq));
+  DCHECK(!base::Contains(changes_, url));
 
   change_seqs_[iter->second.change_seq] = url;
   changes_.insert(*iter);
@@ -419,13 +417,13 @@
     const FileSystemURL& url, const FileChange& change) {
   DCHECK(file_task_runner_->RunsTasksInCurrentSequence());
   int change_seq = current_change_seq_number_++;
-  if (base::ContainsKey(demoted_changes_, url)) {
+  if (base::Contains(demoted_changes_, url)) {
     RecordChangeToChangeMaps(url, change, change_seq,
                              &demoted_changes_, nullptr);
   } else {
     RecordChangeToChangeMaps(url, change, change_seq, &changes_, &change_seqs_);
   }
-  if (base::ContainsKey(mirror_changes_, url)) {
+  if (base::Contains(mirror_changes_, url)) {
     RecordChangeToChangeMaps(url, change, change_seq, &mirror_changes_,
                              nullptr);
   }
diff --git a/chrome/browser/sync_file_system/local/local_file_change_tracker_unittest.cc b/chrome/browser/sync_file_system/local/local_file_change_tracker_unittest.cc
index d90f119..5fc90e3 100644
--- a/chrome/browser/sync_file_system/local/local_file_change_tracker_unittest.cc
+++ b/chrome/browser/sync_file_system/local/local_file_change_tracker_unittest.cc
@@ -177,14 +177,14 @@
   file_system_.GetChangedURLsInTracker(&urls);
 
   EXPECT_EQ(5U, urls.size());
-  EXPECT_TRUE(base::ContainsKey(urls, URL(kPath1)));
-  EXPECT_TRUE(base::ContainsKey(urls, URL(kPath2)));
-  EXPECT_TRUE(base::ContainsKey(urls, URL(kPath3)));
-  EXPECT_TRUE(base::ContainsKey(urls, URL(kPath4)));
-  EXPECT_TRUE(base::ContainsKey(urls, URL(kPath5)));
+  EXPECT_TRUE(base::Contains(urls, URL(kPath1)));
+  EXPECT_TRUE(base::Contains(urls, URL(kPath2)));
+  EXPECT_TRUE(base::Contains(urls, URL(kPath3)));
+  EXPECT_TRUE(base::Contains(urls, URL(kPath4)));
+  EXPECT_TRUE(base::Contains(urls, URL(kPath5)));
 
   // Changes for kPath0 must have been offset and removed.
-  EXPECT_FALSE(base::ContainsKey(urls, URL(kPath0)));
+  EXPECT_FALSE(base::Contains(urls, URL(kPath0)));
 
   // GetNextChangedURLs only returns up to max_urls (i.e. 3) urls.
   base::circular_deque<FileSystemURL> urls_to_process;
@@ -668,8 +668,8 @@
   ASSERT_EQ(2U, urls.size());
 
   // The exact order of recursive removal cannot be determined.
-  EXPECT_TRUE(base::ContainsKey(urls, URL(kPath1)));
-  EXPECT_TRUE(base::ContainsKey(urls, URL(kPath2)));
+  EXPECT_TRUE(base::Contains(urls, URL(kPath1)));
+  EXPECT_TRUE(base::Contains(urls, URL(kPath2)));
 }
 
 TEST_F(LocalFileChangeTrackerTest, ResetForFileSystem) {
@@ -692,10 +692,10 @@
   FileSystemURLSet urls;
   GetAllChangedURLs(&urls);
   EXPECT_EQ(4u, urls.size());
-  EXPECT_TRUE(base::ContainsKey(urls, URL(kPath0)));
-  EXPECT_TRUE(base::ContainsKey(urls, URL(kPath1)));
-  EXPECT_TRUE(base::ContainsKey(urls, URL(kPath2)));
-  EXPECT_TRUE(base::ContainsKey(urls, URL(kPath3)));
+  EXPECT_TRUE(base::Contains(urls, URL(kPath0)));
+  EXPECT_TRUE(base::Contains(urls, URL(kPath1)));
+  EXPECT_TRUE(base::Contains(urls, URL(kPath2)));
+  EXPECT_TRUE(base::Contains(urls, URL(kPath3)));
 
   // Reset all changes for the file system.
   change_tracker()->ResetForFileSystem(
diff --git a/chrome/browser/sync_file_system/local/local_file_sync_context.cc b/chrome/browser/sync_file_system/local/local_file_sync_context.cc
index 3234d03..77e9687 100644
--- a/chrome/browser/sync_file_system/local/local_file_sync_context.cc
+++ b/chrome/browser/sync_file_system/local/local_file_sync_context.cc
@@ -68,7 +68,7 @@
     FileSystemContext* file_system_context,
     const SyncStatusCallback& callback) {
   DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
-  if (base::ContainsKey(file_system_contexts_, file_system_context)) {
+  if (base::Contains(file_system_contexts_, file_system_context)) {
     // The context has been already initialized. Just dispatch the callback
     // with SYNC_STATUS_OK.
     ui_task_runner_->PostTask(FROM_HERE,
@@ -737,8 +737,8 @@
     return;
   }
   DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
-  DCHECK(!base::ContainsKey(file_system_contexts_, file_system_context));
-  DCHECK(base::ContainsKey(pending_initialize_callbacks_, file_system_context));
+  DCHECK(!base::Contains(file_system_contexts_, file_system_context));
+  DCHECK(base::Contains(pending_initialize_callbacks_, file_system_context));
 
   SyncFileSystemBackend* backend =
       SyncFileSystemBackend::GetBackend(file_system_context);
diff --git a/chrome/browser/sync_file_system/local/local_file_sync_context_unittest.cc b/chrome/browser/sync_file_system/local/local_file_sync_context_unittest.cc
index 94087e2..b281d0cc 100644
--- a/chrome/browser/sync_file_system/local/local_file_sync_context_unittest.cc
+++ b/chrome/browser/sync_file_system/local/local_file_sync_context_unittest.cc
@@ -405,7 +405,7 @@
   FileSystemURLSet urls;
   file_system.GetChangedURLsInTracker(&urls);
   ASSERT_EQ(1U, urls.size());
-  EXPECT_TRUE(base::ContainsKey(urls, kURL));
+  EXPECT_TRUE(base::Contains(urls, kURL));
 
   // Finishing the test.
   sync_context_->ShutdownOnUIThread();
@@ -447,7 +447,7 @@
   FileSystemURLSet urls;
   file_system1.GetChangedURLsInTracker(&urls);
   ASSERT_EQ(1U, urls.size());
-  EXPECT_TRUE(base::ContainsKey(urls, kURL1));
+  EXPECT_TRUE(base::Contains(urls, kURL1));
 
   // file_system1's tracker must have no change.
   urls.clear();
@@ -461,13 +461,13 @@
   urls.clear();
   file_system1.GetChangedURLsInTracker(&urls);
   ASSERT_EQ(1U, urls.size());
-  EXPECT_TRUE(base::ContainsKey(urls, kURL1));
+  EXPECT_TRUE(base::Contains(urls, kURL1));
 
   // file_system2's tracker now must have the change for kURL2.
   urls.clear();
   file_system2.GetChangedURLsInTracker(&urls);
   ASSERT_EQ(1U, urls.size());
-  EXPECT_TRUE(base::ContainsKey(urls, kURL2));
+  EXPECT_TRUE(base::Contains(urls, kURL2));
 
   SyncFileMetadata metadata;
   FileChangeList changes;
@@ -627,9 +627,9 @@
   FileSystemURLSet urls;
   file_system.GetChangedURLsInTracker(&urls);
   ASSERT_EQ(3U, urls.size());
-  ASSERT_TRUE(base::ContainsKey(urls, kFile));
-  ASSERT_TRUE(base::ContainsKey(urls, kDir));
-  ASSERT_TRUE(base::ContainsKey(urls, kChild));
+  ASSERT_TRUE(base::Contains(urls, kFile));
+  ASSERT_TRUE(base::Contains(urls, kDir));
+  ASSERT_TRUE(base::Contains(urls, kChild));
   for (auto iter = urls.begin(); iter != urls.end(); ++iter) {
     file_system.ClearChangeForURLInTracker(*iter);
   }
@@ -788,7 +788,7 @@
   FileSystemURLSet urls;
   file_system.GetChangedURLsInTracker(&urls);
   ASSERT_EQ(1U, urls.size());
-  EXPECT_TRUE(base::ContainsKey(urls, kFile1));
+  EXPECT_TRUE(base::Contains(urls, kFile1));
   file_system.ClearChangeForURLInTracker(*urls.begin());
 
   // Prepare temporary files which represent the remote file data.
diff --git a/chrome/browser/sync_file_system/local/local_file_sync_service.cc b/chrome/browser/sync_file_system/local/local_file_sync_service.cc
index 0e3184c..f90d70f 100644
--- a/chrome/browser/sync_file_system/local/local_file_sync_service.cc
+++ b/chrome/browser/sync_file_system/local/local_file_sync_service.cc
@@ -68,7 +68,7 @@
       next_ = change_count_map_.begin();
     DCHECK_NE(0, next_->second);
     *origin = next_++->first;
-    if (!base::ContainsKey(disabled_origins_, *origin))
+    if (!base::Contains(disabled_origins_, *origin))
       return true;
   } while (next_ != begin);
   return false;
@@ -78,7 +78,7 @@
   int64_t num_changes = 0;
   for (auto iter = change_count_map_.begin(); iter != change_count_map_.end();
        ++iter) {
-    if (base::ContainsKey(disabled_origins_, iter->first))
+    if (base::Contains(disabled_origins_, iter->first))
       continue;
     num_changes += iter->second;
   }
@@ -164,7 +164,7 @@
     return;
   }
   DCHECK(!origin.is_empty());
-  DCHECK(base::ContainsKey(origin_to_contexts_, origin));
+  DCHECK(base::Contains(origin_to_contexts_, origin));
 
   DVLOG(1) << "Starting ProcessLocalChange";
 
@@ -187,7 +187,7 @@
 void LocalFileSyncService::HasPendingLocalChanges(
     const FileSystemURL& url,
     const HasPendingLocalChangeCallback& callback) {
-  if (!base::ContainsKey(origin_to_contexts_, url.origin().GetURL())) {
+  if (!base::Contains(origin_to_contexts_, url.origin().GetURL())) {
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE,
         base::BindOnce(callback, SYNC_FILE_ERROR_INVALID_URL, false));
@@ -217,7 +217,7 @@
 
 void LocalFileSyncService::GetLocalFileMetadata(
     const FileSystemURL& url, const SyncFileMetadataCallback& callback) {
-  DCHECK(base::ContainsKey(origin_to_contexts_, url.origin().GetURL()));
+  DCHECK(base::Contains(origin_to_contexts_, url.origin().GetURL()));
   sync_context_->GetFileMetadata(origin_to_contexts_[url.origin().GetURL()],
                                  url, callback);
 }
@@ -227,7 +227,7 @@
     const PrepareChangeCallback& callback) {
   DVLOG(1) << "PrepareForProcessRemoteChange: " << url.DebugString();
 
-  if (!base::ContainsKey(origin_to_contexts_, url.origin().GetURL())) {
+  if (!base::Contains(origin_to_contexts_, url.origin().GetURL())) {
     // This could happen if a remote sync is triggered for the app that hasn't
     // been initialized in this service.
     DCHECK(profile_);
@@ -262,7 +262,7 @@
     return;
   }
 
-  DCHECK(base::ContainsKey(origin_to_contexts_, url.origin().GetURL()));
+  DCHECK(base::Contains(origin_to_contexts_, url.origin().GetURL()));
   sync_context_->PrepareForSync(
       origin_to_contexts_[url.origin().GetURL()], url,
       LocalFileSyncContext::SYNC_EXCLUSIVE,
@@ -274,7 +274,7 @@
     const base::FilePath& local_path,
     const FileSystemURL& url,
     const SyncStatusCallback& callback) {
-  DCHECK(base::ContainsKey(origin_to_contexts_, url.origin().GetURL()));
+  DCHECK(base::Contains(origin_to_contexts_, url.origin().GetURL()));
   util::Log(logging::LOG_VERBOSE, FROM_HERE,
             "[Remote -> Local] ApplyRemoteChange: %s on %s",
             change.DebugString().c_str(),
@@ -290,7 +290,7 @@
     const FileSystemURL& url,
     bool clear_local_changes,
     const base::Closure& completion_callback) {
-  DCHECK(base::ContainsKey(origin_to_contexts_, url.origin().GetURL()));
+  DCHECK(base::Contains(origin_to_contexts_, url.origin().GetURL()));
   sync_context_->FinalizeExclusiveSync(
       origin_to_contexts_[url.origin().GetURL()], url, clear_local_changes,
       completion_callback);
@@ -300,7 +300,7 @@
     const FileSystemURL& url,
     const FileChange& change,
     const SyncStatusCallback& callback) {
-  DCHECK(base::ContainsKey(origin_to_contexts_, url.origin().GetURL()));
+  DCHECK(base::Contains(origin_to_contexts_, url.origin().GetURL()));
   sync_context_->RecordFakeLocalChange(
       origin_to_contexts_[url.origin().GetURL()], url, change, callback);
 }
@@ -310,7 +310,7 @@
   bool need_notification = false;
   for (auto iter = origins.begin(); iter != origins.end(); ++iter) {
     const GURL& origin = *iter;
-    if (!base::ContainsKey(origin_to_contexts_, origin)) {
+    if (!base::Contains(origin_to_contexts_, origin)) {
       // This could happen if this is called for apps/origins that haven't
       // been initialized yet, or for apps/origins that are disabled.
       // (Local change tracker could call this for uninitialized origins
@@ -335,7 +335,7 @@
 }
 
 void LocalFileSyncService::SetOriginEnabled(const GURL& origin, bool enabled) {
-  if (!base::ContainsKey(origin_to_contexts_, origin))
+  if (!base::Contains(origin_to_contexts_, origin))
     return;
   origin_change_map_.SetOriginEnabled(origin, enabled);
 }
@@ -471,7 +471,7 @@
 
   const FileSystemURL& url = sync_file_info.url;
   if (status != SYNC_STATUS_OK || changes.empty()) {
-    DCHECK(base::ContainsKey(origin_to_contexts_, url.origin().GetURL()));
+    DCHECK(base::Contains(origin_to_contexts_, url.origin().GetURL()));
     sync_context_->FinalizeSnapshotSync(
         origin_to_contexts_[url.origin().GetURL()], url, status,
         base::Bind(callback, status, url));
diff --git a/chrome/browser/sync_file_system/local/local_file_sync_service_unittest.cc b/chrome/browser/sync_file_system/local/local_file_sync_service_unittest.cc
index 4fee8dc..12b5784 100644
--- a/chrome/browser/sync_file_system/local/local_file_sync_service_unittest.cc
+++ b/chrome/browser/sync_file_system/local/local_file_sync_service_unittest.cc
@@ -634,7 +634,7 @@
   GURL origin;
   while (!all_origins.empty()) {
     ASSERT_TRUE(NextOriginToProcess(&origin));
-    ASSERT_TRUE(base::ContainsKey(all_origins, origin));
+    ASSERT_TRUE(base::Contains(all_origins, origin));
     all_origins.erase(origin);
   }
 
@@ -647,7 +647,7 @@
   all_origins.insert(kOrigin3);
   while (!all_origins.empty()) {
     ASSERT_TRUE(NextOriginToProcess(&origin));
-    ASSERT_TRUE(base::ContainsKey(all_origins, origin));
+    ASSERT_TRUE(base::Contains(all_origins, origin));
     all_origins.erase(origin);
   }
 
@@ -658,7 +658,7 @@
   all_origins.insert(kOrigin3);
   while (!all_origins.empty()) {
     ASSERT_TRUE(NextOriginToProcess(&origin));
-    ASSERT_TRUE(base::ContainsKey(all_origins, origin));
+    ASSERT_TRUE(base::Contains(all_origins, origin));
     all_origins.erase(origin);
   }
 
@@ -669,7 +669,7 @@
   all_origins.insert(kOrigins, kOrigins + base::size(kOrigins));
   while (!all_origins.empty()) {
     ASSERT_TRUE(NextOriginToProcess(&origin));
-    ASSERT_TRUE(base::ContainsKey(all_origins, origin));
+    ASSERT_TRUE(base::Contains(all_origins, origin));
     all_origins.erase(origin);
   }
 }
@@ -694,7 +694,7 @@
   GURL origin;
   while (!all_origins.empty()) {
     ASSERT_TRUE(NextOriginToProcess(&origin));
-    ASSERT_TRUE(base::ContainsKey(all_origins, origin));
+    ASSERT_TRUE(base::Contains(all_origins, origin));
     all_origins.erase(origin);
   }
 
@@ -706,7 +706,7 @@
   all_origins.insert(kOrigin3);
   while (!all_origins.empty()) {
     ASSERT_TRUE(NextOriginToProcess(&origin));
-    ASSERT_TRUE(base::ContainsKey(all_origins, origin));
+    ASSERT_TRUE(base::Contains(all_origins, origin));
     all_origins.erase(origin);
   }
 
@@ -726,7 +726,7 @@
   all_origins.insert(kOrigin3);
   while (!all_origins.empty()) {
     ASSERT_TRUE(NextOriginToProcess(&origin));
-    ASSERT_TRUE(base::ContainsKey(all_origins, origin));
+    ASSERT_TRUE(base::Contains(all_origins, origin));
     all_origins.erase(origin);
   }
 }
diff --git a/chrome/browser/sync_file_system/local/local_file_sync_status.cc b/chrome/browser/sync_file_system/local/local_file_sync_status.cc
index 71cbba6d..7394157 100644
--- a/chrome/browser/sync_file_system/local/local_file_sync_status.cc
+++ b/chrome/browser/sync_file_system/local/local_file_sync_status.cc
@@ -60,7 +60,7 @@
 
   // Check if any ancestor of |normalized_path| is in |writing_|.
   while (true) {
-    if (base::ContainsKey(paths, normalized_path))
+    if (base::Contains(paths, normalized_path))
       return true;
 
     if (storage::VirtualPath::IsRootPath(normalized_path))
diff --git a/chrome/browser/sync_file_system/local/syncable_file_system_unittest.cc b/chrome/browser/sync_file_system/local/syncable_file_system_unittest.cc
index 8e8cc41b..1f2d54f 100644
--- a/chrome/browser/sync_file_system/local/syncable_file_system_unittest.cc
+++ b/chrome/browser/sync_file_system/local/syncable_file_system_unittest.cc
@@ -198,9 +198,9 @@
   file_system_.GetChangedURLsInTracker(&urls);
 
   EXPECT_EQ(3U, urls.size());
-  EXPECT_TRUE(base::ContainsKey(urls, URL(kPath0)));
-  EXPECT_TRUE(base::ContainsKey(urls, URL(kPath1)));
-  EXPECT_TRUE(base::ContainsKey(urls, URL(kPath2)));
+  EXPECT_TRUE(base::Contains(urls, URL(kPath0)));
+  EXPECT_TRUE(base::Contains(urls, URL(kPath1)));
+  EXPECT_TRUE(base::Contains(urls, URL(kPath2)));
 
   VerifyAndClearChange(URL(kPath0),
                        FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
@@ -232,9 +232,9 @@
 
   // kPath0 and its all chidren (kPath1 and kPath2) must have been deleted.
   EXPECT_EQ(3U, urls.size());
-  EXPECT_TRUE(base::ContainsKey(urls, URL(kPath0)));
-  EXPECT_TRUE(base::ContainsKey(urls, URL(kPath1)));
-  EXPECT_TRUE(base::ContainsKey(urls, URL(kPath2)));
+  EXPECT_TRUE(base::Contains(urls, URL(kPath0)));
+  EXPECT_TRUE(base::Contains(urls, URL(kPath1)));
+  EXPECT_TRUE(base::Contains(urls, URL(kPath2)));
 
   VerifyAndClearChange(URL(kPath0),
                        FileChange(FileChange::FILE_CHANGE_DELETE,
diff --git a/chrome/browser/sync_file_system/subtree_set.cc b/chrome/browser/sync_file_system/subtree_set.cc
index 6dfc3e1c..8c60af35 100644
--- a/chrome/browser/sync_file_system/subtree_set.cc
+++ b/chrome/browser/sync_file_system/subtree_set.cc
@@ -30,8 +30,8 @@
       storage::VirtualPath::GetNormalizedFilePath(subtree_root);
 
   // Check if |subtree_root| contains any of subtrees in the container.
-  if (base::ContainsKey(inclusive_ancestors_of_subtree_roots_,
-                        normalized_subtree_root))
+  if (base::Contains(inclusive_ancestors_of_subtree_roots_,
+                     normalized_subtree_root))
     return false;
 
   base::FilePath path(normalized_subtree_root);
diff --git a/chrome/browser/task_manager/sampling/task_manager_impl.cc b/chrome/browser/task_manager/sampling/task_manager_impl.cc
index 866dea9..425fb545b 100644
--- a/chrome/browser/task_manager/sampling/task_manager_impl.cc
+++ b/chrome/browser/task_manager/sampling/task_manager_impl.cc
@@ -63,6 +63,15 @@
 
 }  // namespace
 
+size_t BytesTransferredKey::Hasher::operator()(
+    const BytesTransferredKey& key) const {
+  return base::HashInts(key.child_id, key.route_id);
+}
+
+bool BytesTransferredKey::operator==(const BytesTransferredKey& other) const {
+  return child_id == other.child_id && route_id == other.route_id;
+}
+
 TaskManagerImpl::TaskManagerImpl()
     : on_background_data_ready_callback_(
           base::Bind(&TaskManagerImpl::OnTaskGroupBackgroundCalculationsDone,
@@ -520,33 +529,9 @@
   NotifyObserversOnTaskUnresponsive(task->task_id());
 }
 
-// static
-void TaskManagerImpl::OnMultipleBytesTransferredUI(BytesTransferredMap params) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
-  for (const auto& entry : params) {
-    const BytesTransferredKey& process_info = entry.first;
-    const BytesTransferredParam& bytes_transferred = entry.second;
-
-    if (!GetInstance()->UpdateTasksWithBytesTransferred(process_info,
-                                                        bytes_transferred)) {
-      // We can't match a task to the notification.  That might mean the
-      // tab that started a download was closed, or the request may have had
-      // no originating task associated with it in the first place.
-      //
-      // Orphaned/unaccounted activity is credited to the Browser process.
-      BytesTransferredKey browser_process_key = {
-          content::ChildProcessHost::kInvalidUniqueID, MSG_ROUTING_NONE};
-      GetInstance()->UpdateTasksWithBytesTransferred(browser_process_key,
-                                                     bytes_transferred);
-    }
-  }
-}
-
 void TaskManagerImpl::OnTotalNetworkUsages(
     std::vector<network::mojom::NetworkUsagePtr> total_network_usages) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService));
   BytesTransferredMap new_total_network_usages_map;
   for (const auto& entry : total_network_usages) {
     BytesTransferredKey process_info = {entry->process_id, entry->routing_id};
@@ -625,8 +610,7 @@
                                         std::move(callback));
   }
 
-  if (base::FeatureList::IsEnabled(network::features::kNetworkService) &&
-      TaskManagerObserver::IsResourceRefreshEnabled(
+  if (TaskManagerObserver::IsResourceRefreshEnabled(
           REFRESH_TYPE_NETWORK_USAGE, enabled_resources_flags())) {
     content::GetNetworkService()->GetTotalNetworkUsages(
         base::BindOnce(&TaskManagerImpl::OnTotalNetworkUsages,
@@ -663,10 +647,6 @@
   for (const auto& provider : task_providers_)
     provider->SetObserver(this);
 
-  if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
-    io_thread_helper_manager_.reset(new IoThreadHelperManager(
-        base::BindRepeating(&TaskManagerImpl::OnMultipleBytesTransferredUI)));
-  }
   // Kick off fetch of asynchronous data, e.g., memory footprint, so that it
   // will be displayed sooner after opening the task manager.
   Refresh();
@@ -678,8 +658,6 @@
 
   is_running_ = false;
 
-  io_thread_helper_manager_.reset();
-
   for (const auto& provider : task_providers_)
     provider->ClearObserver();
 
diff --git a/chrome/browser/task_manager/sampling/task_manager_impl.h b/chrome/browser/task_manager/sampling/task_manager_impl.h
index 9dc4cb3..f96a72d 100644
--- a/chrome/browser/task_manager/sampling/task_manager_impl.h
+++ b/chrome/browser/task_manager/sampling/task_manager_impl.h
@@ -22,7 +22,6 @@
 #include "chrome/browser/task_manager/providers/task_provider_observer.h"
 #include "chrome/browser/task_manager/sampling/arc_shared_sampler.h"
 #include "chrome/browser/task_manager/sampling/task_group.h"
-#include "chrome/browser/task_manager/sampling/task_manager_io_thread_helper.h"
 #include "chrome/browser/task_manager/task_manager_interface.h"
 #include "gpu/ipc/common/memory_stats.h"
 #include "services/network/public/mojom/network_service.mojom.h"
@@ -32,6 +31,38 @@
 
 class SharedSampler;
 
+// Identifies the initiator of a network request, by a (child_id,
+// route_id) tuple.
+// BytesTransferredKey supports hashing and may be used as an unordered_map key.
+struct BytesTransferredKey {
+  // The unique ID of the host of the child process requester.
+  int child_id;
+
+  // The ID of the IPC route for the URLRequest (this identifies the
+  // RenderView or like-thing in the renderer that the request gets routed
+  // to).
+  int route_id;
+
+  struct Hasher {
+    size_t operator()(const BytesTransferredKey& key) const;
+  };
+
+  bool operator==(const BytesTransferredKey& other) const;
+};
+
+// This is the entry of the unordered map that tracks bytes transfered by task.
+struct BytesTransferredParam {
+  // The number of bytes read.
+  int64_t byte_read_count = 0;
+
+  // The number of bytes sent.
+  int64_t byte_sent_count = 0;
+};
+
+using BytesTransferredMap = std::unordered_map<BytesTransferredKey,
+                                               BytesTransferredParam,
+                                               BytesTransferredKey::Hasher>;
+
 // Defines a concrete implementation of the TaskManagerInterface.
 class TaskManagerImpl : public TaskManagerInterface,
                         public TaskProviderObserver {
@@ -98,12 +129,6 @@
   void TaskRemoved(Task* task) override;
   void TaskUnresponsive(Task* task) override;
 
-  // Used when Network Service is disabled.
-  // The notification method on the UI thread when multiple bytes are
-  // transferred from URLRequests. This will be called by the
-  // |io_thread_helper_|.
-  static void OnMultipleBytesTransferredUI(BytesTransferredMap params);
-
   // Used when Network Service is enabled.
   // Receives total network usages from |NetworkService|.
   void OnTotalNetworkUsages(
@@ -165,12 +190,6 @@
   // A cached sorted list of the task IDs.
   mutable std::vector<TaskId> sorted_task_ids_;
 
-  // Used when Network Service is disabled.
-  // The manager of the IO thread helper used to handle network bytes
-  // notifications on IO thread. The manager itself lives on the UI thread, but
-  // the IO thread helper lives entirely on the IO thread.
-  std::unique_ptr<IoThreadHelperManager> io_thread_helper_manager_;
-
   // Used when Network Service is enabled.
   // Stores the total network usages per |process_id, routing_id| from last
   // refresh.
diff --git a/chrome/browser/task_manager/sampling/task_manager_io_thread_helper.cc b/chrome/browser/task_manager/sampling/task_manager_io_thread_helper.cc
deleted file mode 100644
index 15bec7a..0000000
--- a/chrome/browser/task_manager/sampling/task_manager_io_thread_helper.cc
+++ /dev/null
@@ -1,127 +0,0 @@
-// Copyright 2015 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/task_manager/sampling/task_manager_io_thread_helper.h"
-
-#include "base/bind.h"
-#include "base/task/post_task.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "chrome/browser/task_manager/sampling/task_manager_impl.h"
-#include "content/public/browser/browser_task_traits.h"
-#include "content/public/browser/browser_thread.h"
-
-namespace task_manager {
-
-namespace {
-
-TaskManagerIoThreadHelper* g_io_thread_helper = nullptr;
-
-}  // namespace
-
-size_t BytesTransferredKey::Hasher::operator()(
-    const BytesTransferredKey& key) const {
-  return base::HashInts(key.child_id, key.route_id);
-}
-
-bool BytesTransferredKey::operator==(const BytesTransferredKey& other) const {
-  return child_id == other.child_id && route_id == other.route_id;
-}
-
-IoThreadHelperManager::IoThreadHelperManager(
-    BytesTransferredCallback result_callback) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
-  base::PostTaskWithTraits(
-      FROM_HERE, {content::BrowserThread::IO},
-      base::BindOnce(&TaskManagerIoThreadHelper::CreateInstance,
-                     std::move(result_callback)));
-}
-
-IoThreadHelperManager::~IoThreadHelperManager() {
-  // This may be called at exit time when the main thread is no longer
-  // registered as the UI thread.
-  DCHECK(
-      content::BrowserThread::CurrentlyOn(content::BrowserThread::UI) ||
-      !content::BrowserThread::IsThreadInitialized(content::BrowserThread::UI));
-
-  base::PostTaskWithTraits(
-      FROM_HERE, {content::BrowserThread::IO},
-      base::BindOnce(&TaskManagerIoThreadHelper::DeleteInstance));
-}
-
-// static
-void TaskManagerIoThreadHelper::CreateInstance(
-    BytesTransferredCallback result_callback) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-  DCHECK(!g_io_thread_helper);
-
-  g_io_thread_helper =
-      new TaskManagerIoThreadHelper(std::move(result_callback));
-}
-
-// static
-void TaskManagerIoThreadHelper::DeleteInstance() {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-
-  delete g_io_thread_helper;
-  g_io_thread_helper = nullptr;
-}
-
-// static
-void TaskManagerIoThreadHelper::OnRawBytesTransferred(BytesTransferredKey key,
-                                                      int64_t bytes_read,
-                                                      int64_t bytes_sent) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-
-  if (g_io_thread_helper)
-    g_io_thread_helper->OnNetworkBytesTransferred(key, bytes_read, bytes_sent);
-}
-
-TaskManagerIoThreadHelper::TaskManagerIoThreadHelper(
-    BytesTransferredCallback result_callback)
-    : result_callback_(std::move(result_callback)), weak_factory_(this) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-}
-
-TaskManagerIoThreadHelper::~TaskManagerIoThreadHelper() {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-}
-
-void TaskManagerIoThreadHelper::OnMultipleBytesTransferredIO() {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-  DCHECK(!bytes_transferred_unordered_map_.empty());
-
-  base::PostTaskWithTraits(
-      FROM_HERE, {content::BrowserThread::UI},
-      base::BindOnce(result_callback_,
-                     std::move(bytes_transferred_unordered_map_)));
-  bytes_transferred_unordered_map_.clear();
-  DCHECK(bytes_transferred_unordered_map_.empty());
-}
-
-void TaskManagerIoThreadHelper::OnNetworkBytesTransferred(
-    BytesTransferredKey key,
-    int64_t bytes_read,
-    int64_t bytes_sent) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-
-  if (bytes_transferred_unordered_map_.empty()) {
-    // Schedule a task to process the transferred bytes requests a second from
-    // now. We're trying to calculate the tasks' network usage speed as bytes
-    // per second so we collect as many requests during one seconds before the
-    // below delayed TaskManagerIoThreadHelper::OnMultipleBytesReadIO() process
-    // them after one second from now.
-    base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
-        FROM_HERE,
-        base::BindOnce(&TaskManagerIoThreadHelper::OnMultipleBytesTransferredIO,
-                       weak_factory_.GetWeakPtr()),
-        base::TimeDelta::FromSeconds(1));
-  }
-
-  BytesTransferredParam& entry = bytes_transferred_unordered_map_[key];
-  entry.byte_read_count += bytes_read;
-  entry.byte_sent_count += bytes_sent;
-}
-
-}  // namespace task_manager
diff --git a/chrome/browser/task_manager/sampling/task_manager_io_thread_helper.h b/chrome/browser/task_manager/sampling/task_manager_io_thread_helper.h
deleted file mode 100644
index b2b2dc0b..0000000
--- a/chrome/browser/task_manager/sampling/task_manager_io_thread_helper.h
+++ /dev/null
@@ -1,115 +0,0 @@
-// Copyright 2015 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_TASK_MANAGER_SAMPLING_TASK_MANAGER_IO_THREAD_HELPER_H_
-#define CHROME_BROWSER_TASK_MANAGER_SAMPLING_TASK_MANAGER_IO_THREAD_HELPER_H_
-
-#include <stdint.h>
-
-#include <unordered_map>
-
-#include "base/callback.h"
-#include "base/hash/hash.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-
-namespace net {
-class URLRequest;
-}  // namespace net
-
-namespace task_manager {
-
-// Identifies the initiator of a network request, by a (child_id,
-// route_id) tuple.
-// BytesTransferredKey supports hashing and may be used as an unordered_map key.
-struct BytesTransferredKey {
-  // The unique ID of the host of the child process requester.
-  int child_id;
-
-  // The ID of the IPC route for the URLRequest (this identifies the
-  // RenderView or like-thing in the renderer that the request gets routed
-  // to).
-  int route_id;
-
-  struct Hasher {
-    size_t operator()(const BytesTransferredKey& key) const;
-  };
-
-  bool operator==(const BytesTransferredKey& other) const;
-};
-
-// This is the entry of the unordered map that tracks bytes transfered by task.
-struct BytesTransferredParam {
-  // The number of bytes read.
-  int64_t byte_read_count = 0;
-
-  // The number of bytes sent.
-  int64_t byte_sent_count = 0;
-};
-
-using BytesTransferredMap = std::unordered_map<BytesTransferredKey,
-                                               BytesTransferredParam,
-                                               BytesTransferredKey::Hasher>;
-
-using BytesTransferredCallback =
-    base::RepeatingCallback<void(BytesTransferredMap)>;
-
-// Defines a utility class used to schedule the creation and removal of the
-// TaskManagerIoThreadHelper on the IO thread.
-class IoThreadHelperManager {
- public:
-  // A callback that executes whenever there is activity that registers that
-  // bytes have been transferred. It is called from task_manager_impl.cc binding
-  // |OnMultipleBytesTranferred|.
-  explicit IoThreadHelperManager(BytesTransferredCallback result_callback);
-  ~IoThreadHelperManager();
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(IoThreadHelperManager);
-};
-
-// Defines a class used by the task manager to receive notifications of the
-// network bytes transferred by the various tasks.
-// This object lives entirely only on the IO thread.
-class TaskManagerIoThreadHelper {
- public:
-  // Create and delete the instance of this class. They must be called on the IO
-  // thread.
-  static void CreateInstance(BytesTransferredCallback result_callback);
-  static void DeleteInstance();
-
-  // This is used to forward the call to update the network bytes with
-  // transferred bytes from the TaskManagerInterface.
-  static void OnRawBytesTransferred(BytesTransferredKey key,
-                                    int64_t bytes_read,
-                                    int64_t bytes_sent);
-
- private:
-  explicit TaskManagerIoThreadHelper(BytesTransferredCallback result_callback);
-  ~TaskManagerIoThreadHelper();
-
-  // We gather multiple notifications on the IO thread in one second before a
-  // call is made to the following function to start the processing for
-  // transferred bytes.
-  void OnMultipleBytesTransferredIO();
-
-  // This will update the task manager with the network bytes read.
-  void OnNetworkBytesTransferred(BytesTransferredKey key,
-                                 int64_t bytes_read,
-                                 int64_t bytes_sent);
-
-  // This unordered_map will be filled on IO thread with information about the
-  // number of bytes transferred from URLRequests.
-  BytesTransferredMap bytes_transferred_unordered_map_;
-
-  BytesTransferredCallback result_callback_;
-
-  base::WeakPtrFactory<TaskManagerIoThreadHelper> weak_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(TaskManagerIoThreadHelper);
-};
-
-}  // namespace task_manager
-
-#endif  // CHROME_BROWSER_TASK_MANAGER_SAMPLING_TASK_MANAGER_IO_THREAD_HELPER_H_
diff --git a/chrome/browser/task_manager/sampling/task_manager_io_thread_helper_unittest.cc b/chrome/browser/task_manager/sampling/task_manager_io_thread_helper_unittest.cc
deleted file mode 100644
index bf628884..0000000
--- a/chrome/browser/task_manager/sampling/task_manager_io_thread_helper_unittest.cc
+++ /dev/null
@@ -1,289 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/bind.h"
-#include "base/run_loop.h"
-#include "base/test/scoped_mock_time_message_loop_task_runner.h"
-#include "chrome/browser/task_manager/sampling/task_manager_impl.h"
-#include "content/public/test/test_browser_thread_bundle.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace task_manager {
-
-class TaskManagerIoThreadHelperTest : public testing::Test {
- public:
-  TaskManagerIoThreadHelperTest()
-      : helper_manager_(
-            base::BindRepeating(&TaskManagerIoThreadHelperTest::GotData,
-                                base::Unretained(this))) {
-    base::RunLoop().RunUntilIdle();
-  }
-  ~TaskManagerIoThreadHelperTest() override {}
-
-  void GotData(BytesTransferredMap params) {
-    EXPECT_TRUE(returned_map_.empty()) << "GotData() delivered twice";
-    EXPECT_FALSE(params.empty()) << "GotData() called with empty map";
-    returned_map_ = params;
-  }
-
- protected:
-  BytesTransferredMap returned_map_;
-
- private:
-  content::TestBrowserThreadBundle thread_bundle_;
-  IoThreadHelperManager helper_manager_;
-
-  DISALLOW_COPY_AND_ASSIGN(TaskManagerIoThreadHelperTest);
-};
-
-// Tests that the |child_id| and |route_id| are used in the map correctly.
-TEST_F(TaskManagerIoThreadHelperTest, ChildRouteData) {
-  base::ScopedMockTimeMessageLoopTaskRunner mock_main_runner;
-
-  BytesTransferredKey key = {100, 190};
-
-  int64_t correct_read_bytes = 0;
-  int64_t correct_sent_bytes = 0;
-
-  int read_bytes_array[] = {900, 300, 100};
-  int sent_bytes_array[] = {130, 153, 934};
-
-  for (int i : read_bytes_array) {
-    TaskManagerIoThreadHelper::OnRawBytesTransferred(key, i, 0);
-    correct_read_bytes += i;
-  }
-  for (int i : sent_bytes_array) {
-    TaskManagerIoThreadHelper::OnRawBytesTransferred(key, 0, i);
-    correct_sent_bytes += i;
-  }
-
-  EXPECT_TRUE(mock_main_runner->HasPendingTask());
-  mock_main_runner->FastForwardBy(base::TimeDelta::FromSeconds(1));
-  base::RunLoop().RunUntilIdle();
-  EXPECT_FALSE(mock_main_runner->HasPendingTask());
-  EXPECT_EQ(1U, returned_map_.size());
-  EXPECT_EQ(correct_sent_bytes, returned_map_[key].byte_sent_count);
-  EXPECT_EQ(correct_read_bytes, returned_map_[key].byte_read_count);
-}
-
-// Tests that two distinct |child_id| and |route_id| pairs are tracked
-// separately in the unordered map.
-TEST_F(TaskManagerIoThreadHelperTest, TwoChildRouteData) {
-  base::ScopedMockTimeMessageLoopTaskRunner mock_main_runner;
-
-  BytesTransferredKey key1 = {32, 1};
-  BytesTransferredKey key2 = {17, 2};
-
-  int64_t correct_read_bytes1 = 0;
-  int64_t correct_sent_bytes1 = 0;
-
-  int64_t correct_read_bytes2 = 0;
-  int64_t correct_sent_bytes2 = 0;
-
-  int read_bytes_array1[] = {453, 987654, 946650};
-  int sent_bytes_array1[] = {138450, 1556473, 954434};
-
-  int read_bytes_array2[] = {905643, 324340, 654150};
-  int sent_bytes_array2[] = {1232138, 157312, 965464};
-
-  for (int i : read_bytes_array1) {
-    TaskManagerIoThreadHelper::OnRawBytesTransferred(key1, i, 0);
-    correct_read_bytes1 += i;
-  }
-  for (int i : sent_bytes_array1) {
-    TaskManagerIoThreadHelper::OnRawBytesTransferred(key1, 0, i);
-    correct_sent_bytes1 += i;
-  }
-
-  for (int i : read_bytes_array2) {
-    TaskManagerIoThreadHelper::OnRawBytesTransferred(key2, i, 0);
-    correct_read_bytes2 += i;
-  }
-  for (int i : sent_bytes_array2) {
-    TaskManagerIoThreadHelper::OnRawBytesTransferred(key2, 0, i);
-    correct_sent_bytes2 += i;
-  }
-
-  EXPECT_TRUE(mock_main_runner->HasPendingTask());
-  mock_main_runner->FastForwardBy(base::TimeDelta::FromSeconds(1));
-  base::RunLoop().RunUntilIdle();
-  const unsigned long number_of_keys = 2;
-  EXPECT_EQ(number_of_keys, returned_map_.size());
-  EXPECT_FALSE(mock_main_runner->HasPendingTask());
-  EXPECT_EQ(correct_sent_bytes1, returned_map_[key1].byte_sent_count);
-  EXPECT_EQ(correct_read_bytes1, returned_map_[key1].byte_read_count);
-  EXPECT_EQ(correct_sent_bytes2, returned_map_[key2].byte_sent_count);
-  EXPECT_EQ(correct_read_bytes2, returned_map_[key2].byte_read_count);
-}
-
-// Tests that two keys with the same |child_id| and |route_id| are tracked
-// together in the unordered map.
-TEST_F(TaskManagerIoThreadHelperTest, TwoSameChildRouteData) {
-  base::ScopedMockTimeMessageLoopTaskRunner mock_main_runner;
-
-  BytesTransferredKey key1 = {123, 456};
-  BytesTransferredKey key2 = {123, 456};
-
-  int64_t correct_read_bytes = 0;
-  int64_t correct_sent_bytes = 0;
-
-  int read_bytes_array[] = {90440, 12300, 103420};
-  int sent_bytes_array[] = {44130, 12353, 93234};
-
-  for (int i : read_bytes_array) {
-    TaskManagerIoThreadHelper::OnRawBytesTransferred(key1, i, 0);
-    correct_read_bytes += i;
-  }
-  for (int i : sent_bytes_array) {
-    TaskManagerIoThreadHelper::OnRawBytesTransferred(key1, 0, i);
-    correct_sent_bytes += i;
-  }
-
-  for (int i : read_bytes_array) {
-    TaskManagerIoThreadHelper::OnRawBytesTransferred(key2, i, 0);
-    correct_read_bytes += i;
-  }
-  for (int i : sent_bytes_array) {
-    TaskManagerIoThreadHelper::OnRawBytesTransferred(key2, 0, i);
-    correct_sent_bytes += i;
-  }
-
-  mock_main_runner->FastForwardBy(base::TimeDelta::FromSeconds(1));
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(1U, returned_map_.size());
-  EXPECT_EQ(correct_sent_bytes, returned_map_[key1].byte_sent_count);
-  EXPECT_EQ(correct_read_bytes, returned_map_[key1].byte_read_count);
-  EXPECT_EQ(correct_sent_bytes, returned_map_[key2].byte_sent_count);
-  EXPECT_EQ(correct_read_bytes, returned_map_[key2].byte_read_count);
-}
-
-// Tests that the map can handle two child_ids with the same route_id.
-TEST_F(TaskManagerIoThreadHelperTest, SameRouteDifferentProcesses) {
-  base::ScopedMockTimeMessageLoopTaskRunner mock_main_runner;
-  BytesTransferredKey key1 = {12, 143};
-  BytesTransferredKey key2 = {13, 143};
-
-  int64_t correct_read_bytes1 = 0;
-  int64_t correct_sent_bytes1 = 0;
-
-  int64_t correct_read_bytes2 = 0;
-  int64_t correct_sent_bytes2 = 0;
-
-  int read_bytes_array1[] = {453, 98754, 94650};
-  int sent_bytes_array1[] = {1350, 15643, 95434};
-
-  int read_bytes_array2[] = {905643, 3243, 654150};
-  int sent_bytes_array2[] = {12338, 157312, 9664};
-
-  for (int i : read_bytes_array1) {
-    TaskManagerIoThreadHelper::OnRawBytesTransferred(key1, i, 0);
-    correct_read_bytes1 += i;
-  }
-  for (int i : sent_bytes_array1) {
-    TaskManagerIoThreadHelper::OnRawBytesTransferred(key1, 0, i);
-    correct_sent_bytes1 += i;
-  }
-
-  for (int i : read_bytes_array2) {
-    TaskManagerIoThreadHelper::OnRawBytesTransferred(key2, i, 0);
-    correct_read_bytes2 += i;
-  }
-  for (int i : sent_bytes_array2) {
-    TaskManagerIoThreadHelper::OnRawBytesTransferred(key2, 0, i);
-    correct_sent_bytes2 += i;
-  }
-
-  mock_main_runner->FastForwardBy(base::TimeDelta::FromSeconds(1));
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(2U, returned_map_.size());
-  EXPECT_EQ(correct_sent_bytes1, returned_map_[key1].byte_sent_count);
-  EXPECT_EQ(correct_read_bytes1, returned_map_[key1].byte_read_count);
-  EXPECT_EQ(correct_sent_bytes2, returned_map_[key2].byte_sent_count);
-  EXPECT_EQ(correct_read_bytes2, returned_map_[key2].byte_read_count);
-}
-
-// Tests that the map can store both types of keys and that it does update after
-// 1 mocked second passes and there is new traffic.
-TEST_F(TaskManagerIoThreadHelperTest, MultipleWavesMixedData) {
-  base::ScopedMockTimeMessageLoopTaskRunner mock_main_runner;
-
-  BytesTransferredKey key1 = {12, 143};
-  BytesTransferredKey key2 = {-1, -1};
-
-  int64_t correct_read_bytes1 = 0;
-  int64_t correct_sent_bytes1 = 0;
-
-  int read_bytes_array1[] = {453, 98754, 94650};
-  int sent_bytes_array1[] = {1350, 15643, 95434};
-
-  for (int i : read_bytes_array1) {
-    TaskManagerIoThreadHelper::OnRawBytesTransferred(key1, i, 0);
-    correct_read_bytes1 += i;
-  }
-  for (int i : sent_bytes_array1) {
-    TaskManagerIoThreadHelper::OnRawBytesTransferred(key1, 0, i);
-    correct_sent_bytes1 += i;
-  }
-
-  mock_main_runner->FastForwardBy(base::TimeDelta::FromSeconds(1));
-  base::RunLoop().RunUntilIdle();
-  returned_map_.clear();
-
-  correct_sent_bytes1 = 0;
-  correct_read_bytes1 = 0;
-
-  TaskManagerIoThreadHelper::OnRawBytesTransferred(key1, 0, 10);
-  correct_sent_bytes1 += 10;
-
-  mock_main_runner->FastForwardBy(base::TimeDelta::FromSeconds(1));
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(1U, returned_map_.size());
-  EXPECT_EQ(correct_sent_bytes1, returned_map_[key1].byte_sent_count);
-  EXPECT_EQ(correct_read_bytes1, returned_map_[key1].byte_read_count);
-  // |key2| has not been used yet so it should call the implicit constructor
-  // which starts at 0.
-  EXPECT_EQ(0U, returned_map_[key2].byte_sent_count);
-  EXPECT_EQ(0U, returned_map_[key2].byte_read_count);
-  returned_map_.clear();
-
-  correct_read_bytes1 = 0;
-  correct_sent_bytes1 = 0;
-
-  int correct_read_bytes2 = 0;
-  int correct_sent_bytes2 = 0;
-
-  int read_bytes_array_second_1[] = {4153, 987154, 946501};
-  int sent_bytes_array_second_1[] = {13510, 115643, 954134};
-
-  int read_bytes_array2[] = {9056243, 32243, 6541250};
-  int sent_bytes_array2[] = {123238, 1527312, 96624};
-
-  for (int i : read_bytes_array_second_1) {
-    TaskManagerIoThreadHelper::OnRawBytesTransferred(key1, i, 0);
-    correct_read_bytes1 += i;
-  }
-  for (int i : sent_bytes_array_second_1) {
-    TaskManagerIoThreadHelper::OnRawBytesTransferred(key1, 0, i);
-    correct_sent_bytes1 += i;
-  }
-
-  for (int i : read_bytes_array2) {
-    TaskManagerIoThreadHelper::OnRawBytesTransferred(key2, i, 0);
-    correct_read_bytes2 += i;
-  }
-  for (int i : sent_bytes_array2) {
-    TaskManagerIoThreadHelper::OnRawBytesTransferred(key2, 0, i);
-    correct_sent_bytes2 += i;
-  }
-
-  mock_main_runner->FastForwardBy(base::TimeDelta::FromSeconds(1));
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(2U, returned_map_.size());
-  EXPECT_EQ(correct_sent_bytes1, returned_map_[key1].byte_sent_count);
-  EXPECT_EQ(correct_read_bytes1, returned_map_[key1].byte_read_count);
-  EXPECT_EQ(correct_sent_bytes2, returned_map_[key2].byte_sent_count);
-  EXPECT_EQ(correct_read_bytes2, returned_map_[key2].byte_read_count);
-}
-
-}  // namespace task_manager
diff --git a/chrome/browser/task_manager/task_manager_interface.cc b/chrome/browser/task_manager/task_manager_interface.cc
index d35022d..3357a9d 100644
--- a/chrome/browser/task_manager/task_manager_interface.cc
+++ b/chrome/browser/task_manager/task_manager_interface.cc
@@ -7,13 +7,11 @@
 #include "base/bind.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/task_manager/sampling/task_manager_impl.h"
-#include "chrome/browser/task_manager/sampling/task_manager_io_thread_helper.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/browser/resource_request_info.h"
 #include "content/public/common/child_process_host.h"
 
 #if defined(OS_MACOSX)
@@ -22,28 +20,6 @@
 
 namespace task_manager {
 
-namespace {
-BytesTransferredKey KeyForRequest(const net::URLRequest& request) {
-  // Only net::URLRequestJob instances created by the ResourceDispatcherHost
-  // have an associated ResourceRequestInfo and a render frame associated.
-  content::ResourceRequestInfo* info =
-      content::ResourceRequestInfo::ForRequest(&request);
-
-  // Requests without ResourceRequestInfo are attributed to the browser process.
-  if (!info)
-    return {content::ChildProcessHost::kInvalidUniqueID, MSG_ROUTING_NONE};
-
-  // Requests from PPAPI instances are proxied through the renderer, and specify
-  // the plugin_child_id of the plugin process.
-  if (info->GetPluginChildID() != content::ChildProcessHost::kInvalidUniqueID)
-    return {info->GetPluginChildID(), MSG_ROUTING_NONE};
-
-  // Other requests are associated with the child process (and frame, if
-  // originating from a renderer process).
-  return {info->GetChildID(), info->GetRenderFrameID()};
-}
-}  // namespace
-
 // static
 void TaskManagerInterface::RegisterPrefs(PrefRegistrySimple* registry) {
   registry->RegisterDictionaryPref(prefs::kTaskManagerWindowPlacement);
@@ -64,24 +40,6 @@
   return TaskManagerImpl::GetInstance();
 }
 
-// static
-void TaskManagerInterface::OnRawBytesRead(const net::URLRequest& request,
-                                          int64_t bytes_read) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-  BytesTransferredKey key = KeyForRequest(request);
-  TaskManagerIoThreadHelper::OnRawBytesTransferred(key, bytes_read,
-                                                   0 /*bytes_sent*/);
-}
-
-// static
-void TaskManagerInterface::OnRawBytesSent(const net::URLRequest& request,
-                                          int64_t bytes_sent) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-  BytesTransferredKey key = KeyForRequest(request);
-  TaskManagerIoThreadHelper::OnRawBytesTransferred(key, 0 /*bytes_read*/,
-                                                   bytes_sent);
-}
-
 void TaskManagerInterface::AddObserver(TaskManagerObserver* observer) {
   observers_.AddObserver(observer);
   observer->observed_task_manager_ = this;
diff --git a/chrome/browser/task_manager/task_manager_interface.h b/chrome/browser/task_manager/task_manager_interface.h
index 73a108ff..375e82289 100644
--- a/chrome/browser/task_manager/task_manager_interface.h
+++ b/chrome/browser/task_manager/task_manager_interface.h
@@ -29,10 +29,6 @@
 class WebContents;
 }  // namespace content
 
-namespace net {
-class URLRequest;
-}  // namespace net
-
 namespace task_manager {
 
 // Defines the interface for any implementation of the task manager.
@@ -50,16 +46,6 @@
   // create it first. Must be called on the UI thread.
   static TaskManagerInterface* GetTaskManager();
 
-  // This notification will be received on the IO thread from
-  // ChromeNetworkDelegate to update the task manager with read network usage.
-  static void OnRawBytesRead(const net::URLRequest& request,
-                             int64_t bytes_read);
-
-  // This notification will be received on the IO thread from
-  // ChromeNetworkDelegate to update the task manager with sent network usage.
-  static void OnRawBytesSent(const net::URLRequest& request,
-                             int64_t bytes_sent);
-
   void AddObserver(TaskManagerObserver* observer);
   void RemoveObserver(TaskManagerObserver* observer);
 
diff --git a/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc b/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc
index c948d85..d85fcac 100644
--- a/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc
+++ b/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc
@@ -204,8 +204,10 @@
     TabScrubber::GetInstance();
   }
 
-  if (base::FeatureList::IsEnabled(ash::features::kKioskNextShell))
+  if (base::FeatureList::IsEnabled(ash::features::kKioskNextShell)) {
     kiosk_next_shell_client_ = std::make_unique<KioskNextShellClient>();
+    kiosk_next_shell_client_->Init();
+  }
 }
 
 void ChromeBrowserMainExtraPartsAsh::PostBrowserStart() {
diff --git a/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.cc b/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.cc
index da2c62aa..5dfe9fff 100644
--- a/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.cc
+++ b/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.cc
@@ -28,7 +28,6 @@
 #include "extensions/browser/event_router.h"
 #include "extensions/common/api/virtual_keyboard_private.h"
 #include "extensions/common/extension_messages.h"
-#include "services/service_manager/public/cpp/connector.h"
 #include "ui/base/ime/chromeos/input_method_manager.h"
 #include "ui/base/ime/ime_bridge.h"
 #include "ui/base/ime/input_method.h"
@@ -48,20 +47,19 @@
 
 // static
 std::unique_ptr<ChromeKeyboardControllerClient>
-ChromeKeyboardControllerClient::Create(service_manager::Connector* connector) {
+ChromeKeyboardControllerClient::Create() {
   // Use WrapUnique to allow the constructor to be private.
   std::unique_ptr<ChromeKeyboardControllerClient> client =
-      base::WrapUnique(new ChromeKeyboardControllerClient(connector));
+      base::WrapUnique(new ChromeKeyboardControllerClient());
   client->InitializePrefObserver();
   return client;
 }
 
 // static
 std::unique_ptr<ChromeKeyboardControllerClient>
-ChromeKeyboardControllerClient::CreateForTest(
-    service_manager::Connector* connector) {
+ChromeKeyboardControllerClient::CreateForTest() {
   // Use WrapUnique to allow the constructor to be private.
-  return base::WrapUnique(new ChromeKeyboardControllerClient(connector));
+  return base::WrapUnique(new ChromeKeyboardControllerClient());
 }
 
 // static
@@ -76,38 +74,36 @@
   return !!g_chrome_keyboard_controller_client;
 }
 
-ChromeKeyboardControllerClient::ChromeKeyboardControllerClient(
-    service_manager::Connector* connector) {
+ChromeKeyboardControllerClient::ChromeKeyboardControllerClient() {
   CHECK(!g_chrome_keyboard_controller_client);
   g_chrome_keyboard_controller_client = this;
+}
 
-  if (!connector)
-    return;  // May be null in tests.
-
-  connector->BindInterface(ash::mojom::kServiceName, &keyboard_controller_ptr_);
+void ChromeKeyboardControllerClient::Init(
+    ash::KeyboardController* keyboard_controller) {
+  DCHECK(!keyboard_controller_);
+  keyboard_controller_ = keyboard_controller;
 
   // Add this as a KeyboardController observer.
-  ash::mojom::KeyboardControllerObserverAssociatedPtrInfo ptr_info;
-  keyboard_controller_observer_binding_.Bind(mojo::MakeRequest(&ptr_info));
-  keyboard_controller_ptr_->AddObserver(std::move(ptr_info));
+  keyboard_controller_->AddObserver(this);
 
   // Request the initial enabled state.
-  keyboard_controller_ptr_->IsKeyboardEnabled(
+  keyboard_controller_->IsKeyboardEnabled(
       base::BindOnce(&ChromeKeyboardControllerClient::OnKeyboardEnabledChanged,
                      weak_ptr_factory_.GetWeakPtr()));
 
   // Request the initial set of enable flags.
-  keyboard_controller_ptr_->GetEnableFlags(base::BindOnce(
+  keyboard_controller_->GetEnableFlags(base::BindOnce(
       &ChromeKeyboardControllerClient::OnKeyboardEnableFlagsChanged,
       weak_ptr_factory_.GetWeakPtr()));
 
   // Request the initial visible state.
-  keyboard_controller_ptr_->IsKeyboardVisible(base::BindOnce(
+  keyboard_controller_->IsKeyboardVisible(base::BindOnce(
       &ChromeKeyboardControllerClient::OnKeyboardVisibilityChanged,
       weak_ptr_factory_.GetWeakPtr()));
 
   // Request the configuration.
-  keyboard_controller_ptr_->GetKeyboardConfig(
+  keyboard_controller_->GetKeyboardConfig(
       base::BindOnce(&ChromeKeyboardControllerClient::OnKeyboardConfigChanged,
                      weak_ptr_factory_.GetWeakPtr()));
 }
@@ -152,93 +148,91 @@
     observer.OnKeyboardLoaded();
 }
 
-keyboard::mojom::KeyboardConfig
-ChromeKeyboardControllerClient::GetKeyboardConfig() {
+keyboard::KeyboardConfig ChromeKeyboardControllerClient::GetKeyboardConfig() {
   if (!cached_keyboard_config_) {
     // Unlikely edge case (called before the Ash mojo service replies to the
     // initial GetKeyboardConfig request). Return the default value.
-    return keyboard::mojom::KeyboardConfig();
+    return keyboard::KeyboardConfig();
   }
-  return *cached_keyboard_config_.get();
+  return *cached_keyboard_config_;
 }
 
 void ChromeKeyboardControllerClient::SetKeyboardConfig(
-    const keyboard::mojom::KeyboardConfig& config) {
+    const keyboard::KeyboardConfig& config) {
   // Update the cache immediately.
-  cached_keyboard_config_ = keyboard::mojom::KeyboardConfig::New(config);
-  keyboard_controller_ptr_->SetKeyboardConfig(config.Clone());
+  cached_keyboard_config_ = config;
+  keyboard_controller_->SetKeyboardConfig(config);
 }
 
 void ChromeKeyboardControllerClient::GetKeyboardEnabled(
     base::OnceCallback<void(bool)> callback) {
-  keyboard_controller_ptr_->IsKeyboardEnabled(std::move(callback));
+  keyboard_controller_->IsKeyboardEnabled(std::move(callback));
 }
 
 void ChromeKeyboardControllerClient::SetEnableFlag(
-    const keyboard::mojom::KeyboardEnableFlag& flag) {
-  DVLOG(1) << "SetEnableFlag: " << flag;
-  keyboard_controller_ptr_->SetEnableFlag(flag);
+    const keyboard::KeyboardEnableFlag& flag) {
+  DVLOG(1) << "SetEnableFlag: " << static_cast<int>(flag);
+  keyboard_controller_->SetEnableFlag(flag);
 }
 
 void ChromeKeyboardControllerClient::ClearEnableFlag(
-    const keyboard::mojom::KeyboardEnableFlag& flag) {
-  keyboard_controller_ptr_->ClearEnableFlag(flag);
+    const keyboard::KeyboardEnableFlag& flag) {
+  keyboard_controller_->ClearEnableFlag(flag);
 }
 
 bool ChromeKeyboardControllerClient::IsEnableFlagSet(
-    const keyboard::mojom::KeyboardEnableFlag& flag) {
+    const keyboard::KeyboardEnableFlag& flag) {
   return base::ContainsKey(keyboard_enable_flags_, flag);
 }
 
 void ChromeKeyboardControllerClient::ReloadKeyboardIfNeeded() {
-  keyboard_controller_ptr_->ReloadKeyboardIfNeeded();
+  keyboard_controller_->ReloadKeyboardIfNeeded();
 }
 
 void ChromeKeyboardControllerClient::RebuildKeyboardIfEnabled() {
-  keyboard_controller_ptr_->RebuildKeyboardIfEnabled();
+  keyboard_controller_->RebuildKeyboardIfEnabled();
 }
 
 void ChromeKeyboardControllerClient::ShowKeyboard() {
-  keyboard_controller_ptr_->ShowKeyboard();
+  keyboard_controller_->ShowKeyboard();
 }
 
-void ChromeKeyboardControllerClient::HideKeyboard(
-    ash::mojom::HideReason reason) {
-  keyboard_controller_ptr_->HideKeyboard(reason);
+void ChromeKeyboardControllerClient::HideKeyboard(ash::HideReason reason) {
+  keyboard_controller_->HideKeyboard(reason);
 }
 
 void ChromeKeyboardControllerClient::SetContainerType(
-    keyboard::mojom::ContainerType container_type,
+    keyboard::ContainerType container_type,
     const base::Optional<gfx::Rect>& target_bounds,
     base::OnceCallback<void(bool)> callback) {
-  keyboard_controller_ptr_->SetContainerType(container_type, target_bounds,
-                                             std::move(callback));
+  keyboard_controller_->SetContainerType(container_type, target_bounds,
+                                         std::move(callback));
 }
 
 void ChromeKeyboardControllerClient::SetKeyboardLocked(bool locked) {
-  keyboard_controller_ptr_->SetKeyboardLocked(locked);
+  keyboard_controller_->SetKeyboardLocked(locked);
 }
 
 void ChromeKeyboardControllerClient::SetOccludedBounds(
     const std::vector<gfx::Rect>& bounds) {
-  keyboard_controller_ptr_->SetOccludedBounds(bounds);
+  keyboard_controller_->SetOccludedBounds(bounds);
 }
 
 void ChromeKeyboardControllerClient::SetHitTestBounds(
     const std::vector<gfx::Rect>& bounds) {
-  keyboard_controller_ptr_->SetHitTestBounds(bounds);
+  keyboard_controller_->SetHitTestBounds(bounds);
 }
 
 void ChromeKeyboardControllerClient::SetDraggableArea(const gfx::Rect& bounds) {
-  keyboard_controller_ptr_->SetDraggableArea(bounds);
+  keyboard_controller_->SetDraggableArea(bounds);
 }
 
 bool ChromeKeyboardControllerClient::IsKeyboardOverscrollEnabled() {
   DCHECK(cached_keyboard_config_);
   if (cached_keyboard_config_->overscroll_behavior !=
-      keyboard::mojom::KeyboardOverscrollBehavior::kDefault) {
+      keyboard::KeyboardOverscrollBehavior::kDefault) {
     return cached_keyboard_config_->overscroll_behavior ==
-           keyboard::mojom::KeyboardOverscrollBehavior::kEnabled;
+           keyboard::KeyboardOverscrollBehavior::kEnabled;
   }
   return true;
 }
@@ -269,14 +263,10 @@
   return keyboard::KeyboardController::Get()->GetKeyboardWindow();
 }
 
-void ChromeKeyboardControllerClient::FlushForTesting() {
-  keyboard_controller_ptr_.FlushForTesting();
-}
-
 void ChromeKeyboardControllerClient::OnKeyboardEnableFlagsChanged(
-    const std::vector<keyboard::mojom::KeyboardEnableFlag>& flags) {
+    const std::vector<keyboard::KeyboardEnableFlag>& flags) {
   keyboard_enable_flags_ =
-      std::set<keyboard::mojom::KeyboardEnableFlag>(flags.begin(), flags.end());
+      std::set<keyboard::KeyboardEnableFlag>(flags.begin(), flags.end());
 }
 
 void ChromeKeyboardControllerClient::OnKeyboardEnabledChanged(bool enabled) {
@@ -305,7 +295,7 @@
 }
 
 void ChromeKeyboardControllerClient::OnKeyboardConfigChanged(
-    keyboard::mojom::KeyboardConfigPtr config) {
+    const keyboard::KeyboardConfig& config) {
   // Only notify extensions after the initial config is received.
   bool notify = !!cached_keyboard_config_;
   cached_keyboard_config_ = std::move(config);
@@ -394,7 +384,7 @@
     const gfx::Size& size) {
   DVLOG(1) << "OnLoadKeyboardContentsRequested: " << size.ToString();
   NotifyKeyboardLoaded();
-  keyboard_controller_ptr_->KeyboardContentsLoaded(size);
+  keyboard_controller_->KeyboardContentsLoaded(size);
 }
 
 void ChromeKeyboardControllerClient::OnSessionStateChanged() {
@@ -417,7 +407,7 @@
 }
 
 void ChromeKeyboardControllerClient::SetVirtualKeyboardBehaviorFromPrefs() {
-  using keyboard::mojom::KeyboardEnableFlag;
+  using keyboard::KeyboardEnableFlag;
   const PrefService* service = pref_change_registrar_.prefs();
   if (service->HasPrefPath(prefs::kTouchVirtualKeyboardEnabled)) {
     // Since these flags are mutually exclusive, setting one clears the other.
diff --git a/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.h b/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.h
index 2912fde..49be1af 100644
--- a/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.h
+++ b/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.h
@@ -9,8 +9,8 @@
 #include <set>
 #include <vector>
 
-#include "ash/public/interfaces/keyboard_config.mojom.h"
-#include "ash/public/interfaces/keyboard_controller.mojom.h"
+#include "ash/public/cpp/keyboard/keyboard_config.h"
+#include "ash/public/cpp/keyboard/keyboard_controller.h"
 #include "base/callback_forward.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
@@ -18,7 +18,6 @@
 #include "base/observer_list_types.h"
 #include "components/prefs/pref_change_registrar.h"
 #include "components/session_manager/core/session_manager_observer.h"
-#include "mojo/public/cpp/bindings/associated_binding.h"
 #include "url/gurl.h"
 
 class ChromeKeyboardWebContents;
@@ -28,15 +27,11 @@
 class Window;
 }
 
-namespace service_manager {
-class Connector;
-}
-
-// This class implements mojom::KeyboardControllerObserver and makes calls
-// into the mojom::KeyboardController service. It also observes keyboard prefs
+// This class implements KeyboardControllerObserver and makes calls
+// into the KeyboardController service. It also observes keyboard prefs
 // and enables or disables the keyboard accordingly.
 class ChromeKeyboardControllerClient
-    : public ash::mojom::KeyboardControllerObserver,
+    : public ash::KeyboardControllerObserver,
       public session_manager::SessionManagerObserver {
  public:
   // Convenience observer allowing UI classes to observe the global instance of
@@ -62,13 +57,13 @@
   };
 
   // Creates the singleton instance for chrome or browser tests.
-  static std::unique_ptr<ChromeKeyboardControllerClient> Create(
-      service_manager::Connector* connector);
+  // |Init| needs to be called after creation.
+  static std::unique_ptr<ChromeKeyboardControllerClient> Create();
 
   // Creates the singleton instance for unit tests where there is no
   // SessionManager. Prefs will not be observed or affect the enabled state.
-  static std::unique_ptr<ChromeKeyboardControllerClient> CreateForTest(
-      service_manager::Connector* connector);
+  // |Init| needs to be called after creation.
+  static std::unique_ptr<ChromeKeyboardControllerClient> CreateForTest();
 
   // Static getter. The single instance must be instantiated first.
   static ChromeKeyboardControllerClient* Get();
@@ -78,6 +73,9 @@
 
   ~ChromeKeyboardControllerClient() override;
 
+  // Called after ash::Shell is created.
+  void Init(ash::KeyboardController* keyboard_controller);
+
   // Called before Shell or the primary profile is destroyed.
   void Shutdown();
 
@@ -89,28 +87,28 @@
   void NotifyKeyboardLoaded();
 
   // Returns the cached KeyboardConfig value.
-  keyboard::mojom::KeyboardConfig GetKeyboardConfig();
+  keyboard::KeyboardConfig GetKeyboardConfig();
 
   // Sets the new keyboard configuration and updates the cached config.
-  void SetKeyboardConfig(const keyboard::mojom::KeyboardConfig& config);
+  void SetKeyboardConfig(const keyboard::KeyboardConfig& config);
 
   // Invokes |callback| with the current enabled state. Call this after
   // Set/ClearEnableFlag to get the updated enabled state.
   void GetKeyboardEnabled(base::OnceCallback<void(bool)> callback);
 
   // Sets/clears the privided keyboard enable state.
-  void SetEnableFlag(const keyboard::mojom::KeyboardEnableFlag& flag);
-  void ClearEnableFlag(const keyboard::mojom::KeyboardEnableFlag& flag);
+  void SetEnableFlag(const keyboard::KeyboardEnableFlag& flag);
+  void ClearEnableFlag(const keyboard::KeyboardEnableFlag& flag);
 
   // Returns whether |flag| has been set.
-  bool IsEnableFlagSet(const keyboard::mojom::KeyboardEnableFlag& flag);
+  bool IsEnableFlagSet(const keyboard::KeyboardEnableFlag& flag);
 
-  // Calls forwarded to ash.mojom.KeyboardController.
+  // Calls forwarded to ash::KeyboardController.
   void ReloadKeyboardIfNeeded();
   void RebuildKeyboardIfEnabled();
   void ShowKeyboard();
-  void HideKeyboard(ash::mojom::HideReason reason);
-  void SetContainerType(keyboard::mojom::ContainerType container_type,
+  void HideKeyboard(ash::HideReason reason);
+  void SetContainerType(keyboard::ContainerType container_type,
                         const base::Optional<gfx::Rect>& target_bounds,
                         base::OnceCallback<void(bool)> callback);
   void SetKeyboardLocked(bool locked);
@@ -131,29 +129,23 @@
   bool is_keyboard_loaded() { return is_keyboard_loaded_; }
   bool is_keyboard_visible() { return is_keyboard_visible_; }
 
-  void FlushForTesting();
-
   void set_profile_for_test(Profile* profile) { profile_for_test_ = profile; }
   void set_virtual_keyboard_url_for_test(const GURL& url) {
     virtual_keyboard_url_for_test_ = url;
   }
 
  private:
-  // The constructor is private to ensure that SessionManager exists for non
-  // test usage. Use Create or CreateForTest instead.
-  explicit ChromeKeyboardControllerClient(
-      service_manager::Connector* connector);
+  ChromeKeyboardControllerClient();
 
   // Called from Create() to observer session_SessionManager and initialize
   // |pref_change_registrar_| once the session starts.
   void InitializePrefObserver();
 
-  // keyboard::mojom::KeyboardControllerObserver:
+  // ash::KeyboardControllerObserver:
   void OnKeyboardEnableFlagsChanged(
-      const std::vector<keyboard::mojom::KeyboardEnableFlag>& flags) override;
+      const std::vector<keyboard::KeyboardEnableFlag>& flags) override;
   void OnKeyboardEnabledChanged(bool enabled) override;
-  void OnKeyboardConfigChanged(
-      keyboard::mojom::KeyboardConfigPtr config) override;
+  void OnKeyboardConfigChanged(const keyboard::KeyboardConfig& config) override;
   void OnKeyboardVisibilityChanged(bool visible) override;
   void OnKeyboardVisibleBoundsChanged(const gfx::Rect& screen_bounds) override;
   void OnKeyboardOccludedBoundsChanged(const gfx::Rect& screen_bounds) override;
@@ -175,19 +167,16 @@
 
   PrefChangeRegistrar pref_change_registrar_;
 
-  ash::mojom::KeyboardControllerPtr keyboard_controller_ptr_;
-  mojo::AssociatedBinding<ash::mojom::KeyboardControllerObserver>
-      keyboard_controller_observer_binding_{this};
+  ash::KeyboardController* keyboard_controller_ = nullptr;
 
   // Set when the WS is used and OnLoadKeyboardContentsRequested is called.
   std::unique_ptr<ChromeKeyboardWebContents> keyboard_contents_;
 
-  // Cached copy of the latest config provided by mojom::KeyboardController.
-  keyboard::mojom::KeyboardConfigPtr cached_keyboard_config_;
+  // Cached copy of the latest config provided by KeyboardController.
+  base::Optional<keyboard::KeyboardConfig> cached_keyboard_config_;
 
-  // Cached copy of the active enabled flags provided by
-  // mojom::KeyboardController
-  std::set<keyboard::mojom::KeyboardEnableFlag> keyboard_enable_flags_;
+  // Cached copy of the active enabled flags provided by KeyboardController.
+  std::set<keyboard::KeyboardEnableFlag> keyboard_enable_flags_;
 
   // Tracks the enabled state of the keyboard.
   bool is_keyboard_enabled_ = false;
diff --git a/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client_test_helper.cc b/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client_test_helper.cc
index 7c85b41..0d0a0130 100644
--- a/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client_test_helper.cc
+++ b/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client_test_helper.cc
@@ -7,8 +7,8 @@
 #include <set>
 
 #include "ash/keyboard/ash_keyboard_controller.h"
+#include "ash/public/cpp/keyboard/keyboard_controller.h"
 #include "ash/public/interfaces/constants.mojom.h"
-#include "ash/public/interfaces/keyboard_controller.mojom.h"
 #include "ash/shell.h"
 #include "base/bind.h"
 #include "base/callback.h"
@@ -16,36 +16,31 @@
 #include "services/service_manager/public/cpp/connector.h"
 
 class ChromeKeyboardControllerClientTestHelper::FakeKeyboardController
-    : public ash::mojom::KeyboardController {
+    : public ash::KeyboardController {
  public:
   FakeKeyboardController() = default;
   ~FakeKeyboardController() override = default;
 
-  void BindRequest(ash::mojom::KeyboardControllerRequest request) {
-    bindings_.AddBinding(this, std::move(request));
-  }
-
-  // ash::mojom::KeyboardController:
+  // ash::KeyboardController:
   void KeyboardContentsLoaded(const gfx::Size& size) override {}
   void GetKeyboardConfig(GetKeyboardConfigCallback callback) override {
-    std::move(callback).Run(
-        keyboard::mojom::KeyboardConfig::New(keyboard_config_));
+    std::move(callback).Run(keyboard_config_);
   }
   void SetKeyboardConfig(
-      keyboard::mojom::KeyboardConfigPtr keyboard_config) override {
-    keyboard_config_ = *keyboard_config;
+      const keyboard::KeyboardConfig& keyboard_config) override {
+    keyboard_config_ = keyboard_config;
   }
   void IsKeyboardEnabled(IsKeyboardEnabledCallback callback) override {
     std::move(callback).Run(enabled_);
   }
-  void SetEnableFlag(keyboard::mojom::KeyboardEnableFlag flag) override {
+  void SetEnableFlag(keyboard::KeyboardEnableFlag flag) override {
     keyboard_enable_flags_.insert(flag);
   }
-  void ClearEnableFlag(keyboard::mojom::KeyboardEnableFlag flag) override {
+  void ClearEnableFlag(keyboard::KeyboardEnableFlag flag) override {
     keyboard_enable_flags_.erase(flag);
   }
   void GetEnableFlags(GetEnableFlagsCallback callback) override {
-    std::move(callback).Run(std::vector<keyboard::mojom::KeyboardEnableFlag>());
+    std::move(callback).Run(std::vector<keyboard::KeyboardEnableFlag>());
   }
   void ReloadKeyboardIfNeeded() override {}
   void RebuildKeyboardIfEnabled() override {}
@@ -53,10 +48,8 @@
     std::move(callback).Run(visible_);
   }
   void ShowKeyboard() override { visible_ = true; }
-  void HideKeyboard(ash::mojom::HideReason reason) override {
-    visible_ = false;
-  }
-  void SetContainerType(keyboard::mojom::ContainerType container_type,
+  void HideKeyboard(ash::HideReason reason) override { visible_ = false; }
+  void SetContainerType(keyboard::ContainerType container_type,
                         const base::Optional<gfx::Rect>& target_bounds,
                         SetContainerTypeCallback callback) override {
     std::move(callback).Run(true);
@@ -65,13 +58,11 @@
   void SetOccludedBounds(const std::vector<gfx::Rect>& bounds) override {}
   void SetHitTestBounds(const std::vector<gfx::Rect>& bounds) override {}
   void SetDraggableArea(const gfx::Rect& bounds) override {}
-  void AddObserver(ash::mojom::KeyboardControllerObserverAssociatedPtrInfo
-                       observer) override {}
+  void AddObserver(ash::KeyboardControllerObserver* observer) override {}
 
  private:
-  mojo::BindingSet<ash::mojom::KeyboardController> bindings_;
-  keyboard::mojom::KeyboardConfig keyboard_config_;
-  std::set<keyboard::mojom::KeyboardEnableFlag> keyboard_enable_flags_;
+  keyboard::KeyboardConfig keyboard_config_;
+  std::set<keyboard::KeyboardEnableFlag> keyboard_enable_flags_;
   bool enabled_ = false;
   bool visible_ = false;
 
@@ -82,10 +73,7 @@
 std::unique_ptr<ChromeKeyboardControllerClientTestHelper>
 ChromeKeyboardControllerClientTestHelper::InitializeForAsh() {
   auto helper = std::make_unique<ChromeKeyboardControllerClientTestHelper>();
-  helper->Initialize(
-      base::BindRepeating(&ChromeKeyboardControllerClientTestHelper::
-                              AddKeyboardControllerBindingForAsh,
-                          base::Unretained(helper.get())));
+  helper->Initialize(ash::KeyboardController::Get());
   return helper;
 }
 
@@ -93,27 +81,16 @@
 std::unique_ptr<ChromeKeyboardControllerClientTestHelper>
 ChromeKeyboardControllerClientTestHelper::InitializeWithFake() {
   auto helper = std::make_unique<ChromeKeyboardControllerClientTestHelper>();
-  helper->Initialize(
-      base::BindRepeating(&ChromeKeyboardControllerClientTestHelper::
-                              AddKeyboardControllerBindingForFake,
-                          base::Unretained(helper.get())));
+  helper->fake_controller_ = std::make_unique<FakeKeyboardController>();
+  helper->Initialize(helper->fake_controller_.get());
   return helper;
 }
 
 void ChromeKeyboardControllerClientTestHelper::Initialize(
-    base::RepeatingCallback<void(mojo::ScopedMessagePipeHandle)>
-        bind_callback) {
-  // Create a local service manager connector to handle requests to
-  // ash::mojom::KeyboardController and bind to AshKeyboardController.
-  service_manager::mojom::ConnectorRequest request;
-  connector_ = service_manager::Connector::Create(&request);
-  connector_->OverrideBinderForTesting(
-      service_manager::ServiceFilter::ByName(ash::mojom::kServiceName),
-      ash::mojom::KeyboardController::Name_, bind_callback);
-
-  // Provide the local connector to ChromeKeyboardControllerClient.
+    ash::KeyboardController* keyboard_controller) {
   chrome_keyboard_controller_client_ =
-      ChromeKeyboardControllerClient::CreateForTest(connector_.get());
+      ChromeKeyboardControllerClient::CreateForTest();
+  chrome_keyboard_controller_client_->Init(keyboard_controller);
 }
 
 ChromeKeyboardControllerClientTestHelper::
@@ -122,22 +99,8 @@
 ChromeKeyboardControllerClientTestHelper::
     ~ChromeKeyboardControllerClientTestHelper() {
   chrome_keyboard_controller_client_.reset();
-  connector_.reset();
 }
 
 void ChromeKeyboardControllerClientTestHelper::SetProfile(Profile* profile) {
   chrome_keyboard_controller_client_->set_profile_for_test(profile);
 }
-
-void ChromeKeyboardControllerClientTestHelper::
-    AddKeyboardControllerBindingForAsh(mojo::ScopedMessagePipeHandle handle) {
-  ash::Shell::Get()->ash_keyboard_controller()->BindRequest(
-      ash::mojom::KeyboardControllerRequest(std::move(handle)));
-}
-
-void ChromeKeyboardControllerClientTestHelper::
-    AddKeyboardControllerBindingForFake(mojo::ScopedMessagePipeHandle handle) {
-  fake_controller_ = std::make_unique<FakeKeyboardController>();
-  fake_controller_->BindRequest(
-      ash::mojom::KeyboardControllerRequest(std::move(handle)));
-}
diff --git a/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client_test_helper.h b/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client_test_helper.h
index 3b789d4..9f9ef645 100644
--- a/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client_test_helper.h
+++ b/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client_test_helper.h
@@ -10,10 +10,6 @@
 #include "base/callback_forward.h"
 #include "chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.h"
 
-namespace service_manager {
-class Connector;
-}
-
 class Profile;
 
 // Helper for tests depending on ChromeKeyboardControllerClient.
@@ -38,14 +34,8 @@
  private:
   class FakeKeyboardController;
 
-  void Initialize(base::RepeatingCallback<void(mojo::ScopedMessagePipeHandle)>
-                      bind_callback);
+  void Initialize(ash::KeyboardController* keyboard_controller);
 
-  void AddKeyboardControllerBindingForAsh(mojo::ScopedMessagePipeHandle handle);
-  void AddKeyboardControllerBindingForFake(
-      mojo::ScopedMessagePipeHandle handle);
-
-  std::unique_ptr<service_manager::Connector> connector_;
   std::unique_ptr<ChromeKeyboardControllerClient>
       chrome_keyboard_controller_client_;
 
diff --git a/chrome/browser/ui/ash/keyboard/chrome_keyboard_ui.cc b/chrome/browser/ui/ash/keyboard/chrome_keyboard_ui.cc
index 10457b4..d5fc1eb 100644
--- a/chrome/browser/ui/ash/keyboard/chrome_keyboard_ui.cc
+++ b/chrome/browser/ui/ash/keyboard/chrome_keyboard_ui.cc
@@ -130,5 +130,5 @@
   // shadows drawn by IME.
   shadow_->layer()->SetVisible(
       keyboard_controller()->GetActiveContainerType() ==
-      keyboard::mojom::ContainerType::kFullWidth);
+      keyboard::ContainerType::kFullWidth);
 }
diff --git a/chrome/browser/ui/ash/keyboard/chrome_keyboard_ui_unittest.cc b/chrome/browser/ui/ash/keyboard/chrome_keyboard_ui_unittest.cc
index d04a165..c92b633 100644
--- a/chrome/browser/ui/ash/keyboard/chrome_keyboard_ui_unittest.cc
+++ b/chrome/browser/ui/ash/keyboard/chrome_keyboard_ui_unittest.cc
@@ -30,7 +30,7 @@
     if (::features::IsUsingWindowService())
       return;
     chrome_keyboard_controller_client_ =
-        ChromeKeyboardControllerClient::CreateForTest(nullptr /* connector */);
+        ChromeKeyboardControllerClient::CreateForTest();
     chrome_keyboard_ui_ = std::make_unique<ChromeKeyboardUI>(profile());
   }
 
diff --git a/chrome/browser/ui/ash/keyboard/chrome_keyboard_web_contents_unittest.cc b/chrome/browser/ui/ash/keyboard/chrome_keyboard_web_contents_unittest.cc
index 972ed4e..ef130bc4 100644
--- a/chrome/browser/ui/ash/keyboard/chrome_keyboard_web_contents_unittest.cc
+++ b/chrome/browser/ui/ash/keyboard/chrome_keyboard_web_contents_unittest.cc
@@ -28,7 +28,7 @@
   void SetUp() override {
     ChromeRenderViewHostTestHarness::SetUp();
     chrome_keyboard_controller_client_ =
-        ChromeKeyboardControllerClient::CreateForTest(nullptr /* connector */);
+        ChromeKeyboardControllerClient::CreateForTest();
   }
 
   void TearDown() override {
diff --git a/chrome/browser/ui/ash/keyboard/keyboard_controller_browsertest.cc b/chrome/browser/ui/ash/keyboard/keyboard_controller_browsertest.cc
index 6e6de86f..fdb441f9 100644
--- a/chrome/browser/ui/ash/keyboard/keyboard_controller_browsertest.cc
+++ b/chrome/browser/ui/ash/keyboard/keyboard_controller_browsertest.cc
@@ -34,6 +34,7 @@
 
 const int kKeyboardHeightForTest = 100;
 
+// TODO(shend): Remove this since all calls are synchronous now.
 class KeyboardVisibleWaiter : public ChromeKeyboardControllerClient::Observer {
  public:
   explicit KeyboardVisibleWaiter(bool visible) : visible_(visible) {
@@ -43,7 +44,13 @@
     ChromeKeyboardControllerClient::Get()->RemoveObserver(this);
   }
 
-  void Wait() { run_loop_.Run(); }
+  void Wait() {
+    if (ChromeKeyboardControllerClient::Get()->is_keyboard_visible() ==
+        visible_) {
+      return;
+    }
+    run_loop_.Run();
+  }
 
   // ChromeKeyboardControllerClient::Observer
   void OnKeyboardVisibilityChanged(bool visible) override {
@@ -188,8 +195,7 @@
   KeyboardVisibleWaiter(true).Wait();
 
   // Simulate hide keyboard by pressing hide key on the virtual keyboard.
-  ChromeKeyboardControllerClient::Get()->HideKeyboard(
-      ash::mojom::HideReason::kUser);
+  ChromeKeyboardControllerClient::Get()->HideKeyboard(ash::HideReason::kUser);
   KeyboardVisibleWaiter(false).Wait();
 
   MockEnableIMEInDifferentExtension("chrome-extension://domain-2", test_bounds);
@@ -206,8 +212,7 @@
     return;
 
   ChromeKeyboardControllerClient::Get()->SetContainerType(
-      keyboard::mojom::ContainerType::kFloating, base::nullopt,
-      base::DoNothing());
+      keyboard::ContainerType::kFloating, base::nullopt, base::DoNothing());
 
   auto* controller = keyboard::KeyboardController::Get();
   controller->ShowKeyboard(false);
@@ -362,7 +367,7 @@
   controller->ShowKeyboard();
   KeyboardVisibleWaiter(true).Wait();
 
-  controller->HideKeyboard(ash::mojom::HideReason::kSystem);
+  controller->HideKeyboard(ash::HideReason::kSystem);
   KeyboardVisibleWaiter(false).Wait();
 
   controller->ShowKeyboard();
diff --git a/chrome/browser/ui/ash/keyboard/keyboard_end_to_end_browsertest.cc b/chrome/browser/ui/ash/keyboard/keyboard_end_to_end_browsertest.cc
index 620661e4..f4157d3f3 100644
--- a/chrome/browser/ui/ash/keyboard/keyboard_end_to_end_browsertest.cc
+++ b/chrome/browser/ui/ash/keyboard/keyboard_end_to_end_browsertest.cc
@@ -327,8 +327,7 @@
 
   void HideKeyboard() {
     auto* controller = ChromeKeyboardControllerClient::Get();
-    controller->HideKeyboard(ash::mojom::HideReason::kUser);
-    controller->FlushForTesting();
+    controller->HideKeyboard(ash::HideReason::kUser);
   }
 
  protected:
diff --git a/chrome/browser/ui/ash/kiosk_next_shell_client.cc b/chrome/browser/ui/ash/kiosk_next_shell_client.cc
index 028991cb..866454a 100644
--- a/chrome/browser/ui/ash/kiosk_next_shell_client.cc
+++ b/chrome/browser/ui/ash/kiosk_next_shell_client.cc
@@ -7,15 +7,12 @@
 #include <utility>
 
 #include "apps/launcher.h"
-#include "ash/public/interfaces/constants.mojom.h"
 #include "base/logging.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/common/extensions/extension_constants.h"
-#include "content/public/common/service_manager_connection.h"
+#include "components/account_id/account_id.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/common/constants.h"
-#include "mojo/public/cpp/bindings/interface_request.h"
-#include "services/service_manager/public/cpp/connector.h"
 
 namespace {
 
@@ -26,20 +23,16 @@
 KioskNextShellClient::KioskNextShellClient() {
   DCHECK(!g_kiosk_next_shell_client_instance);
   g_kiosk_next_shell_client_instance = this;
-
-  ash::mojom::KioskNextShellControllerPtr kiosk_next_shell_controller;
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindInterface(ash::mojom::kServiceName, &kiosk_next_shell_controller);
-
-  ash::mojom::KioskNextShellClientPtr client;
-  binding_.Bind(mojo::MakeRequest(&client));
-  kiosk_next_shell_controller->SetClient(std::move(client));
 }
 
 KioskNextShellClient::~KioskNextShellClient() {
   DCHECK_EQ(this, g_kiosk_next_shell_client_instance);
   g_kiosk_next_shell_client_instance = nullptr;
+  ash::KioskNextShellController::Get()->SetClientAndLaunchSession(nullptr);
+}
+
+void KioskNextShellClient::Init() {
+  ash::KioskNextShellController::Get()->SetClientAndLaunchSession(this);
 }
 
 // static
diff --git a/chrome/browser/ui/ash/kiosk_next_shell_client.h b/chrome/browser/ui/ash/kiosk_next_shell_client.h
index 3a087171..081fc87 100644
--- a/chrome/browser/ui/ash/kiosk_next_shell_client.h
+++ b/chrome/browser/ui/ash/kiosk_next_shell_client.h
@@ -5,27 +5,25 @@
 #ifndef CHROME_BROWSER_UI_ASH_KIOSK_NEXT_SHELL_CLIENT_H_
 #define CHROME_BROWSER_UI_ASH_KIOSK_NEXT_SHELL_CLIENT_H_
 
-#include "ash/public/interfaces/kiosk_next_shell.mojom.h"
+#include "ash/public/cpp/kiosk_next_shell.h"
 #include "base/macros.h"
-#include "components/account_id/account_id.h"
-#include "mojo/public/cpp/bindings/binding.h"
 
-class KioskNextShellClient : public ash::mojom::KioskNextShellClient {
+class KioskNextShellClient : public ash::KioskNextShellClient {
  public:
   KioskNextShellClient();
   ~KioskNextShellClient() override;
 
+  void Init();
+
   // Returns the singleton KioskNextShellClient instance, if it exists.
   static KioskNextShellClient* Get();
 
-  // mojom::KioskNextShellClient:
+  // ash::KioskNextShellClient:
   void LaunchKioskNextShell(const AccountId& account_id) override;
 
   bool has_launched() const { return has_launched_; }
 
  private:
-  mojo::Binding<ash::mojom::KioskNextShellClient> binding_{this};
-
   // True once the KioskNextShell has been launched.
   bool has_launched_ = false;
 
diff --git a/chrome/browser/ui/ash/login_screen_client.cc b/chrome/browser/ui/ash/login_screen_client.cc
index 870ae33..6a6ce0c 100644
--- a/chrome/browser/ui/ash/login_screen_client.cc
+++ b/chrome/browser/ui/ash/login_screen_client.cc
@@ -9,7 +9,6 @@
 #include "ash/public/cpp/login_screen.h"
 #include "ash/public/cpp/login_screen_model.h"
 #include "ash/public/cpp/login_types.h"
-#include "ash/public/interfaces/constants.mojom.h"
 #include "base/bind.h"
 #include "chrome/browser/chromeos/child_accounts/parent_access_code/parent_access_service.h"
 #include "chrome/browser/chromeos/login/existing_user_controller.h"
@@ -37,22 +36,16 @@
 LoginScreenClient::ParentAccessDelegate::~ParentAccessDelegate() = default;
 
 LoginScreenClient::LoginScreenClient()
-    : binding_(this),
-      auth_recorder_(std::make_unique<chromeos::LoginAuthRecorder>()),
-      weak_ptr_factory_(this) {
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindInterface(ash::mojom::kServiceName, &login_screen_);
+    : auth_recorder_(std::make_unique<chromeos::LoginAuthRecorder>()) {
   // Register this object as the client interface implementation.
-  ash::mojom::LoginScreenClientPtr client;
-  binding_.Bind(mojo::MakeRequest(&client));
-  login_screen_->SetClient(std::move(client));
+  ash::LoginScreen::Get()->SetClient(this);
 
   DCHECK(!g_login_screen_client_instance);
   g_login_screen_client_instance = this;
 }
 
 LoginScreenClient::~LoginScreenClient() {
+  ash::LoginScreen::Get()->SetClient(nullptr);
   DCHECK_EQ(this, g_login_screen_client_instance);
   g_login_screen_client_instance = nullptr;
 }
@@ -82,10 +75,6 @@
   system_tray_focus_observers_.RemoveObserver(observer);
 }
 
-ash::mojom::LoginScreenPtr& LoginScreenClient::login_screen() {
-  return login_screen_;
-}
-
 chromeos::LoginAuthRecorder* LoginScreenClient::auth_recorder() {
   return auth_recorder_.get();
 }
@@ -94,7 +83,7 @@
     const AccountId& account_id,
     const std::string& password,
     bool authenticated_by_pin,
-    AuthenticateUserWithPasswordOrPinCallback callback) {
+    base::OnceCallback<void(bool)> callback) {
   if (delegate_) {
     delegate_->HandleAuthenticateUserWithPasswordOrPin(
         account_id, password, authenticated_by_pin, std::move(callback));
@@ -110,7 +99,7 @@
 
 void LoginScreenClient::AuthenticateUserWithExternalBinary(
     const AccountId& account_id,
-    AuthenticateUserWithExternalBinaryCallback callback) {
+    base::OnceCallback<void(bool)> callback) {
   if (!delegate_)
     LOG(FATAL) << "Failed AuthenticateUserWithExternalBinary; no delegate";
 
@@ -121,7 +110,7 @@
 }
 
 void LoginScreenClient::EnrollUserWithExternalBinary(
-    EnrollUserWithExternalBinaryCallback callback) {
+    base::OnceCallback<void(bool)> callback) {
   if (!delegate_)
     LOG(FATAL) << "Failed EnrollUserWithExternalBinary; no delegate";
 
@@ -140,13 +129,11 @@
   }
 }
 
-void LoginScreenClient::ValidateParentAccessCode(
+bool LoginScreenClient::ValidateParentAccessCode(
     const AccountId& account_id,
-    const std::string& access_code,
-    ValidateParentAccessCodeCallback callback) {
-  bool result = chromeos::parent_access::ParentAccessService::Get()
-                    .ValidateParentAccessCode(account_id, access_code);
-  std::move(callback).Run(result);
+    const std::string& access_code) {
+  return chromeos::parent_access::ParentAccessService::Get()
+      .ValidateParentAccessCode(account_id, access_code);
 }
 
 void LoginScreenClient::HardlockPod(const AccountId& account_id) {
@@ -166,7 +153,7 @@
 
 void LoginScreenClient::FocusLockScreenApps(bool reverse) {
   // If delegate is not set, or it fails to handle focus request, call
-  // |HandleFocusLeavingLockScreenApps| so the lock screen mojo service can
+  // |HandleFocusLeavingLockScreenApps| so the lock screen service can
   // give focus to the next window in the tab order.
   if (!delegate_ || !delegate_->HandleFocusLockScreenApps(reverse)) {
     ash::LoginScreen::Get()->GetModel()->HandleFocusLeavingLockScreenApps(
@@ -179,9 +166,8 @@
     delegate_->HandleFocusOobeDialog();
 }
 
-void LoginScreenClient::ShowGaiaSignin(
-    bool can_close,
-    const base::Optional<AccountId>& prefilled_account) {
+void LoginScreenClient::ShowGaiaSignin(bool can_close,
+                                       const AccountId& prefilled_account) {
   if (chromeos::LoginDisplayHost::default_host()) {
     chromeos::LoginDisplayHost::default_host()->ShowGaiaDialog(
         can_close, prefilled_account);
diff --git a/chrome/browser/ui/ash/login_screen_client.h b/chrome/browser/ui/ash/login_screen_client.h
index 6c9bad1..0c649e9 100644
--- a/chrome/browser/ui/ash/login_screen_client.h
+++ b/chrome/browser/ui/ash/login_screen_client.h
@@ -5,29 +5,19 @@
 #ifndef CHROME_BROWSER_UI_ASH_LOGIN_SCREEN_CLIENT_H_
 #define CHROME_BROWSER_UI_ASH_LOGIN_SCREEN_CLIENT_H_
 
+#include "ash/public/cpp/login_screen_client.h"
 #include "ash/public/cpp/system_tray_focus_observer.h"
-#include "ash/public/interfaces/login_screen.mojom.h"
 #include "base/macros.h"
 #include "base/observer_list.h"
-#include "mojo/public/cpp/bindings/binding.h"
 #include "ui/base/ime/chromeos/input_method_manager.h"
 
-using AuthenticateUserWithPasswordOrPinCallback =
-    ash::mojom::LoginScreenClient::AuthenticateUserWithPasswordOrPinCallback;
-using AuthenticateUserWithExternalBinaryCallback =
-    ash::mojom::LoginScreenClient::AuthenticateUserWithExternalBinaryCallback;
-using ValidateParentAccessCodeCallback =
-    ash::mojom::LoginScreenClient::ValidateParentAccessCodeCallback;
-using EnrollUserWithExternalBinaryCallback =
-    ash::mojom::LoginScreenClient::EnrollUserWithExternalBinaryCallback;
-
 namespace chromeos {
 class LoginAuthRecorder;
 }
 
 // Handles method calls sent from ash to chrome. Also sends messages from chrome
 // to ash.
-class LoginScreenClient : public ash::mojom::LoginScreenClient {
+class LoginScreenClient : public ash::LoginScreenClient {
  public:
   // Handles method calls coming from ash into chrome.
   class Delegate {
@@ -38,12 +28,12 @@
         const AccountId& account_id,
         const std::string& password,
         bool authenticated_by_pin,
-        AuthenticateUserWithPasswordOrPinCallback callback) = 0;
+        base::OnceCallback<void(bool)> callback) = 0;
     virtual void HandleAuthenticateUserWithExternalBinary(
         const AccountId& account_id,
-        AuthenticateUserWithExternalBinaryCallback callback) = 0;
+        base::OnceCallback<void(bool)> callback) = 0;
     virtual void HandleEnrollUserWithExternalBinary(
-        EnrollUserWithExternalBinaryCallback) = 0;
+        base::OnceCallback<void(bool)> callback) = 0;
     virtual void HandleAuthenticateUserWithEasyUnlock(
         const AccountId& account_id) = 0;
     virtual void HandleHardlockPod(const AccountId& account_id) = 0;
@@ -67,9 +57,7 @@
    public:
     virtual ~ParentAccessDelegate();
 
-    virtual void ValidateParentAccessCode(
-        const std::string& access_code,
-        ValidateParentAccessCodeCallback callback) = 0;
+    virtual bool ValidateParentAccessCode(const std::string& access_code) = 0;
   };
 
   LoginScreenClient();
@@ -80,30 +68,25 @@
   // Set the object which will handle calls coming from ash.
   void SetDelegate(Delegate* delegate);
 
-  // Returns an object which can be used to make calls to ash.
-  ash::mojom::LoginScreenPtr& login_screen();
-
   chromeos::LoginAuthRecorder* auth_recorder();
 
   void AddSystemTrayFocusObserver(ash::SystemTrayFocusObserver* observer);
   void RemoveSystemTrayFocusObserver(ash::SystemTrayFocusObserver* observer);
 
-  // ash::mojom::LoginScreenClient:
+  // ash::LoginScreenClient:
   void AuthenticateUserWithPasswordOrPin(
       const AccountId& account_id,
       const std::string& password,
       bool authenticated_by_pin,
-      AuthenticateUserWithPasswordOrPinCallback callback) override;
+      base::OnceCallback<void(bool)> callback) override;
   void AuthenticateUserWithExternalBinary(
       const AccountId& account_id,
-      AuthenticateUserWithExternalBinaryCallback callback) override;
+      base::OnceCallback<void(bool)> callback) override;
   void EnrollUserWithExternalBinary(
-      EnrollUserWithExternalBinaryCallback callback) override;
+      base::OnceCallback<void(bool)> callback) override;
   void AuthenticateUserWithEasyUnlock(const AccountId& account_id) override;
-  void ValidateParentAccessCode(
-      const AccountId& account_id,
-      const std::string& access_code,
-      ValidateParentAccessCodeCallback callback) override;
+  bool ValidateParentAccessCode(const AccountId& account_id,
+                                const std::string& access_code) override;
   void HardlockPod(const AccountId& account_id) override;
   void OnFocusPod(const AccountId& account_id) override;
   void OnNoPodFocused() override;
@@ -114,9 +97,8 @@
   void OnMaxIncorrectPasswordAttempted(const AccountId& account_id) override;
   void FocusLockScreenApps(bool reverse) override;
   void FocusOobeDialog() override;
-  void ShowGaiaSignin(
-      bool can_close,
-      const base::Optional<AccountId>& prefilled_account) override;
+  void ShowGaiaSignin(bool can_close,
+                      const AccountId& prefilled_account) override;
   void OnRemoveUserWarningShown() override;
   void RemoveUser(const AccountId& account_id) override;
   void LaunchPublicSession(const AccountId& account_id,
@@ -136,11 +118,6 @@
       const std::string& locale,
       std::unique_ptr<base::ListValue> keyboard_layouts);
 
-  // Lock screen mojo service in ash.
-  ash::mojom::LoginScreenPtr login_screen_;
-
-  // Binds this object to the client interface.
-  mojo::Binding<ash::mojom::LoginScreenClient> binding_;
   Delegate* delegate_ = nullptr;
 
   // Captures authentication related user metrics for login screen.
@@ -149,7 +126,7 @@
   base::ObserverList<ash::SystemTrayFocusObserver>::Unchecked
       system_tray_focus_observers_;
 
-  base::WeakPtrFactory<LoginScreenClient> weak_ptr_factory_;
+  base::WeakPtrFactory<LoginScreenClient> weak_ptr_factory_{this};
 
   DISALLOW_COPY_AND_ASSIGN(LoginScreenClient);
 };
diff --git a/chrome/browser/ui/ash/test_login_screen.cc b/chrome/browser/ui/ash/test_login_screen.cc
index 4051d81..7275ab07 100644
--- a/chrome/browser/ui/ash/test_login_screen.cc
+++ b/chrome/browser/ui/ash/test_login_screen.cc
@@ -4,47 +4,20 @@
 
 #include "chrome/browser/ui/ash/test_login_screen.h"
 
-#include <utility>
+TestLoginScreen::TestLoginScreen() = default;
 
-#include "ash/public/interfaces/constants.mojom.h"
-#include "content/public/common/service_manager_connection.h"
-#include "services/service_manager/public/cpp/connector.h"
-#include "services/service_manager/public/cpp/service_filter.h"
+TestLoginScreen::~TestLoginScreen() = default;
 
-TestLoginScreen::TestLoginScreen() {
-  CHECK(content::ServiceManagerConnection::GetForProcess())
-      << "ServiceManager is uninitialized. Did you forget to create a "
-         "content::TestServiceManagerContext?";
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->OverrideBinderForTesting(
-          service_manager::ServiceFilter::ByName(ash::mojom::kServiceName),
-          ash::mojom::LoginScreen::Name_,
-          base::BindRepeating(&TestLoginScreen::Bind, base::Unretained(this)));
-}
-
-TestLoginScreen::~TestLoginScreen() {
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->ClearBinderOverrideForTesting(
-          service_manager::ServiceFilter::ByName(ash::mojom::kServiceName),
-          ash::mojom::LoginScreen::Name_);
-}
-
-void TestLoginScreen::SetClient(ash::mojom::LoginScreenClientPtr client) {}
-
-void TestLoginScreen::ShowLockScreen(ShowLockScreenCallback callback) {
-  std::move(callback).Run(true);
-}
-
-void TestLoginScreen::ShowLoginScreen(ShowLoginScreenCallback callback) {
-  std::move(callback).Run(true);
-}
+void TestLoginScreen::SetClient(ash::LoginScreenClient* client) {}
 
 ash::LoginScreenModel* TestLoginScreen::GetModel() {
   return &test_screen_model_;
 }
 
+void TestLoginScreen::ShowLockScreen() {}
+
+void TestLoginScreen::ShowLoginScreen() {}
+
 void TestLoginScreen::ShowKioskAppError(const std::string& message) {}
 
 void TestLoginScreen::FocusLoginShelf(bool reverse) {}
@@ -66,7 +39,3 @@
     base::RepeatingCallback<void(bool success)> callback) {}
 
 void TestLoginScreen::SetAllowLoginAsGuest(bool allow_guest) {}
-
-void TestLoginScreen::Bind(mojo::ScopedMessagePipeHandle handle) {
-  binding_.Bind(ash::mojom::LoginScreenRequest(std::move(handle)));
-}
diff --git a/chrome/browser/ui/ash/test_login_screen.h b/chrome/browser/ui/ash/test_login_screen.h
index 525590c..4bbb101 100644
--- a/chrome/browser/ui/ash/test_login_screen.h
+++ b/chrome/browser/ui/ash/test_login_screen.h
@@ -9,7 +9,6 @@
 #include <vector>
 
 #include "ash/public/cpp/login_screen.h"
-#include "ash/public/interfaces/login_screen.mojom.h"
 #include "base/macros.h"
 #include "chrome/browser/ui/ash/test_login_screen_model.h"
 #include "mojo/public/cpp/bindings/binding.h"
@@ -21,19 +20,16 @@
 //
 // Note: A ServiceManagerConnection must be initialized before constructing this
 // object. Consider using content::TestServiceManagerContext on your tests.
-class TestLoginScreen : public ash::mojom::LoginScreen,
-                        public ash::LoginScreen {
+class TestLoginScreen : public ash::LoginScreen {
  public:
   TestLoginScreen();
   ~TestLoginScreen() override;
 
-  // ash:mojom::LoginScreen:
-  void SetClient(ash::mojom::LoginScreenClientPtr client) override;
-  void ShowLockScreen(ShowLockScreenCallback callback) override;
-  void ShowLoginScreen(ShowLoginScreenCallback callback) override;
-
   // ash::LoginScreen:
+  void SetClient(ash::LoginScreenClient* client) override;
   ash::LoginScreenModel* GetModel() override;
+  void ShowLockScreen() override;
+  void ShowLoginScreen() override;
   void ShowKioskAppError(const std::string& message) override;
   void FocusLoginShelf(bool reverse) override;
   bool IsReadyForPassword() override;
@@ -47,9 +43,6 @@
   void SetAllowLoginAsGuest(bool allow_guest) override;
 
  private:
-  void Bind(mojo::ScopedMessagePipeHandle handle);
-  mojo::Binding<ash::mojom::LoginScreen> binding_{this};
-
   TestLoginScreenModel test_screen_model_;
 
   DISALLOW_COPY_AND_ASSIGN(TestLoginScreen);
diff --git a/chrome/browser/ui/hid/hid_chooser.h b/chrome/browser/ui/hid/hid_chooser.h
index fbb66b6..985785b 100644
--- a/chrome/browser/ui/hid/hid_chooser.h
+++ b/chrome/browser/ui/hid/hid_chooser.h
@@ -7,12 +7,13 @@
 
 #include "base/macros.h"
 #include "components/bubble/bubble_reference.h"
+#include "content/public/browser/hid_chooser.h"
 
 // Owns a HID device chooser dialog and closes it when destroyed.
-class HidChooser {
+class HidChooser : public content::HidChooser {
  public:
   explicit HidChooser(BubbleReference bubble);
-  ~HidChooser();
+  ~HidChooser() override;
 
  private:
   BubbleReference bubble_;
diff --git a/chrome/browser/ui/hid/hid_chooser_controller.cc b/chrome/browser/ui/hid/hid_chooser_controller.cc
index 8960f38a..641f6d8 100644
--- a/chrome/browser/ui/hid/hid_chooser_controller.cc
+++ b/chrome/browser/ui/hid/hid_chooser_controller.cc
@@ -19,7 +19,7 @@
 
 HidChooserController::HidChooserController(
     content::RenderFrameHost* render_frame_host,
-    HidChooserCallback callback)
+    content::HidChooser::Callback callback)
     : ChooserController(render_frame_host,
                         IDS_HID_CHOOSER_PROMPT_ORIGIN,
                         IDS_HID_CHOOSER_PROMPT_EXTENSION_NAME),
diff --git a/chrome/browser/ui/hid/hid_chooser_controller.h b/chrome/browser/ui/hid/hid_chooser_controller.h
index 370bbc1..693e1c5e 100644
--- a/chrome/browser/ui/hid/hid_chooser_controller.h
+++ b/chrome/browser/ui/hid/hid_chooser_controller.h
@@ -12,6 +12,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/strings/string16.h"
 #include "chrome/browser/chooser_controller/chooser_controller.h"
+#include "content/public/browser/hid_chooser.h"
 #include "services/device/public/mojom/hid.mojom-forward.h"
 #include "url/origin.h"
 
@@ -25,9 +26,6 @@
 // It is owned by ChooserBubbleDelegate.
 class HidChooserController : public ChooserController {
  public:
-  using HidChooserCallback =
-      base::OnceCallback<void(device::mojom::HidDeviceInfoPtr)>;
-
   // Construct a chooser controller for Human Interface Devices (HID).
   // |render_frame_host| is used to initialize the chooser strings and to access
   // the requesting and embedding origins. |callback| is called when the chooser
@@ -35,7 +33,7 @@
   // The callback is called with the selected device, or nullptr if no device is
   // selected.
   HidChooserController(content::RenderFrameHost* render_frame_host,
-                       HidChooserCallback callback);
+                       content::HidChooser::Callback callback);
   ~HidChooserController() override;
 
   // ChooserController:
@@ -53,7 +51,7 @@
  private:
   void OnGotDevices(std::vector<device::mojom::HidDeviceInfoPtr> devices);
 
-  HidChooserCallback callback_;
+  content::HidChooser::Callback callback_;
   const url::Origin requesting_origin_;
   const url::Origin embedding_origin_;
 
diff --git a/chrome/browser/ui/hid/hid_chooser_controller_unittest.cc b/chrome/browser/ui/hid/hid_chooser_controller_unittest.cc
index 227532af..875866c 100644
--- a/chrome/browser/ui/hid/hid_chooser_controller_unittest.cc
+++ b/chrome/browser/ui/hid/hid_chooser_controller_unittest.cc
@@ -13,6 +13,7 @@
 #include "chrome/grit/generated_resources.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "chrome/test/base/testing_profile.h"
+#include "content/public/browser/hid_chooser.h"
 #include "content/public/test/web_contents_tester.h"
 #include "services/device/public/cpp/hid/fake_hid_manager.h"
 #include "services/device/public/mojom/hid.mojom.h"
@@ -73,7 +74,7 @@
         std::move(hid_manager_ptr));
 
     hid_chooser_controller_ = std::make_unique<HidChooserController>(
-        main_rfh(), HidChooserController::HidChooserCallback());
+        main_rfh(), content::HidChooser::Callback());
     fake_hid_chooser_view_ = std::make_unique<FakeHidChooserView>();
     hid_chooser_controller_->set_view(fake_hid_chooser_view_.get());
   }
diff --git a/chrome/browser/ui/views/frame/browser_root_view.cc b/chrome/browser/ui/views/frame/browser_root_view.cc
index 39f6dcaf..a1b4920 100644
--- a/chrome/browser/ui/views/frame/browser_root_view.cc
+++ b/chrome/browser/ui/views/frame/browser_root_view.cc
@@ -101,8 +101,7 @@
 }
 
 // static
-const char BrowserRootView::kViewClassName[] =
-    "browser/ui/views/frame/BrowserRootView";
+const char BrowserRootView::kViewClassName[] = "BrowserRootView";
 
 BrowserRootView::BrowserRootView(BrowserView* browser_view,
                                  views::Widget* widget)
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view_browsertest.cc b/chrome/browser/ui/views/location_bar/location_bar_view_browsertest.cc
index 0045b2b..201a3de3 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view_browsertest.cc
+++ b/chrome/browser/ui/views/location_bar/location_bar_view_browsertest.cc
@@ -251,52 +251,26 @@
   const GURL kMockNonsecureURL =
       embedded_test_server()->GetURL("example.test", "/");
   const base::string16 kEvString = base::ASCIIToUTF16("Test CA [US]");
-  const base::string16 kSecureString = base::ASCIIToUTF16("Secure");
   const base::string16 kEmptyString = base::string16();
 
-  const std::string kDefaultVariation = std::string();
-  const std::string kEvToSecureVariation(
-      OmniboxFieldTrial::kSimplifyHttpsIndicatorParameterEvToSecure);
-  const std::string kBothToLockVariation(
-      OmniboxFieldTrial::kSimplifyHttpsIndicatorParameterBothToLock);
-  const std::string kKeepSecureChipVariation(
-      OmniboxFieldTrial::kSimplifyHttpsIndicatorParameterKeepSecureChip);
-
   const struct {
-    std::string feature_param;
+    bool is_enabled;
     GURL url;
     net::CertStatus cert_status;
     security_state::SecurityLevel security_level;
     bool should_show_text;
     base::string16 indicator_text;
-  } cases[]{// Default
-            {kDefaultVariation, kMockSecureURL, net::CERT_STATUS_IS_EV,
-             security_state::EV_SECURE, true, kEvString},
-            {kDefaultVariation, kMockSecureURL, 0, security_state::SECURE,
-             false, kEmptyString},
-            {kDefaultVariation, kMockNonsecureURL, 0, security_state::NONE,
-             false, kEmptyString},
-            // Variation: EV To Secure
-            {kEvToSecureVariation, kMockSecureURL, net::CERT_STATUS_IS_EV,
-             security_state::EV_SECURE, true, kSecureString},
-            {kEvToSecureVariation, kMockSecureURL, 0, security_state::SECURE,
-             false, kEmptyString},
-            {kEvToSecureVariation, kMockNonsecureURL, 0, security_state::NONE,
-             false, kEmptyString},
-            // Variation: Keep Secure chip
-            {kKeepSecureChipVariation, kMockSecureURL, net::CERT_STATUS_IS_EV,
-             security_state::EV_SECURE, true, kEvString},
-            {kKeepSecureChipVariation, kMockSecureURL, 0,
-             security_state::SECURE, true, kSecureString},
-            {kKeepSecureChipVariation, kMockNonsecureURL, 0,
-             security_state::NONE, false, kEmptyString},
-            // Variation: Both to Lock
-            {kBothToLockVariation, kMockSecureURL, net::CERT_STATUS_IS_EV,
-             security_state::EV_SECURE, false, kEmptyString},
-            {kBothToLockVariation, kMockSecureURL, 0, security_state::SECURE,
-             false, kEmptyString},
-            {kBothToLockVariation, kMockNonsecureURL, 0, security_state::NONE,
-             false, kEmptyString}};
+  } cases[]{
+      // Disabled (show EV UI in omnibox)
+      {false, kMockSecureURL, net::CERT_STATUS_IS_EV, security_state::EV_SECURE,
+       true, kEvString},
+      {false, kMockSecureURL, 0, security_state::SECURE, false, kEmptyString},
+      {false, kMockNonsecureURL, 0, security_state::NONE, false, kEmptyString},
+      // Default (lock-only in omnibox)
+      {true, kMockSecureURL, net::CERT_STATUS_IS_EV, security_state::EV_SECURE,
+       false, kEmptyString},
+      {true, kMockSecureURL, 0, security_state::SECURE, false, kEmptyString},
+      {true, kMockNonsecureURL, 0, security_state::NONE, false, kEmptyString}};
 
   content::WebContents* tab =
       browser()->tab_strip_model()->GetActiveWebContents();
@@ -307,14 +281,12 @@
 
   for (const auto& c : cases) {
     base::test::ScopedFeatureList scoped_feature_list;
-    if (c.feature_param.empty()) {
-      scoped_feature_list.InitAndDisableFeature(
+    if (c.is_enabled) {
+      scoped_feature_list.InitAndEnableFeature(
           omnibox::kSimplifyHttpsIndicator);
     } else {
-      scoped_feature_list.InitAndEnableFeatureWithParameters(
-          omnibox::kSimplifyHttpsIndicator,
-          {{OmniboxFieldTrial::kSimplifyHttpsIndicatorParameterName,
-            c.feature_param}});
+      scoped_feature_list.InitAndDisableFeature(
+          omnibox::kSimplifyHttpsIndicator);
     }
     SetUpInterceptor(c.cert_status);
     ui_test_utils::NavigateToURL(browser(), c.url);
diff --git a/chrome/browser/ui/views/sad_tab_view.cc b/chrome/browser/ui/views/sad_tab_view.cc
index a99b6a1..2a81daf4 100644
--- a/chrome/browser/ui/views/sad_tab_view.cc
+++ b/chrome/browser/ui/views/sad_tab_view.cc
@@ -52,9 +52,6 @@
 
 }  // namespace
 
-// static
-const char SadTabView::kViewClassName[] = "SadTabView";
-
 SadTabView::SadTabView(content::WebContents* web_contents, SadTabKind kind)
     : SadTab(web_contents, kind) {
   // This view gets inserted as a child of a WebView, but we don't want the
@@ -208,10 +205,6 @@
   View::Layout();
 }
 
-const char* SadTabView::GetClassName() const {
-  return kViewClassName;
-}
-
 void SadTabView::OnPaint(gfx::Canvas* canvas) {
   if (!painted_) {
     RecordFirstPaint();
@@ -228,3 +221,7 @@
                        SadTabKind kind) {
   return new SadTabView(web_contents, kind);
 }
+
+BEGIN_METADATA(SadTabView)
+METADATA_PARENT_CLASS(views::View)
+END_METADATA()
diff --git a/chrome/browser/ui/views/sad_tab_view.h b/chrome/browser/ui/views/sad_tab_view.h
index 54c2794e..6a9c8cc 100644
--- a/chrome/browser/ui/views/sad_tab_view.h
+++ b/chrome/browser/ui/views/sad_tab_view.h
@@ -39,7 +39,7 @@
                    public views::LinkListener,
                    public views::ButtonListener {
  public:
-  static const char kViewClassName[];
+  METADATA_HEADER(SadTabView);
 
   SadTabView(content::WebContents* web_contents, SadTabKind kind);
   ~SadTabView() override;
@@ -49,7 +49,6 @@
 
   // Overridden from views::View:
   void Layout() override;
-  const char* GetClassName() const override;
 
   // Overridden from views::LinkListener:
   void LinkClicked(views::Link* source, int event_flags) override;
diff --git a/chrome/browser/ui/views/sad_tab_view_interactive_uitest.cc b/chrome/browser/ui/views/sad_tab_view_interactive_uitest.cc
index 1566630..78b561fe 100644
--- a/chrome/browser/ui/views/sad_tab_view_interactive_uitest.cc
+++ b/chrome/browser/ui/views/sad_tab_view_interactive_uitest.cc
@@ -18,7 +18,7 @@
 #include "content/public/browser/render_process_host.h"
 #include "content/public/common/result_codes.h"
 #include "content/public/test/browser_test_utils.h"
-#include "ui/views/controls/button/label_button.h"
+#include "ui/views/controls/button/md_text_button.h"
 #include "ui/views/widget/widget.h"
 
 namespace test {
@@ -79,7 +79,7 @@
   views::View* GetFocusedView() { return GetFocusManager()->GetFocusedView(); }
 
   const char* ActionButtonClassName() {
-    return views::LabelButton::kViewClassName;
+    return views::MdTextButton::kViewClassName;
   }
 
   bool IsFocusedViewInsideViewClass(const char* view_class) {
@@ -145,7 +145,7 @@
   // Kill the renderer process, resulting in a sad tab.
   KillRendererForActiveWebContentsSync();
 
-  // Focus should now be on a label button inside the sad tab.
+  // Focus should now be on a MdText button inside the sad tab.
   ASSERT_STREQ(GetFocusedView()->GetClassName(), ActionButtonClassName());
   ASSERT_TRUE(IsFocusedViewInsideSadTab());
   ASSERT_FALSE(IsFocusedViewInsideBrowserToolbar());
diff --git a/chrome/browser/ui/views/toolbar/browser_app_menu_button.cc b/chrome/browser/ui/views/toolbar/browser_app_menu_button.cc
index 3e2387f..81cb58b 100644
--- a/chrome/browser/ui/views/toolbar/browser_app_menu_button.cc
+++ b/chrome/browser/ui/views/toolbar/browser_app_menu_button.cc
@@ -216,7 +216,7 @@
 #if defined(OS_CHROMEOS)
   auto* keyboard_client = ChromeKeyboardControllerClient::Get();
   if (keyboard_client->is_keyboard_visible())
-    keyboard_client->HideKeyboard(ash::mojom::HideReason::kSystem);
+    keyboard_client->HideKeyboard(ash::HideReason::kSystem);
 #endif
 
   Browser* browser = toolbar_view_->browser();
diff --git a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
index 5e523cde..15e03543 100644
--- a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
@@ -942,7 +942,7 @@
 void GaiaScreenHandler::OnShowAddUser() {
   signin_screen_handler_->is_account_picker_showing_first_time_ = false;
   lock_screen_utils::EnforcePolicyInputMethods(std::string());
-  ShowGaiaAsync(base::nullopt);
+  ShowGaiaAsync(EmptyAccountId());
 }
 
 void GaiaScreenHandler::DoCompleteLogin(
@@ -1086,10 +1086,9 @@
   UMA_HISTOGRAM_BOOLEAN("ChromeOS.SAML.APIUsed", api_used);
 }
 
-void GaiaScreenHandler::ShowGaiaAsync(
-    const base::Optional<AccountId>& account_id) {
-  if (account_id)
-    populated_email_ = account_id->GetUserEmail();
+void GaiaScreenHandler::ShowGaiaAsync(const AccountId& account_id) {
+  if (account_id.is_valid())
+    populated_email_ = account_id.GetUserEmail();
   show_when_ready_ = true;
   if (gaia_silent_load_ && populated_email_.empty()) {
     dns_cleared_ = true;
diff --git a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h
index 674b2a53..5dcd490d 100644
--- a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h
@@ -56,7 +56,7 @@
   // either be shown immediately or after an asynchronous clean-up process that
   // cleans DNS cache and cookies. If available, |account_id| is used for
   // prefilling information.
-  virtual void ShowGaiaAsync(const base::Optional<AccountId>& account_id) = 0;
+  virtual void ShowGaiaAsync(const AccountId& account_id) = 0;
 
   // Show sign-in screen for the given credentials. |services| is a list of
   // services returned by userInfo call as JSON array. Should be an empty array
@@ -109,7 +109,7 @@
   // GaiaView:
   void MaybePreloadAuthExtension() override;
   void DisableRestrictiveProxyCheckForTest() override;
-  void ShowGaiaAsync(const base::Optional<AccountId>& account_id) override;
+  void ShowGaiaAsync(const AccountId& account_id) override;
   void ShowSigninScreenForTest(const std::string& username,
                                const std::string& password,
                                const std::string& services) override;
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index fe054c7..2704474 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -3604,7 +3604,6 @@
       "../browser/task_manager/sampling/shared_sampler_win_unittest.cc",
       "../browser/task_manager/sampling/task_group_unittest.cc",
       "../browser/task_manager/sampling/task_manager_impl_unittest.cc",
-      "../browser/task_manager/sampling/task_manager_io_thread_helper_unittest.cc",
       "../browser/task_manager/task_manager_observer_unittest.cc",
       "../browser/task_manager/test_task_manager.cc",
       "../browser/task_manager/test_task_manager.h",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/Features.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/Features.java
index d4a81a3c..ed22f9d9 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/Features.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/Features.java
@@ -123,8 +123,9 @@
     }
 
     /**
-     * Feature processor intended to be used in JUnit tests, that applies the collected feature
-     * state to {@link ChromeFeatureList}'s internal test-only feature map.
+     * Feature processor intended to be used in Robolectric and {@link DummyUiActivityTestCase}
+     * tests. The collected feature states would be applied to {@link ChromeFeatureList}'s
+     * internal test-only feature map.
      */
     public static class JUnitProcessor extends Processor {
         @Override
@@ -134,8 +135,9 @@
     }
 
     /**
-     * Feature processor intended to be used in instrumentation tests, that applies the collected
-     * feature state to {@link CommandLine}.
+     * Feature processor intended to be used in instrumentation tests with native library, like
+     * {@link ChromeBrowserTestRule}. The collected feature states would be applied to
+     * {@link CommandLine}.
      */
     public static class InstrumentationProcessor extends Processor {
         @Override
diff --git a/chrome/test/data/extensions/api_test/active_tab_cors/background.js b/chrome/test/data/extensions/api_test/active_tab_cors/background.js
new file mode 100644
index 0000000..52f1588
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/active_tab_cors/background.js
@@ -0,0 +1,22 @@
+// 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.
+
+chrome.browserAction.onClicked.addListener(function(tab) {
+  const script = `
+fetch(location.href).then((res) => {
+  chrome.runtime.sendMessage('', res.status === 200 ? 'PASS' : 'FAIL');
+}, () => {
+  chrome.runtime.sendMessage('', 'FAIL');
+});
+`;
+
+  chrome.runtime.onMessage.addListener(function listener(message) {
+    chrome.runtime.onMessage.removeListener(listener);
+    chrome.test.assertEq('PASS', message);
+    chrome.test.notifyPass();
+  });
+  chrome.tabs.executeScript({code: script});
+});
+
+chrome.test.sendMessage('ready');
diff --git a/chrome/test/data/extensions/api_test/active_tab_cors/manifest.json b/chrome/test/data/extensions/api_test/active_tab_cors/manifest.json
new file mode 100644
index 0000000..c00f50f1
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/active_tab_cors/manifest.json
@@ -0,0 +1,12 @@
+{
+  "manifest_version": 2,
+  "name": "The content script should have an access to the page origin",
+  "version": "1.0",
+  "browser_action": {},
+  "background" : {
+    "scripts" : ["background.js"]
+  },
+  "permissions": [
+    "activeTab"
+  ]
+}
diff --git a/chrome/test/data/extensions/api_test/active_tab_cors/page.html b/chrome/test/data/extensions/api_test/active_tab_cors/page.html
new file mode 100644
index 0000000..5fec2e75
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/active_tab_cors/page.html
@@ -0,0 +1 @@
+<title>page</title>
diff --git a/chrome/test/data/webui/print_preview/advanced_dialog_test.js b/chrome/test/data/webui/print_preview/advanced_dialog_test.js
index 498615f2..df9f489 100644
--- a/chrome/test/data/webui/print_preview/advanced_dialog_test.js
+++ b/chrome/test/data/webui/print_preview/advanced_dialog_test.js
@@ -112,7 +112,7 @@
       setupDialog(3);
       setItemValues();
 
-      const buttons = dialog.shadowRoot.querySelectorAll('paper-button');
+      const buttons = dialog.shadowRoot.querySelectorAll('cr-button');
       assertEquals(2, buttons.length);
       const whenDialogClose = test_util.eventToPromise('close', dialog);
 
@@ -133,7 +133,7 @@
       setupDialog(3);
       setItemValues();
 
-      const buttons = dialog.shadowRoot.querySelectorAll('paper-button');
+      const buttons = dialog.shadowRoot.querySelectorAll('cr-button');
       assertEquals(2, buttons.length);
       const whenDialogClose = test_util.eventToPromise('close', dialog);
 
diff --git a/chrome/test/data/webui/print_preview/button_strip_test.js b/chrome/test/data/webui/print_preview/button_strip_test.js
index 6e0c4a55..8967969 100644
--- a/chrome/test/data/webui/print_preview/button_strip_test.js
+++ b/chrome/test/data/webui/print_preview/button_strip_test.js
@@ -55,12 +55,12 @@
     test(assert(TestNames.ButtonOrder), function() {
       // Verify that there are only 2 buttons.
       assertEquals(
-          2, buttonStrip.shadowRoot.querySelectorAll('paper-button').length);
+          2, buttonStrip.shadowRoot.querySelectorAll('cr-button').length);
 
-      const firstButton = buttonStrip.$$('paper-button:not(:last-child)');
-      const lastButton = buttonStrip.$$('paper-button:last-child');
-      const printButton = buttonStrip.$$('paper-button.action-button');
-      const cancelButton = buttonStrip.$$('paper-button.cancel-button');
+      const firstButton = buttonStrip.$$('cr-button:not(:last-child)');
+      const lastButton = buttonStrip.$$('cr-button:last-child');
+      const printButton = buttonStrip.$$('cr-button.action-button');
+      const cancelButton = buttonStrip.$$('cr-button.cancel-button');
 
       if (cr.isWindows) {
         // On Windows, the print button is on the left.
@@ -75,8 +75,8 @@
     // Tests that the button strip fires print-requested and cancel-requested
     // events.
     test(assert(TestNames.ButtonStripFiresEvents), function() {
-      const printButton = buttonStrip.$$('paper-button.action-button');
-      const cancelButton = buttonStrip.$$('paper-button.cancel-button');
+      const printButton = buttonStrip.$$('cr-button.action-button');
+      const cancelButton = buttonStrip.$$('cr-button.cancel-button');
 
       const whenPrintRequested =
           test_util.eventToPromise('print-requested', buttonStrip);
diff --git a/chrome/test/data/webui/print_preview/cloud_print_interface_stub.js b/chrome/test/data/webui/print_preview/cloud_print_interface_stub.js
index 5b22b484..7b78e02a 100644
--- a/chrome/test/data/webui/print_preview/cloud_print_interface_stub.js
+++ b/chrome/test/data/webui/print_preview/cloud_print_interface_stub.js
@@ -22,6 +22,9 @@
 
       /** @private {boolean} */
       this.initialized_ = false;
+
+      /** @private {!Array<string>} */
+      this.users_ = [];
     }
 
     /** @override */
@@ -34,12 +37,20 @@
       return this.searchInProgress_;
     }
 
+    /** @override */
+    setUsers(users) {
+      this.users_ = users;
+    }
+
     /**
      * @param {!print_preview.Destination} printer The destination to return
      *     when the printer is requested.
      */
     setPrinter(printer) {
       this.cloudPrintersMap_.set(printer.key, printer);
+      if (!this.users_.includes(printer.account)) {
+        this.users_.push(printer.account);
+      }
     }
 
     /**
@@ -64,12 +75,12 @@
     search(account) {
       this.methodCalled('search', account);
       this.searchInProgress_ = true;
-      const users = this.getUsers_();
-      const activeUser = users.includes(account) ? account : (users[0] || '');
+      const activeUser =
+          this.users_.includes(account) ? account : (this.users_[0] || '');
       if (activeUser) {
         this.eventTarget_.dispatchEvent(new CustomEvent(
             cloudprint.CloudPrintInterfaceEventType.UPDATE_USERS,
-            {detail: {users: users, activeUser: activeUser}}));
+            {detail: {users: this.users_, activeUser: activeUser}}));
         this.initialized_ = true;
       }
 
@@ -109,12 +120,12 @@
           print_preview.createDestinationKey(printerId, origin, account));
 
       if (!this.initialized_) {
-        const users = this.getUsers_();
-        const activeUser = users.includes(account) ? account : (users[0] || '');
+        const activeUser =
+            this.users_.includes(account) ? account : (this.users_[0] || '');
         if (activeUser) {
           this.eventTarget_.dispatchEvent(new CustomEvent(
               cloudprint.CloudPrintInterfaceEventType.UPDATE_USERS,
-              {detail: {users: users, activeUser: activeUser}}));
+              {detail: {users: this.users_, activeUser: activeUser}}));
           this.initialized_ = true;
         }
       }
diff --git a/chrome/test/data/webui/print_preview/destination_dialog_test.js b/chrome/test/data/webui/print_preview/destination_dialog_test.js
index f116e99..d27a3d83 100644
--- a/chrome/test/data/webui/print_preview/destination_dialog_test.js
+++ b/chrome/test/data/webui/print_preview/destination_dialog_test.js
@@ -7,7 +7,6 @@
   const TestNames = {
     PrinterList: 'PrinterList',
     ShowProvisionalDialog: 'ShowProvisionalDialog',
-    ReloadPrinterList: 'ReloadPrinterList',
     UserAccounts: 'UserAccounts',
   };
 
@@ -63,6 +62,9 @@
       dialog.users = [];
       dialog.destinationStore = destinationStore;
       dialog.invitationStore = new print_preview.InvitationStore();
+    });
+
+    function finishSetup() {
       document.body.appendChild(dialog);
       return nativeLayer.whenCalled('getPrinterCapabilities')
           .then(function() {
@@ -73,10 +75,11 @@
           .then(function() {
             Polymer.dom.flush();
           });
-    });
+    }
 
     // Test that destinations are correctly displayed in the lists.
-    test(assert(TestNames.PrinterList), function() {
+    test(assert(TestNames.PrinterList), async () => {
+      await finishSetup();
       const list = dialog.$$('print-preview-destination-list');
 
       const printerItems = list.shadowRoot.querySelectorAll(
@@ -92,7 +95,7 @@
       assertEquals(
           'rgb(32, 33, 36)',
           window.getComputedStyle(printerItems[0].$$('.name')).color);
-      // FooName will be second since it was updated by the capabilities fetch.
+      // FooName will be second since it was updated by capabilities fetch.
       assertEquals('FooName', getDisplayedName(printerItems[1]));
       Array.from(printerItems).slice(2).forEach((item, index) => {
         assertEquals(destinations[index].displayName, getDisplayedName(item));
@@ -102,9 +105,8 @@
     // Test that clicking a provisional destination shows the provisional
     // destinations dialog, and that the escape key closes only the provisional
     // dialog when it is open, not the destinations dialog.
-    test(assert(TestNames.ShowProvisionalDialog), function() {
-      const provisionalDialog =
-          dialog.$$('print-preview-provisional-destination-resolver');
+    test(assert(TestNames.ShowProvisionalDialog), async () => {
+      let provisionalDialog = null;
       const provisionalDestination = {
         extensionId: 'ABC123',
         extensionName: 'ABC Printing',
@@ -116,73 +118,37 @@
       // Set the extension destinations and force the destination store to
       // reload printers.
       nativeLayer.setExtensionDestinations([provisionalDestination]);
-      destinationStore.onDestinationsReload();
-
-      return nativeLayer.whenCalled('getPrinters')
-          .then(function() {
-            Polymer.dom.flush();
-            assertFalse(provisionalDialog.$.dialog.open);
-            const list = dialog.$$('print-preview-destination-list');
-            const printerItems = list.shadowRoot.querySelectorAll(
-                'print-preview-destination-list-item');
-
-            // Should have 5 local destinations, Save as PDF + extension
-            // destination.
-            assertEquals(7, printerItems.length);
-            const provisionalItem =
-                Array.from(printerItems).find(printerItem => {
-                  return printerItem.destination.id ===
-                      provisionalDestination.id;
-                });
-
-            // Click the provisional destination to select it.
-            provisionalItem.click();
-            Polymer.dom.flush();
-            assertTrue(provisionalDialog.$.dialog.open);
-
-            // Send escape key on provisionalDialog. Destinations dialog should
-            // not close.
-            const whenClosed =
-                test_util.eventToPromise('close', provisionalDialog);
-            MockInteractions.keyEventOn(
-                provisionalDialog, 'keydown', 19, [], 'Escape');
-            Polymer.dom.flush();
-            return whenClosed;
-          })
-          .then(function() {
-            assertFalse(provisionalDialog.$.dialog.open);
-            assertTrue(dialog.$.dialog.open);
-          });
-    });
-
-    // Test that destinations are correctly cleared when the destination store
-    // reloads the printer list.
-    test(assert(TestNames.ReloadPrinterList), function() {
+      await finishSetup();
+      Polymer.dom.flush();
+      provisionalDialog =
+          dialog.$$('print-preview-provisional-destination-resolver');
+      assertFalse(provisionalDialog.$.dialog.open);
       const list = dialog.$$('print-preview-destination-list');
-
       const printerItems = list.shadowRoot.querySelectorAll(
           'print-preview-destination-list-item');
 
-      assertEquals(6, printerItems.length);
-      const oldPdfDestination = printerItems[0].destination;
-      assertEquals(
-          print_preview.Destination.GooglePromotedId.SAVE_AS_PDF,
-          oldPdfDestination.id);
-      const whenReset = test_util.eventToPromise(
-          print_preview.DestinationStore.EventType.DESTINATIONS_RESET,
-          destinationStore);
-      cr.webUIListenerCallback('user-accounts-updated', ['foo@chromium.org']);
-      return whenReset.then(() => {
-        Polymer.dom.flush();
-        const printerItems = dialog.$.printList.shadowRoot.querySelectorAll(
-            'print-preview-destination-list-item');
-        assertEquals(6, printerItems.length);
-        const newPdfDestination = printerItems[0].destination;
-        assertEquals(
-            print_preview.Destination.GooglePromotedId.SAVE_AS_PDF,
-            newPdfDestination.id);
-        assertNotEquals(oldPdfDestination, newPdfDestination);
+      // Should have 5 local destinations, Save as PDF + extension
+      // destination.
+      assertEquals(7, printerItems.length);
+      const provisionalItem = Array.from(printerItems).find(printerItem => {
+        return printerItem.destination.id === provisionalDestination.id;
       });
+
+      // Click the provisional destination to select it.
+      provisionalItem.click();
+      Polymer.dom.flush();
+      assertTrue(provisionalDialog.$.dialog.open);
+
+      // Send escape key on provisionalDialog. Destinations dialog should
+      // not close.
+      const whenClosed = test_util.eventToPromise('close', provisionalDialog);
+      MockInteractions.keyEventOn(
+          provisionalDialog, 'keydown', 19, [], 'Escape');
+      Polymer.dom.flush();
+      await whenClosed;
+
+      assertFalse(provisionalDialog.$.dialog.open);
+      assertTrue(dialog.$.dialog.open);
     });
 
     /**
@@ -223,7 +189,7 @@
     }
 
     // Test that signing in and switching accounts works as expected.
-    test(assert(TestNames.UserAccounts), function() {
+    test(assert(TestNames.UserAccounts), async () => {
       // Set up the cloud print interface with Google Drive printer for a couple
       // different accounts.
       const user1 = 'foo@chromium.org';
@@ -232,17 +198,23 @@
           print_preview_test_utils.getGoogleDriveDestination(user1));
       cloudPrintInterface.setPrinter(
           print_preview_test_utils.getGoogleDriveDestination(user2));
+      let userSelect = null;
 
-      // Check that both cloud print promo and dropdown are hidden when cloud
-      // print is disabled.
+      await finishSetup();
+      // Check that both cloud print promo and dropdown are hidden when
+      // cloud print is disabled.
       dialog.cloudPrintDisabled = true;
       assertTrue(dialog.$.cloudprintPromo.hidden);
       assertTrue(dialog.$$('.user-info').hidden);
-      const userSelect = dialog.$$('.md-select');
+      userSelect = dialog.$$('.md-select');
 
       // Enable cloud print.
       dialog.cloudPrintDisabled = false;
       assertSignedInState('', 0);
+      // Local, extension, privet, and cloud (since
+      // startLoadAllDestinations() was called).
+      assertEquals(3, nativeLayer.getCallCount('getPrinters'));
+      assertEquals(1, cloudPrintInterface.getCallCount('search'));
 
       // 6 printers, no Google drive (since not signed in).
       assertNumPrintersWithDriveAccount(6, '');
@@ -250,68 +222,73 @@
       // Simulate signing in to an account.
       destinationStore.setActiveUser(user1);
       dialog.$.cloudprintPromo.querySelector('[is=\'action-link\']').click();
-      return nativeLayer.whenCalled('signIn')
-          .then(addAccount => {
-            assertFalse(addAccount);
-            nativeLayer.resetResolver('signIn');
-            dialog.activeUser = user1;
-            dialog.users = [user1];
-            Polymer.dom.flush();
+      let addAccount = await nativeLayer.whenCalled('signIn');
 
-            // Promo is hidden and select shows the signed in user.
-            assertSignedInState(user1, 1);
+      assertFalse(addAccount);
+      nativeLayer.resetResolver('signIn');
+      // This will be done by print-preview-user-info, in response to sign
+      // in.
+      destinationStore.setActiveUser(user1);
+      destinationStore.reloadUserCookieBasedDestinations(user1);
+      dialog.activeUser = user1;
+      dialog.users = [user1];
+      Polymer.dom.flush();
 
-            // Now have 7 printers (Google Drive), with user1 signed in.
-            assertNumPrintersWithDriveAccount(7, user1);
+      // Promo is hidden and select shows the signed in user.
+      assertSignedInState(user1, 1);
 
-            // Simulate signing into a second account.
-            userSelect.value = '';
-            userSelect.dispatchEvent(new CustomEvent('change'));
-            return nativeLayer.whenCalled('signIn');
-          })
-          .then(addAccount => {
-            assertTrue(addAccount);
-            dialog.users = [user1, user2];
-            Polymer.dom.flush();
+      // Now have 7 printers (Google Drive), with user1 signed in.
+      assertNumPrintersWithDriveAccount(7, user1);
+      assertEquals(3, nativeLayer.getCallCount('getPrinters'));
+      // Cloud printers should have been re-fetched.
+      assertEquals(2, cloudPrintInterface.getCallCount('search'));
 
-            // Promo is hidden and select shows the signed in user.
-            assertSignedInState(user1, 2);
+      // Simulate signing into a second account.
+      userSelect.value = '';
+      userSelect.dispatchEvent(new CustomEvent('change'));
 
-            // Still have 7 printers (Google Drive), with user1 signed in.
-            assertNumPrintersWithDriveAccount(7, user1);
+      addAccount = await nativeLayer.whenCalled('signIn');
+      assertTrue(addAccount);
+      // No new printer fetch until the user actually changes the active
+      // account.
+      assertEquals(3, nativeLayer.getCallCount('getPrinters'));
+      assertEquals(2, cloudPrintInterface.getCallCount('search'));
+      dialog.users = [user1, user2];
+      Polymer.dom.flush();
 
-            // Select the second account.
-            const whenEventFired =
-                test_util.eventToPromise('account-change', dialog);
-            userSelect.value = user2;
-            userSelect.dispatchEvent(new CustomEvent('change'));
-            return whenEventFired;
-          })
-          .then(() => {
-            Polymer.dom.flush();
+      // Promo is hidden and select shows the signed in user.
+      assertSignedInState(user1, 2);
 
-            // Check printers were temporarily cleared.
-            assertNumPrintersWithDriveAccount(0, '');
+      // Still have 7 printers (Google Drive), with user1 signed in.
+      assertNumPrintersWithDriveAccount(7, user1);
 
-            // This will all be done by app.js and user_manager.js in response
-            // to the account-change event.
-            destinationStore.setActiveUser(user2);
-            dialog.activeUser = user2;
-            const whenInserted = test_util.eventToPromise(
-                print_preview.DestinationStore.EventType.DESTINATIONS_INSERTED,
-                destinationStore);
-            destinationStore.reloadUserCookieBasedDestinations(user2);
+      // Select the second account.
+      const whenEventFired = test_util.eventToPromise('account-change', dialog);
+      userSelect.value = user2;
+      userSelect.dispatchEvent(new CustomEvent('change'));
 
-            return whenInserted;
-          })
-          .then(() => {
-            Polymer.dom.flush();
+      await whenEventFired;
+      Polymer.dom.flush();
 
-            assertSignedInState(user2, 2);
+      // This will all be done by app.js and user_manager.js in response
+      // to the account-change event.
+      destinationStore.setActiveUser(user2);
+      dialog.activeUser = user2;
+      const whenInserted = test_util.eventToPromise(
+          print_preview.DestinationStore.EventType.DESTINATIONS_INSERTED,
+          destinationStore);
+      destinationStore.reloadUserCookieBasedDestinations(user2);
 
-            // 7 printers (Google Drive), with user2 signed in.
-            assertNumPrintersWithDriveAccount(7, user2);
-          });
+      await whenInserted;
+      Polymer.dom.flush();
+
+      assertSignedInState(user2, 2);
+
+      // 7 printers (Google Drive), with user2 signed in.
+      assertNumPrintersWithDriveAccount(7, user2);
+      assertEquals(3, nativeLayer.getCallCount('getPrinters'));
+      // Cloud print should have been queried again for the new account.
+      assertEquals(3, cloudPrintInterface.getCallCount('search'));
     });
   });
 
diff --git a/chrome/test/data/webui/print_preview/destination_select_test.js b/chrome/test/data/webui/print_preview/destination_select_test.js
index 414c4a6..144d66c4 100644
--- a/chrome/test/data/webui/print_preview/destination_select_test.js
+++ b/chrome/test/data/webui/print_preview/destination_select_test.js
@@ -404,6 +404,7 @@
         recentDestinations: recentDestinations,
       });
       initialSettings.userAccounts = [account1, account2];
+      initialSettings.syncAvailable = true;
 
       return setInitialSettings()
           .then(() => {
@@ -415,15 +416,23 @@
             assertPrinterDisplay('Save to Google Drive', false);
 
             // Only the most recent printer + Save as PDF are in the store.
-            const loadedPrinters =
-                destinationSettings.destinationStore_.destinations();
-            assertEquals(2, loadedPrinters.length);
+            const loadedPrintersAccount1 =
+                destinationSettings.destinationStore_.destinations(account1);
+            assertEquals(2, loadedPrintersAccount1.length);
             cloudDestinations.forEach((destination) => {
               assertEquals(
                   destination === driveUser1,
-                  loadedPrinters.some(p => p.key == destination.key));
+                  loadedPrintersAccount1.some(p => p.key == destination.key));
             });
             assertEquals(1, numPrintersSelected);
+
+            // Only Save as PDF exists when filtering for account 2.
+            const loadedPrintersAccount2 =
+                destinationSettings.destinationStore_.destinations(account2);
+            assertEquals(1, loadedPrintersAccount2.length);
+            assertEquals(
+                print_preview.Destination.GooglePromotedId.SAVE_AS_PDF,
+                loadedPrintersAccount2[0].id);
           });
     });
 
diff --git a/chrome/test/data/webui/print_preview/destination_settings_test.js b/chrome/test/data/webui/print_preview/destination_settings_test.js
index 88d50a1..9ebcb11a 100644
--- a/chrome/test/data/webui/print_preview/destination_settings_test.js
+++ b/chrome/test/data/webui/print_preview/destination_settings_test.js
@@ -16,6 +16,7 @@
     OpenDialog: 'open dialog',
     TwoAccountsRecentDestinations: 'two accounts recent destinations',
     UpdateRecentDestinations: 'update recent destinations',
+    ResetDestinationOnSignOut: 'reset destination on sign out',
   };
 
   const suiteName = 'DestinationSettingsTest';
@@ -214,8 +215,9 @@
           .then(() => {
             // This will result in the destination store setting the Save as PDF
             // destination.
-            destinationSettings.destination =
-                print_preview_test_utils.getSaveAsPdfDestination();
+            assertEquals(
+                print_preview.Destination.GooglePromotedId.SAVE_AS_PDF,
+                destinationSettings.destination.id);
             assertFalse(destinationSettings.$.destinationSelect.disabled);
             assertDropdownItems(['Save as PDF/local/']);
 
@@ -244,11 +246,8 @@
           .then(() => {
             // This will result in the destination store setting the most recent
             // destination.
-            destinationSettings.destination = destinations[0];
+            assertEquals('ID1', destinationSettings.destination.id);
             assertFalse(destinationSettings.$.destinationSelect.disabled);
-            return test_util.waitForRender(destinationSettings);
-          })
-          .then(() => {
             assertDropdownItems([
               makeLocalDestinationKey('ID1'),
               makeLocalDestinationKey('ID2'),
@@ -283,11 +282,8 @@
           .then(() => {
             // This will result in the destination store setting the most recent
             // destination.
-            destinationSettings.destination = destinations[0];
+            assertEquals('ID1', destinationSettings.destination.id);
             assertFalse(destinationSettings.$.destinationSelect.disabled);
-            return test_util.waitForRender(destinationSettings);
-          })
-          .then(() => {
             assertDropdownItems([
               makeLocalDestinationKey('ID1'),
               makeLocalDestinationKey('ID3'),
@@ -320,11 +316,9 @@
           .then(() => {
             // This will result in the destination store setting the most recent
             // destination.
-            destinationSettings.destination = destinations[0];
+            assertEquals('ID1', destinationSettings.destination.id);
             assertFalse(destinationSettings.$.destinationSelect.disabled);
-            return test_util.waitForRender(destinationSettings);
-          })
-          .then(() => {
+
             // Google Drive does not show up even though it is recent, since the
             // user is not signed in and the destination is not available.
             assertDropdownItems([
@@ -362,11 +356,8 @@
           .then(() => {
             // This will result in the destination store setting the most recent
             // destination.
-            destinationSettings.destination = destinations[0];
+            assertEquals('ID1', destinationSettings.destination.id);
             assertFalse(dropdown.disabled);
-            return test_util.waitForRender(destinationSettings);
-          })
-          .then(() => {
             assertDropdownItems([
               makeLocalDestinationKey('ID1'),
               makeLocalDestinationKey('ID3'),
@@ -408,11 +399,9 @@
           .then(() => {
             // This will result in the destination store setting the most recent
             // destination.
-            destinationSettings.destination = destinations[0];
+            assertEquals('ID1', destinationSettings.destination.id);
             assertFalse(dropdown.disabled);
-            return test_util.waitForRender(destinationSettings);
-          })
-          .then(() => {
+
             // If the user is signed in, Save to Drive should be displayed.
             signIn();
             assertDropdownItems([
@@ -421,7 +410,8 @@
               'Save as PDF/local/',
               '__google__docs/cookies/foo@chromium.org',
             ]);
-            // Most recent destination is selected by default.
+
+            // Most recent destination is still selected.
             assertEquals('ID1', destinationSettings.destination.id);
 
             // Simulate selection of Google Drive printer.
@@ -453,19 +443,14 @@
           .then(() => {
             // This will result in the destination store setting the most recent
             // destination.
-            destinationSettings.destination = destinations[0];
+            assertEquals('ID1', destinationSettings.destination.id);
             assertFalse(dropdown.disabled);
-            return test_util.waitForRender(destinationSettings);
-          })
-          .then(() => {
             assertDropdownItems([
               makeLocalDestinationKey('ID1'),
               makeLocalDestinationKey('ID2'),
               makeLocalDestinationKey('ID3'),
               'Save as PDF/local/',
             ]);
-            // Most recent destination is selected by default.
-            assertEquals('ID1', destinationSettings.destination.id);
 
             // Simulate selection of Save as PDF printer.
             const whenDestinationSelect = test_util.eventToPromise(
@@ -491,11 +476,8 @@
           .then(() => {
             // This will result in the destination store setting the most recent
             // destination.
-            destinationSettings.destination = destinations[0];
+            assertEquals('ID1', destinationSettings.destination.id);
             assertFalse(dropdown.disabled);
-            return test_util.waitForRender(destinationSettings);
-          })
-          .then(() => {
             assertDropdownItems([
               makeLocalDestinationKey('ID1'),
               makeLocalDestinationKey('ID2'),
@@ -549,12 +531,8 @@
           .then(() => {
             // This will result in the destination store setting the most recent
             // destination.
-            destinationSettings.destination = cloudPrinterUser1;
-            Polymer.dom.flush();
+            assertEquals('FooCloud', destinationSettings.destination.id);
             assertFalse(dropdown.disabled);
-            return test_util.waitForRender(destinationSettings);
-          })
-          .then(() => {
             assertDropdownItems([
               'FooCloud/cookies/foo@chromium.org',
               makeLocalDestinationKey('ID1'),
@@ -661,6 +639,59 @@
             assertEquals(1, nativeLayer.getCallCount('getPrinterCapabilities'));
           });
     });
+
+    // Tests that the dropdown resets the destination if the user signs out of
+    // the account associated with the curret one.
+    test(assert(TestNames.ResetDestinationOnSignOut), function() {
+      recentDestinations = destinations.slice(0, 3).map(
+          destination => print_preview.makeRecentDestination(destination));
+      const driveDestination =
+          print_preview_test_utils.getGoogleDriveDestination(defaultUser);
+      recentDestinations.splice(
+          0, 1, print_preview.makeRecentDestination(driveDestination));
+      cloudPrintInterface.setPrinter(
+          print_preview_test_utils.getGoogleDriveDestination(defaultUser));
+      initialAccounts = [defaultUser];
+      initialize();
+
+      return cloudPrintInterface.whenCalled('printer')
+          .then(() => {
+            assertEquals(
+                print_preview.Destination.GooglePromotedId.DOCS,
+                destinationSettings.destination.id);
+            assertFalse(destinationSettings.$.destinationSelect.disabled);
+            assertDropdownItems([
+              makeLocalDestinationKey('ID2'),
+              makeLocalDestinationKey('ID3'),
+              'Save as PDF/local/',
+              '__google__docs/cookies/foo@chromium.org',
+            ]);
+
+            // Sign out.
+            cr.webUIListenerCallback('user-accounts-updated', []);
+            Polymer.dom.flush();
+
+            return nativeLayer.whenCalled('getPrinterCapabilities');
+          })
+          .then(() => {
+            assertEquals('ID2', destinationSettings.destination.id);
+            assertFalse(destinationSettings.$.destinationSelect.disabled);
+            assertDropdownItems([
+              makeLocalDestinationKey('ID2'),
+              makeLocalDestinationKey('ID3'),
+              'Save as PDF/local/',
+            ]);
+
+            // Now that the selected destination is local, signing in and out
+            // shouldn't impact it.
+            signIn();
+            assertEquals('ID2', destinationSettings.destination.id);
+
+            cr.webUIListenerCallback('user-accounts-updated', []);
+            Polymer.dom.flush();
+            assertEquals('ID2', destinationSettings.destination.id);
+          });
+    });
   });
 
   return {
diff --git a/chrome/test/data/webui/print_preview/header_test.js b/chrome/test/data/webui/print_preview/header_test.js
index 189c2db4..15d818b 100644
--- a/chrome/test/data/webui/print_preview/header_test.js
+++ b/chrome/test/data/webui/print_preview/header_test.js
@@ -134,13 +134,12 @@
     // See https://crbug.com/880562.
     test(assert(TestNames.ButtonOrder), function() {
       // Verify that there are only 2 buttons.
-      assertEquals(
-          2, header.shadowRoot.querySelectorAll('paper-button').length);
+      assertEquals(2, header.shadowRoot.querySelectorAll('cr-button').length);
 
-      const firstButton = header.$$('paper-button:first-child');
-      const lastButton = header.$$('paper-button:last-child');
-      const printButton = header.$$('paper-button.action-button');
-      const cancelButton = header.$$('paper-button.cancel-button');
+      const firstButton = header.$$('cr-button:first-child');
+      const lastButton = header.$$('cr-button:last-child');
+      const printButton = header.$$('cr-button.action-button');
+      const cancelButton = header.$$('cr-button.cancel-button');
 
       if (cr.isWindows) {
         // On Windows, the print button is on the left.
diff --git a/chrome/test/data/webui/print_preview/key_event_test.js b/chrome/test/data/webui/print_preview/key_event_test.js
index d8a2909..5eb7197 100644
--- a/chrome/test/data/webui/print_preview/key_event_test.js
+++ b/chrome/test/data/webui/print_preview/key_event_test.js
@@ -30,7 +30,7 @@
           print_preview_test_utils.getDefaultInitialSettings();
       nativeLayer = new print_preview.NativeLayerStub();
       nativeLayer.setInitialSettings(initialSettings);
-      // Use advanced settings so that we can test with the paper-button.
+      // Use advanced settings so that we can test with the cr-button.
       nativeLayer.setLocalDestinationCapabilities(
           print_preview_test_utils.getCddTemplateWithAdvancedSettings(
               1, initialSettings.printerName));
@@ -99,18 +99,18 @@
 
     // Tests that the enter key does not trigger a call to print if the event
     // comes from a button.
-    test(assert(TestNames.EnterOnButtonDoesNotPrint), function() {
+    test(assert(TestNames.EnterOnButtonDoesNotPrint), async () => {
       const moreSettingsElement =
           page.$$('print-preview-sidebar').$$('print-preview-more-settings');
       moreSettingsElement.$.label.click();
-      const whenKeyEventFired = test_util.eventToPromise('keydown', page);
-      MockInteractions.keyEventOn(
-          page.$$('print-preview-sidebar')
-              .$$('print-preview-advanced-options-settings')
-              .$$('paper-button'),
-          'keydown', 'Enter', [], 'Enter');
-      return whenKeyEventFired.then(
-          () => assertEquals(0, nativeLayer.getCallCount('print')));
+      const button = page.$$('print-preview-sidebar')
+                         .$$('print-preview-advanced-options-settings')
+                         .$$('cr-button');
+      const whenKeyEventFired = test_util.eventToPromise('keydown', button);
+      MockInteractions.keyEventOn(button, 'keydown', 'Enter', [], 'Enter');
+      await whenKeyEventFired;
+      await PolymerTest.flushTasks();
+      assertEquals(0, nativeLayer.getCallCount('print'));
     });
 
     // Tests that the enter key does not trigger a call to print if the event
diff --git a/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js b/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js
index ca316ca9..2cce32a 100644
--- a/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js
+++ b/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js
@@ -746,10 +746,6 @@
     });
 GEN('#endif');
 
-TEST_F('PrintPreviewDestinationDialogTest', 'ReloadPrinterList', function() {
-  this.runMochaTest(destination_dialog_test.TestNames.ReloadPrinterList);
-});
-
 TEST_F('PrintPreviewDestinationDialogTest', 'UserAccounts', function() {
   this.runMochaTest(destination_dialog_test.TestNames.UserAccounts);
 });
@@ -1382,6 +1378,13 @@
           destination_settings_test.TestNames.UpdateRecentDestinations);
     });
 
+TEST_F(
+    'PrintPreviewDestinationSettingsTest', 'ResetDestinationOnSignOut',
+    function() {
+      this.runMochaTest(
+          destination_settings_test.TestNames.ResetDestinationOnSignOut);
+    });
+
 // eslint-disable-next-line no-var
 var PrintPreviewScalingSettingsTest = class extends PrintPreviewTest {
   /** @override */
diff --git a/chrome/test/data/webui/print_preview/user_manager_test.js b/chrome/test/data/webui/print_preview/user_manager_test.js
index 50a0159..89ba3e972 100644
--- a/chrome/test/data/webui/print_preview/user_manager_test.js
+++ b/chrome/test/data/webui/print_preview/user_manager_test.js
@@ -64,7 +64,7 @@
 
       assertTrue(userManager.cloudPrintDisabled);
 
-      userManager.setCloudPrintInterface(cloudPrintInterface);
+      userManager.cloudPrintInterface = cloudPrintInterface;
       assertFalse(userManager.cloudPrintDisabled);
       assertEquals(undefined, userManager.activeUser);
 
@@ -74,28 +74,27 @@
       assertEquals(0, cloudPrintInterface.getCallCount('search'));
 
       // Simulate signing in and out of accounts. This should update the list of
-      // users and the active user and triggers a call to search since the
-      // destination store calls onDestinationsReload each time this event
-      // fires.
+      // users and the active user, but shouldn't result in searching for cloud
+      // printers since |shouldReloadCookies| is false.
       cr.webUIListenerCallback('user-accounts-updated', [account1]);
       assertEquals(account1, userManager.activeUser);
       assertEquals(1, userManager.users.length);
-      assertEquals(1, cloudPrintInterface.getCallCount('search'));
+      assertEquals(0, cloudPrintInterface.getCallCount('search'));
 
       cr.webUIListenerCallback('user-accounts-updated', [account1, account2]);
       assertEquals(account1, userManager.activeUser);
       assertEquals(2, userManager.users.length);
-      assertEquals(2, cloudPrintInterface.getCallCount('search'));
+      assertEquals(0, cloudPrintInterface.getCallCount('search'));
 
       cr.webUIListenerCallback('user-accounts-updated', [account2]);
       assertEquals(account2, userManager.activeUser);
       assertEquals(1, userManager.users.length);
-      assertEquals(3, cloudPrintInterface.getCallCount('search'));
+      assertEquals(0, cloudPrintInterface.getCallCount('search'));
 
       cr.webUIListenerCallback('user-accounts-updated', []);
       assertEquals('', userManager.activeUser);
       assertEquals(0, userManager.users.length);
-      assertEquals(4, cloudPrintInterface.getCallCount('search'));
+      assertEquals(0, cloudPrintInterface.getCallCount('search'));
     });
 
     // Checks that initializing and updating user accounts works as expected
@@ -103,7 +102,54 @@
     test('update users without sync', function() {
       assertTrue(userManager.cloudPrintDisabled);
 
-      userManager.setCloudPrintInterface(cloudPrintInterface);
+      const whenCalled = cloudPrintInterface.whenCalled('printer');
+      userManager.cloudPrintInterface = cloudPrintInterface;
+      assertFalse(userManager.cloudPrintDisabled);
+      assertEquals(undefined, userManager.activeUser);
+
+      userManager.initUserAccounts([], false /* syncAvailable */);
+      return whenCalled
+          .then(() => {
+            assertEquals(undefined, userManager.activeUser);
+            assertEquals(0, userManager.users.length);
+            assertEquals(0, cloudPrintInterface.getCallCount('search'));
+            // Need to check for the Google Drive printer by calling
+            // cloudPrintInterface.printer(), since sync is not available.
+            assertEquals(1, cloudPrintInterface.getCallCount('printer'));
+
+            // Simulate signing into an account by setting a cloud printer for
+            // it and firing the 'check-for-account-update' listener.
+            // This should update the list of users and the active user and
+            // trigger a call to search.
+            cloudPrintInterface.setPrinter(
+                print_preview_test_utils.getGoogleDriveDestination(account1));
+            cr.webUIListenerCallback('check-for-account-update');
+            return cloudPrintInterface.whenCalled('search');
+          })
+          .then(() => {
+            assertEquals(account1, userManager.activeUser);
+            assertEquals(1, userManager.users.length);
+            assertEquals(1, cloudPrintInterface.getCallCount('search'));
+
+            // Simulate signing in to a second account.
+            cloudPrintInterface.setPrinter(
+                print_preview_test_utils.getGoogleDriveDestination(account2));
+            cr.webUIListenerCallback('check-for-account-update');
+            return cloudPrintInterface.whenCalled('search');
+          })
+          .then(() => {
+            assertEquals(account1, userManager.activeUser);
+            assertEquals(2, userManager.users.length);
+            assertEquals(2, cloudPrintInterface.getCallCount('search'));
+          });
+    });
+
+    // Checks that initializing and updating user accounts works as expected
+    // when sync is unavailable.
+    test('update users without sync', function() {
+      assertTrue(userManager.cloudPrintDisabled);
+
+      userManager.cloudPrintInterface = cloudPrintInterface;
       assertFalse(userManager.cloudPrintDisabled);
       assertEquals(undefined, userManager.activeUser);
 
@@ -150,7 +196,7 @@
           print_preview_test_utils.getGoogleDriveDestination(account1));
       cloudPrintInterface.setPrinter(
           print_preview_test_utils.getGoogleDriveDestination(account2));
-      userManager.setCloudPrintInterface(cloudPrintInterface);
+      userManager.cloudPrintInterface = cloudPrintInterface;
       userManager.initUserAccounts(
           [account1, account2], true /* syncAvailable */);
       assertFalse(userManager.cloudPrintDisabled);
diff --git a/chrome/test/data/webui/settings/about_page_tests.js b/chrome/test/data/webui/settings/about_page_tests.js
index a2745141..75c10e2 100644
--- a/chrome/test/data/webui/settings/about_page_tests.js
+++ b/chrome/test/data/webui/settings/about_page_tests.js
@@ -895,7 +895,7 @@
           page = document.createElement('settings-detailed-build-info');
           document.body.appendChild(page);
           return browserProxy.whenCalled('getChannelInfo').then(function() {
-            const changeChannelButton = page.$$('paper-button');
+            const changeChannelButton = page.$$('cr-button');
             assertTrue(!!changeChannelButton);
             assertEquals(canChangeChannel, !changeChannelButton.disabled);
           });
diff --git a/chrome/test/data/webui/settings/chromeos/smb_shares_page_tests.js b/chrome/test/data/webui/settings/chromeos/smb_shares_page_tests.js
index 255a327..fef64e1f 100644
--- a/chrome/test/data/webui/settings/chromeos/smb_shares_page_tests.js
+++ b/chrome/test/data/webui/settings/chromeos/smb_shares_page_tests.js
@@ -212,12 +212,16 @@
 
     page = document.createElement('settings-smb-shares-page');
     page.prefs = {
-      network_file_shares: {most_recently_used_url: {value: expectedSmbUrl}},
+      network_file_shares: {
+        most_recently_used_url: {value: expectedSmbUrl},
+        allowed: {value: true},
+      },
     };
     document.body.appendChild(page);
 
     const button = page.$$('#addShare');
     assertTrue(!!button);
+    assertFalse(button.disabled);
     button.click();
 
     Polymer.dom.flush();
diff --git a/chrome/test/data/webui/settings/controlled_button_tests.js b/chrome/test/data/webui/settings/controlled_button_tests.js
index 33db8d9e..e9030e50 100644
--- a/chrome/test/data/webui/settings/controlled_button_tests.js
+++ b/chrome/test/data/webui/settings/controlled_button_tests.js
@@ -38,45 +38,44 @@
   });
 
   test('controlled prefs', function() {
-    assertFalse(controlledButton.$$('paper-button').disabled);
+    assertFalse(controlledButton.$$('cr-button').disabled);
     assertFalse(!!controlledButton.$$('cr-policy-pref-indicator'));
 
     controlledButton.pref = extensionControlledPref;
     Polymer.dom.flush();
-    assertTrue(controlledButton.$$('paper-button').disabled);
+    assertTrue(controlledButton.$$('cr-button').disabled);
     assertTrue(!!controlledButton.$$('cr-policy-pref-indicator'));
 
     controlledButton.pref = policyControlledPref;
     Polymer.dom.flush();
-    assertTrue(controlledButton.$$('paper-button').disabled);
+    assertTrue(controlledButton.$$('cr-button').disabled);
     const indicator = controlledButton.$$('cr-policy-pref-indicator');
     assertTrue(!!indicator);
     assertGT(indicator.clientHeight, 0);
 
     controlledButton.pref = uncontrolledPref;
     Polymer.dom.flush();
-    assertFalse(controlledButton.$$('paper-button').disabled);
+    assertFalse(controlledButton.$$('cr-button').disabled);
     assertFalse(!!controlledButton.$$('cr-policy-pref-indicator'));
   });
 
   test('null pref', function() {
     controlledButton.pref = extensionControlledPref;
     Polymer.dom.flush();
-    assertTrue(controlledButton.$$('paper-button').disabled);
+    assertTrue(controlledButton.$$('cr-button').disabled);
     assertTrue(!!controlledButton.$$('cr-policy-pref-indicator'));
 
     controlledButton.pref = null;
     Polymer.dom.flush();
-    assertFalse(controlledButton.$$('paper-button').disabled);
+    assertFalse(controlledButton.$$('cr-button').disabled);
     assertFalse(!!controlledButton.$$('cr-policy-pref-indicator'));
   });
 
   test('action-button', function() {
-    assertNotEquals("action-button",
-        controlledButton.$$('paper-button').className);
+    assertNotEquals(
+        'action-button', controlledButton.$$('cr-button').className);
     controlledButton.actionButton = true;
     Polymer.dom.flush();
-    assertEquals("action-button",
-        controlledButton.$$('paper-button').className);
+    assertEquals('action-button', controlledButton.$$('cr-button').className);
   });
 });
diff --git a/chrome/test/data/webui/settings/crostini_page_test.js b/chrome/test/data/webui/settings/crostini_page_test.js
index c937960..7c82642 100644
--- a/chrome/test/data/webui/settings/crostini_page_test.js
+++ b/chrome/test/data/webui/settings/crostini_page_test.js
@@ -125,8 +125,8 @@
       subpage.$$('#crostini-export-import').click();
       return flushAsync().then(() => {
         subpage = crostiniPage.$$('settings-crostini-export-import');
-        assertTrue(!!subpage.$$('#export paper-button'));
-        subpage.$$('#export paper-button').click();
+        assertTrue(!!subpage.$$('#export cr-button'));
+        subpage.$$('#export cr-button').click();
         assertEquals(
             1, crostiniBrowserProxy.getCallCount('exportCrostiniContainer'));
       });
@@ -137,16 +137,16 @@
       subpage.$$('#crostini-export-import').click();
       return flushAsync().then(() => {
         subpage = crostiniPage.$$('settings-crostini-export-import');
-        assertTrue(!!subpage.$$('#import paper-button'));
-        subpage.$$('#import paper-button').click();
+        assertTrue(!!subpage.$$('#import cr-button'));
+        subpage.$$('#import cr-button').click();
         assertEquals(
             1, crostiniBrowserProxy.getCallCount('importCrostiniContainer'));
       });
     });
 
     test('Remove', function() {
-      assertTrue(!!subpage.$$('#remove paper-button'));
-      subpage.$$('#remove paper-button').click();
+      assertTrue(!!subpage.$$('#remove cr-button'));
+      subpage.$$('#remove cr-button').click();
       assertEquals(
           1, crostiniBrowserProxy.getCallCount('requestRemoveCrostini'));
       setCrostiniPrefs(false);
diff --git a/chrome/test/data/webui/settings/cups_printer_page_tests.js b/chrome/test/data/webui/settings/cups_printer_page_tests.js
index 2c4aca4..ace6d37 100644
--- a/chrome/test/data/webui/settings/cups_printer_page_tests.js
+++ b/chrome/test/data/webui/settings/cups_printer_page_tests.js
@@ -287,7 +287,7 @@
     // Starts in discovery dialog, select add manually button.
     const discoveryDialog = dialog.$$('add-printer-discovery-dialog');
     assertTrue(!!discoveryDialog);
-    discoveryDialog.$$('.secondary-button').click();
+    discoveryDialog.$.manuallyAddPrinterButton.click();
     Polymer.dom.flush();
 
     // Now we should be in the manually add dialog.
@@ -324,7 +324,7 @@
   test('NoBlankQueries', function() {
     const discoveryDialog = dialog.$$('add-printer-discovery-dialog');
     assertTrue(!!discoveryDialog);
-    discoveryDialog.$$('.secondary-button').click();
+    discoveryDialog.$.manuallyAddPrinterButton.click();
     Polymer.dom.flush();
 
     const addDialog = dialog.$$('add-printer-manually-dialog');
@@ -497,7 +497,7 @@
     // Starts in discovery dialog, select add manually button.
     const discoveryDialog = dialog.$$('add-printer-discovery-dialog');
     assertTrue(!!discoveryDialog);
-    discoveryDialog.$$('.secondary-button').click();
+    discoveryDialog.$.manuallyAddPrinterButton.click();
     Polymer.dom.flush();
 
     // Now we should be in the manually add dialog.
@@ -535,7 +535,7 @@
   test('getEulaUrlGetsCalledOnModelChange', function() {
     const discoveryDialog = dialog.$$('add-printer-discovery-dialog');
     assertTrue(!!discoveryDialog);
-    discoveryDialog.$$('.secondary-button').click();
+    discoveryDialog.$.manuallyAddPrinterButton.click();
     Polymer.dom.flush();
 
     const addDialog = dialog.$$('add-printer-manually-dialog');
@@ -612,6 +612,8 @@
   function clickSaveButton(dialog) {
     assertTrue(!!dialog, 'Dialog is null for save');
     const saveButton = dialog.$$('.action-button');
+    dialog.printerInfoChanged_ = true;
+    assertFalse(saveButton.disabled);
     assertTrue(!!saveButton, 'Button is null');
     saveButton.click();
   }
@@ -848,8 +850,7 @@
 
     Polymer.dom.flush();
 
-    const saveButton = dialog.$$('.action-button');
-    saveButton.click();
+    clickSaveButton(dialog);
 
     return cupsPrintersBrowserProxy.whenCalled('updateCupsPrinter')
         .then(function() {
diff --git a/chrome/test/data/webui/settings/extension_controlled_indicator_tests.js b/chrome/test/data/webui/settings/extension_controlled_indicator_tests.js
index 7d77bfa8..896b0a2 100644
--- a/chrome/test/data/webui/settings/extension_controlled_indicator_tests.js
+++ b/chrome/test/data/webui/settings/extension_controlled_indicator_tests.js
@@ -23,11 +23,11 @@
 
   test('disable button tracks extensionCanBeDisabled', function() {
     assertTrue(indicator.extensionCanBeDisabled);
-    assertTrue(!!indicator.$$('paper-button'));
+    assertTrue(!!indicator.$$('cr-button'));
 
     indicator.extensionCanBeDisabled = false;
     Polymer.dom.flush();
-    assertFalse(!!indicator.$$('paper-button'));
+    assertFalse(!!indicator.$$('cr-button'));
   });
 
   test('label text and href', function() {
@@ -58,7 +58,7 @@
   });
 
   test('tapping disable button invokes browser proxy', function() {
-    const disableButton = indicator.$$('paper-button');
+    const disableButton = indicator.$$('cr-button');
     assertTrue(!!disableButton);
     disableButton.click();
     return browserProxy.whenCalled('disableExtension')
diff --git a/chrome/test/data/webui/settings/kiosk_next_shell_page_tests.js b/chrome/test/data/webui/settings/kiosk_next_shell_page_tests.js
index 6bfca53..745718cb 100644
--- a/chrome/test/data/webui/settings/kiosk_next_shell_page_tests.js
+++ b/chrome/test/data/webui/settings/kiosk_next_shell_page_tests.js
@@ -21,7 +21,7 @@
   }
 
   function showDialog() {
-    const dialogButton = page.$$('paper-button');
+    const dialogButton = page.$$('cr-button');
     assertTrue(!!dialogButton);
     dialogButton.click();
     Polymer.dom.flush();
diff --git a/chrome/test/data/webui/settings/languages_page_tests.js b/chrome/test/data/webui/settings/languages_page_tests.js
index dbd0044..9e6e1dc1 100644
--- a/chrome/test/data/webui/settings/languages_page_tests.js
+++ b/chrome/test/data/webui/settings/languages_page_tests.js
@@ -701,7 +701,7 @@
         checkAllHidden(errorDivs);
 
         const retryButtons =
-            Array.from(spellCheckCollapse.querySelectorAll('paper-button'));
+            Array.from(spellCheckCollapse.querySelectorAll('cr-button'));
         assertEquals(2, retryButtons.length);
         checkAllHidden(retryButtons);
 
diff --git a/chrome/test/data/webui/settings/multidevice_page_tests.js b/chrome/test/data/webui/settings/multidevice_page_tests.js
index a3d15f39..00c6df15 100644
--- a/chrome/test/data/webui/settings/multidevice_page_tests.js
+++ b/chrome/test/data/webui/settings/multidevice_page_tests.js
@@ -104,7 +104,7 @@
 
   test('clicking setup shows multidevice setup dialog', function() {
     setHostData(settings.MultiDeviceSettingsMode.NO_HOST_SET);
-    const button = multidevicePage.$$('paper-button');
+    const button = multidevicePage.$$('cr-button');
     assertTrue(!!button);
     button.click();
     return browserProxy.whenCalled('showMultiDeviceSetupDialog');
diff --git a/chrome/test/data/webui/settings/people_page_sync_page_test.js b/chrome/test/data/webui/settings/people_page_sync_page_test.js
index 32dbc15..a60b7c3 100644
--- a/chrome/test/data/webui/settings/people_page_sync_page_test.js
+++ b/chrome/test/data/webui/settings/people_page_sync_page_test.js
@@ -586,7 +586,7 @@
         assertTrue(toast.open);
 
         // At the end, confirm that setup can be cancelled.
-        toast.querySelector('paper-button').click();
+        toast.querySelector('cr-button').click();
 
         return browserProxy.whenCalled('didNavigateAwayFromSyncPage')
             .then(abort => {
@@ -620,7 +620,7 @@
 
         const cancelButton =
             syncPage.$$('settings-sync-account-control')
-                .shadowRoot.querySelector('#setup-buttons .secondary-button');
+                .shadowRoot.querySelector('#setup-buttons cr-button');
         assertTrue(!!cancelButton);
 
         // Clicking the setup cancel button aborts sync.
diff --git a/chrome/test/data/webui/settings/quick_unlock_authenticate_browsertest_chromeos.js b/chrome/test/data/webui/settings/quick_unlock_authenticate_browsertest_chromeos.js
index c49ccf2..4e9a866 100644
--- a/chrome/test/data/webui/settings/quick_unlock_authenticate_browsertest_chromeos.js
+++ b/chrome/test/data/webui/settings/quick_unlock_authenticate_browsertest_chromeos.js
@@ -117,7 +117,7 @@
         passwordElement.value = 'foo';
         Polymer.dom.flush();
 
-        passwordPromptDialog.$$('paper-button[class="action-button"]').click();
+        passwordPromptDialog.$$('cr-button[class="action-button"]').click();
         Polymer.dom.flush();
 
         assertEquals(0, passwordElement.inputElement.selectionStart);
@@ -138,7 +138,7 @@
         const confirmButton = passwordPromptDialog.$$('#confirmButton');
         quickUnlockPrivateApi.accountPassword = 'bar';
         passwordElement.value = 'foo';
-        passwordPromptDialog.$$('paper-button[class="action-button"]').click();
+        passwordPromptDialog.$$('cr-button[class="action-button"]').click();
 
         assertTrue(passwordElement.hasAttribute('focused_'));
       });
@@ -443,8 +443,8 @@
         titleDiv = getFromElement('div[slot=title]');
         problemDiv = getFromElement('#problemDiv');
         pinKeyboard = getFromElement('pin-keyboard');
-        backButton = getFromElement('paper-button[class="cancel-button"]');
-        continueButton = getFromElement('paper-button[class="action-button"]');
+        backButton = getFromElement('cr-button[class="cancel-button"]');
+        continueButton = getFromElement('cr-button[class="action-button"]');
 
         assertTrue(isVisible(backButton));
         assertTrue(isVisible(continueButton));
diff --git a/chrome/test/data/webui/settings/site_details_tests.js b/chrome/test/data/webui/settings/site_details_tests.js
index 49dba35..f66e356 100644
--- a/chrome/test/data/webui/settings/site_details_tests.js
+++ b/chrome/test/data/webui/settings/site_details_tests.js
@@ -402,7 +402,7 @@
 
     // Check both cancelling and accepting the dialog closes it.
     ['cancel-button', 'action-button'].forEach(buttonType => {
-      testElement.$$('#usage paper-button').click();
+      testElement.$$('#usage cr-button').click();
       assertTrue(testElement.$.confirmClearStorage.open);
       const actionButtonList =
           testElement.$.confirmClearStorage.getElementsByClassName(buttonType);
diff --git a/chrome/test/data/webui/settings/sync_account_control_test.js b/chrome/test/data/webui/settings/sync_account_control_test.js
index b96bd33..efd6cd1 100644
--- a/chrome/test/data/webui/settings/sync_account_control_test.js
+++ b/chrome/test/data/webui/settings/sync_account_control_test.js
@@ -253,7 +253,7 @@
       assertVisible(testElement.$$('#turn-off'), true);
       assertVisible(testElement.$$('#sync-error-button'), false);
 
-      testElement.$$('#avatar-row .secondary-button').click();
+      testElement.$$('#avatar-row #turn-off').click();
       Polymer.dom.flush();
 
       assertEquals(settings.getCurrentRoute(), settings.routes.SIGN_OUT);
diff --git a/chrome/test/data/webui/settings/system_page_tests.js b/chrome/test/data/webui/settings/system_page_tests.js
index 1e3d3534..23bd841 100644
--- a/chrome/test/data/webui/settings/system_page_tests.js
+++ b/chrome/test/data/webui/settings/system_page_tests.js
@@ -73,7 +73,7 @@
     expectEquals(HARDWARE_ACCELERATION_AT_STARTUP, control.checked);
 
     // Restart button should be hidden by default.
-    expectFalse(!!control.querySelector('paper-button'));
+    expectFalse(!!control.querySelector('cr-button'));
 
     systemPage.set(
         'prefs.hardware_acceleration_mode.enabled.value',
@@ -81,7 +81,7 @@
     Polymer.dom.flush();
     expectNotEquals(HARDWARE_ACCELERATION_AT_STARTUP, control.checked);
 
-    const restart = control.querySelector('paper-button');
+    const restart = control.querySelector('cr-button');
     expectTrue(!!restart);  // The "RESTART" button should be showing now.
 
     restart.click();
diff --git a/chrome/test/data/webui/welcome/signin_view_test.js b/chrome/test/data/webui/welcome/signin_view_test.js
index 6499430..dc1af86 100644
--- a/chrome/test/data/webui/welcome/signin_view_test.js
+++ b/chrome/test/data/webui/welcome/signin_view_test.js
@@ -25,7 +25,7 @@
     });
 
     test('sign-in button', function() {
-      const signinButton = testElement.$$('paper-button');
+      const signinButton = testElement.$$('cr-button');
       assertTrue(!!signinButton);
 
       signinButton.click();
diff --git a/chromecast/media/cma/backend/post_processors/post_processor_unittest.cc b/chromecast/media/cma/backend/post_processors/post_processor_unittest.cc
index f85d3bde..77efe58 100644
--- a/chromecast/media/cma/backend/post_processors/post_processor_unittest.cc
+++ b/chromecast/media/cma/backend/post_processors/post_processor_unittest.cc
@@ -17,6 +17,7 @@
 
 namespace chromecast {
 namespace media {
+namespace post_processor_test {
 
 namespace {
 
@@ -24,14 +25,19 @@
 
 // Benchmark parameters.
 const float kTestDurationSec = 1.0;
-const int kBlockSizeFrames = 256;
 
 }  // namespace
 
-namespace post_processor_test {
-
 using Status = AudioPostProcessor2::Status;
 
+AudioPostProcessor2::Config MakeProcessorConfig(int sample_rate_hz) {
+  AudioPostProcessor2::Config config;
+  config.output_sample_rate = sample_rate_hz;
+  config.system_output_sample_rate = sample_rate_hz;
+  config.output_frames_per_write = kBufSizeFrames;
+  return config;
+}
+
 AlignedBuffer<float> LinearChirp(int frames,
                                  const std::vector<double>& start_frequencies,
                                  const std::vector<double>& end_frequencies) {
@@ -67,7 +73,7 @@
 void TestDelay(AudioPostProcessor2* pp,
                int output_sample_rate,
                int num_input_channels) {
-  ASSERT_TRUE(pp->SetConfig({output_sample_rate}));
+  ASSERT_TRUE(pp->SetConfig(MakeProcessorConfig(output_sample_rate)));
 
   const Status& status = pp->GetStatus();
   ASSERT_GT(status.input_sample_rate, 0);
@@ -125,7 +131,7 @@
 void TestRingingTime(AudioPostProcessor2* pp,
                      int sample_rate,
                      int num_input_channels) {
-  ASSERT_TRUE(pp->SetConfig({sample_rate}));
+  ASSERT_TRUE(pp->SetConfig(MakeProcessorConfig(sample_rate)));
 
   const Status& status = pp->GetStatus();
   ASSERT_GT(status.input_sample_rate, 0);
@@ -133,7 +139,7 @@
   ASSERT_GE(status.rendering_delay_frames, 0);
   ASSERT_GE(status.ringing_time_frames, 0);
 
-  const int kNumFrames = GetMaximumFrames(sample_rate);
+  const int kNumFrames = kBufSizeFrames;
   const int kSinFreq = 2000;
 
   // Send a second of data to excite the filter.
@@ -165,9 +171,8 @@
   }
 
   // Send a little more data and ensure the amplitude is < 1% the original.
-  const int probe_frames = 512;
-  data.assign(probe_frames * num_input_channels, 0);
-  pp->ProcessFrames(data.data(), probe_frames, 1.0, 0.0);
+  data.assign(kNumFrames * num_input_channels, 0);
+  pp->ProcessFrames(data.data(), kNumFrames, 1.0, 0.0);
 
   // Only look at the amplitude of the first few frames.
   EXPECT_LE(SineAmplitude(status.output_buffer, 10 * status.output_channels) /
@@ -180,7 +185,7 @@
 void TestPassthrough(AudioPostProcessor2* pp,
                      int sample_rate,
                      int num_input_channels) {
-  EXPECT_TRUE(pp->SetConfig({sample_rate}));
+  ASSERT_TRUE(pp->SetConfig(MakeProcessorConfig(sample_rate)));
 
   const Status& status = pp->GetStatus();
   ASSERT_GT(status.input_sample_rate, 0);
@@ -193,7 +198,7 @@
 
   ASSERT_EQ(status.input_sample_rate, sample_rate);
 
-  const int kNumFrames = GetMaximumFrames(sample_rate);
+  const int kNumFrames = kBufSizeFrames;
   const int kSinFreq = 2000;
 
   AlignedBuffer<float> data =
@@ -225,19 +230,19 @@
 void AudioProcessorBenchmark(AudioPostProcessor2* pp,
                              int sample_rate,
                              int num_input_channels) {
-  ASSERT_TRUE(pp->SetConfig({sample_rate}));
+  ASSERT_TRUE(pp->SetConfig(MakeProcessorConfig(sample_rate)));
 
   int test_size_frames = kTestDurationSec * pp->GetStatus().input_sample_rate;
-  // Make test_size multiple of kBlockSizeFrames and calculate effective
+  // Make test_size multiple of kBufSizeFrames and calculate effective
   // duration.
-  test_size_frames -= test_size_frames % kBlockSizeFrames;
+  test_size_frames -= test_size_frames % kBufSizeFrames;
   float effective_duration = static_cast<float>(test_size_frames) / sample_rate;
   AlignedBuffer<float> data_in = LinearChirp(
       test_size_frames, std::vector<double>(num_input_channels, 0.0),
       std::vector<double>(num_input_channels, 1.0));
   clock_t start_clock = clock();
-  for (int i = 0; i < test_size_frames; i += kBlockSizeFrames * kNumChannels) {
-    pp->ProcessFrames(&data_in[i], kBlockSizeFrames, 1.0, 0.0);
+  for (int i = 0; i < test_size_frames; i += kBufSizeFrames * kNumChannels) {
+    pp->ProcessFrames(&data_in[i], kBufSizeFrames, 1.0, 0.0);
   }
   clock_t stop_clock = clock();
   LOG(INFO) << "At " << sample_rate
@@ -252,10 +257,6 @@
   AudioProcessorBenchmark(&wrapper, sample_rate, kNumChannels);
 }
 
-int GetMaximumFrames(int sample_rate) {
-  return kMaxAudioWriteTimeMilliseconds * sample_rate / 1000;
-}
-
 template <typename T>
 void CheckArraysEqual(const T* expected, const T* actual, size_t size) {
   std::vector<int> differing_values = CompareArray(expected, actual, size);
diff --git a/chromecast/media/cma/backend/post_processors/post_processor_unittest.h b/chromecast/media/cma/backend/post_processors/post_processor_unittest.h
index 5b93bf7..6d9a84d3 100644
--- a/chromecast/media/cma/backend/post_processors/post_processor_unittest.h
+++ b/chromecast/media/cma/backend/post_processors/post_processor_unittest.h
@@ -38,6 +38,8 @@
 const int kBufSizeFrames = 256;
 const int kNumChannels = 2;
 
+AudioPostProcessor2::Config MakeProcessorConfig(int sample_rate_hz);
+
 void TestDelay(AudioPostProcessor2* pp,
                int sample_rate,
                int num_input_channels = 2);
diff --git a/chromeos/services/ime/ime_service_unittest.cc b/chromeos/services/ime/ime_service_unittest.cc
index ff8024ba..ddf51c8 100644
--- a/chromeos/services/ime/ime_service_unittest.cc
+++ b/chromeos/services/ime/ime_service_unittest.cc
@@ -36,6 +36,20 @@
   *res_out = response;
 }
 
+void TestProcessKeypressForRulebasedCallback(
+    mojom::KeypressResponse* res_out,
+    mojom::KeypressResponsePtr response) {
+  res_out->result = response->result;
+  res_out->operations = std::vector<mojom::OperationPtr>(0);
+  for (int i = 0; i < (int)response->operations.size(); i++) {
+    res_out->operations.push_back(std::move(response->operations[i]));
+  }
+}
+void TestGetRulebasedKeypressCountForTestingCallback(int32_t* res_out,
+                                                     int32_t response) {
+  *res_out = response;
+}
+
 class TestClientChannel : mojom::InputChannel {
  public:
   TestClientChannel() : receiver_(this) {}
@@ -49,6 +63,12 @@
   MOCK_METHOD2(ProcessMessage,
                void(const std::vector<uint8_t>& message,
                     ProcessMessageCallback));
+  MOCK_METHOD2(ProcessKeypressForRulebased,
+               void(const mojom::KeypressInfoPtr message,
+                    ProcessKeypressForRulebasedCallback));
+  MOCK_METHOD0(ResetForRulebased, void());
+  MOCK_METHOD1(GetRulebasedKeypressCountForTesting,
+               void(GetRulebasedKeypressCountForTestingCallback));
 
  private:
   mojo::Receiver<mojom::InputChannel> receiver_;
@@ -275,5 +295,197 @@
   EXPECT_EQ(expected_response, response);
 }
 
+TEST_F(ImeServiceTest, MultipleClientsRulebased) {
+  bool success = false;
+  TestClientChannel test_channel_1;
+  TestClientChannel test_channel_2;
+  mojo::Remote<mojom::InputChannel> remote_engine_1;
+  mojo::Remote<mojom::InputChannel> remote_engine_2;
+
+  remote_manager_->ConnectToImeEngine(
+      "m17n:ar", remote_engine_1.BindNewPipeAndPassReceiver(),
+      test_channel_1.CreatePendingRemote(), extra,
+      base::BindOnce(&ConnectCallback, &success));
+  remote_manager_.FlushForTesting();
+
+  remote_manager_->ConnectToImeEngine(
+      "m17n:ar", remote_engine_2.BindNewPipeAndPassReceiver(),
+      test_channel_2.CreatePendingRemote(), extra,
+      base::BindOnce(&ConnectCallback, &success));
+  remote_manager_.FlushForTesting();
+
+  mojom::KeypressResponse response;
+  mojom::KeypressInfoPtr keypress_info = mojom::KeypressInfo::New(
+      "keydown", "KeyA", true, false, false, false, false);
+  remote_engine_1->ProcessKeypressForRulebased(
+      mojom::KeypressInfo::New("keydown", "KeyA", true, false, false, false,
+                               false),
+      base::BindOnce(&TestProcessKeypressForRulebasedCallback, &response));
+  remote_engine_1.FlushForTesting();
+
+  remote_engine_2->ProcessKeypressForRulebased(
+      mojom::KeypressInfo::New("keydown", "KeyA", true, false, false, false,
+                               false),
+      base::BindOnce(&TestProcessKeypressForRulebasedCallback, &response));
+  remote_engine_2.FlushForTesting();
+
+  int32_t count;
+  remote_engine_1->GetRulebasedKeypressCountForTesting(
+      base::BindOnce(&TestGetRulebasedKeypressCountForTestingCallback, &count));
+  remote_engine_1.FlushForTesting();
+  EXPECT_EQ(1, count);
+
+  remote_engine_2->GetRulebasedKeypressCountForTesting(
+      base::BindOnce(&TestGetRulebasedKeypressCountForTestingCallback, &count));
+  remote_engine_2.FlushForTesting();
+  EXPECT_EQ(1, count);
+}
+
+// Tests that the rule-based Arabic keyboard can work correctly.
+TEST_F(ImeServiceTest, RuleBasedArabicKeypress) {
+  bool success = false;
+  TestClientChannel test_channel;
+  mojom::InputChannelPtr to_engine_ptr;
+
+  remote_manager_->ConnectToImeEngine(
+      "m17n:ar", mojo::MakeRequest(&to_engine_ptr),
+      test_channel.CreatePendingRemote(), extra,
+      base::BindOnce(&ConnectCallback, &success));
+  remote_manager_.FlushForTesting();
+  EXPECT_TRUE(success);
+
+  // Test Shift+KeyA.
+  mojom::KeypressResponse response;
+  to_engine_ptr->ProcessKeypressForRulebased(
+      mojom::KeypressInfo::New("keydown", "KeyA", true, false, false, false,
+                               false),
+      base::BindOnce(&TestProcessKeypressForRulebasedCallback, &response));
+  to_engine_ptr.FlushForTesting();
+
+  EXPECT_EQ(response.result, true);
+  std::vector<mojom::OperationPtr> expected_operations;
+  expected_operations.push_back(
+      {mojom::Operation::New(mojom::OperationMethod::COMMIT_TEXT, "\u0650")});
+  EXPECT_EQ(response.operations.size(), expected_operations.size());
+  EXPECT_EQ(response.operations, expected_operations);
+
+  // Test KeyB
+  to_engine_ptr->ProcessKeypressForRulebased(
+      mojom::KeypressInfo::New("keydown", "KeyB", false, false, false, false,
+                               false),
+      base::BindOnce(&TestProcessKeypressForRulebasedCallback, &response));
+  to_engine_ptr.FlushForTesting();
+  EXPECT_EQ(response.result, true);
+  expected_operations = std::vector<mojom::OperationPtr>(0);
+  expected_operations.push_back({mojom::Operation::New(
+      mojom::OperationMethod::COMMIT_TEXT, "\u0644\u0627")});
+  EXPECT_EQ(response.operations.size(), expected_operations.size());
+  EXPECT_EQ(response.operations, expected_operations);
+
+  // Test unhandled key.
+  to_engine_ptr->ProcessKeypressForRulebased(
+      mojom::KeypressInfo::New("keydown", "Enter", false, false, false, false,
+                               false),
+      base::BindOnce(&TestProcessKeypressForRulebasedCallback, &response));
+  to_engine_ptr.FlushForTesting();
+  EXPECT_EQ(response.result, false);
+
+  // Test keyup.
+  to_engine_ptr->ProcessKeypressForRulebased(
+      mojom::KeypressInfo::New("keyup", "Enter", false, false, false, false,
+                               false),
+      base::BindOnce(&TestProcessKeypressForRulebasedCallback, &response));
+  to_engine_ptr.FlushForTesting();
+  EXPECT_EQ(response.result, false);
+
+  // TODO(keithlee) Test reset function
+  to_engine_ptr->ResetForRulebased();
+
+  // Test invalid request.
+  to_engine_ptr->ProcessKeypressForRulebased(
+      mojom::KeypressInfo::New("keydown", "", false, false, false, false,
+                               false),
+      base::BindOnce(&TestProcessKeypressForRulebasedCallback, &response));
+  to_engine_ptr.FlushForTesting();
+  EXPECT_EQ(response.result, false);
+}
+
+// Tests that the rule-based DevaPhone keyboard can work correctly.
+TEST_F(ImeServiceTest, RuleBasedDevaPhoneKeypress) {
+  bool success = false;
+  TestClientChannel test_channel;
+  mojom::InputChannelPtr to_engine_ptr;
+
+  remote_manager_->ConnectToImeEngine(
+      "m17n:deva_phone", mojo::MakeRequest(&to_engine_ptr),
+      test_channel.CreatePendingRemote(), extra,
+      base::BindOnce(&ConnectCallback, &success));
+  remote_manager_.FlushForTesting();
+  EXPECT_TRUE(success);
+
+  mojom::KeypressResponse response;
+  std::vector<mojom::OperationPtr> expected_operations;
+
+  // Test KeyN.
+  to_engine_ptr->ProcessKeypressForRulebased(
+      mojom::KeypressInfo::New("keydown", "KeyN", false, false, false, false,
+                               false),
+      base::BindOnce(&TestProcessKeypressForRulebasedCallback, &response));
+  to_engine_ptr.FlushForTesting();
+
+  EXPECT_EQ(response.result, true);
+  expected_operations = std::vector<mojom::OperationPtr>(0);
+  expected_operations.push_back({mojom::Operation::New(
+      mojom::OperationMethod::SET_COMPOSITION, "\u0928")});
+  EXPECT_EQ(response.operations.size(), expected_operations.size());
+  EXPECT_EQ(response.operations, expected_operations);
+
+  // Backspace.
+  to_engine_ptr->ProcessKeypressForRulebased(
+      mojom::KeypressInfo::New("keydown", "Backspace", false, false, false,
+                               false, false),
+      base::BindOnce(&TestProcessKeypressForRulebasedCallback, &response));
+  to_engine_ptr.FlushForTesting();
+
+  EXPECT_EQ(response.result, true);
+  expected_operations = std::vector<mojom::OperationPtr>(0);
+  expected_operations.push_back(
+      {mojom::Operation::New(mojom::OperationMethod::SET_COMPOSITION, "")});
+  EXPECT_EQ(response.operations.size(), expected_operations.size());
+  EXPECT_EQ(response.operations, expected_operations);
+
+  // KeyN + KeyC.
+  to_engine_ptr->ProcessKeypressForRulebased(
+      mojom::KeypressInfo::New("keydown", "KeyN", false, false, false, false,
+                               false),
+      base::BindOnce(&TestProcessKeypressForRulebasedCallback, &response));
+  to_engine_ptr->ProcessKeypressForRulebased(
+      mojom::KeypressInfo::New("keydown", "KeyC", false, false, false, false,
+                               false),
+      base::BindOnce(&TestProcessKeypressForRulebasedCallback, &response));
+  to_engine_ptr.FlushForTesting();
+
+  EXPECT_EQ(response.result, true);
+  expected_operations = std::vector<mojom::OperationPtr>(0);
+  expected_operations.push_back({mojom::Operation::New(
+      mojom::OperationMethod::SET_COMPOSITION, "\u091e\u094d\u091a")});
+  EXPECT_EQ(response.operations.size(), expected_operations.size());
+  EXPECT_EQ(response.operations, expected_operations);
+
+  // Space.
+  to_engine_ptr->ProcessKeypressForRulebased(
+      mojom::KeypressInfo::New("keydown", "Space", false, false, false, false,
+                               false),
+      base::BindOnce(&TestProcessKeypressForRulebasedCallback, &response));
+  to_engine_ptr.FlushForTesting();
+
+  EXPECT_EQ(response.result, true);
+  expected_operations = std::vector<mojom::OperationPtr>(0);
+  expected_operations.push_back({mojom::Operation::New(
+      mojom::OperationMethod::COMMIT_TEXT, "\u091e\u094d\u091a ")});
+  EXPECT_EQ(response.operations.size(), expected_operations.size());
+  EXPECT_EQ(response.operations, expected_operations);
+}
+
 }  // namespace ime
 }  // namespace chromeos
diff --git a/chromeos/services/ime/input_engine.cc b/chromeos/services/ime/input_engine.cc
index f96fa81..1d999ea 100644
--- a/chromeos/services/ime/input_engine.cc
+++ b/chromeos/services/ime/input_engine.cc
@@ -24,6 +24,43 @@
              : std::string();
 }
 
+uint8_t GenerateModifierValueForRulebased(bool shift, bool altgr, bool caps) {
+  uint8_t modifiers = 0;
+  if (shift)
+    modifiers |= rulebased::MODIFIER_SHIFT;
+  if (altgr)
+    modifiers |= rulebased::MODIFIER_ALTGR;
+  if (caps)
+    modifiers |= rulebased::MODIFIER_CAPSLOCK;
+  return modifiers;
+}
+
+mojom::KeypressResponsePtr GenerateKeypressResponseForRulebased(
+    rulebased::ProcessKeyResult& process_key_result) {
+  mojom::KeypressResponsePtr keypress_response = mojom::KeypressResponse::New();
+  keypress_response->result = process_key_result.key_handled;
+  if (!process_key_result.commit_text.empty()) {
+    std::string commit_text;
+    base::EscapeJSONString(process_key_result.commit_text, false, &commit_text);
+    keypress_response->operations.push_back(mojom::Operation::New(
+        mojom::OperationMethod::COMMIT_TEXT, commit_text));
+  }
+  // Need to add the setComposition operation to the result when the key is
+  // handled and commit_text and composition_text are both empty.
+  // That is the case of using Backspace to delete the last character in
+  // composition.
+  if (!process_key_result.composition_text.empty() ||
+      (process_key_result.key_handled &&
+       process_key_result.commit_text.empty())) {
+    std::string composition_text;
+    base::EscapeJSONString(process_key_result.composition_text, false,
+                           &composition_text);
+    keypress_response->operations.push_back(mojom::Operation::New(
+        mojom::OperationMethod::SET_COMPOSITION, composition_text));
+  }
+  return keypress_response;
+}
+
 }  // namespace
 
 InputEngineContext::InputEngineContext(const std::string& ime) : ime_spec(ime) {
@@ -74,7 +111,6 @@
 
 std::string InputEngine::Process(const std::string& message,
                                  const InputEngineContext* context) {
-  std::string ime_spec = context->ime_spec;
   auto& engine = context->engine;
   if (!engine)
     return std::string();
@@ -185,5 +221,45 @@
   return response_str;
 }
 
+void InputEngine::ProcessKeypressForRulebased(
+    mojom::KeypressInfoPtr keypress_info,
+    ProcessKeypressForRulebasedCallback callback) {
+  auto& context = channel_receivers_.current_context();
+  auto& engine = context.get()->engine;
+
+  if (!engine || keypress_info->type.empty() ||
+      keypress_info->type != "keydown") {
+    std::move(callback).Run(mojom::KeypressResponse::New(
+        false, std::vector<mojom::OperationPtr>(0)));
+    return;
+  }
+
+  rulebased::ProcessKeyResult process_key_result = engine->ProcessKey(
+      keypress_info->code,
+      GenerateModifierValueForRulebased(
+          keypress_info->shift, keypress_info->altgr, keypress_info->caps));
+  mojom::KeypressResponsePtr keypress_response =
+      GenerateKeypressResponseForRulebased(process_key_result);
+
+  std::move(callback).Run(std::move(keypress_response));
+}
+
+void InputEngine::ResetForRulebased() {
+  auto& context = channel_receivers_.current_context();
+  auto& engine = context.get()->engine;
+  // TODO(https://crbug.com/1633694) Handle the case when the engine is not
+  // defined
+  if (engine) {
+    engine->Reset();
+  }
+}
+
+void InputEngine::GetRulebasedKeypressCountForTesting(
+    GetRulebasedKeypressCountForTestingCallback callback) {
+  auto& context = channel_receivers_.current_context();
+  auto& engine = context.get()->engine;
+  std::move(callback).Run(engine ? engine->process_key_count() : -1);
+}
+
 }  // namespace ime
 }  // namespace chromeos
diff --git a/chromeos/services/ime/input_engine.h b/chromeos/services/ime/input_engine.h
index c6e43f6..55422ab 100644
--- a/chromeos/services/ime/input_engine.h
+++ b/chromeos/services/ime/input_engine.h
@@ -50,6 +50,12 @@
                    ProcessTextCallback callback) override;
   void ProcessMessage(const std::vector<uint8_t>& message,
                       ProcessMessageCallback callback) override;
+  void ProcessKeypressForRulebased(
+      mojom::KeypressInfoPtr keypress_info,
+      ProcessKeypressForRulebasedCallback callback) override;
+  void ResetForRulebased() override;
+  void GetRulebasedKeypressCountForTesting(
+      GetRulebasedKeypressCountForTestingCallback callback) override;
 
   // TODO(https://crbug.com/837156): Implement a state for the interface.
 
diff --git a/chromeos/services/ime/public/mojom/input_engine.mojom b/chromeos/services/ime/public/mojom/input_engine.mojom
index 4af3f89..ae64b42e 100644
--- a/chromeos/services/ime/public/mojom/input_engine.mojom
+++ b/chromeos/services/ime/public/mojom/input_engine.mojom
@@ -4,6 +4,51 @@
 
 module chromeos.ime.mojom;
 
+
+// Method of an operation to apply to a text field
+enum OperationMethod {
+  COMMIT_TEXT = 0,
+  SET_COMPOSITION = 1,
+};
+
+// Operation to apply to a text field, in response to a Keypress
+struct Operation {
+  // The operation we wish to apply to the text field
+  OperationMethod method;
+
+  // Additional arguments of the method to apply to the text field
+  string arguments;
+};
+
+// KeypressResponse represents the Rulebased engine response to a keypress
+struct KeypressResponse {
+  // result indicates if the function call was successful
+  // There must be a valid engine and the keypress must be valid for
+  // this to be the case
+  bool result;
+
+  // An array of operations to apply to the text field in respoonse to
+  // the Keypress
+  array<Operation> operations;
+};
+
+// Information about a specific keypress
+struct KeypressInfo {
+
+  // Keypress Type (Eg; "keydown", "keyup", etc)
+  string type;
+
+  // Keypress key code (eg; "KeyA", "KeyB", "Enter", etc )
+  string code;
+
+  // Booleans to indicate if an option key is active / pressed down
+  bool shift;
+  bool altgr;
+  bool caps;
+  bool ctrl;
+  bool alt;
+};
+
 // Manages access to a set of IME engines.
 interface InputEngineManager {
   // Sets up the connection by binding the |to_engine_request| to the input
@@ -32,4 +77,16 @@
   // Returns a serialized protobuf result after processing a serialized
   // protobuf message.
   ProcessMessage(array<uint8> message) => (array<uint8> result);
+
+  // Process a KeypressInfo mojo object and return a KeypressResponse object
+  // with a list of operations to be handled by the caller's callback
+  // (for rulebased logic)
+  ProcessKeypressForRulebased(KeypressInfo message)
+                              => (KeypressResponse result);
+
+  // Resets the engine for rulebased logic
+  ResetForRulebased();
+
+  // Gets the keypress count for rulebased logic
+  GetRulebasedKeypressCountForTesting() => (int32 count);
 };
diff --git a/components/exo/keyboard.cc b/components/exo/keyboard.cc
index e19a7d40f..35528cb 100644
--- a/components/exo/keyboard.cc
+++ b/components/exo/keyboard.cc
@@ -120,7 +120,7 @@
          keyboard::GetTouchKeyboardEnabled() ||
          (keyboard::KeyboardController::HasInstance() &&
           keyboard::KeyboardController::Get()->IsEnableFlagSet(
-              keyboard::mojom::KeyboardEnableFlag::kCommandLineEnabled));
+              keyboard::KeyboardEnableFlag::kCommandLineEnabled));
 }
 
 bool IsReservedAccelerator(const ui::KeyEvent* event) {
diff --git a/components/omnibox/browser/location_bar_model_impl.cc b/components/omnibox/browser/location_bar_model_impl.cc
index f4dd617..0e5355f 100644
--- a/components/omnibox/browser/location_bar_model_impl.cc
+++ b/components/omnibox/browser/location_bar_model_impl.cc
@@ -210,14 +210,6 @@
   // Note that displayed text (the first output) will be implicitly used as the
   // accessibility text unless no display text has been specified.
 
-  // Security UI study (https://crbug.com/803501): Change EV/Secure text.
-  const std::string securityUIStudyParam =
-      base::FeatureList::IsEnabled(omnibox::kSimplifyHttpsIndicator)
-          ? base::GetFieldTrialParamValueByFeature(
-                omnibox::kSimplifyHttpsIndicator,
-                OmniboxFieldTrial::kSimplifyHttpsIndicatorParameterName)
-          : std::string();
-
   if (IsOfflinePage())
     return SecureChipText(l10n_util::GetStringUTF16(IDS_OFFLINE_VERBOSE_STATE));
 
@@ -226,14 +218,10 @@
       return SecureChipText(
           l10n_util::GetStringUTF16(IDS_NOT_SECURE_VERBOSE_STATE));
     case security_state::EV_SECURE: {
-      if (securityUIStudyParam ==
-          OmniboxFieldTrial::kSimplifyHttpsIndicatorParameterEvToSecure)
-        return SecureChipText(
-            l10n_util::GetStringUTF16(IDS_SECURE_VERBOSE_STATE));
-      if (securityUIStudyParam ==
-          OmniboxFieldTrial::kSimplifyHttpsIndicatorParameterBothToLock)
+      if (base::FeatureList::IsEnabled(omnibox::kSimplifyHttpsIndicator)) {
         return SecureChipText(base::string16(), l10n_util::GetStringUTF16(
                                                     IDS_SECURE_VERBOSE_STATE));
+      }
 
       // Note: Cert is guaranteed non-NULL or the security level would be NONE.
       scoped_refptr<net::X509Certificate> cert = delegate_->GetCertificate();
@@ -249,12 +237,8 @@
           base::UTF8ToUTF16(cert->subject().country_name)));
     }
     case security_state::SECURE:
-      if (securityUIStudyParam !=
-          OmniboxFieldTrial::kSimplifyHttpsIndicatorParameterKeepSecureChip)
-        return SecureChipText(base::string16(), l10n_util::GetStringUTF16(
-                                                    IDS_SECURE_VERBOSE_STATE));
-      return SecureChipText(
-          l10n_util::GetStringUTF16(IDS_SECURE_VERBOSE_STATE));
+      return SecureChipText(base::string16(), l10n_util::GetStringUTF16(
+                                                  IDS_SECURE_VERBOSE_STATE));
     case security_state::DANGEROUS: {
       std::unique_ptr<security_state::VisibleSecurityState>
           visible_security_state = delegate_->GetVisibleSecurityState();
diff --git a/components/omnibox/browser/omnibox_field_trial.cc b/components/omnibox/browser/omnibox_field_trial.cc
index a2135d70..35d16aa3 100644
--- a/components/omnibox/browser/omnibox_field_trial.cc
+++ b/components/omnibox/browser/omnibox_field_trial.cc
@@ -802,17 +802,6 @@
     "UIMaxAutocompleteMatchesByProvider";
 const char OmniboxFieldTrial::kUIVerticalMarginParam[] = "UIVerticalMargin";
 
-const char OmniboxFieldTrial::kSimplifyHttpsIndicatorParameterName[] =
-    "treatment";
-const char OmniboxFieldTrial::kSimplifyHttpsIndicatorParameterEvToSecure[] =
-    "ev-to-secure";
-const char OmniboxFieldTrial::kSimplifyHttpsIndicatorParameterSecureToLock[] =
-    "secure-to-lock";
-const char OmniboxFieldTrial::kSimplifyHttpsIndicatorParameterBothToLock[] =
-    "both-to-lock";
-const char OmniboxFieldTrial::kSimplifyHttpsIndicatorParameterKeepSecureChip[] =
-    "keep-secure-chip";
-
 const char OmniboxFieldTrial::kOnFocusSuggestionsEndpointExperimentIdParam[] =
     "CustomEndpointExperimentID";
 const char OmniboxFieldTrial::kOnFocusSuggestionsEndpointURLParam[] =
diff --git a/components/omnibox/browser/omnibox_field_trial.h b/components/omnibox/browser/omnibox_field_trial.h
index 363093d..838b1951 100644
--- a/components/omnibox/browser/omnibox_field_trial.h
+++ b/components/omnibox/browser/omnibox_field_trial.h
@@ -510,13 +510,6 @@
 extern const char kUIMaxAutocompleteMatchesByProviderParam[];
 extern const char kUIVerticalMarginParam[];
 
-// Parameter name and values used by the Simplify HTTPS experiment.
-extern const char kSimplifyHttpsIndicatorParameterName[];
-extern const char kSimplifyHttpsIndicatorParameterEvToSecure[];
-extern const char kSimplifyHttpsIndicatorParameterSecureToLock[];
-extern const char kSimplifyHttpsIndicatorParameterBothToLock[];
-extern const char kSimplifyHttpsIndicatorParameterKeepSecureChip[];
-
 // Parameter names used by On Focus Suggestions Custom Endpoint.
 extern const char kOnFocusSuggestionsEndpointExperimentIdParam[];
 extern const char kOnFocusSuggestionsEndpointURLParam[];
diff --git a/components/omnibox/common/omnibox_features.cc b/components/omnibox/common/omnibox_features.cc
index a3777fb..35afa1b 100644
--- a/components/omnibox/common/omnibox_features.cc
+++ b/components/omnibox/common/omnibox_features.cc
@@ -56,17 +56,12 @@
 const base::Feature kOneClickUnelide{"OmniboxOneClickUnelide",
                                      base::FEATURE_DISABLED_BY_DEFAULT};
 
-// This feature simplifies the security indiciator UI for https:// pages. The
-// exact UI treatment is dependent on the parameter 'treatment' which can have
-// the following value:
-// - 'ev-to-secure': Show the "Secure" chip for pages with an EV certificate.
-// - 'secure-to-lock': Show only the lock icon for non-EV https:// pages.
-// - 'both-to-lock': Show only the lock icon for all https:// pages.
-// - 'keep-secure-chip': Show the old "Secure" chip for non-EV https:// pages.
-// The default behavior is the same as 'secure-to-lock'.
+// This feature simplifies the security indiciator UI for https:// pages.
+// The default behavior is to show no verbose text for EV pages. When disabled,
+// the verbose EV indicator text will be displayed.
 // This feature is used for EV UI removal experiment (https://crbug.com/803501).
 const base::Feature kSimplifyHttpsIndicator{"SimplifyHttpsIndicator",
-                                            base::FEATURE_DISABLED_BY_DEFAULT};
+                                            base::FEATURE_ENABLED_BY_DEFAULT};
 
 // This feature is used to have final suggestions within the Omnibox grouped
 // by major type. i.e. search types are first, followed by all others,
diff --git a/components/safe_browsing/features.cc b/components/safe_browsing/features.cc
index c0e9e797..8f978e04 100644
--- a/components/safe_browsing/features.cc
+++ b/components/safe_browsing/features.cc
@@ -39,6 +39,9 @@
 const base::Feature kCommittedSBInterstitials{
     "SafeBrowsingCommittedInterstitials", base::FEATURE_DISABLED_BY_DEFAULT};
 
+const base::Feature kForceUseAPDownloadProtection{
+    "ForceUseAPDownloadProtection", base::FEATURE_DISABLED_BY_DEFAULT};
+
 const base::Feature kPasswordProtectionForSignedInUsers{
     "SafeBrowsingPasswordProtectionForSignedInUsers",
     base::FEATURE_DISABLED_BY_DEFAULT};
@@ -53,38 +56,35 @@
     "SafeBrowsingTriggerThrottlerDailyQuota",
     base::FEATURE_DISABLED_BY_DEFAULT};
 
-const base::Feature kUseLocalBlacklistsV2{"SafeBrowsingUseLocalBlacklistsV2",
-                                          base::FEATURE_DISABLED_BY_DEFAULT};
-
 const base::Feature kUseAPDownloadProtection{"UseAPDownloadProtection",
                                              base::FEATURE_DISABLED_BY_DEFAULT};
 
-const base::Feature kForceUseAPDownloadProtection{
-    "ForceUseAPDownloadProtection", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kUseLocalBlacklistsV2{"SafeBrowsingUseLocalBlacklistsV2",
+                                          base::FEATURE_DISABLED_BY_DEFAULT};
 
 constexpr base::FeatureParam<bool> kShouldFillOldPhishGuardProto{
     &kPasswordProtectionForSignedInUsers, "DeprecateOldProto", false};
 
 namespace {
-// List of experimental features. Boolean value for each list member should be
-// set to true if the experiment is currently running at a probability other
-// than 1 or 0, or to false otherwise.
+// List of Safe Browsing features. Boolean value for each list member should be
+// set to true if the experiment state should be listed on
+// chrome://safe-browsing.
 constexpr struct {
   const base::Feature* feature;
-  // True if the feature is running at a probability other than 1 or 0.
-  bool probabilistically_enabled;
+  // True if the feature's state should be listed on chrome://safe-browsing.
+  bool show_state;
 } kExperimentalFeatures[]{
     {&kAdSamplerTriggerFeature, false},
     {&kCaptureSafetyNetId, true},
     {&kCheckByURLLoaderThrottle, true},
     {&kCommittedSBInterstitials, true},
+    {&kForceUseAPDownloadProtection, false},
     {&kPasswordProtectionForSignedInUsers, true},
     {&kSuspiciousSiteTriggerQuotaFeature, true},
     {&kThreatDomDetailsTagAndAttributeFeature, false},
     {&kTriggerThrottlerDailyQuotaFeature, false},
     {&kUseLocalBlacklistsV2, true},
-    {&kUseAPDownloadProtection, false},
-    {&kForceUseAPDownloadProtection, false},
+    {&kUseAPDownloadProtection, true},
 };
 
 // Adds the name and the enabled/disabled status of a given feature.
@@ -104,7 +104,7 @@
 base::ListValue GetFeatureStatusList() {
   base::ListValue param_list;
   for (const auto& feature_status : kExperimentalFeatures) {
-    if (feature_status.probabilistically_enabled)
+    if (feature_status.show_state)
       AddFeatureAndAvailability(feature_status.feature, &param_list);
   }
   return param_list;
diff --git a/components/safe_browsing/features.h b/components/safe_browsing/features.h
index e019741..1508523 100644
--- a/components/safe_browsing/features.h
+++ b/components/safe_browsing/features.h
@@ -31,6 +31,10 @@
 // navigations instead of overlays.
 extern const base::Feature kCommittedSBInterstitials;
 
+// Controls whether the user has forcible enabled AP download protection. See
+// also |kUseAPDownloadProtection|.
+extern const base::Feature kForceUseAPDownloadProtection;
+
 // Enable GAIA password protection for signed-in users.
 extern const base::Feature kPasswordProtectionForSignedInUsers;
 
@@ -55,14 +59,12 @@
 // trials simultaneously.
 extern const base::Feature kTriggerThrottlerDailyQuotaFeature;
 
-// Controls whether Chrome on Android uses locally cached blacklists.
-extern const base::Feature kUseLocalBlacklistsV2;
-
-// Controls whether we use AP download protection.
+// Controls whether we use AP download protection. See also
+// |kForceUseAPDownloadProtection|.
 extern const base::Feature kUseAPDownloadProtection;
 
-// Controls whether the user has forcible enabled AP download protection.
-extern const base::Feature kForceUseAPDownloadProtection;
+// Controls whether Chrome on Android uses locally cached blacklists.
+extern const base::Feature kUseLocalBlacklistsV2;
 
 base::ListValue GetFeatureStatusList();
 
diff --git a/components/tracing/proto/BUILD.gn b/components/tracing/proto/BUILD.gn
deleted file mode 100644
index 315cd813..0000000
--- a/components/tracing/proto/BUILD.gn
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright 2016 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.
-
-import("//third_party/protobuf/proto_library.gni")
-
-tracing_proto_sources = [
-  "event.proto",
-  "events_chunk.proto",
-]
-
-# Official protobuf C++ stubs to test conformance.
-proto_library("golden_protos_for_tests") {
-  visibility = [ "//components/tracing/*" ]
-  testonly = true
-
-  proto_in_dir = "."
-  proto_out_dir = "components/tracing/test/golden_protos"
-  sources = tracing_proto_sources
-
-  generate_python = false
-}
diff --git a/components/tracing/proto/event.proto b/components/tracing/proto/event.proto
deleted file mode 100644
index 24bb7ad..0000000
--- a/components/tracing/proto/event.proto
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2016 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.
-
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-
-package tracing.proto;
-
-// Note on field numbers: fields in the range [1, 15] can be encoded using a
-// single byte preamble. Hence they should be used only for the most commonly
-// used fields (to save trace size). Use the range 16+ for fields that are not
-// expected to be used frequently.
-message Event {
-  // Using ASCII codes as enum values, according to the legacy phase arguments
-  // ("ph") of the Trace Event Format doc (https://goo.gl/mSXylN).
-  enum EventType {
-    METADATA = 77;  // = 'M'.
-    COMPLETE = 88;  // = 'X'.
-  };
-
-  optional EventType type = 1;
-
-  oneof name {
-    int64 name_id = 2;
-    string name_str = 16;
-  }
-
-  optional int64 category_id = 4;
-
-  optional uint64 timestamp = 5;
-  optional uint64 thread_timestamp = 6;
-
-  // TODO(primiano,kraynov): Add args and further fields in next CLs.
-}
diff --git a/components/tracing/proto/events_chunk.proto b/components/tracing/proto/events_chunk.proto
deleted file mode 100644
index aedec76..0000000
--- a/components/tracing/proto/events_chunk.proto
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2016 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.
-
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-
-package tracing.proto;
-
-// An EventsChunk is a fixed portion of the trace ring buffer which is written
-// exclusively by one writer (almost always 1 writer == 1 thread). It contains
-// a variable number of variable-sized events. Events can be fragmented across
-// several chunks.
-
-message EventsChunk {
-  // Chunks produced by the same trace writer have the same writer_id. This
-  // allows to identify the next chunk for a writer (thread) in the ring buffer.
-  optional uint32 writer_id = 1;
-
-  // A monotonic counter within the writer, to establish sequencing of chunks.
-  optional uint32 seq_id = 2;
-
-  // Each event is a byte sequence that encapsulates the bytes for a single
-  // Event (see event.proto) or an incomplete fragment.
-  // Why this isn't just a "repeated Events" field? An Event can spawn across
-  // several chunks. In this case the reader has to first glue the byte
-  // sequences together and then process the event.
-  repeated bytes events = 3;
-
-  // The first entry of |events| is a fragment which continues from the previous
-  // chunk.
-  optional bool first_event_continues_from_prev_chunk = 4;
-
-  // The last entry of |events| is a fragment and contiues into the next chunk.
-  optional bool last_event_continues_on_next_chunk = 5;
-}
diff --git a/components/tracing/test/example_proto/library.proto b/components/tracing/test/example_proto/library.proto
deleted file mode 100644
index a0839190..0000000
--- a/components/tracing/test/example_proto/library.proto
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2016 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.
-
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-
-package foo.bar;
-
-import public "library_internals/galaxies.proto";
-
-message TransgalacticMessage {
-  optional Galaxy origin_galaxy = 1;
-  optional string origin_planet = 2;
-  optional Galaxy destination_galaxy = 3;
-  optional string destination_planet = 4;
-  optional bytes proto_message = 5;
-}
diff --git a/components/tracing/test/example_proto/library_internals/galaxies.proto b/components/tracing/test/example_proto/library_internals/galaxies.proto
deleted file mode 100644
index 0e203e7..0000000
--- a/components/tracing/test/example_proto/library_internals/galaxies.proto
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2016 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.
-
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-
-package foo.bar;
-
-import public "upper_import.proto";
-
-enum Galaxy {
-  MILKY_WAY = 1;
-  ANDROMEDA = 2;
-  SUNFLOWER = 3;
-}
diff --git a/components/tracing/test/example_proto/test_messages.proto b/components/tracing/test/example_proto/test_messages.proto
deleted file mode 100644
index 8903b79..0000000
--- a/components/tracing/test/example_proto/test_messages.proto
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2016 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.
-
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-
-package foo.bar;
-
-import "library.proto";
-
-// This file contains comprehensive set of supported message structures and
-// data types. Unit tests depends on the plugin-processed version of this file.
-
-// Tests importing message definition from another proto file.
-message TransgalacticParcel {
-  optional TransgalacticMessage message = 1;
-  optional string tracking_code = 2;
-}
-
-enum SmallEnum {
-  TO_BE = 1;
-  NOT_TO_BE = 0;
-}
-
-enum SignedEnum {
-  POSITIVE = 1;
-  NEUTRAL = 0;
-  NEGATIVE = -1;
-}
-
-enum BigEnum {
-  BEGIN = 10;
-  END = 100500;
-}
-
-message EveryField {
-  optional int32 field_int32 = 1;
-  optional int64 field_int64 = 2;
-  optional uint32 field_uint32 = 3;
-  optional uint64 field_uint64 = 4;
-  optional sint32 field_sint32 = 5;
-  optional sint64 field_sint64 = 6;
-  optional fixed32 field_fixed32 = 7;
-  optional fixed64 field_fixed64 = 8;
-  optional sfixed32 field_sfixed32 = 9;
-  optional sfixed64 field_sfixed64 = 10;
-  optional float field_float = 11;
-  optional double field_double = 12;
-  optional bool field_bool = 13;
-
-  optional SmallEnum small_enum = 51;
-  optional SignedEnum signed_enum = 52;
-  optional BigEnum big_enum = 53;
-
-  optional string field_string = 500;
-  optional bytes field_bytes = 505;
-
-  enum NestedEnum {
-    PING = 1;
-    PONG = 2;
-  }
-  optional NestedEnum nested_enum = 600;
-
-  repeated int32 repeated_int32 = 999;
-}
-
-message NestedA {
-  message NestedB {
-    message NestedC {
-      optional int32 value_c = 1;
-    }
-    optional NestedC value_b = 1;
-  }
-  repeated NestedB repeated_a = 2;
-  optional NestedB.NestedC super_nested = 3;
-}
-
-message CamelCaseFields {
-  // To check that any reasonable name converts to camel case correctly.
-  optional bool foo_bar_baz = 1;
-  optional bool barBaz = 2;
-  optional bool MooMoo = 3;
-  optional bool URLEncoder = 4;
-  optional bool XMap = 5;
-  optional bool UrLE_nco__der = 6;
-  optional bool __bigBang = 7;
-  optional bool U2 = 8;
-  optional bool bangBig__ = 9;
-}
diff --git a/components/tracing/test/example_proto/upper_import.proto b/components/tracing/test/example_proto/upper_import.proto
deleted file mode 100644
index c948d2e..0000000
--- a/components/tracing/test/example_proto/upper_import.proto
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2016 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.
-
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-
-package foo.bar;
-
-message TrickyPublicImport {
-}
diff --git a/components/tracing/test/fake_scattered_buffer.h b/components/tracing/test/fake_scattered_buffer.h
deleted file mode 100644
index a6dc5e4..0000000
--- a/components/tracing/test/fake_scattered_buffer.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2016 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 COMPONENTS_TRACING_TEST_FAKE_SCATTERED_BUFFER_H_
-#define COMPONENTS_TRACING_TEST_FAKE_SCATTERED_BUFFER_H_
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/macros.h"
-#include "components/tracing/core/scattered_stream_writer.h"
-#include "components/tracing/tracing_export.h"
-
-namespace tracing {
-namespace v2 {
-
-// A simple ScatteredStreamWriter::Delegate implementation which just allocates
-// chunks of a fixed size.
-class FakeScatteredBuffer : public ScatteredStreamWriter::Delegate {
- public:
-  explicit FakeScatteredBuffer(size_t chunk_size);
-  ~FakeScatteredBuffer() override;
-
-  // ScatteredStreamWriter::Delegate implementation.
-  ContiguousMemoryRange GetNewBuffer() override;
-
-  std::string GetChunkAsString(int chunk_index);
-
-  void GetBytes(size_t start, size_t length, uint8_t* buf);
-  std::string GetBytesAsString(size_t start, size_t length);
-
-  const std::vector<std::unique_ptr<uint8_t[]>>& chunks() const {
-    return chunks_;
-  }
-
- private:
-  const size_t chunk_size_;
-  std::vector<std::unique_ptr<uint8_t[]>> chunks_;
-
-  DISALLOW_COPY_AND_ASSIGN(FakeScatteredBuffer);
-};
-
-}  // namespace v2
-}  // namespace tracing
-
-#endif  // COMPONENTS_TRACING_TEST_FAKE_SCATTERED_BUFFER_H_
diff --git a/content/browser/accessibility/accessibility_tree_formatter_uia_win.cc b/content/browser/accessibility/accessibility_tree_formatter_uia_win.cc
index 9ab186f..38bc1e54 100644
--- a/content/browser/accessibility/accessibility_tree_formatter_uia_win.cc
+++ b/content/browser/accessibility/accessibility_tree_formatter_uia_win.cc
@@ -841,10 +841,17 @@
       if (element_list != L"") {
         element_list += L", ";
       }
-      element_list += GetNodeName(element.Get());
+      auto name = GetNodeName(element.Get());
+      if (name.empty()) {
+        base::win::ScopedBstr role;
+        element->get_CurrentAriaRole(role.Receive());
+        name = L"{" + base::string16(role) + L"}";
+      }
+      element_list += name;
     }
   }
-  dict->SetString(UiaIdentifierToCondensedString(propertyId), element_list);
+  if (!element_list.empty())
+    dict->SetString(UiaIdentifierToCondensedString(propertyId), element_list);
 }
 
 base::string16 AccessibilityTreeFormatterUia::GetNodeName(
diff --git a/content/browser/accessibility/cross_platform_accessibility_browsertest.cc b/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
index f594967..35663718 100644
--- a/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
+++ b/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
@@ -162,6 +162,24 @@
   return false;
 }
 
+namespace {
+
+// Convenience method to find a node by its role value.
+BrowserAccessibility* FindNodeByRole(BrowserAccessibility* root,
+                                     ax::mojom::Role role) {
+  if (root->GetRole() == role)
+    return root;
+  for (uint32_t i = 0; i < root->InternalChildCount(); ++i) {
+    BrowserAccessibility* child = root->InternalGetChild(i);
+    DCHECK(child);
+    if (BrowserAccessibility* result = FindNodeByRole(child, role))
+      return result;
+  }
+  return nullptr;
+}
+
+}  // namespace
+
 IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
                        WebpageAccessibility) {
   // Create a data url and load it.
@@ -788,5 +806,146 @@
                                 ui::AXClippingBehavior::kUnclipped)
                 .ToString());
 }
+
+IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
+                       TestControlsIdsForDateTimePopup) {
+  // Create a data url and load it.
+  const char url_str[] =
+      R"HTML(data:text/html,<!DOCTYPE html>
+        <html>
+          <input type="datetime-local" aria-label="datetime"
+                 aria-controls="button1">
+          <button id="button1">button</button>
+        </html>)HTML";
+  GURL url(url_str);
+
+  // Load the document and wait for it
+  {
+    AccessibilityNotificationWaiter waiter(shell()->web_contents(),
+                                           ui::kAXModeComplete,
+                                           ax::mojom::Event::kLoadComplete);
+    NavigateToURL(shell(), url);
+    waiter.WaitForNotification();
+  }
+
+  BrowserAccessibilityManager* manager = GetManager();
+  ASSERT_NE(nullptr, manager);
+  BrowserAccessibility* root = manager->GetRoot();
+  ASSERT_NE(nullptr, root);
+
+  // Find the input control, and the popup-button
+  BrowserAccessibility* input_control =
+      FindNodeByRole(root, ax::mojom::Role::kDateTime);
+  ASSERT_NE(nullptr, input_control);
+  BrowserAccessibility* popup_control =
+      FindNodeByRole(input_control, ax::mojom::Role::kPopUpButton);
+  ASSERT_NE(nullptr, popup_control);
+  const BrowserAccessibility* sibling_button_control =
+      FindNodeByRole(root, ax::mojom::Role::kButton);
+  ASSERT_NE(nullptr, sibling_button_control);
+
+  // Get the list of ControlsIds; should initially just point to the sibling
+  // button control.
+  {
+    const auto& controls_ids = input_control->GetIntListAttribute(
+        ax::mojom::IntListAttribute::kControlsIds);
+    ASSERT_EQ(1u, controls_ids.size());
+    EXPECT_EQ(controls_ids[0], sibling_button_control->GetId());
+  }
+
+  // Expand the popup, and wait for it to appear
+  {
+    AccessibilityNotificationWaiter waiter(shell()->web_contents(),
+                                           ui::kAXModeComplete,
+                                           ax::mojom::Event::kClicked);
+
+    ui::AXActionData action_data;
+    action_data.action = ax::mojom::Action::kDoDefault;
+    popup_control->AccessibilityPerformAction(action_data);
+
+    waiter.WaitForNotification();
+  }
+
+  // Get the list of ControlsIds again; should now also include the popup
+  {
+    const auto& controls_ids = input_control->GetIntListAttribute(
+        ax::mojom::IntListAttribute::kControlsIds);
+    ASSERT_EQ(2u, controls_ids.size());
+    EXPECT_EQ(controls_ids[0], sibling_button_control->GetId());
+
+    const BrowserAccessibility* popup_area =
+        manager->GetFromID(controls_ids[1]);
+    ASSERT_NE(nullptr, popup_area);
+    EXPECT_EQ(ax::mojom::Role::kRootWebArea, popup_area->GetRole());
+  }
+}
+
+IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
+                       TestControlsIdsForColorPopup) {
+  // Create a data url and load it.
+  const char url_str[] =
+      R"HTML(data:text/html,<!DOCTYPE html>
+        <html>
+          <input type="color" aria-label="color" list="colorlist">
+          <datalist id="colorlist">
+            <option value="#ff0000">
+            <option value="#00ff00">
+            <option value="#0000ff">
+          </datalist>
+        </html>)HTML";
+  GURL url(url_str);
+
+  // Load the document and wait for it
+  {
+    AccessibilityNotificationWaiter waiter(shell()->web_contents(),
+                                           ui::kAXModeComplete,
+                                           ax::mojom::Event::kLoadComplete);
+    NavigateToURL(shell(), url);
+    waiter.WaitForNotification();
+  }
+
+  BrowserAccessibilityManager* manager = GetManager();
+  ASSERT_NE(nullptr, manager);
+  BrowserAccessibility* root = manager->GetRoot();
+  ASSERT_NE(nullptr, root);
+
+  // Find the input control
+  BrowserAccessibility* input_control =
+      FindNodeByRole(root, ax::mojom::Role::kColorWell);
+  ASSERT_NE(nullptr, input_control);
+
+  // Get the list of ControlsIds; should initially be empty.
+  {
+    const auto& controls_ids = input_control->GetIntListAttribute(
+        ax::mojom::IntListAttribute::kControlsIds);
+    ASSERT_EQ(0u, controls_ids.size());
+  }
+
+  // Expand the popup, and wait for it to appear
+  {
+    AccessibilityNotificationWaiter waiter(shell()->web_contents(),
+                                           ui::kAXModeComplete,
+                                           ax::mojom::Event::kClicked);
+
+    ui::AXActionData action_data;
+    action_data.action = ax::mojom::Action::kDoDefault;
+    input_control->AccessibilityPerformAction(action_data);
+
+    waiter.WaitForNotification();
+  }
+
+  // Get the list of ControlsIds again; should now include the popup
+  {
+    const auto& controls_ids = input_control->GetIntListAttribute(
+        ax::mojom::IntListAttribute::kControlsIds);
+    ASSERT_EQ(1u, controls_ids.size());
+
+    const BrowserAccessibility* popup_area =
+        manager->GetFromID(controls_ids[0]);
+    ASSERT_NE(nullptr, popup_area);
+    EXPECT_EQ(ax::mojom::Role::kRootWebArea, popup_area->GetRole());
+  }
+}
+
 #endif
 }  // namespace content
diff --git a/content/browser/media/android/browser_gpu_video_accelerator_factories.cc b/content/browser/media/android/browser_gpu_video_accelerator_factories.cc
index ab77ed9..95063f7 100644
--- a/content/browser/media/android/browser_gpu_video_accelerator_factories.cc
+++ b/content/browser/media/android/browser_gpu_video_accelerator_factories.cc
@@ -112,11 +112,6 @@
   return nullptr;
 }
 
-std::unique_ptr<media::VideoDecodeAccelerator>
-BrowserGpuVideoAcceleratorFactories::CreateVideoDecodeAccelerator() {
-  return nullptr;
-}
-
 std::unique_ptr<media::VideoEncodeAccelerator>
 BrowserGpuVideoAcceleratorFactories::CreateVideoEncodeAccelerator() {
   return nullptr;
@@ -196,17 +191,6 @@
   return nullptr;
 }
 
-media::VideoDecodeAccelerator::Capabilities
-BrowserGpuVideoAcceleratorFactories::GetVideoDecodeAcceleratorCapabilities() {
-  DCHECK(context_provider_);
-  auto* proxy = context_provider_->GetCommandBufferProxy();
-  DCHECK(proxy);
-  DCHECK(proxy->channel());
-
-  return media::GpuVideoAcceleratorUtil::ConvertGpuToMediaDecodeCapabilities(
-      proxy->channel()->gpu_info().video_decode_accelerator_capabilities);
-}
-
 media::VideoEncodeAccelerator::SupportedProfiles
 BrowserGpuVideoAcceleratorFactories::
     GetVideoEncodeAcceleratorSupportedProfiles() {
diff --git a/content/browser/media/android/browser_gpu_video_accelerator_factories.h b/content/browser/media/android/browser_gpu_video_accelerator_factories.h
index 65f4142..49f9b15e 100644
--- a/content/browser/media/android/browser_gpu_video_accelerator_factories.h
+++ b/content/browser/media/android/browser_gpu_video_accelerator_factories.h
@@ -31,8 +31,6 @@
       media::MediaLog* media_log,
       media::VideoDecoderImplementation implementation,
       const media::RequestOverlayInfoCB& request_overlay_info_cb) override;
-  std::unique_ptr<media::VideoDecodeAccelerator> CreateVideoDecodeAccelerator()
-      override;
   std::unique_ptr<media::VideoEncodeAccelerator> CreateVideoEncodeAccelerator()
       override;
   bool CreateTextures(int32_t count,
@@ -60,8 +58,6 @@
   gpu::GpuMemoryBufferManager* GpuMemoryBufferManager() override;
   std::unique_ptr<base::SharedMemory> CreateSharedMemory(size_t size) override;
   scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() override;
-  media::VideoDecodeAccelerator::Capabilities
-  GetVideoDecodeAcceleratorCapabilities() override;
   media::VideoEncodeAccelerator::SupportedProfiles
   GetVideoEncodeAcceleratorSupportedProfiles() override;
   scoped_refptr<ws::ContextProviderCommandBuffer> GetMediaContextProvider()
diff --git a/content/browser/media/media_internals.cc b/content/browser/media/media_internals.cc
index 3d25fc29..3e2b27a 100644
--- a/content/browser/media/media_internals.cc
+++ b/content/browser/media/media_internals.cc
@@ -38,7 +38,6 @@
 #include "media/audio/audio_features.h"
 #include "media/base/audio_parameters.h"
 #include "media/base/media_log_event.h"
-#include "media/filters/gpu_video_decoder.h"
 #include "media/webrtc/webrtc_switches.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "services/service_manager/sandbox/features.h"
diff --git a/content/browser/webauth/authenticator_common.cc b/content/browser/webauth/authenticator_common.cc
index a03ec6c8..58418f62 100644
--- a/content/browser/webauth/authenticator_common.cc
+++ b/content/browser/webauth/authenticator_common.cc
@@ -814,14 +814,14 @@
   // |attestation_requested_| for showing the attestation consent prompt later.
   auto attestation = mojo::ConvertTo<::device::AttestationConveyancePreference>(
       options->attestation);
-  if (attestation == ::device::AttestationConveyancePreference::ENTERPRISE &&
+  if (attestation == ::device::AttestationConveyancePreference::kEnterprise &&
       !request_delegate_->ShouldPermitIndividualAttestation(
           relying_party_id_)) {
-    attestation = ::device::AttestationConveyancePreference::DIRECT;
+    attestation = ::device::AttestationConveyancePreference::kDirect;
   }
   ctap_make_credential_request_->attestation_preference = attestation;
   attestation_requested_ =
-      attestation != ::device::AttestationConveyancePreference::NONE;
+      attestation != ::device::AttestationConveyancePreference::kNone;
 
   switch (options->protection_policy) {
     case blink::mojom::ProtectionPolicy::UNSPECIFIED:
@@ -1099,7 +1099,7 @@
         // the extension is not associated with any tab and therefore cannot
         // draw modal dialogs for the UI.
         //
-        // Note that for AttestationConveyancePreference::NONE, attestation
+        // Note that for AttestationConveyancePreference::kNone, attestation
         // erasure is still performed as usual.
         if (OriginIsCryptoTokenExtension(caller_origin_)) {
           InvokeCallbackAndCleanup(
diff --git a/content/browser/webauth/authenticator_type_converters.cc b/content/browser/webauth/authenticator_type_converters.cc
index 91233a4..ee8e5f9 100644
--- a/content/browser/webauth/authenticator_type_converters.cc
+++ b/content/browser/webauth/authenticator_type_converters.cc
@@ -228,16 +228,16 @@
     Convert(const AttestationConveyancePreference& input) {
   switch (input) {
     case AttestationConveyancePreference::NONE:
-      return ::device::AttestationConveyancePreference::NONE;
+      return ::device::AttestationConveyancePreference::kNone;
     case AttestationConveyancePreference::INDIRECT:
-      return ::device::AttestationConveyancePreference::INDIRECT;
+      return ::device::AttestationConveyancePreference::kIndirect;
     case AttestationConveyancePreference::DIRECT:
-      return ::device::AttestationConveyancePreference::DIRECT;
+      return ::device::AttestationConveyancePreference::kDirect;
     case AttestationConveyancePreference::ENTERPRISE:
-      return ::device::AttestationConveyancePreference::ENTERPRISE;
+      return ::device::AttestationConveyancePreference::kEnterprise;
   }
   NOTREACHED();
-  return ::device::AttestationConveyancePreference::NONE;
+  return ::device::AttestationConveyancePreference::kNone;
 }
 
 // static
diff --git a/content/browser/worker_host/worker_script_fetch_initiator.cc b/content/browser/worker_host/worker_script_fetch_initiator.cc
index ad61ea1..e4093c0 100644
--- a/content/browser/worker_host/worker_script_fetch_initiator.cc
+++ b/content/browser/worker_host/worker_script_fetch_initiator.cc
@@ -98,6 +98,20 @@
     resource_request->request_initiator = request_initiator;
     resource_request->resource_type = static_cast<int>(resource_type);
 
+    switch (resource_type) {
+      case ResourceType::kWorker:
+        resource_request->fetch_request_context_type =
+            static_cast<int>(blink::mojom::RequestContextType::WORKER);
+        break;
+      case ResourceType::kSharedWorker:
+        resource_request->fetch_request_context_type =
+            static_cast<int>(blink::mojom::RequestContextType::SHARED_WORKER);
+        break;
+      default:
+        NOTREACHED() << static_cast<int>(resource_type);
+        break;
+    }
+
     AddAdditionalRequestHeaders(resource_request.get(), browser_context);
   }
 
@@ -231,8 +245,22 @@
     if (base::FeatureList::IsEnabled(
             network::features::kFetchMetadataDestination) ||
         experimental_features_enabled) {
+      ResourceType resource_type =
+          static_cast<ResourceType>(resource_request->resource_type);
+      std::string destination;
+      switch (resource_type) {
+        case ResourceType::kWorker:
+          destination = "worker";
+          break;
+        case ResourceType::kSharedWorker:
+          destination = "sharedworker";
+          break;
+        default:
+          NOTREACHED() << resource_request->resource_type;
+          break;
+      }
       resource_request->headers.SetHeaderIfMissing("Sec-Fetch-Dest",
-                                                   "sharedworker");
+                                                   destination);
     }
 
     // Note that the `Sec-Fetch-User` header is always false (and therefore
diff --git a/content/public/browser/BUILD.gn b/content/public/browser/BUILD.gn
index 86c4431..12bdb7b 100644
--- a/content/public/browser/BUILD.gn
+++ b/content/public/browser/BUILD.gn
@@ -165,6 +165,8 @@
     "guest_host.h",
     "guest_mode.cc",
     "guest_mode.h",
+    "hid_chooser.h",
+    "hid_delegate.h",
     "histogram_fetcher.h",
     "indexed_db_context.h",
     "interstitial_page.h",
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc
index 53e6771..04faf010 100644
--- a/content/public/browser/content_browser_client.cc
+++ b/content/public/browser/content_browser_client.cc
@@ -837,6 +837,10 @@
 }
 #endif
 
+HidDelegate* ContentBrowserClient::GetHidDelegate() {
+  return nullptr;
+}
+
 bool ContentBrowserClient::ShowPaymentHandlerWindow(
     content::BrowserContext* browser_context,
     const GURL& url,
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
index 2b4c2c1..34b4fd3 100644
--- a/content/public/browser/content_browser_client.h
+++ b/content/public/browser/content_browser_client.h
@@ -166,6 +166,7 @@
 class ClientCertificateDelegate;
 class ControllerPresentationServiceDelegate;
 class DevToolsManagerDelegate;
+class HidDelegate;
 class LoginDelegate;
 class MediaObserver;
 class NavigationHandle;
@@ -1364,6 +1365,9 @@
   virtual SerialDelegate* GetSerialDelegate();
 #endif
 
+  // Allows the embedder to provide an implementation of the WebHID API.
+  virtual HidDelegate* GetHidDelegate();
+
   // Attempt to open the Payment Handler window inside its corresponding
   // PaymentRequest UI surface. Returns true if the ContentBrowserClient
   // implementation supports this operation (desktop Chrome) or false otherwise.
diff --git a/content/public/browser/hid_chooser.h b/content/public/browser/hid_chooser.h
new file mode 100644
index 0000000..24f8685
--- /dev/null
+++ b/content/public/browser/hid_chooser.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 CONTENT_PUBLIC_BROWSER_HID_CHOOSER_H_
+#define CONTENT_PUBLIC_BROWSER_HID_CHOOSER_H_
+
+#include "base/callback_forward.h"
+#include "base/macros.h"
+#include "content/common/content_export.h"
+#include "services/device/public/mojom/hid.mojom-forward.h"
+
+namespace content {
+
+// Token representing an open HID device chooser prompt. Destroying this
+// object should cancel the prompt.
+class CONTENT_EXPORT HidChooser {
+ public:
+  // Callback type used to report the user action. Passed |nullptr| if no device
+  // was selected.
+  using Callback = base::OnceCallback<void(device::mojom::HidDeviceInfoPtr)>;
+
+  HidChooser() = default;
+  virtual ~HidChooser() = default;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(HidChooser);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_PUBLIC_BROWSER_HID_CHOOSER_H_
diff --git a/content/public/browser/hid_delegate.h b/content/public/browser/hid_delegate.h
new file mode 100644
index 0000000..edcef92
--- /dev/null
+++ b/content/public/browser/hid_delegate.h
@@ -0,0 +1,50 @@
+// 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 CONTENT_PUBLIC_BROWSER_HID_DELEGATE_H_
+#define CONTENT_PUBLIC_BROWSER_HID_DELEGATE_H_
+
+#include <memory>
+#include <vector>
+
+#include "content/common/content_export.h"
+#include "content/public/browser/hid_chooser.h"
+#include "services/device/public/mojom/hid.mojom-forward.h"
+
+namespace content {
+
+class RenderFrameHost;
+
+class CONTENT_EXPORT HidDelegate {
+ public:
+  virtual ~HidDelegate() = default;
+
+  // Shows a chooser for the user to select a HID device. |callback| will be
+  // run when the prompt is closed. Deleting the returned object will cancel the
+  // prompt.
+  virtual std::unique_ptr<HidChooser> RunChooser(
+      RenderFrameHost* frame,
+      HidChooser::Callback callback) = 0;
+
+  // Returns whether |frame| has permission to request access to a device.
+  virtual bool CanRequestDevicePermission(RenderFrameHost* frame) = 0;
+
+  // Returns whether |frame| has permission to access |device|.
+  virtual bool HasDevicePermission(
+      RenderFrameHost* frame,
+      const device::mojom::HidDeviceInfo& device) = 0;
+
+  // Returns an open connection to the HidManager interface owned by the
+  // embedder and being used to serve requests from |frame|.
+  //
+  // Content and the embedder must use the same connection so that the embedder
+  // can process connect/disconnect events for permissions management purposes
+  // before they are delivered to content. Otherwise race conditions are
+  // possible.
+  virtual device::mojom::HidManager* GetHidManager(RenderFrameHost* frame) = 0;
+};
+
+}  // namespace content
+
+#endif  // CONTENT_PUBLIC_BROWSER_HID_DELEGATE_H_
diff --git a/content/renderer/accessibility/blink_ax_tree_source.cc b/content/renderer/accessibility/blink_ax_tree_source.cc
index 8f43940..6c4d356 100644
--- a/content/renderer/accessibility/blink_ax_tree_source.cc
+++ b/content/renderer/accessibility/blink_ax_tree_source.cc
@@ -544,6 +544,16 @@
   AXContentNodeDataSparseAttributeAdapter sparse_attribute_adapter(dst);
   src.GetSparseAXAttributes(sparse_attribute_adapter);
 
+  WebAXObject chooser_popup = src.ChooserPopup();
+  if (!chooser_popup.IsNull()) {
+    int32_t chooser_popup_id = chooser_popup.AxID();
+    auto controls_ids =
+        dst->GetIntListAttribute(ax::mojom::IntListAttribute::kControlsIds);
+    controls_ids.push_back(chooser_popup_id);
+    dst->AddIntListAttribute(ax::mojom::IntListAttribute::kControlsIds,
+                             controls_ids);
+  }
+
   ax::mojom::NameFrom name_from;
   blink::WebVector<WebAXObject> name_objects;
   blink::WebString web_name = src.GetName(name_from, name_objects);
diff --git a/content/renderer/loader/web_url_loader_impl.cc b/content/renderer/loader/web_url_loader_impl.cc
index c6d68e1..3bf1111 100644
--- a/content/renderer/loader/web_url_loader_impl.cc
+++ b/content/renderer/loader/web_url_loader_impl.cc
@@ -685,6 +685,8 @@
   resource_request->top_frame_origin = request.TopFrameOrigin();
   resource_request->upgrade_if_insecure = request.UpgradeIfInsecure();
   resource_request->is_revalidating = request.IsRevalidating();
+  resource_request->should_also_use_factory_bound_origin_for_cors =
+      request.ShouldAlsoUseFactoryBoundOriginForCors();
   if (!request.RequestorOrigin().IsNull()) {
     if (request.RequestorOrigin().ToString() == "null") {
       // "file:" origin is treated like an opaque unique origin when
diff --git a/content/renderer/media/android/stream_texture_wrapper_impl.cc b/content/renderer/media/android/stream_texture_wrapper_impl.cc
index 9d74c5a..8a0eceb9 100644
--- a/content/renderer/media/android/stream_texture_wrapper_impl.cc
+++ b/content/renderer/media/android/stream_texture_wrapper_impl.cc
@@ -168,6 +168,13 @@
   DCHECK(main_task_runner_->BelongsToCurrentThread());
   DVLOG(2) << __func__;
 
+  // Normally, we have a factory.  However, if the gpu process is restarting,
+  // then we might not.
+  if (!factory_) {
+    init_cb.Run(false);
+    return;
+  }
+
   stream_texture_proxy_ =
       factory_->CreateProxy(&texture_id_, &texture_mailbox_);
   if (!stream_texture_proxy_) {
diff --git a/content/renderer/media/android/stream_texture_wrapper_impl_unittest.cc b/content/renderer/media/android/stream_texture_wrapper_impl_unittest.cc
index 2dcfa75..34abfbb 100644
--- a/content/renderer/media/android/stream_texture_wrapper_impl_unittest.cc
+++ b/content/renderer/media/android/stream_texture_wrapper_impl_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "content/renderer/media/android/stream_texture_wrapper_impl.h"
 
+#include "base/bind_helpers.h"
 #include "base/run_loop.h"
 #include "base/test/scoped_task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -30,6 +31,18 @@
       StreamTextureWrapperImpl::Create(
           false, nullptr,
           blink::scheduler::GetSingleThreadTaskRunnerForTesting());
+  // Since we provided a null factory, make sure that it also doesn't crash if
+  // we try to initialize it.
+  int result = 0;
+  stream_texture_wrapper->Initialize(
+      base::DoNothing(), gfx::Size(0, 0),
+      blink::scheduler::GetSingleThreadTaskRunnerForTesting(),
+      base::BindRepeating(
+          [](int* result_out, bool result) { *result_out = result ? 1 : 2; },
+          &result));
+  base::RunLoop().RunUntilIdle();
+  // Should be called with false.
+  EXPECT_EQ(result, 2);
 }
 
 }  // Content
diff --git a/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc b/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc
index 645539e6..7dea447 100644
--- a/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc
+++ b/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc
@@ -21,16 +21,14 @@
 #include "gpu/command_buffer/client/gles2_interface.h"
 #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
 #include "gpu/command_buffer/common/gpu_memory_buffer_support.h"
+#include "gpu/ipc/client/command_buffer_proxy_impl.h"
 #include "gpu/ipc/client/gpu_channel_host.h"
 #include "gpu/ipc/common/gpu_memory_buffer_support.h"
-#include "media/filters/gpu_video_decoder.h"
 #include "media/gpu/gpu_video_accelerator_util.h"
-#include "media/gpu/ipc/client/gpu_video_decode_accelerator_host.h"
 #include "media/gpu/ipc/common/media_messages.h"
 #include "media/mojo/buildflags.h"
 #include "media/mojo/clients/mojo_video_decoder.h"
 #include "media/mojo/clients/mojo_video_encode_accelerator.h"
-#include "media/video/video_decode_accelerator.h"
 #include "media/video/video_encode_accelerator.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/ws/public/cpp/gpu/context_provider_command_buffer.h"
@@ -223,10 +221,11 @@
   DCHECK(video_accelerator_enabled_);
   DCHECK(task_runner_->BelongsToCurrentThread());
   DCHECK(interface_factory_.is_bound());
+
+#if BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER)
   if (CheckContextLost())
     return nullptr;
 
-#if BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER)
   media::mojom::VideoDecoderPtr video_decoder;
   interface_factory_->CreateVideoDecoder(mojo::MakeRequest(&video_decoder));
   return std::make_unique<media::MojoVideoDecoder>(
@@ -237,18 +236,6 @@
 #endif  // BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER)
 }
 
-std::unique_ptr<media::VideoDecodeAccelerator>
-GpuVideoAcceleratorFactoriesImpl::CreateVideoDecodeAccelerator() {
-  DCHECK(video_accelerator_enabled_);
-  DCHECK(task_runner_->BelongsToCurrentThread());
-  if (CheckContextLost())
-    return nullptr;
-
-  return std::unique_ptr<media::VideoDecodeAccelerator>(
-      new media::GpuVideoDecodeAcceleratorHost(
-          context_provider_->GetCommandBufferProxy()));
-}
-
 std::unique_ptr<media::VideoEncodeAccelerator>
 GpuVideoAcceleratorFactoriesImpl::CreateVideoEncodeAccelerator() {
   DCHECK(video_accelerator_enabled_);
@@ -473,12 +460,6 @@
   return task_runner_;
 }
 
-media::VideoDecodeAccelerator::Capabilities
-GpuVideoAcceleratorFactoriesImpl::GetVideoDecodeAcceleratorCapabilities() {
-  return media::GpuVideoAcceleratorUtil::ConvertGpuToMediaDecodeCapabilities(
-      gpu_channel_host_->gpu_info().video_decode_accelerator_capabilities);
-}
-
 media::VideoEncodeAccelerator::SupportedProfiles
 GpuVideoAcceleratorFactoriesImpl::GetVideoEncodeAcceleratorSupportedProfiles() {
   return media::GpuVideoAcceleratorUtil::ConvertGpuToMediaEncodeProfiles(
diff --git a/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.h b/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.h
index 96e1141f..7aa4724 100644
--- a/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.h
+++ b/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.h
@@ -77,8 +77,6 @@
   bool IsDecoderConfigSupported(
       media::VideoDecoderImplementation implementation,
       const media::VideoDecoderConfig& config) override;
-  std::unique_ptr<media::VideoDecodeAccelerator> CreateVideoDecodeAccelerator()
-      override;
   std::unique_ptr<media::VideoEncodeAccelerator> CreateVideoEncodeAccelerator()
       override;
   // Creates textures and produces them into mailboxes. Returns true on success
@@ -125,8 +123,6 @@
   std::unique_ptr<base::SharedMemory> CreateSharedMemory(size_t size) override;
   scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() override;
 
-  media::VideoDecodeAccelerator::Capabilities
-  GetVideoDecodeAcceleratorCapabilities() override;
   std::vector<media::VideoEncodeAccelerator::SupportedProfile>
   GetVideoEncodeAcceleratorSupportedProfiles() override;
 
diff --git a/content/renderer/media/stream/media_stream_video_renderer_sink.cc b/content/renderer/media/stream/media_stream_video_renderer_sink.cc
index f474f66..cdf3b92 100644
--- a/content/renderer/media/stream/media_stream_video_renderer_sink.cc
+++ b/content/renderer/media/stream/media_stream_video_renderer_sink.cc
@@ -13,9 +13,6 @@
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/trace_event/trace_event.h"
-#include "content/child/child_process.h"
-#include "content/public/common/content_features.h"
-#include "content/public/renderer/render_thread.h"
 #include "media/base/video_frame.h"
 #include "media/base/video_frame_metadata.h"
 #include "media/base/video_util.h"
diff --git a/content/renderer/media/stream/webmediaplayer_ms.h b/content/renderer/media/stream/webmediaplayer_ms.h
index dc148fd..1214c08 100644
--- a/content/renderer/media/stream/webmediaplayer_ms.h
+++ b/content/renderer/media/stream/webmediaplayer_ms.h
@@ -16,8 +16,6 @@
 #include "build/build_config.h"
 #include "content/common/content_export.h"
 #include "media/blink/webmediaplayer_delegate.h"
-#include "media/blink/webmediaplayer_params.h"
-#include "media/blink/webmediaplayer_util.h"
 #include "media/renderers/paint_canvas_video_renderer.h"
 #include "media/video/gpu_video_accelerator_factories.h"
 #include "third_party/blink/public/platform/web_media_player.h"
diff --git a/content/renderer/media/stream/webmediaplayer_ms_compositor.h b/content/renderer/media/stream/webmediaplayer_ms_compositor.h
index bb1b8dc9..46bb5a0 100644
--- a/content/renderer/media/stream/webmediaplayer_ms_compositor.h
+++ b/content/renderer/media/stream/webmediaplayer_ms_compositor.h
@@ -20,7 +20,7 @@
 #include "cc/layers/video_frame_provider.h"
 #include "content/common/content_export.h"
 #include "media/base/media_util.h"
-#include "media/blink/webmediaplayer_params.h"
+#include "third_party/blink/public/platform/web_media_player.h"
 #include "third_party/blink/public/platform/web_video_frame_submitter.h"
 
 namespace base {
diff --git a/content/renderer/media/stream/webmediaplayer_ms_unittest.cc b/content/renderer/media/stream/webmediaplayer_ms_unittest.cc
index 3deac070..274e7763 100644
--- a/content/renderer/media/stream/webmediaplayer_ms_unittest.cc
+++ b/content/renderer/media/stream/webmediaplayer_ms_unittest.cc
@@ -19,7 +19,6 @@
 #include "cc/layers/layer.h"
 #include "content/renderer/media/stream/webmediaplayer_ms.h"
 #include "content/renderer/media/stream/webmediaplayer_ms_compositor.h"
-#include "content/renderer/render_frame_impl.h"
 #include "media/base/media_util.h"
 #include "media/base/test_helpers.h"
 #include "media/base/video_frame.h"
diff --git a/content/renderer/media/webrtc/rtc_video_decoder_adapter.cc b/content/renderer/media/webrtc/rtc_video_decoder_adapter.cc
index 1f6a94942..23be5bf 100644
--- a/content/renderer/media/webrtc/rtc_video_decoder_adapter.cc
+++ b/content/renderer/media/webrtc/rtc_video_decoder_adapter.cc
@@ -30,6 +30,7 @@
 #include "media/base/overlay_info.h"
 #include "media/base/video_types.h"
 #include "media/video/gpu_video_accelerator_factories.h"
+#include "media/video/video_decode_accelerator.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"
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index 8f1951e..d54a31c 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -109,7 +109,6 @@
 #include "ui/base/ui_base_features.h"
 #include "ui/base/ui_base_switches.h"
 #include "ui/events/base_event_utils.h"
-#include "ui/events/types/scroll_types.h"
 #include "ui/gfx/geometry/point_conversions.h"
 #include "ui/gfx/geometry/rect_conversions.h"
 #include "ui/gfx/geometry/size_conversions.h"
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h
index 47e137f..1d9ba506 100644
--- a/content/renderer/render_widget.h
+++ b/content/renderer/render_widget.h
@@ -65,6 +65,7 @@
 #include "ui/base/ime/text_input_mode.h"
 #include "ui/base/ime/text_input_type.h"
 #include "ui/base/ui_base_types.h"
+#include "ui/events/types/scroll_types.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/vector2d_f.h"
 #include "ui/gfx/native_widget_types.h"
@@ -101,9 +102,6 @@
 
 namespace ui {
 struct DidOverscrollParams;
-namespace input_types {
-enum class ScrollGranularity;
-}
 }
 
 namespace content {
diff --git a/content/test/data/accessibility/html/input-date-with-popup-open-expected-auralinux.txt b/content/test/data/accessibility/html/input-date-with-popup-open-expected-auralinux.txt
index 8f6c857..d5a98f4 100644
--- a/content/test/data/accessibility/html/input-date-with-popup-open-expected-auralinux.txt
+++ b/content/test/data/accessibility/html/input-date-with-popup-open-expected-auralinux.txt
@@ -1,6 +1,6 @@
 [document web]
 ++[section]
-++++[dateeditor]
+++++[dateeditor] controller-for
 ++++++[section]
 ++++++++[section]
 ++++++++++[spin button] name='Month' current=9.000000 minimum=1.000000 maximum=12.000000
@@ -12,7 +12,7 @@
 ++++++++++[spin button] name='Year' current=2008.000000 minimum=1.000000 maximum=275760.000000
 ++++++++++++[text] name='2008'
 ++++++[push button] name='Show date picker'
-++++++[document web]
+++++++[document web] controlled-by
 ++++++++[section]
 ++++++++++[section]
 ++++++++++++[section]
diff --git a/content/test/data/accessibility/html/input-date-with-popup-open-expected-blink.txt b/content/test/data/accessibility/html/input-date-with-popup-open-expected-blink.txt
index 5e4e0fd0..43a2147 100644
--- a/content/test/data/accessibility/html/input-date-with-popup-open-expected-blink.txt
+++ b/content/test/data/accessibility/html/input-date-with-popup-open-expected-blink.txt
@@ -1,6 +1,6 @@
 rootWebArea
 ++genericContainer
-++++date value='2008-09-01'
+++++date value='2008-09-01' controlsIds=rootWebArea
 ++++++genericContainer
 ++++++++genericContainer
 ++++++++++spinButton name='Month' value='09' valueForRange=9.00 minValueForRange=1.00 maxValueForRange=12.00
diff --git a/content/test/data/accessibility/html/input-date-with-popup-open-expected-uia-win.txt b/content/test/data/accessibility/html/input-date-with-popup-open-expected-uia-win.txt
index eaeeac7..0e8b157c 100644
--- a/content/test/data/accessibility/html/input-date-with-popup-open-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/input-date-with-popup-open-expected-uia-win.txt
@@ -1,7 +1,7 @@
 region
 ++document
 ++++group
-++++++list
+++++++list ControllerFor='{document}'
 ++++++++group
 ++++++++++group
 ++++++++++++spinbutton Name='Month' RangeValue.IsReadOnly=false RangeValue.LargeChange=0.00 RangeValue.SmallChange=0.00 RangeValue.Maximum=12.00 RangeValue.Minimum=1.00 RangeValue.Value=9.00 Value.Value='09'
diff --git a/content/test/data/accessibility/html/input-date-with-popup-open.html b/content/test/data/accessibility/html/input-date-with-popup-open.html
index c07ef3d7..c154848 100644
--- a/content/test/data/accessibility/html/input-date-with-popup-open.html
+++ b/content/test/data/accessibility/html/input-date-with-popup-open.html
@@ -1,6 +1,7 @@
 <!--
 @MAC-ALLOW:AXRole*
 @WIN-ALLOW:ia2_hypertext=*
+@UIA-WIN-ALLOW:ControllerFor=*
 @DEFAULT-ACTION-ON:Show date picker
 @WAIT-FOR:Today
 -->
diff --git a/device/fido/ctap_make_credential_request.h b/device/fido/ctap_make_credential_request.h
index 5c118b7..12eb63d6 100644
--- a/device/fido/ctap_make_credential_request.h
+++ b/device/fido/ctap_make_credential_request.h
@@ -68,7 +68,7 @@
   base::Optional<std::vector<uint8_t>> pin_auth;
   base::Optional<uint8_t> pin_protocol;
   AttestationConveyancePreference attestation_preference =
-      AttestationConveyancePreference::NONE;
+      AttestationConveyancePreference::kNone;
 
   // cred_protect indicates the level of protection afforded to a credential.
   // This depends on a CTAP2 extension that not all authenticators will support.
diff --git a/device/fido/fido_constants.cc b/device/fido/fido_constants.cc
index 3e6aea58..e0a3261 100644
--- a/device/fido/fido_constants.cc
+++ b/device/fido/fido_constants.cc
@@ -31,7 +31,7 @@
 const char kCredentialManagementPreviewMapKey[] = "credentialMgmtPreview";
 const char kBioEnrollmentPreviewMapKey[] = "userVerificationMgmtPreview";
 
-const base::TimeDelta kDeviceTimeout = base::TimeDelta::FromSeconds(3);
+const base::TimeDelta kDeviceTimeout = base::TimeDelta::FromSeconds(10);
 const base::TimeDelta kU2fRetryDelay = base::TimeDelta::FromMilliseconds(200);
 
 const char kFormatKey[] = "fmt";
diff --git a/device/fido/fido_constants.h b/device/fido/fido_constants.h
index 3f33e537..adb9d04 100644
--- a/device/fido/fido_constants.h
+++ b/device/fido/fido_constants.h
@@ -403,12 +403,12 @@
 
 // https://w3c.github.io/webauthn/#attestation-convey
 enum class AttestationConveyancePreference : uint8_t {
-  NONE,
-  INDIRECT,
-  DIRECT,
+  kNone,
+  kIndirect,
+  kDirect,
   // Non-standard value for individual attestation that we hope to end up in
   // the standard eventually.
-  ENTERPRISE,
+  kEnterprise,
 };
 
 // CredProtect enumerates the levels of credential protection specified by the
diff --git a/device/fido/u2f_command_constructor.cc b/device/fido/u2f_command_constructor.cc
index 9c4dfca..ce2839e6 100644
--- a/device/fido/u2f_command_constructor.cc
+++ b/device/fido/u2f_command_constructor.cc
@@ -47,7 +47,7 @@
 
   const bool is_invidual_attestation =
       request.attestation_preference ==
-      AttestationConveyancePreference::ENTERPRISE;
+      AttestationConveyancePreference::kEnterprise;
   return ConstructU2fRegisterCommand(
       fido_parsing_utils::CreateSHA256Hash(request.rp.id),
       request.client_data_hash, is_invidual_attestation);
diff --git a/device/fido/u2f_register_operation_unittest.cc b/device/fido/u2f_register_operation_unittest.cc
index d81ec4f..67693240 100644
--- a/device/fido/u2f_register_operation_unittest.cc
+++ b/device/fido/u2f_register_operation_unittest.cc
@@ -41,7 +41,7 @@
   request.exclude_list = std::move(registered_keys);
   if (is_individual_attestation)
     request.attestation_preference =
-        AttestationConveyancePreference::ENTERPRISE;
+        AttestationConveyancePreference::kEnterprise;
 
   return request;
 }
diff --git a/device/fido/win/type_conversions.cc b/device/fido/win/type_conversions.cc
index 3e0c3b73..f1d01d3 100644
--- a/device/fido/win/type_conversions.cc
+++ b/device/fido/win/type_conversions.cc
@@ -230,13 +230,13 @@
 uint32_t ToWinAttestationConveyancePreference(
     const AttestationConveyancePreference& value) {
   switch (value) {
-    case AttestationConveyancePreference::NONE:
+    case AttestationConveyancePreference::kNone:
       return WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_NONE;
-    case AttestationConveyancePreference::INDIRECT:
+    case AttestationConveyancePreference::kIndirect:
       return WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_DIRECT;
-    case AttestationConveyancePreference::DIRECT:
+    case AttestationConveyancePreference::kDirect:
       return WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_DIRECT;
-    case AttestationConveyancePreference::ENTERPRISE:
+    case AttestationConveyancePreference::kEnterprise:
       // Windows does not support enterprise attestation.
       return WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_DIRECT;
   }
diff --git a/device/gamepad/game_controller_data_fetcher_mac.mm b/device/gamepad/game_controller_data_fetcher_mac.mm
index efa3be6..e6440ec1 100644
--- a/device/gamepad/game_controller_data_fetcher_mac.mm
+++ b/device/gamepad/game_controller_data_fetcher_mac.mm
@@ -7,7 +7,7 @@
 #include <string.h>
 
 #include "base/strings/string16.h"
-#include "base/strings/string_util.h"
+#include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "device/gamepad/gamepad_standard_mappings.h"
 
@@ -19,14 +19,6 @@
 
 const int kGCControllerPlayerIndexCount = 4;
 
-void CopyNSStringAsUTF16LittleEndian(NSString* src,
-                                     base::char16* dest,
-                                     size_t dest_len) {
-  NSData* as16 = [src dataUsingEncoding:NSUTF16LittleEndianStringEncoding];
-  memset(dest, 0, dest_len);
-  [as16 getBytes:dest length:dest_len - sizeof(base::char16)];
-}
-
 }  // namespace
 
 GameControllerDataFetcherMac::GameControllerDataFetcherMac() {}
@@ -90,9 +82,9 @@
       NSString* ident =
           [NSString stringWithFormat:@"%@ (STANDARD GAMEPAD)",
                                      vendorName ? vendorName : @"Unknown"];
-      CopyNSStringAsUTF16LittleEndian(ident, pad.id, sizeof(pad.id));
 
       pad.mapping = GamepadMapping::kStandard;
+      pad.SetID(base::SysNSStringToUTF16(ident));
       pad.axes_length = AXIS_INDEX_COUNT;
       pad.buttons_length = BUTTON_INDEX_COUNT - 1;
       pad.connected = true;
diff --git a/device/gamepad/gamepad_data_fetcher.cc b/device/gamepad/gamepad_data_fetcher.cc
index b36f4cc..a33216df 100644
--- a/device/gamepad/gamepad_data_fetcher.cc
+++ b/device/gamepad/gamepad_data_fetcher.cc
@@ -64,15 +64,12 @@
                                               uint16_t product_id,
                                               bool has_standard_mapping,
                                               Gamepad& pad) {
-  // Set the ID string. The ID contains the device name, vendor and product IDs,
+  // The ID contains the device name, vendor and product IDs,
   // and an indication of whether the standard mapping is in use.
   std::string id = base::StringPrintf(
       "%s (%sVendor: %04x Product: %04x)", name.c_str(),
       has_standard_mapping ? "STANDARD GAMEPAD " : "", vendor_id, product_id);
-  base::TruncateUTF8ToByteSize(id, Gamepad::kIdLengthCap - 1, &id);
-  base::string16 tmp16 = base::UTF8ToUTF16(id);
-  memset(pad.id, 0, sizeof(pad.id));
-  tmp16.copy(pad.id, base::size(pad.id) - 1);
+  pad.SetID(base::UTF8ToUTF16(id));
 
   // Set GamepadMapping::kStandard if the gamepad has a standard mapping, or
   // GamepadMapping::kNone otherwise.
diff --git a/device/gamepad/gamepad_platform_data_fetcher_android.cc b/device/gamepad/gamepad_platform_data_fetcher_android.cc
index 6865f55f..ca39b0be 100644
--- a/device/gamepad/gamepad_platform_data_fetcher_android.cc
+++ b/device/gamepad/gamepad_platform_data_fetcher_android.cc
@@ -94,13 +94,9 @@
     // be mapped to vendor and product information but it is only available at
     // kernel level and it can not be queried using class
     // android.hardware.input.InputManager.
-    base::string16 device_name;
-    base::android::ConvertJavaStringToUTF16(env, devicename, &device_name);
-    const size_t name_to_copy =
-        std::min(device_name.size(), Gamepad::kIdLengthCap - 1);
-    memcpy(pad.id, device_name.data(),
-           name_to_copy * sizeof(base::string16::value_type));
-    pad.id[name_to_copy] = 0;
+    base::string16 gamepad_id;
+    base::android::ConvertJavaStringToUTF16(env, devicename, &gamepad_id);
+    pad.SetID(gamepad_id);
 
     pad.mapping = mapping ? GamepadMapping::kStandard : GamepadMapping::kNone;
   }
diff --git a/device/gamepad/gamepad_platform_data_fetcher_mac.mm b/device/gamepad/gamepad_platform_data_fetcher_mac.mm
index 23679309..009810e 100644
--- a/device/gamepad/gamepad_platform_data_fetcher_mac.mm
+++ b/device/gamepad/gamepad_platform_data_fetcher_mac.mm
@@ -9,6 +9,7 @@
 
 #include "base/mac/foundation_util.h"
 #include "base/mac/scoped_nsobject.h"
+#include "base/strings/sys_string_conversions.h"
 #include "base/time/time.h"
 #include "device/gamepad/gamepad_id_list.h"
 #include "device/gamepad/gamepad_uma.h"
@@ -27,14 +28,6 @@
 const uint16_t kGameUsageNumber = 0x05;
 const uint16_t kMultiAxisUsageNumber = 0x08;
 
-void CopyNSStringAsUTF16LittleEndian(NSString* src,
-                                     base::char16* dest,
-                                     size_t dest_len) {
-  NSData* as16 = [src dataUsingEncoding:NSUTF16LittleEndianStringEncoding];
-  memset(dest, 0, dest_len);
-  [as16 getBytes:dest length:dest_len - sizeof(base::char16)];
-}
-
 NSDictionary* DeviceMatching(uint32_t usage_page, uint32_t usage) {
   return [NSDictionary
       dictionaryWithObjectsAndKeys:[NSNumber numberWithUnsignedInt:usage_page],
@@ -227,8 +220,7 @@
       [NSString stringWithFormat:@"%@ (%sVendor: %04x Product: %04x)", product,
                                  state->mapper ? "STANDARD GAMEPAD " : "",
                                  vendor_int, product_int];
-  CopyNSStringAsUTF16LittleEndian(ident, state->data.id,
-                                  sizeof(state->data.id));
+  state->data.SetID(base::SysNSStringToUTF16(ident));
 
   state->data.mapping =
       state->mapper ? GamepadMapping::kStandard : GamepadMapping::kNone;
diff --git a/device/gamepad/gamepad_platform_data_fetcher_win.cc b/device/gamepad/gamepad_platform_data_fetcher_win.cc
index 4da09e9f..ff3fe354 100644
--- a/device/gamepad/gamepad_platform_data_fetcher_win.cc
+++ b/device/gamepad/gamepad_platform_data_fetcher_win.cc
@@ -134,9 +134,9 @@
         pad.vibration_actuator.type = GamepadHapticActuatorType::kDualRumble;
         pad.vibration_actuator.not_null = true;
 
-        swprintf(base::as_writable_wcstr(pad.id), Gamepad::kIdLengthCap,
-                 L"Xbox 360 Controller (XInput STANDARD %ls)",
-                 GamepadSubTypeName(caps.SubType));
+        pad.SetID(
+            base::StringPrintf(L"Xbox 360 Controller (XInput STANDARD %ls)",
+                               GamepadSubTypeName(caps.SubType)));
         pad.mapping = GamepadMapping::kStandard;
       }
     }
diff --git a/device/gamepad/public/cpp/gamepad.cc b/device/gamepad/public/cpp/gamepad.cc
index f8b22682..31c5c6e 100644
--- a/device/gamepad/public/cpp/gamepad.cc
+++ b/device/gamepad/public/cpp/gamepad.cc
@@ -24,4 +24,9 @@
 
 Gamepad::Gamepad(const Gamepad& other) = default;
 
+void Gamepad::SetID(const base::string16& src) {
+  memset(id, 0, sizeof(id));
+  src.copy(id, kIdLengthCap - 1);
+}
+
 }  // namespace device
diff --git a/device/gamepad/public/cpp/gamepad.h b/device/gamepad/public/cpp/gamepad.h
index c63cc5e2..9203c4f 100644
--- a/device/gamepad/public/cpp/gamepad.h
+++ b/device/gamepad/public/cpp/gamepad.h
@@ -107,6 +107,11 @@
   Gamepad();
   Gamepad(const Gamepad& other);
 
+  // If src is too long, then the contents of id will be truncated to
+  // kIdLengthCap-1. id will be null-terminated and any extra space in the
+  // buffer will be zeroed out.
+  void SetID(const base::string16& src);
+
   // Is there a gamepad connected at this index?
   bool connected;
 
diff --git a/device/gamepad/raw_input_data_fetcher_win.cc b/device/gamepad/raw_input_data_fetcher_win.cc
index 2e052a0..071960c 100644
--- a/device/gamepad/raw_input_data_fetcher_win.cc
+++ b/device/gamepad/raw_input_data_fetcher_win.cc
@@ -215,10 +215,10 @@
         state->axis_mask = 0;
         state->button_mask = 0;
 
-        swprintf(base::as_writable_wcstr(pad.id), Gamepad::kIdLengthCap,
-                 L"%ls (%lsVendor: %04x Product: %04x)", product_string.c_str(),
-                 state->mapper ? L"STANDARD GAMEPAD " : L"", vendor_int,
-                 product_int);
+        pad.SetID(base::StringPrintf(L"%ls (%lsVendor: %04x Product: %04x)",
+                                     product_string.c_str(),
+                                     state->mapper ? L"STANDARD GAMEPAD " : L"",
+                                     vendor_int, product_int));
 
         // The mapping is standard if there is a standard mapping function.
         pad.mapping =
diff --git a/device/gamepad/xbox_data_fetcher_mac.cc b/device/gamepad/xbox_data_fetcher_mac.cc
index b8ffc025..2cf8a91 100644
--- a/device/gamepad/xbox_data_fetcher_mac.cc
+++ b/device/gamepad/xbox_data_fetcher_mac.cc
@@ -22,16 +22,6 @@
 
 namespace device {
 
-namespace {
-
-void CopyToUString(base::char16* dest, size_t dest_length, base::string16 src) {
-  const size_t str_to_copy = std::min(src.size(), dest_length - 1);
-  src.copy(dest, str_to_copy);
-  std::fill(dest + str_to_copy, dest + dest_length, 0);
-}
-
-}  // namespace
-
 XboxDataFetcher::PendingController::PendingController(
     XboxDataFetcher* fetcher,
     std::unique_ptr<XboxControllerMac> controller)
@@ -320,9 +310,7 @@
   controller->SetLEDPattern((XboxControllerMac::LEDPattern)(
       XboxControllerMac::LED_FLASH_TOP_LEFT + controller->location_id()));
 
-  CopyToUString(state->data.id, base::size(state->data.id),
-                base::UTF8ToUTF16(controller->GetIdString()));
-
+  state->data.SetID(base::UTF8ToUTF16(controller->GetIdString()));
   state->data.mapping = GamepadMapping::kStandard;
   state->data.connected = true;
   state->data.axes_length = 4;
diff --git a/device/vr/BUILD.gn b/device/vr/BUILD.gn
index 34fbcf7..44403d0 100644
--- a/device/vr/BUILD.gn
+++ b/device/vr/BUILD.gn
@@ -25,8 +25,6 @@
       "orientation/orientation_device.h",
       "orientation/orientation_device_provider.cc",
       "orientation/orientation_device_provider.h",
-      "util/copy_to_ustring.cc",
-      "util/copy_to_ustring.h",
       "util/fps_meter.cc",
       "util/fps_meter.h",
       "util/gamepad_builder.cc",
diff --git a/device/vr/android/gvr/cardboard_gamepad_data_fetcher.cc b/device/vr/android/gvr/cardboard_gamepad_data_fetcher.cc
index a2c2231..b116063a 100644
--- a/device/vr/android/gvr/cardboard_gamepad_data_fetcher.cc
+++ b/device/vr/android/gvr/cardboard_gamepad_data_fetcher.cc
@@ -11,16 +11,6 @@
 
 namespace device {
 
-namespace {
-
-void CopyToUString(base::char16* dest, size_t dest_length, base::string16 src) {
-  const size_t str_to_copy = std::min(src.size(), dest_length - 1);
-  memcpy(dest, src.data(), str_to_copy * sizeof(base::string16::value_type));
-  dest[str_to_copy] = 0;
-}
-
-}  // namespace
-
 CardboardGamepadDataFetcher::Factory::Factory(
     CardboardGamepadDataProvider* data_provider,
     device::mojom::XRDeviceId display_id)
@@ -83,9 +73,8 @@
     // initialization
     pad.connected = true;
     pad.is_xr = true;
-    CopyToUString(pad.id, Gamepad::kIdLengthCap,
-                  base::UTF8ToUTF16("Cardboard Button"));
     pad.mapping = GamepadMapping::kNone;
+    pad.SetID(base::UTF8ToUTF16("Cardboard Button"));
     pad.buttons_length = 1;
     pad.axes_length = 0;
 
diff --git a/device/vr/android/gvr/gvr_gamepad_data_fetcher.cc b/device/vr/android/gvr/gvr_gamepad_data_fetcher.cc
index 928ed82..001426cc 100644
--- a/device/vr/android/gvr/gvr_gamepad_data_fetcher.cc
+++ b/device/vr/android/gvr/gvr_gamepad_data_fetcher.cc
@@ -12,16 +12,6 @@
 
 namespace device {
 
-namespace {
-
-void CopyToUString(base::char16* dest, size_t dest_length, base::string16 src) {
-  const size_t str_to_copy = std::min(src.size(), dest_length - 1);
-  memcpy(dest, src.data(), str_to_copy * sizeof(base::string16::value_type));
-  dest[str_to_copy] = 0;
-}
-
-}  // namespace
-
 GvrGamepadDataFetcher::Factory::Factory(GvrGamepadDataProvider* data_provider,
                                         mojom::XRDeviceId display_id)
     : data_provider_(data_provider), display_id_(display_id) {
@@ -83,9 +73,8 @@
     state->is_initialized = true;
     // This is the first time we've seen this device, so do some one-time
     // initialization
-    CopyToUString(pad.id, Gamepad::kIdLengthCap,
-                  base::UTF8ToUTF16("Daydream Controller"));
     pad.mapping = GamepadMapping::kNone;
+    pad.SetID(base::UTF8ToUTF16("Daydream Controller"));
     pad.buttons_length = 1;
     pad.axes_length = 2;
 
diff --git a/device/vr/isolated_gamepad_data_fetcher.cc b/device/vr/isolated_gamepad_data_fetcher.cc
index 51ea46a9..f766fe14c 100644
--- a/device/vr/isolated_gamepad_data_fetcher.cc
+++ b/device/vr/isolated_gamepad_data_fetcher.cc
@@ -5,6 +5,7 @@
 #include "device/vr/isolated_gamepad_data_fetcher.h"
 
 #include "base/bind.h"
+#include "base/strings/utf_string_conversions.h"
 #include "build/buildflag.h"
 #include "device/vr/buildflags/buildflags.h"
 #include "device/vr/vr_device.h"
@@ -217,18 +218,14 @@
     // a headset.  This doesn't change behavior, but the device/display naming
     // could be confusing here.
     if (this->source() == GAMEPAD_SOURCE_OPENVR) {
-      swprintf(base::as_writable_wcstr(dest.id), Gamepad::kIdLengthCap,
-               L"OpenVR Gamepad");
+      dest.SetID(base::UTF8ToUTF16("OpenVR Gamepad"));
     } else if (this->source() == GAMEPAD_SOURCE_OCULUS) {
       if (dest.hand == GamepadHand::kLeft) {
-        swprintf(base::as_writable_wcstr(dest.id), Gamepad::kIdLengthCap,
-                 L"Oculus Touch (Left)");
+        dest.SetID(base::UTF8ToUTF16("Oculus Touch (Left)"));
       } else if (dest.hand == GamepadHand::kRight) {
-        swprintf(base::as_writable_wcstr(dest.id), Gamepad::kIdLengthCap,
-                 L"Oculus Touch (Right)");
+        dest.SetID(base::UTF8ToUTF16("Oculus Touch (Right)"));
       } else {
-        swprintf(base::as_writable_wcstr(dest.id), Gamepad::kIdLengthCap,
-                 L"Oculus Remote");
+        dest.SetID(base::UTF8ToUTF16("Oculus Remote"));
       }
     } else if (this->source() == GAMEPAD_SOURCE_WIN_MR) {
       // For compatibility with Edge and existing libraries, Win MR may plumb
@@ -241,11 +238,10 @@
           source->pose->input_state.value()[0]->gamepad) {
         Gamepad id_gamepad =
             source->pose->input_state.value()[0]->gamepad.value();
-        swprintf(base::as_writable_wcstr(dest.id), Gamepad::kIdLengthCap,
-                 id_gamepad.id);
+        dest.SetID(id_gamepad.id);
       } else {
-        swprintf(base::as_writable_wcstr(dest.id), Gamepad::kIdLengthCap,
-                 L"Spatial Controller (Spatial Interaction Source) 0000-0000");
+        dest.SetID(base::UTF8ToUTF16(
+            "Spatial Controller (Spatial Interaction Source) 0000-0000"));
       }
     }
 
diff --git a/device/vr/util/copy_to_ustring.cc b/device/vr/util/copy_to_ustring.cc
deleted file mode 100644
index 19ed8f6..0000000
--- a/device/vr/util/copy_to_ustring.cc
+++ /dev/null
@@ -1,21 +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.
-
-#include "device/vr/util/copy_to_ustring.h"
-
-#include <algorithm>
-
-#include "device/gamepad/public/cpp/gamepad.h"
-
-namespace device {
-
-void CopyToUString(const base::string16& src,
-                   base::char16* dest,
-                   size_t dest_length) {
-  const size_t copy_char_count = std::min(src.size(), dest_length - 1);
-  src.copy(dest, copy_char_count);
-  std::fill(dest + copy_char_count, dest + dest_length, 0);
-}
-
-}  // namespace device
diff --git a/device/vr/util/copy_to_ustring.h b/device/vr/util/copy_to_ustring.h
deleted file mode 100644
index e950065..0000000
--- a/device/vr/util/copy_to_ustring.h
+++ /dev/null
@@ -1,23 +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 DEVICE_VR_UTIL_COPY_TO_USTRING_H_
-#define DEVICE_VR_UTIL_COPY_TO_USTRING_H_
-
-#include "base/strings/string16.h"
-
-namespace device {
-
-// Cross-platform way of copying a string to fixed-length UTF-16 buffer. When
-// copying src to dest, the contents will be truncated if necessary.
-// TODO(https://crbug.com/957806): Code that does the same thing is copied in
-// several places across device/vr. Consolidate them and this function into one
-// shared among device/gamepad and device/vr.
-void CopyToUString(const base::string16& src,
-                   base::char16* dest,
-                   size_t dest_length);
-
-}  // namespace device
-
-#endif  // DEVICE_VR_UTIL_COPY_TO_USTRING_H_
diff --git a/device/vr/util/gamepad_builder.cc b/device/vr/util/gamepad_builder.cc
index 90735b49..0289cf3 100644
--- a/device/vr/util/gamepad_builder.cc
+++ b/device/vr/util/gamepad_builder.cc
@@ -7,7 +7,6 @@
 #include "base/stl_util.h"
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
-#include "device/vr/util/copy_to_ustring.h"
 
 namespace device {
 
@@ -36,8 +35,7 @@
   gamepad_.timestamp = base::TimeTicks::Now().since_origin().InMicroseconds();
   gamepad_.mapping = mapping;
   gamepad_.hand = MojoToGamepadHandedness(handedness);
-  CopyToUString(base::UTF8ToUTF16(gamepad_id), gamepad_.id,
-                Gamepad::kIdLengthCap);
+  gamepad_.SetID(base::UTF8ToUTF16(gamepad_id));
 }
 
 GamepadBuilder::~GamepadBuilder() = default;
diff --git a/fuchsia/engine/context_provider_impl.cc b/fuchsia/engine/context_provider_impl.cc
index 53e7fb2ff..f5086687 100644
--- a/fuchsia/engine/context_provider_impl.cc
+++ b/fuchsia/engine/context_provider_impl.cc
@@ -57,14 +57,13 @@
     fuchsia::web::CreateContextParams params,
     fidl::InterfaceRequest<fuchsia::web::Context> context_request) {
   if (!context_request.is_valid()) {
-    // TODO(crbug.com/934539): Add type epitaph.
-    DLOG(WARNING) << "Invalid |context_request|.";
+    DLOG(ERROR) << "Invalid |context_request|.";
     return;
   }
   if (!params.has_service_directory()) {
-    // TODO(crbug.com/934539): Add type epitaph.
-    DLOG(WARNING)
+    DLOG(ERROR)
         << "Missing argument |service_directory| in CreateContextParams.";
+    context_request.Close(ZX_ERR_INVALID_ARGS);
     return;
   }
 
@@ -77,25 +76,23 @@
 
   // Transfer the ContextRequest handle to a well-known location in the child
   // process' handle table.
-  zx::channel context_handle(context_request.TakeChannel());
   launch_options.handles_to_transfer.push_back(
-      {kContextRequestHandleId, context_handle.get()});
+      {kContextRequestHandleId, context_request.channel().get()});
 
   // Bind |data_directory| to /data directory, if provided.
   if (params.has_data_directory()) {
     zx::channel data_directory_channel = ValidateDirectoryAndTakeChannel(
         std::move(*params.mutable_data_directory()));
     if (data_directory_channel.get() == ZX_HANDLE_INVALID) {
-      // TODO(crbug.com/934539): Add type epitaph.
-      DLOG(WARNING)
+      DLOG(ERROR)
           << "Invalid argument |data_directory| in CreateContextParams.";
+      context_request.Close(ZX_ERR_INVALID_ARGS);
       return;
     }
 
     base::FilePath data_path;
     if (!base::PathService::Get(base::DIR_APP_DATA, &data_path)) {
-      // TODO(crbug.com/934539): Add type epitaph.
-      DLOG(WARNING) << "Failed to get data directory service path.";
+      DLOG(ERROR) << "Failed to get data directory service path.";
       return;
     }
     launch_options.paths_to_transfer.push_back(
@@ -107,12 +104,14 @@
   zx::job job;
   zx_status_t status = zx::job::create(*base::GetDefaultJob(), 0, &job);
   if (status != ZX_OK) {
-    ZX_LOG(FATAL, status) << "zx_job_create";
+    ZX_LOG(ERROR, status) << "zx_job_create";
     return;
   }
   launch_options.job_handle = job.get();
 
+  // Connect DevTools listeners to the new Context process.
   base::CommandLine launch_command(*base::CommandLine::ForCurrentProcess());
+  std::vector<zx::channel> devtools_listener_channels;
   if (devtools_listeners_.size() != 0) {
     std::vector<std::string> handles_ids;
     for (auto& devtools_listener : devtools_listeners_.ptrs()) {
@@ -120,10 +119,11 @@
           client_listener;
       devtools_listener.get()->get()->OnContextDevToolsAvailable(
           client_listener.NewRequest());
+      devtools_listener_channels.emplace_back(client_listener.TakeChannel());
       handles_ids.push_back(
           base::NumberToString(base::LaunchOptions::AddHandleToTransfer(
               &launch_options.handles_to_transfer,
-              client_listener.TakeChannel().release())));
+              devtools_listener_channels.back().get())));
     }
     launch_command.AppendSwitchNative(kRemoteDebuggerHandles,
                                       base::JoinString(handles_ids, ","));
@@ -134,8 +134,11 @@
   else
     base::LaunchProcess(launch_command, launch_options);
 
-  // |context_handle| was transferred (not copied) to the Context process.
-  ignore_result(context_handle.release());
+  // |context_request| and any DevTools channels were transferred (not copied)
+  // to the Context process.
+  ignore_result(context_request.TakeChannel().release());
+  for (auto& channel : devtools_listener_channels)
+    ignore_result(channel.release());
 }
 
 void ContextProviderImpl::SetLaunchCallbackForTest(
diff --git a/fuchsia/engine/context_provider_impl_unittest.cc b/fuchsia/engine/context_provider_impl_unittest.cc
index f03815ea..078e765 100644
--- a/fuchsia/engine/context_provider_impl_unittest.cc
+++ b/fuchsia/engine/context_provider_impl_unittest.cc
@@ -7,6 +7,7 @@
 #include <fuchsia/web/cpp/fidl.h>
 #include <lib/fdio/directory.h>
 #include <lib/fidl/cpp/binding.h>
+#include <lib/zx/socket.h>
 #include <zircon/processargs.h>
 #include <zircon/types.h>
 
@@ -214,6 +215,38 @@
   CheckContextResponsive(&context);
 }
 
+TEST_F(ContextProviderImplTest, LaunchContextInvalidArguments) {
+  {
+    // Attempt to create a Context without specifying a service directory.
+    fidl::InterfacePtr<fuchsia::web::Context> context;
+    fuchsia::web::CreateContextParams create_params;
+    provider_ptr_->Create(std::move(create_params), context.NewRequest());
+    base::RunLoop run_loop;
+    context.set_error_handler([&run_loop](zx_status_t status) {
+      EXPECT_EQ(status, ZX_ERR_INVALID_ARGS);
+      run_loop.Quit();
+    });
+  }
+
+  // Deliberately supply the wrong kind of object as the data-directory.
+  {
+    fidl::InterfacePtr<fuchsia::web::Context> context;
+    fuchsia::web::CreateContextParams create_params =
+        BuildCreateContextParams();
+    zx::socket socket1, socket2;
+    ASSERT_EQ(zx::socket::create(0, &socket1, &socket2), ZX_OK);
+    create_params.set_data_directory(
+        fidl::InterfaceHandle<fuchsia::io::Directory>(
+            zx::channel(socket1.release())));
+    provider_ptr_->Create(std::move(create_params), context.NewRequest());
+    base::RunLoop run_loop;
+    context.set_error_handler([&run_loop](zx_status_t status) {
+      EXPECT_EQ(status, ZX_ERR_INVALID_ARGS);
+      run_loop.Quit();
+    });
+  }
+}
+
 TEST_F(ContextProviderImplTest, MultipleConcurrentClients) {
   // Bind a Provider connection, and create a Context from it.
   fuchsia::web::ContextProviderPtr provider_1_ptr;
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc
index 211bfd81..7421f84 100644
--- a/gpu/command_buffer/client/gles2_implementation.cc
+++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -208,6 +208,7 @@
       bound_atomic_counter_buffer_(0),
       bound_copy_read_buffer_(0),
       bound_copy_write_buffer_(0),
+      bound_dispatch_indirect_buffer_(0),
       bound_pixel_pack_buffer_(0),
       bound_pixel_unpack_buffer_(0),
       bound_shader_storage_buffer_(0),
@@ -1045,6 +1046,9 @@
     case GL_ATOMIC_COUNTER_BUFFER_BINDING:
       *params = bound_atomic_counter_buffer_;
       return true;
+    case GL_DISPATCH_INDIRECT_BUFFER_BINDING:
+      *params = bound_dispatch_indirect_buffer_;
+      return true;
     case GL_SHADER_STORAGE_BUFFER_BINDING:
       *params = bound_shader_storage_buffer_;
       return true;
@@ -4645,6 +4649,12 @@
         changed = true;
       }
       break;
+    case GL_DISPATCH_INDIRECT_BUFFER:
+      if (bound_dispatch_indirect_buffer_ != buffer_id) {
+        bound_dispatch_indirect_buffer_ = buffer_id;
+        changed = true;
+      }
+      break;
     case GL_ELEMENT_ARRAY_BUFFER:
       changed = vertex_array_object_manager_->BindElementArray(buffer_id);
       break;
@@ -4967,6 +4977,9 @@
     if (buffers[ii] == bound_copy_write_buffer_) {
       bound_copy_write_buffer_ = 0;
     }
+    if (buffers[ii] == bound_dispatch_indirect_buffer_) {
+      bound_dispatch_indirect_buffer_ = 0;
+    }
     if (buffers[ii] == bound_pixel_pack_buffer_) {
       bound_pixel_pack_buffer_ = 0;
     }
@@ -5669,6 +5682,7 @@
     case GL_ELEMENT_ARRAY_BUFFER:
     case GL_COPY_READ_BUFFER:
     case GL_COPY_WRITE_BUFFER:
+    case GL_DISPATCH_INDIRECT_BUFFER:
     case GL_PIXEL_PACK_BUFFER:
     case GL_PIXEL_UNPACK_BUFFER:
     case GL_SHADER_STORAGE_BUFFER:
diff --git a/gpu/command_buffer/client/gles2_implementation.h b/gpu/command_buffer/client/gles2_implementation.h
index 99e350d..ed401c4 100644
--- a/gpu/command_buffer/client/gles2_implementation.h
+++ b/gpu/command_buffer/client/gles2_implementation.h
@@ -750,6 +750,7 @@
   GLuint bound_atomic_counter_buffer_;
   GLuint bound_copy_read_buffer_;
   GLuint bound_copy_write_buffer_;
+  GLuint bound_dispatch_indirect_buffer_;
   GLuint bound_pixel_pack_buffer_;
   GLuint bound_pixel_unpack_buffer_;
   GLuint bound_shader_storage_buffer_;
diff --git a/gpu/command_buffer/common/gles2_cmd_utils.cc b/gpu/command_buffer/common/gles2_cmd_utils.cc
index 10cb229..e2ff04d 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils.cc
+++ b/gpu/command_buffer/common/gles2_cmd_utils.cc
@@ -290,6 +290,8 @@
       return 1;
     case GL_ATOMIC_COUNTER_BUFFER_START:
       return 1;
+    case GL_DISPATCH_INDIRECT_BUFFER_BINDING:
+      return 1;
     case GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS:
       return 1;
     case GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS:
@@ -1674,6 +1676,8 @@
       return GL_COPY_READ_BUFFER_BINDING;
     case GL_COPY_WRITE_BUFFER:
       return GL_COPY_WRITE_BUFFER_BINDING;
+    case GL_DISPATCH_INDIRECT_BUFFER:
+      return GL_DISPATCH_INDIRECT_BUFFER_BINDING;
     case GL_ELEMENT_ARRAY_BUFFER:
       return GL_ELEMENT_ARRAY_BUFFER_BINDING;
     case GL_PIXEL_PACK_BUFFER:
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc
index 15fd3f9..78719a9 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc
@@ -1627,10 +1627,24 @@
   gpu_tracer_->BeginDecoding();
   gpu_trace_commands_ = gpu_tracer_->IsTracing() && *gpu_decoder_category_;
   gpu_debug_commands_ = log_commands() || debug() || gpu_trace_commands_;
+
+  auto it = active_queries_.find(GL_COMMANDS_ISSUED_CHROMIUM);
+  if (it != active_queries_.end()) {
+    DCHECK_EQ(it->second.command_processing_start_time, base::TimeTicks());
+    it->second.command_processing_start_time = base::TimeTicks::Now();
+  }
 }
 
 void GLES2DecoderPassthroughImpl::EndDecoding() {
   gpu_tracer_->EndDecoding();
+
+  auto it = active_queries_.find(GL_COMMANDS_ISSUED_CHROMIUM);
+  if (it != active_queries_.end()) {
+    DCHECK_NE(it->second.command_processing_start_time, base::TimeTicks());
+    it->second.active_time +=
+        (base::TimeTicks::Now() - it->second.command_processing_start_time);
+    it->second.command_processing_start_time = base::TimeTicks();
+  }
 }
 
 const gpu::gles2::ContextState* GLES2DecoderPassthroughImpl::GetContextState() {
@@ -1789,6 +1803,7 @@
     case GL_COPY_READ_BUFFER_BINDING:
     case GL_COPY_WRITE_BUFFER_BINDING:
     case GL_UNIFORM_BUFFER_BINDING:
+    case GL_DISPATCH_INDIRECT_BUFFER_BINDING:
       if (*params != 0 &&
           !GetClientID(&resources_->buffer_id_map, *params, params)) {
         return error::kInvalidArguments;
@@ -2095,7 +2110,7 @@
 
       case GL_COMMANDS_ISSUED_CHROMIUM:
         result_available = GL_TRUE;
-        result = GL_TRUE;
+        result = query.commands_issued_time.InMicroseconds();
         break;
 
       case GL_LATENCY_QUERY_CHROMIUM:
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h
index 1fa45e8..f2f2256 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h
@@ -669,6 +669,7 @@
     base::subtle::Atomic32 submit_count = 0;
 
     std::unique_ptr<gl::GLFence> commands_completed_fence;
+    base::TimeDelta commands_issued_time;
 
     std::vector<base::OnceClosure> callbacks;
     std::unique_ptr<gl::GLFence> buffer_shadow_update_fence = nullptr;
@@ -689,6 +690,12 @@
     GLuint service_id = 0;
     scoped_refptr<gpu::Buffer> shm;
     QuerySync* sync = nullptr;
+
+    // Time at which the commands for this query started processing. This is
+    // used to ensure we only include the time when the decoder is scheduled in
+    // the |active_time|. Used for GL_COMMANDS_ISSUED_CHROMIUM type query.
+    base::TimeTicks command_processing_start_time;
+    base::TimeDelta active_time;
   };
   std::unordered_map<GLenum, ActiveQuery> active_queries_;
 
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc
index 76837d5..96f77de 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc
@@ -3405,6 +3405,8 @@
   query.service_id = service_id;
   query.shm = std::move(buffer);
   query.sync = sync;
+  if (target == GL_COMMANDS_ISSUED_CHROMIUM)
+    query.command_processing_start_time = base::TimeTicks::Now();
   active_queries_[target] = std::move(query);
 
   return error::kNoError;
@@ -3467,6 +3469,12 @@
       pending_query.program_service_id = linking_program_service_id_;
       break;
 
+    case GL_COMMANDS_ISSUED_CHROMIUM:
+      pending_query.commands_issued_time =
+          active_query.active_time +
+          (base::TimeTicks::Now() - active_query.command_processing_start_time);
+      break;
+
     default:
       break;
   }
diff --git a/gpu/config/gpu_crash_keys.cc b/gpu/config/gpu_crash_keys.cc
index 6f512b0..075630f 100644
--- a/gpu/config/gpu_crash_keys.cc
+++ b/gpu/config/gpu_crash_keys.cc
@@ -24,6 +24,8 @@
     "gpu-gl-context-is-virtual");
 crash_reporter::CrashKeyString<20> available_physical_memory_in_mb(
     "available-physical-memory-in-mb");
+crash_reporter::CrashKeyString<1024> current_shader_0("current-shader-0");
+crash_reporter::CrashKeyString<1024> current_shader_1("current-shader-1");
 
 }  // namespace crash_keys
 }  // namespace gpu
diff --git a/gpu/config/gpu_crash_keys.h b/gpu/config/gpu_crash_keys.h
index df1ccf1..e757abe 100644
--- a/gpu/config/gpu_crash_keys.h
+++ b/gpu/config/gpu_crash_keys.h
@@ -29,6 +29,8 @@
 extern GPU_EXPORT crash_reporter::CrashKeyString<4> gpu_gl_context_is_virtual;
 extern GPU_EXPORT crash_reporter::CrashKeyString<20>
     available_physical_memory_in_mb;
+extern GPU_EXPORT crash_reporter::CrashKeyString<1024> current_shader_0;
+extern GPU_EXPORT crash_reporter::CrashKeyString<1024> current_shader_1;
 
 }  // namespace crash_keys
 }  // namespace gpu
diff --git a/gpu/ipc/service/gpu_watchdog_thread.cc b/gpu/ipc/service/gpu_watchdog_thread.cc
index bee2a68..857e92b 100644
--- a/gpu/ipc/service/gpu_watchdog_thread.cc
+++ b/gpu/ipc/service/gpu_watchdog_thread.cc
@@ -18,6 +18,7 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
 #include "gpu/config/gpu_crash_keys.h"
+#include "ui/gl/shader_tracking.h"
 
 #if defined(OS_WIN)
 #include <windows.h>
@@ -478,6 +479,15 @@
   crash_keys::available_physical_memory_in_mb.Set(
       base::NumberToString(available_physical_memory));
 
+  ui::gl::ShaderTracking* shader_tracking =
+      ui::gl::ShaderTracking::GetInstance();
+  if (shader_tracking) {
+    std::string shaders[2];
+    shader_tracking->GetShaders(shaders, shaders + 1);
+    crash_keys::current_shader_0.Set(shaders[0]);
+    crash_keys::current_shader_1.Set(shaders[1]);
+  }
+
   // Check it one last time before crashing.
   if (!base::subtle::NoBarrier_Load(&awaiting_acknowledge_)) {
     OnAcknowledge();
diff --git a/infra/config/cr-buildbucket.cfg b/infra/config/cr-buildbucket.cfg
index 837e6eb..169bb0f 100644
--- a/infra/config/cr-buildbucket.cfg
+++ b/infra/config/cr-buildbucket.cfg
@@ -1183,6 +1183,7 @@
     builders {
       name: "android-kitkat-arm-rel"
       mixins: "android-ci"
+      mixins: "builderless"
       dimensions: "os:Ubuntu-16.04"
     }
 
@@ -1353,6 +1354,8 @@
     builders {
       name: "Fuchsia ARM64"
       mixins: "linux-ci"
+      mixins: "linux-xenial"
+      mixins: "builderless"
     }
 
     builders {
@@ -1363,6 +1366,8 @@
     builders {
       name: "Fuchsia x64"
       mixins: "linux-ci"
+      mixins: "linux-xenial"
+      mixins: "builderless"
     }
 
     builders {
@@ -1436,6 +1441,7 @@
       mixins: "linux"
       mixins: "memory-ci"
       mixins: "linux-xenial"
+      mixins: "builderless"
     }
 
     builders {
@@ -1455,6 +1461,7 @@
       name: "Linux Tests"
       mixins: "linux-ci"
       mixins: "linux-xenial"
+      mixins: "builderless"
     }
 
     builders {
@@ -1549,6 +1556,7 @@
       mixins: "linux"
       mixins: "linux-xenial"
       mixins: "memory-ci"
+      mixins: "builderless"
     }
 
     builders {
@@ -1556,6 +1564,7 @@
       mixins: "linux"
       mixins: "linux-xenial"
       mixins: "memory-ci"
+      mixins: "builderless"
     }
 
     # chromium.gpu
@@ -1858,11 +1867,11 @@
     }
     builders {
       name: "win-pixel-builder-rel"
-      mixins: "win-ci"
+      mixins: "fyi-ci"
     }
     builders {
       name: "win-pixel-tester-rel"
-      mixins: "win-ci"
+      mixins: "fyi-ci"
     }
     builders {
       name: "win32-arm64-rel"
@@ -3695,12 +3704,22 @@
 
     builders { mixins: "linux-dawn-try" name: "dawn-linux-x64-deps-rel" }
 
-    builders { mixins: "linux-try" name: "fuchsia_arm64" }
+    builders {
+      mixins: "linux-try"
+      name: "fuchsia_arm64"
+      mixins: "linux-xenial"
+      mixins: "builderless"
+    }
     builders { mixins: "linux-try" name: "fuchsia-arm64-cast" }
     builders { mixins: "linux-try" name: "fuchsia-fyi-arm64-rel" }
     builders { mixins: "linux-try" name: "fuchsia-fyi-x64-dbg" }
     builders { mixins: "linux-try" name: "fuchsia-fyi-x64-rel" }
-    builders { mixins: "linux-try" name: "fuchsia_x64" }
+    builders {
+      mixins: "linux-try"
+      name: "fuchsia_x64"
+      mixins: "linux-xenial"
+      mixins: "builderless"
+    }
     builders { mixins: "linux-try" name: "fuchsia-x64-cast" }
     builders {
       mixins: "linux-optional-gpu-try"
diff --git a/ios/chrome/browser/snapshots/snapshot_generator.mm b/ios/chrome/browser/snapshots/snapshot_generator.mm
index 6f4ace1..32b9c6a8 100644
--- a/ios/chrome/browser/snapshots/snapshot_generator.mm
+++ b/ios/chrome/browser/snapshots/snapshot_generator.mm
@@ -20,6 +20,7 @@
 #import "ios/chrome/browser/snapshots/snapshot_generator_delegate.h"
 #include "ios/chrome/browser/ui/ui_feature_flags.h"
 #import "ios/chrome/browser/ui/util/uikit_ui_util.h"
+#import "ios/web/public/web_client.h"
 #import "ios/web/public/web_state/web_state.h"
 #import "ios/web/public/web_state/web_state_observer_bridge.h"
 #include "ios/web/public/web_task_traits.h"
@@ -132,7 +133,9 @@
 }
 
 - (void)updateWebViewSnapshotWithCompletion:(void (^)(UIImage*))completion {
-  DCHECK(self.webState->ContentIsHTML());
+  DCHECK(!web::GetWebClient()->IsAppSpecificURL(
+      self.webState->GetLastCommittedURL()));
+
   if (![self canTakeSnapshot]) {
     if (completion) {
       base::PostTaskWithTraits(FROM_HERE, {web::WebThread::UI},
diff --git a/ios/chrome/browser/snapshots/snapshot_tab_helper.mm b/ios/chrome/browser/snapshots/snapshot_tab_helper.mm
index 11d8d73..4477fda 100644
--- a/ios/chrome/browser/snapshots/snapshot_tab_helper.mm
+++ b/ios/chrome/browser/snapshots/snapshot_tab_helper.mm
@@ -11,6 +11,7 @@
 #include "ios/chrome/browser/infobars/infobar_manager_impl.h"
 #import "ios/chrome/browser/snapshots/snapshot_generator.h"
 #include "ios/chrome/browser/ui/util/ui_util.h"
+#import "ios/web/public/web_client.h"
 #import "ios/web/public/web_state/web_state.h"
 #include "ios/web/public/web_task_traits.h"
 #include "ios/web/public/web_thread.h"
@@ -67,11 +68,16 @@
 void SnapshotTabHelper::UpdateSnapshotWithCallback(void (^callback)(UIImage*)) {
   was_loading_during_last_snapshot_ = web_state_->IsLoading();
 
-  if (web_state_->ContentIsHTML()) {
+  bool showing_native_content =
+      web::GetWebClient()->IsAppSpecificURL(web_state_->GetLastCommittedURL());
+  if (!showing_native_content && web_state_->CanTakeSnapshot()) {
+    // Take the snapshot using the optimized WKWebView snapshotting API for
+    // pages loaded in the web view when the WebState snapshot API is available.
     [snapshot_generator_ updateWebViewSnapshotWithCompletion:callback];
     return;
   }
-  // Native content cannot utilize the WKWebView snapshotting API.
+  // Use the UIKit-based snapshot API as a fallback when the WKWebView API is
+  // unavailable.
   UIImage* image = UpdateSnapshot();
   dispatch_async(dispatch_get_main_queue(), ^{
     if (callback)
diff --git a/ios/web/public/test/fakes/test_java_script_dialog_presenter.h b/ios/web/public/test/fakes/test_java_script_dialog_presenter.h
index 16ea902..82c375b2 100644
--- a/ios/web/public/test/fakes/test_java_script_dialog_presenter.h
+++ b/ios/web/public/test/fakes/test_java_script_dialog_presenter.h
@@ -5,6 +5,7 @@
 #ifndef IOS_WEB_PUBLIC_TEST_FAKES_TEST_JAVA_SCRIPT_DIALOG_PRESENTER_H_
 #define IOS_WEB_PUBLIC_TEST_FAKES_TEST_JAVA_SCRIPT_DIALOG_PRESENTER_H_
 
+#include <memory>
 #include <vector>
 
 #import "ios/web/public/java_script_dialog_presenter.h"
@@ -13,13 +14,13 @@
 
 struct TestJavaScriptDialog {
   TestJavaScriptDialog();
-  TestJavaScriptDialog(const TestJavaScriptDialog&);
   ~TestJavaScriptDialog();
   WebState* web_state = nullptr;
   GURL origin_url;
   JavaScriptDialogType java_script_dialog_type;
   NSString* message_text;
   NSString* default_prompt_text;
+  DialogClosedCallback callback;
 };
 
 // Test presenter to check that the JavaScriptDialogPresenter methods are called
@@ -39,11 +40,23 @@
                            DialogClosedCallback callback) override;
   void CancelDialogs(WebState* web_state) override;
 
+  // Whether callback execution is paused.  If a dialog presentation is
+  // requested while true, the callback will not be executed until unpaused.
+  bool callback_execution_paused() const { return callback_execution_paused_; }
+  void set_callback_execution_paused(bool callback_execution_paused) {
+    if (callback_execution_paused_ == callback_execution_paused)
+      return;
+    callback_execution_paused_ = callback_execution_paused;
+    if (!callback_execution_paused_)
+      ExecuteAllDialogCallbacks();
+  }
+
   // True if the JavaScriptDialogPresenter CancelDialogs method has been called.
   bool cancel_dialogs_called() const { return cancel_dialogs_called_; }
 
   // Returns a vector of requested dialogs.
-  const std::vector<TestJavaScriptDialog>& requested_dialogs() const {
+  const std::vector<std::unique_ptr<TestJavaScriptDialog>>& requested_dialogs()
+      const {
     return requested_dialogs_;
   }
 
@@ -58,8 +71,14 @@
   }
 
  private:
+  // Executes all non-executed callbacks in |requested_dialogs_|.
+  void ExecuteAllDialogCallbacks();
+  // Executes the callback for |dialog|.
+  void ExecuteDialogCallback(TestJavaScriptDialog* dialog);
+
+  bool callback_execution_paused_ = false;
   bool cancel_dialogs_called_ = false;
-  std::vector<TestJavaScriptDialog> requested_dialogs_;
+  std::vector<std::unique_ptr<TestJavaScriptDialog>> requested_dialogs_;
   bool callback_success_argument_ = false;
   NSString* callback_user_input_argument_;
 };
diff --git a/ios/web/public/test/fakes/test_java_script_dialog_presenter.mm b/ios/web/public/test/fakes/test_java_script_dialog_presenter.mm
index 261b8949..e6c6a23e 100644
--- a/ios/web/public/test/fakes/test_java_script_dialog_presenter.mm
+++ b/ios/web/public/test/fakes/test_java_script_dialog_presenter.mm
@@ -12,14 +12,15 @@
 
 TestJavaScriptDialog::TestJavaScriptDialog() = default;
 
-TestJavaScriptDialog::TestJavaScriptDialog(const TestJavaScriptDialog&) =
-    default;
-
 TestJavaScriptDialog::~TestJavaScriptDialog() = default;
 
 TestJavaScriptDialogPresenter::TestJavaScriptDialogPresenter() = default;
 
-TestJavaScriptDialogPresenter::~TestJavaScriptDialogPresenter() = default;
+TestJavaScriptDialogPresenter::~TestJavaScriptDialogPresenter() {
+  // Unpause callback execution so that all callbacks are executed before
+  // deallocation.
+  set_callback_execution_paused(false);
+}
 
 void TestJavaScriptDialogPresenter::RunJavaScriptDialog(
     WebState* web_state,
@@ -28,21 +29,39 @@
     NSString* message_text,
     NSString* default_prompt_text,
     DialogClosedCallback callback) {
-  TestJavaScriptDialog dialog;
-  dialog.web_state = web_state;
-  dialog.origin_url = origin_url;
-  dialog.java_script_dialog_type = java_script_dialog_type;
-  dialog.message_text = [message_text copy];
-  dialog.default_prompt_text = [default_prompt_text copy];
+  std::unique_ptr<TestJavaScriptDialog> dialog =
+      std::make_unique<TestJavaScriptDialog>();
+  dialog->web_state = web_state;
+  dialog->origin_url = origin_url;
+  dialog->java_script_dialog_type = java_script_dialog_type;
+  dialog->message_text = [message_text copy];
+  dialog->default_prompt_text = [default_prompt_text copy];
+  dialog->callback = std::move(callback);
 
-  requested_dialogs_.push_back(dialog);
+  requested_dialogs_.push_back(std::move(dialog));
 
-  std::move(callback).Run(callback_success_argument_,
-                          callback_user_input_argument_);
+  if (!callback_execution_paused())
+    ExecuteDialogCallback(requested_dialogs_.back().get());
 }
 
 void TestJavaScriptDialogPresenter::CancelDialogs(WebState* web_state) {
   cancel_dialogs_called_ = true;
 }
 
+void TestJavaScriptDialogPresenter::ExecuteAllDialogCallbacks() {
+  DCHECK(!callback_execution_paused());
+  for (std::unique_ptr<TestJavaScriptDialog>& dialog : requested_dialogs_) {
+    ExecuteDialogCallback(dialog.get());
+  }
+}
+
+void TestJavaScriptDialogPresenter::ExecuteDialogCallback(
+    TestJavaScriptDialog* dialog) {
+  DialogClosedCallback& callback = dialog->callback;
+  if (!callback.is_null()) {
+    std::move(callback).Run(callback_success_argument_,
+                            callback_user_input_argument_);
+  }
+}
+
 }  // namespace web
diff --git a/ios/web/public/test/fakes/test_web_state.h b/ios/web/public/test/fakes/test_web_state.h
index 8bbb67c3..06bc74b 100644
--- a/ios/web/public/test/fakes/test_web_state.h
+++ b/ios/web/public/test/fakes/test_web_state.h
@@ -84,6 +84,7 @@
   void DidChangeVisibleSecurityState() override {}
   bool HasOpener() const override;
   void SetHasOpener(bool has_opener) override;
+  bool CanTakeSnapshot() const override;
   void TakeSnapshot(const gfx::RectF& rect, SnapshotCallback callback) override;
 
   // Setters for test data.
@@ -105,6 +106,7 @@
   void CreateWebFramesManager();
   void AddWebFrame(std::unique_ptr<web::WebFrame> frame);
   void RemoveWebFrame(std::string frame_id);
+  void SetCanTakeSnapshot(bool can_take_snapshot);
 
   // Getters for test data.
   // Uses |policy_deciders| to return whether the navigation corresponding to
@@ -135,6 +137,7 @@
   bool is_crashed_;
   bool is_evicted_;
   bool has_opener_;
+  bool can_take_snapshot_;
   GURL url_;
   base::string16 title_;
   base::string16 last_executed_javascript_;
diff --git a/ios/web/public/test/fakes/test_web_state.mm b/ios/web/public/test/fakes/test_web_state.mm
index ac7931a6..349452d 100644
--- a/ios/web/public/test/fakes/test_web_state.mm
+++ b/ios/web/public/test/fakes/test_web_state.mm
@@ -42,6 +42,7 @@
       is_crashed_(false),
       is_evicted_(false),
       has_opener_(false),
+      can_take_snapshot_(false),
       trust_level_(kAbsolute),
       content_is_html_(true),
       web_view_proxy_(nil) {}
@@ -366,6 +367,10 @@
   manager->RemoveFrameWithId(frame_id);
 }
 
+void TestWebState::SetCanTakeSnapshot(bool can_take_snapshot) {
+  can_take_snapshot_ = can_take_snapshot;
+}
+
 CRWWebViewProxyType TestWebState::GetWebViewProxy() const {
   return web_view_proxy_;
 }
@@ -390,6 +395,10 @@
   has_opener_ = has_opener;
 }
 
+bool TestWebState::CanTakeSnapshot() const {
+  return can_take_snapshot_;
+}
+
 void TestWebState::TakeSnapshot(const gfx::RectF& rect,
                                 SnapshotCallback callback) {
   std::move(callback).Run(gfx::Image([[UIImage alloc] init]));
diff --git a/ios/web/public/web_state/web_state.h b/ios/web/public/web_state/web_state.h
index 11b7b92b..80abee30 100644
--- a/ios/web/public/web_state/web_state.h
+++ b/ios/web/public/web_state/web_state.h
@@ -323,6 +323,11 @@
   // Callback used to handle snapshots. The parameter is the snapshot image.
   typedef base::OnceCallback<void(const gfx::Image&)> SnapshotCallback;
 
+  // Returns whether TakeSnapshot() can be executed.  The API may be disabled if
+  // the WKWebView IPC mechanism is blocked due to an outstanding JavaScript
+  // dialog.
+  virtual bool CanTakeSnapshot() const = 0;
+
   // Takes a snapshot of this WebState with |rect|. |rect| should be specified
   // in the coordinate system of the view returned by GetView(). |callback| is
   // asynchronously invoked after performing the snapshot. Prior to iOS 11, the
diff --git a/ios/web/web_state/ui/crw_web_controller_unittest.mm b/ios/web/web_state/ui/crw_web_controller_unittest.mm
index 9826e21..1b12bd6 100644
--- a/ios/web/web_state/ui/crw_web_controller_unittest.mm
+++ b/ios/web/web_state/ui/crw_web_controller_unittest.mm
@@ -412,7 +412,8 @@
   TestJavaScriptDialogPresenter* js_dialog_presenter() {
     return test_web_delegate_.GetTestJavaScriptDialogPresenter();
   }
-  const std::vector<TestJavaScriptDialog>& requested_dialogs() {
+  const std::vector<std::unique_ptr<TestJavaScriptDialog>>&
+  requested_dialogs() {
     return js_dialog_presenter()->requested_dialogs();
   }
   const GURL& page_url() { return page_url_; }
@@ -429,12 +430,12 @@
   ExecuteJavaScript(@"alert('test')");
 
   ASSERT_EQ(1U, requested_dialogs().size());
-  TestJavaScriptDialog dialog = requested_dialogs()[0];
-  EXPECT_EQ(web_state(), dialog.web_state);
-  EXPECT_EQ(page_url(), dialog.origin_url);
-  EXPECT_EQ(JAVASCRIPT_DIALOG_TYPE_ALERT, dialog.java_script_dialog_type);
-  EXPECT_NSEQ(@"test", dialog.message_text);
-  EXPECT_FALSE(dialog.default_prompt_text);
+  auto& dialog = requested_dialogs().front();
+  EXPECT_EQ(web_state(), dialog->web_state);
+  EXPECT_EQ(page_url(), dialog->origin_url);
+  EXPECT_EQ(JAVASCRIPT_DIALOG_TYPE_ALERT, dialog->java_script_dialog_type);
+  EXPECT_NSEQ(@"test", dialog->message_text);
+  EXPECT_FALSE(dialog->default_prompt_text);
 }
 
 // Tests that window.confirm dialog is shown and its result is true.
@@ -446,12 +447,12 @@
   EXPECT_NSEQ(@YES, ExecuteJavaScript(@"confirm('test')"));
 
   ASSERT_EQ(1U, requested_dialogs().size());
-  TestJavaScriptDialog dialog = requested_dialogs()[0];
-  EXPECT_EQ(web_state(), dialog.web_state);
-  EXPECT_EQ(page_url(), dialog.origin_url);
-  EXPECT_EQ(JAVASCRIPT_DIALOG_TYPE_CONFIRM, dialog.java_script_dialog_type);
-  EXPECT_NSEQ(@"test", dialog.message_text);
-  EXPECT_FALSE(dialog.default_prompt_text);
+  auto& dialog = requested_dialogs().front();
+  EXPECT_EQ(web_state(), dialog->web_state);
+  EXPECT_EQ(page_url(), dialog->origin_url);
+  EXPECT_EQ(JAVASCRIPT_DIALOG_TYPE_CONFIRM, dialog->java_script_dialog_type);
+  EXPECT_NSEQ(@"test", dialog->message_text);
+  EXPECT_FALSE(dialog->default_prompt_text);
 }
 
 // Tests that window.confirm dialog is shown and its result is false.
@@ -461,12 +462,12 @@
   EXPECT_NSEQ(@NO, ExecuteJavaScript(@"confirm('test')"));
 
   ASSERT_EQ(1U, requested_dialogs().size());
-  TestJavaScriptDialog dialog = requested_dialogs()[0];
-  EXPECT_EQ(web_state(), dialog.web_state);
-  EXPECT_EQ(page_url(), dialog.origin_url);
-  EXPECT_EQ(JAVASCRIPT_DIALOG_TYPE_CONFIRM, dialog.java_script_dialog_type);
-  EXPECT_NSEQ(@"test", dialog.message_text);
-  EXPECT_FALSE(dialog.default_prompt_text);
+  auto& dialog = requested_dialogs().front();
+  EXPECT_EQ(web_state(), dialog->web_state);
+  EXPECT_EQ(page_url(), dialog->origin_url);
+  EXPECT_EQ(JAVASCRIPT_DIALOG_TYPE_CONFIRM, dialog->java_script_dialog_type);
+  EXPECT_NSEQ(@"test", dialog->message_text);
+  EXPECT_FALSE(dialog->default_prompt_text);
 }
 
 // Tests that window.prompt dialog is shown.
@@ -478,12 +479,12 @@
   EXPECT_NSEQ(@"Maybe", ExecuteJavaScript(@"prompt('Yes?', 'No')"));
 
   ASSERT_EQ(1U, requested_dialogs().size());
-  TestJavaScriptDialog dialog = requested_dialogs()[0];
-  EXPECT_EQ(web_state(), dialog.web_state);
-  EXPECT_EQ(page_url(), dialog.origin_url);
-  EXPECT_EQ(JAVASCRIPT_DIALOG_TYPE_PROMPT, dialog.java_script_dialog_type);
-  EXPECT_NSEQ(@"Yes?", dialog.message_text);
-  EXPECT_NSEQ(@"No", dialog.default_prompt_text);
+  auto& dialog = requested_dialogs().front();
+  EXPECT_EQ(web_state(), dialog->web_state);
+  EXPECT_EQ(page_url(), dialog->origin_url);
+  EXPECT_EQ(JAVASCRIPT_DIALOG_TYPE_PROMPT, dialog->java_script_dialog_type);
+  EXPECT_NSEQ(@"Yes?", dialog->message_text);
+  EXPECT_NSEQ(@"No", dialog->default_prompt_text);
 }
 
 INSTANTIATE_TEST_SUITES(JavaScriptDialogPresenterTest);
diff --git a/ios/web/web_state/web_state_impl.h b/ios/web/web_state/web_state_impl.h
index 4fe8983..0447bfa 100644
--- a/ios/web/web_state/web_state_impl.h
+++ b/ios/web/web_state/web_state_impl.h
@@ -15,6 +15,7 @@
 
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
 #include "base/strings/string16.h"
 #include "base/values.h"
@@ -226,6 +227,7 @@
       mojo::ScopedMessagePipeHandle interface_pipe) override;
   bool HasOpener() const override;
   void SetHasOpener(bool has_opener) override;
+  bool CanTakeSnapshot() const override;
   void TakeSnapshot(const gfx::RectF& rect, SnapshotCallback callback) override;
   void AddObserver(WebStateObserver* observer) override;
   void RemoveObserver(WebStateObserver* observer) override;
@@ -304,6 +306,13 @@
   // WebStateImpl.
   friend SessionStorageBuilder;
 
+  // Called when a dialog presented by the JavaScriptDialogPresenter is
+  // dismissed.  |original_callback| is the callback provided to
+  // RunJavaScriptDialog(), and is executed with |success| and |user_input|.
+  void JavaScriptDialogClosed(DialogClosedCallback callback,
+                              bool success,
+                              NSString* user_input);
+
   // Creates a WebUIIOS object for |url| that is owned by the caller. Returns
   // nullptr if |url| does not correspond to a WebUI page.
   std::unique_ptr<web::WebUIIOS> CreateWebUIIOS(const GURL& url);
@@ -381,6 +390,11 @@
   // fetching JavaScript.
   std::vector<web::FaviconURL> cached_favicon_urls_;
 
+  // Whether a JavaScript dialog is currently being presented.
+  bool running_javascript_dialog_ = false;
+
+  base::WeakPtrFactory<WebStateImpl> weak_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(WebStateImpl);
 };
 
diff --git a/ios/web/web_state/web_state_impl.mm b/ios/web/web_state/web_state_impl.mm
index ddfb7699..46a41f4 100644
--- a/ios/web/web_state/web_state_impl.mm
+++ b/ios/web/web_state/web_state_impl.mm
@@ -88,7 +88,8 @@
       is_being_destroyed_(false),
       web_controller_(nil),
       interstitial_(nullptr),
-      created_with_opener_(params.created_with_opener) {
+      created_with_opener_(params.created_with_opener),
+      weak_factory_(this) {
   if (web::GetWebClient()->IsSlimNavigationManagerEnabled()) {
     navigation_manager_ = std::make_unique<WKBasedNavigationManagerImpl>();
   } else {
@@ -417,9 +418,20 @@
     std::move(callback).Run(false, nil);
     return;
   }
+  running_javascript_dialog_ = true;
+  DialogClosedCallback presenter_callback =
+      base::BindOnce(&WebStateImpl::JavaScriptDialogClosed,
+                     weak_factory_.GetWeakPtr(), std::move(callback));
   presenter->RunJavaScriptDialog(this, origin_url, javascript_dialog_type,
                                  message_text, default_prompt_text,
-                                 std::move(callback));
+                                 std::move(presenter_callback));
+}
+
+void WebStateImpl::JavaScriptDialogClosed(DialogClosedCallback callback,
+                                          bool success,
+                                          NSString* user_input) {
+  running_javascript_dialog_ = false;
+  std::move(callback).Run(success, user_input);
 }
 
 WebState* WebStateImpl::CreateNewWebState(const GURL& url,
@@ -762,8 +774,15 @@
   created_with_opener_ = has_opener;
 }
 
+bool WebStateImpl::CanTakeSnapshot() const {
+  // The WKWebView snapshot API depends on IPC execution that does not function
+  // properly when JavaScript dialogs are running.
+  return !running_javascript_dialog_;
+}
+
 void WebStateImpl::TakeSnapshot(const gfx::RectF& rect,
                                 SnapshotCallback callback) {
+  DCHECK(CanTakeSnapshot());
   __block SnapshotCallback shared_callback = std::move(callback);
   [web_controller_
       takeSnapshotWithRect:rect.ToCGRect()
diff --git a/ios/web/web_state/web_state_impl_unittest.mm b/ios/web/web_state/web_state_impl_unittest.mm
index bf9ea272..93aba6f 100644
--- a/ios/web/web_state/web_state_impl_unittest.mm
+++ b/ios/web/web_state/web_state_impl_unittest.mm
@@ -30,6 +30,7 @@
 #import "ios/web/public/test/fakes/fake_navigation_context.h"
 #import "ios/web/public/test/fakes/fake_web_frame.h"
 #include "ios/web/public/test/fakes/test_browser_state.h"
+#import "ios/web/public/test/fakes/test_java_script_dialog_presenter.h"
 #import "ios/web/public/test/fakes/test_web_state_delegate.h"
 #import "ios/web/public/test/fakes/test_web_state_observer.h"
 #include "ios/web/public/test/web_test.h"
@@ -1069,6 +1070,32 @@
   EXPECT_FALSE(observer.did_change_visible_security_state_info());
 }
 
+// Tests that CanTakeSnapshot() is false when a JavaScript dialog is being
+// presented.
+TEST_P(WebStateImplTest, DisallowSnapshotsDuringDialogPresentation) {
+  TestWebStateDelegate delegate;
+  web_state_->SetDelegate(&delegate);
+
+  EXPECT_TRUE(web_state_->CanTakeSnapshot());
+
+  // Pause the callback execution to allow testing while the dialog is
+  // presented.
+  delegate.GetTestJavaScriptDialogPresenter()->set_callback_execution_paused(
+      true);
+  web_state_->RunJavaScriptDialog(GURL(), JAVASCRIPT_DIALOG_TYPE_ALERT,
+                                  @"message", @"",
+                                  base::BindOnce(^(bool, NSString*){
+                                  }));
+
+  // Verify that CanTakeSnapshot() returns no while the dialog is presented.
+  EXPECT_FALSE(web_state_->CanTakeSnapshot());
+
+  // Unpause the presenter and verify that snapshots are enabled again.
+  delegate.GetTestJavaScriptDialogPresenter()->set_callback_execution_paused(
+      false);
+  EXPECT_TRUE(web_state_->CanTakeSnapshot());
+}
+
 INSTANTIATE_TEST_SUITE_P(ProgrammaticWebStateImplTest,
                          WebStateImplTest,
                          ::testing::Values(NavigationManagerChoice::LEGACY,
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc
index 8a48c2b..4652a24 100644
--- a/media/base/media_switches.cc
+++ b/media/base/media_switches.cc
@@ -242,6 +242,11 @@
 const base::Feature kMemoryPressureBasedSourceBufferGC{
     "MemoryPressureBasedSourceBufferGC", base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Enable the instance from LinuxVideoDecoderFactory in MojoVideoDecoderService,
+// replacing VdaVideoDecoder at Chrome OS platform.
+const base::Feature kLinuxVideoDecoder{"LinuxVideoDecoder",
+                                       base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Enable The D3D11 Video decoder.
 const base::Feature kD3D11VideoDecoder{"D3D11VideoDecoder",
                                        base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/media/base/media_switches.h b/media/base/media_switches.h
index 267154b7..040a7dc 100644
--- a/media/base/media_switches.h
+++ b/media/base/media_switches.h
@@ -114,6 +114,7 @@
 MEDIA_EXPORT extern const base::Feature kMediaEngagementHTTPSOnly;
 MEDIA_EXPORT extern const base::Feature kMediaLearningExperiment;
 MEDIA_EXPORT extern const base::Feature kMemoryPressureBasedSourceBufferGC;
+MEDIA_EXPORT extern const base::Feature kLinuxVideoDecoder;
 MEDIA_EXPORT extern const base::Feature kNewEncodeCpuLoadEstimator;
 MEDIA_EXPORT extern const base::Feature kOverflowIconsForMediaControls;
 MEDIA_EXPORT extern const base::Feature kOverlayFullscreenVideo;
diff --git a/media/base/win/d3d11_mocks.cc b/media/base/win/d3d11_mocks.cc
index a2e34df5..bfaf6e5 100644
--- a/media/base/win/d3d11_mocks.cc
+++ b/media/base/win/d3d11_mocks.cc
@@ -39,6 +39,14 @@
 D3D11VideoDecoderMock::D3D11VideoDecoderMock() = default;
 D3D11VideoDecoderMock::~D3D11VideoDecoderMock() = default;
 
+D3D11VideoProcessorMock::D3D11VideoProcessorMock() = default;
+D3D11VideoProcessorMock::~D3D11VideoProcessorMock() = default;
+
+D3D11VideoProcessorEnumeratorMock::D3D11VideoProcessorEnumeratorMock() =
+    default;
+D3D11VideoProcessorEnumeratorMock::~D3D11VideoProcessorEnumeratorMock() =
+    default;
+
 D3D11CryptoSessionMock::D3D11CryptoSessionMock() = default;
 D3D11CryptoSessionMock::~D3D11CryptoSessionMock() = default;
 
diff --git a/media/base/win/d3d11_mocks.h b/media/base/win/d3d11_mocks.h
index eacb856..554daac 100644
--- a/media/base/win/d3d11_mocks.h
+++ b/media/base/win/d3d11_mocks.h
@@ -532,6 +532,56 @@
                        HRESULT(const GUID&, const IUnknown*));
 };
 
+class D3D11VideoProcessorEnumeratorMock
+    : public MockCOMInterface<ID3D11VideoProcessorEnumerator> {
+ public:
+  D3D11VideoProcessorEnumeratorMock();
+  ~D3D11VideoProcessorEnumeratorMock() override;
+
+  MOCK_STDCALL_METHOD1(GetDevice, void(ID3D11Device**));
+  MOCK_STDCALL_METHOD3(GetPrivateData, HRESULT(const GUID&, UINT*, void*));
+  MOCK_STDCALL_METHOD3(SetPrivateData, HRESULT(const GUID&, UINT, const void*));
+  MOCK_STDCALL_METHOD2(SetPrivateDataInterface,
+                       HRESULT(const GUID&, const IUnknown*));
+
+  MOCK_STDCALL_METHOD2(GetVideoProcessorRateConversionCaps,
+                       HRESULT(UINT,
+                               D3D11_VIDEO_PROCESSOR_RATE_CONVERSION_CAPS*));
+
+  MOCK_STDCALL_METHOD2(GetVideoProcessorFilterRange,
+                       HRESULT(D3D11_VIDEO_PROCESSOR_FILTER,
+                               D3D11_VIDEO_PROCESSOR_FILTER_RANGE*));
+
+  MOCK_STDCALL_METHOD3(GetVideoProcessorCustomRate,
+                       HRESULT(UINT, UINT, D3D11_VIDEO_PROCESSOR_CUSTOM_RATE*));
+
+  MOCK_STDCALL_METHOD1(GetVideoProcessorContentDesc,
+                       HRESULT(D3D11_VIDEO_PROCESSOR_CONTENT_DESC*));
+
+  MOCK_STDCALL_METHOD1(GetVideoProcessorCaps,
+                       HRESULT(D3D11_VIDEO_PROCESSOR_CAPS*));
+
+  MOCK_STDCALL_METHOD2(CheckVideoProcessorFormat, HRESULT(DXGI_FORMAT, UINT*));
+};
+
+class D3D11VideoProcessorMock : public MockCOMInterface<ID3D11VideoProcessor> {
+ public:
+  D3D11VideoProcessorMock();
+  ~D3D11VideoProcessorMock() override;
+
+  MOCK_STDCALL_METHOD1(GetDevice, void(ID3D11Device**));
+  MOCK_STDCALL_METHOD3(GetPrivateData, HRESULT(const GUID&, UINT*, void*));
+  MOCK_STDCALL_METHOD3(SetPrivateData, HRESULT(const GUID&, UINT, const void*));
+  MOCK_STDCALL_METHOD2(SetPrivateDataInterface,
+                       HRESULT(const GUID&, const IUnknown*));
+
+  MOCK_STDCALL_METHOD1(GetContentDesc,
+                       void(D3D11_VIDEO_PROCESSOR_CONTENT_DESC*));
+
+  MOCK_STDCALL_METHOD1(GetRateConversionCaps,
+                       void(D3D11_VIDEO_PROCESSOR_RATE_CONVERSION_CAPS*));
+};
+
 class D3D11VideoContextMock : public MockCOMInterface<ID3D11VideoContext> {
  public:
   D3D11VideoContextMock();
diff --git a/media/filters/BUILD.gn b/media/filters/BUILD.gn
index d08e594..13d43335 100644
--- a/media/filters/BUILD.gn
+++ b/media/filters/BUILD.gn
@@ -44,8 +44,6 @@
     "frame_buffer_pool.h",
     "frame_processor.cc",
     "frame_processor.h",
-    "gpu_video_decoder.cc",
-    "gpu_video_decoder.h",
     "memory_data_source.cc",
     "memory_data_source.h",
     "offloading_video_decoder.cc",
@@ -87,7 +85,6 @@
 
   deps = [
     "//cc/base",  # For MathUtil.
-    "//gpu/command_buffer/common",
     "//media:media_buildflags",
     "//media/base",
     "//media/cdm",
diff --git a/media/filters/gpu_video_decoder.cc b/media/filters/gpu_video_decoder.cc
deleted file mode 100644
index 19b1a1e1..0000000
--- a/media/filters/gpu_video_decoder.cc
+++ /dev/null
@@ -1,962 +0,0 @@
-// Copyright (c) 2012 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 "media/filters/gpu_video_decoder.h"
-
-#include <algorithm>
-#include <array>
-#include <cinttypes>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/callback_helpers.h"
-#include "base/command_line.h"
-#include "base/cpu.h"
-#include "base/location.h"
-#include "base/memory/ptr_util.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/task_runner_util.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/trace_event/memory_dump_manager.h"
-#include "base/trace_event/process_memory_dump.h"
-#include "build/build_config.h"
-#include "gpu/command_buffer/client/context_support.h"
-#include "gpu/command_buffer/common/mailbox_holder.h"
-#include "media/base/bind_to_current_loop.h"
-#include "media/base/cdm_context.h"
-#include "media/base/decoder_buffer.h"
-#include "media/base/media_log.h"
-#include "media/base/media_switches.h"
-#include "media/base/pipeline_status.h"
-#include "media/base/video_decoder_config.h"
-#include "media/base/video_util.h"
-#include "media/media_buildflags.h"
-#include "media/video/gpu_video_accelerator_factories.h"
-#include "media/video/trace_util.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-
-#if defined(OS_ANDROID) && BUILDFLAG(USE_PROPRIETARY_CODECS)
-#include "media/base/android/extract_sps_and_pps.h"
-#endif
-
-namespace media {
-const char GpuVideoDecoder::kDecoderName[] = "GpuVideoDecoder";
-
-// Maximum number of concurrent VDA::Decode() operations GVD will maintain.
-// Higher values allow better pipelining in the GPU, but also require more
-// resources.
-enum { kMaxInFlightDecodes = 4 };
-
-// Number of bitstream buffers returned before GC is attempted on shared memory
-// segments. Value chosen arbitrarily.
-enum { kBufferCountBeforeGC = 1024 };
-
-struct GpuVideoDecoder::PendingDecoderBuffer {
-  PendingDecoderBuffer(std::unique_ptr<base::SharedMemory> s, DecodeCB done_cb)
-      : shared_memory(std::move(s)), done_cb(std::move(done_cb)) {}
-  std::unique_ptr<base::SharedMemory> shared_memory;
-  DecodeCB done_cb;
-};
-
-GpuVideoDecoder::BufferData::BufferData(int32_t bbid,
-                                        base::TimeDelta ts,
-                                        const gfx::Rect& vr,
-                                        const gfx::Size& ns)
-    : bitstream_buffer_id(bbid),
-      timestamp(ts),
-      visible_rect(vr),
-      natural_size(ns) {}
-
-GpuVideoDecoder::BufferData::~BufferData() = default;
-
-GpuVideoDecoder::GpuVideoDecoder(
-    GpuVideoAcceleratorFactories* factories,
-    const RequestOverlayInfoCB& request_overlay_info_cb,
-    const gfx::ColorSpace& target_color_space,
-    MediaLog* media_log)
-    : needs_bitstream_conversion_(false),
-      factories_(factories),
-      request_overlay_info_cb_(request_overlay_info_cb),
-      overlay_info_requested_(false),
-      target_color_space_(target_color_space),
-      media_log_(media_log),
-      vda_initialized_(false),
-      state_(kNormal),
-      next_picture_buffer_id_(0),
-      next_bitstream_buffer_id_(0),
-      needs_all_picture_buffers_to_decode_(false),
-      supports_deferred_initialization_(false),
-      requires_texture_copy_(false),
-      cdm_id_(CdmContext::kInvalidCdmId),
-      min_shared_memory_segment_size_(0),
-      bitstream_buffer_id_of_last_gc_(0),
-      weak_factory_(this) {
-  DCHECK(factories_);
-  base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
-      this, "media::GpuVideoDecoder", base::ThreadTaskRunnerHandle::Get());
-}
-
-void GpuVideoDecoder::Reset(base::OnceClosure closure) {
-  DVLOG(3) << "Reset()";
-  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
-
-  if (state_ == kDrainingDecoder) {
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE,
-        base::BindOnce(&GpuVideoDecoder::Reset, weak_factory_.GetWeakPtr(),
-                       std::move(closure)));
-    return;
-  }
-
-  if (!vda_) {
-    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
-                                                  std::move(closure));
-    return;
-  }
-
-  DCHECK(!pending_reset_cb_);
-  pending_reset_cb_ = BindToCurrentLoop(std::move(closure));
-
-  vda_->Reset();
-}
-
-static bool IsCodedSizeSupported(const gfx::Size& coded_size,
-                                 const gfx::Size& min_resolution,
-                                 const gfx::Size& max_resolution) {
-  return (coded_size.width() <= max_resolution.width() &&
-          coded_size.height() <= max_resolution.height() &&
-          coded_size.width() >= min_resolution.width() &&
-          coded_size.height() >= min_resolution.height());
-}
-
-// Report |success| to UMA and run |cb| with it.  This is super-specific to the
-// UMA stat reported because the UMA_HISTOGRAM_ENUMERATION API requires a
-// callsite to always be called with the same stat name (can't parameterize it).
-static void ReportGpuVideoDecoderInitializeStatusToUMAAndRunCB(
-    VideoDecoder::InitCB cb,
-    MediaLog* media_log,
-    bool success) {
-  // TODO(xhwang): Report |success| directly.
-  PipelineStatus status = success ? PIPELINE_OK : DECODER_ERROR_NOT_SUPPORTED;
-  UMA_HISTOGRAM_ENUMERATION("Media.GpuVideoDecoderInitializeStatus", status,
-                            PIPELINE_STATUS_MAX + 1);
-
-  if (!success) {
-    media_log->RecordRapporWithSecurityOrigin(
-        "Media.OriginUrl.GpuVideoDecoderInitFailure");
-  }
-
-  std::move(cb).Run(success);
-}
-
-bool GpuVideoDecoder::IsPlatformDecoder() const {
-  return true;
-}
-
-std::string GpuVideoDecoder::GetDisplayName() const {
-  return kDecoderName;
-}
-
-void GpuVideoDecoder::Initialize(const VideoDecoderConfig& config,
-                                 bool /* low_delay */,
-                                 CdmContext* cdm_context,
-                                 InitCB init_cb,
-                                 const OutputCB& output_cb,
-                                 const WaitingCB& /* waiting_cb */) {
-  DVLOG(3) << "Initialize()";
-  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
-  DCHECK(config.IsValidConfig());
-
-  InitCB bound_init_cb =
-      base::BindOnce(&ReportGpuVideoDecoderInitializeStatusToUMAAndRunCB,
-                     BindToCurrentLoop(std::move(init_cb)), media_log_);
-
-  bool previously_initialized = config_.IsValidConfig();
-  DVLOG(1) << (previously_initialized ? "Reinitializing" : "Initializing")
-           << " GVD with config: " << config.AsHumanReadableString();
-
-  auto encryption_mode = config.encryption_scheme().mode();
-  if (encryption_mode != EncryptionScheme::CIPHER_MODE_UNENCRYPTED &&
-      encryption_mode != EncryptionScheme::CIPHER_MODE_AES_CTR) {
-    DVLOG(1) << "VDAs only support clear or cenc encrypted streams.";
-    std::move(bound_init_cb).Run(false);
-    return;
-  }
-
-  // Disallow codec changes between configuration changes.
-  if (previously_initialized && config_.codec() != config.codec()) {
-    DVLOG(1) << "Codec changed, cannot reinitialize.";
-    std::move(bound_init_cb).Run(false);
-    return;
-  }
-
-  // TODO(sandersd): This should be moved to capabilities if we ever have a
-  // hardware decoder which supports alpha formats.
-  if (config.format() == PIXEL_FORMAT_I420A) {
-    DVLOG(1) << "Alpha transparency formats are not supported.";
-    std::move(bound_init_cb).Run(false);
-    return;
-  }
-
-  VideoDecodeAccelerator::Capabilities capabilities =
-      factories_->GetVideoDecodeAcceleratorCapabilities();
-
-  const bool supports_encrypted_streams =
-      capabilities.flags &
-      VideoDecodeAccelerator::Capabilities::SUPPORTS_ENCRYPTED_STREAMS;
-  if (config.is_encrypted() && (!cdm_context || !supports_encrypted_streams)) {
-    DVLOG(1) << "Encrypted stream not supported.";
-    std::move(bound_init_cb).Run(false);
-    return;
-  }
-
-  if (!IsProfileSupported(capabilities, config.profile(), config.coded_size(),
-                          config.is_encrypted())) {
-    DVLOG(1) << "Unsupported profile " << GetProfileName(config.profile())
-             << ", unsupported coded size " << config.coded_size().ToString()
-             << ", or accelerator should only be used for encrypted content. "
-             << " is_encrypted: " << (config.is_encrypted() ? "yes." : "no.");
-    std::move(bound_init_cb).Run(false);
-    return;
-  }
-
-  config_ = config;
-  needs_all_picture_buffers_to_decode_ =
-      capabilities.flags &
-      VideoDecodeAccelerator::Capabilities::NEEDS_ALL_PICTURE_BUFFERS_TO_DECODE;
-  needs_bitstream_conversion_ =
-      (config.codec() == kCodecH264) || (config.codec() == kCodecHEVC);
-  requires_texture_copy_ =
-      !!(capabilities.flags &
-         VideoDecodeAccelerator::Capabilities::REQUIRES_TEXTURE_COPY);
-  supports_deferred_initialization_ = !!(
-      capabilities.flags &
-      VideoDecodeAccelerator::Capabilities::SUPPORTS_DEFERRED_INITIALIZATION);
-  output_cb_ = output_cb;
-
-  // Attempt to choose a reasonable size for the shared memory segments based on
-  // the size of video. These values are chosen based on experiments with common
-  // videos from the web. Too small and you'll end up creating too many segments
-  // too large and you end up wasting significant amounts of memory.
-  const int height = config.coded_size().height();
-  if (height >= 4000)  // ~4320p
-    min_shared_memory_segment_size_ = 384 * 1024;
-  else if (height >= 2000)  // ~2160p
-    min_shared_memory_segment_size_ = 192 * 1024;
-  else if (height >= 1000)  // ~1080p
-    min_shared_memory_segment_size_ = 96 * 1024;
-  else if (height >= 700)  // ~720p
-    min_shared_memory_segment_size_ = 72 * 1024;
-  else if (height >= 400)  // ~480p
-    min_shared_memory_segment_size_ = 48 * 1024;
-  else  // ~360p or less
-    min_shared_memory_segment_size_ = 32 * 1024;
-
-  if (config.is_encrypted() && !supports_deferred_initialization_) {
-    DVLOG(1) << __func__
-             << " Encrypted stream requires deferred initialialization.";
-    std::move(bound_init_cb).Run(false);
-    return;
-  }
-
-  if (previously_initialized) {
-    DVLOG(3) << __func__
-             << " Expecting initialized VDA to detect in-stream config change.";
-    // Reinitialization with a different config (but same codec and profile).
-    // VDA should handle it by detecting this in-stream by itself,
-    // no need to notify it.
-    std::move(bound_init_cb).Run(true);
-    return;
-  }
-
-  vda_ = factories_->CreateVideoDecodeAccelerator();
-  if (!vda_) {
-    DVLOG(1) << "Failed to create a VDA.";
-    std::move(bound_init_cb).Run(false);
-    return;
-  }
-
-  if (cdm_context)
-    cdm_id_ = cdm_context->GetCdmId();
-
-  if (config.is_encrypted() && cdm_id_ == CdmContext::kInvalidCdmId) {
-    DVLOG(1) << "CDM ID not available.";
-    std::move(bound_init_cb).Run(false);
-    return;
-  }
-
-  init_cb_ = std::move(bound_init_cb);
-
-  const bool supports_external_output_surface = !!(
-      capabilities.flags &
-      VideoDecodeAccelerator::Capabilities::SUPPORTS_EXTERNAL_OUTPUT_SURFACE);
-  if (supports_external_output_surface && request_overlay_info_cb_) {
-    const bool requires_restart_for_external_output_surface =
-        !(capabilities.flags & VideoDecodeAccelerator::Capabilities::
-                                   SUPPORTS_SET_EXTERNAL_OUTPUT_SURFACE);
-
-    // If we have a surface request callback we should call it and complete
-    // initialization with the returned surface.
-    request_overlay_info_cb_.Run(
-        requires_restart_for_external_output_surface,
-        BindToCurrentLoop(base::Bind(&GpuVideoDecoder::OnOverlayInfoAvailable,
-                                     weak_factory_.GetWeakPtr())));
-    overlay_info_requested_ = true;
-    return;
-  }
-
-  // If external surfaces are not supported we can complete initialization now.
-  CompleteInitialization(OverlayInfo());
-}
-
-// OnOverlayInfoAvailable() might be called at any time between Initialize() and
-// ~GpuVideoDecoder() so we have to be careful to not make assumptions about
-// the current state.
-// At most one of |surface_id| and |token| should be provided.  The other will
-// be kNoSurfaceID or an empty token, respectively.
-void GpuVideoDecoder::OnOverlayInfoAvailable(const OverlayInfo& overlay_info) {
-  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
-
-  if (!vda_)
-    return;
-
-  // If the VDA has not been initialized, we were waiting for the first surface
-  // so it can be passed to Initialize() via the config. We can't call
-  // SetSurface() before initializing because there is no remote VDA to handle
-  // the call yet.
-  if (!vda_initialized_) {
-    CompleteInitialization(overlay_info);
-    return;
-  }
-
-  // The VDA must be already initialized (or async initialization is in
-  // progress) so we can call SetSurface().
-  vda_->SetOverlayInfo(overlay_info);
-}
-
-void GpuVideoDecoder::CompleteInitialization(const OverlayInfo& overlay_info) {
-  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
-  DCHECK(vda_);
-  DCHECK(init_cb_);
-  DCHECK(!vda_initialized_);
-
-  VideoDecodeAccelerator::Config vda_config;
-  vda_config.profile = config_.profile();
-  vda_config.cdm_id = cdm_id_;
-  vda_config.overlay_info = overlay_info;
-  vda_config.encryption_scheme = config_.encryption_scheme();
-  vda_config.is_deferred_initialization_allowed = true;
-  vda_config.initial_expected_coded_size = config_.coded_size();
-  vda_config.container_color_space = config_.color_space_info();
-  vda_config.target_color_space = target_color_space_;
-  vda_config.hdr_metadata = config_.hdr_metadata();
-
-#if defined(OS_ANDROID) && BUILDFLAG(USE_PROPRIETARY_CODECS)
-  // We pass the SPS and PPS on Android because it lets us initialize
-  // MediaCodec more reliably (http://crbug.com/649185).
-  if (config_.codec() == kCodecH264)
-    ExtractSpsAndPps(config_.extra_data(), &vda_config.sps, &vda_config.pps);
-#endif
-
-  vda_initialized_ = true;
-  if (!vda_->Initialize(vda_config, this)) {
-    DVLOG(1) << "VDA::Initialize failed.";
-    // It's important to set |vda_| to null so that OnSurfaceAvailable() will
-    // not call SetSurface() on a nonexistent remote VDA.
-    DestroyVDA();
-    std::move(init_cb_).Run(false);
-    return;
-  }
-
-  // If deferred initialization is not supported, initialization is complete.
-  // Otherwise, a call to NotifyInitializationComplete will follow with the
-  // result of deferred initialization.
-  if (!supports_deferred_initialization_)
-    std::move(init_cb_).Run(true);
-}
-
-void GpuVideoDecoder::NotifyInitializationComplete(bool success) {
-  DVLOG_IF(1, !success) << __func__ << " Deferred initialization failed.";
-
-  if (init_cb_)
-    std::move(init_cb_).Run(success);
-}
-
-void GpuVideoDecoder::DestroyPictureBuffers() {
-  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
-
-  for (const auto& kv : assigned_picture_buffers_) {
-    int64_t picture_buffer_id = kv.first;
-    PictureBuffer::TextureIds texture_ids = kv.second.client_texture_ids();
-
-    // Not destroying PictureBuffers in |picture_buffers_at_display_| yet, since
-    // their textures may still be in use by the user of this GpuVideoDecoder.
-    if (picture_buffers_at_display_.find(picture_buffer_id) ==
-        picture_buffers_at_display_.end()) {
-      for (uint32_t id : texture_ids)
-        factories_->DeleteTexture(id);
-    }
-  }
-  factories_->ShallowFlushCHROMIUM();
-  assigned_picture_buffers_.clear();
-}
-
-void GpuVideoDecoder::DestroyVDA() {
-  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
-
-  vda_.reset();
-
-  DestroyPictureBuffers();
-}
-
-void GpuVideoDecoder::Decode(scoped_refptr<DecoderBuffer> buffer,
-                             DecodeCB decode_cb) {
-  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
-  DCHECK(!pending_reset_cb_);
-
-  DVLOG(3) << __func__ << " " << buffer->AsHumanReadableString();
-
-  if (state_ == kError || !vda_) {
-    BindToCurrentLoop(std::move(decode_cb)).Run(DecodeStatus::DECODE_ERROR);
-    return;
-  }
-
-  switch (state_) {
-    case kDecoderDrained:
-      state_ = kNormal;
-      FALLTHROUGH;
-    case kNormal:
-      break;
-    case kDrainingDecoder:
-    case kError:
-      NOTREACHED();
-      return;
-  }
-
-  DCHECK_EQ(state_, kNormal);
-
-  if (buffer->end_of_stream()) {
-    DVLOG(3) << __func__ << " Initiating Flush for EOS.";
-    state_ = kDrainingDecoder;
-    eos_decode_cb_ = BindToCurrentLoop(std::move(decode_cb));
-    vda_->Flush();
-    return;
-  }
-
-  size_t size = buffer->data_size();
-  auto shared_memory = GetSharedMemory(size);
-  if (!shared_memory) {
-    BindToCurrentLoop(std::move(decode_cb)).Run(DecodeStatus::DECODE_ERROR);
-    return;
-  }
-
-  memcpy(shared_memory->memory(), buffer->data(), size);
-  BitstreamBuffer bitstream_buffer(
-      next_bitstream_buffer_id_, shared_memory->handle(), false /* read_only */,
-      size, 0, buffer->timestamp());
-
-  if (buffer->decrypt_config()) {
-    bitstream_buffer.SetDecryptionSettings(
-        buffer->decrypt_config()->key_id(), buffer->decrypt_config()->iv(),
-        buffer->decrypt_config()->subsamples());
-  }
-
-  // Mask against 30 bits, to avoid (undefined) wraparound on signed integer.
-  next_bitstream_buffer_id_ = (next_bitstream_buffer_id_ + 1) & 0x3FFFFFFF;
-  DCHECK(
-      !base::ContainsKey(bitstream_buffers_in_decoder_, bitstream_buffer.id()));
-  RecordBufferData(bitstream_buffer, *buffer);
-
-  bitstream_buffers_in_decoder_.emplace(
-      bitstream_buffer.id(),
-      PendingDecoderBuffer(std::move(shared_memory), std::move(decode_cb)));
-  DCHECK_LE(static_cast<int>(bitstream_buffers_in_decoder_.size()),
-            kMaxInFlightDecodes);
-
-  vda_->Decode(std::move(bitstream_buffer));
-}
-
-void GpuVideoDecoder::RecordBufferData(const BitstreamBuffer& bitstream_buffer,
-                                       const DecoderBuffer& buffer) {
-  input_buffer_data_.push_front(
-      BufferData(bitstream_buffer.id(), buffer.timestamp(),
-                 config_.visible_rect(), config_.natural_size()));
-  // Why this value?  Because why not.  avformat.h:MAX_REORDER_DELAY is 16, but
-  // that's too small for some pathological B-frame test videos.  The cost of
-  // using too-high a value is low (192 bits per extra slot).
-  static const size_t kMaxInputBufferDataSize = 128;
-  // Pop from the back of the list, because that's the oldest and least likely
-  // to be useful in the future data.
-  if (input_buffer_data_.size() > kMaxInputBufferDataSize)
-    input_buffer_data_.pop_back();
-}
-
-void GpuVideoDecoder::GetBufferData(int32_t id,
-                                    base::TimeDelta* timestamp,
-                                    gfx::Rect* visible_rect,
-                                    gfx::Size* natural_size) {
-  for (std::list<BufferData>::const_iterator it = input_buffer_data_.begin();
-       it != input_buffer_data_.end(); ++it) {
-    if (it->bitstream_buffer_id != id)
-      continue;
-    *timestamp = it->timestamp;
-    *visible_rect = it->visible_rect;
-    *natural_size = it->natural_size;
-    return;
-  }
-  NOTREACHED() << "Missing bitstreambuffer id: " << id;
-}
-
-bool GpuVideoDecoder::NeedsBitstreamConversion() const {
-  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
-  return needs_bitstream_conversion_;
-}
-
-bool GpuVideoDecoder::CanReadWithoutStalling() const {
-  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
-  size_t available_pictures = AvailablePictures();
-  return next_picture_buffer_id_ ==
-             0 ||  // Decode() will ProvidePictureBuffers().
-         (!needs_all_picture_buffers_to_decode_ && available_pictures > 0) ||
-         available_pictures == assigned_picture_buffers_.size();
-}
-
-size_t GpuVideoDecoder::AvailablePictures() const {
-  size_t ret = 0;
-  for (const auto& kv : assigned_picture_buffers_) {
-    if (picture_buffers_at_display_.find(kv.first) ==
-        picture_buffers_at_display_.end()) {
-      ++ret;
-    }
-  }
-  return ret;
-}
-
-int GpuVideoDecoder::GetMaxDecodeRequests() const {
-  return kMaxInFlightDecodes;
-}
-
-void GpuVideoDecoder::ProvidePictureBuffers(uint32_t count,
-                                            VideoPixelFormat format,
-                                            uint32_t textures_per_buffer,
-                                            const gfx::Size& size,
-                                            uint32_t texture_target) {
-  DVLOG(3) << "ProvidePictureBuffers(" << count << ", " << size.width() << "x"
-           << size.height() << ")";
-  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
-
-  std::vector<uint32_t> texture_ids;
-  std::vector<gpu::Mailbox> texture_mailboxes;
-
-  if (format == PIXEL_FORMAT_UNKNOWN) {
-    format = IsOpaque(config_.format()) ? PIXEL_FORMAT_XRGB : PIXEL_FORMAT_ARGB;
-  }
-
-  if (!factories_->CreateTextures(count * textures_per_buffer, size,
-                                  &texture_ids, &texture_mailboxes,
-                                  texture_target)) {
-    NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE);
-    return;
-  }
-
-  sync_token_ = factories_->CreateSyncToken();
-  DCHECK_EQ(count * textures_per_buffer, texture_ids.size());
-  DCHECK_EQ(count * textures_per_buffer, texture_mailboxes.size());
-
-  if (!vda_)
-    return;
-
-  std::vector<PictureBuffer> picture_buffers;
-  size_t index = 0;
-  for (size_t i = 0; i < count; ++i) {
-    PictureBuffer::TextureIds ids;
-    std::vector<gpu::Mailbox> mailboxes;
-    for (size_t j = 0; j < textures_per_buffer; j++) {
-      ids.push_back(texture_ids[index]);
-      mailboxes.push_back(texture_mailboxes[index]);
-      index++;
-    }
-
-    picture_buffers.push_back(PictureBuffer(next_picture_buffer_id_++, size,
-                                            ids, mailboxes, texture_target,
-                                            format));
-    bool inserted = assigned_picture_buffers_
-                        .insert(std::make_pair(picture_buffers.back().id(),
-                                               picture_buffers.back()))
-                        .second;
-    DCHECK(inserted);
-  }
-
-  vda_->AssignPictureBuffers(picture_buffers);
-}
-
-void GpuVideoDecoder::DismissPictureBuffer(int32_t id) {
-  DVLOG(3) << "DismissPictureBuffer(" << id << ")";
-  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
-
-  auto it = assigned_picture_buffers_.find(id);
-  if (it == assigned_picture_buffers_.end()) {
-    NOTREACHED() << "Missing picture buffer: " << id;
-    return;
-  }
-
-  // If it's in |picture_buffers_at_display_|, postpone deletion of it until
-  // it's returned to us.
-  if (picture_buffers_at_display_.find(id) ==
-      picture_buffers_at_display_.end()) {
-    for (const auto texture_id : (it->second).client_texture_ids())
-      factories_->DeleteTexture(texture_id);
-  }
-
-  assigned_picture_buffers_.erase(it);
-}
-
-void GpuVideoDecoder::PictureReady(const media::Picture& picture) {
-  DVLOG(3) << "PictureReady()";
-  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
-
-  auto it = assigned_picture_buffers_.find(picture.picture_buffer_id());
-  if (it == assigned_picture_buffers_.end()) {
-    DLOG(ERROR) << "Missing picture buffer: " << picture.picture_buffer_id();
-    NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE);
-    return;
-  }
-  PictureBuffer& pb = it->second;
-  if (picture.size_changed()) {
-    // Update the PictureBuffer size to match that of the Picture. Some VDA's
-    // (e.g. Android) will handle resolution changes internally without
-    // requesting new PictureBuffers. Sending a Picture of unmatched size is
-    // the signal that we should update the size of our PictureBuffer.
-    DCHECK(pb.size() != picture.visible_rect().size());
-    DVLOG(3) << __func__ << " Updating size of PictureBuffer[" << pb.id()
-             << "] from:" << pb.size().ToString()
-             << " to:" << picture.visible_rect().size().ToString();
-    pb.set_size(picture.visible_rect().size());
-  }
-
-  // Update frame's timestamp.
-  base::TimeDelta timestamp;
-  // Some of the VDAs like DXVA, and VTVDA don't support and thus don't provide
-  // us with visible size in picture.size, passing (0, 0) instead, so for those
-  // cases drop it and use config information instead.
-  gfx::Rect visible_rect;
-  gfx::Size natural_size;
-  GetBufferData(picture.bitstream_buffer_id(), &timestamp, &visible_rect,
-                &natural_size);
-
-  double pixel_aspect_ratio = GetPixelAspectRatio(visible_rect, natural_size);
-  if (!picture.visible_rect().IsEmpty()) {
-    visible_rect = picture.visible_rect();
-    natural_size = GetNaturalSize(visible_rect, pixel_aspect_ratio);
-  }
-  if (!gfx::Rect(pb.size()).Contains(visible_rect)) {
-    LOG(WARNING) << "Visible size " << visible_rect.ToString()
-                 << " is larger than coded size " << pb.size().ToString();
-    visible_rect.Intersect(gfx::Rect(pb.size()));
-    natural_size = GetNaturalSize(visible_rect, pixel_aspect_ratio);
-  }
-
-  DCHECK(pb.texture_target());
-
-  gpu::MailboxHolder mailbox_holders[VideoFrame::kMaxPlanes];
-  for (size_t i = 0; i < pb.client_texture_ids().size(); ++i) {
-    mailbox_holders[i] = gpu::MailboxHolder(pb.texture_mailbox(i), sync_token_,
-                                            pb.texture_target());
-  }
-
-  scoped_refptr<VideoFrame> frame(VideoFrame::WrapNativeTextures(
-      pb.pixel_format(), mailbox_holders,
-      // Always post ReleaseMailbox to avoid deadlock with the compositor when
-      // releasing video frames on the media thread; http://crbug.com/710209.
-      BindToCurrentLoop(base::Bind(
-          &GpuVideoDecoder::ReleaseMailbox, weak_factory_.GetWeakPtr(),
-          factories_, picture.picture_buffer_id(), pb.client_texture_ids())),
-      pb.size(), visible_rect, natural_size, timestamp));
-  if (!frame) {
-    DLOG(ERROR) << "Create frame failed for: " << picture.picture_buffer_id();
-    NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE);
-    return;
-  }
-  frame->set_color_space(picture.color_space());
-  if (picture.allow_overlay())
-    frame->metadata()->SetBoolean(VideoFrameMetadata::ALLOW_OVERLAY, true);
-  if (picture.read_lock_fences_enabled()) {
-    frame->metadata()->SetBoolean(VideoFrameMetadata::READ_LOCK_FENCES_ENABLED,
-                                  true);
-  }
-  if (picture.texture_owner())
-    frame->metadata()->SetBoolean(VideoFrameMetadata::TEXTURE_OWNER, true);
-  if (picture.wants_promotion_hint()) {
-    frame->metadata()->SetBoolean(VideoFrameMetadata::WANTS_PROMOTION_HINT,
-                                  true);
-  }
-
-  if (requires_texture_copy_)
-    frame->metadata()->SetBoolean(VideoFrameMetadata::COPY_REQUIRED, true);
-
-  picture_buffers_at_display_.insert(
-      std::make_pair(picture.picture_buffer_id(), pb.client_texture_ids()));
-
-  DeliverFrame(frame);
-}
-
-void GpuVideoDecoder::DeliverFrame(scoped_refptr<VideoFrame> frame) {
-  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
-
-  // During a pending vda->Reset(), we don't accumulate frames.  Drop it on the
-  // floor and return.
-  if (pending_reset_cb_)
-    return;
-
-  frame->metadata()->SetBoolean(VideoFrameMetadata::POWER_EFFICIENT, true);
-
-  output_cb_.Run(std::move(frame));
-}
-
-// static
-void GpuVideoDecoder::ReleaseMailbox(
-    base::WeakPtr<GpuVideoDecoder> decoder,
-    media::GpuVideoAcceleratorFactories* factories,
-    int64_t picture_buffer_id,
-    PictureBuffer::TextureIds ids,
-    const gpu::SyncToken& release_sync_token) {
-  DCHECK(factories->GetTaskRunner()->BelongsToCurrentThread());
-  factories->WaitSyncToken(release_sync_token);
-
-  if (decoder) {
-    decoder->ReusePictureBuffer(picture_buffer_id);
-    return;
-  }
-  // It's the last chance to delete the texture after display,
-  // because GpuVideoDecoder was destructed.
-  for (uint32_t id : ids)
-    factories->DeleteTexture(id);
-
-  // Flush the delete(s) to the server, to avoid crbug.com/737992 .
-  factories->ShallowFlushCHROMIUM();
-}
-
-void GpuVideoDecoder::ReusePictureBuffer(int64_t picture_buffer_id) {
-  DVLOG(3) << "ReusePictureBuffer(" << picture_buffer_id << ")";
-  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
-
-  auto iter_range = picture_buffers_at_display_.equal_range(picture_buffer_id);
-  DCHECK(iter_range.first != iter_range.second);
-  bool only_one_element = (std::next(iter_range.first) == iter_range.second);
-  PictureBuffer::TextureIds ids = iter_range.first->second;
-  picture_buffers_at_display_.erase(iter_range.first);
-
-  if (only_one_element && assigned_picture_buffers_.find(picture_buffer_id) ==
-                              assigned_picture_buffers_.end()) {
-    // This picture was dismissed while in display, so we postponed deletion.
-    for (const auto id : ids)
-      factories_->DeleteTexture(id);
-    return;
-  }
-
-  // DestroyVDA() might already have been called.
-  if (vda_)
-    vda_->ReusePictureBuffer(picture_buffer_id);
-}
-
-std::unique_ptr<base::SharedMemory> GpuVideoDecoder::GetSharedMemory(
-    size_t min_size) {
-  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
-  auto it = std::lower_bound(available_shm_segments_.begin(),
-                             available_shm_segments_.end(), min_size,
-                             [](const ShMemEntry& entry, const size_t size) {
-                               return entry.first->mapped_size() < size;
-                             });
-  if (it != available_shm_segments_.end()) {
-    auto ret = std::move(it->first);
-    available_shm_segments_.erase(it);
-    return ret;
-  }
-
-  return factories_->CreateSharedMemory(
-      std::max(min_shared_memory_segment_size_, min_size));
-}
-
-void GpuVideoDecoder::PutSharedMemory(
-    std::unique_ptr<base::SharedMemory> shared_memory,
-    int32_t last_bitstream_buffer_id) {
-  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
-  available_shm_segments_.emplace(std::move(shared_memory),
-                                  last_bitstream_buffer_id);
-
-  if (next_bitstream_buffer_id_ < bitstream_buffer_id_of_last_gc_ ||
-      next_bitstream_buffer_id_ - bitstream_buffer_id_of_last_gc_ >
-          kBufferCountBeforeGC) {
-    base::EraseIf(available_shm_segments_, [this](const ShMemEntry& entry) {
-      // Check for overflow rollover...
-      if (next_bitstream_buffer_id_ < entry.second)
-        return next_bitstream_buffer_id_ > kBufferCountBeforeGC;
-
-      return next_bitstream_buffer_id_ - entry.second > kBufferCountBeforeGC;
-    });
-    bitstream_buffer_id_of_last_gc_ = next_bitstream_buffer_id_;
-  }
-}
-
-void GpuVideoDecoder::NotifyEndOfBitstreamBuffer(int32_t id) {
-  DVLOG(3) << "NotifyEndOfBitstreamBuffer(" << id << ")";
-  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
-
-  auto it = bitstream_buffers_in_decoder_.find(id);
-  if (it == bitstream_buffers_in_decoder_.end()) {
-    NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE);
-    NOTREACHED() << "Missing bitstream buffer: " << id;
-    return;
-  }
-
-  PutSharedMemory(std::move(it->second.shared_memory), id);
-  std::move(it->second.done_cb)
-      .Run(state_ == kError ? DecodeStatus::DECODE_ERROR : DecodeStatus::OK);
-  bitstream_buffers_in_decoder_.erase(it);
-}
-
-GpuVideoDecoder::~GpuVideoDecoder() {
-  DVLOG(3) << __func__;
-  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
-
-  base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
-      this);
-
-  if (vda_)
-    DestroyVDA();
-  DCHECK(assigned_picture_buffers_.empty());
-
-  if (init_cb_)
-    std::move(init_cb_).Run(false);
-  if (request_overlay_info_cb_ && overlay_info_requested_) {
-    std::move(request_overlay_info_cb_).Run(false, ProvideOverlayInfoCB());
-  }
-
-  for (auto& pair : bitstream_buffers_in_decoder_)
-    std::move(pair.second.done_cb).Run(DecodeStatus::ABORTED);
-  bitstream_buffers_in_decoder_.clear();
-
-  if (pending_reset_cb_)
-    std::move(pending_reset_cb_).Run();
-}
-
-void GpuVideoDecoder::NotifyFlushDone() {
-  DVLOG(3) << "NotifyFlushDone()";
-  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
-  DCHECK_EQ(state_, kDrainingDecoder);
-  state_ = kDecoderDrained;
-  std::move(eos_decode_cb_).Run(DecodeStatus::OK);
-
-  // Assume flush is for a config change, so drop shared memory segments in
-  // anticipation of a resize occurring.
-  available_shm_segments_.clear();
-}
-
-void GpuVideoDecoder::NotifyResetDone() {
-  DVLOG(3) << "NotifyResetDone()";
-  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
-  DCHECK(bitstream_buffers_in_decoder_.empty());
-
-  // This needs to happen after the Reset() on vda_ is done to ensure pictures
-  // delivered during the reset can find their time data.
-  input_buffer_data_.clear();
-
-  if (pending_reset_cb_)
-    std::move(pending_reset_cb_).Run();
-}
-
-void GpuVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) {
-  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
-  if (!vda_)
-    return;
-
-  if (init_cb_)
-    std::move(init_cb_).Run(false);
-
-  // If we have any bitstream buffers, then notify one that an error has
-  // occurred.  This guarantees that somebody finds out about the error.  If
-  // we don't do this, and if the max decodes are already in flight, then there
-  // won't be another decode request to report the error.
-  if (!bitstream_buffers_in_decoder_.empty()) {
-    auto it = bitstream_buffers_in_decoder_.begin();
-    std::move(it->second.done_cb).Run(DecodeStatus::DECODE_ERROR);
-    bitstream_buffers_in_decoder_.erase(it);
-  }
-
-  if (state_ == kDrainingDecoder)
-    std::move(eos_decode_cb_).Run(DecodeStatus::DECODE_ERROR);
-
-  state_ = kError;
-
-  DLOG(ERROR) << "VDA Error: " << error;
-  UMA_HISTOGRAM_ENUMERATION("Media.GpuVideoDecoderError", error,
-                            media::VideoDecodeAccelerator::ERROR_MAX + 1);
-
-  DestroyVDA();
-}
-
-bool GpuVideoDecoder::OnMemoryDump(
-    const base::trace_event::MemoryDumpArgs& args,
-    base::trace_event::ProcessMemoryDump* pmd) {
-  using base::trace_event::MemoryAllocatorDump;
-  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
-  if (assigned_picture_buffers_.empty())
-    return false;
-
-  if (!factories_)
-    return false;
-  auto* context_support = factories_->GetMediaContextProviderContextSupport();
-  if (!context_support)
-    return false;
-  const uint64_t context_group_tracing_id =
-      context_support->ShareGroupTracingGUID();
-
-  for (const auto& picture_buffer : assigned_picture_buffers_) {
-    PictureBuffer::TextureIds texture_ids =
-        picture_buffer.second.client_texture_ids();
-
-    for (uint32_t id : texture_ids) {
-      const auto dump_name = base::StringPrintf(
-          "gpu/video_decoding/context_group_0x%" PRIx64 "/texture_0x%" PRIX32,
-          context_group_tracing_id, id);
-      MemoryAllocatorDump* dump = pmd->CreateAllocatorDump(dump_name);
-      dump->AddScalar(
-          MemoryAllocatorDump::kNameSize, MemoryAllocatorDump::kUnitsBytes,
-          static_cast<uint64_t>(picture_buffer.second.size().GetArea() * 4));
-
-      const auto client_guid =
-          GetGLTextureClientGUIDForTracing(context_group_tracing_id, id);
-      pmd->CreateSharedGlobalAllocatorDump(client_guid);
-      pmd->AddOwnershipEdge(dump->guid(), client_guid, 2 /* importance */);
-    }
-  }
-  return true;
-}
-
-bool GpuVideoDecoder::IsProfileSupported(
-    const VideoDecodeAccelerator::Capabilities& capabilities,
-    VideoCodecProfile profile,
-    const gfx::Size& coded_size,
-    bool is_encrypted) {
-  DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
-  for (const auto& supported_profile : capabilities.supported_profiles) {
-    if (profile == supported_profile.profile &&
-        !(supported_profile.encrypted_only && !is_encrypted) &&
-        IsCodedSizeSupported(coded_size, supported_profile.min_resolution,
-                             supported_profile.max_resolution)) {
-      return true;
-    }
-  }
-  return false;
-}
-
-void GpuVideoDecoder::DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent()
-    const {
-  DCHECK(factories_->GetTaskRunner()->BelongsToCurrentThread());
-}
-
-}  // namespace media
diff --git a/media/filters/gpu_video_decoder.h b/media/filters/gpu_video_decoder.h
deleted file mode 100644
index ef04bf9..0000000
--- a/media/filters/gpu_video_decoder.h
+++ /dev/null
@@ -1,282 +0,0 @@
-// Copyright (c) 2012 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 MEDIA_FILTERS_GPU_VIDEO_DECODER_H_
-#define MEDIA_FILTERS_GPU_VIDEO_DECODER_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <list>
-#include <map>
-#include <set>
-#include <utility>
-#include <vector>
-
-#include "base/containers/flat_set.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/trace_event/memory_dump_provider.h"
-#include "gpu/command_buffer/common/sync_token.h"
-#include "media/base/overlay_info.h"
-#include "media/base/pipeline_status.h"
-#include "media/base/video_decoder.h"
-#include "media/video/video_decode_accelerator.h"
-
-template <class T> class scoped_refptr;
-
-namespace base {
-class SharedMemory;
-}
-
-namespace gpu {
-struct SyncToken;
-}
-
-namespace media {
-
-class DecoderBuffer;
-class GpuVideoAcceleratorFactories;
-class MediaLog;
-
-// GPU-accelerated video decoder implementation.  Relies on
-// AcceleratedVideoDecoderMsg_Decode and friends.  Can be created on any thread
-// but must be accessed and destroyed on GpuVideoAcceleratorFactories's
-// GetMessageLoop().
-class MEDIA_EXPORT GpuVideoDecoder
-    : public VideoDecoder,
-      public VideoDecodeAccelerator::Client,
-      public base::trace_event::MemoryDumpProvider {
- public:
-  GpuVideoDecoder(GpuVideoAcceleratorFactories* factories,
-                  const RequestOverlayInfoCB& request_overlay_info_cb,
-                  const gfx::ColorSpace& target_color_space,
-                  MediaLog* media_log);
-  ~GpuVideoDecoder() override;
-
-  // VideoDecoder implementation.
-  std::string GetDisplayName() const override;
-  bool IsPlatformDecoder() const override;
-  void Initialize(const VideoDecoderConfig& config,
-                  bool low_delay,
-                  CdmContext* cdm_context,
-                  InitCB init_cb,
-                  const OutputCB& output_cb,
-                  const WaitingCB& waiting_cb) override;
-  void Decode(scoped_refptr<DecoderBuffer> buffer, DecodeCB decode_cb) override;
-  void Reset(base::OnceClosure closure) override;
-  bool NeedsBitstreamConversion() const override;
-  bool CanReadWithoutStalling() const override;
-  int GetMaxDecodeRequests() const override;
-
-  // VideoDecodeAccelerator::Client implementation.
-  void NotifyInitializationComplete(bool success) override;
-  void ProvidePictureBuffers(uint32_t count,
-                             VideoPixelFormat format,
-                             uint32_t textures_per_buffer,
-                             const gfx::Size& size,
-                             uint32_t texture_target) override;
-  void DismissPictureBuffer(int32_t id) override;
-  void PictureReady(const media::Picture& picture) override;
-  void NotifyEndOfBitstreamBuffer(int32_t id) override;
-  void NotifyFlushDone() override;
-  void NotifyResetDone() override;
-  void NotifyError(media::VideoDecodeAccelerator::Error error) override;
-
-  // base::trace_event::MemoryDumpProvider implementation.
-  bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
-                    base::trace_event::ProcessMemoryDump* pmd) override;
-
-  static const char kDecoderName[];
-
- private:
-  enum State {
-    kNormal,
-    kDrainingDecoder,
-    kDecoderDrained,
-    kError
-  };
-
-  // A SHMBuffer and the DecoderBuffer its data came from.
-  struct PendingDecoderBuffer;
-
-  typedef std::map<int32_t, PictureBuffer> PictureBufferMap;
-
-  void DeliverFrame(scoped_refptr<VideoFrame> frame);
-
-  // Static method is to allow it to run even after GVD is deleted.
-  static void ReleaseMailbox(base::WeakPtr<GpuVideoDecoder> decoder,
-                             media::GpuVideoAcceleratorFactories* factories,
-                             int64_t picture_buffer_id,
-                             PictureBuffer::TextureIds ids,
-                             const gpu::SyncToken& release_sync_token);
-  // Indicate the picture buffer can be reused by the decoder.
-  void ReusePictureBuffer(int64_t picture_buffer_id);
-
-  void RecordBufferData(
-      const BitstreamBuffer& bitstream_buffer, const DecoderBuffer& buffer);
-  void GetBufferData(int32_t id,
-                     base::TimeDelta* timetamp,
-                     gfx::Rect* visible_rect,
-                     gfx::Size* natural_size);
-
-  void DestroyVDA();
-
-  // Request a shared-memory segment of at least |min_size| bytes.  Will
-  // allocate as necessary. May return nullptr during Shutdown.
-  std::unique_ptr<base::SharedMemory> GetSharedMemory(size_t min_size);
-
-  // Return a shared-memory segment to the available pool.
-  void PutSharedMemory(std::unique_ptr<base::SharedMemory> shm_buffer,
-                       int32_t last_bitstream_buffer_id);
-
-  // Destroy all the assigned picture buffers and delete their textures, but
-  // skip the textures of the buffers which is still at display.
-  void DestroyPictureBuffers();
-
-  // Returns true if the video decoder with |capabilities| can support
-  // |profile|, |coded_size|, and |is_encrypted|.
-  bool IsProfileSupported(
-      const VideoDecodeAccelerator::Capabilities& capabilities,
-      VideoCodecProfile profile,
-      const gfx::Size& coded_size,
-      bool is_encrypted);
-
-  // Assert the contract that this class is operated on the right thread.
-  void DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent() const;
-
-  // Provided to the |request_overlay_info_cb_| callback given during
-  // construction.  Sets or changes the output surface.
-  void OnOverlayInfoAvailable(const OverlayInfo& overlay_info);
-
-  // If the VDA supports external surfaces, we must wait for the surface before
-  // completing initialization. This will be called by OnSurfaceAvailable() once
-  // the surface is known or immediately by Initialize() if external surfaces
-  // are unsupported.
-  void CompleteInitialization(const OverlayInfo& overlay_info);
-
-  // Return the number of picture buffers which ids are in
-  // |assigned_picture_buffers_| but not in |picture_buffers_at_display_|.
-  // It is used for checking and implementing CanReadWithoutStalling().
-  size_t AvailablePictures() const;
-
-  bool needs_bitstream_conversion_;
-
-  GpuVideoAcceleratorFactories* factories_;
-
-  // For requesting overlay info updates. If this is null, overlays are not
-  // supported.
-  RequestOverlayInfoCB request_overlay_info_cb_;
-  bool overlay_info_requested_;
-
-  gfx::ColorSpace target_color_space_;
-
-  MediaLog* media_log_;
-
-  // Populated during Initialize() (on success) and unchanged until an error
-  // occurs.
-  std::unique_ptr<VideoDecodeAccelerator> vda_;
-
-  // Whether |vda_->Initialize()| has been called. This is used to avoid
-  // calling Initialize() again while a deferred initialization is in progress.
-  bool vda_initialized_;
-
-  InitCB init_cb_;
-  OutputCB output_cb_;
-
-  DecodeCB eos_decode_cb_;
-
-  // Not null only during reset.
-  base::OnceClosure pending_reset_cb_;
-
-  State state_;
-
-  VideoDecoderConfig config_;
-
-  // Shared-memory buffer pool.  Since allocating SHM segments requires a round-
-  // trip to the browser process, we try to keep allocation out of the steady-
-  // state of the decoder.
-  //
-  // The second value in the ShMemEntry is the last bitstream buffer id assigned
-  // to that segment; it's used to erase segments which are no longer active.
-  using ShMemEntry = std::pair<std::unique_ptr<base::SharedMemory>, int32_t>;
-  class ShMemEntrySortedBySize {
-   public:
-    bool operator()(const ShMemEntry& lhs, const ShMemEntry& rhs) const {
-      return lhs.first->mapped_size() < rhs.first->mapped_size();
-    }
-  };
-  base::flat_set<ShMemEntry, ShMemEntrySortedBySize> available_shm_segments_;
-
-  // Placeholder sync token that was created and validated after the most
-  // recent picture buffers were created.
-  gpu::SyncToken sync_token_;
-
-  std::map<int32_t, PendingDecoderBuffer> bitstream_buffers_in_decoder_;
-  PictureBufferMap assigned_picture_buffers_;
-  // PictureBuffers given to us by VDA via PictureReady, which we sent forward
-  // as VideoFrames to be rendered via decode_cb_, and which will be returned
-  // to us via ReusePictureBuffer. Note that a picture buffer might be sent from
-  // VDA multiple times. Therefore we use multimap to track the number of times
-  // we passed the picture buffer for display.
-  std::multimap<int32_t /* picture_buffer_id */,
-                PictureBuffer::TextureIds /* texture_id */>
-      picture_buffers_at_display_;
-
-  struct BufferData {
-    BufferData(int32_t bbid,
-               base::TimeDelta ts,
-               const gfx::Rect& visible_rect,
-               const gfx::Size& natural_size);
-    ~BufferData();
-    int32_t bitstream_buffer_id;
-    base::TimeDelta timestamp;
-    gfx::Rect visible_rect;
-    gfx::Size natural_size;
-  };
-  std::list<BufferData> input_buffer_data_;
-
-  // picture_buffer_id and the frame wrapping the corresponding Picture, for
-  // frames that have been decoded but haven't been requested by a Decode() yet.
-  int32_t next_picture_buffer_id_;
-  int32_t next_bitstream_buffer_id_;
-
-  // If true, the client cannot expect the VDA to produce any new decoded
-  // frames, until it returns all PictureBuffers it may be holding back to the
-  // VDA. In other words, the VDA may require all PictureBuffers to be able to
-  // proceed with decoding the next frame.
-  bool needs_all_picture_buffers_to_decode_;
-
-  // If true, then the VDA supports deferred initialization via
-  // NotifyInitializationComplete.  Otherwise, it will return initialization
-  // status synchronously from VDA::Initialize.
-  bool supports_deferred_initialization_;
-
-  // This flag translates to COPY_REQUIRED flag for each frame.
-  bool requires_texture_copy_;
-
-  // Set during Initialize(); given to the VDA for purposes for handling
-  // encrypted content.
-  int cdm_id_;
-
-  // Minimum size for shared memory segments. Ideally chosen to optimize the
-  // number of segments and total size of allocations over the course of a
-  // playback.  See Initialize() for more details.
-  size_t min_shared_memory_segment_size_;
-
-  // |next_bitstream_buffer_id_| at the time we last performed a GC of no longer
-  // used ShMemEntry objects in |available_shm_segments_|.  Updated whenever
-  // PutSharedMemory() performs a GC.
-  int32_t bitstream_buffer_id_of_last_gc_;
-
-  // Bound to factories_->GetMessageLoop().
-  // NOTE: Weak pointers must be invalidated before all other member variables.
-  base::WeakPtrFactory<GpuVideoDecoder> weak_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(GpuVideoDecoder);
-};
-
-}  // namespace media
-
-#endif  // MEDIA_FILTERS_GPU_VIDEO_DECODER_H_
diff --git a/media/gpu/BUILD.gn b/media/gpu/BUILD.gn
index 83d778d..b3f43cd 100644
--- a/media/gpu/BUILD.gn
+++ b/media/gpu/BUILD.gn
@@ -82,7 +82,10 @@
   ldflags = []
 
   if (is_linux) {
-    public_deps += [ "//media/gpu/linux" ]
+    public_deps += [
+      "//media/gpu/linux",
+      "//media/gpu/linux:common",
+    ]
   }
 
   if (is_mac) {
@@ -157,6 +160,9 @@
 
   if (is_win) {
     sources += [
+      "windows/d3d11_com_defs.h",
+      "windows/d3d11_copying_texture_wrapper.cc",
+      "windows/d3d11_copying_texture_wrapper.h",
       "windows/d3d11_h264_accelerator.cc",
       "windows/d3d11_h264_accelerator.h",
       "windows/d3d11_picture_buffer.cc",
@@ -170,6 +176,8 @@
       "windows/d3d11_video_decoder_client.h",
       "windows/d3d11_video_decoder_impl.cc",
       "windows/d3d11_video_decoder_impl.h",
+      "windows/d3d11_video_processor_proxy.cc",
+      "windows/d3d11_video_processor_proxy.h",
       "windows/d3d11_vp9_accelerator.cc",
       "windows/d3d11_vp9_accelerator.h",
       "windows/d3d11_vp9_picture.cc",
@@ -561,8 +569,10 @@
   if (is_win && enable_library_cdms) {
     sources += [
       "windows/d3d11_cdm_proxy_unittest.cc",
+      "windows/d3d11_copying_texture_wrapper_unittest.cc",
       "windows/d3d11_decryptor_unittest.cc",
       "windows/d3d11_video_decoder_unittest.cc",
+      "windows/d3d11_video_processor_proxy_unittest.cc",
     ]
     libs = [ "dxguid.lib" ]
   }
diff --git a/media/gpu/linux/BUILD.gn b/media/gpu/linux/BUILD.gn
index 9be5fd2c..8119c38 100644
--- a/media/gpu/linux/BUILD.gn
+++ b/media/gpu/linux/BUILD.gn
@@ -4,12 +4,34 @@
 
 import("//build/buildflag_header.gni")
 import("//build/config/ui.gni")
+import("//media/gpu/args.gni")
 
 assert(is_linux)
 
 source_set("linux") {
   defines = [ "MEDIA_GPU_IMPLEMENTATION" ]
   sources = [
+    "linux_video_decoder_factory.cc",
+    "linux_video_decoder_factory.h",
+  ]
+
+  deps = [
+    ":common",
+    "//base",
+    "//media",
+    "//media/gpu:buildflags",
+    "//media/gpu:command_buffer_helper",
+    "//media/gpu:common",
+  ]
+
+  if (use_v4l2_codec) {
+    deps += [ "//media/gpu/v4l2" ]
+  }
+}
+
+source_set("common") {
+  defines = [ "MEDIA_GPU_IMPLEMENTATION" ]
+  sources = [
     "dmabuf_video_frame_pool.cc",
     "dmabuf_video_frame_pool.h",
     "mailbox_video_frame_converter.cc",
@@ -57,7 +79,7 @@
     "platform_video_frame_pool_unittest.cc",
   ]
   deps = [
-    ":linux",
+    ":common",
     "//base",
     "//base/test:test_support",
     "//skia",
diff --git a/media/gpu/linux/linux_video_decoder_factory.cc b/media/gpu/linux/linux_video_decoder_factory.cc
new file mode 100644
index 0000000..448d2bd
--- /dev/null
+++ b/media/gpu/linux/linux_video_decoder_factory.cc
@@ -0,0 +1,69 @@
+// 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 "media/gpu/linux/linux_video_decoder_factory.h"
+
+#include <utility>
+
+#include "base/sequenced_task_runner.h"
+#include "media/base/video_decoder.h"
+#include "media/gpu/buildflags.h"
+#include "media/gpu/linux/mailbox_video_frame_converter.h"
+#include "media/gpu/linux/platform_video_frame_pool.h"
+
+#if BUILDFLAG(USE_V4L2_CODEC)
+#include "media/gpu/v4l2/v4l2_slice_video_decoder.h"
+#endif
+
+namespace media {
+
+namespace {
+
+std::unique_ptr<VideoDecoder> CreateLinuxVideoDecoder(
+    scoped_refptr<base::SequencedTaskRunner> client_task_runner,
+    std::unique_ptr<DmabufVideoFramePool> frame_pool,
+    std::unique_ptr<VideoFrameConverter> frame_converter) {
+  if (!client_task_runner || !frame_pool || !frame_converter)
+    return nullptr;
+
+#if BUILDFLAG(USE_V4L2_CODEC)
+  return V4L2SliceVideoDecoder::Create(std::move(client_task_runner),
+                                       std::move(frame_pool),
+                                       std::move(frame_converter));
+#endif
+
+  return nullptr;
+}
+
+}  // namespace
+
+// static
+std::unique_ptr<VideoDecoder> LinuxVideoDecoderFactory::Create(
+    scoped_refptr<base::SequencedTaskRunner> client_task_runner,
+    scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,
+    GetCommandBufferStubCB get_stub_cb) {
+  std::unique_ptr<DmabufVideoFramePool> frame_pool =
+      std::make_unique<PlatformVideoFramePool>();
+  std::unique_ptr<VideoFrameConverter> frame_converter =
+      std::make_unique<MailboxVideoFrameConverter>(
+          base::BindRepeating(&DmabufVideoFramePool::UnwrapFrame,
+                              base::Unretained(frame_pool.get())),
+          std::move(gpu_task_runner), std::move(get_stub_cb));
+
+  return CreateLinuxVideoDecoder(std::move(client_task_runner),
+                                 std::move(frame_pool),
+                                 std::move(frame_converter));
+}
+
+// static
+std::unique_ptr<VideoDecoder> LinuxVideoDecoderFactory::CreateForTesting(
+    scoped_refptr<base::SequencedTaskRunner> client_task_runner) {
+  // Use VideoFrameConverter because we don't convert the frame to
+  // Mailbox-backed.
+  return CreateLinuxVideoDecoder(std::move(client_task_runner),
+                                 std::make_unique<PlatformVideoFramePool>(),
+                                 std::make_unique<VideoFrameConverter>());
+}
+
+}  // namespace media
diff --git a/media/gpu/linux/linux_video_decoder_factory.h b/media/gpu/linux/linux_video_decoder_factory.h
new file mode 100644
index 0000000..0c207244
--- /dev/null
+++ b/media/gpu/linux/linux_video_decoder_factory.h
@@ -0,0 +1,46 @@
+// 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 MEDIA_GPU_LINUX_LINUX_VIDEO_DECODER_FACTORY_H_
+#define MEDIA_GPU_LINUX_LINUX_VIDEO_DECODER_FACTORY_H_
+
+#include <memory>
+
+#include "base/memory/scoped_refptr.h"
+#include "media/gpu/media_gpu_export.h"
+
+namespace base {
+class SequencedTaskRunner;
+class SingleThreadTaskRunner;
+}  // namespace base
+
+namespace gpu {
+class CommandBufferStub;
+}
+
+namespace media {
+
+class VideoDecoder;
+
+class MEDIA_GPU_EXPORT LinuxVideoDecoderFactory {
+ public:
+  using GetCommandBufferStubCB = base::OnceCallback<gpu::CommandBufferStub*()>;
+
+  // Create VideoDecoder instance that does convert the output VideoFrame
+  // to mailbox-backed VideoFrame by CommandBufferHelper.
+  // We convert the frame by MailboxVideoFrameConverter. See the description for
+  // |get_stub_cb| at MailboxVideoFrameConverter class.
+  static std::unique_ptr<VideoDecoder> Create(
+      scoped_refptr<base::SequencedTaskRunner> client_task_runner,
+      scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,
+      GetCommandBufferStubCB get_stub_cb);
+
+  // Create VideoDecoder instance for tesing. The created VideoDecoder does not
+  // convert the output VideoFrame to mailbox-backed VideoFrame.
+  static std::unique_ptr<VideoDecoder> CreateForTesting(
+      scoped_refptr<base::SequencedTaskRunner> client_task_runner);
+};
+
+}  // namespace media
+#endif  // MEDIA_GPU_LINUX_LINUX_VIDEO_DECODER_FACTORY_H_
diff --git a/media/gpu/test/video_player/video_decoder_client.cc b/media/gpu/test/video_player/video_decoder_client.cc
index e258af9..3063df4 100644
--- a/media/gpu/test/video_player/video_decoder_client.cc
+++ b/media/gpu/test/video_player/video_decoder_client.cc
@@ -9,6 +9,8 @@
 
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "build/build_config.h"
 #include "media/base/bind_to_current_loop.h"
 #include "media/base/waiting.h"
 #include "media/gpu/macros.h"
@@ -17,6 +19,12 @@
 #include "media/gpu/test/video_player/test_vda_video_decoder.h"
 #include "media/gpu/test/video_player/video.h"
 
+#if defined(OS_LINUX)
+#include "media/gpu/linux/linux_video_decoder_factory.h"
+#include "media/gpu/linux/platform_video_frame_pool.h"
+#include "media/gpu/video_frame_converter.h"
+#endif  // defined(OS_LINUX)
+
 namespace media {
 namespace test {
 
@@ -169,8 +177,11 @@
       base::BindRepeating([](WaitingReason) { NOTIMPLEMENTED(); });
 
   if (decoder_client_config_.use_vd) {
-    // TODO(dstaessens@) Create VD-based video decoder.
-    NOTIMPLEMENTED();
+#if defined(OS_LINUX)
+    decoder_ = LinuxVideoDecoderFactory::CreateForTesting(
+        base::ThreadTaskRunnerHandle::Get());
+#endif  // defined(OS_LINUX)
+    LOG_ASSERT(decoder_) << "Failed to create decoder.";
   } else {
     // The video decoder client expects decoders to use the VD interface. We can
     // use the TestVDAVideoDecoder wrapper here to test VDA-based video
@@ -178,10 +189,11 @@
     decoder_ = std::make_unique<TestVDAVideoDecoder>(
         decoder_client_config_.allocation_mode, gfx::ColorSpace(),
         frame_renderer_.get());
-    decoder_->Initialize(config, false, nullptr, std::move(init_cb), output_cb,
-                         waiting_cb);
   }
 
+  decoder_->Initialize(config, false, nullptr, std::move(init_cb), output_cb,
+                       waiting_cb);
+
   DCHECK_LE(decoder_client_config_.max_outstanding_decode_requests,
             static_cast<size_t>(decoder_->GetMaxDecodeRequests()));
 
diff --git a/media/gpu/v4l2/BUILD.gn b/media/gpu/v4l2/BUILD.gn
index 7758cd6..d3b910e 100644
--- a/media/gpu/v4l2/BUILD.gn
+++ b/media/gpu/v4l2/BUILD.gn
@@ -74,7 +74,7 @@
     "//media/gpu:buildflags",
     "//media/gpu:common",
     "//media/gpu:image_processor_common",
-    "//media/gpu/linux",
+    "//media/gpu/linux:common",
     "//third_party/libyuv",
     "//ui/gfx/geometry",
     "//ui/ozone",
diff --git a/media/gpu/vaapi/BUILD.gn b/media/gpu/vaapi/BUILD.gn
index 2bac145bb..7d87defb 100644
--- a/media/gpu/vaapi/BUILD.gn
+++ b/media/gpu/vaapi/BUILD.gn
@@ -39,6 +39,8 @@
     "vaapi_common.h",
     "vaapi_dmabuf_video_frame_mapper.cc",
     "vaapi_dmabuf_video_frame_mapper.h",
+    "vaapi_image_decoder.h",
+    "vaapi_image_decoder.cc",
     "vaapi_h264_accelerator.cc",
     "vaapi_h264_accelerator.h",
     "vaapi_jpeg_decode_accelerator_worker.cc",
@@ -103,7 +105,7 @@
 
   if (is_linux) {
     configs += [ "//build/config/linux/libva" ]
-    deps += [ "//media/gpu/linux" ]
+    deps += [ "//media/gpu/linux:common" ]
   }
 
   if (use_x11) {
@@ -188,4 +190,4 @@
     # Indirect dependency from vaapi_wrapper.h.
     "//skia",
   ]
-}
+}
\ No newline at end of file
diff --git a/media/gpu/vaapi/vaapi_image_decoder.cc b/media/gpu/vaapi/vaapi_image_decoder.cc
new file mode 100644
index 0000000..c94aaf0
--- /dev/null
+++ b/media/gpu/vaapi/vaapi_image_decoder.cc
@@ -0,0 +1,18 @@
+// 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 "media/gpu/vaapi/vaapi_image_decoder.h"
+
+#include <va/va.h>
+
+#include "media/gpu/vaapi/vaapi_wrapper.h"
+
+namespace media {
+
+VaapiImageDecoder::VaapiImageDecoder()
+    : va_surface_id_(VA_INVALID_SURFACE), va_rt_format_(kInvalidVaRtFormat) {}
+
+VaapiImageDecoder::~VaapiImageDecoder() = default;
+
+}  // namespace media
diff --git a/media/gpu/vaapi/vaapi_image_decoder.h b/media/gpu/vaapi/vaapi_image_decoder.h
new file mode 100644
index 0000000..39a3072
--- /dev/null
+++ b/media/gpu/vaapi/vaapi_image_decoder.h
@@ -0,0 +1,86 @@
+// 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 MEDIA_GPU_VAAPI_VAAPI_IMAGE_DECODER_H_
+#define MEDIA_GPU_VAAPI_VAAPI_IMAGE_DECODER_H_
+
+#include <stdint.h>
+
+#include "base/callback_forward.h"
+#include "base/containers/span.h"
+#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
+#include "ui/gfx/geometry/size.h"
+
+// This data type is defined in va/va.h using typedef, reproduced here.
+typedef unsigned int VASurfaceID;
+
+namespace media {
+
+class VASurface;
+class VaapiWrapper;
+
+constexpr unsigned int kInvalidVaRtFormat = 0u;
+
+enum class VaapiImageDecodeStatus : uint32_t {
+  kSuccess,
+  kParseJpegFailed,
+  kUnsupportedJpeg,
+  kUnsupportedSubsampling,
+  kSurfaceCreationFailed,
+  kSubmitPicParamsFailed,
+  kSubmitIQMatrixFailed,
+  kSubmitHuffmanFailed,
+  kSubmitSliceParamsFailed,
+  kSubmitSliceDataFailed,
+  kExecuteDecodeFailed,
+  kUnsupportedSurfaceFormat,
+  kCannotGetImage,
+  kInvalidState,
+};
+
+// This class abstracts the idea of VA-API format-specific decoders. It is the
+// responsibility of each subclass to initialize |vaapi_wrapper_| appropriately
+// for the purpose of performing hardware-accelerated image decodes of a
+// particular format (e.g. JPEG or WebP). Objects of this class are not
+// thread-safe, but they are also not thread-affine, i.e., the caller is free to
+// call the methods on any thread, but calls must be synchronized externally.
+// TODO(gildekel): move more common image decoding functions to this class as
+// more implementing classes are added (e.g. VaapiWebPDecoder).
+class VaapiImageDecoder {
+ public:
+  virtual ~VaapiImageDecoder();
+
+  // Initializes |vaapi_wrapper_| in kDecode mode with the appropriate VAAPI
+  // profile and |error_uma_cb| for error reporting.
+  virtual bool Initialize(const base::RepeatingClosure& error_uma_cb) = 0;
+
+  // Decodes a picture. It will fill VA-API parameters and call the
+  // corresponding VA-API methods according to the image in |encoded_image|.
+  // The image will be decoded into an internally allocated VA surface. It
+  // will be returned as an unowned VASurface, which remains valid until the
+  // next Decode() call or destruction of this class. Returns nullptr on
+  // failure and sets *|status| to the reason for failure.
+  virtual scoped_refptr<VASurface> Decode(
+      base::span<const uint8_t> encoded_image,
+      VaapiImageDecodeStatus* status) = 0;
+
+ protected:
+  VaapiImageDecoder();
+
+  scoped_refptr<VaapiWrapper> vaapi_wrapper_;
+
+  // The current VA surface for decoding.
+  VASurfaceID va_surface_id_;
+  // The coded size associated with |va_surface_id_|.
+  gfx::Size coded_size_;
+  // The VA RT format associated with |va_surface_id_|.
+  unsigned int va_rt_format_;
+
+  DISALLOW_COPY_AND_ASSIGN(VaapiImageDecoder);
+};
+
+}  // namespace media
+
+#endif  // MEDIA_GPU_VAAPI_VAAPI_IMAGE_DECODER_H_
diff --git a/media/gpu/vaapi/vaapi_jpeg_decode_accelerator_worker.cc b/media/gpu/vaapi/vaapi_jpeg_decode_accelerator_worker.cc
index df73e05..78b7cff 100644
--- a/media/gpu/vaapi/vaapi_jpeg_decode_accelerator_worker.cc
+++ b/media/gpu/vaapi/vaapi_jpeg_decode_accelerator_worker.cc
@@ -18,6 +18,7 @@
 #include "base/trace_event/trace_event.h"
 #include "media/gpu/macros.h"
 #include "media/gpu/vaapi/va_surface.h"
+#include "media/gpu/vaapi/vaapi_image_decoder.h"
 #include "media/gpu/vaapi/vaapi_jpeg_decoder.h"
 #include "media/gpu/vaapi/vaapi_utils.h"
 #include "mojo/public/cpp/bindings/callback_helpers.h"
@@ -52,17 +53,17 @@
   gpu::ImageDecodeAcceleratorWorker::CompletedDecodeCB scoped_decode_callback =
       mojo::WrapCallbackWithDefaultInvokeIfNotRun(std::move(decode_cb),
                                                   nullptr);
-  VaapiJpegDecodeStatus status;
+  VaapiImageDecodeStatus status;
   decoder->Decode(
       base::make_span<const uint8_t>(encoded_data.data(), encoded_data.size()),
       &status);
-  if (status != VaapiJpegDecodeStatus::kSuccess) {
+  if (status != VaapiImageDecodeStatus::kSuccess) {
     VLOGF(1) << "Failed to decode - status = " << static_cast<uint32_t>(status);
     return;
   }
   std::unique_ptr<ScopedVAImage> scoped_image =
       decoder->GetImage(VA_FOURCC_RGBX /* preferred_image_fourcc */, &status);
-  if (status != VaapiJpegDecodeStatus::kSuccess) {
+  if (status != VaapiImageDecodeStatus::kSuccess) {
     VLOGF(1) << "Failed to get image - status = "
              << static_cast<uint32_t>(status);
     return;
diff --git a/media/gpu/vaapi/vaapi_jpeg_decoder.cc b/media/gpu/vaapi/vaapi_jpeg_decoder.cc
index 364a874f..86ed8cd 100644
--- a/media/gpu/vaapi/vaapi_jpeg_decoder.cc
+++ b/media/gpu/vaapi/vaapi_jpeg_decoder.cc
@@ -210,11 +210,6 @@
   return kInvalidVaRtFormat;
 }
 
-VaapiJpegDecoder::VaapiJpegDecoder()
-    : va_surface_id_(VA_INVALID_SURFACE), va_rt_format_(kInvalidVaRtFormat) {}
-
-VaapiJpegDecoder::~VaapiJpegDecoder() = default;
-
 bool VaapiJpegDecoder::Initialize(const base::RepeatingClosure& error_uma_cb) {
   vaapi_wrapper_ = VaapiWrapper::Create(VaapiWrapper::kDecode,
                                         VAProfileJPEGBaseline, error_uma_cb);
@@ -227,10 +222,10 @@
 
 scoped_refptr<VASurface> VaapiJpegDecoder::Decode(
     base::span<const uint8_t> encoded_image,
-    VaapiJpegDecodeStatus* status) {
+    VaapiImageDecodeStatus* status) {
   if (!vaapi_wrapper_) {
     VLOGF(1) << "VaapiJpegDecoder has not been initialized";
-    *status = VaapiJpegDecodeStatus::kInvalidState;
+    *status = VaapiImageDecodeStatus::kInvalidState;
     return nullptr;
   }
 
@@ -239,7 +234,7 @@
   if (!ParseJpegPicture(encoded_image.data(), encoded_image.size(),
                         &parse_result)) {
     VLOGF(1) << "ParseJpegPicture failed";
-    *status = VaapiJpegDecodeStatus::kParseJpegFailed;
+    *status = VaapiImageDecodeStatus::kParseJpegFailed;
     return nullptr;
   }
 
@@ -248,14 +243,14 @@
       VaSurfaceFormatForJpeg(parse_result.frame_header);
   if (picture_va_rt_format == kInvalidVaRtFormat) {
     VLOGF(1) << "Unsupported subsampling";
-    *status = VaapiJpegDecodeStatus::kUnsupportedSubsampling;
+    *status = VaapiImageDecodeStatus::kUnsupportedSubsampling;
     return nullptr;
   }
 
   // Make sure this JPEG can be decoded.
   if (!IsVaapiSupportedJpeg(parse_result)) {
     VLOGF(1) << "The supplied JPEG is unsupported";
-    *status = VaapiJpegDecodeStatus::kUnsupportedJpeg;
+    *status = VaapiImageDecodeStatus::kUnsupportedJpeg;
     return nullptr;
   }
 
@@ -273,7 +268,7 @@
     if (!vaapi_wrapper_->CreateContextAndSurfaces(va_rt_format_, new_coded_size,
                                                   1, &va_surfaces)) {
       VLOGF(1) << "Could not create the context or the surface";
-      *status = VaapiJpegDecodeStatus::kSurfaceCreationFailed;
+      *status = VaapiImageDecodeStatus::kSurfaceCreationFailed;
       return nullptr;
     }
     va_surface_id_ = va_surfaces[0];
@@ -285,7 +280,7 @@
   FillPictureParameters(parse_result.frame_header, &pic_param);
   if (!vaapi_wrapper_->SubmitBuffer(VAPictureParameterBufferType, &pic_param)) {
     VLOGF(1) << "Could not submit VAPictureParameterBufferType";
-    *status = VaapiJpegDecodeStatus::kSubmitPicParamsFailed;
+    *status = VaapiImageDecodeStatus::kSubmitPicParamsFailed;
     return nullptr;
   }
 
@@ -294,7 +289,7 @@
   FillIQMatrix(parse_result.q_table, &iq_matrix);
   if (!vaapi_wrapper_->SubmitBuffer(VAIQMatrixBufferType, &iq_matrix)) {
     VLOGF(1) << "Could not submit VAIQMatrixBufferType";
-    *status = VaapiJpegDecodeStatus::kSubmitIQMatrixFailed;
+    *status = VaapiImageDecodeStatus::kSubmitIQMatrixFailed;
     return nullptr;
   }
 
@@ -304,7 +299,7 @@
                    &huffman_table);
   if (!vaapi_wrapper_->SubmitBuffer(VAHuffmanTableBufferType, &huffman_table)) {
     VLOGF(1) << "Could not submit VAHuffmanTableBufferType";
-    *status = VaapiJpegDecodeStatus::kSubmitHuffmanFailed;
+    *status = VaapiImageDecodeStatus::kSubmitHuffmanFailed;
     return nullptr;
   }
 
@@ -313,7 +308,7 @@
   FillSliceParameters(parse_result, &slice_param);
   if (!vaapi_wrapper_->SubmitBuffer(VASliceParameterBufferType, &slice_param)) {
     VLOGF(1) << "Could not submit VASliceParameterBufferType";
-    *status = VaapiJpegDecodeStatus::kSubmitSliceParamsFailed;
+    *status = VaapiImageDecodeStatus::kSubmitSliceParamsFailed;
     return nullptr;
   }
 
@@ -322,18 +317,18 @@
                                     parse_result.data_size,
                                     const_cast<char*>(parse_result.data))) {
     VLOGF(1) << "Could not submit VASliceDataBufferType";
-    *status = VaapiJpegDecodeStatus::kSubmitSliceDataFailed;
+    *status = VaapiImageDecodeStatus::kSubmitSliceDataFailed;
     return nullptr;
   }
 
   // Execute the decode.
   if (!vaapi_wrapper_->ExecuteAndDestroyPendingBuffers(va_surface_id_)) {
     VLOGF(1) << "Executing the decode failed";
-    *status = VaapiJpegDecodeStatus::kExecuteDecodeFailed;
+    *status = VaapiImageDecodeStatus::kExecuteDecodeFailed;
     return nullptr;
   }
 
-  *status = VaapiJpegDecodeStatus::kSuccess;
+  *status = VaapiImageDecodeStatus::kSuccess;
   return base::MakeRefCounted<VASurface>(va_surface_id_, coded_size_,
                                          va_rt_format_,
                                          base::DoNothing() /* release_cb */);
@@ -341,10 +336,10 @@
 
 std::unique_ptr<ScopedVAImage> VaapiJpegDecoder::GetImage(
     uint32_t preferred_image_fourcc,
-    VaapiJpegDecodeStatus* status) {
+    VaapiImageDecodeStatus* status) {
   if (va_surface_id_ == VA_INVALID_ID) {
     VLOGF(1) << "No decoded JPEG available";
-    *status = VaapiJpegDecodeStatus::kInvalidState;
+    *status = VaapiImageDecodeStatus::kInvalidState;
     return nullptr;
   }
 
@@ -352,7 +347,7 @@
   if (!VaapiWrapper::GetJpegDecodeSuitableImageFourCC(
           va_rt_format_, preferred_image_fourcc, &image_fourcc)) {
     VLOGF(1) << "Cannot determine the output FOURCC";
-    *status = VaapiJpegDecodeStatus::kCannotGetImage;
+    *status = VaapiImageDecodeStatus::kCannotGetImage;
     return nullptr;
   }
   VAImageFormat image_format{.fourcc = image_fourcc};
@@ -361,11 +356,11 @@
   if (!scoped_image) {
     VLOGF(1) << "Cannot get VAImage, FOURCC = "
              << FourccToString(image_format.fourcc);
-    *status = VaapiJpegDecodeStatus::kCannotGetImage;
+    *status = VaapiImageDecodeStatus::kCannotGetImage;
     return nullptr;
   }
 
-  *status = VaapiJpegDecodeStatus::kSuccess;
+  *status = VaapiImageDecodeStatus::kSuccess;
   return scoped_image;
 }
 
diff --git a/media/gpu/vaapi/vaapi_jpeg_decoder.h b/media/gpu/vaapi/vaapi_jpeg_decoder.h
index c5fcdb4..4dfe28333 100644
--- a/media/gpu/vaapi/vaapi_jpeg_decoder.h
+++ b/media/gpu/vaapi/vaapi_jpeg_decoder.h
@@ -9,67 +9,30 @@
 
 #include <memory>
 
-#include "base/callback_forward.h"
-#include "base/containers/span.h"
 #include "base/macros.h"
-#include "base/memory/scoped_refptr.h"
-#include "ui/gfx/geometry/size.h"
-
-// This data type is defined in va/va.h using typedef, reproduced here.
-typedef unsigned int VASurfaceID;
+#include "media/gpu/vaapi/vaapi_image_decoder.h"
 
 namespace media {
 
 struct JpegFrameHeader;
 class ScopedVAImage;
-class VASurface;
-class VaapiWrapper;
-
-enum class VaapiJpegDecodeStatus : uint32_t {
-  kSuccess,
-  kParseJpegFailed,
-  kUnsupportedJpeg,
-  kUnsupportedSubsampling,
-  kSurfaceCreationFailed,
-  kSubmitPicParamsFailed,
-  kSubmitIQMatrixFailed,
-  kSubmitHuffmanFailed,
-  kSubmitSliceParamsFailed,
-  kSubmitSliceDataFailed,
-  kExecuteDecodeFailed,
-  kUnsupportedSurfaceFormat,
-  kCannotGetImage,
-  kInvalidState,
-};
-
-constexpr unsigned int kInvalidVaRtFormat = 0u;
 
 // Returns the internal format required for a JPEG image given its parsed
 // |frame_header|. If the image's subsampling format is not one of 4:2:0, 4:2:2,
 // or 4:4:4, returns kInvalidVaRtFormat.
 unsigned int VaSurfaceFormatForJpeg(const JpegFrameHeader& frame_header);
 
-// Encapsulates a VaapiWrapper for the purpose of performing
-// hardware-accelerated JPEG decodes. Objects of this class are not thread-safe,
-// but they are also not thread-affine, i.e., the caller is free to call the
-// methods on any thread, but calls must be synchronized externally.
-class VaapiJpegDecoder final {
+// Initializes a VaapiWrapper for the purpose of performing
+// hardware-accelerated JPEG decodes.
+class VaapiJpegDecoder : public VaapiImageDecoder {
  public:
-  VaapiJpegDecoder();
-  ~VaapiJpegDecoder();
+  VaapiJpegDecoder() = default;
+  ~VaapiJpegDecoder() override = default;
 
-  // Initializes |vaapi_wrapper_| in kDecode mode with VAProfileJPEGBaseline
-  // profile and |error_uma_cb| for error reporting.
-  bool Initialize(const base::RepeatingClosure& error_uma_cb);
-
-  // Decodes a JPEG picture. It will fill VA-API parameters and call the
-  // corresponding VA-API methods according to the JPEG in |encoded_image|.
-  // The image will be decoded into an internally allocated VA surface. It
-  // will be returned as an unowned VASurface, which remains valid until the
-  // next Decode() call or destruction of this class. Returns nullptr on
-  // failure and sets *|status| to the reason for failure.
+  // VaapiImageDecoder implementation.
+  bool Initialize(const base::RepeatingClosure& error_uma_cb) override;
   scoped_refptr<VASurface> Decode(base::span<const uint8_t> encoded_image,
-                                  VaapiJpegDecodeStatus* status);
+                                  VaapiImageDecodeStatus* status) override;
 
   // Get the decoded data from the last Decode() call as a ScopedVAImage. The
   // VAImage's format will be either |preferred_image_fourcc| if the conversion
@@ -77,17 +40,7 @@
   // VaapiWrapper::GetJpegDecodeSuitableImageFourCC() for details). Returns
   // nullptr on failure and sets *|status| to the reason for failure.
   std::unique_ptr<ScopedVAImage> GetImage(uint32_t preferred_image_fourcc,
-                                          VaapiJpegDecodeStatus* status);
-
- private:
-  scoped_refptr<VaapiWrapper> vaapi_wrapper_;
-
-  // The current VA surface for decoding.
-  VASurfaceID va_surface_id_;
-  // The coded size associated with |va_surface_id_|.
-  gfx::Size coded_size_;
-  // The VA RT format associated with |va_surface_id_|.
-  unsigned int va_rt_format_;
+                                          VaapiImageDecodeStatus* status);
 
   DISALLOW_COPY_AND_ASSIGN(VaapiJpegDecoder);
 };
diff --git a/media/gpu/vaapi/vaapi_jpeg_decoder_unittest.cc b/media/gpu/vaapi/vaapi_jpeg_decoder_unittest.cc
index a410bcb..5ff8df1 100644
--- a/media/gpu/vaapi/vaapi_jpeg_decoder_unittest.cc
+++ b/media/gpu/vaapi/vaapi_jpeg_decoder_unittest.cc
@@ -26,6 +26,7 @@
 #include "base/strings/string_util.h"
 #include "media/base/test_data_util.h"
 #include "media/base/video_types.h"
+#include "media/gpu/vaapi/vaapi_image_decoder.h"
 #include "media/gpu/vaapi/vaapi_jpeg_decoder.h"
 #include "media/gpu/vaapi/vaapi_utils.h"
 #include "media/gpu/vaapi/vaapi_wrapper.h"
@@ -354,11 +355,11 @@
   std::unique_ptr<ScopedVAImage> Decode(
       base::span<const uint8_t> encoded_image,
       uint32_t preferred_fourcc,
-      VaapiJpegDecodeStatus* status = nullptr);
+      VaapiImageDecodeStatus* status = nullptr);
 
   std::unique_ptr<ScopedVAImage> Decode(
       base::span<const uint8_t> encoded_image,
-      VaapiJpegDecodeStatus* status = nullptr);
+      VaapiImageDecodeStatus* status = nullptr);
 
  protected:
   std::string test_data_path_;
@@ -382,29 +383,29 @@
 std::unique_ptr<ScopedVAImage> VaapiJpegDecoderTest::Decode(
     base::span<const uint8_t> encoded_image,
     uint32_t preferred_fourcc,
-    VaapiJpegDecodeStatus* status) {
-  VaapiJpegDecodeStatus decode_status;
+    VaapiImageDecodeStatus* status) {
+  VaapiImageDecodeStatus decode_status;
   scoped_refptr<VASurface> surface =
       decoder_.Decode(encoded_image, &decode_status);
-  EXPECT_EQ(!!surface, decode_status == VaapiJpegDecodeStatus::kSuccess);
+  EXPECT_EQ(!!surface, decode_status == VaapiImageDecodeStatus::kSuccess);
 
   // Still try to get image when decode fails.
-  VaapiJpegDecodeStatus image_status;
+  VaapiImageDecodeStatus image_status;
   std::unique_ptr<ScopedVAImage> scoped_image;
   scoped_image = decoder_.GetImage(preferred_fourcc, &image_status);
-  EXPECT_EQ(!!scoped_image, image_status == VaapiJpegDecodeStatus::kSuccess);
+  EXPECT_EQ(!!scoped_image, image_status == VaapiImageDecodeStatus::kSuccess);
 
   // Record the first fail status.
   if (status) {
-    *status = decode_status != VaapiJpegDecodeStatus::kSuccess ? decode_status
-                                                               : image_status;
+    *status = decode_status != VaapiImageDecodeStatus::kSuccess ? decode_status
+                                                                : image_status;
   }
   return scoped_image;
 }
 
 std::unique_ptr<ScopedVAImage> VaapiJpegDecoderTest::Decode(
     base::span<const uint8_t> encoded_image,
-    VaapiJpegDecodeStatus* status) {
+    VaapiImageDecodeStatus* status) {
   return Decode(encoded_image, VA_FOURCC_I420, status);
 }
 
@@ -585,13 +586,13 @@
   for (const auto& test_size : test_sizes) {
     const std::vector<unsigned char> jpeg_data = GenerateJpegImage(test_size);
     ASSERT_FALSE(jpeg_data.empty());
-    VaapiJpegDecodeStatus status = VaapiJpegDecodeStatus::kSuccess;
+    VaapiImageDecodeStatus status = VaapiImageDecodeStatus::kSuccess;
     ASSERT_FALSE(Decode(base::make_span<const uint8_t>(
                             reinterpret_cast<const uint8_t*>(jpeg_data.data()),
                             jpeg_data.size()),
                         &status))
         << "Decode unexpectedly succeeded for size = " << test_size.ToString();
-    EXPECT_EQ(VaapiJpegDecodeStatus::kUnsupportedJpeg, status);
+    EXPECT_EQ(VaapiImageDecodeStatus::kUnsupportedJpeg, status);
   }
 }
 
@@ -632,13 +633,13 @@
   for (const auto& test_size : test_sizes) {
     const std::vector<unsigned char> jpeg_data = GenerateJpegImage(test_size);
     ASSERT_FALSE(jpeg_data.empty());
-    VaapiJpegDecodeStatus status = VaapiJpegDecodeStatus::kSuccess;
+    VaapiImageDecodeStatus status = VaapiImageDecodeStatus::kSuccess;
     ASSERT_FALSE(Decode(base::make_span<const uint8_t>(
                             reinterpret_cast<const uint8_t*>(jpeg_data.data()),
                             jpeg_data.size()),
                         &status))
         << "Decode unexpectedly succeeded for size = " << test_size.ToString();
-    EXPECT_EQ(VaapiJpegDecodeStatus::kUnsupportedJpeg, status);
+    EXPECT_EQ(VaapiImageDecodeStatus::kUnsupportedJpeg, status);
   }
 }
 
@@ -648,12 +649,12 @@
   std::string jpeg_data;
   ASSERT_TRUE(base::ReadFileToString(input_file, &jpeg_data))
       << "failed to read input data from " << input_file.value();
-  VaapiJpegDecodeStatus status = VaapiJpegDecodeStatus::kSuccess;
+  VaapiImageDecodeStatus status = VaapiImageDecodeStatus::kSuccess;
   ASSERT_FALSE(Decode(
       base::make_span<const uint8_t>(
           reinterpret_cast<const uint8_t*>(jpeg_data.data()), jpeg_data.size()),
       &status));
-  EXPECT_EQ(VaapiJpegDecodeStatus::kUnsupportedSubsampling, status);
+  EXPECT_EQ(VaapiImageDecodeStatus::kUnsupportedSubsampling, status);
 }
 
 std::string TestParamToString(
diff --git a/media/gpu/vaapi/vaapi_mjpeg_decode_accelerator.cc b/media/gpu/vaapi/vaapi_mjpeg_decode_accelerator.cc
index 35eabc4..e0e78c1 100644
--- a/media/gpu/vaapi/vaapi_mjpeg_decode_accelerator.cc
+++ b/media/gpu/vaapi/vaapi_mjpeg_decode_accelerator.cc
@@ -25,6 +25,7 @@
 #include "media/base/video_types.h"
 #include "media/gpu/macros.h"
 #include "media/gpu/vaapi/va_surface.h"
+#include "media/gpu/vaapi/vaapi_image_decoder.h"
 #include "media/gpu/vaapi/vaapi_utils.h"
 #include "media/gpu/vaapi/vaapi_wrapper.h"
 #include "third_party/libyuv/include/libyuv.h"
@@ -53,13 +54,13 @@
 }
 
 static chromeos_camera::MjpegDecodeAccelerator::Error
-VaapiJpegDecodeStatusToError(VaapiJpegDecodeStatus status) {
+VaapiJpegDecodeStatusToError(VaapiImageDecodeStatus status) {
   switch (status) {
-    case VaapiJpegDecodeStatus::kSuccess:
+    case VaapiImageDecodeStatus::kSuccess:
       return chromeos_camera::MjpegDecodeAccelerator::Error::NO_ERRORS;
-    case VaapiJpegDecodeStatus::kParseJpegFailed:
+    case VaapiImageDecodeStatus::kParseJpegFailed:
       return chromeos_camera::MjpegDecodeAccelerator::Error::PARSE_JPEG_FAILED;
-    case VaapiJpegDecodeStatus::kUnsupportedSubsampling:
+    case VaapiImageDecodeStatus::kUnsupportedSubsampling:
       return chromeos_camera::MjpegDecodeAccelerator::Error::UNSUPPORTED_JPEG;
     default:
       return chromeos_camera::MjpegDecodeAccelerator::Error::PLATFORM_FAILURE;
@@ -226,17 +227,17 @@
   DCHECK(decoder_task_runner_->BelongsToCurrentThread());
   TRACE_EVENT0("jpeg", "DecodeTask");
 
-  VaapiJpegDecodeStatus status;
+  VaapiImageDecodeStatus status;
   decoder_.Decode(
       base::make_span(static_cast<const uint8_t*>(shm->memory()), shm->size()),
       &status);
-  if (status != VaapiJpegDecodeStatus::kSuccess) {
+  if (status != VaapiImageDecodeStatus::kSuccess) {
     NotifyError(bitstream_buffer_id, VaapiJpegDecodeStatusToError(status));
     return;
   }
   std::unique_ptr<ScopedVAImage> image =
       decoder_.GetImage(VA_FOURCC_I420 /* preferred_image_fourcc */, &status);
-  if (status != VaapiJpegDecodeStatus::kSuccess) {
+  if (status != VaapiImageDecodeStatus::kSuccess) {
     NotifyError(bitstream_buffer_id, VaapiJpegDecodeStatusToError(status));
     return;
   }
diff --git a/media/gpu/windows/d3d11_cdm_proxy.cc b/media/gpu/windows/d3d11_cdm_proxy.cc
index 56c82795..eea15b9 100644
--- a/media/gpu/windows/d3d11_cdm_proxy.cc
+++ b/media/gpu/windows/d3d11_cdm_proxy.cc
@@ -29,9 +29,8 @@
 // The key exhange capabilities are checked using these.
 // https://msdn.microsoft.com/en-us/library/windows/desktop/hh447640%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
 // https://msdn.microsoft.com/en-us/library/windows/desktop/hh447782(v=vs.85).aspx
-bool CanDoHardwareProtectedKeyExchange(
-    Microsoft::WRL::ComPtr<ID3D11VideoDevice> video_device,
-    const GUID& crypto_type) {
+bool CanDoHardwareProtectedKeyExchange(ComD3D11VideoDevice video_device,
+                                       const GUID& crypto_type) {
   D3D11_VIDEO_CONTENT_PROTECTION_CAPS caps = {};
   HRESULT hresult = video_device->GetContentProtectionCaps(
       &crypto_type, &D3D11_DECODER_PROFILE_H264_VLD_NOFGT, &caps);
@@ -150,11 +149,11 @@
   // Returns an instance if it starts watching for events, otherwise returns
   // nullptr.
   static std::unique_ptr<HardwareEventWatcher> Create(
-      ComPtr<ID3D11Device> device,
+      ComD3D11Device device,
       base::RepeatingClosure teardown_callback);
 
  private:
-  HardwareEventWatcher(ComPtr<ID3D11Device> device,
+  HardwareEventWatcher(ComD3D11Device device,
                        base::RepeatingClosure teardown_callback);
 
   // Start watching for events.
@@ -162,7 +161,7 @@
 
   // Registers for hardware content protection teardown events.
   // Return true on success.
-  bool RegisterHardwareContentProtectionTeardown(ComPtr<ID3D11Device> device);
+  bool RegisterHardwareContentProtectionTeardown(ComD3D11Device device);
 
   // Regiesters for power events, specifically power resume event.
   // Returns true on success.
@@ -181,9 +180,9 @@
   // IDXGIAdapter3::RegisterHardwareContentProtectionTeardownStatusEvent
   // allows watching for teardown events. It is queried thru the following
   // Devices.
-  ComPtr<ID3D11Device> device_;
-  ComPtr<IDXGIDevice2> dxgi_device_;
-  ComPtr<IDXGIAdapter3> dxgi_adapter_;
+  ComD3D11Device device_;
+  ComDXGIDevice2 dxgi_device_;
+  ComDXGIAdapter3 dxgi_adapter_;
 
   // Cookie, event, and watcher used for watching events from
   // RegisterHardwareContentProtectionTeardownStatusEvent.
@@ -342,7 +341,7 @@
     return;
   }
 
-  ComPtr<ID3D11CryptoSession> csme_crypto_session;
+  ComD3D11CryptoSession csme_crypto_session;
   hresult = video_device_->CreateCryptoSession(
       &crypto_type_, &D3D11_DECODER_PROFILE_H264_VLD_NOFGT,
       &D3D11_KEY_EXCHANGE_HW_PROTECTION, csme_crypto_session.GetAddressOf());
@@ -397,7 +396,7 @@
     return;
   }
 
-  ComPtr<ID3D11CryptoSession>& crypto_session = crypto_session_it->second;
+  ComD3D11CryptoSession& crypto_session = crypto_session_it->second;
 
   D3D11_KEY_EXCHANGE_HW_PROTECTION_DATA key_exchange_data = {};
   key_exchange_data.HWProtectionFunctionID = function_id_it->second;
@@ -461,7 +460,7 @@
     return;
   }
 
-  ComPtr<ID3D11CryptoSession> media_crypto_session;
+  ComD3D11CryptoSession media_crypto_session;
   HRESULT hresult = video_device_->CreateCryptoSession(
       &crypto_type_, &D3D11_DECODER_PROFILE_H264_VLD_NOFGT, &crypto_type_,
       media_crypto_session.GetAddressOf());
@@ -572,7 +571,7 @@
 
 std::unique_ptr<D3D11CdmProxy::HardwareEventWatcher>
 D3D11CdmProxy::HardwareEventWatcher::Create(
-    Microsoft::WRL::ComPtr<ID3D11Device> device,
+    ComD3D11Device device,
     base::RepeatingClosure teardown_callback) {
   std::unique_ptr<HardwareEventWatcher> event_watcher = base::WrapUnique(
       new HardwareEventWatcher(device, std::move(teardown_callback)));
@@ -582,7 +581,7 @@
 }
 
 D3D11CdmProxy::HardwareEventWatcher::HardwareEventWatcher(
-    Microsoft::WRL::ComPtr<ID3D11Device> device,
+    ComD3D11Device device,
     base::RepeatingClosure teardown_callback)
     : device_(device), teardown_callback_(std::move(teardown_callback)) {}
 
@@ -597,7 +596,7 @@
 }
 
 bool D3D11CdmProxy::HardwareEventWatcher::
-    RegisterHardwareContentProtectionTeardown(ComPtr<ID3D11Device> device) {
+    RegisterHardwareContentProtectionTeardown(ComD3D11Device device) {
   device_ = device;
   HRESULT hresult = device_.CopyTo(dxgi_device_.ReleaseAndGetAddressOf());
   if (FAILED(hresult)) {
diff --git a/media/gpu/windows/d3d11_cdm_proxy.h b/media/gpu/windows/d3d11_cdm_proxy.h
index 8b62d2f..d05410e 100644
--- a/media/gpu/windows/d3d11_cdm_proxy.h
+++ b/media/gpu/windows/d3d11_cdm_proxy.h
@@ -18,6 +18,7 @@
 #include "base/memory/weak_ptr.h"
 #include "media/base/win/d3d11_create_device_cb.h"
 #include "media/gpu/media_gpu_export.h"
+#include "media/gpu/windows/d3d11_com_defs.h"
 
 namespace media {
 
@@ -68,8 +69,6 @@
   void SetCreateDeviceCallbackForTesting(D3D11CreateDeviceCB callback);
 
  private:
-  template <typename T>
-  using ComPtr = Microsoft::WRL::ComPtr<T>;
 
   class HardwareEventWatcher;
 
@@ -98,21 +97,19 @@
   Client* client_ = nullptr;
   bool initialized_ = false;
 
-  // These ComPtrs are refcounted pointers.
-  // https://msdn.microsoft.com/en-us/library/br244983.aspx
-  ComPtr<ID3D11Device> device_;
-  ComPtr<ID3D11DeviceContext> device_context_;
+  ComD3D11Device device_;
+  ComD3D11DeviceContext device_context_;
   // TODO(crbug.com/788880): Remove ID3D11VideoDevice and ID3D11VideoContext if
   // they are not required.
-  ComPtr<ID3D11VideoDevice> video_device_;
-  ComPtr<ID3D11VideoDevice1> video_device1_;
-  ComPtr<ID3D11VideoContext> video_context_;
-  ComPtr<ID3D11VideoContext1> video_context1_;
+  ComD3D11VideoDevice video_device_;
+  ComD3D11VideoDevice1 video_device1_;
+  ComD3D11VideoContext video_context_;
+  ComD3D11VideoContext1 video_context1_;
 
   std::unique_ptr<HardwareEventWatcher> hardware_event_watcher_;
 
   // Crypto session ID -> actual crypto session.
-  std::map<uint32_t, ComPtr<ID3D11CryptoSession>> crypto_session_map_;
+  std::map<uint32_t, ComD3D11CryptoSession> crypto_session_map_;
 
   // The values output from ID3D11VideoDevice1::GetCryptoSessionPrivateDataSize.
   // Used when calling NegotiateCryptoSessionKeyExchange.
diff --git a/media/gpu/windows/d3d11_com_defs.h b/media/gpu/windows/d3d11_com_defs.h
new file mode 100644
index 0000000..6537de3
--- /dev/null
+++ b/media/gpu/windows/d3d11_com_defs.h
@@ -0,0 +1,45 @@
+// 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 MEDIA_GPU_WINDOWS_D3D11_COM_DEFS_H_
+#define MEDIA_GPU_WINDOWS_D3D11_COM_DEFS_H_
+
+#include <d3d11.h>
+#include <d3d11_4.h>
+#include <wrl/client.h>
+
+// TODO(tmathmeyer) Ensure that Microsoft::WRL::ComPtr doesn't show up
+// in any of the other files in media/gpu/windows.
+namespace media {
+
+// We want to shorten this so the |using| statements are single line -
+// this improves readability greatly.
+#define COM Microsoft::WRL::ComPtr
+
+// Keep these sorted alphabetically.
+using ComD3D11CryptoSession = COM<ID3D11CryptoSession>;
+using ComD3D11Device = COM<ID3D11Device>;
+using ComD3D11DeviceContext = COM<ID3D11DeviceContext>;
+using ComD3D11Multithread = COM<ID3D11Multithread>;
+using ComD3D11Query = COM<ID3D11Query>;
+using ComD3D11Texture2D = COM<ID3D11Texture2D>;
+using ComD3D11VideoContext = COM<ID3D11VideoContext>;
+using ComD3D11VideoContext1 = COM<ID3D11VideoContext1>;
+using ComD3D11VideoDecoder = COM<ID3D11VideoDecoder>;
+using ComD3D11VideoDecoderOutputView = COM<ID3D11VideoDecoderOutputView>;
+using ComD3D11VideoDevice = COM<ID3D11VideoDevice>;
+using ComD3D11VideoDevice1 = COM<ID3D11VideoDevice1>;
+using ComD3D11VideoProcessor = COM<ID3D11VideoProcessor>;
+using ComD3D11VideoProcessorEnumerator = COM<ID3D11VideoProcessorEnumerator>;
+using ComD3D11VideoProcessorInputView = COM<ID3D11VideoProcessorInputView>;
+using ComD3D11VideoProcessorOutputView = COM<ID3D11VideoProcessorOutputView>;
+
+using ComDXGIAdapter3 = COM<IDXGIAdapter3>;
+using ComDXGIDevice2 = COM<IDXGIDevice2>;
+
+#undef COM
+
+}  // namespace media
+
+#endif  // MEDIA_GPU_WINDOWS_D3D11_COM_DEFS_H_
diff --git a/media/gpu/windows/d3d11_copying_texture_wrapper.cc b/media/gpu/windows/d3d11_copying_texture_wrapper.cc
new file mode 100644
index 0000000..e84986f
--- /dev/null
+++ b/media/gpu/windows/d3d11_copying_texture_wrapper.cc
@@ -0,0 +1,76 @@
+// 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 "media/gpu/windows/d3d11_copying_texture_wrapper.h"
+
+#include <memory>
+
+#include "gpu/command_buffer/service/mailbox_manager.h"
+#include "media/gpu/windows/d3d11_com_defs.h"
+
+namespace media {
+
+// TODO(tmathmeyer) What D3D11 Resources do we need to do the copying?
+CopyingTexture2DWrapper::CopyingTexture2DWrapper(
+    std::unique_ptr<Texture2DWrapper> output_wrapper,
+    std::unique_ptr<VideoProcessorProxy> processor,
+    ComD3D11Texture2D input_texture)
+    : Texture2DWrapper(input_texture),
+      video_processor_(std::move(processor)),
+      output_texture_wrapper_(std::move(output_wrapper)) {}
+
+CopyingTexture2DWrapper::~CopyingTexture2DWrapper() = default;
+
+#define RETURN_ON_FAILURE(expr) \
+  do {                          \
+    if (!SUCCEEDED((expr))) {   \
+      return false;             \
+    }                           \
+  } while (0)
+
+bool CopyingTexture2DWrapper::ProcessTexture(const D3D11PictureBuffer* owner_pb,
+                                             MailboxHolderArray* mailbox_dest) {
+  D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC output_view_desc = {
+      D3D11_VPOV_DIMENSION_TEXTURE2D};
+  output_view_desc.Texture2D.MipSlice = 0;
+  ComD3D11VideoProcessorOutputView output_view;
+  RETURN_ON_FAILURE(video_processor_->CreateVideoProcessorOutputView(
+      output_texture_wrapper_->Texture().Get(), &output_view_desc,
+      &output_view));
+
+  D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC input_view_desc = {0};
+  input_view_desc.ViewDimension = D3D11_VPIV_DIMENSION_TEXTURE2D;
+  input_view_desc.Texture2D.ArraySlice = owner_pb->level();
+  input_view_desc.Texture2D.MipSlice = 0;
+  ComD3D11VideoProcessorInputView input_view;
+  RETURN_ON_FAILURE(video_processor_->CreateVideoProcessorInputView(
+      Texture().Get(), &input_view_desc, &input_view));
+
+  D3D11_VIDEO_PROCESSOR_STREAM streams = {0};
+  streams.Enable = TRUE;
+  streams.pInputSurface = input_view.Get();
+
+  RETURN_ON_FAILURE(video_processor_->VideoProcessorBlt(output_view.Get(),
+                                                        0,  // output_frameno
+                                                        1,  // stream_count
+                                                        &streams));
+
+  return output_texture_wrapper_->ProcessTexture(owner_pb, mailbox_dest);
+}
+
+bool CopyingTexture2DWrapper::Init(GetCommandBufferHelperCB get_helper_cb,
+                                   size_t array_slice,
+                                   GLenum target,
+                                   gfx::Size size,
+                                   int textures_per_picture) {
+  if (!video_processor_->Init(size.width(), size.height()))
+    return false;
+
+  return output_texture_wrapper_->Init(
+      get_helper_cb,
+      0,  // The output texture only has an array size of 1.
+      target, size, textures_per_picture);
+}
+
+}  // namespace media
diff --git a/media/gpu/windows/d3d11_copying_texture_wrapper.h b/media/gpu/windows/d3d11_copying_texture_wrapper.h
new file mode 100644
index 0000000..6524ea0
--- /dev/null
+++ b/media/gpu/windows/d3d11_copying_texture_wrapper.h
@@ -0,0 +1,44 @@
+// 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 MEDIA_GPU_WINDOWS_D3D11_COPYING_TEXTURE_WRAPPER_H_
+#define MEDIA_GPU_WINDOWS_D3D11_COPYING_TEXTURE_WRAPPER_H_
+
+#include <memory>
+#include <vector>
+
+#include "media/gpu/media_gpu_export.h"
+#include "media/gpu/windows/d3d11_picture_buffer.h"
+#include "media/gpu/windows/d3d11_video_processor_proxy.h"
+
+namespace media {
+
+// Uses D3D11VideoProcessor to convert between an input texture2D and an output
+// texture2D.
+class MEDIA_GPU_EXPORT CopyingTexture2DWrapper : public Texture2DWrapper {
+ public:
+  // |output_wrapper| must wrap a Texture2D which is a single-entry Texture,
+  // while |input_texture| may have multiple entries.
+  CopyingTexture2DWrapper(std::unique_ptr<Texture2DWrapper> output_wrapper,
+                          std::unique_ptr<VideoProcessorProxy> processor,
+                          ComD3D11Texture2D input_texture);
+  ~CopyingTexture2DWrapper() override;
+
+  bool ProcessTexture(const D3D11PictureBuffer* owner_pb,
+                      MailboxHolderArray* mailbox_dest) override;
+
+  bool Init(GetCommandBufferHelperCB get_helper_cb,
+            size_t array_slice,
+            GLenum target,
+            gfx::Size size,
+            int textures_per_picture) override;
+
+ private:
+  std::unique_ptr<VideoProcessorProxy> video_processor_;
+  std::unique_ptr<Texture2DWrapper> output_texture_wrapper_;
+};
+
+}  // namespace media
+
+#endif  // MEDIA_GPU_WINDOWS_D3D11_COPYING_TEXTURE_WRAPPER_H_
diff --git a/media/gpu/windows/d3d11_copying_texture_wrapper_unittest.cc b/media/gpu/windows/d3d11_copying_texture_wrapper_unittest.cc
new file mode 100644
index 0000000..33ed3e4
--- /dev/null
+++ b/media/gpu/windows/d3d11_copying_texture_wrapper_unittest.cc
@@ -0,0 +1,164 @@
+// 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 <utility>
+
+#include "base/bind_helpers.h"
+#include "media/gpu/windows/d3d11_copying_texture_wrapper.h"
+#include "media/gpu/windows/d3d11_texture_wrapper.h"
+#include "media/gpu/windows/d3d11_video_processor_proxy.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::_;
+using ::testing::Bool;
+using ::testing::Combine;
+using ::testing::Return;
+using ::testing::Values;
+
+namespace media {
+
+class MockVideoProcessorProxy : public VideoProcessorProxy {
+ public:
+  MockVideoProcessorProxy() : VideoProcessorProxy(nullptr, nullptr) {}
+
+  bool Init(uint32_t width, uint32_t height) override {
+    return MockInit(width, height);
+  }
+
+  HRESULT CreateVideoProcessorOutputView(
+      ID3D11Texture2D* output_texture,
+      D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC* output_view_descriptor,
+      ID3D11VideoProcessorOutputView** output_view) override {
+    return MockCreateVideoProcessorOutputView();
+  }
+
+  HRESULT CreateVideoProcessorInputView(
+      ID3D11Texture2D* input_texture,
+      D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC* input_view_descriptor,
+      ID3D11VideoProcessorInputView** input_view) override {
+    return MockCreateVideoProcessorInputView();
+  }
+
+  HRESULT VideoProcessorBlt(ID3D11VideoProcessorOutputView* output_view,
+                            UINT output_frameno,
+                            UINT stream_count,
+                            D3D11_VIDEO_PROCESSOR_STREAM* streams) override {
+    return MockVideoProcessorBlt();
+  }
+
+  MOCK_METHOD2(MockInit, bool(uint32_t, uint32_t));
+  MOCK_METHOD0(MockCreateVideoProcessorOutputView, HRESULT());
+  MOCK_METHOD0(MockCreateVideoProcessorInputView, HRESULT());
+  MOCK_METHOD0(MockVideoProcessorBlt, HRESULT());
+};
+
+class MockTexture2DWrapper : public Texture2DWrapper {
+ public:
+  MockTexture2DWrapper() : Texture2DWrapper(nullptr) {}
+
+  bool ProcessTexture(const D3D11PictureBuffer* owner_pb,
+                      MailboxHolderArray* mailbox_dest) override {
+    return MockProcessTexture();
+  }
+
+  bool Init(GetCommandBufferHelperCB get_helper_cb,
+            size_t array_slice,
+            GLenum target,
+            gfx::Size size,
+            int textures_per_picture) override {
+    return MockInit();
+  }
+
+  MOCK_METHOD0(MockInit, bool());
+  MOCK_METHOD0(MockProcessTexture, bool());
+};
+
+CommandBufferHelperPtr UselessHelper() {
+  return nullptr;
+}
+
+class D3D11CopyingTexture2DWrapperTest
+    : public ::testing::TestWithParam<
+          std::tuple<HRESULT, HRESULT, HRESULT, bool, bool, bool>> {
+ public:
+#define FIELD(TYPE, NAME, INDEX) \
+  TYPE Get##NAME() { return std::get<INDEX>(GetParam()); }
+  FIELD(HRESULT, CreateVideoProcessorOutputView, 0)
+  FIELD(HRESULT, CreateVideoProcessorInputView, 1)
+  FIELD(HRESULT, VideoProcessorBlt, 2)
+  FIELD(bool, ProcessorProxyInit, 3)
+  FIELD(bool, TextureWrapperInit, 4)
+  FIELD(bool, ProcessTexture, 5)
+#undef FIELD
+
+  std::unique_ptr<VideoProcessorProxy> ExpectProcessorProxy() {
+    auto result = std::make_unique<MockVideoProcessorProxy>();
+    ON_CALL(*result.get(), MockInit(_, _))
+        .WillByDefault(Return(GetProcessorProxyInit()));
+
+    ON_CALL(*result.get(), MockCreateVideoProcessorOutputView())
+        .WillByDefault(Return(GetCreateVideoProcessorOutputView()));
+
+    ON_CALL(*result.get(), MockCreateVideoProcessorInputView())
+        .WillByDefault(Return(GetCreateVideoProcessorInputView()));
+
+    ON_CALL(*result.get(), MockVideoProcessorBlt())
+        .WillByDefault(Return(GetVideoProcessorBlt()));
+
+    return std::move(result);
+  }
+
+  std::unique_ptr<Texture2DWrapper> ExpectTextureWrapper() {
+    auto result = std::make_unique<MockTexture2DWrapper>();
+
+    ON_CALL(*result.get(), MockInit())
+        .WillByDefault(Return(GetTextureWrapperInit()));
+
+    ON_CALL(*result.get(), MockProcessTexture())
+        .WillByDefault(Return(GetProcessTexture()));
+
+    return std::move(result);
+  }
+
+  GetCommandBufferHelperCB CreateMockHelperCB() {
+    return base::BindRepeating(&UselessHelper);
+  }
+
+  bool InitSucceeds() {
+    return GetProcessorProxyInit() && GetTextureWrapperInit();
+  }
+
+  bool ProcessTextureSucceeds() {
+    return GetProcessTexture() &&
+           SUCCEEDED(GetCreateVideoProcessorOutputView()) &&
+           SUCCEEDED(GetCreateVideoProcessorInputView()) &&
+           SUCCEEDED(GetVideoProcessorBlt());
+  }
+};
+
+INSTANTIATE_TEST_CASE_P(CopyingTexture2DWrapperTest,
+                        D3D11CopyingTexture2DWrapperTest,
+                        Combine(Values(S_OK, E_FAIL),
+                                Values(S_OK, E_FAIL),
+                                Values(S_OK, E_FAIL),
+                                Bool(),
+                                Bool(),
+                                Bool()));
+
+// For ever potential return value combination for the D3D11VideoProcessor,
+// make sure that any failures result in a total failure.
+TEST_P(D3D11CopyingTexture2DWrapperTest,
+       CopyingTextureWrapperProcessesCorrectly) {
+  auto wrapper = std::make_unique<CopyingTexture2DWrapper>(
+      ExpectTextureWrapper(), ExpectProcessorProxy(), nullptr);
+  auto picture_buffer = base::MakeRefCounted<D3D11PictureBuffer>(
+      GL_TEXTURE_EXTERNAL_OES, nullptr, gfx::Size(0, 0), 0);
+
+  EXPECT_EQ(wrapper->Init(CreateMockHelperCB(), 0, {}, {}, 0), InitSucceeds());
+  EXPECT_EQ(wrapper->ProcessTexture(picture_buffer.get(), nullptr),
+            ProcessTextureSucceeds());
+}
+
+}  // namespace media
diff --git a/media/gpu/windows/d3d11_decryptor.cc b/media/gpu/windows/d3d11_decryptor.cc
index 2049270..2585609 100644
--- a/media/gpu/windows/d3d11_decryptor.cc
+++ b/media/gpu/windows/d3d11_decryptor.cc
@@ -8,6 +8,7 @@
 #include "base/logging.h"
 #include "base/stl_util.h"
 #include "media/base/decoder_buffer.h"
+#include "media/gpu/windows/d3d11_com_defs.h"
 
 namespace media {
 
@@ -107,8 +108,7 @@
 // Checks whether |device1| is the same component as |device2|.
 // Note that comparing COM pointers require using their IUnknowns.
 // https://docs.microsoft.com/en-us/windows/desktop/api/unknwn/nf-unknwn-iunknown-queryinterface(q_)
-bool SameDevices(Microsoft::WRL::ComPtr<ID3D11Device> device1,
-                 Microsoft::WRL::ComPtr<ID3D11Device> device2) {
+bool SameDevices(ComD3D11Device device1, ComD3D11Device device2) {
   // For the case where both are nullptrs, they aren't devices, so returning
   // false here.
   if (!device1 || !device2)
diff --git a/media/gpu/windows/d3d11_h264_accelerator.cc b/media/gpu/windows/d3d11_h264_accelerator.cc
index edfcb6b..0159614 100644
--- a/media/gpu/windows/d3d11_h264_accelerator.cc
+++ b/media/gpu/windows/d3d11_h264_accelerator.cc
@@ -65,8 +65,8 @@
     D3D11VideoDecoderClient* client,
     MediaLog* media_log,
     CdmProxyContext* cdm_proxy_context,
-    Microsoft::WRL::ComPtr<ID3D11VideoDecoder> video_decoder,
-    Microsoft::WRL::ComPtr<ID3D11VideoDevice> video_device,
+    ComD3D11VideoDecoder video_decoder,
+    ComD3D11VideoDevice video_device,
     std::unique_ptr<VideoContextWrapper> video_context)
     : client_(client),
       media_log_(media_log),
diff --git a/media/gpu/windows/d3d11_h264_accelerator.h b/media/gpu/windows/d3d11_h264_accelerator.h
index 997d569..eeb0f642 100644
--- a/media/gpu/windows/d3d11_h264_accelerator.h
+++ b/media/gpu/windows/d3d11_h264_accelerator.h
@@ -16,6 +16,7 @@
 #include "media/base/video_frame.h"
 #include "media/gpu/h264_decoder.h"
 #include "media/gpu/h264_dpb.h"
+#include "media/gpu/windows/d3d11_com_defs.h"
 #include "media/gpu/windows/d3d11_video_context_wrapper.h"
 #include "media/gpu/windows/d3d11_video_decoder_client.h"
 #include "media/gpu/windows/return_on_failure.h"
@@ -36,8 +37,8 @@
   D3D11H264Accelerator(D3D11VideoDecoderClient* client,
                        MediaLog* media_log,
                        CdmProxyContext* cdm_proxy_context,
-                       Microsoft::WRL::ComPtr<ID3D11VideoDecoder> video_decoder,
-                       Microsoft::WRL::ComPtr<ID3D11VideoDevice> video_device,
+                       ComD3D11VideoDecoder video_decoder,
+                       ComD3D11VideoDevice video_device,
                        std::unique_ptr<VideoContextWrapper> video_context);
   ~D3D11H264Accelerator() override;
 
@@ -91,8 +92,8 @@
   MediaLog* media_log_ = nullptr;
   CdmProxyContext* const cdm_proxy_context_;
 
-  Microsoft::WRL::ComPtr<ID3D11VideoDecoder> video_decoder_;
-  Microsoft::WRL::ComPtr<ID3D11VideoDevice> video_device_;
+  ComD3D11VideoDecoder video_decoder_;
+  ComD3D11VideoDevice video_device_;
   std::unique_ptr<VideoContextWrapper> video_context_;
 
   // This information set at the beginning of a frame and saved for processing
diff --git a/media/gpu/windows/d3d11_picture_buffer.cc b/media/gpu/windows/d3d11_picture_buffer.cc
index 19c2838..781e873 100644
--- a/media/gpu/windows/d3d11_picture_buffer.cc
+++ b/media/gpu/windows/d3d11_picture_buffer.cc
@@ -66,8 +66,8 @@
   return true;
 }
 
-const MailboxHolderArray& D3D11PictureBuffer::ProcessTexture() const {
-  return texture_wrapper_->ProcessTexture(this);
+bool D3D11PictureBuffer::ProcessTexture(MailboxHolderArray* mailbox_dest) {
+  return texture_wrapper_->ProcessTexture(this, mailbox_dest);
 }
 
 ComD3D11Texture2D D3D11PictureBuffer::Texture() const {
diff --git a/media/gpu/windows/d3d11_picture_buffer.h b/media/gpu/windows/d3d11_picture_buffer.h
index 26874eee..5e5ee6e 100644
--- a/media/gpu/windows/d3d11_picture_buffer.h
+++ b/media/gpu/windows/d3d11_picture_buffer.h
@@ -61,8 +61,8 @@
             int textures_per_picture,
             std::unique_ptr<MediaLog> media_log);
 
-  // Return the mailbox holders that can be used to create a VideoFrame for us.
-  const MailboxHolderArray& ProcessTexture() const;
+  // Set the contents of a mailbox holder array, return true if successful.
+  bool ProcessTexture(MailboxHolderArray* mailbox_dest);
   ComD3D11Texture2D Texture() const;
 
   const gfx::Size& size() const { return size_; }
diff --git a/media/gpu/windows/d3d11_texture_wrapper.cc b/media/gpu/windows/d3d11_texture_wrapper.cc
index 66b9e73..9776f8f 100644
--- a/media/gpu/windows/d3d11_texture_wrapper.cc
+++ b/media/gpu/windows/d3d11_texture_wrapper.cc
@@ -24,9 +24,11 @@
     : Texture2DWrapper(texture) {}
 DefaultTexture2DWrapper::~DefaultTexture2DWrapper() {}
 
-const MailboxHolderArray& DefaultTexture2DWrapper::ProcessTexture(
-    const D3D11PictureBuffer* owner_pb) {
-  return mailbox_holders_;
+bool DefaultTexture2DWrapper::ProcessTexture(const D3D11PictureBuffer* owner_pb,
+                                             MailboxHolderArray* mailbox_dest) {
+  for (size_t i = 0; i < VideoFrame::kMaxPlanes; i++)
+    (*mailbox_dest)[i] = mailbox_holders_[i];
+  return true;
 }
 
 bool DefaultTexture2DWrapper::Init(GetCommandBufferHelperCB get_helper_cb,
diff --git a/media/gpu/windows/d3d11_texture_wrapper.h b/media/gpu/windows/d3d11_texture_wrapper.h
index 0ed14d7..b3ac8c4a 100644
--- a/media/gpu/windows/d3d11_texture_wrapper.h
+++ b/media/gpu/windows/d3d11_texture_wrapper.h
@@ -15,6 +15,7 @@
 #include "media/base/video_frame.h"
 #include "media/gpu/command_buffer_helper.h"
 #include "media/gpu/media_gpu_export.h"
+#include "media/gpu/windows/d3d11_com_defs.h"
 #include "ui/gl/gl_bindings.h"
 #include "ui/gl/gl_context.h"
 #include "ui/gl/gl_image_dxgi.h"
@@ -27,10 +28,6 @@
 using MailboxHolderArray = gpu::MailboxHolder[VideoFrame::kMaxPlanes];
 using GetCommandBufferHelperCB =
     base::RepeatingCallback<CommandBufferHelperPtr()>;
-using ComD3D11VideoDevice = Microsoft::WRL::ComPtr<ID3D11VideoDevice>;
-using ComD3D11Texture2D = Microsoft::WRL::ComPtr<ID3D11Texture2D>;
-using ComD3D11VideoDecoderOutputView =
-    Microsoft::WRL::ComPtr<ID3D11VideoDecoderOutputView>;
 
 class D3D11PictureBuffer;
 
@@ -45,9 +42,13 @@
 
   // This pointer can be raw, since each Texture2DWrapper is directly owned
   // by the D3D11PictureBuffer through a unique_ptr.
-  virtual const MailboxHolderArray& ProcessTexture(
-      const D3D11PictureBuffer* owner_pb) = 0;
+  virtual bool ProcessTexture(const D3D11PictureBuffer* owner_pb,
+                              MailboxHolderArray* mailbox_dest) = 0;
 
+  // |array_slice| Tells us which array index of the array-type Texture2D
+  // we should be using - if it is not an array-type, |array_slice| is 0.
+  // |textures_per_picture| is the number of entries present in an array-type
+  // Texture2D. It is 1 otherwise.
   virtual bool Init(GetCommandBufferHelperCB get_helper_cb,
                     size_t array_slice,
                     GLenum target,
@@ -71,8 +72,8 @@
             gfx::Size size,
             int textures_per_picture) override;
 
-  const MailboxHolderArray& ProcessTexture(
-      const D3D11PictureBuffer* owner_pb) override;
+  bool ProcessTexture(const D3D11PictureBuffer* owner_pb,
+                      MailboxHolderArray* mailbox_dest) override;
 
  private:
   // Things that are to be accessed / freed only on the main thread.  In
diff --git a/media/gpu/windows/d3d11_video_context_wrapper.cc b/media/gpu/windows/d3d11_video_context_wrapper.cc
index 45d05547..c17bdc7a 100644
--- a/media/gpu/windows/d3d11_video_context_wrapper.cc
+++ b/media/gpu/windows/d3d11_video_context_wrapper.cc
@@ -19,7 +19,7 @@
 template <>
 struct BufferSubmitter<ID3D11VideoContext1> {
   static HRESULT SubmitDecoderBuffers(
-      Microsoft::WRL::ComPtr<ID3D11VideoContext1> context,
+      ComD3D11VideoContext1 context,
       ID3D11VideoDecoder* decoder,
       const UINT num_buffers,
       const VideoContextWrapper::VideoBufferWrapper* src) {
@@ -42,7 +42,7 @@
 template <>
 struct BufferSubmitter<ID3D11VideoContext> {
   static HRESULT SubmitDecoderBuffers(
-      Microsoft::WRL::ComPtr<ID3D11VideoContext> context,
+      ComD3D11VideoContext context,
       ID3D11VideoDecoder* decoder,
       const UINT num_buffers,
       const VideoContextWrapper::VideoBufferWrapper* src) {
@@ -110,17 +110,17 @@
 
 std::unique_ptr<VideoContextWrapper> VideoContextWrapper::CreateWrapper(
     D3D_FEATURE_LEVEL supported_d3d11_version,
-    Microsoft::WRL::ComPtr<ID3D11DeviceContext> device_context,
+    ComD3D11DeviceContext device_context,
     HRESULT* status) {
   if (supported_d3d11_version == D3D_FEATURE_LEVEL_11_0) {
-    Microsoft::WRL::ComPtr<ID3D11VideoContext> video_context;
+    ComD3D11VideoContext video_context;
     *status = device_context.CopyTo(video_context.ReleaseAndGetAddressOf());
     return std::make_unique<VideoContextWrapperImpl<ID3D11VideoContext>>(
         video_context);
   }
 
   if (supported_d3d11_version == D3D_FEATURE_LEVEL_11_1) {
-    Microsoft::WRL::ComPtr<ID3D11VideoContext1> video_context;
+    ComD3D11VideoContext1 video_context;
     *status = device_context.CopyTo(video_context.ReleaseAndGetAddressOf());
     return std::make_unique<VideoContextWrapperImpl<ID3D11VideoContext1>>(
         video_context);
diff --git a/media/gpu/windows/d3d11_video_context_wrapper.h b/media/gpu/windows/d3d11_video_context_wrapper.h
index 71649aac..f4cef4a 100644
--- a/media/gpu/windows/d3d11_video_context_wrapper.h
+++ b/media/gpu/windows/d3d11_video_context_wrapper.h
@@ -11,6 +11,7 @@
 
 #include "base/macros.h"
 #include "media/gpu/media_gpu_export.h"
+#include "media/gpu/windows/d3d11_com_defs.h"
 
 namespace media {
 
@@ -40,7 +41,7 @@
 
   static std::unique_ptr<VideoContextWrapper> CreateWrapper(
       D3D_FEATURE_LEVEL supported_d3d11_version,
-      Microsoft::WRL::ComPtr<ID3D11DeviceContext> device_context,
+      ComD3D11DeviceContext device_context,
       HRESULT* status);
 
   // This method signiture is defined to match exactly that of
diff --git a/media/gpu/windows/d3d11_video_decoder.cc b/media/gpu/windows/d3d11_video_decoder.cc
index 5f4d9ca6..f61b8dbd 100644
--- a/media/gpu/windows/d3d11_video_decoder.cc
+++ b/media/gpu/windows/d3d11_video_decoder.cc
@@ -111,8 +111,7 @@
   return texture_desc;
 }
 
-bool TextureSelector::SupportsDevice(
-    Microsoft::WRL::ComPtr<ID3D11VideoDevice> video_device) {
+bool TextureSelector::SupportsDevice(ComD3D11VideoDevice video_device) {
   for (UINT i = video_device->GetVideoDecoderProfileCount(); i--;) {
     GUID profile = {};
     if (SUCCEEDED(video_device->GetVideoDecoderProfile(i, &profile))) {
@@ -227,7 +226,7 @@
 HRESULT D3D11VideoDecoder::InitializeAcceleratedDecoder(
     const VideoDecoderConfig& config,
     CdmProxyContext* proxy_context,
-    Microsoft::WRL::ComPtr<ID3D11VideoDecoder> video_decoder) {
+    ComD3D11VideoDecoder video_decoder) {
   // If we got an 11.1 D3D11 Device, we can use a |ID3D11VideoContext1|,
   // otherwise we have to make sure we only use a |ID3D11VideoContext|.
   HRESULT hr;
@@ -342,7 +341,7 @@
   }
 
   // TODO(liberato): dxva does this.  don't know if we need to.
-  Microsoft::WRL::ComPtr<ID3D11Multithread> multi_threaded;
+  ComD3D11Multithread multi_threaded;
   hr = device_->QueryInterface(IID_PPV_ARGS(&multi_threaded));
   if (!SUCCEEDED(hr)) {
     NotifyError("Failed to query ID3D11Multithread");
@@ -394,7 +393,7 @@
     return;
   }
 
-  Microsoft::WRL::ComPtr<ID3D11VideoDecoder> video_decoder;
+  ComD3D11VideoDecoder video_decoder;
   hr = video_device_->CreateVideoDecoder(
       &desc, &dec_config, video_decoder.ReleaseAndGetAddressOf());
   if (!video_decoder.Get()) {
@@ -655,7 +654,7 @@
   D3D11_TEXTURE2D_DESC texture_desc =
       texture_selector_->TextureDescriptor(size);
 
-  Microsoft::WRL::ComPtr<ID3D11Texture2D> out_texture;
+  ComD3D11Texture2D out_texture;
   HRESULT hr = device_->CreateTexture2D(&texture_desc, nullptr,
                                         out_texture.ReleaseAndGetAddressOf());
   if (!SUCCEEDED(hr)) {
@@ -713,8 +712,15 @@
   double pixel_aspect_ratio = config_.GetPixelAspectRatio();
 
   base::TimeDelta timestamp = picture_buffer->timestamp_;
+
+  MailboxHolderArray mailbox_holders;
+  if (!picture_buffer->ProcessTexture(&mailbox_holders)) {
+    NotifyError("Unable to process texture");
+    return;
+  }
+
   scoped_refptr<VideoFrame> frame = VideoFrame::WrapNativeTextures(
-      texture_selector_->pixel_format, picture_buffer->ProcessTexture(),
+      texture_selector_->pixel_format, mailbox_holders,
       VideoFrame::ReleaseMailboxCB(), picture_buffer->size(), visible_rect,
       GetNaturalSize(visible_rect, pixel_aspect_ratio), timestamp);
 
diff --git a/media/gpu/windows/d3d11_video_decoder.h b/media/gpu/windows/d3d11_video_decoder.h
index e54297a..369b643 100644
--- a/media/gpu/windows/d3d11_video_decoder.h
+++ b/media/gpu/windows/d3d11_video_decoder.h
@@ -21,6 +21,7 @@
 #include "media/base/win/d3d11_create_device_cb.h"
 #include "media/gpu/command_buffer_helper.h"
 #include "media/gpu/media_gpu_export.h"
+#include "media/gpu/windows/d3d11_com_defs.h"
 #include "media/gpu/windows/d3d11_h264_accelerator.h"
 #include "media/gpu/windows/d3d11_video_decoder_client.h"
 #include "media/gpu/windows/d3d11_vp9_accelerator.h"
@@ -58,7 +59,7 @@
 
   D3D11_VIDEO_DECODER_DESC DecoderDescriptor(gfx::Size size);
   D3D11_TEXTURE2D_DESC TextureDescriptor(gfx::Size size);
-  bool SupportsDevice(Microsoft::WRL::ComPtr<ID3D11VideoDevice> video_device);
+  bool SupportsDevice(ComD3D11VideoDevice video_device);
 
   const VideoPixelFormat pixel_format;
   const DXGI_FORMAT dxgi_format;
@@ -80,8 +81,7 @@
                                            public D3D11VideoDecoderClient {
  public:
   // Callback to get a D3D11 device.
-  using GetD3D11DeviceCB =
-      base::RepeatingCallback<Microsoft::WRL::ComPtr<ID3D11Device>()>;
+  using GetD3D11DeviceCB = base::RepeatingCallback<ComD3D11Device()>;
 
   // List of configs that we'll check against when initializing.  This is only
   // needed since GpuMojoMediaClient merges our supported configs with the VDA
@@ -154,10 +154,9 @@
   void DoDecode();
 
   // instantiate |accelerated_video_decoder_| based on the video profile
-  HRESULT InitializeAcceleratedDecoder(
-      const VideoDecoderConfig& config,
-      CdmProxyContext* proxy_context,
-      Microsoft::WRL::ComPtr<ID3D11VideoDecoder> video_decoder);
+  HRESULT InitializeAcceleratedDecoder(const VideoDecoderConfig& config,
+                                       CdmProxyContext* proxy_context,
+                                       ComD3D11VideoDecoder video_decoder);
 
   // Query the video device for a specific decoder ID.
   bool DeviceHasDecoderID(GUID decoder_guid);
@@ -255,9 +254,9 @@
   // the ANGLE device for display (plus texture sharing, if needed).
   GetD3D11DeviceCB get_d3d11_device_cb_;
 
-  Microsoft::WRL::ComPtr<ID3D11Device> device_;
-  Microsoft::WRL::ComPtr<ID3D11DeviceContext> device_context_;
-  Microsoft::WRL::ComPtr<ID3D11VideoDevice> video_device_;
+  ComD3D11Device device_;
+  ComD3D11DeviceContext device_context_;
+  ComD3D11VideoDevice video_device_;
 
   // D3D11 version on this device.
   D3D_FEATURE_LEVEL usable_feature_level_;
diff --git a/media/gpu/windows/d3d11_video_processor_proxy.cc b/media/gpu/windows/d3d11_video_processor_proxy.cc
new file mode 100644
index 0000000..c35a028
--- /dev/null
+++ b/media/gpu/windows/d3d11_video_processor_proxy.cc
@@ -0,0 +1,74 @@
+// 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 "media/gpu/windows/d3d11_video_processor_proxy.h"
+
+namespace media {
+
+VideoProcessorProxy::~VideoProcessorProxy() {}
+
+VideoProcessorProxy::VideoProcessorProxy(
+    ComD3D11VideoDevice video_device,
+    ComD3D11DeviceContext d3d11_device_context)
+    : video_device_(video_device), device_context_(d3d11_device_context) {}
+
+bool VideoProcessorProxy::Init(uint32_t width, uint32_t height) {
+  processor_enumerator_.Reset();
+  video_processor_.Reset();
+
+  D3D11_VIDEO_PROCESSOR_CONTENT_DESC desc;
+  desc.InputFrameFormat = D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE;
+  desc.InputFrameRate.Numerator = 60;
+  desc.InputFrameRate.Denominator = 1;
+  desc.InputWidth = width;
+  desc.InputHeight = height;
+  desc.OutputFrameRate.Numerator = 60;
+  desc.OutputFrameRate.Denominator = 1;
+  desc.OutputWidth = width;
+  desc.OutputHeight = height;
+  desc.Usage = D3D11_VIDEO_USAGE_PLAYBACK_NORMAL;
+
+  if (!SUCCEEDED(video_device_->CreateVideoProcessorEnumerator(
+          &desc, &processor_enumerator_)))
+    return false;
+
+  if (!SUCCEEDED(video_device_->CreateVideoProcessor(
+          processor_enumerator_.Get(), 0, &video_processor_)))
+    return false;
+
+  if (!SUCCEEDED(device_context_.As(&video_context_)))
+    return false;
+
+  return true;
+}
+
+HRESULT VideoProcessorProxy::CreateVideoProcessorOutputView(
+    ID3D11Texture2D* output_texture,
+    D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC* output_view_descriptor,
+    ID3D11VideoProcessorOutputView** output_view) {
+  return video_device_->CreateVideoProcessorOutputView(
+      output_texture, processor_enumerator_.Get(), output_view_descriptor,
+      output_view);
+}
+
+HRESULT VideoProcessorProxy::CreateVideoProcessorInputView(
+    ID3D11Texture2D* input_texture,
+    D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC* input_view_descriptor,
+    ID3D11VideoProcessorInputView** input_view) {
+  return video_device_->CreateVideoProcessorInputView(
+      input_texture, processor_enumerator_.Get(), input_view_descriptor,
+      input_view);
+}
+
+HRESULT VideoProcessorProxy::VideoProcessorBlt(
+    ID3D11VideoProcessorOutputView* output_view,
+    UINT output_frameno,
+    UINT stream_count,
+    D3D11_VIDEO_PROCESSOR_STREAM* streams) {
+  return video_context_->VideoProcessorBlt(video_processor_.Get(), output_view,
+                                           output_frameno, stream_count,
+                                           streams);
+}
+
+}  // namespace media
diff --git a/media/gpu/windows/d3d11_video_processor_proxy.h b/media/gpu/windows/d3d11_video_processor_proxy.h
new file mode 100644
index 0000000..d705090
--- /dev/null
+++ b/media/gpu/windows/d3d11_video_processor_proxy.h
@@ -0,0 +1,54 @@
+// 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 MEDIA_GPU_WINDOWS_D3D11_VIDEO_PROCESSOR_PROXY_H_
+#define MEDIA_GPU_WINDOWS_D3D11_VIDEO_PROCESSOR_PROXY_H_
+
+#include <d3d11.h>
+#include <wrl/client.h>
+#include <cstdint>
+
+#include "media/gpu/media_gpu_export.h"
+#include "media/gpu/windows/d3d11_com_defs.h"
+
+namespace media {
+
+// Wrap ID3D11VideoProcessor to provide nicer methods for initialization,
+// color space modification, and output/input view creation.
+class MEDIA_GPU_EXPORT VideoProcessorProxy {
+ public:
+  VideoProcessorProxy(ComD3D11VideoDevice video_device,
+                      ComD3D11DeviceContext d3d11_device_context);
+  virtual ~VideoProcessorProxy();
+
+  virtual bool Init(uint32_t width, uint32_t height);
+
+  // TODO(tmathmeyer) implement color space modification.
+
+  virtual HRESULT CreateVideoProcessorOutputView(
+      ID3D11Texture2D* output_texture,
+      D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC* output_view_descriptor,
+      ID3D11VideoProcessorOutputView** output_view);
+
+  virtual HRESULT CreateVideoProcessorInputView(
+      ID3D11Texture2D* input_texture,
+      D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC* input_view_descriptor,
+      ID3D11VideoProcessorInputView** input_view);
+
+  virtual HRESULT VideoProcessorBlt(ID3D11VideoProcessorOutputView* output_view,
+                                    UINT output_frameno,
+                                    UINT stream_count,
+                                    D3D11_VIDEO_PROCESSOR_STREAM* streams);
+
+ private:
+  ComD3D11VideoDevice video_device_;
+  ComD3D11VideoProcessorEnumerator processor_enumerator_;
+  ComD3D11VideoProcessor video_processor_;
+  ComD3D11DeviceContext device_context_;
+  ComD3D11VideoContext video_context_;
+};
+
+}  // namespace media
+
+#endif  // MEDIA_GPU_WINDOWS_D3D11_VIDEO_PROCESSOR_PROXY_H_
diff --git a/media/gpu/windows/d3d11_video_processor_proxy_unittest.cc b/media/gpu/windows/d3d11_video_processor_proxy_unittest.cc
new file mode 100644
index 0000000..9d411644
--- /dev/null
+++ b/media/gpu/windows/d3d11_video_processor_proxy_unittest.cc
@@ -0,0 +1,95 @@
+// 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 <random>
+#include <utility>
+
+#include "base/bind_helpers.h"
+#include "media/base/win/d3d11_mocks.h"
+#include "media/gpu/windows/d3d11_copying_texture_wrapper.h"
+#include "media/gpu/windows/d3d11_texture_wrapper.h"
+#include "media/gpu/windows/d3d11_video_processor_proxy.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::_;
+using ::testing::DoAll;
+using ::testing::Return;
+using ::testing::SetArgPointee;
+
+namespace media {
+
+using MockD3D11VideoDevice = Microsoft::WRL::ComPtr<D3D11VideoDeviceMock>;
+using MockD3D11DeviceContext = Microsoft::WRL::ComPtr<D3D11DeviceContextMock>;
+using MockD3D11VideoContext = Microsoft::WRL::ComPtr<D3D11VideoContextMock>;
+using MockD3D11VideoProcessor = Microsoft::WRL::ComPtr<D3D11VideoProcessorMock>;
+using MockD3D11VideoProcessorEnumerator =
+    Microsoft::WRL::ComPtr<D3D11VideoProcessorEnumeratorMock>;
+
+class D3D11VideoProcessorProxyUnittest : public ::testing::Test {
+ public:
+  MockD3D11VideoDevice dev_;
+  MockD3D11DeviceContext ctx_;
+  MockD3D11VideoContext vctx_;
+  MockD3D11VideoProcessorEnumerator enumerator_;
+  MockD3D11VideoProcessor proc_;
+
+  std::unique_ptr<VideoProcessorProxy> CreateProxy() {
+    dev_ = CreateD3D11Mock<D3D11VideoDeviceMock>();
+    ctx_ = CreateD3D11Mock<D3D11DeviceContextMock>();
+    vctx_ = CreateD3D11Mock<D3D11VideoContextMock>();
+    proc_ = CreateD3D11Mock<D3D11VideoProcessorMock>();
+    enumerator_ = CreateD3D11Mock<D3D11VideoProcessorEnumeratorMock>();
+
+    EXPECT_CALL(*dev_.Get(), CreateVideoProcessorEnumerator(_, _))
+        .WillOnce(SetComPointeeAndReturnOk<1>(enumerator_.Get()));
+
+    EXPECT_CALL(*dev_.Get(), CreateVideoProcessor(_, _, _))
+        .WillOnce(SetComPointeeAndReturnOk<2>(proc_.Get()));
+
+    EXPECT_CALL(*ctx_.Get(), QueryInterface(_, _))
+        .WillOnce(SetComPointeeAndReturnOk<1>(vctx_.Get()));
+
+    return std::make_unique<VideoProcessorProxy>(dev_, ctx_);
+  }
+
+  // Pull a random pointer off the stack, rather than relying on nullptrs.
+  template <typename T>
+  T* CreateGarbagePtr() {
+    int foo;
+    void* local = &foo;
+    return static_cast<T*>(local);
+  }
+};
+
+// The processor proxy wraps the VideoDevice/VideoContext and stores some of the
+// d3d11 types. Make sure that the arguments we give these methods are passed
+// through correctly.
+TEST_F(D3D11VideoProcessorProxyUnittest, EnsureMethodPassthrough) {
+  auto proxy = CreateProxy();
+
+  // Garbage pointers are used because the proxy just passes them along and does
+  // absolutely nothing with them.
+  auto* texture = CreateGarbagePtr<ID3D11Texture2D>();
+  auto* out_desc = CreateGarbagePtr<D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC>();
+  auto* in_desc = CreateGarbagePtr<D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC>();
+  auto* out_view = CreateGarbagePtr<ID3D11VideoProcessorOutputView>();
+  auto* streams = CreateGarbagePtr<D3D11_VIDEO_PROCESSOR_STREAM>();
+
+  EXPECT_CALL(*dev_.Get(), CreateVideoProcessorOutputView(
+                               texture, enumerator_.Get(), out_desc, nullptr));
+
+  EXPECT_CALL(*dev_.Get(), CreateVideoProcessorInputView(
+                               texture, enumerator_.Get(), in_desc, nullptr));
+
+  EXPECT_CALL(*vctx_.Get(),
+              VideoProcessorBlt(proc_.Get(), out_view, 6, 7, streams));
+
+  EXPECT_TRUE(proxy->Init(0, 0));
+  proxy->CreateVideoProcessorOutputView(texture, out_desc, nullptr);
+  proxy->CreateVideoProcessorInputView(texture, in_desc, nullptr);
+  proxy->VideoProcessorBlt(out_view, 6, 7, streams);
+}
+
+}  // namespace media
diff --git a/media/gpu/windows/d3d11_vp9_accelerator.cc b/media/gpu/windows/d3d11_vp9_accelerator.cc
index c2157b5..f185a93 100644
--- a/media/gpu/windows/d3d11_vp9_accelerator.cc
+++ b/media/gpu/windows/d3d11_vp9_accelerator.cc
@@ -38,8 +38,8 @@
     D3D11VideoDecoderClient* client,
     MediaLog* media_log,
     CdmProxyContext* cdm_proxy_context,
-    Microsoft::WRL::ComPtr<ID3D11VideoDecoder> video_decoder,
-    Microsoft::WRL::ComPtr<ID3D11VideoDevice> video_device,
+    ComD3D11VideoDecoder video_decoder,
+    ComD3D11VideoDevice video_device,
     std::unique_ptr<VideoContextWrapper> video_context)
     : client_(client),
       media_log_(media_log),
diff --git a/media/gpu/windows/d3d11_vp9_accelerator.h b/media/gpu/windows/d3d11_vp9_accelerator.h
index c75505d7..861752b 100644
--- a/media/gpu/windows/d3d11_vp9_accelerator.h
+++ b/media/gpu/windows/d3d11_vp9_accelerator.h
@@ -12,6 +12,7 @@
 
 #include "media/base/media_log.h"
 #include "media/gpu/vp9_decoder.h"
+#include "media/gpu/windows/d3d11_com_defs.h"
 #include "media/gpu/windows/d3d11_video_context_wrapper.h"
 #include "media/gpu/windows/d3d11_video_decoder_client.h"
 #include "media/gpu/windows/d3d11_vp9_picture.h"
@@ -24,8 +25,8 @@
   D3D11VP9Accelerator(D3D11VideoDecoderClient* client,
                       MediaLog* media_log,
                       CdmProxyContext* cdm_proxy_context,
-                      Microsoft::WRL::ComPtr<ID3D11VideoDecoder> video_decoder,
-                      Microsoft::WRL::ComPtr<ID3D11VideoDevice> video_device,
+                      ComD3D11VideoDecoder video_decoder,
+                      ComD3D11VideoDevice video_device,
                       std::unique_ptr<VideoContextWrapper> video_context);
   ~D3D11VP9Accelerator() override;
 
@@ -73,8 +74,8 @@
   MediaLog* const media_log_;
   CdmProxyContext* cdm_proxy_context_;
   UINT status_feedback_;
-  Microsoft::WRL::ComPtr<ID3D11VideoDecoder> video_decoder_;
-  Microsoft::WRL::ComPtr<ID3D11VideoDevice> video_device_;
+  ComD3D11VideoDecoder video_decoder_;
+  ComD3D11VideoDevice video_device_;
   std::unique_ptr<VideoContextWrapper> video_context_;
 
   DISALLOW_COPY_AND_ASSIGN(D3D11VP9Accelerator);
diff --git a/media/gpu/windows/dxva_picture_buffer_win.cc b/media/gpu/windows/dxva_picture_buffer_win.cc
index 1e82740..5ffc851 100644
--- a/media/gpu/windows/dxva_picture_buffer_win.cc
+++ b/media/gpu/windows/dxva_picture_buffer_win.cc
@@ -609,8 +609,7 @@
   RETURN_ON_FAILURE(result, "Could not create stream producer", false);
   scoped_refptr<gl::CopyingGLImageDXGI> copying_image_ =
       base::MakeRefCounted<gl::CopyingGLImageDXGI>(
-          Microsoft::WRL::ComPtr<ID3D11Device>(decoder.D3D11Device()), size(),
-          stream_);
+          ComD3D11Device(decoder.D3D11Device()), size(), stream_);
   gl_image_ = copying_image_;
   return copying_image_->Initialize();
 }
diff --git a/media/gpu/windows/dxva_picture_buffer_win.h b/media/gpu/windows/dxva_picture_buffer_win.h
index d38e6a1..891e763 100644
--- a/media/gpu/windows/dxva_picture_buffer_win.h
+++ b/media/gpu/windows/dxva_picture_buffer_win.h
@@ -12,6 +12,7 @@
 
 #include <memory>
 
+#include "media/gpu/windows/d3d11_com_defs.h"
 #include "media/video/picture.h"
 #include "third_party/angle/include/EGL/egl.h"
 #include "third_party/angle/include/EGL/eglext.h"
@@ -129,7 +130,7 @@
 
   HANDLE texture_share_handle_;
   Microsoft::WRL::ComPtr<IDirect3DTexture9> decoding_texture_;
-  Microsoft::WRL::ComPtr<ID3D11Texture2D> dx11_decoding_texture_;
+  ComD3D11Texture2D dx11_decoding_texture_;
 
   Microsoft::WRL::ComPtr<IDXGIKeyedMutex> egl_keyed_mutex_;
   Microsoft::WRL::ComPtr<IDXGIKeyedMutex> dx11_keyed_mutex_;
@@ -147,7 +148,7 @@
   // This ID3D11Texture2D interface pointer is used to hold a reference to the
   // decoder texture during the course of a copy operation. This reference is
   // released when the copy completes.
-  Microsoft::WRL::ComPtr<ID3D11Texture2D> decoder_dx11_texture_;
+  ComD3D11Texture2D decoder_dx11_texture_;
 
   // Set to true if RGB is supported by the texture.
   // Defaults to true.
@@ -171,7 +172,7 @@
   EGLStreamKHR stream_;
 
   Microsoft::WRL::ComPtr<IMFSample> current_d3d_sample_;
-  Microsoft::WRL::ComPtr<ID3D11Texture2D> dx11_decoding_texture_;
+  ComD3D11Texture2D dx11_decoding_texture_;
 };
 
 // Shares the decoded texture with ANGLE without copying by using an EGL stream.
@@ -191,7 +192,7 @@
   EGLStreamKHR stream_;
 
   Microsoft::WRL::ComPtr<IMFSample> current_d3d_sample_;
-  Microsoft::WRL::ComPtr<ID3D11Texture2D> dx11_decoding_texture_;
+  ComD3D11Texture2D dx11_decoding_texture_;
 };
 
 // Creates an NV12 texture and copies to it, then shares that with ANGLE.
@@ -218,7 +219,7 @@
   // This ID3D11Texture2D interface pointer is used to hold a reference to the
   // MFT decoder texture during the course of a copy operation. This reference
   // is released when the copy completes.
-  Microsoft::WRL::ComPtr<ID3D11Texture2D> dx11_decoding_texture_;
+  ComD3D11Texture2D dx11_decoding_texture_;
 
   Microsoft::WRL::ComPtr<IDXGIKeyedMutex> egl_keyed_mutex_;
   Microsoft::WRL::ComPtr<IDXGIKeyedMutex> dx11_keyed_mutex_;
@@ -226,10 +227,10 @@
   HANDLE texture_share_handle_;
   // This is the texture (created on ANGLE's device) that will be put in the
   // EGLStream.
-  Microsoft::WRL::ComPtr<ID3D11Texture2D> angle_copy_texture_;
+  ComD3D11Texture2D angle_copy_texture_;
   // This is another copy of that shared resource that will be copied to from
   // the decoder.
-  Microsoft::WRL::ComPtr<ID3D11Texture2D> decoder_copy_texture_;
+  ComD3D11Texture2D decoder_copy_texture_;
 
   // This is the last value that was used to release the keyed mutex.
   uint64_t keyed_mutex_value_ = 0;
diff --git a/media/gpu/windows/dxva_video_decode_accelerator_win.cc b/media/gpu/windows/dxva_video_decode_accelerator_win.cc
index 0bb051f..55196204 100644
--- a/media/gpu/windows/dxva_video_decode_accelerator_win.cc
+++ b/media/gpu/windows/dxva_video_decode_accelerator_win.cc
@@ -1427,13 +1427,12 @@
     // To detect if a driver supports the desired resolutions, we try and create
     // a DXVA decoder instance for that resolution and profile. If that succeeds
     // we assume that the driver supports decoding for that resolution.
-    Microsoft::WRL::ComPtr<ID3D11Device> device =
-        gl::QueryD3D11DeviceObjectFromANGLE();
+    ComD3D11Device device = gl::QueryD3D11DeviceObjectFromANGLE();
 
     // Legacy AMD drivers with UVD3 or earlier and some Intel GPU's crash while
     // creating surfaces larger than 1920 x 1088.
     if (device && !IsLegacyGPU(device.Get())) {
-      Microsoft::WRL::ComPtr<ID3D11VideoDevice> video_device;
+      ComD3D11VideoDevice video_device;
       if (SUCCEEDED(device.As(&video_device))) {
         max_h264_resolutions = GetMaxResolutionsForGUIDs(
             max_h264_resolutions.first, video_device.Get(),
@@ -2035,7 +2034,7 @@
           hr, "Failed to get buffer from output sample", PLATFORM_FAILURE, );
 
       Microsoft::WRL::ComPtr<IDirect3DSurface9> surface;
-      Microsoft::WRL::ComPtr<ID3D11Texture2D> d3d11_texture;
+      ComD3D11Texture2D d3d11_texture;
 
       if (use_dx11_) {
         Microsoft::WRL::ComPtr<IMFDXGIBuffer> dxgi_buffer;
@@ -2790,7 +2789,7 @@
   RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to get resource index",
                                   PLATFORM_FAILURE, );
 
-  Microsoft::WRL::ComPtr<ID3D11Texture2D> dx11_decoding_texture;
+  ComD3D11Texture2D dx11_decoding_texture;
   hr = dxgi_buffer->GetResource(IID_PPV_ARGS(&dx11_decoding_texture));
   RETURN_AND_NOTIFY_ON_HR_FAILURE(
       hr, "Failed to get resource from output sample", PLATFORM_FAILURE, );
@@ -2798,7 +2797,7 @@
   D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC output_view_desc = {
       D3D11_VPOV_DIMENSION_TEXTURE2D};
   output_view_desc.Texture2D.MipSlice = 0;
-  Microsoft::WRL::ComPtr<ID3D11VideoProcessorOutputView> output_view;
+  ComD3D11VideoProcessorOutputView output_view;
   hr = video_device_->CreateVideoProcessorOutputView(
       dest_texture, enumerator_.Get(), &output_view_desc, &output_view);
   RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to get output view",
@@ -2808,7 +2807,7 @@
   input_view_desc.ViewDimension = D3D11_VPIV_DIMENSION_TEXTURE2D;
   input_view_desc.Texture2D.ArraySlice = index;
   input_view_desc.Texture2D.MipSlice = 0;
-  Microsoft::WRL::ComPtr<ID3D11VideoProcessorInputView> input_view;
+  ComD3D11VideoProcessorInputView input_view;
   hr = video_device_->CreateVideoProcessorInputView(
       dx11_decoding_texture.Get(), enumerator_.Get(), &input_view_desc,
       &input_view);
@@ -2960,7 +2959,7 @@
   DCHECK_EQ(GetPictureBufferMechanism(), PictureBufferMechanism::COPY_TO_RGB);
 
   // On platforms prior to Windows 10 we won't have a ID3D11VideoContext1.
-  Microsoft::WRL::ComPtr<ID3D11VideoContext1> video_context1;
+  ComD3D11VideoContext1 video_context1;
   if (FAILED(video_context_.As(&video_context1))) {
     auto d3d11_color_space =
         gfx::ColorSpaceWin::GetD3D11ColorSpace(color_space);
@@ -3027,7 +3026,7 @@
 
   if (use_dx11_) {
     Microsoft::WRL::ComPtr<IMFDXGIBuffer> dxgi_buffer;
-    Microsoft::WRL::ComPtr<ID3D11Texture2D> d3d11_texture;
+    ComD3D11Texture2D d3d11_texture;
     hr = output_buffer.As(&dxgi_buffer);
     RETURN_ON_HR_FAILURE(hr, "Failed to get DXGIBuffer from output sample",
                          false);
diff --git a/media/gpu/windows/dxva_video_decode_accelerator_win.h b/media/gpu/windows/dxva_video_decode_accelerator_win.h
index 93ec74c..43b4150d 100644
--- a/media/gpu/windows/dxva_video_decode_accelerator_win.h
+++ b/media/gpu/windows/dxva_video_decode_accelerator_win.h
@@ -33,6 +33,7 @@
 #include "media/base/video_color_space.h"
 #include "media/gpu/gpu_video_decode_accelerator_helpers.h"
 #include "media/gpu/media_gpu_export.h"
+#include "media/gpu/windows/d3d11_com_defs.h"
 #include "media/video/video_decode_accelerator.h"
 #include "ui/gfx/color_space.h"
 #include "ui/gfx/geometry/rect.h"
@@ -387,17 +388,17 @@
   Microsoft::WRL::ComPtr<IDirect3DDeviceManager9> device_manager_;
   Microsoft::WRL::ComPtr<IDirect3DQuery9> query_;
 
-  Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device_;
-  Microsoft::WRL::ComPtr<ID3D11Device> angle_device_;
+  ComD3D11Device d3d11_device_;
+  ComD3D11Device angle_device_;
   Microsoft::WRL::ComPtr<IMFDXGIDeviceManager> d3d11_device_manager_;
   Microsoft::WRL::ComPtr<ID3D10Multithread> multi_threaded_;
-  Microsoft::WRL::ComPtr<ID3D11DeviceContext> d3d11_device_context_;
-  Microsoft::WRL::ComPtr<ID3D11Query> d3d11_query_;
+  ComD3D11DeviceContext d3d11_device_context_;
+  ComD3D11Query d3d11_query_;
 
-  Microsoft::WRL::ComPtr<ID3D11VideoDevice> video_device_;
-  Microsoft::WRL::ComPtr<ID3D11VideoContext> video_context_;
-  Microsoft::WRL::ComPtr<ID3D11VideoProcessorEnumerator> enumerator_;
-  Microsoft::WRL::ComPtr<ID3D11VideoProcessor> d3d11_processor_;
+  ComD3D11VideoDevice video_device_;
+  ComD3D11VideoContext video_context_;
+  ComD3D11VideoProcessorEnumerator enumerator_;
+  ComD3D11VideoProcessor d3d11_processor_;
 
   int processor_width_ = 0;
   int processor_height_ = 0;
diff --git a/media/mojo/services/gpu_mojo_media_client.cc b/media/mojo/services/gpu_mojo_media_client.cc
index 053ea8a5..913a7af3 100644
--- a/media/mojo/services/gpu_mojo_media_client.cc
+++ b/media/mojo/services/gpu_mojo_media_client.cc
@@ -45,6 +45,12 @@
 #include "ui/gl/gl_angle_util_win.h"
 #endif  // defined(OS_WIN)
 
+#if defined(OS_CHROMEOS) || defined(OS_LINUX)
+#include "media/gpu/linux/linux_video_decoder_factory.h"
+#include "media/gpu/linux/mailbox_video_frame_converter.h"
+#include "media/gpu/linux/platform_video_frame_pool.h"
+#endif  // defined(OS_CHROMEOS) || defined(OS_LINUX)
+
 #if defined(OS_ANDROID)
 #include "media/mojo/services/android_mojo_util.h"
 using media::android_mojo_util::CreateProvisionFetcher;
@@ -200,8 +206,29 @@
       std::make_unique<VideoFrameFactoryImpl>(
           gpu_task_runner_, std::move(get_stub_cb), gpu_preferences_,
           MaybeRenderEarlyManager::Create(gpu_task_runner_)));
-#elif defined(OS_CHROMEOS) || defined(OS_MACOSX) || defined(OS_WIN) || \
-    defined(OS_LINUX)
+
+#elif defined(OS_CHROMEOS) || defined(OS_LINUX)
+      std::unique_ptr<VideoDecoder> linux_video_decoder;
+      if (base::FeatureList::IsEnabled(kLinuxVideoDecoder)) {
+        linux_video_decoder = LinuxVideoDecoderFactory::Create(
+            task_runner, gpu_task_runner_,
+            base::BindOnce(&GetCommandBufferStub, media_gpu_channel_manager_,
+                           command_buffer_id->channel_token,
+                           command_buffer_id->route_id));
+      }
+
+      if (linux_video_decoder) {
+        video_decoder = std::move(linux_video_decoder);
+      } else {
+        video_decoder = VdaVideoDecoder::Create(
+            task_runner, gpu_task_runner_, media_log->Clone(),
+            target_color_space, gpu_preferences_, gpu_workarounds_,
+            base::BindRepeating(
+                &GetCommandBufferStub, media_gpu_channel_manager_,
+                command_buffer_id->channel_token, command_buffer_id->route_id));
+      }
+
+#elif defined(OS_MACOSX) || defined(OS_WIN)
       video_decoder = VdaVideoDecoder::Create(
           task_runner, gpu_task_runner_, media_log->Clone(), target_color_space,
           gpu_preferences_, gpu_workarounds_,
diff --git a/media/video/gpu_video_accelerator_factories.h b/media/video/gpu_video_accelerator_factories.h
index 64f84f58..cc399fc 100644
--- a/media/video/gpu_video_accelerator_factories.h
+++ b/media/video/gpu_video_accelerator_factories.h
@@ -21,7 +21,6 @@
 #include "media/base/video_decoder.h"
 #include "media/base/video_types.h"
 #include "media/video/supported_video_decoder_config.h"
-#include "media/video/video_decode_accelerator.h"
 #include "media/video/video_encode_accelerator.h"
 #include "ui/gfx/gpu_memory_buffer.h"
 
@@ -49,7 +48,6 @@
 namespace media {
 
 class MediaLog;
-class VideoDecodeAccelerator;
 
 // Helper interface for specifying factories needed to instantiate a hardware
 // video accelerator.
@@ -97,12 +95,6 @@
 
   // Caller owns returned pointer, but should call Destroy() on it (instead of
   // directly deleting) for proper destruction, as per the
-  // VideoDecodeAccelerator interface.
-  virtual std::unique_ptr<VideoDecodeAccelerator>
-  CreateVideoDecodeAccelerator() = 0;
-
-  // Caller owns returned pointer, but should call Destroy() on it (instead of
-  // directly deleting) for proper destruction, as per the
   // VideoEncodeAccelerator interface.
   virtual std::unique_ptr<VideoEncodeAccelerator>
   CreateVideoEncodeAccelerator() = 0;
@@ -162,11 +154,6 @@
   // Returns the task runner the video accelerator runs on.
   virtual scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() = 0;
 
-  // Return the capabilities of video decode accelerator, which includes the
-  // supported codec profiles.
-  virtual VideoDecodeAccelerator::Capabilities
-  GetVideoDecodeAcceleratorCapabilities() = 0;
-
   // Returns the supported codec profiles of video encode accelerator.
   virtual VideoEncodeAccelerator::SupportedProfiles
   GetVideoEncodeAcceleratorSupportedProfiles() = 0;
diff --git a/media/video/mock_gpu_video_accelerator_factories.cc b/media/video/mock_gpu_video_accelerator_factories.cc
index 901c41f..761ddcd 100644
--- a/media/video/mock_gpu_video_accelerator_factories.cc
+++ b/media/video/mock_gpu_video_accelerator_factories.cc
@@ -123,11 +123,6 @@
   return nullptr;
 }
 
-std::unique_ptr<VideoDecodeAccelerator>
-MockGpuVideoAcceleratorFactories::CreateVideoDecodeAccelerator() {
-  return base::WrapUnique(DoCreateVideoDecodeAccelerator());
-}
-
 std::unique_ptr<VideoEncodeAccelerator>
 MockGpuVideoAcceleratorFactories::CreateVideoEncodeAccelerator() {
   return base::WrapUnique(DoCreateVideoEncodeAccelerator());
diff --git a/media/video/mock_gpu_video_accelerator_factories.h b/media/video/mock_gpu_video_accelerator_factories.h
index 18f9453..e42d7da0 100644
--- a/media/video/mock_gpu_video_accelerator_factories.h
+++ b/media/video/mock_gpu_video_accelerator_factories.h
@@ -15,7 +15,6 @@
 #include "base/memory/ref_counted.h"
 #include "base/single_thread_task_runner.h"
 #include "media/video/gpu_video_accelerator_factories.h"
-#include "media/video/video_decode_accelerator.h"
 #include "media/video/video_encode_accelerator.h"
 #include "services/ws/public/cpp/gpu/context_provider_command_buffer.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -44,9 +43,8 @@
                                            VideoDecoderImplementation,
                                            const RequestOverlayInfoCB&));
 
-  // CreateVideo{Decode,Encode}Accelerator returns scoped_ptr, which the mocking
-  // framework does not want.  Trampoline them.
-  MOCK_METHOD0(DoCreateVideoDecodeAccelerator, VideoDecodeAccelerator*());
+  // CreateVideoEncodeAccelerator returns scoped_ptr, which the mocking
+  // framework does not want. Trampoline it.
   MOCK_METHOD0(DoCreateVideoEncodeAccelerator, VideoEncodeAccelerator*());
 
   MOCK_METHOD5(CreateTextures,
@@ -63,8 +61,6 @@
                     base::OnceClosure callback));
   MOCK_METHOD0(ShallowFlushCHROMIUM, void());
   MOCK_METHOD0(GetTaskRunner, scoped_refptr<base::SingleThreadTaskRunner>());
-  MOCK_METHOD0(GetVideoDecodeAcceleratorCapabilities,
-               VideoDecodeAccelerator::Capabilities());
   MOCK_METHOD0(GetVideoEncodeAcceleratorSupportedProfiles,
                VideoEncodeAccelerator::SupportedProfiles());
   MOCK_METHOD0(GetMediaContextProvider,
@@ -102,9 +98,6 @@
 
   std::unique_ptr<base::SharedMemory> CreateSharedMemory(size_t size) override;
 
-  std::unique_ptr<VideoDecodeAccelerator> CreateVideoDecodeAccelerator()
-      override;
-
   std::unique_ptr<VideoEncodeAccelerator> CreateVideoEncodeAccelerator()
       override;
 
diff --git a/mojo/public/cpp/bindings/lib/sync_handle_registry.cc b/mojo/public/cpp/bindings/lib/sync_handle_registry.cc
index 3278a76a..2ae6353 100644
--- a/mojo/public/cpp/bindings/lib/sync_handle_registry.cc
+++ b/mojo/public/cpp/bindings/lib/sync_handle_registry.cc
@@ -85,17 +85,14 @@
     // Not safe to remove any elements from |callbacks| here since an outer
     // stack frame is currently iterating over it in Wait().
     for (auto& cb : callbacks) {
-      if (cb.Equals(callback))
+      if (cb == callback)
         cb.Reset();
       else if (cb)
         has_valid_callbacks = true;
     }
     remove_invalid_event_callbacks_after_dispatch_ = true;
   } else {
-    callbacks.erase(std::remove_if(callbacks.begin(), callbacks.end(),
-                                   [&callback](const base::Closure& cb) {
-                                     return cb.Equals(callback);
-                                   }),
+    callbacks.erase(std::remove(callbacks.begin(), callbacks.end(), callback),
                     callbacks.end());
     if (callbacks.empty())
       events_.erase(it);
diff --git a/net/cert/cert_verify_proc.cc b/net/cert/cert_verify_proc.cc
index 1fb2c2c5..d12a247c 100644
--- a/net/cert/cert_verify_proc.cc
+++ b/net/cert/cert_verify_proc.cc
@@ -30,6 +30,7 @@
 #include "net/cert/crl_set.h"
 #include "net/cert/internal/ocsp.h"
 #include "net/cert/internal/parse_certificate.h"
+#include "net/cert/internal/revocation_checker.h"
 #include "net/cert/internal/signature_algorithm.h"
 #include "net/cert/known_roots.h"
 #include "net/cert/ocsp_revocation_status.h"
@@ -243,7 +244,7 @@
 
   verify_result->revocation_status =
       CheckOCSP(raw_response, cert_der, issuer_der, base::Time::Now(),
-                kMaxOCSPLeafUpdateAge, &verify_result->response_status);
+                kMaxRevocationLeafUpdateAge, &verify_result->response_status);
 }
 
 // Records histograms indicating whether the certificate |cert|, which
diff --git a/net/cert/internal/ocsp.h b/net/cert/internal/ocsp.h
index e8ab44e..5a4dca1 100644
--- a/net/cert/internal/ocsp.h
+++ b/net/cert/internal/ocsp.h
@@ -224,24 +224,6 @@
   std::vector<der::Input> certs;
 };
 
-// Baseline Requirements 1.5.6, section 4.9.10:
-//   For the status of Subscriber Certificates: The CA SHALL update information
-//     provided via an Online Certificate Status Protocol at least every four
-//     days.  OCSP responses from this service MUST have a maximum expiration
-//     time of ten days.
-// TODO(mattm): Document the rationale for 7 days.
-constexpr base::TimeDelta kMaxOCSPLeafUpdateAge = base::TimeDelta::FromDays(7);
-
-// Baseline Requirements 1.5.6, section 4.9.10:
-//   For the status of Subordinate CA Certificates: The CA SHALL update
-//     information provided via an Online Certificate Status Protocol at least
-//     (i) every twelve months and (ii) within 24 hours after revoking a
-//     Subordinate CA Certificate.
-// Use 366 days to allow for leap years, though it is overly permissive in
-// other years.
-constexpr base::TimeDelta kMaxOCSPIntermediateUpdateAge =
-    base::TimeDelta::FromDays(366);
-
 // From RFC 6960:
 //
 // id-pkix-ocsp           OBJECT IDENTIFIER ::= { id-ad-ocsp }
diff --git a/net/cert/internal/revocation_checker.cc b/net/cert/internal/revocation_checker.cc
index e01b910..a2da615c 100644
--- a/net/cert/internal/revocation_checker.cc
+++ b/net/cert/internal/revocation_checker.cc
@@ -206,8 +206,11 @@
     base::StringPiece stapled_ocsp =
         (i == 0) ? stapled_leaf_ocsp_response : base::StringPiece();
 
-    base::TimeDelta max_age =
-        (i == 0) ? kMaxOCSPLeafUpdateAge : kMaxOCSPIntermediateUpdateAge;
+    // TODO(https://crbug.com/971714): This applies Baseline Requirements max
+    // update age to all revocation checks, including locally trusted anchors.
+    // Confirm whether this causes any issues in enterprise deployments.
+    base::TimeDelta max_age = (i == 0) ? kMaxRevocationLeafUpdateAge
+                                       : kMaxRevocationIntermediateUpdateAge;
 
     // Check whether this certificate's revocation status complies with the
     // policy.
diff --git a/net/cert/internal/revocation_checker.h b/net/cert/internal/revocation_checker.h
index e22972f..89590bb 100644
--- a/net/cert/internal/revocation_checker.h
+++ b/net/cert/internal/revocation_checker.h
@@ -15,6 +15,41 @@
 class CertPathErrors;
 class CertNetFetcher;
 
+// Baseline Requirements 1.6.5, section 4.9.7:
+//     For the status of Subscriber Certificates: If the CA publishes a CRL,
+//     then the CA SHALL update and reissue CRLs at least once every seven
+//     days, and the value of the nextUpdate field MUST NOT be more than ten
+//     days beyond the value of the thisUpdate field.
+//
+// Baseline Requirements 1.6.5, section 4.9.10:
+//     For the status of Subscriber Certificates: The CA SHALL update
+//     information provided via an Online Certificate Status Protocol at least
+//     every four days.  OCSP responses from this service MUST have a maximum
+//     expiration time of ten days.
+//
+// Use 7 days as the max allowable leaf revocation status age, which is
+// sufficient for both CRL and OCSP, and which aligns with Microsoft policies.
+constexpr base::TimeDelta kMaxRevocationLeafUpdateAge =
+    base::TimeDelta::FromDays(7);
+
+// Baseline Requirements 1.6.5, section 4.9.7:
+//     For the status of Subordinate CA Certificates: The CA SHALL update and
+//     reissue CRLs at least (i) once every twelve months and (ii) within 24
+//     hours after revoking a Subordinate CA Certificate, and the value of the
+//     nextUpdate field MUST NOT be more than twelve months beyond the value of
+//     the thisUpdate field.
+//
+// Baseline Requirements 1.6.5, section 4.9.10:
+//     For the status of Subordinate CA Certificates: The CA SHALL update
+//     information provided via an Online Certificate Status Protocol at least
+//     (i) every twelve months and (ii) within 24 hours after revoking a
+//     Subordinate CA Certificate.
+//
+// Use 366 days to allow for leap years, though it is overly permissive in
+// other years.
+constexpr base::TimeDelta kMaxRevocationIntermediateUpdateAge =
+    base::TimeDelta::FromDays(366);
+
 // RevocationPolicy describes how revocation should be carried out for a
 // particular chain.
 struct NET_EXPORT_PRIVATE RevocationPolicy {
diff --git a/net/http/http_stream_factory_job_controller_unittest.cc b/net/http/http_stream_factory_job_controller_unittest.cc
index 59dc7f77d..957c397d 100644
--- a/net/http/http_stream_factory_job_controller_unittest.cc
+++ b/net/http/http_stream_factory_job_controller_unittest.cc
@@ -1031,8 +1031,7 @@
        AltJobSucceedsMainJobBlockedControllerDestroyed) {
   quic_data_ = std::make_unique<MockQuicData>(
       HttpNetworkSession::Params().quic_supported_versions.front());
-  quic_data_->AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeInitialSettingsPacket(1, nullptr));
+  quic_data_->AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
   quic_data_->AddRead(ASYNC, OK);
 
   HttpRequestInfo request_info;
@@ -2301,8 +2300,7 @@
 TEST_F(HttpStreamFactoryJobControllerTest, PreconnectToHostWithValidAltSvc) {
   quic_data_ = std::make_unique<MockQuicData>(
       HttpNetworkSession::Params().quic_supported_versions.front());
-  quic_data_->AddWrite(SYNCHRONOUS,
-                       client_maker_.MakeInitialSettingsPacket(1, nullptr));
+  quic_data_->AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
   quic_data_->AddRead(ASYNC, OK);
 
   HttpRequestInfo request_info;
@@ -2801,7 +2799,7 @@
         HttpNetworkSession::Params().quic_supported_versions.front());
     quic_data_->AddConnect(SYNCHRONOUS, OK);
     quic_data_->AddWrite(SYNCHRONOUS,
-                         client_maker_.MakeInitialSettingsPacket(1, nullptr));
+                         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 9258f8f..656a3a6 100644
--- a/net/http/http_stream_factory_unittest.cc
+++ b/net/http/http_stream_factory_unittest.cc
@@ -48,6 +48,7 @@
 #include "net/quic/quic_http_utils.h"
 #include "net/quic/quic_stream_factory_peer.h"
 #include "net/quic/quic_test_packet_maker.h"
+#include "net/quic/quic_test_packet_printer.h"
 #include "net/socket/client_socket_handle.h"
 #include "net/socket/client_socket_pool.h"
 #include "net/socket/connect_job.h"
@@ -835,7 +836,8 @@
 // Simplify ownership issues and the interaction with the MockSocketFactory.
 class MockQuicData {
  public:
-  MockQuicData() : packet_number_(0) {}
+  explicit MockQuicData(quic::ParsedQuicVersion version)
+      : packet_number_(0), printer_(version) {}
 
   ~MockQuicData() = default;
 
@@ -857,6 +859,7 @@
 
   void AddSocketDataToFactory(MockClientSocketFactory* factory) {
     socket_data_ = std::make_unique<SequencedSocketData>(reads_, writes_);
+    socket_data_->set_printer(&printer_);
     factory->AddSocketDataProvider(socket_data_.get());
   }
 
@@ -865,6 +868,7 @@
   std::vector<MockWrite> writes_;
   std::vector<MockRead> reads_;
   size_t packet_number_;
+  QuicPacketPrinter printer_;
   std::unique_ptr<SequencedSocketData> socket_data_;
 };
 
@@ -2268,6 +2272,8 @@
         version_.transport_version, n);
   }
 
+  quic::ParsedQuicVersion version() const { return version_; }
+
  private:
   const quic::ParsedQuicVersion version_;
   const bool client_headers_include_h2_stream_dependency_;
@@ -2298,20 +2304,17 @@
 
 TEST_P(HttpStreamFactoryBidirectionalQuicTest,
        RequestBidirectionalStreamImplQuicAlternative) {
-  MockQuicData mock_quic_data;
+  MockQuicData mock_quic_data(version());
   spdy::SpdyPriority priority =
       ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY);
   size_t spdy_headers_frame_length;
-  quic::QuicStreamOffset header_stream_offset = 0;
-  mock_quic_data.AddWrite(client_packet_maker().MakeInitialSettingsPacket(
-      1, &header_stream_offset));
+  mock_quic_data.AddWrite(client_packet_maker().MakeInitialSettingsPacket(1));
   mock_quic_data.AddWrite(client_packet_maker().MakeRequestHeadersPacket(
       2, GetNthClientInitiatedBidirectionalStreamId(0),
       /*should_include_version=*/true,
       /*fin=*/true, priority,
       client_packet_maker().GetRequestHeaders("GET", "https", "/"),
-      /*parent_stream_id=*/0, &spdy_headers_frame_length,
-      &header_stream_offset));
+      /*parent_stream_id=*/0, &spdy_headers_frame_length));
   size_t spdy_response_headers_frame_length;
   mock_quic_data.AddRead(server_packet_maker().MakeResponseHeadersPacket(
       1, GetNthClientInitiatedBidirectionalStreamId(0),
@@ -2426,20 +2429,17 @@
 TEST_P(HttpStreamFactoryBidirectionalQuicTest,
        RequestBidirectionalStreamImplHttpJobFailsQuicJobSucceeds) {
   // Set up Quic data.
-  MockQuicData mock_quic_data;
+  MockQuicData mock_quic_data(version());
   spdy::SpdyPriority priority =
       ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY);
   size_t spdy_headers_frame_length;
-  quic::QuicStreamOffset header_stream_offset = 0;
-  mock_quic_data.AddWrite(client_packet_maker().MakeInitialSettingsPacket(
-      1, &header_stream_offset));
+  mock_quic_data.AddWrite(client_packet_maker().MakeInitialSettingsPacket(1));
   mock_quic_data.AddWrite(client_packet_maker().MakeRequestHeadersPacket(
       2, GetNthClientInitiatedBidirectionalStreamId(0),
       /*should_include_version=*/true,
       /*fin=*/true, priority,
       client_packet_maker().GetRequestHeaders("GET", "https", "/"),
-      /*parent_stream_id=*/0, &spdy_headers_frame_length,
-      &header_stream_offset));
+      /*parent_stream_id=*/0, &spdy_headers_frame_length));
   size_t spdy_response_headers_frame_length;
   mock_quic_data.AddRead(server_packet_maker().MakeResponseHeadersPacket(
       1, GetNthClientInitiatedBidirectionalStreamId(0),
@@ -2680,20 +2680,17 @@
 // should not be shared amongst streams with different socket tags).
 TEST_P(HttpStreamFactoryBidirectionalQuicTest, Tag) {
   // Prepare mock QUIC data for a first session establishment.
-  MockQuicData mock_quic_data;
+  MockQuicData mock_quic_data(version());
   spdy::SpdyPriority priority =
       ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY);
   size_t spdy_headers_frame_length;
-  quic::QuicStreamOffset header_stream_offset = 0;
-  mock_quic_data.AddWrite(client_packet_maker().MakeInitialSettingsPacket(
-      1, &header_stream_offset));
+  mock_quic_data.AddWrite(client_packet_maker().MakeInitialSettingsPacket(1));
   mock_quic_data.AddWrite(client_packet_maker().MakeRequestHeadersPacket(
       2, GetNthClientInitiatedBidirectionalStreamId(0),
       /*should_include_version=*/true,
       /*fin=*/true, priority,
       client_packet_maker().GetRequestHeaders("GET", "https", "/"),
-      /*parent_stream_id=*/0, &spdy_headers_frame_length,
-      &header_stream_offset));
+      /*parent_stream_id=*/0, &spdy_headers_frame_length));
   size_t spdy_response_headers_frame_length;
   mock_quic_data.AddRead(server_packet_maker().MakeResponseHeadersPacket(
       1, GetNthClientInitiatedBidirectionalStreamId(0),
@@ -2704,17 +2701,15 @@
   mock_quic_data.AddSocketDataToFactory(&socket_factory());
 
   // Prepare mock QUIC data for a second session establishment.
-  MockQuicData mock_quic_data2;
-  quic::QuicStreamOffset header_stream_offset2 = 0;
-  mock_quic_data2.AddWrite(client_packet_maker().MakeInitialSettingsPacket(
-      1, &header_stream_offset2));
+  client_packet_maker().Reset();
+  MockQuicData mock_quic_data2(version());
+  mock_quic_data2.AddWrite(client_packet_maker().MakeInitialSettingsPacket(1));
   mock_quic_data2.AddWrite(client_packet_maker().MakeRequestHeadersPacket(
       2, GetNthClientInitiatedBidirectionalStreamId(0),
       /*should_include_version=*/true,
       /*fin=*/true, priority,
       client_packet_maker().GetRequestHeaders("GET", "https", "/"),
-      /*parent_stream_id=*/0, &spdy_headers_frame_length,
-      &header_stream_offset));
+      /*parent_stream_id=*/0, &spdy_headers_frame_length));
   mock_quic_data2.AddRead(server_packet_maker().MakeResponseHeadersPacket(
       1, GetNthClientInitiatedBidirectionalStreamId(0),
       /*should_include_version=*/false,
diff --git a/net/quic/bidirectional_stream_quic_impl_unittest.cc b/net/quic/bidirectional_stream_quic_impl_unittest.cc
index cb3561e..718cf5bb 100644
--- a/net/quic/bidirectional_stream_quic_impl_unittest.cc
+++ b/net/quic/bidirectional_stream_quic_impl_unittest.cc
@@ -601,9 +601,9 @@
       bool fin,
       RequestPriority request_priority,
       size_t* spdy_headers_frame_length) {
-    return ConstructRequestHeadersPacketInner(
-        packet_number, stream_id_, fin, request_priority,
-        spdy_headers_frame_length, /*offset=*/nullptr);
+    return ConstructRequestHeadersPacketInner(packet_number, stream_id_, fin,
+                                              request_priority,
+                                              spdy_headers_frame_length);
   }
 
   std::unique_ptr<quic::QuicReceivedPacket> ConstructRequestHeadersPacketInner(
@@ -611,11 +611,10 @@
       quic::QuicStreamId stream_id,
       bool fin,
       RequestPriority request_priority,
-      size_t* spdy_headers_frame_length,
-      quic::QuicStreamOffset* offset) {
-    return ConstructRequestHeadersPacketInner(
-        packet_number, stream_id, fin, request_priority, 0,
-        spdy_headers_frame_length, offset);
+      size_t* spdy_headers_frame_length) {
+    return ConstructRequestHeadersPacketInner(packet_number, stream_id, fin,
+                                              request_priority, 0,
+                                              spdy_headers_frame_length);
   }
 
   std::unique_ptr<quic::QuicReceivedPacket> ConstructRequestHeadersPacketInner(
@@ -624,15 +623,14 @@
       bool fin,
       RequestPriority request_priority,
       quic::QuicStreamId parent_stream_id,
-      size_t* spdy_headers_frame_length,
-      quic::QuicStreamOffset* offset) {
+      size_t* spdy_headers_frame_length) {
     spdy::SpdyPriority priority =
         ConvertRequestPriorityToQuicPriority(request_priority);
     std::unique_ptr<quic::QuicReceivedPacket> packet(
         client_maker_.MakeRequestHeadersPacket(
             packet_number, stream_id, kIncludeVersion, fin, priority,
             std::move(request_headers_), parent_stream_id,
-            spdy_headers_frame_length, offset));
+            spdy_headers_frame_length));
     DVLOG(2) << "packet(" << packet_number << "): " << std::endl
              << quic::QuicTextUtils::HexDump(packet->AsStringPiece());
     return packet;
@@ -643,7 +641,6 @@
       uint64_t packet_number,
       bool fin,
       RequestPriority request_priority,
-      quic::QuicStreamOffset* header_stream_offset,
       size_t* spdy_headers_frame_length,
       const std::vector<std::string>& data) {
     spdy::SpdyPriority priority =
@@ -651,8 +648,7 @@
     std::unique_ptr<quic::QuicReceivedPacket> packet(
         client_maker_.MakeRequestHeadersAndMultipleDataFramesPacket(
             packet_number, stream_id_, kIncludeVersion, fin, priority,
-            std::move(request_headers_), 0, header_stream_offset,
-            spdy_headers_frame_length, data));
+            std::move(request_headers_), 0, spdy_headers_frame_length, data));
     DVLOG(2) << "packet(" << packet_number << "): " << std::endl
              << quic::QuicTextUtils::HexDump(packet->AsStringPiece());
     return packet;
@@ -662,11 +658,10 @@
       uint64_t packet_number,
       bool fin,
       spdy::SpdyHeaderBlock response_headers,
-      size_t* spdy_headers_frame_length,
-      quic::QuicStreamOffset* offset) {
-    return ConstructResponseHeadersPacketInner(
-        packet_number, stream_id_, fin, std::move(response_headers),
-        spdy_headers_frame_length, offset);
+      size_t* spdy_headers_frame_length) {
+    return ConstructResponseHeadersPacketInner(packet_number, stream_id_, fin,
+                                               std::move(response_headers),
+                                               spdy_headers_frame_length);
   }
 
   std::unique_ptr<quic::QuicReceivedPacket> ConstructResponseHeadersPacketInner(
@@ -674,22 +669,20 @@
       quic::QuicStreamId stream_id,
       bool fin,
       spdy::SpdyHeaderBlock response_headers,
-      size_t* spdy_headers_frame_length,
-      quic::QuicStreamOffset* offset) {
+      size_t* spdy_headers_frame_length) {
     return server_maker_.MakeResponseHeadersPacket(
         packet_number, stream_id, !kIncludeVersion, fin,
-        std::move(response_headers), spdy_headers_frame_length, offset);
+        std::move(response_headers), spdy_headers_frame_length);
   }
 
   std::unique_ptr<quic::QuicReceivedPacket> ConstructResponseTrailersPacket(
       uint64_t packet_number,
       bool fin,
       spdy::SpdyHeaderBlock trailers,
-      size_t* spdy_headers_frame_length,
-      quic::QuicStreamOffset* offset) {
+      size_t* spdy_headers_frame_length) {
     return server_maker_.MakeResponseHeadersPacket(
         packet_number, stream_id_, !kIncludeVersion, fin, std::move(trailers),
-        spdy_headers_frame_length, offset);
+        spdy_headers_frame_length);
   }
 
   std::unique_ptr<quic::QuicReceivedPacket> ConstructClientRstStreamPacket(
@@ -794,9 +787,8 @@
   }
 
   std::unique_ptr<quic::QuicReceivedPacket> ConstructInitialSettingsPacket(
-      uint64_t packet_number,
-      quic::QuicStreamOffset* offset) {
-    return client_maker_.MakeInitialSettingsPacket(packet_number, offset);
+      uint64_t packet_number) {
+    return client_maker_.MakeInitialSettingsPacket(packet_number);
   }
 
   void ExpectLoadTimingValid(const LoadTimingInfo& load_timing_info,
@@ -872,13 +864,12 @@
 TEST_P(BidirectionalStreamQuicImplTest, GetRequest) {
   SetRequest("GET", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  quic::QuicStreamOffset header_stream_offset = 0;
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
   AddWrite(ConstructRequestHeadersPacketInner(
       1, GetNthClientInitiatedBidirectionalStreamId(0), kFin, DEFAULT_PRIORITY,
-      &spdy_request_headers_frame_length, &header_stream_offset));
+      &spdy_request_headers_frame_length));
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
-  AddWrite(ConstructInitialSettingsPacket(2, &header_stream_offset));
+  AddWrite(ConstructInitialSettingsPacket(2));
   AddWrite(ConstructClientAckPacket(3, 3, 1, 2));
 
   Initialize();
@@ -906,10 +897,9 @@
   spdy::SpdyHeaderBlock response_headers = ConstructResponseHeaders("200");
 
   size_t spdy_response_headers_frame_length;
-  quic::QuicStreamOffset offset = 0;
-  ProcessPacket(ConstructResponseHeadersPacket(
-      2, !kFin, std::move(response_headers),
-      &spdy_response_headers_frame_length, &offset));
+  ProcessPacket(
+      ConstructResponseHeadersPacket(2, !kFin, std::move(response_headers),
+                                     &spdy_response_headers_frame_length));
 
   delegate->WaitUntilNextCallback(kOnHeadersReceived);
   LoadTimingInfo load_timing_info;
@@ -936,8 +926,8 @@
   trailers[quic::kFinalOffsetHeaderKey] =
       base::NumberToString(strlen(kResponseBody));
   // Server sends trailers.
-  ProcessPacket(ConstructResponseTrailersPacket(
-      4, kFin, trailers.Clone(), &spdy_trailers_frame_length, &offset));
+  ProcessPacket(ConstructResponseTrailersPacket(4, kFin, trailers.Clone(),
+                                                &spdy_trailers_frame_length));
 
   delegate->WaitUntilNextCallback(kOnTrailersReceived);
   EXPECT_THAT(cb2.WaitForResult(), IsOk());
@@ -975,18 +965,17 @@
 
 TEST_P(BidirectionalStreamQuicImplTest, LoadTimingTwoRequests) {
   SetRequest("GET", "/", DEFAULT_PRIORITY);
-  quic::QuicStreamOffset offset = 0;
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
   AddWrite(ConstructRequestHeadersPacketInner(
       1, GetNthClientInitiatedBidirectionalStreamId(0), kFin, DEFAULT_PRIORITY,
-      nullptr, &offset));
+      nullptr));
   // SetRequest() again for second request as |request_headers_| was moved.
   SetRequest("GET", "/", DEFAULT_PRIORITY);
   AddWrite(ConstructRequestHeadersPacketInner(
       2, GetNthClientInitiatedBidirectionalStreamId(1), kFin, DEFAULT_PRIORITY,
-      GetNthClientInitiatedBidirectionalStreamId(0), nullptr, &offset));
+      GetNthClientInitiatedBidirectionalStreamId(0), nullptr));
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
-  AddWrite(ConstructInitialSettingsPacket(3, &offset));
+  AddWrite(ConstructInitialSettingsPacket(3));
   AddWrite(ConstructClientAckPacket(4, 3, 1, 2));
   Initialize();
 
@@ -1020,14 +1009,13 @@
   ProcessPacket(ConstructServerAckPacket(1, 1, 1, 1));
 
   // Server sends the response headers.
-  offset = 0;
   ProcessPacket(ConstructResponseHeadersPacketInner(
       2, GetNthClientInitiatedBidirectionalStreamId(0), kFin,
-      ConstructResponseHeaders("200"), nullptr, &offset));
+      ConstructResponseHeaders("200"), nullptr));
 
   ProcessPacket(ConstructResponseHeadersPacketInner(
       3, GetNthClientInitiatedBidirectionalStreamId(1), kFin,
-      ConstructResponseHeaders("200"), nullptr, &offset));
+      ConstructResponseHeaders("200"), nullptr));
 
   delegate->WaitUntilNextCallback(kOnHeadersReceived);
   delegate2->WaitUntilNextCallback(kOnHeadersReceived);
@@ -1051,8 +1039,7 @@
 TEST_P(BidirectionalStreamQuicImplTest, CoalesceDataBuffersNotHeadersFrame) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  quic::QuicStreamOffset header_stream_offset = 0;
-  AddWrite(ConstructInitialSettingsPacket(1, &header_stream_offset));
+  AddWrite(ConstructInitialSettingsPacket(1));
   const char kBody1[] = "here are some data";
   const char kBody2[] = "data keep coming";
   std::string header = ConstructDataHeader(strlen(kBody1));
@@ -1060,7 +1047,7 @@
   std::vector<std::string> two_writes = {kBody1, kBody2};
   AddWrite(ConstructRequestHeadersPacketInner(
       2, GetNthClientInitiatedBidirectionalStreamId(0), !kFin, DEFAULT_PRIORITY,
-      &spdy_request_headers_frame_length, &header_stream_offset));
+      &spdy_request_headers_frame_length));
   if (version_.transport_version != quic::QUIC_VERSION_99) {
     AddWrite(ConstructClientMultipleDataFramesPacket(3, kIncludeVersion, !kFin,
                                                      0, {kBody1, kBody2}));
@@ -1127,10 +1114,9 @@
   // Server sends the response headers.
   spdy::SpdyHeaderBlock response_headers = ConstructResponseHeaders("200");
   size_t spdy_response_headers_frame_length;
-  quic::QuicStreamOffset offset = 0;
-  ProcessPacket(ConstructResponseHeadersPacket(
-      2, !kFin, std::move(response_headers),
-      &spdy_response_headers_frame_length, &offset));
+  ProcessPacket(
+      ConstructResponseHeadersPacket(2, !kFin, std::move(response_headers),
+                                     &spdy_response_headers_frame_length));
 
   delegate->WaitUntilNextCallback(kOnHeadersReceived);
   TestCompletionCallback cb;
@@ -1163,8 +1149,8 @@
   trailers[quic::kFinalOffsetHeaderKey] =
       base::NumberToString(strlen(kResponseBody));
   // Server sends trailers.
-  ProcessPacket(ConstructResponseTrailersPacket(
-      4, kFin, trailers.Clone(), &spdy_trailers_frame_length, &offset));
+  ProcessPacket(ConstructResponseTrailersPacket(4, kFin, trailers.Clone(),
+                                                &spdy_trailers_frame_length));
 
   delegate->WaitUntilNextCallback(kOnTrailersReceived);
   trailers.erase(quic::kFinalOffsetHeaderKey);
@@ -1192,18 +1178,17 @@
        SendDataCoalesceDataBufferAndHeaderFrame) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  quic::QuicStreamOffset header_stream_offset = 0;
-  AddWrite(ConstructInitialSettingsPacket(1, &header_stream_offset));
+  AddWrite(ConstructInitialSettingsPacket(1));
   const char kBody1[] = "here are some data";
   std::string header = ConstructDataHeader(strlen(kBody1));
   if (version_.transport_version == quic::QUIC_VERSION_99) {
     AddWrite(ConstructRequestHeadersAndMultipleDataFramesPacket(
-        2, !kFin, DEFAULT_PRIORITY, &header_stream_offset,
-        &spdy_request_headers_frame_length, {header, kBody1}));
+        2, !kFin, DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
+        {header, kBody1}));
   } else {
     AddWrite(ConstructRequestHeadersAndMultipleDataFramesPacket(
-        2, !kFin, DEFAULT_PRIORITY, &header_stream_offset,
-        &spdy_request_headers_frame_length, {kBody1}));
+        2, !kFin, DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
+        {kBody1}));
   }
 
   // Ack server's data packet.
@@ -1250,10 +1235,9 @@
   // Server sends the response headers.
   spdy::SpdyHeaderBlock response_headers = ConstructResponseHeaders("200");
   size_t spdy_response_headers_frame_length;
-  quic::QuicStreamOffset offset = 0;
-  ProcessPacket(ConstructResponseHeadersPacket(
-      2, !kFin, std::move(response_headers),
-      &spdy_response_headers_frame_length, &offset));
+  ProcessPacket(
+      ConstructResponseHeadersPacket(2, !kFin, std::move(response_headers),
+                                     &spdy_response_headers_frame_length));
 
   delegate->WaitUntilNextCallback(kOnHeadersReceived);
   TestCompletionCallback cb;
@@ -1281,8 +1265,8 @@
   trailers[quic::kFinalOffsetHeaderKey] =
       base::NumberToString(strlen(kResponseBody));
   // Server sends trailers.
-  ProcessPacket(ConstructResponseTrailersPacket(
-      4, kFin, trailers.Clone(), &spdy_trailers_frame_length, &offset));
+  ProcessPacket(ConstructResponseTrailersPacket(4, kFin, trailers.Clone(),
+                                                &spdy_trailers_frame_length));
 
   delegate->WaitUntilNextCallback(kOnTrailersReceived);
   trailers.erase(quic::kFinalOffsetHeaderKey);
@@ -1308,8 +1292,7 @@
        SendvDataCoalesceDataBuffersAndHeaderFrame) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  quic::QuicStreamOffset header_stream_offset = 0;
-  AddWrite(ConstructInitialSettingsPacket(1, &header_stream_offset));
+  AddWrite(ConstructInitialSettingsPacket(1));
   const char kBody1[] = "here are some data";
   const char kBody2[] = "data keep coming";
   std::string header = ConstructDataHeader(strlen(kBody1));
@@ -1317,12 +1300,12 @@
 
   if (version_.transport_version == quic::QUIC_VERSION_99) {
     AddWrite(ConstructRequestHeadersAndMultipleDataFramesPacket(
-        2, !kFin, DEFAULT_PRIORITY, &header_stream_offset,
-        &spdy_request_headers_frame_length, {header, kBody1, header2, kBody2}));
+        2, !kFin, DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
+        {header, kBody1, header2, kBody2}));
   } else {
     AddWrite(ConstructRequestHeadersAndMultipleDataFramesPacket(
-        2, !kFin, DEFAULT_PRIORITY, &header_stream_offset,
-        &spdy_request_headers_frame_length, {kBody1, kBody2}));
+        2, !kFin, DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
+        {kBody1, kBody2}));
   }
 
   // Ack server's data packet.
@@ -1378,10 +1361,9 @@
   // Server sends the response headers.
   spdy::SpdyHeaderBlock response_headers = ConstructResponseHeaders("200");
   size_t spdy_response_headers_frame_length;
-  quic::QuicStreamOffset offset = 0;
-  ProcessPacket(ConstructResponseHeadersPacket(
-      2, !kFin, std::move(response_headers),
-      &spdy_response_headers_frame_length, &offset));
+  ProcessPacket(
+      ConstructResponseHeadersPacket(2, !kFin, std::move(response_headers),
+                                     &spdy_response_headers_frame_length));
 
   delegate->WaitUntilNextCallback(kOnHeadersReceived);
   TestCompletionCallback cb;
@@ -1414,8 +1396,8 @@
   trailers[quic::kFinalOffsetHeaderKey] =
       base::NumberToString(strlen(kResponseBody));
   // Server sends trailers.
-  ProcessPacket(ConstructResponseTrailersPacket(
-      4, kFin, trailers.Clone(), &spdy_trailers_frame_length, &offset));
+  ProcessPacket(ConstructResponseTrailersPacket(4, kFin, trailers.Clone(),
+                                                &spdy_trailers_frame_length));
 
   delegate->WaitUntilNextCallback(kOnTrailersReceived);
   trailers.erase(quic::kFinalOffsetHeaderKey);
@@ -1441,8 +1423,7 @@
 // headers to be sent, if that write fails the stream does not crash.
 TEST_P(BidirectionalStreamQuicImplTest,
        SendDataWriteErrorCoalesceDataBufferAndHeaderFrame) {
-  quic::QuicStreamOffset header_stream_offset = 0;
-  AddWrite(ConstructInitialSettingsPacket(1, &header_stream_offset));
+  AddWrite(ConstructInitialSettingsPacket(1));
   AddWriteError(SYNCHRONOUS, ERR_CONNECTION_REFUSED);
 
   Initialize();
@@ -1477,8 +1458,7 @@
 // headers to be sent, if that write fails the stream does not crash.
 TEST_P(BidirectionalStreamQuicImplTest,
        SendvDataWriteErrorCoalesceDataBufferAndHeaderFrame) {
-  quic::QuicStreamOffset header_stream_offset = 0;
-  AddWrite(ConstructInitialSettingsPacket(1, &header_stream_offset));
+  AddWrite(ConstructInitialSettingsPacket(1));
   AddWriteError(SYNCHRONOUS, ERR_CONNECTION_REFUSED);
 
   Initialize();
@@ -1516,11 +1496,10 @@
 TEST_P(BidirectionalStreamQuicImplTest, PostRequest) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  quic::QuicStreamOffset header_stream_offset = 0;
-  AddWrite(ConstructInitialSettingsPacket(1, &header_stream_offset));
+  AddWrite(ConstructInitialSettingsPacket(1));
   AddWrite(ConstructRequestHeadersPacketInner(
       2, GetNthClientInitiatedBidirectionalStreamId(0), !kFin, DEFAULT_PRIORITY,
-      &spdy_request_headers_frame_length, &header_stream_offset));
+      &spdy_request_headers_frame_length));
   std::string header = ConstructDataHeader(strlen(kUploadData));
   if (version_.transport_version == quic::QUIC_VERSION_99) {
     AddWrite(ConstructClientMultipleDataFramesPacket(3, kIncludeVersion, kFin,
@@ -1562,10 +1541,9 @@
   // Server sends the response headers.
   spdy::SpdyHeaderBlock response_headers = ConstructResponseHeaders("200");
   size_t spdy_response_headers_frame_length;
-  quic::QuicStreamOffset offset = 0;
-  ProcessPacket(ConstructResponseHeadersPacket(
-      2, !kFin, std::move(response_headers),
-      &spdy_response_headers_frame_length, &offset));
+  ProcessPacket(
+      ConstructResponseHeadersPacket(2, !kFin, std::move(response_headers),
+                                     &spdy_response_headers_frame_length));
 
   delegate->WaitUntilNextCallback(kOnHeadersReceived);
   TestCompletionCallback cb;
@@ -1586,8 +1564,8 @@
   trailers[quic::kFinalOffsetHeaderKey] =
       base::NumberToString(strlen(kResponseBody));
   // Server sends trailers.
-  ProcessPacket(ConstructResponseTrailersPacket(
-      4, kFin, trailers.Clone(), &spdy_trailers_frame_length, &offset));
+  ProcessPacket(ConstructResponseTrailersPacket(4, kFin, trailers.Clone(),
+                                                &spdy_trailers_frame_length));
 
   delegate->WaitUntilNextCallback(kOnTrailersReceived);
   trailers.erase(quic::kFinalOffsetHeaderKey);
@@ -1609,11 +1587,10 @@
 TEST_P(BidirectionalStreamQuicImplTest, EarlyDataOverrideRequest) {
   SetRequest("PUT", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  quic::QuicStreamOffset header_stream_offset = 0;
-  AddWrite(ConstructInitialSettingsPacket(1, &header_stream_offset));
+  AddWrite(ConstructInitialSettingsPacket(1));
   AddWrite(ConstructRequestHeadersPacketInner(
       2, GetNthClientInitiatedBidirectionalStreamId(0), !kFin, DEFAULT_PRIORITY,
-      &spdy_request_headers_frame_length, &header_stream_offset));
+      &spdy_request_headers_frame_length));
   std::string header = ConstructDataHeader(strlen(kUploadData));
   if (version_.transport_version == quic::QUIC_VERSION_99) {
     AddWrite(ConstructClientMultipleDataFramesPacket(3, kIncludeVersion, kFin,
@@ -1656,10 +1633,9 @@
   // Server sends the response headers.
   spdy::SpdyHeaderBlock response_headers = ConstructResponseHeaders("200");
   size_t spdy_response_headers_frame_length;
-  quic::QuicStreamOffset offset = 0;
-  ProcessPacket(ConstructResponseHeadersPacket(
-      2, !kFin, std::move(response_headers),
-      &spdy_response_headers_frame_length, &offset));
+  ProcessPacket(
+      ConstructResponseHeadersPacket(2, !kFin, std::move(response_headers),
+                                     &spdy_response_headers_frame_length));
 
   delegate->WaitUntilNextCallback(kOnHeadersReceived);
   TestCompletionCallback cb;
@@ -1680,8 +1656,8 @@
   trailers[quic::kFinalOffsetHeaderKey] =
       base::NumberToString(strlen(kResponseBody));
   // Server sends trailers.
-  ProcessPacket(ConstructResponseTrailersPacket(
-      4, kFin, trailers.Clone(), &spdy_trailers_frame_length, &offset));
+  ProcessPacket(ConstructResponseTrailersPacket(4, kFin, trailers.Clone(),
+                                                &spdy_trailers_frame_length));
 
   delegate->WaitUntilNextCallback(kOnTrailersReceived);
   trailers.erase(quic::kFinalOffsetHeaderKey);
@@ -1703,11 +1679,10 @@
 TEST_P(BidirectionalStreamQuicImplTest, InterleaveReadDataAndSendData) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  quic::QuicStreamOffset header_stream_offset = 0;
-  AddWrite(ConstructInitialSettingsPacket(1, &header_stream_offset));
+  AddWrite(ConstructInitialSettingsPacket(1));
   AddWrite(ConstructRequestHeadersPacketInner(
       2, GetNthClientInitiatedBidirectionalStreamId(0), !kFin, DEFAULT_PRIORITY,
-      &spdy_request_headers_frame_length, &header_stream_offset));
+      &spdy_request_headers_frame_length));
 
   std::string header = ConstructDataHeader(strlen(kUploadData));
   if (version_.transport_version != quic::QUIC_VERSION_99) {
@@ -1746,9 +1721,9 @@
   // Server sends the response headers.
   spdy::SpdyHeaderBlock response_headers = ConstructResponseHeaders("200");
   size_t spdy_response_headers_frame_length;
-  ProcessPacket(ConstructResponseHeadersPacket(
-      2, !kFin, std::move(response_headers),
-      &spdy_response_headers_frame_length, nullptr));
+  ProcessPacket(
+      ConstructResponseHeadersPacket(2, !kFin, std::move(response_headers),
+                                     &spdy_response_headers_frame_length));
 
   delegate->WaitUntilNextCallback(kOnHeadersReceived);
   EXPECT_EQ("200", delegate->response_headers().find(":status")->second);
@@ -1808,13 +1783,12 @@
 TEST_P(BidirectionalStreamQuicImplTest, ServerSendsRstAfterHeaders) {
   SetRequest("GET", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  quic::QuicStreamOffset header_stream_offset = 0;
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
   AddWrite(ConstructRequestHeadersPacketInner(
       1, GetNthClientInitiatedBidirectionalStreamId(0), kFin, DEFAULT_PRIORITY,
-      &spdy_request_headers_frame_length, &header_stream_offset));
+      &spdy_request_headers_frame_length));
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
-  AddWrite(ConstructInitialSettingsPacket(2, &header_stream_offset));
+  AddWrite(ConstructInitialSettingsPacket(2));
   Initialize();
 
   BidirectionalStreamRequestInfo request;
@@ -1854,13 +1828,12 @@
 TEST_P(BidirectionalStreamQuicImplTest, ServerSendsRstAfterReadData) {
   SetRequest("GET", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  quic::QuicStreamOffset header_stream_offset = 0;
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
   AddWrite(ConstructRequestHeadersPacketInner(
       1, GetNthClientInitiatedBidirectionalStreamId(0), kFin, DEFAULT_PRIORITY,
-      &spdy_request_headers_frame_length, &header_stream_offset));
+      &spdy_request_headers_frame_length));
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
-  AddWrite(ConstructInitialSettingsPacket(2, &header_stream_offset));
+  AddWrite(ConstructInitialSettingsPacket(2));
   // Why does QUIC ack Rst? Is this expected?
   AddWrite(ConstructClientAckPacket(3, 3, 1, 2));
 
@@ -1888,10 +1861,9 @@
   spdy::SpdyHeaderBlock response_headers = ConstructResponseHeaders("200");
 
   size_t spdy_response_headers_frame_length;
-  quic::QuicStreamOffset offset = 0;
-  ProcessPacket(ConstructResponseHeadersPacket(
-      2, !kFin, std::move(response_headers),
-      &spdy_response_headers_frame_length, &offset));
+  ProcessPacket(
+      ConstructResponseHeadersPacket(2, !kFin, std::move(response_headers),
+                                     &spdy_response_headers_frame_length));
 
   delegate->WaitUntilNextCallback(kOnHeadersReceived);
   EXPECT_EQ("200", delegate->response_headers().find(":status")->second);
@@ -1919,11 +1891,10 @@
 TEST_P(BidirectionalStreamQuicImplTest, SessionClosedBeforeReadData) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  quic::QuicStreamOffset header_stream_offset = 0;
-  AddWrite(ConstructInitialSettingsPacket(1, &header_stream_offset));
+  AddWrite(ConstructInitialSettingsPacket(1));
   AddWrite(ConstructRequestHeadersPacketInner(
       2, GetNthClientInitiatedBidirectionalStreamId(0), !kFin, DEFAULT_PRIORITY,
-      &spdy_request_headers_frame_length, &header_stream_offset));
+      &spdy_request_headers_frame_length));
   Initialize();
 
   BidirectionalStreamRequestInfo request;
@@ -1948,10 +1919,9 @@
   spdy::SpdyHeaderBlock response_headers = ConstructResponseHeaders("200");
 
   size_t spdy_response_headers_frame_length;
-  quic::QuicStreamOffset offset = 0;
-  ProcessPacket(ConstructResponseHeadersPacket(
-      2, !kFin, std::move(response_headers),
-      &spdy_response_headers_frame_length, &offset));
+  ProcessPacket(
+      ConstructResponseHeadersPacket(2, !kFin, std::move(response_headers),
+                                     &spdy_response_headers_frame_length));
 
   delegate->WaitUntilNextCallback(kOnHeadersReceived);
   TestCompletionCallback cb;
@@ -2029,8 +1999,7 @@
 
 TEST_P(BidirectionalStreamQuicImplTest, SessionCloseDuringOnStreamReady) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
-  quic::QuicStreamOffset header_stream_offset = 0;
-  AddWrite(ConstructInitialSettingsPacket(1, &header_stream_offset));
+  AddWrite(ConstructInitialSettingsPacket(1));
   AddWriteError(SYNCHRONOUS, ERR_CONNECTION_REFUSED);
 
   Initialize();
@@ -2057,11 +2026,10 @@
 TEST_P(BidirectionalStreamQuicImplTest, DeleteStreamDuringOnStreamReady) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  quic::QuicStreamOffset header_stream_offset = 0;
-  AddWrite(ConstructInitialSettingsPacket(1, &header_stream_offset));
+  AddWrite(ConstructInitialSettingsPacket(1));
   AddWrite(ConstructRequestHeadersPacketInner(
       2, GetNthClientInitiatedBidirectionalStreamId(0), !kFin, DEFAULT_PRIORITY,
-      &spdy_request_headers_frame_length, &header_stream_offset));
+      &spdy_request_headers_frame_length));
   AddWrite(ConstructClientEarlyRstStreamPacket(3));
 
   Initialize();
@@ -2089,11 +2057,10 @@
 TEST_P(BidirectionalStreamQuicImplTest, DeleteStreamAfterReadData) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  quic::QuicStreamOffset header_stream_offset = 0;
-  AddWrite(ConstructInitialSettingsPacket(1, &header_stream_offset));
+  AddWrite(ConstructInitialSettingsPacket(1));
   AddWrite(ConstructRequestHeadersPacketInner(
       2, GetNthClientInitiatedBidirectionalStreamId(0), !kFin, DEFAULT_PRIORITY,
-      &spdy_request_headers_frame_length, &header_stream_offset));
+      &spdy_request_headers_frame_length));
   AddWrite(ConstructClientAckAndRstStreamPacket(3, 2, 1, 2));
 
   Initialize();
@@ -2119,9 +2086,9 @@
   // Server sends the response headers.
   spdy::SpdyHeaderBlock response_headers = ConstructResponseHeaders("200");
   size_t spdy_response_headers_frame_length;
-  ProcessPacket(ConstructResponseHeadersPacket(
-      2, !kFin, std::move(response_headers),
-      &spdy_response_headers_frame_length, nullptr));
+  ProcessPacket(
+      ConstructResponseHeadersPacket(2, !kFin, std::move(response_headers),
+                                     &spdy_response_headers_frame_length));
 
   delegate->WaitUntilNextCallback(kOnHeadersReceived);
   EXPECT_EQ("200", delegate->response_headers().find(":status")->second);
@@ -2145,11 +2112,10 @@
 TEST_P(BidirectionalStreamQuicImplTest, DeleteStreamDuringOnHeadersReceived) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  quic::QuicStreamOffset header_stream_offset = 0;
-  AddWrite(ConstructInitialSettingsPacket(1, &header_stream_offset));
+  AddWrite(ConstructInitialSettingsPacket(1));
   AddWrite(ConstructRequestHeadersPacketInner(
       2, GetNthClientInitiatedBidirectionalStreamId(0), !kFin, DEFAULT_PRIORITY,
-      &spdy_request_headers_frame_length, &header_stream_offset));
+      &spdy_request_headers_frame_length));
   AddWrite(ConstructClientAckAndRstStreamPacket(3, 2, 1, 2));
 
   Initialize();
@@ -2177,9 +2143,9 @@
   spdy::SpdyHeaderBlock response_headers = ConstructResponseHeaders("200");
 
   size_t spdy_response_headers_frame_length;
-  ProcessPacket(ConstructResponseHeadersPacket(
-      2, !kFin, std::move(response_headers),
-      &spdy_response_headers_frame_length, nullptr));
+  ProcessPacket(
+      ConstructResponseHeadersPacket(2, !kFin, std::move(response_headers),
+                                     &spdy_response_headers_frame_length));
 
   delegate->WaitUntilNextCallback(kOnHeadersReceived);
   EXPECT_EQ("200", delegate->response_headers().find(":status")->second);
@@ -2193,11 +2159,10 @@
 TEST_P(BidirectionalStreamQuicImplTest, DeleteStreamDuringOnDataRead) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  quic::QuicStreamOffset header_stream_offset = 0;
-  AddWrite(ConstructInitialSettingsPacket(1, &header_stream_offset));
+  AddWrite(ConstructInitialSettingsPacket(1));
   AddWrite(ConstructRequestHeadersPacketInner(
       2, GetNthClientInitiatedBidirectionalStreamId(0), !kFin, DEFAULT_PRIORITY,
-      &spdy_request_headers_frame_length, &header_stream_offset));
+      &spdy_request_headers_frame_length));
   AddWrite(ConstructClientAckPacket(3, 3, 1, 2));
   AddWrite(ConstructClientRstStreamPacket(4));
 
@@ -2225,9 +2190,9 @@
   spdy::SpdyHeaderBlock response_headers = ConstructResponseHeaders("200");
 
   size_t spdy_response_headers_frame_length;
-  ProcessPacket(ConstructResponseHeadersPacket(
-      2, !kFin, std::move(response_headers),
-      &spdy_response_headers_frame_length, nullptr));
+  ProcessPacket(
+      ConstructResponseHeadersPacket(2, !kFin, std::move(response_headers),
+                                     &spdy_response_headers_frame_length));
 
   delegate->WaitUntilNextCallback(kOnHeadersReceived);
 
@@ -2253,11 +2218,10 @@
   const char kBody[] = "here is some data";
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  quic::QuicStreamOffset header_stream_offset = 0;
-  AddWrite(ConstructInitialSettingsPacket(1, &header_stream_offset));
+  AddWrite(ConstructInitialSettingsPacket(1));
   AddWrite(ConstructRequestHeadersPacketInner(
       2, GetNthClientInitiatedBidirectionalStreamId(0), !kFin, DEFAULT_PRIORITY,
-      &spdy_request_headers_frame_length, &header_stream_offset));
+      &spdy_request_headers_frame_length));
   std::string header = ConstructDataHeader(strlen(kBody));
   if (version_.transport_version == quic::QUIC_VERSION_99) {
     AddWrite(ConstructClientMultipleDataFramesPacket(3, kIncludeVersion, kFin,
@@ -2299,9 +2263,9 @@
   spdy::SpdyHeaderBlock response_headers = ConstructResponseHeaders("200");
 
   size_t spdy_response_headers_frame_length;
-  ProcessPacket(ConstructResponseHeadersPacket(
-      2, !kFin, std::move(response_headers),
-      &spdy_response_headers_frame_length, nullptr));
+  ProcessPacket(
+      ConstructResponseHeadersPacket(2, !kFin, std::move(response_headers),
+                                     &spdy_response_headers_frame_length));
 
   delegate->WaitUntilNextCallback(kOnHeadersReceived);
 
@@ -2358,11 +2322,10 @@
   // Server sends the response headers.
   spdy::SpdyHeaderBlock response_headers = ConstructResponseHeaders("200");
 
-  quic::QuicStreamOffset offset = 0;
   size_t spdy_response_headers_frame_length;
-  ProcessPacket(ConstructResponseHeadersPacket(
-      2, !kFin, std::move(response_headers),
-      &spdy_response_headers_frame_length, &offset));
+  ProcessPacket(
+      ConstructResponseHeadersPacket(2, !kFin, std::move(response_headers),
+                                     &spdy_response_headers_frame_length));
 
   delegate->WaitUntilNextCallback(kOnHeadersReceived);
 
@@ -2387,8 +2350,8 @@
   trailers[quic::kFinalOffsetHeaderKey] =
       base::NumberToString(strlen(kResponseBody));
   // Server sends trailers.
-  ProcessPacket(ConstructResponseTrailersPacket(
-      4, kFin, trailers.Clone(), &spdy_trailers_frame_length, &offset));
+  ProcessPacket(ConstructResponseTrailersPacket(4, kFin, trailers.Clone(),
+                                                &spdy_trailers_frame_length));
 
   delegate->WaitUntilNextCallback(kOnTrailersReceived);
   trailers.erase(quic::kFinalOffsetHeaderKey);
diff --git a/net/quic/quic_chromium_client_session_test.cc b/net/quic/quic_chromium_client_session_test.cc
index 1d269e2..79cf49c 100644
--- a/net/quic/quic_chromium_client_session_test.cc
+++ b/net/quic/quic_chromium_client_session_test.cc
@@ -264,7 +264,7 @@
 TEST_P(QuicChromiumClientSessionTest, IsFatalErrorNotSetForNonFatalError) {
   MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
   std::unique_ptr<quic::QuicEncryptedPacket> settings_packet(
-      client_maker_.MakeInitialSettingsPacket(1, nullptr));
+      client_maker_.MakeInitialSettingsPacket(1));
   MockWrite writes[] = {
       MockWrite(ASYNC, settings_packet->data(), settings_packet->length(), 1)};
   socket_data_.reset(new SequencedSocketData(reads, writes));
@@ -287,7 +287,7 @@
 TEST_P(QuicChromiumClientSessionTest, IsFatalErrorSetForFatalError) {
   MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
   std::unique_ptr<quic::QuicEncryptedPacket> settings_packet(
-      client_maker_.MakeInitialSettingsPacket(1, nullptr));
+      client_maker_.MakeInitialSettingsPacket(1));
   MockWrite writes[] = {
       MockWrite(ASYNC, settings_packet->data(), settings_packet->length(), 1)};
   socket_data_.reset(new SequencedSocketData(reads, writes));
@@ -309,7 +309,7 @@
 TEST_P(QuicChromiumClientSessionTest, CryptoConnect) {
   MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
   std::unique_ptr<quic::QuicEncryptedPacket> settings_packet(
-      client_maker_.MakeInitialSettingsPacket(1, nullptr));
+      client_maker_.MakeInitialSettingsPacket(1));
   MockWrite writes[] = {
       MockWrite(ASYNC, settings_packet->data(), settings_packet->length(), 1)};
   socket_data_.reset(new SequencedSocketData(reads, writes));
@@ -319,8 +319,7 @@
 
 TEST_P(QuicChromiumClientSessionTest, Handle) {
   MockQuicData quic_data(version_);
-  quic_data.AddWrite(SYNCHRONOUS,
-                     client_maker_.MakeInitialSettingsPacket(1, nullptr));
+  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_);
@@ -405,8 +404,7 @@
 
 TEST_P(QuicChromiumClientSessionTest, StreamRequest) {
   MockQuicData quic_data(version_);
-  quic_data.AddWrite(SYNCHRONOUS,
-                     client_maker_.MakeInitialSettingsPacket(1, nullptr));
+  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_);
@@ -430,8 +428,7 @@
 
 TEST_P(QuicChromiumClientSessionTest, ConfirmationRequiredStreamRequest) {
   MockQuicData quic_data(version_);
-  quic_data.AddWrite(SYNCHRONOUS,
-                     client_maker_.MakeInitialSettingsPacket(1, nullptr));
+  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_);
@@ -455,8 +452,7 @@
 
 TEST_P(QuicChromiumClientSessionTest, StreamRequestBeforeConfirmation) {
   MockQuicData quic_data(version_);
-  quic_data.AddWrite(SYNCHRONOUS,
-                     client_maker_.MakeInitialSettingsPacket(1, nullptr));
+  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_);
@@ -485,8 +481,7 @@
 
 TEST_P(QuicChromiumClientSessionTest, CancelStreamRequestBeforeRelease) {
   MockQuicData quic_data(version_);
-  quic_data.AddWrite(SYNCHRONOUS,
-                     client_maker_.MakeInitialSettingsPacket(1, nullptr));
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
   quic_data.AddWrite(SYNCHRONOUS,
                      client_maker_.MakeRstPacket(
                          2, true, GetNthClientInitiatedBidirectionalStreamId(0),
@@ -514,8 +509,7 @@
 
 TEST_P(QuicChromiumClientSessionTest, AsyncStreamRequest) {
   MockQuicData quic_data(version_);
-  quic_data.AddWrite(SYNCHRONOUS,
-                     client_maker_.MakeInitialSettingsPacket(1, nullptr));
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
   if (version_.transport_version == quic::QUIC_VERSION_99) {
     // The open stream limit is set to 50 by
     // MockCryptoClientStream::SetConfigNegotiated() so when the 51st stream is
@@ -591,8 +585,7 @@
 
 TEST_P(QuicChromiumClientSessionTest, ClosedWithAsyncStreamRequest) {
   MockQuicData quic_data(version_);
-  quic_data.AddWrite(SYNCHRONOUS,
-                     client_maker_.MakeInitialSettingsPacket(1, nullptr));
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
   if (version_.transport_version == quic::QUIC_VERSION_99) {
     // The open stream limit is set to 50 by
     // MockCryptoClientStream::SetConfigNegotiated() so when the 51st stream is
@@ -654,8 +647,7 @@
 
 TEST_P(QuicChromiumClientSessionTest, CancelPendingStreamRequest) {
   MockQuicData quic_data(version_);
-  quic_data.AddWrite(SYNCHRONOUS,
-                     client_maker_.MakeInitialSettingsPacket(1, nullptr));
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
   if (version_.transport_version == quic::QUIC_VERSION_99) {
     // The open stream limit is set to 50 by
     // MockCryptoClientStream::SetConfigNegotiated() so when the 51st stream is
@@ -726,8 +718,7 @@
 
 TEST_P(QuicChromiumClientSessionTest, ConnectionCloseBeforeStreamRequest) {
   MockQuicData quic_data(version_);
-  quic_data.AddWrite(SYNCHRONOUS,
-                     client_maker_.MakeInitialSettingsPacket(1, nullptr));
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
   quic_data.AddRead(
       ASYNC,
       server_maker_.MakeConnectionClosePacket(
@@ -795,8 +786,7 @@
 
 TEST_P(QuicChromiumClientSessionTest, ConnectionCloseWithPendingStreamRequest) {
   MockQuicData quic_data(version_);
-  quic_data.AddWrite(SYNCHRONOUS,
-                     client_maker_.MakeInitialSettingsPacket(1, nullptr));
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
   if (version_.transport_version == quic::QUIC_VERSION_99) {
     quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeStreamsBlockedPacket(
                                         2, true, 51,
@@ -842,8 +832,7 @@
 
 TEST_P(QuicChromiumClientSessionTest, MaxNumStreams) {
   MockQuicData quic_data(version_);
-  quic_data.AddWrite(SYNCHRONOUS,
-                     client_maker_.MakeInitialSettingsPacket(1, nullptr));
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
   if (version_.transport_version == quic::QUIC_VERSION_99) {
     // Initial configuration is 50 dynamic streams. Taking into account
     // the static stream (headers), expect to block on when hitting the limit
@@ -912,7 +901,7 @@
   base::HistogramTester histogram_tester;
   MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
   std::unique_ptr<quic::QuicEncryptedPacket> settings_packet(
-      client_maker_.MakeInitialSettingsPacket(1, nullptr));
+      client_maker_.MakeInitialSettingsPacket(1));
   std::unique_ptr<quic::QuicEncryptedPacket> client_rst(
       client_maker_.MakeRstPacket(
           2, true, GetNthServerInitiatedUnidirectionalStreamId(0),
@@ -964,7 +953,7 @@
   base::HistogramTester histogram_tester;
   MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
   std::unique_ptr<quic::QuicEncryptedPacket> settings_packet(
-      client_maker_.MakeInitialSettingsPacket(1, nullptr));
+      client_maker_.MakeInitialSettingsPacket(1));
   std::unique_ptr<quic::QuicEncryptedPacket> client_rst(
       client_maker_.MakeRstPacket(
           2, true, GetNthServerInitiatedUnidirectionalStreamId(0),
@@ -1024,7 +1013,7 @@
 
   MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
   std::unique_ptr<quic::QuicEncryptedPacket> settings_packet(
-      client_maker_.MakeInitialSettingsPacket(1, nullptr));
+      client_maker_.MakeInitialSettingsPacket(1));
   std::unique_ptr<quic::QuicEncryptedPacket> client_rst(
       client_maker_.MakeRstPacket(
           2, true, GetNthServerInitiatedUnidirectionalStreamId(0),
@@ -1051,7 +1040,7 @@
 TEST_P(QuicChromiumClientSessionTest, CancelPushWhenPendingValidation) {
   MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
   std::unique_ptr<quic::QuicEncryptedPacket> settings_packet(
-      client_maker_.MakeInitialSettingsPacket(1, nullptr));
+      client_maker_.MakeInitialSettingsPacket(1));
   std::unique_ptr<quic::QuicEncryptedPacket> client_rst(
       client_maker_.MakeRstPacket(2, true,
                                   GetNthClientInitiatedBidirectionalStreamId(0),
@@ -1108,7 +1097,7 @@
   base::HistogramTester histogram_tester;
   MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
   std::unique_ptr<quic::QuicEncryptedPacket> settings_packet(
-      client_maker_.MakeInitialSettingsPacket(1, nullptr));
+      client_maker_.MakeInitialSettingsPacket(1));
   std::unique_ptr<quic::QuicEncryptedPacket> client_rst(
       client_maker_.MakeRstPacket(
           2, true, GetNthServerInitiatedUnidirectionalStreamId(0),
@@ -1160,7 +1149,7 @@
   base::HistogramTester histogram_tester;
   MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
   std::unique_ptr<quic::QuicEncryptedPacket> settings_packet(
-      client_maker_.MakeInitialSettingsPacket(1, nullptr));
+      client_maker_.MakeInitialSettingsPacket(1));
   std::unique_ptr<quic::QuicEncryptedPacket> client_rst(
       client_maker_.MakeRstPacket(
           2, true, GetNthServerInitiatedUnidirectionalStreamId(0),
@@ -1217,8 +1206,7 @@
 
 TEST_P(QuicChromiumClientSessionTest, MaxNumStreamsViaRequest) {
   MockQuicData quic_data(version_);
-  quic_data.AddWrite(SYNCHRONOUS,
-                     client_maker_.MakeInitialSettingsPacket(1, nullptr));
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
   if (version_.transport_version == quic::QUIC_VERSION_99) {
     quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeStreamsBlockedPacket(
                                         2, true, 51,
@@ -1275,7 +1263,7 @@
 TEST_P(QuicChromiumClientSessionTest, GoAwayReceived) {
   MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
   std::unique_ptr<quic::QuicEncryptedPacket> settings_packet(
-      client_maker_.MakeInitialSettingsPacket(1, nullptr));
+      client_maker_.MakeInitialSettingsPacket(1));
   MockWrite writes[] = {
       MockWrite(ASYNC, settings_packet->data(), settings_packet->length(), 1)};
   socket_data_.reset(new SequencedSocketData(reads, writes));
@@ -1294,7 +1282,7 @@
 TEST_P(QuicChromiumClientSessionTest, CanPool) {
   MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
   std::unique_ptr<quic::QuicEncryptedPacket> settings_packet(
-      client_maker_.MakeInitialSettingsPacket(1, nullptr));
+      client_maker_.MakeInitialSettingsPacket(1));
   MockWrite writes[] = {
       MockWrite(ASYNC, settings_packet->data(), settings_packet->length(), 1)};
   socket_data_.reset(new SequencedSocketData(reads, writes));
@@ -1367,7 +1355,7 @@
 
   MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
   std::unique_ptr<quic::QuicEncryptedPacket> settings_packet(
-      client_maker_.MakeInitialSettingsPacket(1, nullptr));
+      client_maker_.MakeInitialSettingsPacket(1));
   MockWrite writes[] = {
       MockWrite(ASYNC, settings_packet->data(), settings_packet->length(), 1)};
   socket_data_.reset(new SequencedSocketData(reads, writes));
@@ -1425,7 +1413,7 @@
 
   MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
   std::unique_ptr<quic::QuicEncryptedPacket> settings_packet(
-      client_maker_.MakeInitialSettingsPacket(1, nullptr));
+      client_maker_.MakeInitialSettingsPacket(1));
   MockWrite writes[] = {
       MockWrite(ASYNC, settings_packet->data(), settings_packet->length(), 1)};
   socket_data_.reset(new SequencedSocketData(reads, writes));
@@ -1456,7 +1444,7 @@
 
   MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
   std::unique_ptr<quic::QuicEncryptedPacket> settings_packet(
-      client_maker_.MakeInitialSettingsPacket(1, nullptr));
+      client_maker_.MakeInitialSettingsPacket(1));
   MockWrite writes[] = {
       MockWrite(ASYNC, settings_packet->data(), settings_packet->length(), 1)};
   socket_data_.reset(new SequencedSocketData(reads, writes));
@@ -1486,7 +1474,7 @@
 TEST_P(QuicChromiumClientSessionTest, MigrateToSocket) {
   MockRead old_reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
   std::unique_ptr<quic::QuicEncryptedPacket> settings_packet(
-      client_maker_.MakeInitialSettingsPacket(1, nullptr));
+      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));
@@ -1551,7 +1539,7 @@
 TEST_P(QuicChromiumClientSessionTest, MigrateToSocketMaxReaders) {
   MockRead old_reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
   std::unique_ptr<quic::QuicEncryptedPacket> settings_packet(
-      client_maker_.MakeInitialSettingsPacket(1, nullptr));
+      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));
@@ -1604,7 +1592,7 @@
 
 TEST_P(QuicChromiumClientSessionTest, MigrateToSocketReadError) {
   std::unique_ptr<quic::QuicEncryptedPacket> settings_packet(
-      client_maker_.MakeInitialSettingsPacket(1, nullptr));
+      client_maker_.MakeInitialSettingsPacket(1));
   std::unique_ptr<quic::QuicEncryptedPacket> client_ping;
   client_ping = client_maker_.MakeAckAndPingPacket(2, false, 1, 1, 1);
   std::unique_ptr<quic::QuicEncryptedPacket> server_ping(
@@ -1738,8 +1726,7 @@
   migrate_session_early_v2_ = true;
 
   MockQuicData quic_data(version_);
-  quic_data.AddWrite(SYNCHRONOUS,
-                     client_maker_.MakeInitialSettingsPacket(1, nullptr));
+  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));
 
diff --git a/net/quic/quic_http_stream_test.cc b/net/quic/quic_http_stream_test.cc
index f794486..4bf09a6 100644
--- a/net/quic/quic_http_stream_test.cc
+++ b/net/quic/quic_http_stream_test.cc
@@ -40,6 +40,7 @@
 #include "net/quic/quic_server_info.h"
 #include "net/quic/quic_stream_factory.h"
 #include "net/quic/quic_test_packet_maker.h"
+#include "net/quic/quic_test_packet_printer.h"
 #include "net/quic/test_task_runner.h"
 #include "net/socket/socket_performance_watcher.h"
 #include "net/socket/socket_test_util.h"
@@ -214,7 +215,7 @@
                       quic::Perspective::IS_SERVER,
                       false),
         random_generator_(0),
-        response_offset_(0) {
+        printer_(version_) {
     IPAddress ip(192, 0, 2, 33);
     peer_addr_ = IPEndPoint(ip, 443);
     self_addr_ = IPEndPoint(ip, 8435);
@@ -268,6 +269,7 @@
     socket_data_.reset(new StaticSocketDataProvider(
         base::span<MockRead>(),
         base::make_span(mock_writes_.get(), writes_.size())));
+    socket_data_->set_printer(&printer_);
 
     std::unique_ptr<MockUDPClientSocket> socket(new MockUDPClientSocket(
         socket_data_.get(), net_log_.bound().net_log()));
@@ -422,11 +424,10 @@
       bool should_include_version,
       bool fin,
       RequestPriority request_priority,
-      size_t* spdy_headers_frame_length,
-      quic::QuicStreamOffset* offset) {
+      size_t* spdy_headers_frame_length) {
     return InnerConstructRequestHeadersPacket(
         packet_number, stream_id, should_include_version, fin, request_priority,
-        0, spdy_headers_frame_length, offset);
+        0, spdy_headers_frame_length);
   }
 
   std::unique_ptr<quic::QuicReceivedPacket> InnerConstructRequestHeadersPacket(
@@ -436,14 +437,13 @@
       bool fin,
       RequestPriority request_priority,
       quic::QuicStreamId parent_stream_id,
-      size_t* spdy_headers_frame_length,
-      quic::QuicStreamOffset* offset) {
+      size_t* spdy_headers_frame_length) {
     spdy::SpdyPriority priority =
         ConvertRequestPriorityToQuicPriority(request_priority);
     return client_maker_.MakeRequestHeadersPacket(
         packet_number, stream_id, should_include_version, fin, priority,
         std::move(request_headers_), parent_stream_id,
-        spdy_headers_frame_length, offset);
+        spdy_headers_frame_length);
   }
 
   std::unique_ptr<quic::QuicReceivedPacket>
@@ -454,14 +454,13 @@
       bool fin,
       RequestPriority request_priority,
       quic::QuicStreamId parent_stream_id,
-      quic::QuicStreamOffset* offset,
       size_t* spdy_headers_frame_length,
       const std::vector<std::string>& data_writes) {
     spdy::SpdyPriority priority =
         ConvertRequestPriorityToQuicPriority(request_priority);
     return client_maker_.MakeRequestHeadersAndMultipleDataFramesPacket(
         packet_number, stream_id, should_include_version, fin, priority,
-        std::move(request_headers_), parent_stream_id, offset,
+        std::move(request_headers_), parent_stream_id,
         spdy_headers_frame_length, data_writes);
   }
 
@@ -473,7 +472,6 @@
       RequestPriority request_priority,
       quic::QuicStreamId parent_stream_id,
       size_t* spdy_headers_frame_length,
-      quic::QuicStreamOffset* header_stream_offset,
       quic::QuicRstStreamErrorCode error_code,
       size_t bytes_written) {
     spdy::SpdyPriority priority =
@@ -481,8 +479,7 @@
     return client_maker_.MakeRequestHeadersAndRstPacket(
         packet_number, stream_id, should_include_version, fin, priority,
         std::move(request_headers_), parent_stream_id,
-        spdy_headers_frame_length, header_stream_offset, error_code,
-        bytes_written);
+        spdy_headers_frame_length, error_code, bytes_written);
   }
 
   std::unique_ptr<quic::QuicReceivedPacket> ConstructRequestHeadersPacket(
@@ -492,7 +489,7 @@
       size_t* spdy_headers_frame_length) {
     return InnerConstructRequestHeadersPacket(
         packet_number, stream_id_, kIncludeVersion, fin, request_priority,
-        spdy_headers_frame_length, nullptr);
+        spdy_headers_frame_length);
   }
 
   std::unique_ptr<quic::QuicReceivedPacket> InnerConstructResponseHeadersPacket(
@@ -502,8 +499,7 @@
       size_t* spdy_headers_frame_length) {
     return server_maker_.MakeResponseHeadersPacket(
         packet_number, stream_id, !kIncludeVersion, fin,
-        std::move(response_headers_), spdy_headers_frame_length,
-        &response_offset_);
+        std::move(response_headers_), spdy_headers_frame_length);
   }
 
   std::unique_ptr<quic::QuicReceivedPacket> ConstructResponseHeadersPacket(
@@ -514,25 +510,14 @@
                                                spdy_headers_frame_length);
   }
 
-  std::unique_ptr<quic::QuicReceivedPacket>
-  ConstructResponseHeadersPacketWithOffset(uint64_t packet_number,
-                                           bool fin,
-                                           size_t* spdy_headers_frame_length,
-                                           quic::QuicStreamOffset* offset) {
-    return server_maker_.MakeResponseHeadersPacket(
-        packet_number, stream_id_, !kIncludeVersion, fin,
-        std::move(response_headers_), spdy_headers_frame_length, offset);
-  }
-
   std::unique_ptr<quic::QuicReceivedPacket> ConstructResponseTrailersPacket(
       uint64_t packet_number,
       bool fin,
       spdy::SpdyHeaderBlock trailers,
-      size_t* spdy_headers_frame_length,
-      quic::QuicStreamOffset* offset) {
+      size_t* spdy_headers_frame_length) {
     return server_maker_.MakeResponseHeadersPacket(
         packet_number, stream_id_, !kIncludeVersion, fin, std::move(trailers),
-        spdy_headers_frame_length, offset);
+        spdy_headers_frame_length);
   }
 
   std::unique_ptr<quic::QuicReceivedPacket> ConstructClientRstStreamPacket(
@@ -562,15 +547,14 @@
       bool fin,
       RequestPriority request_priority,
       quic::QuicStreamId parent_stream_id,
-      size_t* spdy_headers_frame_length,
-      quic::QuicStreamOffset* offset) {
+      size_t* spdy_headers_frame_length) {
     spdy::SpdyPriority priority =
         ConvertRequestPriorityToQuicPriority(request_priority);
     return client_maker_.MakeRstAndRequestHeadersPacket(
         packet_number, should_include_version, promise_id_,
         quic::QUIC_PROMISE_VARY_MISMATCH, stream_id, fin, priority,
         std::move(request_headers_), parent_stream_id,
-        spdy_headers_frame_length, offset);
+        spdy_headers_frame_length);
   }
 
   std::unique_ptr<quic::QuicReceivedPacket> ConstructAckAndRstStreamPacket(
@@ -622,17 +606,14 @@
       bool should_include_version,
       quic::QuicStreamId id,
       quic::QuicStreamId parent_stream_id,
-      RequestPriority request_priority,
-      quic::QuicStreamOffset* header_stream_offset) {
+      RequestPriority request_priority) {
     return client_maker_.MakePriorityPacket(
         packet_number, should_include_version, id, parent_stream_id,
-        ConvertRequestPriorityToQuicPriority(request_priority),
-        header_stream_offset);
+        ConvertRequestPriorityToQuicPriority(request_priority));
   }
 
-  std::unique_ptr<quic::QuicReceivedPacket> ConstructInitialSettingsPacket(
-      quic::QuicStreamOffset* offset) {
-    return client_maker_.MakeInitialSettingsPacket(1, offset);
+  std::unique_ptr<quic::QuicReceivedPacket> ConstructInitialSettingsPacket() {
+    return client_maker_.MakeInitialSettingsPacket(1);
   }
 
   std::string ConstructDataHeader(size_t body_len) {
@@ -721,8 +702,8 @@
   ProofVerifyDetailsChromium verify_details_;
   MockCryptoClientStreamFactory crypto_client_stream_factory_;
   std::unique_ptr<StaticSocketDataProvider> socket_data_;
+  QuicPacketPrinter printer_;
   std::vector<PacketToWrite> writes_;
-  quic::QuicStreamOffset response_offset_;
 };
 
 INSTANTIATE_TEST_SUITE_P(
@@ -755,12 +736,10 @@
 TEST_P(QuicHttpStreamTest, GetRequest) {
   SetRequest("GET", "/", DEFAULT_PRIORITY);
   size_t spdy_request_header_frame_length;
-  quic::QuicStreamOffset header_stream_offset = 0;
-  AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
+  AddWrite(ConstructInitialSettingsPacket());
   AddWrite(InnerConstructRequestHeadersPacket(
       2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
-      DEFAULT_PRIORITY, &spdy_request_header_frame_length,
-      &header_stream_offset));
+      DEFAULT_PRIORITY, &spdy_request_header_frame_length));
 
   Initialize();
 
@@ -818,18 +797,17 @@
   SetRequest("GET", "/", DEFAULT_PRIORITY);
   size_t spdy_request_header_frame_length;
 
-  quic::QuicStreamOffset offset = 0;
-  AddWrite(ConstructInitialSettingsPacket(&offset));
+  AddWrite(ConstructInitialSettingsPacket());
   AddWrite(InnerConstructRequestHeadersPacket(
       2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
-      DEFAULT_PRIORITY, &spdy_request_header_frame_length, &offset));
+      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),
-      &spdy_request_header_frame_length, &offset));
+      &spdy_request_header_frame_length));
   AddWrite(ConstructClientAckPacket(4, 3, 1, 2));  // Ack the responses.
 
   Initialize();
@@ -905,12 +883,10 @@
 TEST_P(QuicHttpStreamTest, GetRequestWithTrailers) {
   SetRequest("GET", "/", DEFAULT_PRIORITY);
   size_t spdy_request_header_frame_length;
-  quic::QuicStreamOffset header_stream_offset = 0;
-  AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
+  AddWrite(ConstructInitialSettingsPacket());
   AddWrite(InnerConstructRequestHeadersPacket(
       2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
-      DEFAULT_PRIORITY, &spdy_request_header_frame_length,
-      &header_stream_offset));
+      DEFAULT_PRIORITY, &spdy_request_header_frame_length));
   AddWrite(ConstructClientAckPacket(3, 3, 1, 2));  // Ack the data packet.
 
   Initialize();
@@ -934,9 +910,8 @@
 
   // Send the response headers.
   size_t spdy_response_header_frame_length;
-  quic::QuicStreamOffset offset = 0;
-  ProcessPacket(ConstructResponseHeadersPacketWithOffset(
-      2, !kFin, &spdy_response_header_frame_length, &offset));
+  ProcessPacket(ConstructResponseHeadersPacket(
+      2, !kFin, &spdy_response_header_frame_length));
   // Now that the headers have been processed, the callback will return.
   EXPECT_THAT(callback_.WaitForResult(), IsOk());
   ASSERT_TRUE(response_.headers.get());
@@ -955,8 +930,8 @@
   trailers["foo"] = "bar";
   trailers[quic::kFinalOffsetHeaderKey] =
       base::NumberToString(strlen(kResponseBody) + header.length());
-  ProcessPacket(ConstructResponseTrailersPacket(
-      4, kFin, std::move(trailers), &spdy_trailers_frame_length, &offset));
+  ProcessPacket(ConstructResponseTrailersPacket(4, kFin, std::move(trailers),
+                                                &spdy_trailers_frame_length));
 
   // Make sure trailers are processed.
   base::RunLoop().RunUntilIdle();
@@ -1002,12 +977,10 @@
 TEST_P(QuicHttpStreamTest, GetRequestLargeResponse) {
   SetRequest("GET", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  quic::QuicStreamOffset header_stream_offset = 0;
-  AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
+  AddWrite(ConstructInitialSettingsPacket());
   AddWrite(InnerConstructRequestHeadersPacket(
       2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
-      DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
-      &header_stream_offset));
+      DEFAULT_PRIORITY, &spdy_request_headers_frame_length));
   Initialize();
 
   request_.method = "GET";
@@ -1130,12 +1103,10 @@
 TEST_P(QuicHttpStreamTest, LogGranularQuicConnectionError) {
   SetRequest("GET", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  quic::QuicStreamOffset header_stream_offset = 0;
-  AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
+  AddWrite(ConstructInitialSettingsPacket());
   AddWrite(InnerConstructRequestHeadersPacket(
       2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
-      DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
-      &header_stream_offset));
+      DEFAULT_PRIORITY, &spdy_request_headers_frame_length));
   AddWrite(ConstructAckAndRstStreamPacket(3));
   Initialize();
 
@@ -1171,12 +1142,10 @@
 
   SetRequest("GET", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  quic::QuicStreamOffset header_stream_offset = 0;
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
   AddWrite(InnerConstructRequestHeadersPacket(
       1, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
-      DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
-      &header_stream_offset));
+      DEFAULT_PRIORITY, &spdy_request_headers_frame_length));
   Initialize();
 
   request_.method = "GET";
@@ -1206,12 +1175,10 @@
 TEST_P(QuicHttpStreamTest, SessionClosedBeforeReadResponseHeaders) {
   SetRequest("GET", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  quic::QuicStreamOffset header_stream_offset = 0;
-  AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
+  AddWrite(ConstructInitialSettingsPacket());
   AddWrite(InnerConstructRequestHeadersPacket(
       2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
-      DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
-      &header_stream_offset));
+      DEFAULT_PRIORITY, &spdy_request_headers_frame_length));
   Initialize();
 
   request_.method = "GET";
@@ -1239,20 +1206,19 @@
 TEST_P(QuicHttpStreamTest, SendPostRequest) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  quic::QuicStreamOffset header_stream_offset = 0;
-  AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
+  AddWrite(ConstructInitialSettingsPacket());
 
   std::string header = ConstructDataHeader(strlen(kUploadData));
   if (version_.transport_version != quic::QUIC_VERSION_99) {
     AddWrite(ConstructRequestHeadersAndDataFramesPacket(
         2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
-        DEFAULT_PRIORITY, 0, &header_stream_offset,
-        &spdy_request_headers_frame_length, {kUploadData}));
+        DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
+        {kUploadData}));
   } else {
     AddWrite(ConstructRequestHeadersAndDataFramesPacket(
         2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
-        DEFAULT_PRIORITY, 0, &header_stream_offset,
-        &spdy_request_headers_frame_length, {header, kUploadData}));
+        DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
+        {header, kUploadData}));
   }
 
   AddWrite(ConstructClientAckPacket(3, 3, 1, 2));
@@ -1321,19 +1287,18 @@
 TEST_P(QuicHttpStreamTest, SendPostRequestAndReceiveSoloFin) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  quic::QuicStreamOffset header_stream_offset = 0;
-  AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
+  AddWrite(ConstructInitialSettingsPacket());
   std::string header = ConstructDataHeader(strlen(kUploadData));
   if (version_.transport_version != quic::QUIC_VERSION_99) {
     AddWrite(ConstructRequestHeadersAndDataFramesPacket(
         2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
-        DEFAULT_PRIORITY, 0, &header_stream_offset,
-        &spdy_request_headers_frame_length, {kUploadData}));
+        DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
+        {kUploadData}));
   } else {
     AddWrite(ConstructRequestHeadersAndDataFramesPacket(
         2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
-        DEFAULT_PRIORITY, 0, &header_stream_offset,
-        &spdy_request_headers_frame_length, {header, kUploadData}));
+        DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
+        {header, kUploadData}));
   }
 
   AddWrite(ConstructClientAckPacket(3, 3, 1, 2));
@@ -1405,22 +1370,21 @@
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   size_t chunk_size = strlen(kUploadData);
   size_t spdy_request_headers_frame_length;
-  quic::QuicStreamOffset header_stream_offset = 0;
-  AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
+  AddWrite(ConstructInitialSettingsPacket());
   std::string header = ConstructDataHeader(chunk_size);
   if (version_.transport_version == quic::QUIC_VERSION_99) {
     AddWrite(ConstructRequestHeadersAndDataFramesPacket(
         2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
-        !kFin, DEFAULT_PRIORITY, 0, &header_stream_offset,
-        &spdy_request_headers_frame_length, {header, kUploadData}));
+        !kFin, DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
+        {header, kUploadData}));
     AddWrite(ConstructClientMultipleDataFramesPacket(
         3, kIncludeVersion, kFin, header.length() + chunk_size,
         {header, kUploadData}));
   } else {
     AddWrite(ConstructRequestHeadersAndDataFramesPacket(
         2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
-        !kFin, DEFAULT_PRIORITY, 0, &header_stream_offset,
-        &spdy_request_headers_frame_length, {kUploadData}));
+        !kFin, DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
+        {kUploadData}));
     AddWrite(ConstructClientDataPacket(3, kIncludeVersion, kFin, chunk_size,
                                        kUploadData));
   }
@@ -1491,20 +1455,19 @@
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   size_t chunk_size = strlen(kUploadData);
   size_t spdy_request_headers_frame_length;
-  quic::QuicStreamOffset header_stream_offset = 0;
-  AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
+  AddWrite(ConstructInitialSettingsPacket());
   std::string header = ConstructDataHeader(chunk_size);
 
   if (version_.transport_version != quic::QUIC_VERSION_99) {
     AddWrite(ConstructRequestHeadersAndDataFramesPacket(
         2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
-        !kFin, DEFAULT_PRIORITY, 0, &header_stream_offset,
-        &spdy_request_headers_frame_length, {kUploadData}));
+        !kFin, DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
+        {kUploadData}));
   } else {
     AddWrite(ConstructRequestHeadersAndDataFramesPacket(
         2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
-        !kFin, DEFAULT_PRIORITY, 0, &header_stream_offset,
-        &spdy_request_headers_frame_length, {header, kUploadData}));
+        !kFin, DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
+        {header, kUploadData}));
   }
   AddWrite(ConstructClientDataPacket(3, kIncludeVersion, kFin,
                                      chunk_size + header.length(), ""));
@@ -1571,12 +1534,10 @@
 TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithOneEmptyDataPacket) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  quic::QuicStreamOffset header_stream_offset = 0;
-  AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
+  AddWrite(ConstructInitialSettingsPacket());
   AddWrite(InnerConstructRequestHeadersPacket(
       2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, !kFin,
-      DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
-      &header_stream_offset));
+      DEFAULT_PRIORITY, &spdy_request_headers_frame_length));
   AddWrite(ConstructClientDataPacket(3, kIncludeVersion, kFin, 0, ""));
   AddWrite(ConstructClientAckPacket(4, 3, 1, 2));
   Initialize();
@@ -1640,12 +1601,10 @@
 TEST_P(QuicHttpStreamTest, DestroyedEarly) {
   SetRequest("GET", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  quic::QuicStreamOffset header_stream_offset = 0;
-  AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
+  AddWrite(ConstructInitialSettingsPacket());
   AddWrite(InnerConstructRequestHeadersPacket(
       2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
-      DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
-      &header_stream_offset));
+      DEFAULT_PRIORITY, &spdy_request_headers_frame_length));
   AddWrite(ConstructAckAndRstStreamPacket(3));
   Initialize();
 
@@ -1687,11 +1646,10 @@
 TEST_P(QuicHttpStreamTest, Priority) {
   SetRequest("GET", "/", MEDIUM);
   size_t spdy_request_headers_frame_length;
-  quic::QuicStreamOffset header_stream_offset = 0;
-  AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
+  AddWrite(ConstructInitialSettingsPacket());
   AddWrite(InnerConstructRequestHeadersPacket(
       2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, kFin,
-      MEDIUM, &spdy_request_headers_frame_length, &header_stream_offset));
+      MEDIUM, &spdy_request_headers_frame_length));
   Initialize();
 
   request_.method = "GET";
@@ -1729,19 +1687,18 @@
 TEST_P(QuicHttpStreamTest, SessionClosedDuringDoLoop) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  quic::QuicStreamOffset header_stream_offset = 0;
-  AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
+  AddWrite(ConstructInitialSettingsPacket());
   std::string header = ConstructDataHeader(strlen(kUploadData));
   if (version_.transport_version != quic::QUIC_VERSION_99) {
     AddWrite(ConstructRequestHeadersAndDataFramesPacket(
         2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
-        !kFin, DEFAULT_PRIORITY, 0, &header_stream_offset,
-        &spdy_request_headers_frame_length, {kUploadData}));
+        !kFin, DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
+        {kUploadData}));
   } else {
     AddWrite(ConstructRequestHeadersAndDataFramesPacket(
         2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
-        !kFin, DEFAULT_PRIORITY, 0, &header_stream_offset,
-        &spdy_request_headers_frame_length, {header, kUploadData}));
+        !kFin, DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
+        {header, kUploadData}));
   }
 
   // Second data write will result in a synchronous failure which will close
@@ -1781,8 +1738,7 @@
 
 TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersComplete) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
-  quic::QuicStreamOffset header_stream_offset = 0;
-  AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
+  AddWrite(ConstructInitialSettingsPacket());
   AddWrite(SYNCHRONOUS, ERR_FAILED);
   Initialize();
 
@@ -1813,8 +1769,7 @@
 
 TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersCompleteReadResponse) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
-  quic::QuicStreamOffset header_stream_offset = 0;
-  AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
+  AddWrite(ConstructInitialSettingsPacket());
   AddWrite(SYNCHRONOUS, ERR_FAILED);
   Initialize();
 
@@ -1849,12 +1804,10 @@
 TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBodyComplete) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  quic::QuicStreamOffset header_stream_offset = 0;
-  AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
+  AddWrite(ConstructInitialSettingsPacket());
   AddWrite(InnerConstructRequestHeadersPacket(
       2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, !kFin,
-      DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
-      &header_stream_offset));
+      DEFAULT_PRIORITY, &spdy_request_headers_frame_length));
   AddWrite(SYNCHRONOUS, ERR_FAILED);
   Initialize();
 
@@ -1890,19 +1843,18 @@
 TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBundledBodyComplete) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  quic::QuicStreamOffset header_stream_offset = 0;
-  AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
+  AddWrite(ConstructInitialSettingsPacket());
   std::string header = ConstructDataHeader(strlen(kUploadData));
   if (version_.transport_version != quic::QUIC_VERSION_99) {
     AddWrite(ConstructRequestHeadersAndDataFramesPacket(
         2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
-        !kFin, DEFAULT_PRIORITY, 0, &header_stream_offset,
-        &spdy_request_headers_frame_length, {kUploadData}));
+        !kFin, DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
+        {kUploadData}));
   } else {
     AddWrite(ConstructRequestHeadersAndDataFramesPacket(
         2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion,
-        !kFin, DEFAULT_PRIORITY, 0, &header_stream_offset,
-        &spdy_request_headers_frame_length, {header, kUploadData}));
+        !kFin, DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
+        {header, kUploadData}));
   }
 
   AddWrite(SYNCHRONOUS, ERR_FAILED);
@@ -2305,21 +2257,20 @@
   request_headers_["accept-encoding"] = "sdch";
 
   size_t spdy_request_header_frame_length;
-  quic::QuicStreamOffset header_stream_offset = 0;
-  AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
+  AddWrite(ConstructInitialSettingsPacket());
 
   uint64_t client_packet_number = 2;
   if (client_headers_include_h2_stream_dependency_ &&
       version_.transport_version >= quic::QUIC_VERSION_43) {
-    AddWrite(ConstructClientPriorityPacket(
-        client_packet_number++, kIncludeVersion, promise_id_, 0,
-        DEFAULT_PRIORITY, &header_stream_offset));
+    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, &header_stream_offset));
+      &spdy_request_header_frame_length));
   AddWrite(ConstructClientAckPacket(client_packet_number++, 3, 1, 2));
   AddWrite(ConstructClientRstStreamCancelledPacket(client_packet_number++));
 
@@ -2428,12 +2379,11 @@
 TEST_P(QuicHttpStreamTest, DataReadErrorSynchronous) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  quic::QuicStreamOffset header_stream_offset = 0;
-  AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
+  AddWrite(ConstructInitialSettingsPacket());
   AddWrite(ConstructRequestAndRstPacket(
       2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, !kFin,
       DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
-      &header_stream_offset, quic::QUIC_ERROR_PROCESSING_STREAM, 0));
+      quic::QUIC_ERROR_PROCESSING_STREAM, 0));
 
   Initialize();
 
@@ -2463,12 +2413,10 @@
 TEST_P(QuicHttpStreamTest, DataReadErrorAsynchronous) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
-  quic::QuicStreamOffset header_stream_offset = 0;
-  AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
+  AddWrite(ConstructInitialSettingsPacket());
   AddWrite(InnerConstructRequestHeadersPacket(
       2, GetNthClientInitiatedBidirectionalStreamId(0), kIncludeVersion, !kFin,
-      DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
-      &header_stream_offset));
+      DEFAULT_PRIORITY, &spdy_request_headers_frame_length));
   AddWrite(ConstructClientRstStreamErrorPacket(3, !kIncludeVersion));
 
   Initialize();
diff --git a/net/quic/quic_network_transaction_unittest.cc b/net/quic/quic_network_transaction_unittest.cc
index c1344d1..0497c7f1 100644
--- a/net/quic/quic_network_transaction_unittest.cc
+++ b/net/quic/quic_network_transaction_unittest.cc
@@ -411,9 +411,8 @@
   }
 
   std::unique_ptr<quic::QuicReceivedPacket> ConstructInitialSettingsPacket(
-      uint64_t packet_number,
-      quic::QuicStreamOffset* offset) {
-    return client_maker_.MakeInitialSettingsPacket(packet_number, offset);
+      uint64_t packet_number) {
+    return client_maker_.MakeInitialSettingsPacket(packet_number);
   }
 
   std::unique_ptr<quic::QuicReceivedPacket> ConstructServerAckPacket(
@@ -430,11 +429,10 @@
       bool should_include_version,
       quic::QuicStreamId id,
       quic::QuicStreamId parent_stream_id,
-      RequestPriority request_priority,
-      quic::QuicStreamOffset* offset) {
+      RequestPriority request_priority) {
     return client_maker_.MakePriorityPacket(
         packet_number, should_include_version, id, parent_stream_id,
-        ConvertRequestPriorityToQuicPriority(request_priority), offset);
+        ConvertRequestPriorityToQuicPriority(request_priority));
   }
 
   std::unique_ptr<quic::QuicEncryptedPacket>
@@ -445,11 +443,10 @@
       uint64_t smallest_received,
       uint64_t least_unacked,
       const std::vector<QuicTestPacketMaker::Http2StreamDependency>&
-          priority_frames,
-      quic::QuicStreamOffset* offset) {
+          priority_frames) {
     return client_maker_.MakeAckAndMultiplePriorityFramesPacket(
         packet_number, should_include_version, largest_received,
-        smallest_received, least_unacked, priority_frames, offset);
+        smallest_received, least_unacked, priority_frames);
   }
 
   // Uses default QuicTestPacketMaker.
@@ -566,7 +563,7 @@
                                       spdy::SpdyHeaderBlock headers) {
     return ConstructClientRequestHeadersPacket(packet_number, stream_id,
                                                should_include_version, fin,
-                                               std::move(headers), nullptr);
+                                               std::move(headers), 0);
   }
 
   std::unique_ptr<quic::QuicEncryptedPacket>
@@ -575,23 +572,10 @@
                                       bool should_include_version,
                                       bool fin,
                                       spdy::SpdyHeaderBlock headers,
-                                      quic::QuicStreamOffset* offset) {
-    return ConstructClientRequestHeadersPacket(packet_number, stream_id,
-                                               should_include_version, fin,
-                                               std::move(headers), 0, offset);
-  }
-
-  std::unique_ptr<quic::QuicEncryptedPacket>
-  ConstructClientRequestHeadersPacket(uint64_t packet_number,
-                                      quic::QuicStreamId stream_id,
-                                      bool should_include_version,
-                                      bool fin,
-                                      spdy::SpdyHeaderBlock headers,
-                                      quic::QuicStreamId parent_stream_id,
-                                      quic::QuicStreamOffset* offset) {
+                                      quic::QuicStreamId parent_stream_id) {
     return ConstructClientRequestHeadersPacket(
         packet_number, stream_id, should_include_version, fin, DEFAULT_PRIORITY,
-        std::move(headers), parent_stream_id, offset);
+        std::move(headers), parent_stream_id);
   }
 
   std::unique_ptr<quic::QuicEncryptedPacket>
@@ -601,13 +585,12 @@
                                       bool fin,
                                       RequestPriority request_priority,
                                       spdy::SpdyHeaderBlock headers,
-                                      quic::QuicStreamId parent_stream_id,
-                                      quic::QuicStreamOffset* offset) {
+                                      quic::QuicStreamId parent_stream_id) {
     spdy::SpdyPriority priority =
         ConvertRequestPriorityToQuicPriority(request_priority);
-    return client_maker_.MakeRequestHeadersPacketWithOffsetTracking(
+    return client_maker_.MakeRequestHeadersPacket(
         packet_number, stream_id, should_include_version, fin, priority,
-        std::move(headers), parent_stream_id, offset);
+        std::move(headers), parent_stream_id, nullptr);
   }
 
   std::unique_ptr<quic::QuicReceivedPacket>
@@ -619,39 +602,26 @@
       RequestPriority request_priority,
       spdy::SpdyHeaderBlock headers,
       quic::QuicStreamId parent_stream_id,
-      quic::QuicStreamOffset* offset,
       size_t* spdy_headers_frame_length,
       const std::vector<std::string>& data_writes) {
     spdy::SpdyPriority priority =
         ConvertRequestPriorityToQuicPriority(request_priority);
     return client_maker_.MakeRequestHeadersAndMultipleDataFramesPacket(
         packet_number, stream_id, should_include_version, fin, priority,
-        std::move(headers), parent_stream_id, offset, spdy_headers_frame_length,
+        std::move(headers), parent_stream_id, spdy_headers_frame_length,
         data_writes);
   }
 
-  std::unique_ptr<quic::QuicEncryptedPacket>
-  ConstructClientMultipleDataFramesPacket(uint64_t packet_number,
-                                          quic::QuicStreamId stream_id,
-                                          bool should_include_version,
-                                          bool fin,
-                                          const std::vector<std::string>& data,
-                                          quic::QuicStreamOffset offset) {
-    return client_maker_.MakeMultipleDataFramesPacket(
-        packet_number, stream_id, should_include_version, fin, offset, data);
-  }
-
   std::unique_ptr<quic::QuicEncryptedPacket> ConstructServerPushPromisePacket(
       uint64_t packet_number,
       quic::QuicStreamId stream_id,
       quic::QuicStreamId promised_stream_id,
       bool should_include_version,
       spdy::SpdyHeaderBlock headers,
-      quic::QuicStreamOffset* offset,
       QuicTestPacketMaker* maker) {
     return maker->MakePushPromisePacket(
         packet_number, stream_id, promised_stream_id, should_include_version,
-        false, std::move(headers), nullptr, offset);
+        false, std::move(headers), nullptr);
   }
 
   std::unique_ptr<quic::QuicEncryptedPacket>
@@ -660,21 +630,9 @@
                                        bool should_include_version,
                                        bool fin,
                                        spdy::SpdyHeaderBlock headers) {
-    return ConstructServerResponseHeadersPacket(packet_number, stream_id,
-                                                should_include_version, fin,
-                                                std::move(headers), nullptr);
-  }
-
-  std::unique_ptr<quic::QuicEncryptedPacket>
-  ConstructServerResponseHeadersPacket(uint64_t packet_number,
-                                       quic::QuicStreamId stream_id,
-                                       bool should_include_version,
-                                       bool fin,
-                                       spdy::SpdyHeaderBlock headers,
-                                       quic::QuicStreamOffset* offset) {
-    return server_maker_.MakeResponseHeadersPacketWithOffsetTracking(
-        packet_number, stream_id, should_include_version, fin,
-        std::move(headers), offset);
+    return server_maker_.MakeResponseHeadersPacket(packet_number, stream_id,
+                                                   should_include_version, fin,
+                                                   std::move(headers), nullptr);
   }
 
   std::string ConstructDataHeader(size_t body_len) {
@@ -1022,9 +980,7 @@
       MockCryptoClientStream::CONFIRM_HANDSHAKE);
 
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
+  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
@@ -1054,9 +1010,7 @@
       MockCryptoClientStream::CONFIRM_HANDSHAKE);
 
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
+  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
@@ -1082,14 +1036,11 @@
       HostPortPair::FromString("mail.example.org:443"));
 
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientRequestHeadersPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-          GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
+      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
+                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
+                       true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -1119,14 +1070,11 @@
       HostPortPair::FromString("mail.example.org:443"));
 
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientRequestHeadersPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-          GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
+      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
+                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
+                       true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -1156,14 +1104,11 @@
       HostPortPair::FromString("mail.example.org:443"));
 
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientRequestHeadersPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-          GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
+      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
+                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
+                       true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -1227,14 +1172,11 @@
       HostPortPair::FromString("mail.example.org:443"));
 
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientRequestHeadersPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-          GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
+      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
+                       2, 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');
@@ -1289,14 +1231,11 @@
       HostPortPair::FromString("mail.example.org:443"));
 
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientRequestHeadersPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-          GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
+      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
+                       2, 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');
@@ -1357,14 +1296,11 @@
   AddQuicAlternateProtocolMapping(MockCryptoClientStream::CONFIRM_HANDSHAKE);
 
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientRequestHeadersPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-          GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
+      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
+                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
+                       true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -1392,14 +1328,11 @@
       "QUIC mail.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientRequestHeadersPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-          GetRequestHeaders("GET", "http", "/"), &header_stream_offset));
+      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
+                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
+                       true, GetRequestHeaders("GET", "http", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -1441,14 +1374,11 @@
 
   client_maker_.set_hostname(origin_host);
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientRequestHeadersPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-          GetRequestHeaders("GET", "http", "/"), &header_stream_offset));
+      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
+                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
+                       true, GetRequestHeaders("GET", "http", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -1502,14 +1432,12 @@
 
   client_maker_.set_hostname(origin.host());
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
+
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientRequestHeadersPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-          GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
+      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
+                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
+                       true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -1595,14 +1523,11 @@
   // 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_);
-  quic::QuicStreamOffset header_stream_offset = 0;
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientRequestHeadersPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-          GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
+      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
+                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
+                       true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -1667,18 +1592,15 @@
   // 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_);
-  quic::QuicStreamOffset request_header_offset = 0;
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &request_header_offset));
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientRequestHeadersPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-          GetRequestHeaders("GET", "https", "/"), &request_header_offset));
+      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
+                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
+                       true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
-                 GetResponseHeaders("421"), nullptr));
+                 GetResponseHeaders("421")));
   mock_quic_data.AddRead(ASYNC, OK);
   mock_quic_data.AddSocketDataToFactory(&socket_factory_);
 
@@ -1727,14 +1649,11 @@
       HostPortPair::FromString("mail.example.org:443"));
 
   MockQuicData mock_quic_data1(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
-  mock_quic_data1.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
+  mock_quic_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   mock_quic_data1.AddRead(ASYNC, ERR_SOCKET_NOT_CONNECTED);
+  client_maker_.Reset();
   MockQuicData mock_quic_data2(version_);
-  header_stream_offset = 0;
-  mock_quic_data2.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
+  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_);
@@ -1793,14 +1712,11 @@
   socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
 
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientRequestHeadersPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-          GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
+      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
+                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
+                       true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -1860,14 +1776,11 @@
   socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
 
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientRequestHeadersPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-          GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
+      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
+                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
+                       true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -1923,14 +1836,11 @@
   socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
 
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientRequestHeadersPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-          GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
+      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
+                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
+                       true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -1968,14 +1878,11 @@
   socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
 
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientRequestHeadersPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-          GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
+      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
+                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
+                       true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -2097,14 +2004,11 @@
   socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
 
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientRequestHeadersPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-          GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
+      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
+                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
+                       true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -2162,14 +2066,11 @@
   socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
 
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientRequestHeadersPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-          GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
+      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
+                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
+                       true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -2198,14 +2099,11 @@
     return;
   }
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientRequestHeadersPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-          GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
+      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
+                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
+                       true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -2435,14 +2333,12 @@
   // Quic connection will be retried on the alternate network after the initial
   // one fails on the default network.
   MockQuicData quic_data2(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
   quic_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // Handing read.
   quic_data2.AddWrite(SYNCHRONOUS,
                       client_maker_.MakeDummyCHLOPacket(1));  // CHLO
 
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
-  quic_data2.AddWrite(SYNCHRONOUS,
-                      ConstructInitialSettingsPacket(2, &header_stream_offset));
+  quic_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(2));
   quic_data2.AddSocketDataToFactory(&socket_factory_);
 
   // Resolve the host resolution synchronously.
@@ -2553,7 +2449,6 @@
 
   // Quic connection will then be retried on the alternate network.
   MockQuicData quic_data2(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
   quic_data2.AddWrite(SYNCHRONOUS,
                       client_maker_.MakeDummyCHLOPacket(1));  // CHLO
 
@@ -2561,13 +2456,11 @@
   std::string header = ConstructDataHeader(body.length());
 
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
-  quic_data2.AddWrite(SYNCHRONOUS,
-                      ConstructInitialSettingsPacket(2, &header_stream_offset));
+  quic_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(2));
   quic_data2.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientRequestHeadersPacket(
-          3, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-          GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
+      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
+                       3, GetNthClientInitiatedBidirectionalStreamId(0), true,
+                       true, GetRequestHeaders("GET", "https", "/")));
   quic_data2.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -2644,69 +2537,55 @@
 
   // The request will initially go out over QUIC.
   MockQuicData quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
   spdy::SpdyPriority priority =
       ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY);
 
   std::string request_data;
+  quic::QuicStreamOffset request_header_stream_offset =
+      client_maker_.header_stream_offset();
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
   quic_data.AddWrite(SYNCHRONOUS,
                      client_maker_.MakeRequestHeadersPacketAndSaveData(
                          1, GetNthClientInitiatedBidirectionalStreamId(0), true,
                          true, priority, GetRequestHeaders("GET", "https", "/"),
-                         0, nullptr, &header_stream_offset, &request_data));
+                         0, nullptr, &request_data));
 
   std::string settings_data;
-  quic::QuicStreamOffset settings_offset = header_stream_offset;
+  quic::QuicStreamOffset settings_header_stream_offset =
+      client_maker_.header_stream_offset();
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
-  quic_data.AddWrite(SYNCHRONOUS,
-                     client_maker_.MakeInitialSettingsPacketAndSaveData(
-                         2, &header_stream_offset, &settings_data));
+  quic_data.AddWrite(
+      SYNCHRONOUS,
+      client_maker_.MakeInitialSettingsPacketAndSaveData(2, &settings_data));
   // TLP 1
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          3, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, 0, request_data));
+  client_maker_.set_header_stream_offset(request_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      3, true, false, request_data));
   // TLP 2
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          4, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, settings_offset, settings_data));
+  client_maker_.set_header_stream_offset(settings_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      4, true, false, settings_data));
   // RTO 1
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          5, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, 0, request_data));
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          6, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, settings_offset, settings_data));
+  client_maker_.set_header_stream_offset(request_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      5, true, false, request_data));
+  client_maker_.set_header_stream_offset(settings_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      6, true, false, settings_data));
   // RTO 2
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          7, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, 0, request_data));
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          8, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, settings_offset, settings_data));
+  client_maker_.set_header_stream_offset(request_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      7, true, false, request_data));
+  client_maker_.set_header_stream_offset(settings_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      8, true, false, settings_data));
   // RTO 3
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          9, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, 0, request_data));
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          10, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, settings_offset, settings_data));
+  client_maker_.set_header_stream_offset(request_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      9, true, false, request_data));
+  client_maker_.set_header_stream_offset(settings_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      10, true, false, settings_data));
 
   quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeConnectionClosePacket(
                                       11, true, quic::QUIC_NETWORK_IDLE_TIMEOUT,
@@ -2761,80 +2640,62 @@
 
   // The request will initially go out over QUIC.
   MockQuicData quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
   spdy::SpdyPriority priority =
       ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY);
 
   std::string request_data;
+  quic::QuicStreamOffset request_header_stream_offset =
+      client_maker_.header_stream_offset();
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
   quic_data.AddWrite(SYNCHRONOUS,
                      client_maker_.MakeRequestHeadersPacketAndSaveData(
                          1, GetNthClientInitiatedBidirectionalStreamId(0), true,
                          true, priority, GetRequestHeaders("GET", "https", "/"),
-                         0, nullptr, &header_stream_offset, &request_data));
+                         0, nullptr, &request_data));
 
   std::string settings_data;
-  quic::QuicStreamOffset settings_offset = header_stream_offset;
+  quic::QuicStreamOffset settings_header_stream_offset =
+      client_maker_.header_stream_offset();
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
-  quic_data.AddWrite(SYNCHRONOUS,
-                     client_maker_.MakeInitialSettingsPacketAndSaveData(
-                         2, &header_stream_offset, &settings_data));
+  quic_data.AddWrite(
+      SYNCHRONOUS,
+      client_maker_.MakeInitialSettingsPacketAndSaveData(2, &settings_data));
   // TLP 1
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          3, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, 0, request_data));
+  client_maker_.set_header_stream_offset(request_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      3, true, false, request_data));
   // TLP 2
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          4, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, settings_offset, settings_data));
+  client_maker_.set_header_stream_offset(settings_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      4, true, false, settings_data));
   // RTO 1
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          5, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, 0, request_data));
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          6, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, settings_offset, settings_data));
+  client_maker_.set_header_stream_offset(request_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      5, true, false, request_data));
+  client_maker_.set_header_stream_offset(settings_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      6, true, false, settings_data));
   // RTO 2
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          7, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, 0, request_data));
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          8, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, settings_offset, settings_data));
+  client_maker_.set_header_stream_offset(request_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      7, true, false, request_data));
+  client_maker_.set_header_stream_offset(settings_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      8, true, false, settings_data));
   // RTO 3
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          9, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, 0, request_data));
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          10, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, settings_offset, settings_data));
+  client_maker_.set_header_stream_offset(request_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      9, true, false, request_data));
+  client_maker_.set_header_stream_offset(settings_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      10, true, false, settings_data));
   // RTO 4
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          11, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, 0, request_data));
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          12, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, settings_offset, settings_data));
+  client_maker_.set_header_stream_offset(request_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      11, true, false, request_data));
+  client_maker_.set_header_stream_offset(settings_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      12, true, false, settings_data));
   // RTO 5
   quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeConnectionClosePacket(
                                       13, true, quic::QUIC_TOO_MANY_RTOS,
@@ -2888,82 +2749,70 @@
 
   // The request will initially go out over QUIC.
   MockQuicData quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
   spdy::SpdyPriority priority =
       ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY);
 
   std::string request_data;
+  quic::QuicStreamOffset request_header_stream_offset =
+      client_maker_.header_stream_offset();
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
   quic_data.AddWrite(SYNCHRONOUS,
                      client_maker_.MakeRequestHeadersPacketAndSaveData(
                          1, GetNthClientInitiatedBidirectionalStreamId(0), true,
                          true, priority, GetRequestHeaders("GET", "https", "/"),
-                         0, nullptr, &header_stream_offset, &request_data));
+                         0, nullptr, &request_data));
 
   std::string settings_data;
-  quic::QuicStreamOffset settings_offset = header_stream_offset;
+  quic::QuicStreamOffset settings_header_stream_offset =
+      client_maker_.header_stream_offset();
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
-  quic_data.AddWrite(SYNCHRONOUS,
-                     client_maker_.MakeInitialSettingsPacketAndSaveData(
-                         2, &header_stream_offset, &settings_data));
+  quic_data.AddWrite(
+      SYNCHRONOUS,
+      client_maker_.MakeInitialSettingsPacketAndSaveData(2, &settings_data));
 
   quic_data.AddWrite(SYNCHRONOUS,
                      client_maker_.MakeRstPacket(
                          3, true, GetNthClientInitiatedBidirectionalStreamId(0),
                          quic::QUIC_STREAM_CANCELLED));
   // TLP 1
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          4, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, 0, request_data));
+  client_maker_.set_header_stream_offset(request_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      4, true, false, request_data));
   // TLP 2
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          5, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, settings_offset, settings_data));
+  client_maker_.set_header_stream_offset(settings_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      5, true, false, settings_data));
   // RTO 1
   quic_data.AddWrite(SYNCHRONOUS,
                      client_maker_.MakeRstPacket(
                          6, true, GetNthClientInitiatedBidirectionalStreamId(0),
                          quic::QUIC_STREAM_CANCELLED));
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          7, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, 0, request_data));
+  client_maker_.set_header_stream_offset(request_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      7, true, false, request_data));
   // RTO 2
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          8, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, settings_offset, settings_data));
+  client_maker_.set_header_stream_offset(settings_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      8, true, false, settings_data));
   quic_data.AddWrite(SYNCHRONOUS,
                      client_maker_.MakeRstPacket(
                          9, true, GetNthClientInitiatedBidirectionalStreamId(0),
                          quic::QUIC_STREAM_CANCELLED));
   // RTO 3
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          10, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, 0, request_data));
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          11, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, settings_offset, settings_data));
+  client_maker_.set_header_stream_offset(request_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      10, true, false, request_data));
+  client_maker_.set_header_stream_offset(settings_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      11, true, false, settings_data));
   // RTO 4
   quic_data.AddWrite(
       SYNCHRONOUS, client_maker_.MakeRstPacket(
                        12, true, GetNthClientInitiatedBidirectionalStreamId(0),
                        quic::QUIC_STREAM_CANCELLED));
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          13, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, 0, request_data));
+  client_maker_.set_header_stream_offset(request_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      13, true, false, request_data));
   // RTO 5
   quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeConnectionClosePacket(
                                       14, true, quic::QUIC_TOO_MANY_RTOS,
@@ -3019,16 +2868,13 @@
   session_params_.retry_without_alt_svc_on_quic_errors = false;
   // The request will initially go out over QUIC.
   MockQuicData quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientRequestHeadersPacket(
-          1, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-          GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
-  client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
   quic_data.AddWrite(SYNCHRONOUS,
-                     ConstructInitialSettingsPacket(2, &header_stream_offset));
+                     ConstructClientRequestHeadersPacket(
+                         1, GetNthClientInitiatedBidirectionalStreamId(0), true,
+                         true, GetRequestHeaders("GET", "https", "/")));
+  client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
+  quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(2));
   // Peer sending data from an non-existing stream causes this end to raise
   // error and close connection.
   quic_data.AddRead(
@@ -3087,69 +2933,55 @@
 
   // The request will initially go out over QUIC.
   MockQuicData quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
   spdy::SpdyPriority priority =
       ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY);
 
   std::string request_data;
+  quic::QuicStreamOffset request_header_stream_offset =
+      client_maker_.header_stream_offset();
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
   quic_data.AddWrite(SYNCHRONOUS,
                      client_maker_.MakeRequestHeadersPacketAndSaveData(
                          1, GetNthClientInitiatedBidirectionalStreamId(0), true,
                          true, priority, GetRequestHeaders("GET", "https", "/"),
-                         0, nullptr, &header_stream_offset, &request_data));
+                         0, nullptr, &request_data));
 
   std::string settings_data;
-  quic::QuicStreamOffset settings_offset = header_stream_offset;
+  quic::QuicStreamOffset settings_header_stream_offset =
+      client_maker_.header_stream_offset();
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
-  quic_data.AddWrite(SYNCHRONOUS,
-                     client_maker_.MakeInitialSettingsPacketAndSaveData(
-                         2, &header_stream_offset, &settings_data));
+  quic_data.AddWrite(
+      SYNCHRONOUS,
+      client_maker_.MakeInitialSettingsPacketAndSaveData(2, &settings_data));
   // TLP 1
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          3, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, 0, request_data));
+  client_maker_.set_header_stream_offset(request_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      3, true, false, request_data));
   // TLP 2
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          4, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, settings_offset, settings_data));
+  client_maker_.set_header_stream_offset(settings_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      4, true, false, settings_data));
   // RTO 1
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          5, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, 0, request_data));
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          6, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, settings_offset, settings_data));
+  client_maker_.set_header_stream_offset(request_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      5, true, false, request_data));
+  client_maker_.set_header_stream_offset(settings_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      6, true, false, settings_data));
   // RTO 2
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          7, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, 0, request_data));
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          8, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, settings_offset, settings_data));
+  client_maker_.set_header_stream_offset(request_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      7, true, false, request_data));
+  client_maker_.set_header_stream_offset(settings_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      8, true, false, settings_data));
   // RTO 3
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          9, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, 0, request_data));
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          10, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, settings_offset, settings_data));
+  client_maker_.set_header_stream_offset(request_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      9, true, false, request_data));
+  client_maker_.set_header_stream_offset(settings_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      10, true, false, settings_data));
 
   quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeConnectionClosePacket(
                                       11, true, quic::QUIC_NETWORK_IDLE_TIMEOUT,
@@ -3228,69 +3060,55 @@
 
   // The request will initially go out over QUIC.
   MockQuicData quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
   spdy::SpdyPriority priority =
       ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY);
 
   std::string request_data;
+  quic::QuicStreamOffset request_header_stream_offset =
+      client_maker_.header_stream_offset();
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
   quic_data.AddWrite(SYNCHRONOUS,
                      client_maker_.MakeRequestHeadersPacketAndSaveData(
                          1, GetNthClientInitiatedBidirectionalStreamId(0), true,
                          true, priority, GetRequestHeaders("GET", "https", "/"),
-                         0, nullptr, &header_stream_offset, &request_data));
+                         0, nullptr, &request_data));
 
   std::string settings_data;
-  quic::QuicStreamOffset settings_offset = header_stream_offset;
+  quic::QuicStreamOffset settings_header_stream_offset =
+      client_maker_.header_stream_offset();
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
-  quic_data.AddWrite(SYNCHRONOUS,
-                     client_maker_.MakeInitialSettingsPacketAndSaveData(
-                         2, &header_stream_offset, &settings_data));
+  quic_data.AddWrite(
+      SYNCHRONOUS,
+      client_maker_.MakeInitialSettingsPacketAndSaveData(2, &settings_data));
   // TLP 1
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          3, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, 0, request_data));
+  client_maker_.set_header_stream_offset(request_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      3, true, false, request_data));
   // TLP 2
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          4, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, settings_offset, settings_data));
+  client_maker_.set_header_stream_offset(settings_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      4, true, false, settings_data));
   // RTO 1
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          5, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, 0, request_data));
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          6, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, settings_offset, settings_data));
+  client_maker_.set_header_stream_offset(request_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      5, true, false, request_data));
+  client_maker_.set_header_stream_offset(settings_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      6, true, false, settings_data));
   // RTO 2
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          7, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, 0, request_data));
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          8, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, settings_offset, settings_data));
+  client_maker_.set_header_stream_offset(request_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      7, true, false, request_data));
+  client_maker_.set_header_stream_offset(settings_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      8, true, false, settings_data));
   // RTO 3
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          9, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, 0, request_data));
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          10, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, settings_offset, settings_data));
+  client_maker_.set_header_stream_offset(request_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      9, true, false, request_data));
+  client_maker_.set_header_stream_offset(settings_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      10, true, false, settings_data));
 
   quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeConnectionClosePacket(
                                       11, true, quic::QUIC_NETWORK_IDLE_TIMEOUT,
@@ -3373,24 +3191,26 @@
 
   // The request will initially go out over QUIC.
   MockQuicData quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
   spdy::SpdyPriority priority =
       ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY);
 
   std::string request_data;
+  quic::QuicStreamOffset request_header_stream_offset =
+      client_maker_.header_stream_offset();
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
   quic_data.AddWrite(SYNCHRONOUS,
                      client_maker_.MakeRequestHeadersPacketAndSaveData(
                          1, GetNthClientInitiatedBidirectionalStreamId(0), true,
                          true, priority, GetRequestHeaders("GET", "https", "/"),
-                         0, nullptr, &header_stream_offset, &request_data));
+                         0, nullptr, &request_data));
 
   std::string settings_data;
-  quic::QuicStreamOffset settings_offset = header_stream_offset;
+  quic::QuicStreamOffset setting_header_stream_offset =
+      client_maker_.header_stream_offset();
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
-  quic_data.AddWrite(SYNCHRONOUS,
-                     client_maker_.MakeInitialSettingsPacketAndSaveData(
-                         2, &header_stream_offset, &settings_data));
+  quic_data.AddWrite(
+      SYNCHRONOUS,
+      client_maker_.MakeInitialSettingsPacketAndSaveData(2, &settings_data));
 
   quic_data.AddRead(ASYNC, ConstructServerResponseHeadersPacket(
                                1, GetNthClientInitiatedBidirectionalStreamId(0),
@@ -3402,50 +3222,34 @@
                                quic::QuicTime::Delta::FromMilliseconds(25)));
 
   // TLP 1
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          4, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          false, false, 0, request_data));
+  client_maker_.set_header_stream_offset(request_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      4, false, false, request_data));
   // TLP 2
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          5, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          false, false, settings_offset, settings_data));
+  client_maker_.set_header_stream_offset(setting_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      5, false, false, settings_data));
   // RTO 1
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          6, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          false, false, 0, request_data));
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          7, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          false, false, settings_offset, settings_data));
+  client_maker_.set_header_stream_offset(request_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      6, false, false, request_data));
+  client_maker_.set_header_stream_offset(setting_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      7, false, false, settings_data));
   // RTO 2
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          8, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          false, false, 0, request_data));
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          9, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          false, false, settings_offset, settings_data));
+  client_maker_.set_header_stream_offset(request_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      8, false, false, request_data));
+  client_maker_.set_header_stream_offset(setting_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      9, false, false, settings_data));
   // RTO 3
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          10, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          false, false, 0, request_data));
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          11, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          false, false, settings_offset, settings_data));
+  client_maker_.set_header_stream_offset(request_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      10, false, false, request_data));
+  client_maker_.set_header_stream_offset(setting_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      11, false, false, settings_data));
 
   if (GetQuicReloadableFlag(
           quic_fix_time_of_first_packet_sent_after_receiving)) {
@@ -3525,80 +3329,62 @@
 
   // The request will initially go out over QUIC.
   MockQuicData quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
   spdy::SpdyPriority priority =
       ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY);
 
   std::string request_data;
+  quic::QuicStreamOffset request_header_stream_offset =
+      client_maker_.header_stream_offset();
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
   quic_data.AddWrite(SYNCHRONOUS,
                      client_maker_.MakeRequestHeadersPacketAndSaveData(
                          1, GetNthClientInitiatedBidirectionalStreamId(0), true,
                          true, priority, GetRequestHeaders("GET", "https", "/"),
-                         0, nullptr, &header_stream_offset, &request_data));
+                         0, nullptr, &request_data));
 
   std::string settings_data;
-  quic::QuicStreamOffset settings_offset = header_stream_offset;
+  quic::QuicStreamOffset settings_header_stream_offset =
+      client_maker_.header_stream_offset();
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
-  quic_data.AddWrite(SYNCHRONOUS,
-                     client_maker_.MakeInitialSettingsPacketAndSaveData(
-                         2, &header_stream_offset, &settings_data));
+  quic_data.AddWrite(
+      SYNCHRONOUS,
+      client_maker_.MakeInitialSettingsPacketAndSaveData(2, &settings_data));
   // TLP 1
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          3, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, 0, request_data));
+  client_maker_.set_header_stream_offset(request_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      3, true, false, request_data));
   // TLP 2
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          4, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, settings_offset, settings_data));
+  client_maker_.set_header_stream_offset(settings_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      4, true, false, settings_data));
   // RTO 1
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          5, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, 0, request_data));
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          6, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, settings_offset, settings_data));
+  client_maker_.set_header_stream_offset(request_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      5, true, false, request_data));
+  client_maker_.set_header_stream_offset(settings_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      6, true, false, settings_data));
   // RTO 2
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          7, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, 0, request_data));
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          8, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, settings_offset, settings_data));
+  client_maker_.set_header_stream_offset(request_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      7, true, false, request_data));
+  client_maker_.set_header_stream_offset(settings_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      8, true, false, settings_data));
   // RTO 3
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          9, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, 0, request_data));
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          10, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, settings_offset, settings_data));
+  client_maker_.set_header_stream_offset(request_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      9, true, false, request_data));
+  client_maker_.set_header_stream_offset(settings_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      10, true, false, settings_data));
   // RTO 4
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          11, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, 0, request_data));
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          12, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, settings_offset, settings_data));
+  client_maker_.set_header_stream_offset(request_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      11, true, false, request_data));
+  client_maker_.set_header_stream_offset(settings_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      12, true, false, settings_data));
 
   quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeConnectionClosePacket(
                                       13, true, quic::QUIC_TOO_MANY_RTOS,
@@ -3677,82 +3463,70 @@
 
   // The request will initially go out over QUIC.
   MockQuicData quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
   spdy::SpdyPriority priority =
       ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY);
 
   std::string request_data;
+  quic::QuicStreamOffset request_header_stream_offset =
+      client_maker_.header_stream_offset();
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
   quic_data.AddWrite(SYNCHRONOUS,
                      client_maker_.MakeRequestHeadersPacketAndSaveData(
                          1, GetNthClientInitiatedBidirectionalStreamId(0), true,
                          true, priority, GetRequestHeaders("GET", "https", "/"),
-                         0, nullptr, &header_stream_offset, &request_data));
+                         0, nullptr, &request_data));
 
   std::string settings_data;
-  quic::QuicStreamOffset settings_offset = header_stream_offset;
+  quic::QuicStreamOffset settings_header_stream_offset =
+      client_maker_.header_stream_offset();
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
-  quic_data.AddWrite(SYNCHRONOUS,
-                     client_maker_.MakeInitialSettingsPacketAndSaveData(
-                         2, &header_stream_offset, &settings_data));
+  quic_data.AddWrite(
+      SYNCHRONOUS,
+      client_maker_.MakeInitialSettingsPacketAndSaveData(2, &settings_data));
 
   quic_data.AddWrite(SYNCHRONOUS,
                      client_maker_.MakeRstPacket(
                          3, true, GetNthClientInitiatedBidirectionalStreamId(0),
                          quic::QUIC_STREAM_CANCELLED));
   // TLP 1
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          4, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, 0, request_data));
+  client_maker_.set_header_stream_offset(request_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      4, true, false, request_data));
   // TLP 2
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          5, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, settings_offset, settings_data));
+  client_maker_.set_header_stream_offset(settings_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      5, true, false, settings_data));
   // RTO 1
   quic_data.AddWrite(SYNCHRONOUS,
                      client_maker_.MakeRstPacket(
                          6, true, GetNthClientInitiatedBidirectionalStreamId(0),
                          quic::QUIC_STREAM_CANCELLED));
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          7, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, 0, request_data));
+  client_maker_.set_header_stream_offset(request_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      7, true, false, request_data));
   // RTO 2
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          8, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, settings_offset, settings_data));
+  client_maker_.set_header_stream_offset(settings_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      8, true, false, settings_data));
   quic_data.AddWrite(SYNCHRONOUS,
                      client_maker_.MakeRstPacket(
                          9, true, GetNthClientInitiatedBidirectionalStreamId(0),
                          quic::QUIC_STREAM_CANCELLED));
   // RTO 3
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          10, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, 0, request_data));
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          11, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, settings_offset, settings_data));
+  client_maker_.set_header_stream_offset(request_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      10, true, false, request_data));
+  client_maker_.set_header_stream_offset(settings_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      11, true, false, settings_data));
   // RTO 4
   quic_data.AddWrite(
       SYNCHRONOUS, client_maker_.MakeRstPacket(
                        12, true, GetNthClientInitiatedBidirectionalStreamId(0),
                        quic::QUIC_STREAM_CANCELLED));
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          13, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          true, false, 0, request_data));
+  client_maker_.set_header_stream_offset(request_header_stream_offset);
+  quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeHeadersDataPacket(
+                                      13, true, false, request_data));
   // RTO 5
   quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeConnectionClosePacket(
                                       14, true, quic::QUIC_TOO_MANY_RTOS,
@@ -3811,16 +3585,13 @@
 
   // The request will initially go out over QUIC.
   MockQuicData quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
-  quic_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientRequestHeadersPacket(
-          1, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-          GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
-  client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
   quic_data.AddWrite(SYNCHRONOUS,
-                     ConstructInitialSettingsPacket(2, &header_stream_offset));
+                     ConstructClientRequestHeadersPacket(
+                         1, GetNthClientInitiatedBidirectionalStreamId(0), true,
+                         true, GetRequestHeaders("GET", "https", "/")));
+  client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
+  quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(2));
   // Peer sending data from an non-existing stream causes this end to raise
   // error and close connection.
   quic_data.AddRead(
@@ -3898,7 +3669,6 @@
 TEST_P(QuicNetworkTransactionTest, ResetAfterHandshakeConfirmedThenBroken) {
   // The request will initially go out over QUIC.
   MockQuicData quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
   spdy::SpdyPriority priority =
       ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY);
 
@@ -3908,14 +3678,13 @@
                      client_maker_.MakeRequestHeadersPacketAndSaveData(
                          1, GetNthClientInitiatedBidirectionalStreamId(0), true,
                          true, priority, GetRequestHeaders("GET", "https", "/"),
-                         0, nullptr, &header_stream_offset, &request_data));
+                         0, nullptr, &request_data));
 
   std::string settings_data;
-  // quic::QuicStreamOffset settings_offset = header_stream_offset;
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
-  quic_data.AddWrite(SYNCHRONOUS,
-                     client_maker_.MakeInitialSettingsPacketAndSaveData(
-                         2, &header_stream_offset, &settings_data));
+  quic_data.AddWrite(
+      SYNCHRONOUS,
+      client_maker_.MakeInitialSettingsPacketAndSaveData(2, &settings_data));
 
   quic_data.AddRead(ASYNC,
                     ConstructServerRstPacket(
@@ -4004,19 +3773,15 @@
   crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
 
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset request_header_offset(0);
-  quic::QuicStreamOffset response_header_offset(0);
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &request_header_offset));
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientRequestHeadersPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-          GetRequestHeaders("GET", "https", "/"), &request_header_offset));
+      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
+                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
+                       true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
-                 GetResponseHeaders("200 OK"), &response_header_offset));
+                 GetResponseHeaders("200 OK")));
   std::string header = ConstructDataHeader(6);
   mock_quic_data.AddRead(
       ASYNC, ConstructServerDataPacket(
@@ -4068,8 +3833,6 @@
   ASSERT_NE(origin1.host(), origin2.host());
 
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset request_header_offset(0);
-  quic::QuicStreamOffset response_header_offset(0);
 
   scoped_refptr<X509Certificate> cert(
       ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem"));
@@ -4081,18 +3844,16 @@
   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, &request_header_offset));
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   // First request.
   mock_quic_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientRequestHeadersPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-          GetRequestHeaders("GET", "https", "/"), &request_header_offset));
+      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
+                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
+                       true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
-                 GetResponseHeaders("200 OK"), &response_header_offset));
+                 GetResponseHeaders("200 OK")));
   std::string header = ConstructDataHeader(6);
   mock_quic_data.AddRead(
       ASYNC, ConstructServerDataPacket(
@@ -4114,8 +3875,7 @@
       ConstructClientRequestHeadersPacket(
           4, GetNthClientInitiatedBidirectionalStreamId(1), false, true,
           GetRequestHeaders("GET", "https", "/", &client_maker2),
-          GetNthClientInitiatedBidirectionalStreamId(0),
-          &request_header_offset));
+          GetNthClientInitiatedBidirectionalStreamId(0)));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerRstPacket(
                  3, false, GetNthClientInitiatedBidirectionalStreamId(1),
@@ -4222,28 +3982,23 @@
   AddCertificate(&ssl_data_);
   socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
 
-  quic::QuicStreamOffset request_header_offset = 0;
-  quic::QuicStreamOffset response_header_offset = 0;
   // First QUIC request data.
   // 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));
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &request_header_offset));
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientRequestHeadersPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-          GetRequestHeaders("GET", "https", "/"), &request_header_offset));
+      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
+                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
+                       true, GetRequestHeaders("GET", "https", "/")));
 
   std::string alt_svc_list =
       "quic=\"mail.example.org:444\", quic=\"foo.example.org:443\", "
       "quic=\"bar.example.org:445\"";
   mock_quic_data.AddRead(
-      ASYNC,
-      ConstructServerResponseHeadersPacket(
-          1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
-          GetResponseHeaders("200 OK", alt_svc_list), &response_header_offset));
+      ASYNC, ConstructServerResponseHeadersPacket(
+                 1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
+                 GetResponseHeaders("200 OK", alt_svc_list)));
   std::string header = ConstructDataHeader(6);
   mock_quic_data.AddRead(
       ASYNC, ConstructServerDataPacket(
@@ -4258,12 +4013,11 @@
       SYNCHRONOUS, ConstructClientRequestHeadersPacket(
                        4, GetNthClientInitiatedBidirectionalStreamId(1), false,
                        true, GetRequestHeaders("GET", "https", "/"),
-                       GetNthClientInitiatedBidirectionalStreamId(0),
-                       &request_header_offset));
+                       GetNthClientInitiatedBidirectionalStreamId(0)));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  3, GetNthClientInitiatedBidirectionalStreamId(1), false, false,
-                 GetResponseHeaders("200 OK"), &response_header_offset));
+                 GetResponseHeaders("200 OK")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerDataPacket(
                  4, GetNthClientInitiatedBidirectionalStreamId(1), false, true,
@@ -4293,26 +4047,21 @@
 TEST_P(QuicNetworkTransactionTest, UseExistingQUICAlternativeProxy) {
   base::HistogramTester histogram_tester;
 
-  quic::QuicStreamOffset request_header_offset = 0;
-  quic::QuicStreamOffset response_header_offset = 0;
   // First QUIC request data.
   // 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));
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &request_header_offset));
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientRequestHeadersPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-          GetRequestHeaders("GET", "http", "/"), &request_header_offset));
+      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
+                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
+                       true, GetRequestHeaders("GET", "http", "/")));
 
   std::string alt_svc_list;
   mock_quic_data.AddRead(
-      ASYNC,
-      ConstructServerResponseHeadersPacket(
-          1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
-          GetResponseHeaders("200 OK", alt_svc_list), &response_header_offset));
+      ASYNC, ConstructServerResponseHeadersPacket(
+                 1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
+                 GetResponseHeaders("200 OK", alt_svc_list)));
   std::string header = ConstructDataHeader(6);
   mock_quic_data.AddRead(
       ASYNC, ConstructServerDataPacket(
@@ -4327,12 +4076,11 @@
       SYNCHRONOUS, ConstructClientRequestHeadersPacket(
                        4, GetNthClientInitiatedBidirectionalStreamId(1), false,
                        true, GetRequestHeaders("GET", "http", "/"),
-                       GetNthClientInitiatedBidirectionalStreamId(0),
-                       &request_header_offset));
+                       GetNthClientInitiatedBidirectionalStreamId(0)));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  3, GetNthClientInitiatedBidirectionalStreamId(1), false, false,
-                 GetResponseHeaders("200 OK"), &response_header_offset));
+                 GetResponseHeaders("200 OK")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerDataPacket(
                  4, GetNthClientInitiatedBidirectionalStreamId(1), false, true,
@@ -4380,21 +4128,17 @@
 TEST_P(QuicNetworkTransactionTest, PoolByOrigin) {
   session_params_.quic_allow_remote_alt_svc = true;
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset request_header_offset(0);
-  quic::QuicStreamOffset response_header_offset(0);
 
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &request_header_offset));
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   // First request.
   mock_quic_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientRequestHeadersPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-          GetRequestHeaders("GET", "https", "/"), &request_header_offset));
+      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
+                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
+                       true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
-                 GetResponseHeaders("200 OK"), &response_header_offset));
+                 GetResponseHeaders("200 OK")));
   std::string header = ConstructDataHeader(6);
   mock_quic_data.AddRead(
       ASYNC, ConstructServerDataPacket(
@@ -4407,12 +4151,11 @@
       SYNCHRONOUS, ConstructClientRequestHeadersPacket(
                        4, GetNthClientInitiatedBidirectionalStreamId(1), false,
                        true, GetRequestHeaders("GET", "https", "/"),
-                       GetNthClientInitiatedBidirectionalStreamId(0),
-                       &request_header_offset));
+                       GetNthClientInitiatedBidirectionalStreamId(0)));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  3, GetNthClientInitiatedBidirectionalStreamId(1), false, false,
-                 GetResponseHeaders("200 OK"), &response_header_offset));
+                 GetResponseHeaders("200 OK")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerDataPacket(
                  4, GetNthClientInitiatedBidirectionalStreamId(1), false, true,
@@ -4465,21 +4208,17 @@
   ASSERT_NE(origin1.host(), origin2.host());
 
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset request_header_offset(0);
-  quic::QuicStreamOffset response_header_offset(0);
 
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &request_header_offset));
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   // First request.
   mock_quic_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientRequestHeadersPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-          GetRequestHeaders("GET", "https", "/"), &request_header_offset));
+      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
+                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
+                       true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
-                 GetResponseHeaders("200 OK"), &response_header_offset));
+                 GetResponseHeaders("200 OK")));
   std::string header = ConstructDataHeader(6);
   mock_quic_data.AddRead(
       ASYNC, ConstructServerDataPacket(
@@ -4500,12 +4239,11 @@
       ConstructClientRequestHeadersPacket(
           4, GetNthClientInitiatedBidirectionalStreamId(1), false, true,
           GetRequestHeaders("GET", "https", "/", &client_maker2),
-          GetNthClientInitiatedBidirectionalStreamId(0),
-          &request_header_offset));
+          GetNthClientInitiatedBidirectionalStreamId(0)));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  3, GetNthClientInitiatedBidirectionalStreamId(1), false, false,
-                 GetResponseHeaders("200 OK"), &response_header_offset));
+                 GetResponseHeaders("200 OK")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerDataPacket(
                  4, GetNthClientInitiatedBidirectionalStreamId(1), false, true,
@@ -4597,9 +4335,6 @@
   socket_factory_.AddSocketDataProvider(&http_data2);
   socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
 
-  quic::QuicStreamOffset request_header_offset = 0;
-  quic::QuicStreamOffset response_header_offset = 0;
-
   QuicTestPacketMaker client_maker(
       version_, quic::QuicUtils::CreateRandomConnectionId(&random_generator_),
       &clock_, "mail.example.org", quic::Perspective::IS_CLIENT,
@@ -4607,19 +4342,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, &request_header_offset));
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   // First QUIC request data.
   mock_quic_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientRequestHeadersPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-          GetRequestHeaders("GET", "https", "/"), &request_header_offset));
+      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
+                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
+                       true, GetRequestHeaders("GET", "https", "/")));
 
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
-                 GetResponseHeaders("200 OK"), &response_header_offset));
+                 GetResponseHeaders("200 OK")));
   std::string header = ConstructDataHeader(21);
   mock_quic_data.AddRead(
       ASYNC, ConstructServerDataPacket(
@@ -4632,12 +4365,11 @@
       ConstructClientRequestHeadersPacket(
           4, GetNthClientInitiatedBidirectionalStreamId(1), false, true,
           GetRequestHeaders("GET", "https", "/", &client_maker),
-          GetNthClientInitiatedBidirectionalStreamId(0),
-          &request_header_offset));
+          GetNthClientInitiatedBidirectionalStreamId(0)));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  3, GetNthClientInitiatedBidirectionalStreamId(1), false, false,
-                 GetResponseHeaders("200 OK"), &response_header_offset));
+                 GetResponseHeaders("200 OK")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerDataPacket(
                  4, GetNthClientInitiatedBidirectionalStreamId(1), false, true,
@@ -4714,14 +4446,11 @@
   socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
 
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientRequestHeadersPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-          GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
+      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
+                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
+                       true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -4771,14 +4500,11 @@
   socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
 
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientRequestHeadersPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-          GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
+      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
+                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
+                       true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -4808,14 +4534,11 @@
       "HTTPS mail.example.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientRequestHeadersPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-          GetRequestHeaders("GET", "http", "/"), &header_stream_offset));
+      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
+                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
+                       true, GetRequestHeaders("GET", "http", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -4911,13 +4634,11 @@
 
 TEST_P(QuicNetworkTransactionTest, ZeroRTTWithHttpRace) {
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
   mock_quic_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientRequestHeadersPacket(
-          1, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-          GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
+      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
+                       1, GetNthClientInitiatedBidirectionalStreamId(0), true,
+                       true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -5013,14 +4734,11 @@
 
 TEST_P(QuicNetworkTransactionTest, ZeroRTTWithConfirmationRequired) {
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientRequestHeadersPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-          GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
+      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
+                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
+                       true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -5066,19 +4784,15 @@
 
 TEST_P(QuicNetworkTransactionTest, ZeroRTTWithTooEarlyResponse) {
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset client_header_stream_offset = 0;
-  quic::QuicStreamOffset server_header_stream_offset = 0;
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
   mock_quic_data.AddWrite(
       SYNCHRONOUS, ConstructClientRequestHeadersPacket(
                        1, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "https", "/"),
-                       &client_header_stream_offset));
+                       true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
-      ASYNC,
-      ConstructServerResponseHeadersPacket(
-          1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
-          GetResponseHeaders("425 TOO_EARLY"), &server_header_stream_offset));
+      ASYNC, ConstructServerResponseHeadersPacket(
+                 1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
+                 GetResponseHeaders("425 TOO_EARLY")));
   mock_quic_data.AddWrite(SYNCHRONOUS,
                           ConstructClientAckAndRstPacket(
                               2, GetNthClientInitiatedBidirectionalStreamId(0),
@@ -5086,29 +4800,18 @@
 
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
 
-  spdy::SpdySettingsIR settings_frame;
-  settings_frame.AddSetting(spdy::SETTINGS_MAX_HEADER_LIST_SIZE,
-                            quic::kDefaultMaxUncompressedHeaderSize);
-  spdy::SpdySerializedFrame spdy_frame(
-      client_maker_.spdy_request_framer()->SerializeFrame(settings_frame));
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          3, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          false, false, client_header_stream_offset,
-          quic::QuicStringPiece(spdy_frame.data(), spdy_frame.size())));
-  client_header_stream_offset += spdy_frame.size();
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          client_maker_.MakeSettingsPacket(3, false));
 
   mock_quic_data.AddWrite(
       SYNCHRONOUS, ConstructClientRequestHeadersPacket(
                        4, GetNthClientInitiatedBidirectionalStreamId(1), false,
                        true, GetRequestHeaders("GET", "https", "/"),
-                       GetNthClientInitiatedBidirectionalStreamId(0),
-                       &client_header_stream_offset));
+                       GetNthClientInitiatedBidirectionalStreamId(0)));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  2, GetNthClientInitiatedBidirectionalStreamId(1), false, false,
-                 GetResponseHeaders("200 OK"), &server_header_stream_offset));
+                 GetResponseHeaders("200 OK")));
   std::string header = ConstructDataHeader(6);
   mock_quic_data.AddRead(
       ASYNC, ConstructServerDataPacket(
@@ -5158,19 +4861,15 @@
 
 TEST_P(QuicNetworkTransactionTest, ZeroRTTWithMultipleTooEarlyResponse) {
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset client_header_stream_offset = 0;
-  quic::QuicStreamOffset server_header_stream_offset = 0;
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
   mock_quic_data.AddWrite(
       SYNCHRONOUS, ConstructClientRequestHeadersPacket(
                        1, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "https", "/"),
-                       &client_header_stream_offset));
+                       true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
-      ASYNC,
-      ConstructServerResponseHeadersPacket(
-          1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
-          GetResponseHeaders("425 TOO_EARLY"), &server_header_stream_offset));
+      ASYNC, ConstructServerResponseHeadersPacket(
+                 1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
+                 GetResponseHeaders("425 TOO_EARLY")));
   mock_quic_data.AddWrite(SYNCHRONOUS,
                           ConstructClientAckAndRstPacket(
                               2, GetNthClientInitiatedBidirectionalStreamId(0),
@@ -5178,30 +4877,18 @@
 
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
 
-  spdy::SpdySettingsIR settings_frame;
-  settings_frame.AddSetting(spdy::SETTINGS_MAX_HEADER_LIST_SIZE,
-                            quic::kDefaultMaxUncompressedHeaderSize);
-  spdy::SpdySerializedFrame spdy_frame(
-      client_maker_.spdy_request_framer()->SerializeFrame(settings_frame));
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS,
-      client_maker_.MakeDataPacket(
-          3, quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
-          false, false, client_header_stream_offset,
-          quic::QuicStringPiece(spdy_frame.data(), spdy_frame.size())));
-  client_header_stream_offset += spdy_frame.size();
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          client_maker_.MakeSettingsPacket(3, false));
 
   mock_quic_data.AddWrite(
       SYNCHRONOUS, ConstructClientRequestHeadersPacket(
                        4, GetNthClientInitiatedBidirectionalStreamId(1), false,
                        true, GetRequestHeaders("GET", "https", "/"),
-                       GetNthClientInitiatedBidirectionalStreamId(0),
-                       &client_header_stream_offset));
+                       GetNthClientInitiatedBidirectionalStreamId(0)));
   mock_quic_data.AddRead(
-      ASYNC,
-      ConstructServerResponseHeadersPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(1), false, false,
-          GetResponseHeaders("425 TOO_EARLY"), &server_header_stream_offset));
+      ASYNC, ConstructServerResponseHeadersPacket(
+                 2, GetNthClientInitiatedBidirectionalStreamId(1), false, false,
+                 GetResponseHeaders("425 TOO_EARLY")));
   mock_quic_data.AddWrite(SYNCHRONOUS,
                           ConstructClientAckAndRstPacket(
                               5, GetNthClientInitiatedBidirectionalStreamId(1),
@@ -5257,14 +4944,11 @@
        LogGranularQuicErrorCodeOnQuicProtocolErrorLocal) {
   session_params_.retry_without_alt_svc_on_quic_errors = false;
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientRequestHeadersPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-          GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
+      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
+                       2, 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));
@@ -5309,14 +4993,11 @@
        LogGranularQuicErrorCodeOnQuicProtocolErrorRemote) {
   session_params_.retry_without_alt_svc_on_quic_errors = false;
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientRequestHeadersPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-          GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
+      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
+                       2, 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(
@@ -5364,14 +5045,11 @@
 
 TEST_P(QuicNetworkTransactionTest, RstSteamErrorHandling) {
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientRequestHeadersPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-          GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
+      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
+                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
+                       true, GetRequestHeaders("GET", "https", "/")));
   // Read the response headers, then a RST_STREAM frame.
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
@@ -5429,14 +5107,11 @@
 TEST_P(QuicNetworkTransactionTest, RstSteamBeforeHeaders) {
   session_params_.retry_without_alt_svc_on_quic_errors = false;
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientRequestHeadersPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-          GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
+      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
+                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
+                       true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerRstPacket(
                  1, false, GetNthClientInitiatedBidirectionalStreamId(0),
@@ -5566,13 +5241,11 @@
   http_server_properties_.SetSupportsQuic(true, IPAddress(192, 0, 2, 33));
 
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT);
   mock_quic_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientRequestHeadersPacket(
-          1, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-          GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
+      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
+                       1, GetNthClientInitiatedBidirectionalStreamId(0), true,
+                       true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -5625,14 +5298,11 @@
   http_server_properties_.SetSupportsQuic(true, IPAddress(1, 2, 3, 4));
 
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientRequestHeadersPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-          GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
+      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
+                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
+                       true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -5911,14 +5581,11 @@
   EXPECT_FALSE(
       test_socket_performance_watcher_factory_.rtt_notification_received());
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientRequestHeadersPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-          GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
+      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
+                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
+                       true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -6032,13 +5699,11 @@
 
   MockQuicData socket_data(version_);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  quic::QuicStreamOffset offset = 0;
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1, &offset));
+  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   socket_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientRequestHeadersPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, false,
-          GetRequestHeaders("POST", "https", "/"), &offset));
+      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
+                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
+                       false, GetRequestHeaders("POST", "https", "/")));
   socket_data.AddWrite(SYNCHRONOUS, ERR_FAILED);
   socket_data.AddSocketDataToFactory(&socket_factory_);
 
@@ -6076,13 +5741,12 @@
       HostPortPair::FromString("mail.example.org:443"));
 
   MockQuicData socket_data(version_);
-  quic::QuicStreamOffset offset = 0;
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1, &offset));
+  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   socket_data.AddWrite(ASYNC, ERR_NO_BUFFER_SPACE);
   socket_data.AddWrite(
       SYNCHRONOUS, ConstructClientRequestHeadersPacket(
                        2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "https", "/"), &offset));
+                       true, GetRequestHeaders("GET", "https", "/")));
   socket_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -6112,13 +5776,12 @@
       HostPortPair::FromString("mail.example.org:443"));
 
   MockQuicData socket_data(version_);
-  quic::QuicStreamOffset offset = 0;
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1, &offset));
+  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   socket_data.AddWrite(SYNCHRONOUS, ERR_NO_BUFFER_SPACE);
   socket_data.AddWrite(
       SYNCHRONOUS, ConstructClientRequestHeadersPacket(
                        2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, GetRequestHeaders("GET", "https", "/"), &offset));
+                       true, GetRequestHeaders("GET", "https", "/")));
   socket_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -6149,9 +5812,8 @@
       HostPortPair::FromString("mail.example.org:443"));
 
   MockQuicData socket_data(version_);
-  quic::QuicStreamOffset offset = 0;
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // No more data to read
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1, &offset));
+  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);
   }
@@ -6186,9 +5848,8 @@
       HostPortPair::FromString("mail.example.org:443"));
 
   MockQuicData socket_data(version_);
-  quic::QuicStreamOffset offset = 0;
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // No more data to read
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1, &offset));
+  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);
   }
@@ -6226,9 +5887,8 @@
                        strerror(ERR_MSG_TOO_BIG), ")");
 
   MockQuicData socket_data(version_);
-  quic::QuicStreamOffset offset = 0;
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1, &offset));
+  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   socket_data.AddWrite(SYNCHRONOUS, ERR_MSG_TOO_BIG);
   // Connection close packet will be sent for MSG_TOO_BIG.
   socket_data.AddWrite(
@@ -6255,43 +5915,39 @@
       HostPortPair::FromString("mail.example.org:443"));
 
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
   uint64_t client_packet_number = 1;
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(client_packet_number++,
-                                                  &header_stream_offset));
+      SYNCHRONOUS, ConstructInitialSettingsPacket(client_packet_number++));
   mock_quic_data.AddWrite(
       SYNCHRONOUS,
       ConstructClientRequestHeadersPacket(
           client_packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
-          true, true, GetRequestHeaders("GET", "https", "/"),
-          &header_stream_offset));
-  quic::QuicStreamOffset server_header_offset = 0;
+          true, true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
-      ASYNC, ConstructServerPushPromisePacket(
-                 1, GetNthClientInitiatedBidirectionalStreamId(0),
-                 GetNthServerInitiatedUnidirectionalStreamId(0), false,
-                 GetRequestHeaders("GET", "https", "/pushed.jpg"),
-                 &server_header_offset, &server_maker_));
+      ASYNC,
+      ConstructServerPushPromisePacket(
+          1, GetNthClientInitiatedBidirectionalStreamId(0),
+          GetNthServerInitiatedUnidirectionalStreamId(0), false,
+          GetRequestHeaders("GET", "https", "/pushed.jpg"), &server_maker_));
   if (client_headers_include_h2_stream_dependency_ &&
       version_.transport_version >= quic::QUIC_VERSION_43) {
-    mock_quic_data.AddWrite(SYNCHRONOUS,
-                            ConstructClientPriorityPacket(
-                                client_packet_number++, false,
-                                GetNthServerInitiatedUnidirectionalStreamId(0),
-                                GetNthClientInitiatedBidirectionalStreamId(0),
-                                DEFAULT_PRIORITY, &header_stream_offset));
+    mock_quic_data.AddWrite(
+        SYNCHRONOUS,
+        ConstructClientPriorityPacket(
+            client_packet_number++, false,
+            GetNthServerInitiatedUnidirectionalStreamId(0),
+            GetNthClientInitiatedBidirectionalStreamId(0), DEFAULT_PRIORITY));
   }
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  2, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
-                 GetResponseHeaders("200 OK"), &server_header_offset));
+                 GetResponseHeaders("200 OK")));
   mock_quic_data.AddWrite(
       SYNCHRONOUS, ConstructClientAckPacket(client_packet_number++, 2, 1, 1));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  3, GetNthServerInitiatedUnidirectionalStreamId(0), false,
-                 false, GetResponseHeaders("200 OK"), &server_header_offset));
+                 false, GetResponseHeaders("200 OK")));
   std::string header = ConstructDataHeader(6);
   mock_quic_data.AddRead(
       ASYNC, ConstructServerDataPacket(
@@ -6346,41 +6002,37 @@
       HostPortPair::FromString("mail.example.org:443"));
 
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
   uint64_t client_packet_number = 1;
   // Initial SETTINGS frame.
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(client_packet_number++,
-                                                  &header_stream_offset));
+      SYNCHRONOUS, ConstructInitialSettingsPacket(client_packet_number++));
   // First request: GET https://mail.example.org/
   mock_quic_data.AddWrite(
       SYNCHRONOUS,
       ConstructClientRequestHeadersPacket(
           client_packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
-          true, true, GetRequestHeaders("GET", "https", "/"),
-          &header_stream_offset));
-  quic::QuicStreamOffset server_header_offset = 0;
+          true, true, GetRequestHeaders("GET", "https", "/")));
   // Server promise for: https://mail.example.org/pushed.jpg
   mock_quic_data.AddRead(
-      ASYNC, ConstructServerPushPromisePacket(
-                 1, GetNthClientInitiatedBidirectionalStreamId(0),
-                 GetNthServerInitiatedUnidirectionalStreamId(0), false,
-                 GetRequestHeaders("GET", "https", "/pushed.jpg"),
-                 &server_header_offset, &server_maker_));
+      ASYNC,
+      ConstructServerPushPromisePacket(
+          1, GetNthClientInitiatedBidirectionalStreamId(0),
+          GetNthServerInitiatedUnidirectionalStreamId(0), false,
+          GetRequestHeaders("GET", "https", "/pushed.jpg"), &server_maker_));
   if (client_headers_include_h2_stream_dependency_ &&
       version_.transport_version >= quic::QUIC_VERSION_43) {
-    mock_quic_data.AddWrite(SYNCHRONOUS,
-                            ConstructClientPriorityPacket(
-                                client_packet_number++, false,
-                                GetNthServerInitiatedUnidirectionalStreamId(0),
-                                GetNthClientInitiatedBidirectionalStreamId(0),
-                                DEFAULT_PRIORITY, &header_stream_offset));
+    mock_quic_data.AddWrite(
+        SYNCHRONOUS,
+        ConstructClientPriorityPacket(
+            client_packet_number++, false,
+            GetNthServerInitiatedUnidirectionalStreamId(0),
+            GetNthClientInitiatedBidirectionalStreamId(0), DEFAULT_PRIORITY));
   }
   // Response headers for first request.
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  2, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
-                 GetResponseHeaders("200 OK"), &server_header_offset));
+                 GetResponseHeaders("200 OK")));
   // Client ACKs the response headers.
   mock_quic_data.AddWrite(
       SYNCHRONOUS, ConstructClientAckPacket(client_packet_number++, 2, 1, 1));
@@ -6438,10 +6090,9 @@
 
   MockQuicData mock_quic_data(version_);
 
-  quic::QuicStreamOffset offset = 0;
   int write_packet_index = 1;
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(
-                                           write_packet_index++, &offset));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructInitialSettingsPacket(write_packet_index++));
 
   std::string header = ConstructDataHeader(1);
   if (version_.transport_version != quic::QUIC_VERSION_99) {
@@ -6450,15 +6101,14 @@
         ConstructClientRequestHeadersAndDataFramesPacket(
             write_packet_index++, GetNthClientInitiatedBidirectionalStreamId(0),
             true, true, DEFAULT_PRIORITY,
-            GetRequestHeaders("POST", "https", "/"), 0, &offset, nullptr,
-            {"1"}));
+            GetRequestHeaders("POST", "https", "/"), 0, nullptr, {"1"}));
   } else {
     mock_quic_data.AddWrite(
         SYNCHRONOUS,
         ConstructClientRequestHeadersAndDataFramesPacket(
             write_packet_index++, GetNthClientInitiatedBidirectionalStreamId(0),
             true, true, DEFAULT_PRIORITY,
-            GetRequestHeaders("POST", "https", "/"), 0, &offset, nullptr,
+            GetRequestHeaders("POST", "https", "/"), 0, nullptr,
             {header, "1"}));
   }
 
@@ -6533,23 +6183,21 @@
       HostPortPair::FromString("mail.example.org:443"));
 
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   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), &header_stream_offset));
+                       true, std::move(headers)));
 
-  quic::QuicStreamOffset expected_raw_header_response_size = 0;
   mock_quic_data.AddRead(
-      ASYNC,
-      ConstructServerResponseHeadersPacket(
-          1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
-          GetResponseHeaders("200 OK"), &expected_raw_header_response_size));
+      ASYNC, ConstructServerResponseHeadersPacket(
+                 1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
+                 GetResponseHeaders("200 OK")));
+  quic::QuicStreamOffset expected_raw_header_response_size =
+      server_maker_.header_stream_offset();
 
   std::string header = ConstructDataHeader(18);
   mock_quic_data.AddRead(
@@ -6601,11 +6249,9 @@
       HostPortPair::FromString("mail.example.org:443"));
 
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
   uint64_t client_packet_number = 1;
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(client_packet_number++,
-                                                  &header_stream_offset));
+      SYNCHRONOUS, ConstructInitialSettingsPacket(client_packet_number++));
   spdy::SpdyHeaderBlock headers(GetRequestHeaders("GET", "https", "/"));
   headers["user-agent"] = "";
   headers["accept-encoding"] = "gzip, deflate";
@@ -6613,35 +6259,33 @@
       SYNCHRONOUS,
       ConstructClientRequestHeadersPacket(
           client_packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
-          true, true, std::move(headers), &header_stream_offset));
-
-  quic::QuicStreamOffset server_header_offset = 0;
-  quic::QuicStreamOffset expected_raw_header_response_size = 0;
+          true, true, std::move(headers)));
 
   mock_quic_data.AddRead(
-      ASYNC, ConstructServerPushPromisePacket(
-                 1, GetNthClientInitiatedBidirectionalStreamId(0),
-                 GetNthServerInitiatedUnidirectionalStreamId(0), false,
-                 GetRequestHeaders("GET", "https", "/pushed.jpg"),
-                 &server_header_offset, &server_maker_));
+      ASYNC,
+      ConstructServerPushPromisePacket(
+          1, GetNthClientInitiatedBidirectionalStreamId(0),
+          GetNthServerInitiatedUnidirectionalStreamId(0), false,
+          GetRequestHeaders("GET", "https", "/pushed.jpg"), &server_maker_));
 
   if (client_headers_include_h2_stream_dependency_ &&
       version_.transport_version >= quic::QUIC_VERSION_43) {
-    mock_quic_data.AddWrite(SYNCHRONOUS,
-                            ConstructClientPriorityPacket(
-                                client_packet_number++, false,
-                                GetNthServerInitiatedUnidirectionalStreamId(0),
-                                GetNthClientInitiatedBidirectionalStreamId(0),
-                                DEFAULT_PRIORITY, &header_stream_offset));
+    mock_quic_data.AddWrite(
+        SYNCHRONOUS,
+        ConstructClientPriorityPacket(
+            client_packet_number++, false,
+            GetNthServerInitiatedUnidirectionalStreamId(0),
+            GetNthClientInitiatedBidirectionalStreamId(0), DEFAULT_PRIORITY));
   }
 
-  expected_raw_header_response_size = server_header_offset;
+  quic::QuicStreamOffset server_header_offset =
+      server_maker_.header_stream_offset();
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  2, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
-                 GetResponseHeaders("200 OK"), &server_header_offset));
-  expected_raw_header_response_size =
-      server_header_offset - expected_raw_header_response_size;
+                 GetResponseHeaders("200 OK")));
+  quic::QuicStreamOffset expected_raw_header_response_size =
+      server_maker_.header_stream_offset() - server_header_offset;
 
   mock_quic_data.AddWrite(
       SYNCHRONOUS, ConstructClientAckPacket(client_packet_number++, 2, 1, 1));
@@ -6649,7 +6293,7 @@
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  3, GetNthServerInitiatedUnidirectionalStreamId(0), false,
-                 false, GetResponseHeaders("200 OK"), &server_header_offset));
+                 false, GetResponseHeaders("200 OK")));
   std::string header = ConstructDataHeader(20);
   mock_quic_data.AddRead(
       ASYNC, ConstructServerDataPacket(
@@ -6717,14 +6361,11 @@
   socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
 
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientRequestHeadersPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-          GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
+      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
+                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
+                       true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -6858,30 +6499,20 @@
         url::SchemeHostPort("https", origin, 443), alternative_service,
         expiration, supported_versions_);
   }
-  std::unique_ptr<quic::QuicEncryptedPacket>
-  ConstructClientRequestHeadersPacket(uint64_t packet_number,
-                                      quic::QuicStreamId stream_id,
-                                      bool should_include_version,
-                                      quic::QuicStreamOffset* offset,
-                                      QuicTestPacketMaker* maker) {
-    return ConstructClientRequestHeadersPacket(
-        packet_number, stream_id, should_include_version, 0, offset, maker);
-  }
 
   std::unique_ptr<quic::QuicEncryptedPacket>
   ConstructClientRequestHeadersPacket(uint64_t packet_number,
                                       quic::QuicStreamId stream_id,
                                       bool should_include_version,
                                       quic::QuicStreamId parent_stream_id,
-                                      quic::QuicStreamOffset* offset,
                                       QuicTestPacketMaker* maker) {
     spdy::SpdyPriority priority =
         ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY);
     spdy::SpdyHeaderBlock headers(
         maker->GetRequestHeaders("GET", "https", "/"));
-    return maker->MakeRequestHeadersPacketWithOffsetTracking(
+    return maker->MakeRequestHeadersPacket(
         packet_number, stream_id, should_include_version, true, priority,
-        std::move(headers), parent_stream_id, offset);
+        std::move(headers), parent_stream_id, nullptr);
   }
 
   std::unique_ptr<quic::QuicEncryptedPacket>
@@ -6890,25 +6521,16 @@
                                       bool should_include_version,
                                       QuicTestPacketMaker* maker) {
     return ConstructClientRequestHeadersPacket(
-        packet_number, stream_id, should_include_version, nullptr, maker);
+        packet_number, stream_id, should_include_version, 0, maker);
   }
 
   std::unique_ptr<quic::QuicEncryptedPacket>
   ConstructServerResponseHeadersPacket(uint64_t packet_number,
                                        quic::QuicStreamId stream_id,
-                                       quic::QuicStreamOffset* offset,
                                        QuicTestPacketMaker* maker) {
     spdy::SpdyHeaderBlock headers(maker->GetResponseHeaders("200 OK"));
-    return maker->MakeResponseHeadersPacketWithOffsetTracking(
-        packet_number, stream_id, false, false, std::move(headers), offset);
-  }
-
-  std::unique_ptr<quic::QuicEncryptedPacket>
-  ConstructServerResponseHeadersPacket(uint64_t packet_number,
-                                       quic::QuicStreamId stream_id,
-                                       QuicTestPacketMaker* maker) {
-    return ConstructServerResponseHeadersPacket(packet_number, stream_id,
-                                                nullptr, maker);
+    return maker->MakeResponseHeadersPacket(packet_number, stream_id, false,
+                                            false, std::move(headers), nullptr);
   }
 
   std::unique_ptr<quic::QuicEncryptedPacket> ConstructServerDataPacket(
@@ -6938,9 +6560,8 @@
 
   std::unique_ptr<quic::QuicReceivedPacket> ConstructInitialSettingsPacket(
       uint64_t packet_number,
-      quic::QuicStreamOffset* offset,
       QuicTestPacketMaker* maker) {
-    return maker->MakeInitialSettingsPacket(packet_number, offset);
+    return maker->MakeInitialSettingsPacket(packet_number);
   }
 
   void AddRefusedSocketData() {
@@ -7113,21 +6734,17 @@
       version_, quic::QuicUtils::CreateRandomConnectionId(&random_generator_),
       &clock_, origin1_, quic::Perspective::IS_SERVER, false);
 
-  quic::QuicStreamOffset request_header_offset(0);
-  quic::QuicStreamOffset response_header_offset(0);
-
   MockQuicData mock_quic_data(version_);
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructInitialSettingsPacket(1, &request_header_offset, &client_maker));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructInitialSettingsPacket(1, &client_maker));
   mock_quic_data.AddWrite(
       SYNCHRONOUS, ConstructClientRequestHeadersPacket(
                        2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       &request_header_offset, &client_maker));
-  mock_quic_data.AddRead(ASYNC,
-                         ConstructServerResponseHeadersPacket(
-                             1, GetNthClientInitiatedBidirectionalStreamId(0),
-                             &response_header_offset, &server_maker));
+                       &client_maker));
+  mock_quic_data.AddRead(
+      ASYNC,
+      ConstructServerResponseHeadersPacket(
+          1, GetNthClientInitiatedBidirectionalStreamId(0), &server_maker));
   mock_quic_data.AddRead(
       ASYNC,
       ConstructServerDataPacket(
@@ -7139,14 +6756,14 @@
   server_maker.set_hostname(origin2_);
 
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
-                       4, GetNthClientInitiatedBidirectionalStreamId(1), false,
-                       GetNthClientInitiatedBidirectionalStreamId(0),
-                       &request_header_offset, &client_maker));
-  mock_quic_data.AddRead(ASYNC,
-                         ConstructServerResponseHeadersPacket(
-                             3, GetNthClientInitiatedBidirectionalStreamId(1),
-                             &response_header_offset, &server_maker));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          4, GetNthClientInitiatedBidirectionalStreamId(1), false,
+          GetNthClientInitiatedBidirectionalStreamId(0), &client_maker));
+  mock_quic_data.AddRead(
+      ASYNC,
+      ConstructServerResponseHeadersPacket(
+          3, GetNthClientInitiatedBidirectionalStreamId(1), &server_maker));
   mock_quic_data.AddRead(
       ASYNC,
       ConstructServerDataPacket(
@@ -7215,14 +6832,12 @@
       &clock_, origin1_, quic::Perspective::IS_SERVER, false);
 
   MockQuicData mock_quic_data1(version_);
-  quic::QuicStreamOffset header_stream_offset1 = 0;
-  mock_quic_data1.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset1,
-                                                  &client_maker1));
+  mock_quic_data1.AddWrite(SYNCHRONOUS,
+                           ConstructInitialSettingsPacket(1, &client_maker1));
   mock_quic_data1.AddWrite(
       SYNCHRONOUS, ConstructClientRequestHeadersPacket(
                        2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       &header_stream_offset1, &client_maker1));
+                       &client_maker1));
   mock_quic_data1.AddRead(
       ASYNC,
       ConstructServerResponseHeadersPacket(
@@ -7247,14 +6862,12 @@
       &clock_, origin2_, quic::Perspective::IS_SERVER, false);
 
   MockQuicData mock_quic_data2(version_);
-  quic::QuicStreamOffset header_stream_offset2 = 0;
-  mock_quic_data2.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset2,
-                                                  &client_maker2));
+  mock_quic_data2.AddWrite(SYNCHRONOUS,
+                           ConstructInitialSettingsPacket(1, &client_maker2));
   mock_quic_data2.AddWrite(
       SYNCHRONOUS, ConstructClientRequestHeadersPacket(
                        2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       &header_stream_offset2, &client_maker2));
+                       &client_maker2));
   mock_quic_data2.AddRead(
       ASYNC,
       ConstructServerResponseHeadersPacket(
@@ -7283,43 +6896,39 @@
       HostPortPair::FromString("mail.example.org:443"));
 
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
   uint64_t client_packet_number = 1;
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(client_packet_number++,
-                                                  &header_stream_offset));
+      SYNCHRONOUS, ConstructInitialSettingsPacket(client_packet_number++));
   mock_quic_data.AddWrite(
       SYNCHRONOUS,
       ConstructClientRequestHeadersPacket(
           client_packet_number++, GetNthClientInitiatedBidirectionalStreamId(0),
-          true, true, GetRequestHeaders("GET", "https", "/"),
-          &header_stream_offset));
-  quic::QuicStreamOffset server_header_offset = 0;
+          true, true, GetRequestHeaders("GET", "https", "/")));
   mock_quic_data.AddRead(
-      ASYNC, ConstructServerPushPromisePacket(
-                 1, GetNthClientInitiatedBidirectionalStreamId(0),
-                 GetNthServerInitiatedUnidirectionalStreamId(0), false,
-                 GetRequestHeaders("GET", "https", "/pushed.jpg"),
-                 &server_header_offset, &server_maker_));
+      ASYNC,
+      ConstructServerPushPromisePacket(
+          1, GetNthClientInitiatedBidirectionalStreamId(0),
+          GetNthServerInitiatedUnidirectionalStreamId(0), false,
+          GetRequestHeaders("GET", "https", "/pushed.jpg"), &server_maker_));
   if (client_headers_include_h2_stream_dependency_ &&
       version_.transport_version >= quic::QUIC_VERSION_43) {
-    mock_quic_data.AddWrite(SYNCHRONOUS,
-                            ConstructClientPriorityPacket(
-                                client_packet_number++, false,
-                                GetNthServerInitiatedUnidirectionalStreamId(0),
-                                GetNthClientInitiatedBidirectionalStreamId(0),
-                                DEFAULT_PRIORITY, &header_stream_offset));
+    mock_quic_data.AddWrite(
+        SYNCHRONOUS,
+        ConstructClientPriorityPacket(
+            client_packet_number++, false,
+            GetNthServerInitiatedUnidirectionalStreamId(0),
+            GetNthClientInitiatedBidirectionalStreamId(0), DEFAULT_PRIORITY));
   }
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  2, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
-                 GetResponseHeaders("200 OK"), &server_header_offset));
+                 GetResponseHeaders("200 OK")));
   mock_quic_data.AddWrite(
       SYNCHRONOUS, ConstructClientAckPacket(client_packet_number++, 2, 1, 1));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  3, GetNthServerInitiatedUnidirectionalStreamId(0), false,
-                 false, GetResponseHeaders("200 OK"), &server_header_offset));
+                 false, GetResponseHeaders("200 OK")));
   std::string header = ConstructDataHeader(6);
   mock_quic_data.AddRead(
       ASYNC, ConstructServerDataPacket(
@@ -7351,8 +6960,7 @@
             client_packet_number++,
             GetNthClientInitiatedBidirectionalStreamId(1), false, true,
             DEFAULT_PRIORITY, GetRequestHeaders("GET", "https", "/pushed.jpg"),
-            GetNthServerInitiatedUnidirectionalStreamId(0),
-            &header_stream_offset, nullptr, {kBody}));
+            GetNthServerInitiatedUnidirectionalStreamId(0), nullptr, {kBody}));
   } else {
     mock_quic_data.AddWrite(
         SYNCHRONOUS,
@@ -7360,8 +6968,8 @@
             client_packet_number++,
             GetNthClientInitiatedBidirectionalStreamId(1), false, true,
             DEFAULT_PRIORITY, GetRequestHeaders("GET", "https", "/pushed.jpg"),
-            GetNthServerInitiatedUnidirectionalStreamId(0),
-            &header_stream_offset, nullptr, {header3, kBody}));
+            GetNthServerInitiatedUnidirectionalStreamId(0), nullptr,
+            {header3, kBody}));
   }
 
   // We see the same response as for the earlier pushed and cancelled
@@ -7369,7 +6977,7 @@
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  6, GetNthClientInitiatedBidirectionalStreamId(1), false, false,
-                 GetResponseHeaders("200 OK"), &server_header_offset));
+                 GetResponseHeaders("200 OK")));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerDataPacket(
                  7, GetNthClientInitiatedBidirectionalStreamId(1), false, true,
@@ -7412,22 +7020,17 @@
 
   MockQuicData mock_quic_data(version_);
 
-  quic::QuicStreamOffset header_stream_offset = 0;
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientRequestHeadersPacket(
-          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-          GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
+      SYNCHRONOUS, ConstructClientRequestHeadersPacket(
+                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
+                       true, GetRequestHeaders("GET", "https", "/")));
 
-  quic::QuicStreamOffset server_header_offset = 0;
   mock_quic_data.AddRead(
       ASYNC, ConstructServerPushPromisePacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0),
                  GetNthServerInitiatedUnidirectionalStreamId(0), false,
-                 std::move(pushed_request_headers), &server_header_offset,
-                 &server_maker_));
+                 std::move(pushed_request_headers), &server_maker_));
   mock_quic_data.AddWrite(SYNCHRONOUS,
                           ConstructClientRstPacket(
                               3, GetNthServerInitiatedUnidirectionalStreamId(0),
@@ -7436,13 +7039,13 @@
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  2, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
-                 GetResponseHeaders("200 OK"), &server_header_offset));
+                 GetResponseHeaders("200 OK")));
   mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(4, 2, 1, 1));
 
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  3, GetNthServerInitiatedUnidirectionalStreamId(0), false,
-                 false, GetResponseHeaders("200 OK"), &server_header_offset));
+                 false, GetResponseHeaders("200 OK")));
   std::string header = ConstructDataHeader(6);
   mock_quic_data.AddRead(
       ASYNC, ConstructServerDataPacket(
@@ -7474,15 +7077,12 @@
       "QUIC proxy.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   mock_quic_data.AddWrite(
       SYNCHRONOUS, ConstructClientRequestHeadersPacket(
                        2, GetNthClientInitiatedBidirectionalStreamId(0), true,
                        false, HttpProxyConnectJob::kH2QuicTunnelPriority,
-                       ConnectRequestHeaders("mail.example.org:443"), 0,
-                       &header_stream_offset));
+                       ConnectRequestHeaders("mail.example.org:443"), 0));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -7567,15 +7167,12 @@
       "QUIC proxy.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   mock_quic_data.AddWrite(
       SYNCHRONOUS, ConstructClientRequestHeadersPacket(
                        2, GetNthClientInitiatedBidirectionalStreamId(0), true,
                        false, HttpProxyConnectJob::kH2QuicTunnelPriority,
-                       ConnectRequestHeaders("mail.example.org:443"), 0,
-                       &header_stream_offset));
+                       ConnectRequestHeaders("mail.example.org:443"), 0));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -7667,18 +7264,15 @@
       "QUIC proxy.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
   int write_packet_index = 1;
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(write_packet_index++,
-                                                  &header_stream_offset));
+  mock_quic_data.AddWrite(SYNCHRONOUS,
+                          ConstructInitialSettingsPacket(write_packet_index++));
   mock_quic_data.AddWrite(
       SYNCHRONOUS,
       ConstructClientRequestHeadersPacket(
           write_packet_index++, GetNthClientInitiatedBidirectionalStreamId(0),
           true, false, HttpProxyConnectJob::kH2QuicTunnelPriority,
-          ConnectRequestHeaders("mail.example.org:443"), 0,
-          &header_stream_offset));
+          ConnectRequestHeaders("mail.example.org:443"), 0));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -7832,22 +7426,18 @@
       "QUIC proxy.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset client_header_stream_offset = 0;
-  quic::QuicStreamOffset server_header_stream_offset = 0;
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(
-                                           1, &client_header_stream_offset));
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
 
   // 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,
-                       &client_header_stream_offset));
+                       ConnectRequestHeaders("mail.example.org:443"), 0));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
-                 GetResponseHeaders("200 OK"), &server_header_stream_offset));
+                 GetResponseHeaders("200 OK")));
 
   // GET request, response, and data over QUIC tunnel for first request
   const char get_request[] =
@@ -7891,12 +7481,11 @@
                        5, GetNthClientInitiatedBidirectionalStreamId(1), false,
                        false, HttpProxyConnectJob::kH2QuicTunnelPriority,
                        ConnectRequestHeaders("different.example.org:443"),
-                       GetNthClientInitiatedBidirectionalStreamId(0),
-                       &client_header_stream_offset));
+                       GetNthClientInitiatedBidirectionalStreamId(0)));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  4, GetNthClientInitiatedBidirectionalStreamId(1), false, false,
-                 GetResponseHeaders("200 OK"), &server_header_stream_offset));
+                 GetResponseHeaders("200 OK")));
 
   // GET request, response, and data over QUIC tunnel for second request
   SpdyTestUtil spdy_util;
@@ -8004,15 +7593,12 @@
       "QUIC proxy.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   mock_quic_data.AddWrite(
       SYNCHRONOUS, ConstructClientRequestHeadersPacket(
                        2, GetNthClientInitiatedBidirectionalStreamId(0), true,
                        false, HttpProxyConnectJob::kH2QuicTunnelPriority,
-                       ConnectRequestHeaders("mail.example.org:443"), 0,
-                       &header_stream_offset));
+                       ConnectRequestHeaders("mail.example.org:443"), 0));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
@@ -8053,15 +7639,12 @@
       "QUIC proxy.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   mock_quic_data.AddWrite(
       SYNCHRONOUS, ConstructClientRequestHeadersPacket(
                        2, GetNthClientInitiatedBidirectionalStreamId(0), true,
                        false, HttpProxyConnectJob::kH2QuicTunnelPriority,
-                       ConnectRequestHeaders("mail.example.org:443"), 0,
-                       &header_stream_offset));
+                       ConnectRequestHeaders("mail.example.org:443"), 0));
   mock_quic_data.AddRead(ASYNC, ERR_CONNECTION_FAILED);
 
   mock_quic_data.AddSocketDataToFactory(&socket_factory_);
@@ -8092,20 +7675,16 @@
       "QUIC proxy.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset client_header_stream_offset = 0;
-  quic::QuicStreamOffset server_header_stream_offset = 0;
-  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(
-                                           1, &client_header_stream_offset));
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   mock_quic_data.AddWrite(
       SYNCHRONOUS, ConstructClientRequestHeadersPacket(
                        2, GetNthClientInitiatedBidirectionalStreamId(0), true,
                        false, HttpProxyConnectJob::kH2QuicTunnelPriority,
-                       ConnectRequestHeaders("mail.example.org:443"), 0,
-                       &client_header_stream_offset));
+                       ConnectRequestHeaders("mail.example.org:443"), 0));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
-                 GetResponseHeaders("200 OK"), &server_header_stream_offset));
+                 GetResponseHeaders("200 OK")));
   mock_quic_data.AddWrite(SYNCHRONOUS,
                           ConstructClientAckAndRstPacket(
                               3, GetNthClientInitiatedBidirectionalStreamId(0),
@@ -8116,12 +7695,11 @@
                        4, GetNthClientInitiatedBidirectionalStreamId(1), false,
                        false, HttpProxyConnectJob::kH2QuicTunnelPriority,
                        ConnectRequestHeaders("mail.example.org:443"),
-                       GetNthClientInitiatedBidirectionalStreamId(0),
-                       &client_header_stream_offset));
+                       GetNthClientInitiatedBidirectionalStreamId(0)));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
                  2, GetNthClientInitiatedBidirectionalStreamId(1), false, false,
-                 GetResponseHeaders("200 OK"), &server_header_stream_offset));
+                 GetResponseHeaders("200 OK")));
 
   const char get_request[] =
       "GET / HTTP/1.1\r\n"
@@ -8216,17 +7794,15 @@
       "QUIC proxy.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS);
 
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
 
   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, &header_stream_offset));
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          2, 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);
@@ -8266,15 +7842,12 @@
   const RequestPriority request_priority = MEDIUM;
 
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   mock_quic_data.AddWrite(
       SYNCHRONOUS, ConstructClientRequestHeadersPacket(
                        2, GetNthClientInitiatedBidirectionalStreamId(0), true,
                        false, HttpProxyConnectJob::kH2QuicTunnelPriority,
-                       ConnectRequestHeaders("mail.example.org:443"), 0,
-                       &header_stream_offset));
+                       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);
@@ -8306,9 +7879,7 @@
   const RequestPriority kRequestPriority2 = LOWEST;
 
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
-  mock_quic_data.AddWrite(
-      ASYNC, ConstructInitialSettingsPacket(1, &header_stream_offset));
+  mock_quic_data.AddWrite(ASYNC, ConstructInitialSettingsPacket(1));
   mock_quic_data.AddWrite(SYNCHRONOUS, ERR_FAILED);
   // This should never be reached.
   mock_quic_data.AddRead(ASYNC, ERR_CONNECTION_FAILED);
@@ -8388,32 +7959,29 @@
             "QUIC proxy.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS);
 
     MockQuicData mock_quic_data(version_);
-    quic::QuicStreamOffset client_header_stream_offset = 0;
-    quic::QuicStreamOffset server_header_stream_offset = 0;
     quic::QuicStreamOffset client_data_offset = 0;
     quic::QuicStreamOffset server_data_offset = 0;
 
     mock_quic_data.AddWrite(SYNCHRONOUS,
-                            client_maker->MakeInitialSettingsPacket(
-                                1, &client_header_stream_offset));
+                            client_maker->MakeInitialSettingsPacket(1));
 
     mock_quic_data.AddWrite(
         SYNCHRONOUS,
-        client_maker->MakeRequestHeadersPacketWithOffsetTracking(
+        client_maker->MakeRequestHeadersPacket(
             2, GetNthClientInitiatedBidirectionalStreamId(0), true, false,
             ConvertRequestPriorityToQuicPriority(
                 HttpProxyConnectJob::kH2QuicTunnelPriority),
             client_maker->ConnectRequestHeaders("mail.example.org:443"), 0,
-            &client_header_stream_offset));
+            nullptr));
 
     spdy::SpdyHeaderBlock headers =
         server_maker->GetResponseHeaders("407 Proxy Authentication Required");
     headers["proxy-authenticate"] = "Basic realm=\"MyRealm1\"";
     headers["content-length"] = "10";
     mock_quic_data.AddRead(
-        ASYNC, server_maker->MakeResponseHeadersPacketWithOffsetTracking(
+        ASYNC, server_maker->MakeResponseHeadersPacket(
                    1, GetNthClientInitiatedBidirectionalStreamId(0), false,
-                   false, std::move(headers), &server_header_stream_offset));
+                   false, std::move(headers), nullptr));
 
     if (i == 0) {
       mock_quic_data.AddRead(
@@ -8442,12 +8010,12 @@
     headers["proxy-authorization"] = "Basic Zm9vOmJheg==";
     mock_quic_data.AddWrite(
         SYNCHRONOUS,
-        client_maker->MakeRequestHeadersPacketWithOffsetTracking(
+        client_maker->MakeRequestHeadersPacket(
             5, GetNthClientInitiatedBidirectionalStreamId(1), false, false,
             ConvertRequestPriorityToQuicPriority(
                 HttpProxyConnectJob::kH2QuicTunnelPriority),
             std::move(headers), GetNthClientInitiatedBidirectionalStreamId(0),
-            &client_header_stream_offset));
+            nullptr));
 
     // Response to wrong password
     headers =
@@ -8455,9 +8023,9 @@
     headers["proxy-authenticate"] = "Basic realm=\"MyRealm1\"";
     headers["content-length"] = "10";
     mock_quic_data.AddRead(
-        ASYNC, server_maker->MakeResponseHeadersPacketWithOffsetTracking(
+        ASYNC, server_maker->MakeResponseHeadersPacket(
                    3, GetNthClientInitiatedBidirectionalStreamId(1), false,
-                   false, std::move(headers), &server_header_stream_offset));
+                   false, std::move(headers), nullptr));
     mock_quic_data.AddRead(SYNCHRONOUS,
                            ERR_IO_PENDING);  // No more data to read
 
@@ -8556,78 +8124,67 @@
       GetNthServerInitiatedUnidirectionalStreamId(1);
 
   MockQuicData mock_quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
-  quic::QuicStreamOffset server_header_offset = 0;
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
+  mock_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
 
   // 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,
-                              &header_stream_offset));
-  mock_quic_data.AddWrite(SYNCHRONOUS,
-                          ConstructClientRequestHeadersPacket(
-                              3, client_stream_1, true, true, MEDIUM,
-                              GetRequestHeaders("GET", "https", "/1.jpg"),
-                              client_stream_0, &header_stream_offset));
-  mock_quic_data.AddWrite(SYNCHRONOUS,
-                          ConstructClientRequestHeadersPacket(
-                              4, client_stream_2, true, true, MEDIUM,
-                              GetRequestHeaders("GET", "https", "/2.jpg"),
-                              client_stream_1, &header_stream_offset));
+                              GetRequestHeaders("GET", "https", "/0.jpg"), 0));
+  mock_quic_data.AddWrite(
+      SYNCHRONOUS,
+      ConstructClientRequestHeadersPacket(
+          3, 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,
+          GetRequestHeaders("GET", "https", "/2.jpg"), client_stream_1));
 
   // Server replies "OK" for the three requests.
-  mock_quic_data.AddRead(
-      ASYNC, ConstructServerResponseHeadersPacket(
-                 1, client_stream_0, false, false, GetResponseHeaders("200 OK"),
-                 &server_header_offset));
-  mock_quic_data.AddRead(
-      ASYNC, ConstructServerResponseHeadersPacket(
-                 2, client_stream_1, false, false, GetResponseHeaders("200 OK"),
-                 &server_header_offset));
+  mock_quic_data.AddRead(ASYNC, ConstructServerResponseHeadersPacket(
+                                    1, client_stream_0, false, false,
+                                    GetResponseHeaders("200 OK")));
+  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.AddRead(
-      ASYNC, ConstructServerResponseHeadersPacket(
-                 3, client_stream_2, false, false, GetResponseHeaders("200 OK"),
-                 &server_header_offset));
+  mock_quic_data.AddRead(ASYNC, ConstructServerResponseHeadersPacket(
+                                    3, client_stream_2, false, false,
+                                    GetResponseHeaders("200 OK")));
 
   // Server sends two push promises associated with |client_stream_0|; client
   // responds with a PRIORITY frame after each to notify server of HTTP/2 stream
   // dependency info for each push promise stream.
-  mock_quic_data.AddRead(ASYNC,
-                         ConstructServerPushPromisePacket(
-                             4, client_stream_0, push_stream_0, false,
-                             GetRequestHeaders("GET", "https", "/pushed_0.jpg"),
-                             &server_header_offset, &server_maker_));
+  mock_quic_data.AddRead(
+      ASYNC,
+      ConstructServerPushPromisePacket(
+          4, client_stream_0, push_stream_0, false,
+          GetRequestHeaders("GET", "https", "/pushed_0.jpg"), &server_maker_));
   mock_quic_data.AddWrite(
       SYNCHRONOUS,
       ConstructClientAckAndPriorityFramesPacket(
           6, false, 4, 3, 1,
           {{push_stream_0, client_stream_2,
-            ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY)}},
-          &header_stream_offset));
-  mock_quic_data.AddRead(ASYNC,
-                         ConstructServerPushPromisePacket(
-                             5, client_stream_0, push_stream_1, false,
-                             GetRequestHeaders("GET", "https", "/pushed_1.jpg"),
-                             &server_header_offset, &server_maker_));
-  mock_quic_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructClientPriorityPacket(7, false, push_stream_1, push_stream_0,
-                                    DEFAULT_PRIORITY, &header_stream_offset));
+            ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY)}}));
+  mock_quic_data.AddRead(
+      ASYNC,
+      ConstructServerPushPromisePacket(
+          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,
+                                           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"),
-                 &server_header_offset));
+                 6, push_stream_0, false, false, GetResponseHeaders("200 OK")));
   mock_quic_data.AddWrite(SYNCHRONOUS, ConstructClientAckPacket(8, 6, 5, 1));
   mock_quic_data.AddRead(
       ASYNC, ConstructServerResponseHeadersPacket(
-                 7, push_stream_1, false, false, GetResponseHeaders("200 OK"),
-                 &server_header_offset));
+                 7, push_stream_1, false, false, GetResponseHeaders("200 OK")));
 
   // Request for "pushed_0.jpg" matches |push_stream_0|. |push_stream_0|'s
   // priority updates to match the request's priority. Client sends PRIORITY
@@ -8639,8 +8196,7 @@
           {{push_stream_1, client_stream_2,
             ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY)},
            {push_stream_0, client_stream_0,
-            ConvertRequestPriorityToQuicPriority(HIGHEST)}},
-          &header_stream_offset));
+            ConvertRequestPriorityToQuicPriority(HIGHEST)}}));
 
   // Server sends data for the three requests and the two push promises.
   std::string header = ConstructDataHeader(8);
@@ -8778,8 +8334,6 @@
           HostPortPair::FromString("mail.example.org:443"));
 
       MockQuicData unpartitioned_mock_quic_data(version_);
-      quic::QuicStreamOffset request_header_offset = 0;
-      quic::QuicStreamOffset response_header_offset = 0;
       QuicTestPacketMaker client_maker1(
           version_,
           quic::QuicUtils::CreateRandomConnectionId(&random_generator_),
@@ -8791,21 +8345,18 @@
           &clock_, kDefaultServerHostName, quic::Perspective::IS_SERVER, false);
 
       unpartitioned_mock_quic_data.AddWrite(
-          SYNCHRONOUS,
-          client_maker1.MakeInitialSettingsPacket(1, &request_header_offset));
+          SYNCHRONOUS, client_maker1.MakeInitialSettingsPacket(1));
 
       unpartitioned_mock_quic_data.AddWrite(
           SYNCHRONOUS,
-          client_maker1.MakeRequestHeadersPacketWithOffsetTracking(
+          client_maker1.MakeRequestHeadersPacket(
               2, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
               ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY),
-              GetRequestHeaders("GET", url1.scheme(), "/1"), 0,
-              &request_header_offset));
+              GetRequestHeaders("GET", url1.scheme(), "/1"), 0, nullptr));
       unpartitioned_mock_quic_data.AddRead(
-          ASYNC,
-          server_maker1.MakeResponseHeadersPacketWithOffsetTracking(
-              1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
-              GetResponseHeaders("200 OK"), &response_header_offset));
+          ASYNC, server_maker1.MakeResponseHeadersPacket(
+                     1, GetNthClientInitiatedBidirectionalStreamId(0), false,
+                     false, GetResponseHeaders("200 OK"), nullptr));
       unpartitioned_mock_quic_data.AddRead(
           ASYNC, server_maker1.MakeDataPacket(
                      2, GetNthClientInitiatedBidirectionalStreamId(0), false,
@@ -8815,16 +8366,14 @@
 
       unpartitioned_mock_quic_data.AddWrite(
           SYNCHRONOUS,
-          client_maker1.MakeRequestHeadersPacketWithOffsetTracking(
+          client_maker1.MakeRequestHeadersPacket(
               4, GetNthClientInitiatedBidirectionalStreamId(1), false, true,
               ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY),
-              GetRequestHeaders("GET", url2.scheme(), "/2"), 0,
-              &request_header_offset));
+              GetRequestHeaders("GET", url2.scheme(), "/2"), 0, nullptr));
       unpartitioned_mock_quic_data.AddRead(
-          ASYNC,
-          server_maker1.MakeResponseHeadersPacketWithOffsetTracking(
-              3, GetNthClientInitiatedBidirectionalStreamId(1), false, false,
-              GetResponseHeaders("200 OK"), &response_header_offset));
+          ASYNC, server_maker1.MakeResponseHeadersPacket(
+                     3, GetNthClientInitiatedBidirectionalStreamId(1), false,
+                     false, GetResponseHeaders("200 OK"), nullptr));
       unpartitioned_mock_quic_data.AddRead(
           ASYNC, server_maker1.MakeDataPacket(
                      4, GetNthClientInitiatedBidirectionalStreamId(1), false,
@@ -8834,16 +8383,14 @@
 
       unpartitioned_mock_quic_data.AddWrite(
           SYNCHRONOUS,
-          client_maker1.MakeRequestHeadersPacketWithOffsetTracking(
+          client_maker1.MakeRequestHeadersPacket(
               6, GetNthClientInitiatedBidirectionalStreamId(2), false, true,
               ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY),
-              GetRequestHeaders("GET", url3.scheme(), "/3"), 0,
-              &request_header_offset));
+              GetRequestHeaders("GET", url3.scheme(), "/3"), 0, nullptr));
       unpartitioned_mock_quic_data.AddRead(
-          ASYNC,
-          server_maker1.MakeResponseHeadersPacketWithOffsetTracking(
-              5, GetNthClientInitiatedBidirectionalStreamId(2), false, false,
-              GetResponseHeaders("200 OK"), &response_header_offset));
+          ASYNC, server_maker1.MakeResponseHeadersPacket(
+                     5, GetNthClientInitiatedBidirectionalStreamId(2), false,
+                     false, GetResponseHeaders("200 OK"), nullptr));
       unpartitioned_mock_quic_data.AddRead(
           ASYNC, server_maker1.MakeDataPacket(
                      6, GetNthClientInitiatedBidirectionalStreamId(2), false,
@@ -8856,8 +8403,6 @@
       // Reads and writes for the partitioned case, where two sockets are used.
 
       MockQuicData partitioned_mock_quic_data1(version_);
-      request_header_offset = 0;
-      response_header_offset = 0;
       QuicTestPacketMaker client_maker2(
           version_,
           quic::QuicUtils::CreateRandomConnectionId(&random_generator_),
@@ -8869,21 +8414,18 @@
           &clock_, kDefaultServerHostName, quic::Perspective::IS_SERVER, false);
 
       partitioned_mock_quic_data1.AddWrite(
-          SYNCHRONOUS,
-          client_maker2.MakeInitialSettingsPacket(1, &request_header_offset));
+          SYNCHRONOUS, client_maker2.MakeInitialSettingsPacket(1));
 
       partitioned_mock_quic_data1.AddWrite(
           SYNCHRONOUS,
-          client_maker2.MakeRequestHeadersPacketWithOffsetTracking(
+          client_maker2.MakeRequestHeadersPacket(
               2, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
               ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY),
-              GetRequestHeaders("GET", url1.scheme(), "/1"), 0,
-              &request_header_offset));
+              GetRequestHeaders("GET", url1.scheme(), "/1"), 0, nullptr));
       partitioned_mock_quic_data1.AddRead(
-          ASYNC,
-          server_maker2.MakeResponseHeadersPacketWithOffsetTracking(
-              1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
-              GetResponseHeaders("200 OK"), &response_header_offset));
+          ASYNC, server_maker2.MakeResponseHeadersPacket(
+                     1, GetNthClientInitiatedBidirectionalStreamId(0), false,
+                     false, GetResponseHeaders("200 OK"), nullptr));
       partitioned_mock_quic_data1.AddRead(
           ASYNC, server_maker2.MakeDataPacket(
                      2, GetNthClientInitiatedBidirectionalStreamId(0), false,
@@ -8893,16 +8435,14 @@
 
       partitioned_mock_quic_data1.AddWrite(
           SYNCHRONOUS,
-          client_maker2.MakeRequestHeadersPacketWithOffsetTracking(
+          client_maker2.MakeRequestHeadersPacket(
               4, GetNthClientInitiatedBidirectionalStreamId(1), false, true,
               ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY),
-              GetRequestHeaders("GET", url3.scheme(), "/3"), 0,
-              &request_header_offset));
+              GetRequestHeaders("GET", url3.scheme(), "/3"), 0, nullptr));
       partitioned_mock_quic_data1.AddRead(
-          ASYNC,
-          server_maker2.MakeResponseHeadersPacketWithOffsetTracking(
-              3, GetNthClientInitiatedBidirectionalStreamId(1), false, false,
-              GetResponseHeaders("200 OK"), &response_header_offset));
+          ASYNC, server_maker2.MakeResponseHeadersPacket(
+                     3, GetNthClientInitiatedBidirectionalStreamId(1), false,
+                     false, GetResponseHeaders("200 OK"), nullptr));
       partitioned_mock_quic_data1.AddRead(
           ASYNC, server_maker2.MakeDataPacket(
                      4, GetNthClientInitiatedBidirectionalStreamId(1), false,
@@ -8913,8 +8453,6 @@
       partitioned_mock_quic_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
 
       MockQuicData partitioned_mock_quic_data2(version_);
-      request_header_offset = 0;
-      response_header_offset = 0;
       QuicTestPacketMaker client_maker3(
           version_,
           quic::QuicUtils::CreateRandomConnectionId(&random_generator_),
@@ -8926,21 +8464,18 @@
           &clock_, kDefaultServerHostName, quic::Perspective::IS_SERVER, false);
 
       partitioned_mock_quic_data2.AddWrite(
-          SYNCHRONOUS,
-          client_maker3.MakeInitialSettingsPacket(1, &request_header_offset));
+          SYNCHRONOUS, client_maker3.MakeInitialSettingsPacket(1));
 
       partitioned_mock_quic_data2.AddWrite(
           SYNCHRONOUS,
-          client_maker3.MakeRequestHeadersPacketWithOffsetTracking(
+          client_maker3.MakeRequestHeadersPacket(
               2, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
               ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY),
-              GetRequestHeaders("GET", url2.scheme(), "/2"), 0,
-              &request_header_offset));
+              GetRequestHeaders("GET", url2.scheme(), "/2"), 0, nullptr));
       partitioned_mock_quic_data2.AddRead(
-          ASYNC,
-          server_maker3.MakeResponseHeadersPacketWithOffsetTracking(
-              1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
-              GetResponseHeaders("200 OK"), &response_header_offset));
+          ASYNC, server_maker3.MakeResponseHeadersPacket(
+                     1, GetNthClientInitiatedBidirectionalStreamId(0), false,
+                     false, GetResponseHeaders("200 OK"), nullptr));
       partitioned_mock_quic_data2.AddRead(
           ASYNC, server_maker3.MakeDataPacket(
                      2, GetNthClientInitiatedBidirectionalStreamId(0), false,
@@ -9046,21 +8581,18 @@
         version_, quic::QuicUtils::CreateRandomConnectionId(&random_generator_),
         &clock_, kDefaultServerHostName, quic::Perspective::IS_SERVER, false);
 
-    quic::QuicStreamOffset header_stream_offset = 0;
-    mock_quic_data[index]->AddWrite(
-        SYNCHRONOUS,
-        client_maker.MakeInitialSettingsPacket(1, &header_stream_offset));
+    mock_quic_data[index]->AddWrite(SYNCHRONOUS,
+                                    client_maker.MakeInitialSettingsPacket(1));
 
     mock_quic_data[index]->AddWrite(
         SYNCHRONOUS,
-        client_maker.MakeRequestHeadersPacketWithOffsetTracking(
+        client_maker.MakeRequestHeadersPacket(
             2, GetNthClientInitiatedBidirectionalStreamId(0), true, false,
             ConvertRequestPriorityToQuicPriority(
                 HttpProxyConnectJob::kH2QuicTunnelPriority),
-            ConnectRequestHeaders("mail.example.org:443"), 0,
-            &header_stream_offset));
+            ConnectRequestHeaders("mail.example.org:443"), 0, nullptr));
     mock_quic_data[index]->AddRead(
-        ASYNC, server_maker.MakeResponseHeadersPacketWithOffsetTracking(
+        ASYNC, server_maker.MakeResponseHeadersPacket(
                    1, GetNthClientInitiatedBidirectionalStreamId(0), false,
                    false, GetResponseHeaders("200 OK"), nullptr));
 
diff --git a/net/quic/quic_proxy_client_socket_unittest.cc b/net/quic/quic_proxy_client_socket_unittest.cc
index 633d2d6..571af998 100644
--- a/net/quic/quic_proxy_client_socket_unittest.cc
+++ b/net/quic/quic_proxy_client_socket_unittest.cc
@@ -145,8 +145,6 @@
                       quic::Perspective::IS_SERVER,
                       false),
         random_generator_(0),
-        header_stream_offset_(0),
-        response_offset_(0),
         user_agent_(kUserAgent),
         proxy_host_port_(kProxyHost, kProxyPort),
         endpoint_host_port_(kOriginHost, kOriginPort),
@@ -279,8 +277,7 @@
 
   std::unique_ptr<quic::QuicReceivedPacket> ConstructSettingsPacket(
       uint64_t packet_number) {
-    return client_maker_.MakeInitialSettingsPacket(packet_number,
-                                                   &header_stream_offset_);
+    return client_maker_.MakeInitialSettingsPacket(packet_number);
   }
 
   std::unique_ptr<quic::QuicReceivedPacket> ConstructAckAndRstPacket(
@@ -340,7 +337,7 @@
     return client_maker_.MakeRequestHeadersPacket(
         packet_number, client_data_stream_id1_, kIncludeVersion, !kFin,
         ConvertRequestPriorityToQuicPriority(request_priority),
-        std::move(block), 0, nullptr, &header_stream_offset_);
+        std::move(block), 0, nullptr);
   }
 
   std::unique_ptr<quic::QuicReceivedPacket> ConstructConnectAuthRequestPacket(
@@ -351,7 +348,7 @@
     return client_maker_.MakeRequestHeadersPacket(
         packet_number, client_data_stream_id1_, kIncludeVersion, !kFin,
         ConvertRequestPriorityToQuicPriority(LOWEST), std::move(block), 0,
-        nullptr, &header_stream_offset_);
+        nullptr);
   }
 
   std::unique_ptr<quic::QuicReceivedPacket> ConstructDataPacket(
@@ -444,7 +441,7 @@
 
     return server_maker_.MakeResponseHeadersPacket(
         packet_number, client_data_stream_id1_, !kIncludeVersion, fin,
-        std::move(block), nullptr, &response_offset_);
+        std::move(block), nullptr);
   }
 
   std::unique_ptr<quic::QuicReceivedPacket>
@@ -454,7 +451,7 @@
     block["proxy-authenticate"] = "Basic realm=\"MyRealm1\"";
     return server_maker_.MakeResponseHeadersPacket(
         packet_number, client_data_stream_id1_, !kIncludeVersion, fin,
-        std::move(block), nullptr, &response_offset_);
+        std::move(block), nullptr);
   }
 
   std::unique_ptr<quic::QuicReceivedPacket>
@@ -465,7 +462,7 @@
     block["set-cookie"] = "foo=bar";
     return server_maker_.MakeResponseHeadersPacket(
         packet_number, client_data_stream_id1_, !kIncludeVersion, fin,
-        std::move(block), nullptr, &response_offset_);
+        std::move(block), nullptr);
   }
 
   std::unique_ptr<quic::QuicReceivedPacket>
@@ -475,7 +472,7 @@
 
     return server_maker_.MakeResponseHeadersPacket(
         packet_number, client_data_stream_id1_, !kIncludeVersion, fin,
-        std::move(block), nullptr, &response_offset_);
+        std::move(block), nullptr);
   }
 
   void AssertConnectSucceeds() {
@@ -593,8 +590,6 @@
   quic::test::MockRandom random_generator_;
   ProofVerifyDetailsChromium verify_details_;
   MockCryptoClientStreamFactory crypto_client_stream_factory_;
-  quic::QuicStreamOffset header_stream_offset_;
-  quic::QuicStreamOffset response_offset_;
 
   std::string user_agent_;
   HostPortPair proxy_host_port_;
diff --git a/net/quic/quic_stream_factory_test.cc b/net/quic/quic_stream_factory_test.cc
index 1f7a86f..30463dc0 100644
--- a/net/quic/quic_stream_factory_test.cc
+++ b/net/quic/quic_stream_factory_test.cc
@@ -39,6 +39,7 @@
 #include "net/quic/quic_server_info.h"
 #include "net/quic/quic_stream_factory_peer.h"
 #include "net/quic/quic_test_packet_maker.h"
+#include "net/quic/quic_test_packet_printer.h"
 #include "net/quic/test_task_runner.h"
 #include "net/socket/next_proto.h"
 #include "net/socket/socket_test_util.h"
@@ -472,8 +473,7 @@
       quic::QuicStreamId stream_id,
       quic::QuicStreamId parent_stream_id,
       bool should_include_version,
-      bool fin,
-      quic::QuicStreamOffset* offset) {
+      bool fin) {
     spdy::SpdyHeaderBlock headers =
         client_maker_.GetRequestHeaders("GET", "https", "/");
     spdy::SpdyPriority priority =
@@ -481,18 +481,7 @@
     size_t spdy_headers_frame_len;
     return client_maker_.MakeRequestHeadersPacket(
         packet_number, stream_id, should_include_version, fin, priority,
-        std::move(headers), parent_stream_id, &spdy_headers_frame_len, offset);
-  }
-
-  std::unique_ptr<quic::QuicEncryptedPacket> ConstructGetRequestPacket(
-      uint64_t packet_number,
-      quic::QuicStreamId stream_id,
-      bool should_include_version,
-      bool fin,
-      quic::QuicStreamOffset* offset) {
-    return ConstructGetRequestPacket(packet_number, stream_id,
-                                     /*parent_stream_id=*/0,
-                                     should_include_version, fin, offset);
+        std::move(headers), parent_stream_id, &spdy_headers_frame_len);
   }
 
   std::unique_ptr<quic::QuicEncryptedPacket> ConstructOkResponsePacket(
@@ -508,13 +497,12 @@
   }
 
   std::unique_ptr<quic::QuicReceivedPacket> ConstructInitialSettingsPacket() {
-    return client_maker_.MakeInitialSettingsPacket(1, nullptr);
+    return client_maker_.MakeInitialSettingsPacket(1);
   }
 
   std::unique_ptr<quic::QuicReceivedPacket> ConstructInitialSettingsPacket(
-      uint64_t packet_number,
-      quic::QuicStreamOffset* offset) {
-    return client_maker_.MakeInitialSettingsPacket(packet_number, offset);
+      uint64_t packet_number) {
+    return client_maker_.MakeInitialSettingsPacket(packet_number);
   }
 
   // Helper method for server migration tests.
@@ -1364,17 +1352,20 @@
   session->CloseSessionOnError(0u, quic::QUIC_NO_ERROR,
                                quic::ConnectionCloseBehavior::SILENT_CLOSE);
 
+  client_maker_.Reset();
   // Set up server IP, socket, proof, and config for new session.
   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, nullptr));
+      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);
 
   ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
@@ -1410,6 +1401,7 @@
   socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   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());
@@ -1567,6 +1559,7 @@
   socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   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());
@@ -1633,6 +1626,7 @@
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   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());
@@ -1869,6 +1863,7 @@
                            3, true, quic::QUIC_INTERNAL_ERROR, "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());
@@ -1951,6 +1946,7 @@
       MockCryptoClientStream::COLD_START);
   ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
   crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
+  client_maker_.Reset();
   MockQuicData socket_data2(version_);
   socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
@@ -2017,6 +2013,7 @@
       MockCryptoClientStream::COLD_START);
   ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
   crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
+  client_maker_.Reset();
   MockQuicData socket_data2(version_);
   socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
@@ -2066,6 +2063,7 @@
                        3, 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());
@@ -2141,13 +2139,11 @@
   crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
 
   MockQuicData quic_data1(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
-  quic_data1.AddWrite(SYNCHRONOUS,
-                      ConstructInitialSettingsPacket(1, &header_stream_offset));
+  quic_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   quic_data1.AddWrite(
-      SYNCHRONOUS, ConstructGetRequestPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, &header_stream_offset));
+      SYNCHRONOUS,
+      ConstructGetRequestPacket(
+          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
   quic_data1.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
   quic_data1.AddRead(
       ASYNC,
@@ -2156,11 +2152,10 @@
   quic_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // Hanging read.
   quic_data1.AddSocketDataToFactory(socket_factory_.get());
 
+  client_maker_.Reset();
   MockQuicData quic_data2(version_);
-  quic::QuicStreamOffset header_stream_offset2 = 0;
   quic_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // Hanging read.
-  quic_data2.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset2));
+  quic_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(1));
   quic_data2.AddSocketDataToFactory(socket_factory_.get());
 
   // Create request and QuicHttpStream.
@@ -2315,18 +2310,17 @@
       ->QueueNetworkMadeDefault(kDefaultNetworkForTests);
 
   MockQuicData quic_data1(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
   quic_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // Hanging Read.
-  quic_data1.AddWrite(SYNCHRONOUS,
-                      ConstructInitialSettingsPacket(1, &header_stream_offset));
+  quic_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   quic_data1.AddWrite(
-      write_mode, ConstructGetRequestPacket(
-                      2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                      true, &header_stream_offset));
+      write_mode,
+      ConstructGetRequestPacket(
+          2, 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.
+  client_maker_.Reset();
   MockQuicData quic_data2(version_);
   // Connectivity probe to be sent on the new path.
   quic_data2.AddWrite(SYNCHRONOUS,
@@ -2490,18 +2484,17 @@
       ->QueueNetworkMadeDefault(kDefaultNetworkForTests);
 
   MockQuicData quic_data1(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
   quic_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // Hanging Read.
-  quic_data1.AddWrite(SYNCHRONOUS,
-                      ConstructInitialSettingsPacket(1, &header_stream_offset));
+  quic_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   quic_data1.AddWrite(
-      SYNCHRONOUS, ConstructGetRequestPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, &header_stream_offset));
+      SYNCHRONOUS,
+      ConstructGetRequestPacket(
+          2, 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.
+  client_maker_.Reset();
   MockQuicData quic_data2(version_);
   // First connectivity probe to be sent on the new path.
   quic_data2.AddWrite(SYNCHRONOUS,
@@ -2919,10 +2912,8 @@
   MockQuicData failed_socket_data(version_);
   MockQuicData socket_data(version_);
   if (migrate_idle_sessions) {
-    quic::QuicStreamOffset header_stream_offset = 0;
     failed_socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-    failed_socket_data.AddWrite(
-        SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
+    failed_socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
     // A RESET will be sent to the peer to cancel the non-migratable stream.
     failed_socket_data.AddWrite(
         SYNCHRONOUS, client_maker_.MakeRstPacket(
@@ -3224,16 +3215,14 @@
 
   int packet_number = 1;
   MockQuicData socket_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructInitialSettingsPacket(packet_number++, &header_stream_offset));
+  socket_data.AddWrite(SYNCHRONOUS,
+                       ConstructInitialSettingsPacket(packet_number++));
   socket_data.AddWrite(
       SYNCHRONOUS,
       ConstructGetRequestPacket(packet_number++,
                                 GetNthClientInitiatedBidirectionalStreamId(0),
-                                true, true, &header_stream_offset));
+                                true, true));
   if (async_write_before) {
     socket_data.AddWrite(ASYNC, OK);
     packet_number++;
@@ -3349,14 +3338,12 @@
   QuicStreamFactoryPeer::SetTaskRunner(factory_.get(), runner_.get());
 
   MockQuicData socket_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
-  socket_data.AddWrite(
-      SYNCHRONOUS, ConstructGetRequestPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, &header_stream_offset));
+      SYNCHRONOUS,
+      ConstructGetRequestPacket(
+          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
   // Create request and QuicHttpStream.
@@ -3479,19 +3466,19 @@
 
   int packet_number = 1;
   MockQuicData quic_data1(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
   quic_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // Hanging Read.
-  quic_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(
-                                       packet_number++, &header_stream_offset));
+  quic_data1.AddWrite(SYNCHRONOUS,
+                      ConstructInitialSettingsPacket(packet_number++));
   quic_data1.AddWrite(
       SYNCHRONOUS,
       ConstructGetRequestPacket(packet_number++,
                                 GetNthClientInitiatedBidirectionalStreamId(0),
-                                true, true, &header_stream_offset));
+                                true, true));
   quic_data1.AddSocketDataToFactory(socket_factory_.get());
 
   // Set up the second socket data provider that is used for probing on the
   // alternate network.
+  client_maker_.Reset();
   MockQuicData quic_data2(version_);
   // Connectivity probe to be sent on the new path.
   quic_data2.AddWrite(SYNCHRONOUS, client_maker_.MakeConnectivityProbingPacket(
@@ -3656,15 +3643,14 @@
 
   int packet_number = 1;
   MockQuicData quic_data1(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
   quic_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // Hanging Read.
-  quic_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(
-                                       packet_number++, &header_stream_offset));
+  quic_data1.AddWrite(SYNCHRONOUS,
+                      ConstructInitialSettingsPacket(packet_number++));
   quic_data1.AddWrite(
       SYNCHRONOUS,
       ConstructGetRequestPacket(packet_number++,
                                 GetNthClientInitiatedBidirectionalStreamId(0),
-                                true, true, &header_stream_offset));
+                                true, true));
   if (async_write_before) {
     quic_data1.AddWrite(ASYNC, OK);
     packet_number++;
@@ -3673,6 +3659,7 @@
 
   // Set up the second socket data provider that is used after migration.
   // The response to the earlier request is read on the new socket.
+  client_maker_.Reset();
   MockQuicData quic_data2(version_);
   // Connectivity probe to be sent on the new path.
   quic_data2.AddWrite(SYNCHRONOUS, client_maker_.MakeConnectivityProbingPacket(
@@ -3812,13 +3799,11 @@
   crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
 
   MockQuicData quic_data1(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
-  quic_data1.AddWrite(SYNCHRONOUS,
-                      ConstructInitialSettingsPacket(1, &header_stream_offset));
+  quic_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   quic_data1.AddWrite(
-      SYNCHRONOUS, ConstructGetRequestPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, &header_stream_offset));
+      SYNCHRONOUS,
+      ConstructGetRequestPacket(
+          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
   quic_data1.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
   quic_data1.AddRead(
       ASYNC,
@@ -3827,11 +3812,10 @@
   quic_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // Hanging read.
   quic_data1.AddSocketDataToFactory(socket_factory_.get());
 
+  client_maker_.Reset();
   MockQuicData quic_data2(version_);
-  quic::QuicStreamOffset header_stream_offset2 = 0;
   quic_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // Hanging read.
-  quic_data2.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset2));
+  quic_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   quic_data2.AddSocketDataToFactory(socket_factory_.get());
 
   // Creat request and QuicHttpStream.
@@ -3926,13 +3910,11 @@
       ->QueueNetworkMadeDefault(kDefaultNetworkForTests);
 
   MockQuicData quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
-  quic_data.AddWrite(SYNCHRONOUS,
-                     ConstructInitialSettingsPacket(1, &header_stream_offset));
-  quic_data.AddWrite(SYNCHRONOUS,
-                     ConstructGetRequestPacket(
-                         2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                         true, &header_stream_offset));
+  quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  quic_data.AddWrite(
+      SYNCHRONOUS,
+      ConstructGetRequestPacket(
+          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
   quic_data.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
   quic_data.AddRead(ASYNC, ConstructOkResponsePacket(
                                1, GetNthClientInitiatedBidirectionalStreamId(0),
@@ -4045,14 +4027,13 @@
 
   int packet_number = 1;
   MockQuicData quic_data1(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
-  quic_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(
-                                       packet_number++, &header_stream_offset));
+  quic_data1.AddWrite(SYNCHRONOUS,
+                      ConstructInitialSettingsPacket(packet_number++));
   quic_data1.AddWrite(
       SYNCHRONOUS,
       ConstructGetRequestPacket(packet_number++,
                                 GetNthClientInitiatedBidirectionalStreamId(0),
-                                true, true, &header_stream_offset));
+                                true, true));
   // Read an out of order packet with FIN to drain the stream.
   quic_data1.AddRead(
       ASYNC, ConstructOkResponsePacket(
@@ -4084,6 +4065,7 @@
     quic_data2.AddWrite(ASYNC,
                         client_maker_.MakePingPacket(packet_number++, false));
   }
+  server_maker_.Reset();
   quic_data2.AddRead(
       ASYNC,
       ConstructOkResponsePacket(
@@ -4216,14 +4198,12 @@
       ->QueueNetworkMadeDefault(kDefaultNetworkForTests);
 
   MockQuicData quic_data1(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
   quic_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // Hanging Read.
-  quic_data1.AddWrite(SYNCHRONOUS,
-                      ConstructInitialSettingsPacket(1, &header_stream_offset));
+  quic_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   quic_data1.AddWrite(
-      SYNCHRONOUS, ConstructGetRequestPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, &header_stream_offset));
+      SYNCHRONOUS,
+      ConstructGetRequestPacket(
+          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
   quic_data1.AddSocketDataToFactory(socket_factory_.get());
 
   // Set up the second socket data provider that is used after migration.
@@ -4374,6 +4354,7 @@
   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());
@@ -4495,13 +4476,11 @@
   crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
 
   MockQuicData quic_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
-  quic_data.AddWrite(SYNCHRONOUS,
-                     ConstructInitialSettingsPacket(1, &header_stream_offset));
-  quic_data.AddWrite(SYNCHRONOUS,
-                     ConstructGetRequestPacket(
-                         2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                         true, &header_stream_offset));
+  quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
+  quic_data.AddWrite(
+      SYNCHRONOUS,
+      ConstructGetRequestPacket(
+          2, 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
@@ -4761,10 +4740,8 @@
   QuicStreamFactoryPeer::SetTaskRunner(factory_.get(), task_runner.get());
 
   MockQuicData socket_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
+  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data.AddWrite(ASYNC, ERR_ADDRESS_UNREACHABLE);
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
@@ -4773,14 +4750,14 @@
   // response to the request is read on this new socket.
   MockQuicData socket_data1(version_);
   socket_data1.AddWrite(
-      SYNCHRONOUS, ConstructGetRequestPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, &header_stream_offset));
-  socket_data1.AddWrite(SYNCHRONOUS,
-                        ConstructGetRequestPacket(
-                            3, GetNthClientInitiatedBidirectionalStreamId(1),
-                            GetNthClientInitiatedBidirectionalStreamId(0), true,
-                            true, &header_stream_offset));
+      SYNCHRONOUS,
+      ConstructGetRequestPacket(
+          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
+  socket_data1.AddWrite(
+      SYNCHRONOUS,
+      ConstructGetRequestPacket(
+          3, GetNthClientInitiatedBidirectionalStreamId(1),
+          GetNthClientInitiatedBidirectionalStreamId(0), true, true));
   socket_data1.AddRead(
       ASYNC,
       ConstructOkResponsePacket(
@@ -4913,10 +4890,8 @@
   QuicStreamFactoryPeer::SetTaskRunner(factory_.get(), task_runner.get());
 
   MockQuicData socket_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
+  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data.AddWrite(ASYNC, ERR_ADDRESS_UNREACHABLE);
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
@@ -4925,9 +4900,9 @@
   // response to the request is read on this new socket.
   MockQuicData quic_data2(version_);
   quic_data2.AddWrite(
-      SYNCHRONOUS, ConstructGetRequestPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, &header_stream_offset));
+      SYNCHRONOUS,
+      ConstructGetRequestPacket(
+          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
   quic_data2.AddRead(
       ASYNC,
       ConstructOkResponsePacket(
@@ -5211,17 +5186,14 @@
 
   // Socket data for connection on the alternate network.
   MockQuicData socket_data2(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
   socket_data2.AddWrite(SYNCHRONOUS, client_maker_.MakeDummyCHLOPacket(1));
   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, &header_stream_offset));
+  socket_data2.AddWrite(ASYNC, ConstructInitialSettingsPacket(2));
   socket_data2.AddWrite(
       ASYNC, ConstructGetRequestPacket(
-                 3, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-                 &header_stream_offset));
+                 3, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
   socket_data2.AddRead(
       ASYNC,
       ConstructOkResponsePacket(
@@ -5374,6 +5346,7 @@
       MockCryptoClientStream::COLD_START);
   ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
   crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
+  client_maker_.Reset();
   MockQuicData socket_data2(version_);
   socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
@@ -5430,17 +5403,14 @@
 
   // Socket data for connection on the alternate network.
   MockQuicData socket_data2(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
   socket_data2.AddWrite(SYNCHRONOUS, client_maker_.MakeDummyCHLOPacket(1));
   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, &header_stream_offset));
+  socket_data2.AddWrite(ASYNC, ConstructInitialSettingsPacket(2));
   socket_data2.AddWrite(
       ASYNC, ConstructGetRequestPacket(
-                 3, GetNthClientInitiatedBidirectionalStreamId(0), true, true,
-                 &header_stream_offset));
+                 3, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
   socket_data2.AddRead(
       ASYNC,
       ConstructOkResponsePacket(
@@ -5515,10 +5485,8 @@
   auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>();
 
   MockQuicData socket_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
+  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data.AddWrite(write_error_mode, ERR_ADDRESS_UNREACHABLE);
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
@@ -5553,9 +5521,9 @@
   // response to the request is read on this new socket.
   MockQuicData socket_data1(version_);
   socket_data1.AddWrite(
-      SYNCHRONOUS, ConstructGetRequestPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, &header_stream_offset));
+      SYNCHRONOUS,
+      ConstructGetRequestPacket(
+          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
   socket_data1.AddRead(
       ASYNC,
       ConstructOkResponsePacket(
@@ -5724,10 +5692,8 @@
   crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
 
   MockQuicData socket_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
+  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data.AddWrite(write_error_mode, ERR_ADDRESS_UNREACHABLE);
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
@@ -5736,9 +5702,9 @@
   // response to the request is read on this new socket.
   MockQuicData socket_data1(version_);
   socket_data1.AddWrite(
-      SYNCHRONOUS, ConstructGetRequestPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, &header_stream_offset));
+      SYNCHRONOUS,
+      ConstructGetRequestPacket(
+          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
   socket_data1.AddRead(
       ASYNC,
       ConstructOkResponsePacket(
@@ -5857,11 +5823,10 @@
 
   int packet_number = 1;
   MockQuicData socket_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
+
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructInitialSettingsPacket(packet_number++, &header_stream_offset));
+  socket_data.AddWrite(SYNCHRONOUS,
+                       ConstructInitialSettingsPacket(packet_number++));
   socket_data.AddWrite(write_error_mode, ERR_ADDRESS_UNREACHABLE);
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
@@ -5873,7 +5838,7 @@
       SYNCHRONOUS,
       ConstructGetRequestPacket(packet_number++,
                                 GetNthClientInitiatedBidirectionalStreamId(0),
-                                true, true, &header_stream_offset));
+                                true, true));
   socket_data1.AddWrite(
       SYNCHRONOUS,
       client_maker_.MakeRstPacket(packet_number++, true,
@@ -5996,11 +5961,9 @@
 
   int packet_number = 1;
   MockQuicData socket_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(
-      SYNCHRONOUS,
-      ConstructInitialSettingsPacket(packet_number++, &header_stream_offset));
+  socket_data.AddWrite(SYNCHRONOUS,
+                       ConstructInitialSettingsPacket(packet_number++));
   socket_data.AddWrite(write_error_mode,
                        ERR_ADDRESS_UNREACHABLE);  // Write error.
   socket_data.AddSocketDataToFactory(socket_factory_.get());
@@ -6015,7 +5978,7 @@
       SYNCHRONOUS,
       ConstructGetRequestPacket(packet_number++,
                                 GetNthClientInitiatedBidirectionalStreamId(1),
-                                true, true, &header_stream_offset));
+                                true, true));
   socket_data1.AddWrite(
       SYNCHRONOUS,
       client_maker_.MakeRstPacket(packet_number++, true,
@@ -6026,7 +5989,7 @@
       SYNCHRONOUS,
       ConstructGetRequestPacket(packet_number++,
                                 GetNthClientInitiatedBidirectionalStreamId(0),
-                                true, true, &header_stream_offset));
+                                true, true));
   socket_data1.AddRead(
       ASYNC,
       ConstructOkResponsePacket(
@@ -6142,11 +6105,9 @@
   MockQuicData failed_socket_data(version_);
   MockQuicData socket_data(version_);
   if (migrate_idle_sessions) {
-    quic::QuicStreamOffset header_stream_offset = 0;
     // The socket data provider for the original socket before migration.
     failed_socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-    failed_socket_data.AddWrite(
-        SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
+    failed_socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
     failed_socket_data.AddWrite(write_error_mode, ERR_ADDRESS_UNREACHABLE);
     failed_socket_data.AddSocketDataToFactory(socket_factory_.get());
 
@@ -6156,9 +6117,9 @@
     // non-migratable stream and the stream will be cancelled during migration,
     // the packet will still be retransimitted at the connection level.
     socket_data.AddWrite(
-        SYNCHRONOUS, ConstructGetRequestPacket(
-                         2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                         true, &header_stream_offset));
+        SYNCHRONOUS,
+        ConstructGetRequestPacket(
+            2, 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(
@@ -6344,10 +6305,8 @@
   // Set up the socket data used by the original network, which encounters a
   // write erorr.
   MockQuicData socket_data1(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
   socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data1.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
+  socket_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data1.AddWrite(write_error_mode_on_old_network,
                         ERR_ADDRESS_UNREACHABLE);  // Write Error
   socket_data1.AddSocketDataToFactory(socket_factory_.get());
@@ -6371,9 +6330,9 @@
   // and the response to the request is read on this socket.
   MockQuicData socket_data2(version_);
   socket_data2.AddWrite(
-      SYNCHRONOUS, ConstructGetRequestPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, &header_stream_offset));
+      SYNCHRONOUS,
+      ConstructGetRequestPacket(
+          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
   socket_data2.AddRead(
       ASYNC,
       ConstructOkResponsePacket(
@@ -6512,10 +6471,8 @@
   crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
 
   MockQuicData socket_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
+  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data.AddWrite(SYNCHRONOUS, ERR_ADDRESS_UNREACHABLE);
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
@@ -6550,9 +6507,9 @@
   // response to the request is read on this new socket.
   MockQuicData socket_data1(version_);
   socket_data1.AddWrite(
-      SYNCHRONOUS, ConstructGetRequestPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, &header_stream_offset));
+      SYNCHRONOUS,
+      ConstructGetRequestPacket(
+          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
   socket_data1.AddRead(
       ASYNC,
       ConstructOkResponsePacket(
@@ -6646,10 +6603,8 @@
   crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
 
   MockQuicData socket_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
+  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data.AddWrite(SYNCHRONOUS, ERR_ADDRESS_UNREACHABLE);
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
@@ -6684,9 +6639,9 @@
   // response to the request is read on this new socket.
   MockQuicData socket_data1(version_);
   socket_data1.AddWrite(
-      SYNCHRONOUS, ConstructGetRequestPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, &header_stream_offset));
+      SYNCHRONOUS,
+      ConstructGetRequestPacket(
+          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
   socket_data1.AddRead(
       ASYNC,
       ConstructOkResponsePacket(
@@ -6786,10 +6741,8 @@
   QuicStreamFactoryPeer::SetTaskRunner(factory_.get(), runner_.get());
 
   MockQuicData socket_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // Hanging read.
-  socket_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
+  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data.AddWrite(write_error_mode, ERR_FAILED);
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
@@ -6835,9 +6788,9 @@
   // The response to the earlier request is read on this new socket.
   MockQuicData socket_data1(version_);
   socket_data1.AddWrite(
-      SYNCHRONOUS, ConstructGetRequestPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, &header_stream_offset));
+      SYNCHRONOUS,
+      ConstructGetRequestPacket(
+          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
   socket_data1.AddRead(
       ASYNC,
       ConstructOkResponsePacket(
@@ -6916,9 +6869,7 @@
   QuicStreamFactoryPeer::SetTaskRunner(factory_.get(), task_runner.get());
 
   MockQuicData socket_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
-  socket_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
+  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
   socket_data.AddWrite(ASYNC, ERR_ADDRESS_UNREACHABLE);
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
@@ -7021,9 +6972,7 @@
   QuicStreamFactoryPeer::SetTaskRunner(factory_.get(), task_runner.get());
 
   MockQuicData socket_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
-  socket_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
+  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
   socket_data.AddRead(ASYNC, ERR_ADDRESS_UNREACHABLE);
   socket_data.AddSocketDataToFactory(socket_factory_.get());
@@ -7061,9 +7010,9 @@
   socket_data1.AddWrite(
       SYNCHRONOUS, client_maker_.MakePingPacket(2, /*include_version=*/true));
   socket_data1.AddWrite(
-      SYNCHRONOUS, ConstructGetRequestPacket(
-                       3, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, &header_stream_offset));
+      SYNCHRONOUS,
+      ConstructGetRequestPacket(
+          3, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
   socket_data1.AddRead(
       ASYNC,
       ConstructOkResponsePacket(
@@ -7135,9 +7084,7 @@
   QuicStreamFactoryPeer::SetTaskRunner(factory_.get(), task_runner.get());
 
   MockQuicData socket_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
-  socket_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
+  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
   socket_data.AddRead(ASYNC, ERR_ADDRESS_UNREACHABLE);
   socket_data.AddSocketDataToFactory(socket_factory_.get());
@@ -7175,9 +7122,9 @@
   socket_data1.AddWrite(
       SYNCHRONOUS, client_maker_.MakePingPacket(2, /*include_version=*/true));
   socket_data1.AddWrite(
-      SYNCHRONOUS, ConstructGetRequestPacket(
-                       3, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, &header_stream_offset));
+      SYNCHRONOUS,
+      ConstructGetRequestPacket(
+          3, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
   socket_data1.AddRead(
       ASYNC,
       ConstructOkResponsePacket(
@@ -7251,9 +7198,7 @@
       std::make_unique<QuicChromiumAlarmFactory>(task_runner.get(), &clock_));
 
   MockQuicData socket_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
-  socket_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
+  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
   socket_data.AddRead(ASYNC, ERR_ADDRESS_UNREACHABLE);
   socket_data.AddSocketDataToFactory(socket_factory_.get());
@@ -7265,9 +7210,9 @@
   // The PING packet sent post migration.
   socket_data1.AddWrite(SYNCHRONOUS, client_maker_.MakePingPacket(2, true));
   socket_data1.AddWrite(
-      SYNCHRONOUS, ConstructGetRequestPacket(
-                       3, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, &header_stream_offset));
+      SYNCHRONOUS,
+      ConstructGetRequestPacket(
+          3, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
   socket_data1.AddRead(ASYNC, ERR_IO_PENDING);  // Pause.
   // Read two packets so that client will send ACK immedaitely.
   spdy::SpdyHeaderBlock response_headers =
@@ -7411,9 +7356,7 @@
       std::make_unique<QuicChromiumAlarmFactory>(task_runner.get(), &clock_));
 
   MockQuicData socket_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
-  socket_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
+  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
   socket_data.AddRead(ASYNC, ERR_ADDRESS_UNREACHABLE);
   socket_data.AddSocketDataToFactory(socket_factory_.get());
@@ -7425,9 +7368,9 @@
   // The PING packet sent post migration.
   socket_data1.AddWrite(SYNCHRONOUS, client_maker_.MakePingPacket(2, true));
   socket_data1.AddWrite(
-      SYNCHRONOUS, ConstructGetRequestPacket(
-                       3, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, &header_stream_offset));
+      SYNCHRONOUS,
+      ConstructGetRequestPacket(
+          3, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
   socket_data1.AddRead(ASYNC, ERR_IO_PENDING);  // Pause.
   // Read two packets so that client will send ACK immedaitely.
   spdy::SpdyHeaderBlock response_headers =
@@ -7570,13 +7513,11 @@
       std::make_unique<QuicChromiumAlarmFactory>(task_runner.get(), &clock_));
 
   MockQuicData socket_data1(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
+  socket_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data1.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
-  socket_data1.AddWrite(
-      SYNCHRONOUS, ConstructGetRequestPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, &header_stream_offset));
+      SYNCHRONOUS,
+      ConstructGetRequestPacket(
+          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
   socket_data1.AddRead(ASYNC, ERR_IO_PENDING);  // Pause.
   // Read two packets so that client will send ACK immedaitely.
   spdy::SpdyHeaderBlock response_headers =
@@ -7708,13 +7649,11 @@
       std::make_unique<QuicChromiumAlarmFactory>(task_runner.get(), &clock_));
 
   MockQuicData socket_data1(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
+  socket_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data1.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
-  socket_data1.AddWrite(
-      SYNCHRONOUS, ConstructGetRequestPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, &header_stream_offset));
+      SYNCHRONOUS,
+      ConstructGetRequestPacket(
+          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
   socket_data1.AddRead(ASYNC, ERR_IO_PENDING);  // Pause.
   // Read two packets so that client will send ACK immedaitely.
   spdy::SpdyHeaderBlock response_headers =
@@ -7846,13 +7785,11 @@
       std::make_unique<QuicChromiumAlarmFactory>(task_runner.get(), &clock_));
 
   MockQuicData socket_data1(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
+  socket_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data1.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
-  socket_data1.AddWrite(
-      SYNCHRONOUS, ConstructGetRequestPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, &header_stream_offset));
+      SYNCHRONOUS,
+      ConstructGetRequestPacket(
+          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
   socket_data1.AddRead(ASYNC, ERR_IO_PENDING);  // Pause.
   // Read two packets so that client will send ACK immedaitely.
   spdy::SpdyHeaderBlock response_headers =
@@ -7986,13 +7923,11 @@
       std::make_unique<QuicChromiumAlarmFactory>(task_runner.get(), &clock_));
 
   MockQuicData socket_data1(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
+  socket_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data1.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
-  socket_data1.AddWrite(
-      SYNCHRONOUS, ConstructGetRequestPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, &header_stream_offset));
+      SYNCHRONOUS,
+      ConstructGetRequestPacket(
+          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
   socket_data1.AddRead(ASYNC, ERR_IO_PENDING);  // Pause.
   // Read two packets so that client will send ACK immedaitely.
   spdy::SpdyHeaderBlock response_headers =
@@ -8118,9 +8053,7 @@
   QuicStreamFactoryPeer::SetTaskRunner(factory_.get(), task_runner.get());
 
   MockQuicData socket_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
-  socket_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
+  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data.AddWrite(ASYNC, ERR_FAILED);              // Write error.
   socket_data.AddRead(ASYNC, ERR_ADDRESS_UNREACHABLE);  // Read error.
   socket_data.AddSocketDataToFactory(socket_factory_.get());
@@ -8156,9 +8089,9 @@
   // response to the request is read on this new socket.
   MockQuicData socket_data1(version_);
   socket_data1.AddWrite(
-      SYNCHRONOUS, ConstructGetRequestPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, &header_stream_offset));
+      SYNCHRONOUS,
+      ConstructGetRequestPacket(
+          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
   socket_data1.AddRead(
       ASYNC,
       ConstructOkResponsePacket(
@@ -8263,10 +8196,8 @@
   crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
 
   MockQuicData socket_data(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
+  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data.AddWrite(write_error_mode, ERR_FAILED);  // Write error.
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
@@ -8318,9 +8249,9 @@
   // response to the request is read on this new socket.
   MockQuicData socket_data1(version_);
   socket_data1.AddWrite(
-      SYNCHRONOUS, ConstructGetRequestPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, &header_stream_offset));
+      SYNCHRONOUS,
+      ConstructGetRequestPacket(
+          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
   socket_data1.AddRead(
       ASYNC,
       ConstructOkResponsePacket(
@@ -8429,21 +8360,25 @@
   quic_data1.AddWrite(SYNCHRONOUS, ERR_ADDRESS_UNREACHABLE);
   quic_data1.AddSocketDataToFactory(socket_factory_.get());
 
+  client_maker_.Reset();
   MockQuicData quic_data2(version_);                // retry count: 2
   quic_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // Hanging read.
   quic_data2.AddWrite(SYNCHRONOUS, ERR_ADDRESS_UNREACHABLE);
   quic_data2.AddSocketDataToFactory(socket_factory_.get());
 
+  client_maker_.Reset();
   MockQuicData quic_data3(version_);                // retry count: 3
   quic_data3.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // Hanging read.
   quic_data3.AddWrite(SYNCHRONOUS, ERR_ADDRESS_UNREACHABLE);
   quic_data3.AddSocketDataToFactory(socket_factory_.get());
 
+  client_maker_.Reset();
   MockQuicData quic_data4(version_);                // retry count: 4
   quic_data4.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // Hanging read.
   quic_data4.AddWrite(SYNCHRONOUS, ERR_ADDRESS_UNREACHABLE);
   quic_data4.AddSocketDataToFactory(socket_factory_.get());
 
+  client_maker_.Reset();
   MockQuicData quic_data5(version_);                // retry count: 5
   quic_data5.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // Hanging read.
   quic_data5.AddWrite(SYNCHRONOUS, ERR_ADDRESS_UNREACHABLE);
@@ -8543,21 +8478,25 @@
   quic_data.AddWrite(SYNCHRONOUS, ERR_ADDRESS_UNREACHABLE);
   quic_data.AddSocketDataToFactory(socket_factory_.get());
 
+  client_maker_.Reset();
   MockQuicData quic_data1(version_);                // retry count: 1
   quic_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // Hanging read.
   quic_data1.AddWrite(SYNCHRONOUS, ERR_ADDRESS_UNREACHABLE);
   quic_data1.AddSocketDataToFactory(socket_factory_.get());
 
+  client_maker_.Reset();
   MockQuicData quic_data2(version_);                // retry count: 2
   quic_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // Hanging read.
   quic_data2.AddWrite(SYNCHRONOUS, ERR_ADDRESS_UNREACHABLE);
   quic_data2.AddSocketDataToFactory(socket_factory_.get());
 
+  client_maker_.Reset();
   MockQuicData quic_data3(version_);                // retry count: 3
   quic_data3.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // Hanging read.
   quic_data3.AddWrite(SYNCHRONOUS, ERR_ADDRESS_UNREACHABLE);
   quic_data3.AddSocketDataToFactory(socket_factory_.get());
 
+  client_maker_.Reset();
   MockQuicData quic_data4(version_);                // retry count: 4
   quic_data4.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // Hanging read.
   quic_data4.AddWrite(SYNCHRONOUS, ERR_ADDRESS_UNREACHABLE);
@@ -8631,14 +8570,12 @@
   crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
 
   MockQuicData socket_data1(version_);
-  quic::QuicStreamOffset header_stream_offset = 0;
   socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+  socket_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data1.AddWrite(
-      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
-  socket_data1.AddWrite(
-      SYNCHRONOUS, ConstructGetRequestPacket(
-                       2, GetNthClientInitiatedBidirectionalStreamId(0), true,
-                       true, &header_stream_offset));
+      SYNCHRONOUS,
+      ConstructGetRequestPacket(
+          2, GetNthClientInitiatedBidirectionalStreamId(0), true, true));
   socket_data1.AddSocketDataToFactory(socket_factory_.get());
 
   // Create request and QuicHttpStream.
@@ -8842,10 +8779,10 @@
   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(1, nullptr));
+  socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data2.AddSocketDataToFactory(socket_factory_.get());
 
   QuicStreamRequest request(factory_.get());
@@ -9023,10 +8960,10 @@
   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(1, nullptr));
+  socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
   socket_data2.AddSocketDataToFactory(socket_factory_.get());
 
   HostPortPair server2(kServer2HostName, kDefaultServerPort);
@@ -9333,6 +9270,7 @@
                        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());
@@ -9562,7 +9500,7 @@
 
   MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
   std::unique_ptr<quic::QuicEncryptedPacket> settings_packet(
-      client_maker_.MakeInitialSettingsPacket(1, nullptr));
+      client_maker_.MakeInitialSettingsPacket(1));
   MockWrite writes[] = {MockWrite(SYNCHRONOUS, settings_packet->data(),
                                   settings_packet->length(), 1)};
   std::unique_ptr<SequencedSocketData> sequenced_socket_data(
@@ -9637,7 +9575,7 @@
 
   MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
   std::unique_ptr<quic::QuicEncryptedPacket> settings_packet(
-      client_maker_.MakeInitialSettingsPacket(1, nullptr));
+      client_maker_.MakeInitialSettingsPacket(1));
   MockWrite writes[] = {MockWrite(SYNCHRONOUS, settings_packet->data(),
                                   settings_packet->length(), 1)};
   std::unique_ptr<SequencedSocketData> sequenced_socket_data(
@@ -9724,7 +9662,7 @@
 
   MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
   std::unique_ptr<quic::QuicEncryptedPacket> settings_packet(
-      client_maker_.MakeInitialSettingsPacket(1, nullptr));
+      client_maker_.MakeInitialSettingsPacket(1));
   MockWrite writes[] = {MockWrite(SYNCHRONOUS, settings_packet->data(),
                                   settings_packet->length(), 1)};
   std::unique_ptr<SequencedSocketData> sequenced_socket_data(
@@ -10488,6 +10426,7 @@
   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());
@@ -10559,6 +10498,7 @@
           2, true, quic::QUIC_STALE_CONNECTION_CANCELLED, "net error"));
   quic_data.AddSocketDataToFactory(socket_factory_.get());
 
+  client_maker_.Reset();
   MockQuicData quic_data2(version_);
   quic_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   quic_data2.AddSocketDataToFactory(socket_factory_.get());
@@ -10631,6 +10571,7 @@
           1, true, quic::QUIC_STALE_CONNECTION_CANCELLED, "net error"));
   quic_data.AddSocketDataToFactory(socket_factory_.get());
 
+  client_maker_.Reset();
   MockQuicData quic_data2(version_);
   quic_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
@@ -10802,6 +10743,7 @@
   quic_data.AddConnect(SYNCHRONOUS, ERR_ADDRESS_IN_USE);
   quic_data.AddSocketDataToFactory(socket_factory_.get());
 
+  client_maker_.Reset();
   MockQuicData quic_data2(version_);
   quic_data2.AddConnect(SYNCHRONOUS, ERR_ADDRESS_IN_USE);
   quic_data2.AddSocketDataToFactory(socket_factory_.get());
@@ -10850,6 +10792,7 @@
   quic_data.AddConnect(SYNCHRONOUS, ERR_ADDRESS_IN_USE);
   quic_data.AddSocketDataToFactory(socket_factory_.get());
 
+  client_maker_.Reset();
   MockQuicData quic_data2(version_);
   quic_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   quic_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
@@ -10913,6 +10856,7 @@
   quic_data.AddSocketDataToFactory(socket_factory_.get());
 
   // Add failure for resolved dns connection.
+  client_maker_.Reset();
   MockQuicData quic_data2(version_);
   quic_data2.AddConnect(SYNCHRONOUS, ERR_ADDRESS_IN_USE);
   quic_data2.AddSocketDataToFactory(socket_factory_.get());
@@ -11108,7 +11052,8 @@
   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, 0));
+  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(3));
+
   socket_data.AddSocketDataToFactory(socket_factory_.get());
 
   QuicStreamRequest request(factory_.get());
@@ -11164,6 +11109,7 @@
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
   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());
diff --git a/net/quic/quic_test_packet_maker.cc b/net/quic/quic_test_packet_maker.cc
index 26dae2b6..679cc06 100644
--- a/net/quic/quic_test_packet_maker.cc
+++ b/net/quic/quic_test_packet_maker.cc
@@ -40,6 +40,7 @@
       host_(host),
       spdy_request_framer_(spdy::SpdyFramer::ENABLE_COMPRESSION),
       spdy_response_framer_(spdy::SpdyFramer::ENABLE_COMPRESSION),
+      header_stream_offset_(0),
       perspective_(perspective),
       encryption_level_(quic::ENCRYPTION_FORWARD_SECURE),
       long_header_type_(quic::INVALID_PACKET_TYPE),
@@ -339,8 +340,7 @@
     spdy::SpdyPriority priority,
     spdy::SpdyHeaderBlock headers,
     quic::QuicStreamId parent_stream_id,
-    size_t* spdy_headers_frame_length,
-    quic::QuicStreamOffset* offset) {
+    size_t* spdy_headers_frame_length) {
   quic::QuicRstStreamFrame rst_frame(1, rst_stream_id, rst_error_code, 0);
 
   spdy::SpdySerializedFrame spdy_frame = MakeSpdyHeadersFrame(
@@ -348,15 +348,11 @@
   if (spdy_headers_frame_length) {
     *spdy_headers_frame_length = spdy_frame.size();
   }
-  quic::QuicStreamOffset header_offset = 0;
-  if (offset != nullptr) {
-    header_offset = *offset;
-    *offset += spdy_frame.size();
-  }
   quic::QuicStreamFrame headers_frame(
       quic::QuicUtils::GetHeadersStreamId(version_.transport_version), false,
-      header_offset,
+      header_stream_offset_,
       quic::QuicStringPiece(spdy_frame.data(), spdy_frame.size()));
+  header_stream_offset_ += spdy_frame.size();
 
   quic::QuicFrames frames;
   frames.push_back(quic::QuicFrame(&rst_frame));
@@ -748,6 +744,16 @@
   return encrypted.Clone();
 }
 
+std::unique_ptr<quic::QuicReceivedPacket>
+QuicTestPacketMaker::MakeHeadersDataPacket(uint64_t packet_number,
+                                           bool should_include_version,
+                                           bool fin,
+                                           quic::QuicStringPiece data) {
+  return MakeDataPacket(
+      packet_number,
+      quic::QuicUtils::GetHeadersStreamId(version_.transport_version),
+      should_include_version, fin, header_stream_offset_, data);
+}
 // Returns a newly created packet to send kData on stream 1.
 std::unique_ptr<quic::QuicReceivedPacket> QuicTestPacketMaker::MakeDataPacket(
     uint64_t packet_number,
@@ -863,7 +869,6 @@
     spdy::SpdyPriority priority,
     spdy::SpdyHeaderBlock headers,
     quic::QuicStreamId parent_stream_id,
-    quic::QuicStreamOffset* header_stream_offset,
     size_t* spdy_headers_frame_length,
     const std::vector<std::string>& data_writes) {
   InitializeHeader(packet_number, should_include_version);
@@ -875,17 +880,13 @@
     *spdy_headers_frame_length = spdy_frame.size();
   }
   quic::QuicFrames frames;
-  quic::QuicStreamOffset header_offset =
-      header_stream_offset == nullptr ? 0 : *header_stream_offset;
   quic::QuicStreamFrame frame(
       quic::QuicUtils::GetHeadersStreamId(version_.transport_version), false,
-      header_offset,
+      header_stream_offset_,
       quic::QuicStringPiece(spdy_frame.data(), spdy_frame.size()));
   frames.push_back(quic::QuicFrame(frame));
   DVLOG(1) << "Adding frame: " << frames.back();
-  if (header_stream_offset != nullptr) {
-    *header_stream_offset += spdy_frame.size();
-  }
+  header_stream_offset_ += spdy_frame.size();
 
   quic::QuicStreamOffset offset = 0;
   // quic::QuicFrame takes a raw pointer. Use a std::vector here so we keep
@@ -912,28 +913,10 @@
     spdy::SpdyHeaderBlock headers,
     quic::QuicStreamId parent_stream_id,
     size_t* spdy_headers_frame_length) {
-  return MakeRequestHeadersPacket(
-      packet_number, stream_id, should_include_version, fin, priority,
-      std::move(headers), parent_stream_id, spdy_headers_frame_length, nullptr);
-}
-
-// If |offset| is provided, will use the value when creating the packet.
-// Will also update the value after packet creation.
-std::unique_ptr<quic::QuicReceivedPacket>
-QuicTestPacketMaker::MakeRequestHeadersPacket(
-    uint64_t packet_number,
-    quic::QuicStreamId stream_id,
-    bool should_include_version,
-    bool fin,
-    spdy::SpdyPriority priority,
-    spdy::SpdyHeaderBlock headers,
-    quic::QuicStreamId parent_stream_id,
-    size_t* spdy_headers_frame_length,
-    quic::QuicStreamOffset* offset) {
   std::string unused_stream_data;
   return MakeRequestHeadersPacketAndSaveData(
       packet_number, stream_id, should_include_version, fin, priority,
-      std::move(headers), parent_stream_id, spdy_headers_frame_length, offset,
+      std::move(headers), parent_stream_id, spdy_headers_frame_length,
       &unused_stream_data);
 }
 
@@ -947,7 +930,6 @@
     spdy::SpdyHeaderBlock headers,
     quic::QuicStreamId parent_stream_id,
     size_t* spdy_headers_frame_length,
-    quic::QuicStreamOffset* offset,
     std::string* stream_data) {
   InitializeHeader(packet_number, should_include_version);
   spdy::SpdySerializedFrame spdy_frame = MakeSpdyHeadersFrame(
@@ -957,19 +939,12 @@
   if (spdy_headers_frame_length)
     *spdy_headers_frame_length = spdy_frame.size();
 
-  if (offset != nullptr) {
-    quic::QuicStreamFrame frame(
-        quic::QuicUtils::GetHeadersStreamId(version_.transport_version), false,
-        *offset, quic::QuicStringPiece(spdy_frame.data(), spdy_frame.size()));
-    *offset += spdy_frame.size();
-    return MakePacket(header_, quic::QuicFrame(frame));
-  } else {
-    quic::QuicStreamFrame frame(
-        quic::QuicUtils::GetHeadersStreamId(version_.transport_version), false,
-        0, quic::QuicStringPiece(spdy_frame.data(), spdy_frame.size()));
-
-    return MakePacket(header_, quic::QuicFrame(frame));
-  }
+  quic::QuicStreamFrame frame(
+      quic::QuicUtils::GetHeadersStreamId(version_.transport_version), false,
+      header_stream_offset_,
+      quic::QuicStringPiece(spdy_frame.data(), spdy_frame.size()));
+  header_stream_offset_ += spdy_frame.size();
+  return MakePacket(header_, quic::QuicFrame(frame));
 }
 
 std::unique_ptr<quic::QuicReceivedPacket>
@@ -982,7 +957,6 @@
     spdy::SpdyHeaderBlock headers,
     quic::QuicStreamId parent_stream_id,
     size_t* spdy_headers_frame_length,
-    quic::QuicStreamOffset* header_stream_offset,
     quic::QuicRstStreamErrorCode error_code,
     size_t bytes_written) {
   spdy::SpdySerializedFrame spdy_frame = MakeSpdyHeadersFrame(
@@ -990,15 +964,11 @@
   if (spdy_headers_frame_length) {
     *spdy_headers_frame_length = spdy_frame.size();
   }
-  quic::QuicStreamOffset header_offset = 0;
-  if (header_stream_offset != nullptr) {
-    header_offset = *header_stream_offset;
-    *header_stream_offset += spdy_frame.size();
-  }
   quic::QuicStreamFrame headers_frame(
       quic::QuicUtils::GetHeadersStreamId(version_.transport_version), false,
-      header_offset,
+      header_stream_offset_,
       quic::QuicStringPiece(spdy_frame.data(), spdy_frame.size()));
+  header_stream_offset_ += spdy_frame.size();
 
   quic::QuicRstStreamFrame rst_frame(1, stream_id, error_code, bytes_written);
 
@@ -1042,25 +1012,6 @@
   return spdy_request_framer_.SerializeFrame(headers_frame);
 }
 
-// Convenience method for calling MakeRequestHeadersPacket with nullptr for
-// |spdy_headers_frame_length|.
-std::unique_ptr<quic::QuicReceivedPacket>
-QuicTestPacketMaker::MakeRequestHeadersPacketWithOffsetTracking(
-    uint64_t packet_number,
-    quic::QuicStreamId stream_id,
-    bool should_include_version,
-    bool fin,
-    spdy::SpdyPriority priority,
-    spdy::SpdyHeaderBlock headers,
-    quic::QuicStreamId parent_stream_id,
-    quic::QuicStreamOffset* offset) {
-  return MakeRequestHeadersPacket(
-      packet_number, stream_id, should_include_version, fin, priority,
-      std::move(headers), parent_stream_id, nullptr, offset);
-}
-
-// If |offset| is provided, will use the value when creating the packet.
-// Will also update the value after packet creation.
 std::unique_ptr<quic::QuicReceivedPacket>
 QuicTestPacketMaker::MakePushPromisePacket(
     uint64_t packet_number,
@@ -1069,8 +1020,7 @@
     bool should_include_version,
     bool fin,
     spdy::SpdyHeaderBlock headers,
-    size_t* spdy_headers_frame_length,
-    quic::QuicStreamOffset* offset) {
+    size_t* spdy_headers_frame_length) {
   InitializeHeader(packet_number, should_include_version);
   spdy::SpdySerializedFrame spdy_frame;
   spdy::SpdyPushPromiseIR promise_frame(stream_id, promised_stream_id,
@@ -1080,18 +1030,12 @@
   if (spdy_headers_frame_length) {
     *spdy_headers_frame_length = spdy_frame.size();
   }
-  if (offset != nullptr) {
-    quic::QuicStreamFrame frame(
-        quic::QuicUtils::GetHeadersStreamId(version_.transport_version), false,
-        *offset, quic::QuicStringPiece(spdy_frame.data(), spdy_frame.size()));
-    *offset += spdy_frame.size();
-    return MakePacket(header_, quic::QuicFrame(frame));
-  } else {
-    quic::QuicStreamFrame frame(
-        quic::QuicUtils::GetHeadersStreamId(version_.transport_version), false,
-        0, quic::QuicStringPiece(spdy_frame.data(), spdy_frame.size()));
-    return MakePacket(header_, quic::QuicFrame(frame));
-  }
+  quic::QuicStreamFrame frame(
+      quic::QuicUtils::GetHeadersStreamId(version_.transport_version), false,
+      header_stream_offset_,
+      quic::QuicStringPiece(spdy_frame.data(), spdy_frame.size()));
+  header_stream_offset_ += spdy_frame.size();
+  return MakePacket(header_, quic::QuicFrame(frame));
 }
 
 std::unique_ptr<quic::QuicReceivedPacket>
@@ -1122,8 +1066,7 @@
     bool should_include_version,
     bool fin,
     spdy::SpdyHeaderBlock headers,
-    size_t* spdy_headers_frame_length,
-    quic::QuicStreamOffset* offset) {
+    size_t* spdy_headers_frame_length) {
   InitializeHeader(packet_number, should_include_version);
   spdy::SpdySerializedFrame spdy_frame;
   spdy::SpdyHeadersIR headers_frame(stream_id, std::move(headers));
@@ -1133,46 +1076,12 @@
   if (spdy_headers_frame_length) {
     *spdy_headers_frame_length = spdy_frame.size();
   }
-  if (offset != nullptr) {
-    quic::QuicStreamFrame frame(
-        quic::QuicUtils::GetHeadersStreamId(version_.transport_version), false,
-        *offset, quic::QuicStringPiece(spdy_frame.data(), spdy_frame.size()));
-    *offset += spdy_frame.size();
-    return MakePacket(header_, quic::QuicFrame(frame));
-  } else {
-    quic::QuicStreamFrame frame(
-        quic::QuicUtils::GetHeadersStreamId(version_.transport_version), false,
-        0, quic::QuicStringPiece(spdy_frame.data(), spdy_frame.size()));
-    return MakePacket(header_, quic::QuicFrame(frame));
-  }
-}
-
-std::unique_ptr<quic::QuicReceivedPacket>
-QuicTestPacketMaker::MakeResponseHeadersPacket(
-    uint64_t packet_number,
-    quic::QuicStreamId stream_id,
-    bool should_include_version,
-    bool fin,
-    spdy::SpdyHeaderBlock headers,
-    size_t* spdy_headers_frame_length) {
-  return MakeResponseHeadersPacket(
-      packet_number, stream_id, should_include_version, fin, std::move(headers),
-      spdy_headers_frame_length, nullptr);
-}
-
-// Convenience method for calling MakeResponseHeadersPacket with nullptr for
-// |spdy_headers_frame_length|.
-std::unique_ptr<quic::QuicReceivedPacket>
-QuicTestPacketMaker::MakeResponseHeadersPacketWithOffsetTracking(
-    uint64_t packet_number,
-    quic::QuicStreamId stream_id,
-    bool should_include_version,
-    bool fin,
-    spdy::SpdyHeaderBlock headers,
-    quic::QuicStreamOffset* offset) {
-  return MakeResponseHeadersPacket(packet_number, stream_id,
-                                   should_include_version, fin,
-                                   std::move(headers), nullptr, offset);
+  quic::QuicStreamFrame frame(
+      quic::QuicUtils::GetHeadersStreamId(version_.transport_version), false,
+      header_stream_offset_,
+      quic::QuicStringPiece(spdy_frame.data(), spdy_frame.size()));
+  header_stream_offset_ += spdy_frame.size();
+  return MakePacket(header_, quic::QuicFrame(frame));
 }
 
 spdy::SpdyHeaderBlock QuicTestPacketMaker::GetRequestHeaders(
@@ -1290,17 +1199,31 @@
 }
 
 std::unique_ptr<quic::QuicReceivedPacket>
-QuicTestPacketMaker::MakeInitialSettingsPacket(uint64_t packet_number,
-                                               quic::QuicStreamOffset* offset) {
+QuicTestPacketMaker::MakeInitialSettingsPacket(uint64_t packet_number) {
   std::string unused_data;
-  return MakeInitialSettingsPacketAndSaveData(packet_number, offset,
-                                              &unused_data);
+  return MakeInitialSettingsPacketAndSaveData(packet_number, &unused_data);
+}
+
+std::unique_ptr<quic::QuicReceivedPacket>
+QuicTestPacketMaker::MakeSettingsPacket(uint64_t packet_number,
+                                        bool should_include_version) {
+  spdy::SpdySettingsIR settings_frame;
+  settings_frame.AddSetting(spdy::SETTINGS_MAX_HEADER_LIST_SIZE,
+                            quic::kDefaultMaxUncompressedHeaderSize);
+  spdy::SpdySerializedFrame spdy_frame(
+      spdy_request_framer_.SerializeFrame(settings_frame));
+  InitializeHeader(packet_number, should_include_version);
+  quic::QuicStreamFrame quic_frame(
+      quic::QuicUtils::GetHeadersStreamId(version_.transport_version), false,
+      header_stream_offset_,
+      quic::QuicStringPiece(spdy_frame.data(), spdy_frame.size()));
+  header_stream_offset_ += spdy_frame.size();
+  return MakePacket(header_, quic::QuicFrame(quic_frame));
 }
 
 std::unique_ptr<quic::QuicReceivedPacket>
 QuicTestPacketMaker::MakeInitialSettingsPacketAndSaveData(
     uint64_t packet_number,
-    quic::QuicStreamOffset* offset,
     std::string* stream_data) {
   spdy::SpdySettingsIR settings_frame;
   settings_frame.AddSetting(spdy::SETTINGS_MAX_HEADER_LIST_SIZE,
@@ -1309,16 +1232,11 @@
       spdy_request_framer_.SerializeFrame(settings_frame));
   InitializeHeader(packet_number, /*should_include_version*/ true);
   *stream_data = std::string(spdy_frame.data(), spdy_frame.size());
-  if (offset != nullptr) {
-    quic::QuicStreamFrame quic_frame(
-        quic::QuicUtils::GetHeadersStreamId(version_.transport_version), false,
-        *offset, quic::QuicStringPiece(spdy_frame.data(), spdy_frame.size()));
-    *offset += spdy_frame.size();
-    return MakePacket(header_, quic::QuicFrame(quic_frame));
-  }
   quic::QuicStreamFrame quic_frame(
-      quic::QuicUtils::GetHeadersStreamId(version_.transport_version), false, 0,
+      quic::QuicUtils::GetHeadersStreamId(version_.transport_version), false,
+      header_stream_offset_,
       quic::QuicStringPiece(spdy_frame.data(), spdy_frame.size()));
+  header_stream_offset_ += spdy_frame.size();
   return MakePacket(header_, quic::QuicFrame(quic_frame));
 }
 
@@ -1327,8 +1245,7 @@
                                         bool should_include_version,
                                         quic::QuicStreamId id,
                                         quic::QuicStreamId parent_stream_id,
-                                        spdy::SpdyPriority priority,
-                                        quic::QuicStreamOffset* offset) {
+                                        spdy::SpdyPriority priority) {
   if (!client_headers_include_h2_stream_dependency_) {
     parent_stream_id = 0;
   }
@@ -1338,15 +1255,11 @@
   spdy::SpdySerializedFrame spdy_frame(
       spdy_request_framer_.SerializeFrame(priority_frame));
 
-  quic::QuicStreamOffset header_offset = 0;
-  if (offset != nullptr) {
-    header_offset = *offset;
-    *offset += spdy_frame.size();
-  }
   quic::QuicStreamFrame quic_frame(
       quic::QuicUtils::GetHeadersStreamId(version_.transport_version), false,
-      header_offset,
+      header_stream_offset_,
       quic::QuicStringPiece(spdy_frame.data(), spdy_frame.size()));
+  header_stream_offset_ += spdy_frame.size();
   DVLOG(1) << "Adding frame: " << quic::QuicFrame(quic_frame);
   InitializeHeader(packet_number, should_include_version);
   return MakePacket(header_, quic::QuicFrame(quic_frame));
@@ -1359,8 +1272,7 @@
     uint64_t largest_received,
     uint64_t smallest_received,
     uint64_t least_unacked,
-    const std::vector<Http2StreamDependency>& priority_frames,
-    quic::QuicStreamOffset* offset) {
+    const std::vector<Http2StreamDependency>& priority_frames) {
   quic::QuicAckFrame ack(MakeAckFrame(largest_received));
   ack.ack_delay_time = quic::QuicTime::Delta::Zero();
   for (uint64_t i = smallest_received; i <= largest_received; ++i) {
@@ -1376,10 +1288,6 @@
   DVLOG(1) << "Adding frame: " << frames.back();
 
   const bool exclusive = client_headers_include_h2_stream_dependency_;
-  quic::QuicStreamOffset header_offset = 0;
-  if (offset == nullptr) {
-    offset = &header_offset;
-  }
   // Keep SpdySerializedFrames alive until MakeMultipleFramesPacket is done.
   std::vector<std::unique_ptr<spdy::SpdySerializedFrame>> spdy_frames;
   for (const Http2StreamDependency& info : priority_frames) {
@@ -1393,8 +1301,9 @@
     spdy::SpdySerializedFrame* spdy_frame = spdy_frames.back().get();
     quic::QuicStreamFrame stream_frame(
         quic::QuicUtils::GetHeadersStreamId(version_.transport_version), false,
-        *offset, quic::QuicStringPiece(spdy_frame->data(), spdy_frame->size()));
-    *offset += spdy_frame->size();
+        header_stream_offset_,
+        quic::QuicStringPiece(spdy_frame->data(), spdy_frame->size()));
+    header_stream_offset_ += spdy_frame->size();
 
     frames.push_back(quic::QuicFrame(stream_frame));
     DVLOG(1) << "Adding frame: " << frames.back();
@@ -1458,5 +1367,9 @@
   return quic::CONNECTION_ID_ABSENT;
 }
 
+void QuicTestPacketMaker::Reset() {
+  header_stream_offset_ = 0;
+}
+
 }  // namespace test
 }  // namespace net
diff --git a/net/quic/quic_test_packet_maker.h b/net/quic/quic_test_packet_maker.h
index 9569b53..5ebdb79 100644
--- a/net/quic/quic_test_packet_maker.h
+++ b/net/quic/quic_test_packet_maker.h
@@ -100,8 +100,7 @@
       spdy::SpdyPriority priority,
       spdy::SpdyHeaderBlock headers,
       quic::QuicStreamId parent_stream_id,
-      size_t* spdy_headers_frame_length,
-      quic::QuicStreamOffset* offset);
+      size_t* spdy_headers_frame_length);
 
   std::unique_ptr<quic::QuicReceivedPacket> MakeAckAndRstPacket(
       uint64_t num,
@@ -187,6 +186,11 @@
       bool fin,
       quic::QuicStreamOffset offset,
       quic::QuicStringPiece data);
+  std::unique_ptr<quic::QuicReceivedPacket> MakeHeadersDataPacket(
+      uint64_t packet_number,
+      bool should_include_version,
+      bool fin,
+      quic::QuicStringPiece data);
   std::unique_ptr<quic::QuicReceivedPacket> MakeForceHolDataPacket(
       uint64_t packet_number,
       quic::QuicStreamId stream_id,
@@ -231,7 +235,6 @@
       spdy::SpdyPriority priority,
       spdy::SpdyHeaderBlock headers,
       quic::QuicStreamId parent_stream_id,
-      quic::QuicStreamOffset* header_stream_offset,
       size_t* spdy_headers_frame_length,
       const std::vector<std::string>& data_writes);
 
@@ -247,17 +250,6 @@
       quic::QuicStreamId parent_stream_id,
       size_t* spdy_headers_frame_length);
 
-  std::unique_ptr<quic::QuicReceivedPacket> MakeRequestHeadersPacket(
-      uint64_t packet_number,
-      quic::QuicStreamId stream_id,
-      bool should_include_version,
-      bool fin,
-      spdy::SpdyPriority priority,
-      spdy::SpdyHeaderBlock headers,
-      quic::QuicStreamId parent_stream_id,
-      size_t* spdy_headers_frame_length,
-      quic::QuicStreamOffset* offset);
-
   // Saves the serialized QUIC stream data in |stream_data|.
   std::unique_ptr<quic::QuicReceivedPacket> MakeRequestHeadersPacketAndSaveData(
       uint64_t packet_number,
@@ -268,7 +260,6 @@
       spdy::SpdyHeaderBlock headers,
       quic::QuicStreamId parent_stream_id,
       size_t* spdy_headers_frame_length,
-      quic::QuicStreamOffset* offset,
       std::string* stream_data);
 
   std::unique_ptr<quic::QuicReceivedPacket> MakeRequestHeadersAndRstPacket(
@@ -280,23 +271,9 @@
       spdy::SpdyHeaderBlock headers,
       quic::QuicStreamId parent_stream_id,
       size_t* spdy_headers_frame_length,
-      quic::QuicStreamOffset* header_stream_offset,
       quic::QuicRstStreamErrorCode error_code,
       size_t bytes_written);
 
-  // Convenience method for calling MakeRequestHeadersPacket with nullptr for
-  // |spdy_headers_frame_length|.
-  std::unique_ptr<quic::QuicReceivedPacket>
-  MakeRequestHeadersPacketWithOffsetTracking(
-      uint64_t packet_number,
-      quic::QuicStreamId stream_id,
-      bool should_include_version,
-      bool fin,
-      spdy::SpdyPriority priority,
-      spdy::SpdyHeaderBlock headers,
-      quic::QuicStreamId parent_stream_id,
-      quic::QuicStreamOffset* offset);
-
   // If |spdy_headers_frame_length| is non-null, it will be set to the size of
   // the SPDY headers frame created for this packet.
   std::unique_ptr<quic::QuicReceivedPacket> MakePushPromisePacket(
@@ -306,8 +283,7 @@
       bool should_include_version,
       bool fin,
       spdy::SpdyHeaderBlock headers,
-      size_t* spdy_headers_frame_length,
-      quic::QuicStreamOffset* offset);
+      size_t* spdy_headers_frame_length);
 
   // If |spdy_headers_frame_length| is non-null, it will be set to the size of
   // the SPDY headers frame created for this packet.
@@ -317,38 +293,21 @@
       bool should_include_version,
       bool fin,
       spdy::SpdyHeaderBlock headers,
-      size_t* spdy_headers_frame_length,
-      quic::QuicStreamOffset* offset);
-
-  std::unique_ptr<quic::QuicReceivedPacket> MakeResponseHeadersPacket(
-      uint64_t packet_number,
-      quic::QuicStreamId stream_id,
-      bool should_include_version,
-      bool fin,
-      spdy::SpdyHeaderBlock headers,
       size_t* spdy_headers_frame_length);
 
-  // Convenience method for calling MakeResponseHeadersPacket with nullptr for
-  // |spdy_headers_frame_length|.
-  std::unique_ptr<quic::QuicReceivedPacket>
-  MakeResponseHeadersPacketWithOffsetTracking(uint64_t packet_number,
-                                              quic::QuicStreamId stream_id,
-                                              bool should_include_version,
-                                              bool fin,
-                                              spdy::SpdyHeaderBlock headers,
-                                              quic::QuicStreamOffset* offset);
-
   // Creates a packet containing the initial SETTINGS frame, and saves the
   // headers stream offset into |offset|.
   std::unique_ptr<quic::QuicReceivedPacket> MakeInitialSettingsPacket(
+      uint64_t packet_number);
+
+  std::unique_ptr<quic::QuicReceivedPacket> MakeSettingsPacket(
       uint64_t packet_number,
-      quic::QuicStreamOffset* offset);
+      bool should_include_version);
 
   // Same as above, but also saves the serialized QUIC stream data in
   // |stream_data|.
   std::unique_ptr<quic::QuicReceivedPacket>
   MakeInitialSettingsPacketAndSaveData(uint64_t packet_number,
-                                       quic::QuicStreamOffset* offset,
                                        std::string* stream_data);
 
   std::unique_ptr<quic::QuicReceivedPacket> MakePriorityPacket(
@@ -356,8 +315,7 @@
       bool should_include_version,
       quic::QuicStreamId id,
       quic::QuicStreamId parent_stream_id,
-      spdy::SpdyPriority priority,
-      quic::QuicStreamOffset* offset);
+      spdy::SpdyPriority priority);
 
   std::unique_ptr<quic::QuicReceivedPacket>
   MakeAckAndMultiplePriorityFramesPacket(
@@ -366,8 +324,7 @@
       uint64_t largest_received,
       uint64_t smallest_received,
       uint64_t least_unacked,
-      const std::vector<Http2StreamDependency>& priority_frames,
-      quic::QuicStreamOffset* offset);
+      const std::vector<Http2StreamDependency>& priority_frames);
 
   void SetEncryptionLevel(quic::EncryptionLevel level);
 
@@ -385,6 +342,16 @@
   spdy::SpdyFramer* spdy_request_framer() { return &spdy_request_framer_; }
   spdy::SpdyFramer* spdy_response_framer() { return &spdy_response_framer_; }
 
+  void Reset();
+
+  quic::QuicStreamOffset header_stream_offset() const {
+    return header_stream_offset_;
+  }
+
+  void set_header_stream_offset(quic::QuicStreamOffset offset) {
+    header_stream_offset_ = offset;
+  }
+
  private:
   std::unique_ptr<quic::QuicReceivedPacket> MakePacket(
       const quic::QuicPacketHeader& header,
@@ -417,6 +384,7 @@
   spdy::SpdyFramer spdy_request_framer_;
   spdy::SpdyFramer spdy_response_framer_;
   quic::test::MockRandom random_generator_;
+  quic::QuicStreamOffset header_stream_offset_;
   quic::QuicPacketHeader header_;
   quic::Perspective perspective_;
   quic::EncryptionLevel encryption_level_;
diff --git a/services/audio/group_coordinator-impl.h b/services/audio/group_coordinator-impl.h
index 6e10c3b..5c3b540 100644
--- a/services/audio/group_coordinator-impl.h
+++ b/services/audio/group_coordinator-impl.h
@@ -42,7 +42,7 @@
 
   const auto it = FindGroup(group_id);
   std::vector<Member*>& members = it->second.members;
-  DCHECK(!base::ContainsValue(members, member));
+  DCHECK(!base::Contains(members, member));
   members.push_back(member);
   DCHECK_INCREMENT_MUTATION_COUNT();
   DCHECK_REMEMBER_CURRENT_MUTATION_COUNT();
@@ -84,7 +84,7 @@
   DCHECK(observer);
 
   std::vector<Observer*>& observers = FindGroup(group_id)->second.observers;
-  DCHECK(!base::ContainsValue(observers, observer));
+  DCHECK(!base::Contains(observers, observer));
   observers.push_back(observer);
   DCHECK_INCREMENT_MUTATION_COUNT();
 }
diff --git a/services/audio/group_coordinator_unittest.cc b/services/audio/group_coordinator_unittest.cc
index 91b81c5..8dbdfb9 100644
--- a/services/audio/group_coordinator_unittest.cc
+++ b/services/audio/group_coordinator_unittest.cc
@@ -72,8 +72,8 @@
   const std::vector<MockGroupMember*>& members =
       coordinator.GetCurrentMembers(group_id);
   EXPECT_EQ(2u, members.size());
-  EXPECT_TRUE(base::ContainsValue(members, &member1));
-  EXPECT_TRUE(base::ContainsValue(members, &member2));
+  EXPECT_TRUE(base::Contains(members, &member1));
+  EXPECT_TRUE(base::Contains(members, &member2));
   EXPECT_TRUE(
       coordinator.GetCurrentMembers(UnguessableToken::Create()).empty());
 
@@ -120,8 +120,8 @@
   const std::vector<MockGroupMember*>& members_a =
       coordinator.GetCurrentMembers(group_id_a);
   EXPECT_EQ(2u, members_a.size());
-  EXPECT_TRUE(base::ContainsValue(members_a, &member_a_1));
-  EXPECT_TRUE(base::ContainsValue(members_a, &member_a_2));
+  EXPECT_TRUE(base::Contains(members_a, &member_a_1));
+  EXPECT_TRUE(base::Contains(members_a, &member_a_2));
   EXPECT_EQ(std::vector<MockGroupMember*>({&member_b_1}),
             coordinator.GetCurrentMembers(group_id_b));
   EXPECT_TRUE(
@@ -155,8 +155,8 @@
   const std::vector<MockGroupMember*>& members =
       coordinator.GetCurrentMembers(group_id);
   EXPECT_EQ(2u, members.size());
-  EXPECT_TRUE(base::ContainsValue(members, &member1));
-  EXPECT_TRUE(base::ContainsValue(members, &member2));
+  EXPECT_TRUE(base::Contains(members, &member1));
+  EXPECT_TRUE(base::Contains(members, &member2));
   EXPECT_TRUE(
       coordinator.GetCurrentMembers(UnguessableToken::Create()).empty());
 
@@ -191,8 +191,8 @@
   const std::vector<MockGroupMember*>& members =
       coordinator.GetCurrentMembers(group_id);
   EXPECT_EQ(2u, members.size());
-  EXPECT_TRUE(base::ContainsValue(members, &member1));
-  EXPECT_TRUE(base::ContainsValue(members, &member2));
+  EXPECT_TRUE(base::Contains(members, &member1));
+  EXPECT_TRUE(base::Contains(members, &member2));
 
   coordinator.UnregisterMember(group_id, &member1);
   EXPECT_EQ(std::vector<MockGroupMember*>({&member2}),
diff --git a/services/audio/loopback_stream.cc b/services/audio/loopback_stream.cc
index fed7bb1..2160fc3 100644
--- a/services/audio/loopback_stream.cc
+++ b/services/audio/loopback_stream.cc
@@ -262,7 +262,7 @@
   if (inputs_.empty()) {
     HelpDiagnoseCauseOfLoopbackCrash("adding first input");
   }
-  DCHECK(!base::ContainsValue(inputs_, node));
+  DCHECK(!base::Contains(inputs_, node));
   inputs_.push_back(node);
 }
 
diff --git a/services/audio/output_controller.cc b/services/audio/output_controller.cc
index cf04797..faf7e55 100644
--- a/services/audio/output_controller.cc
+++ b/services/audio/output_controller.cc
@@ -498,7 +498,7 @@
 
   // The list will only update on this thread, and only be read on the realtime
   // audio thread.
-  DCHECK(!base::ContainsValue(snoopers_, snooper));
+  DCHECK(!base::Contains(snoopers_, snooper));
   base::AutoLock lock(snooper_lock_);
   snoopers_.push_back(snooper);
 }
diff --git a/services/device/bluetooth/bluetooth_system_unittest.cc b/services/device/bluetooth/bluetooth_system_unittest.cc
index 41b7d14..7239df9 100644
--- a/services/device/bluetooth/bluetooth_system_unittest.cc
+++ b/services/device/bluetooth/bluetooth_system_unittest.cc
@@ -168,12 +168,11 @@
                          base::Unretained(this), object_path)));
     DCHECK(was_inserted);
 
-    DCHECK(
-        !base::ContainsKey(adapter_object_paths_to_call_counts_, object_path));
+    DCHECK(!base::Contains(adapter_object_paths_to_call_counts_, object_path));
     adapter_object_paths_to_call_counts_[object_path];
 
-    DCHECK(!base::ContainsKey(adapter_object_paths_to_next_responses_,
-                              object_path));
+    DCHECK(
+        !base::Contains(adapter_object_paths_to_next_responses_, object_path));
     adapter_object_paths_to_next_responses_[object_path];
 
     GetProperties(object_path)->powered.ReplaceValue(false);
@@ -342,12 +341,11 @@
 
   void StartDiscovery(const dbus::ObjectPath& object_path,
                       ResponseCallback callback) override {
-    DCHECK(
-        base::ContainsKey(adapter_object_paths_to_call_counts_, object_path));
+    DCHECK(base::Contains(adapter_object_paths_to_call_counts_, object_path));
     ++adapter_object_paths_to_call_counts_[object_path].start_discovery;
 
-    DCHECK(base::ContainsKey(adapter_object_paths_to_next_responses_,
-                             object_path));
+    DCHECK(
+        base::Contains(adapter_object_paths_to_next_responses_, object_path));
 
     base::Optional<bool> response;
     response.swap(
@@ -362,12 +360,11 @@
 
   void StopDiscovery(const dbus::ObjectPath& object_path,
                      ResponseCallback callback) override {
-    DCHECK(
-        base::ContainsKey(adapter_object_paths_to_call_counts_, object_path));
+    DCHECK(base::Contains(adapter_object_paths_to_call_counts_, object_path));
     ++adapter_object_paths_to_call_counts_[object_path].stop_discovery;
 
-    DCHECK(base::ContainsKey(adapter_object_paths_to_next_responses_,
-                             object_path));
+    DCHECK(
+        base::Contains(adapter_object_paths_to_next_responses_, object_path));
 
     base::Optional<bool> response;
     response.swap(
diff --git a/services/device/generic_sensor/linux/sensor_device_manager.cc b/services/device/generic_sensor/linux/sensor_device_manager.cc
index 3e3b708..a5a02e6 100644
--- a/services/device/generic_sensor/linux/sensor_device_manager.cc
+++ b/services/device/generic_sensor/linux/sensor_device_manager.cc
@@ -137,7 +137,7 @@
     }
 
     // Update own cache of known sensor devices.
-    if (!base::ContainsKey(sensors_by_node_, device_node))
+    if (!base::Contains(sensors_by_node_, device_node))
       sensors_by_node_[device_node] = data.type;
 
     std::unique_ptr<SensorInfoLinux> device(new SensorInfoLinux(
diff --git a/services/device/generic_sensor/platform_sensor_fusion_algorithm.cc b/services/device/generic_sensor/platform_sensor_fusion_algorithm.cc
index e83da71..d9a5da4 100644
--- a/services/device/generic_sensor/platform_sensor_fusion_algorithm.cc
+++ b/services/device/generic_sensor/platform_sensor_fusion_algorithm.cc
@@ -33,7 +33,7 @@
 bool PlatformSensorFusionAlgorithm::GetFusedData(
     mojom::SensorType which_sensor_changed,
     SensorReading* fused_reading) {
-  DCHECK(base::ContainsValue(source_types_, which_sensor_changed));
+  DCHECK(base::Contains(source_types_, which_sensor_changed));
   return GetFusedDataInternal(which_sensor_changed, fused_reading);
 }
 
diff --git a/services/device/generic_sensor/platform_sensor_provider_linux.cc b/services/device/generic_sensor/platform_sensor_provider_linux.cc
index 57e01dba..1d447a3 100644
--- a/services/device/generic_sensor/platform_sensor_provider_linux.cc
+++ b/services/device/generic_sensor/platform_sensor_provider_linux.cc
@@ -183,7 +183,7 @@
     std::unique_ptr<SensorInfoLinux> sensor_device) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   // At the moment, we support only one device per type.
-  if (base::ContainsKey(sensor_devices_by_type_, type)) {
+  if (base::Contains(sensor_devices_by_type_, type)) {
     DVLOG(1) << "Sensor ignored. Type " << type
              << ". Node: " << sensor_device->device_node;
     return;
diff --git a/services/device/hid/hid_connection.cc b/services/device/hid/hid_connection.cc
index fe12348..cf8e9c426 100644
--- a/services/device/hid/hid_connection.cc
+++ b/services/device/hid/hid_connection.cc
@@ -28,7 +28,7 @@
     if (report_id_ == HidConnection::kAnyReportId)
       return true;
 
-    return base::ContainsValue(info->report_ids, report_id_);
+    return base::Contains(info->report_ids, report_id_);
   }
 
  private:
diff --git a/services/device/hid/hid_service.cc b/services/device/hid/hid_service.cc
index 95465f4..f367372 100644
--- a/services/device/hid/hid_service.cc
+++ b/services/device/hid/hid_service.cc
@@ -101,7 +101,7 @@
   if (!device_guid.empty()) {
     HID_LOG(USER) << "HID device removed: deviceId='" << platform_device_id
                   << "'";
-    DCHECK(base::ContainsKey(devices_, device_guid));
+    DCHECK(base::Contains(devices_, device_guid));
 
     scoped_refptr<HidDeviceInfo> device_info = devices_[device_guid];
     if (enumeration_ready_) {
diff --git a/services/device/media_transfer_protocol/mtp_device_manager.cc b/services/device/media_transfer_protocol/mtp_device_manager.cc
index 1bc49be..139a0643 100644
--- a/services/device/media_transfer_protocol/mtp_device_manager.cc
+++ b/services/device/media_transfer_protocol/mtp_device_manager.cc
@@ -87,7 +87,7 @@
     const std::string& storage_name,
     GetStorageInfoFromDeviceCallback callback) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  if (!base::ContainsKey(storage_info_map_, storage_name) || !mtp_client_) {
+  if (!base::Contains(storage_info_map_, storage_name) || !mtp_client_) {
     std::move(callback).Run(nullptr, true /* error */);
     return;
   }
@@ -104,7 +104,7 @@
                                    const std::string& mode,
                                    OpenStorageCallback callback) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  if (!base::ContainsKey(storage_info_map_, storage_name) || !mtp_client_) {
+  if (!base::Contains(storage_info_map_, storage_name) || !mtp_client_) {
     std::move(callback).Run(std::string(), true);
     return;
   }
@@ -119,7 +119,7 @@
 void MtpDeviceManager::CloseStorage(const std::string& storage_handle,
                                     CloseStorageCallback callback) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  if (!base::ContainsKey(handles_, storage_handle) || !mtp_client_) {
+  if (!base::Contains(handles_, storage_handle) || !mtp_client_) {
     std::move(callback).Run(true);
     return;
   }
@@ -138,7 +138,7 @@
                                        const std::string& directory_name,
                                        CreateDirectoryCallback callback) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  if (!base::ContainsKey(handles_, storage_handle) || !mtp_client_) {
+  if (!base::Contains(handles_, storage_handle) || !mtp_client_) {
     std::move(callback).Run(true /* error */);
     return;
   }
@@ -156,7 +156,7 @@
     uint32_t file_id,
     ReadDirectoryEntryIdsCallback callback) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  if (!base::ContainsKey(handles_, storage_handle) || !mtp_client_) {
+  if (!base::Contains(handles_, storage_handle) || !mtp_client_) {
     std::move(callback).Run(std::vector<uint32_t>(), /*error=*/true);
     return;
   }
@@ -175,7 +175,7 @@
                                      uint32_t count,
                                      ReadFileChunkCallback callback) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  if (!base::ContainsKey(handles_, storage_handle) || !mtp_client_) {
+  if (!base::Contains(handles_, storage_handle) || !mtp_client_) {
     std::move(callback).Run(std::string(), true);
     return;
   }
@@ -191,7 +191,7 @@
                                    const std::vector<uint32_t>& file_ids,
                                    GetFileInfoCallback callback) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  if (!base::ContainsKey(handles_, storage_handle) || !mtp_client_) {
+  if (!base::Contains(handles_, storage_handle) || !mtp_client_) {
     std::move(callback).Run(std::vector<device::mojom::MtpFileEntryPtr>(),
                             /*error=*/true);
     return;
@@ -209,7 +209,7 @@
                                     const std::string& new_name,
                                     RenameObjectCallback callback) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  if (!base::ContainsKey(handles_, storage_handle) || !mtp_client_) {
+  if (!base::Contains(handles_, storage_handle) || !mtp_client_) {
     std::move(callback).Run(true /* error */);
     return;
   }
@@ -228,7 +228,7 @@
                                          const std::string& file_name,
                                          CopyFileFromLocalCallback callback) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  if (!base::ContainsKey(handles_, storage_handle) || !mtp_client_) {
+  if (!base::Contains(handles_, storage_handle) || !mtp_client_) {
     std::move(callback).Run(true /* error */);
     return;
   }
@@ -245,7 +245,7 @@
                                     uint32_t object_id,
                                     DeleteObjectCallback callback) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  if (!base::ContainsKey(handles_, storage_handle) || !mtp_client_) {
+  if (!base::Contains(handles_, storage_handle) || !mtp_client_) {
     std::move(callback).Run(true /* error */);
     return;
   }
@@ -298,7 +298,7 @@
   DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(mtp_client_);
   for (const auto& name : storage_names) {
-    if (base::ContainsKey(storage_info_map_, name)) {
+    if (base::Contains(storage_info_map_, name)) {
       // OnStorageChanged() might have gotten called first.
       continue;
     }
@@ -310,7 +310,7 @@
     const mojom::MtpStorageInfo& storage_info) {
   DCHECK(thread_checker_.CalledOnValidThread());
   const std::string& storage_name = storage_info.storage_name;
-  if (base::ContainsKey(storage_info_map_, storage_name)) {
+  if (base::Contains(storage_info_map_, storage_name)) {
     // This should not happen, since MtpDeviceManager should
     // only call EnumerateStorages() once, which populates |storage_info_map_|
     // with the already-attached devices.
@@ -345,7 +345,7 @@
 
 void MtpDeviceManager::OnOpenStorage(const std::string& handle) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  if (!base::ContainsKey(handles_, handle)) {
+  if (!base::Contains(handles_, handle)) {
     handles_.insert(handle);
     std::move(open_storage_callbacks_.front()).Run(handle, false);
   } else {
@@ -363,7 +363,7 @@
 void MtpDeviceManager::OnCloseStorage() {
   DCHECK(thread_checker_.CalledOnValidThread());
   const std::string& handle = close_storage_callbacks_.front().second;
-  if (base::ContainsKey(handles_, handle)) {
+  if (base::Contains(handles_, handle)) {
     handles_.erase(handle);
     std::move(close_storage_callbacks_.front().first).Run(false);
   } else {
diff --git a/services/device/public/cpp/hid/fake_hid_manager.cc b/services/device/public/cpp/hid/fake_hid_manager.cc
index 42d9813..8a67f31 100644
--- a/services/device/public/cpp/hid/fake_hid_manager.cc
+++ b/services/device/public/cpp/hid/fake_hid_manager.cc
@@ -120,7 +120,7 @@
 void FakeHidManager::Connect(const std::string& device_guid,
                              mojom::HidConnectionClientPtr connection_client,
                              ConnectCallback callback) {
-  if (!base::ContainsKey(devices_, device_guid)) {
+  if (!base::Contains(devices_, device_guid)) {
     std::move(callback).Run(nullptr);
     return;
   }
@@ -160,7 +160,7 @@
 }
 
 void FakeHidManager::RemoveDevice(const std::string& guid) {
-  if (base::ContainsKey(devices_, guid)) {
+  if (base::Contains(devices_, guid)) {
     mojom::HidDeviceInfo* device_info = devices_[guid].get();
     clients_.ForAllPtrs([device_info](mojom::HidManagerClient* client) {
       client->DeviceRemoved(device_info->Clone());
diff --git a/services/device/public/cpp/test/fake_usb_device_manager.cc b/services/device/public/cpp/test/fake_usb_device_manager.cc
index 16294af..db59084 100644
--- a/services/device/public/cpp/test/fake_usb_device_manager.cc
+++ b/services/device/public/cpp/test/fake_usb_device_manager.cc
@@ -102,7 +102,7 @@
 mojom::UsbDeviceInfoPtr FakeUsbDeviceManager::AddDevice(
     scoped_refptr<FakeUsbDeviceInfo> device) {
   DCHECK(device);
-  DCHECK(!base::ContainsKey(devices_, device->guid()));
+  DCHECK(!base::Contains(devices_, device->guid()));
   devices_[device->guid()] = device;
   auto device_info = device->GetDeviceInfo().Clone();
 
@@ -117,7 +117,7 @@
 void FakeUsbDeviceManager::RemoveDevice(
     scoped_refptr<FakeUsbDeviceInfo> device) {
   DCHECK(device);
-  DCHECK(base::ContainsKey(devices_, device->guid()));
+  DCHECK(base::Contains(devices_, device->guid()));
 
   auto device_info = device->GetDeviceInfo().Clone();
   devices_.erase(device->guid());
@@ -149,7 +149,7 @@
 
 bool FakeUsbDeviceManager::SetMockForDevice(const std::string& guid,
                                             MockUsbMojoDevice* mock_device) {
-  if (!base::ContainsKey(devices_, guid))
+  if (!base::Contains(devices_, guid))
     return false;
 
   devices_[guid]->SetMockDevice(mock_device);
diff --git a/services/device/serial/fake_serial_device_enumerator.cc b/services/device/serial/fake_serial_device_enumerator.cc
index b3b8af68..2507d8e 100644
--- a/services/device/serial/fake_serial_device_enumerator.cc
+++ b/services/device/serial/fake_serial_device_enumerator.cc
@@ -15,7 +15,7 @@
 FakeSerialEnumerator::~FakeSerialEnumerator() = default;
 
 bool FakeSerialEnumerator::AddDevicePath(const base::FilePath& path) {
-  if (base::ContainsValue(device_paths_, path))
+  if (base::Contains(device_paths_, path))
     return false;
 
   device_paths_.push_back(path);
diff --git a/services/device/usb/mojo/device_impl_unittest.cc b/services/device/usb/mojo/device_impl_unittest.cc
index 0cd64fc..e23728e 100644
--- a/services/device/usb/mojo/device_impl_unittest.cc
+++ b/services/device/usb/mojo/device_impl_unittest.cc
@@ -228,7 +228,7 @@
 
   void AddMockConfig(const ConfigBuilder& builder) {
     const UsbConfigDescriptor& config = builder.config();
-    DCHECK(!base::ContainsKey(mock_configs_, config.configuration_value));
+    DCHECK(!base::Contains(mock_configs_, config.configuration_value));
     mock_configs_.insert(std::make_pair(config.configuration_value, config));
     mock_device_->AddMockConfig(config);
   }
@@ -293,7 +293,7 @@
 
   void ReleaseInterface(uint8_t interface_number,
                         UsbDeviceHandle::ResultCallback& callback) {
-    if (base::ContainsKey(claimed_interfaces_, interface_number)) {
+    if (base::Contains(claimed_interfaces_, interface_number)) {
       claimed_interfaces_.erase(interface_number);
       std::move(callback).Run(true);
     } else {
diff --git a/services/device/usb/usb_device_handle_impl.cc b/services/device/usb/usb_device_handle_impl.cc
index 7a9c7c9f..d76d96f 100644
--- a/services/device/usb/usb_device_handle_impl.cc
+++ b/services/device/usb/usb_device_handle_impl.cc
@@ -564,7 +564,7 @@
     std::move(callback).Run(false);
     return;
   }
-  if (base::ContainsKey(claimed_interfaces_, interface_number)) {
+  if (base::Contains(claimed_interfaces_, interface_number)) {
     std::move(callback).Run(true);
     return;
   }
@@ -578,7 +578,7 @@
                                            ResultCallback callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  if (!device_ || !base::ContainsKey(claimed_interfaces_, interface_number)) {
+  if (!device_ || !base::Contains(claimed_interfaces_, interface_number)) {
     task_runner_->PostTask(FROM_HERE,
                            base::BindOnce(std::move(callback), false));
     return;
@@ -606,7 +606,7 @@
     ResultCallback callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  if (!device_ || !base::ContainsKey(claimed_interfaces_, interface_number)) {
+  if (!device_ || !base::Contains(claimed_interfaces_, interface_number)) {
     std::move(callback).Run(false);
     return;
   }
@@ -1046,8 +1046,7 @@
 void UsbDeviceHandleImpl::TransferComplete(Transfer* transfer,
                                            base::OnceClosure callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  DCHECK(base::ContainsKey(transfers_, transfer))
-      << "Missing transfer completed";
+  DCHECK(base::Contains(transfers_, transfer)) << "Missing transfer completed";
   transfers_.erase(transfer);
 
   std::move(callback).Run();
diff --git a/services/device/usb/usb_device_handle_usbfs.cc b/services/device/usb/usb_device_handle_usbfs.cc
index e40ba78..0204bd6 100644
--- a/services/device/usb/usb_device_handle_usbfs.cc
+++ b/services/device/usb/usb_device_handle_usbfs.cc
@@ -485,7 +485,7 @@
     return;
   }
 
-  if (base::ContainsKey(interfaces_, interface_number)) {
+  if (base::Contains(interfaces_, interface_number)) {
     USB_LOG(DEBUG) << "Interface " << interface_number << " already claimed.";
     task_runner_->PostTask(FROM_HERE,
                            base::BindOnce(std::move(callback), false));
diff --git a/services/device/usb/usb_service_impl.cc b/services/device/usb/usb_service_impl.cc
index d22dd85..975bc33 100644
--- a/services/device/usb/usb_service_impl.cc
+++ b/services/device/usb/usb_service_impl.cc
@@ -346,7 +346,7 @@
   // Look for new and existing devices.
   for (auto& device : *devices) {
     // Ignore devices that have failed enumeration previously.
-    if (base::ContainsValue(ignored_devices_, device.get()))
+    if (base::Contains(ignored_devices_, device.get()))
       continue;
 
     auto it = platform_devices_.find(device.get());
@@ -465,16 +465,15 @@
 
 void UsbServiceImpl::AddDevice(const base::Closure& refresh_complete,
                                scoped_refptr<UsbDeviceImpl> device) {
-  if (!base::ContainsKey(devices_being_enumerated_,
-                         device->platform_device())) {
+  if (!base::Contains(devices_being_enumerated_, device->platform_device())) {
     // Device was removed while being enumerated.
     refresh_complete.Run();
     return;
   }
 
-  DCHECK(!base::ContainsKey(platform_devices_, device->platform_device()));
+  DCHECK(!base::Contains(platform_devices_, device->platform_device()));
   platform_devices_[device->platform_device()] = device;
-  DCHECK(!base::ContainsKey(devices(), device->guid()));
+  DCHECK(!base::Contains(devices(), device->guid()));
   devices()[device->guid()] = device;
 
   USB_LOG(USER) << "USB device added: vendor=" << device->vendor_id() << " \""
@@ -536,7 +535,7 @@
 void UsbServiceImpl::OnPlatformDeviceAdded(
     ScopedLibusbDeviceRef platform_device) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  DCHECK(!base::ContainsKey(platform_devices_, platform_device.get()));
+  DCHECK(!base::Contains(platform_devices_, platform_device.get()));
   EnumerateDevice(std::move(platform_device), base::DoNothing());
 }
 
diff --git a/services/device/usb/usb_service_linux.cc b/services/device/usb/usb_service_linux.cc
index 688f1d46..2868bb2 100644
--- a/services/device/usb/usb_service_linux.cc
+++ b/services/device/usb/usb_service_linux.cc
@@ -278,7 +278,7 @@
   if (it == devices_by_path_.end()) {
     success = false;
   } else if (success) {
-    DCHECK(!base::ContainsKey(devices(), device->guid()));
+    DCHECK(!base::Contains(devices(), device->guid()));
     devices()[device->guid()] = device;
 
     USB_LOG(USER) << "USB device added: path=" << device->device_path()
diff --git a/services/device/usb/usb_service_win.cc b/services/device/usb/usb_service_win.cc
index 1905f8b..4f47f16 100644
--- a/services/device/usb/usb_service_win.cc
+++ b/services/device/usb/usb_service_win.cc
@@ -396,7 +396,7 @@
   if (it == devices_by_path_.end()) {
     success = false;
   } else if (success) {
-    DCHECK(!base::ContainsKey(devices(), device->guid()));
+    DCHECK(!base::Contains(devices(), device->guid()));
     devices()[device->guid()] = device;
 
     USB_LOG(USER) << "USB device added: path=" << device->device_path()
diff --git a/services/identity/public/cpp/primary_account_mutator_unittest.cc b/services/identity/public/cpp/primary_account_mutator_unittest.cc
index f6048c7b..7ee1a1ad 100644
--- a/services/identity/public/cpp/primary_account_mutator_unittest.cc
+++ b/services/identity/public/cpp/primary_account_mutator_unittest.cc
@@ -189,20 +189,20 @@
           former_primary_account.account_id));
       EXPECT_TRUE(identity_manager->HasAccountWithRefreshToken(
           secondary_account_info.account_id));
-      EXPECT_TRUE(base::ContainsKey(observed_removals,
-                                    former_primary_account.account_id.id));
-      EXPECT_FALSE(base::ContainsKey(observed_removals,
-                                     secondary_account_info.account_id.id));
+      EXPECT_TRUE(base::Contains(observed_removals,
+                                 former_primary_account.account_id.id));
+      EXPECT_FALSE(base::Contains(observed_removals,
+                                  secondary_account_info.account_id.id));
       break;
     case RemoveAccountExpectation::kRemoveAll:
       EXPECT_FALSE(identity_manager->HasAccountWithRefreshToken(
           former_primary_account.account_id));
       EXPECT_FALSE(identity_manager->HasAccountWithRefreshToken(
           secondary_account_info.account_id));
-      EXPECT_TRUE(base::ContainsKey(observed_removals,
-                                    former_primary_account.account_id.id));
-      EXPECT_TRUE(base::ContainsKey(observed_removals,
-                                    secondary_account_info.account_id.id));
+      EXPECT_TRUE(base::Contains(observed_removals,
+                                 former_primary_account.account_id.id));
+      EXPECT_TRUE(base::Contains(observed_removals,
+                                 secondary_account_info.account_id.id));
       break;
   }
 }
diff --git a/services/image_annotation/annotator.cc b/services/image_annotation/annotator.cc
index d3750ab4..21927540 100644
--- a/services/image_annotation/annotator.cc
+++ b/services/image_annotation/annotator.cc
@@ -404,8 +404,8 @@
                      true /* canceled */));
 
   // Don't start local work if it would duplicate some already-ongoing work.
-  if (base::ContainsKey(local_processors_, request_key) ||
-      base::ContainsKey(pending_requests_, request_key))
+  if (base::Contains(local_processors_, request_key) ||
+      base::Contains(pending_requests_, request_key))
     return;
 
   local_processors_.insert(
diff --git a/services/media_session/media_controller.cc b/services/media_session/media_controller.cc
index 32a3665..5f267ba 100644
--- a/services/media_session/media_controller.cc
+++ b/services/media_session/media_controller.cc
@@ -199,7 +199,7 @@
       // No image of this type is available from the session so we should clear
       // any image the observers might have.
       holder->ClearImage();
-    } else if (base::ContainsKey(types_changed, holder->type())) {
+    } else if (base::Contains(types_changed, holder->type())) {
       holder->ImagesChanged(it->second);
     }
   }
diff --git a/services/media_session/public/cpp/test/mock_media_session.cc b/services/media_session/public/cpp/test/mock_media_session.cc
index 9b930f3..7d774d6a 100644
--- a/services/media_session/public/cpp/test/mock_media_session.cc
+++ b/services/media_session/public/cpp/test/mock_media_session.cc
@@ -349,7 +349,7 @@
 }
 
 void MockMediaSession::EnableAction(mojom::MediaSessionAction action) {
-  if (base::ContainsKey(actions_, action))
+  if (base::Contains(actions_, action))
     return;
 
   actions_.insert(action);
@@ -357,7 +357,7 @@
 }
 
 void MockMediaSession::DisableAction(mojom::MediaSessionAction action) {
-  if (!base::ContainsKey(actions_, action))
+  if (!base::Contains(actions_, action))
     return;
 
   actions_.erase(action);
diff --git a/services/network/cookie_settings.cc b/services/network/cookie_settings.cc
index b0f9ac8..0f56483 100644
--- a/services/network/cookie_settings.cc
+++ b/services/network/cookie_settings.cc
@@ -34,15 +34,14 @@
                                       const GURL& first_party_url,
                                       content_settings::SettingSource* source,
                                       ContentSetting* cookie_setting) const {
-  if (base::ContainsKey(secure_origin_cookies_allowed_schemes_,
-                        first_party_url.scheme()) &&
+  if (base::Contains(secure_origin_cookies_allowed_schemes_,
+                     first_party_url.scheme()) &&
       url.SchemeIsCryptographic()) {
     *cookie_setting = CONTENT_SETTING_ALLOW;
     return;
   }
 
-  if (base::ContainsKey(matching_scheme_cookies_allowed_schemes_,
-                        url.scheme()) &&
+  if (base::Contains(matching_scheme_cookies_allowed_schemes_, url.scheme()) &&
       url.SchemeIs(first_party_url.scheme_piece())) {
     *cookie_setting = CONTENT_SETTING_ALLOW;
     return;
@@ -51,8 +50,8 @@
   // Default to allowing cookies.
   *cookie_setting = CONTENT_SETTING_ALLOW;
   bool block_third = block_third_party_cookies_ &&
-                     !base::ContainsKey(third_party_cookies_allowed_schemes_,
-                                        first_party_url.scheme());
+                     !base::Contains(third_party_cookies_allowed_schemes_,
+                                     first_party_url.scheme());
   for (const auto& entry : content_settings_) {
     if (entry.primary_pattern.Matches(url) &&
         entry.secondary_pattern.Matches(first_party_url)) {
diff --git a/services/network/cors/cors_url_loader.cc b/services/network/cors/cors_url_loader.cc
index b797be51..954da001 100644
--- a/services/network/cors/cors_url_loader.cc
+++ b/services/network/cors/cors_url_loader.cc
@@ -83,6 +83,7 @@
     mojom::URLLoaderClientPtr client,
     const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
     mojom::URLLoaderFactory* network_loader_factory,
+    const base::Optional<url::Origin>& factory_bound_origin,
     const OriginAccessList* origin_access_list,
     const OriginAccessList* factory_bound_origin_access_list,
     PreflightController* preflight_controller)
@@ -96,6 +97,7 @@
       request_(resource_request),
       forwarding_client_(std::move(client)),
       traffic_annotation_(traffic_annotation),
+      factory_bound_origin_(factory_bound_origin),
       origin_access_list_(origin_access_list),
       factory_bound_origin_access_list_(factory_bound_origin_access_list),
       preflight_controller_(preflight_controller),
@@ -390,8 +392,8 @@
 }
 
 void CorsURLLoader::StartRequest() {
-  if (fetch_cors_flag_ && !base::ContainsValue(url::GetCorsEnabledSchemes(),
-                                               request_.url.scheme())) {
+  if (fetch_cors_flag_ &&
+      !base::Contains(url::GetCorsEnabledSchemes(), request_.url.scheme())) {
     HandleComplete(URLLoaderCompletionStatus(
         CorsErrorStatus(mojom::CorsError::kCorsDisabledScheme)));
     return;
@@ -502,6 +504,18 @@
     return;
   }
 
+  // In some cases we want to use the origin attached to the URLLoaderFactory
+  // to check same-originness.
+  // TODO(lukasza): https://crbug.com/940068: Revert https://crrev.com/c/1642752
+  // once request_initiator is always set to the webpage (and never to the
+  // isolated world).
+  if (request_.should_also_use_factory_bound_origin_for_cors &&
+      factory_bound_origin_ &&
+      factory_bound_origin_->IsSameOriginWith(
+          url::Origin::Create(request_.url))) {
+    return;
+  }
+
   // The source origin and destination URL pair may be in the allow list.
   switch (origin_access_list_->CheckAccessState(*request_.request_initiator,
                                                 request_.url)) {
diff --git a/services/network/cors/cors_url_loader.h b/services/network/cors/cors_url_loader.h
index 3de8bb2..8748cb88 100644
--- a/services/network/cors/cors_url_loader.h
+++ b/services/network/cors/cors_url_loader.h
@@ -45,6 +45,7 @@
       mojom::URLLoaderClientPtr client,
       const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
       mojom::URLLoaderFactory* network_loader_factory,
+      const base::Optional<url::Origin>& factory_bound_origin_,
       const OriginAccessList* origin_access_list,
       const OriginAccessList* factory_bound_origin_access_list,
       PreflightController* preflight_controller);
@@ -166,6 +167,8 @@
   // Holds timing info if a preflight was made.
   std::vector<PreflightTimingInfo> preflight_timing_info_;
 
+  const base::Optional<url::Origin> factory_bound_origin_;
+
   // Outlives |this|.
   const OriginAccessList* const origin_access_list_;
   const OriginAccessList* const factory_bound_origin_access_list_;
diff --git a/services/network/cors/cors_url_loader_factory.cc b/services/network/cors/cors_url_loader_factory.cc
index 9da640ab..20daf7b 100644
--- a/services/network/cors/cors_url_loader_factory.cc
+++ b/services/network/cors/cors_url_loader_factory.cc
@@ -98,8 +98,8 @@
         base::BindOnce(&CorsURLLoaderFactory::DestroyURLLoader,
                        base::Unretained(this)),
         resource_request, std::move(client), traffic_annotation,
-        network_loader_factory_.get(), origin_access_list_,
-        factory_bound_origin_access_list_.get(),
+        network_loader_factory_.get(), request_initiator_site_lock_,
+        origin_access_list_, factory_bound_origin_access_list_.get(),
         context_->cors_preflight_controller());
     auto* raw_loader = loader.get();
     OnLoaderCreated(std::move(loader));
diff --git a/services/network/cross_origin_read_blocking.cc b/services/network/cross_origin_read_blocking.cc
index e4a07ea..14dd79ec 100644
--- a/services/network/cross_origin_read_blocking.cc
+++ b/services/network/cross_origin_read_blocking.cc
@@ -269,8 +269,8 @@
   if (base::LowerCaseEqualsASCII(mime_type, kTextPlain))
     return MimeType::kPlain;
 
-  if (base::ContainsKey(GetNeverSniffedMimeTypes(),
-                        base::ToLowerASCII(mime_type))) {
+  if (base::Contains(GetNeverSniffedMimeTypes(),
+                     base::ToLowerASCII(mime_type))) {
     return MimeType::kNeverSniffed;
   }
 
@@ -994,7 +994,7 @@
 // static
 bool CrossOriginReadBlocking::ShouldAllowForPlugin(int process_id) {
   std::set<int>& plugin_proxies = GetPluginProxyingProcesses();
-  return base::ContainsKey(plugin_proxies, process_id);
+  return base::Contains(plugin_proxies, process_id);
 }
 
 // static
diff --git a/services/network/network_context_unittest.cc b/services/network/network_context_unittest.cc
index 3c869f759..25f61f43b 100644
--- a/services/network/network_context_unittest.cc
+++ b/services/network/network_context_unittest.cc
@@ -3832,7 +3832,7 @@
   run_loop.Run();
   EXPECT_FALSE(result);
 
-  EXPECT_TRUE(base::ContainsKey(requested_urls, kReportURL));
+  EXPECT_TRUE(base::Contains(requested_urls, kReportURL));
 }
 #endif  // BUILDFLAG(IS_CT_SUPPORTED)
 
diff --git a/services/network/p2p/socket_udp.cc b/services/network/p2p/socket_udp.cc
index bb11a9a..3dc0c919 100644
--- a/services/network/p2p/socket_udp.cc
+++ b/services/network/p2p/socket_udp.cc
@@ -209,7 +209,7 @@
     std::vector<int8_t> data(recv_buffer_->data(),
                              recv_buffer_->data() + result);
 
-    if (!base::ContainsKey(connected_peers_, recv_address_)) {
+    if (!base::Contains(connected_peers_, recv_address_)) {
       P2PSocket::StunMessageType type;
       bool stun = GetStunPacketType(reinterpret_cast<uint8_t*>(&*data.begin()),
                                     data.size(), &type);
@@ -247,7 +247,7 @@
   // messages to that peer and they are throttled using the |throttler_|. This
   // has to be done here instead of Send() to ensure P2PMsg_OnSendComplete
   // messages are sent in correct order.
-  if (!base::ContainsKey(connected_peers_, packet.to)) {
+  if (!base::Contains(connected_peers_, packet.to)) {
     P2PSocket::StunMessageType type = P2PSocket::StunMessageType();
     bool stun =
         GetStunPacketType(reinterpret_cast<const uint8_t*>(packet.data->data()),
diff --git a/services/network/public/cpp/is_potentially_trustworthy.cc b/services/network/public/cpp/is_potentially_trustworthy.cc
index 5657ce3..e34e5bd 100644
--- a/services/network/public/cpp/is_potentially_trustworthy.cc
+++ b/services/network/public/cpp/is_potentially_trustworthy.cc
@@ -189,7 +189,7 @@
 
 bool IsAllowlisted(const std::vector<std::string>& allowlist,
                    const url::Origin& origin) {
-  if (base::ContainsValue(allowlist, origin.Serialize()))
+  if (base::Contains(allowlist, origin.Serialize()))
     return true;
 
   for (const std::string& origin_or_pattern : allowlist) {
@@ -249,8 +249,8 @@
   //   content::ContentClient::Schemes::secure_schemes
   // - url::AddLocalScheme
   // - url::AddSecureScheme
-  if (base::ContainsValue(url::GetSecureSchemes(), origin.scheme()) ||
-      base::ContainsValue(url::GetLocalSchemes(), origin.scheme())) {
+  if (base::Contains(url::GetSecureSchemes(), origin.scheme()) ||
+      base::Contains(url::GetLocalSchemes(), origin.scheme())) {
     return true;
   }
 
diff --git a/services/network/public/cpp/resource_request.cc b/services/network/public/cpp/resource_request.cc
index ff679e75..d1fe50a 100644
--- a/services/network/public/cpp/resource_request.cc
+++ b/services/network/public/cpp/resource_request.cc
@@ -60,6 +60,8 @@
          initiated_in_secure_context == request.initiated_in_secure_context &&
          upgrade_if_insecure == request.upgrade_if_insecure &&
          is_revalidating == request.is_revalidating &&
+         should_also_use_factory_bound_origin_for_cors ==
+             request.should_also_use_factory_bound_origin_for_cors &&
          throttling_profile_id == request.throttling_profile_id &&
          custom_proxy_pre_cache_headers.ToString() ==
              request.custom_proxy_pre_cache_headers.ToString() &&
diff --git a/services/network/public/cpp/resource_request.h b/services/network/public/cpp/resource_request.h
index 21c7df9..c2f7bf44 100644
--- a/services/network/public/cpp/resource_request.h
+++ b/services/network/public/cpp/resource_request.h
@@ -85,6 +85,7 @@
   bool initiated_in_secure_context = false;
   bool upgrade_if_insecure = false;
   bool is_revalidating = false;
+  bool should_also_use_factory_bound_origin_for_cors = false;
   base::Optional<base::UnguessableToken> throttling_profile_id;
   net::HttpRequestHeaders custom_proxy_pre_cache_headers;
   net::HttpRequestHeaders custom_proxy_post_cache_headers;
diff --git a/services/network/public/cpp/url_request_mojom_traits.cc b/services/network/public/cpp/url_request_mojom_traits.cc
index 08e1563f..727c784 100644
--- a/services/network/public/cpp/url_request_mojom_traits.cc
+++ b/services/network/public/cpp/url_request_mojom_traits.cc
@@ -210,6 +210,8 @@
   out->initiated_in_secure_context = data.initiated_in_secure_context();
   out->upgrade_if_insecure = data.upgrade_if_insecure();
   out->is_revalidating = data.is_revalidating();
+  out->should_also_use_factory_bound_origin_for_cors =
+      data.should_also_use_factory_bound_origin_for_cors();
   return true;
 }
 
diff --git a/services/network/public/cpp/url_request_mojom_traits.h b/services/network/public/cpp/url_request_mojom_traits.h
index 9825b1f..ced5daa8 100644
--- a/services/network/public/cpp/url_request_mojom_traits.h
+++ b/services/network/public/cpp/url_request_mojom_traits.h
@@ -199,6 +199,10 @@
   static bool is_revalidating(const network::ResourceRequest& request) {
     return request.is_revalidating;
   }
+  static bool should_also_use_factory_bound_origin_for_cors(
+      const network::ResourceRequest& request) {
+    return request.should_also_use_factory_bound_origin_for_cors;
+  }
   static const base::Optional<base::UnguessableToken>& throttling_profile_id(
       const network::ResourceRequest& request) {
     return request.throttling_profile_id;
diff --git a/services/network/public/mojom/url_loader.mojom b/services/network/public/mojom/url_loader.mojom
index 03200c84..df9db84 100644
--- a/services/network/public/mojom/url_loader.mojom
+++ b/services/network/public/mojom/url_loader.mojom
@@ -293,6 +293,10 @@
   // some CORS logic for a revalidating request.
   bool is_revalidating;
 
+  // True when the CORS module should *also* use the origin set to the
+  // associated URLLoaderFactory.
+  bool should_also_use_factory_bound_origin_for_cors;
+
   // The profile ID of network conditions to throttle the network request.
   mojo_base.mojom.UnguessableToken? throttling_profile_id;
 
diff --git a/services/network/resource_scheduler.cc b/services/network/resource_scheduler.cc
index a629b776..d8a157f 100644
--- a/services/network/resource_scheduler.cc
+++ b/services/network/resource_scheduler.cc
@@ -162,7 +162,7 @@
 
   // Returns true if |request| is queued.
   bool IsQueued(ScheduledResourceRequestImpl* request) const {
-    return base::ContainsKey(pointers_, request);
+    return base::Contains(pointers_, request);
   }
 
   // Returns true if no requests are queued.
@@ -355,7 +355,7 @@
 
 void ResourceScheduler::RequestQueue::Insert(
     ScheduledResourceRequestImpl* request) {
-  DCHECK(!base::ContainsKey(pointers_, request));
+  DCHECK(!base::Contains(pointers_, request));
   request->set_fifo_ordering(MakeFifoOrderingId());
   pointers_[request] = queue_.insert(request);
 }
@@ -402,7 +402,7 @@
   void RemoveRequest(ScheduledResourceRequestImpl* request) {
     if (pending_requests_.IsQueued(request)) {
       pending_requests_.Erase(request);
-      DCHECK(!base::ContainsKey(in_flight_requests_, request));
+      DCHECK(!base::Contains(in_flight_requests_, request));
     } else {
       // Record metrics.
       if (!RequestAttributesAreSet(request->attributes(), kAttributeDelayable))
@@ -448,7 +448,7 @@
     request->set_request_priority_params(new_priority_params);
     SetRequestAttributes(request, DetermineRequestAttributes(request));
     if (!pending_requests_.IsQueued(request)) {
-      DCHECK(base::ContainsKey(in_flight_requests_, request));
+      DCHECK(base::Contains(in_flight_requests_, request));
       // Request has already started.
       return;
     }
@@ -567,7 +567,7 @@
       }
       // Account for the current request if it is not in one of the lists yet.
       if (current_request &&
-          !base::ContainsKey(in_flight_requests_, current_request) &&
+          !base::Contains(in_flight_requests_, current_request) &&
           !current_request_is_pending) {
         if (RequestAttributesAreSet(current_request->attributes(), attributes))
           matching_request_count++;
@@ -613,7 +613,7 @@
       ScheduledResourceRequestImpl* request) {
     RequestAttributes attributes = kAttributeNone;
 
-    if (base::ContainsKey(in_flight_requests_, request))
+    if (base::Contains(in_flight_requests_, request))
       attributes |= kAttributeInFlight;
 
     if (RequestAttributesAreSet(request->attributes(),
@@ -1089,7 +1089,7 @@
 
 void ResourceScheduler::RemoveRequest(ScheduledResourceRequestImpl* request) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  if (base::ContainsKey(unowned_requests_, request)) {
+  if (base::Contains(unowned_requests_, request)) {
     unowned_requests_.erase(request);
     return;
   }
@@ -1108,7 +1108,7 @@
     net::NetworkQualityEstimator* network_quality_estimator) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   ClientId client_id = MakeClientId(child_id, route_id);
-  DCHECK(!base::ContainsKey(client_map_, client_id));
+  DCHECK(!base::Contains(client_map_, client_id));
 
   client_map_[client_id] =
       std::make_unique<Client>(child_id == mojom::kBrowserProcessId,
diff --git a/services/preferences/persistent_pref_store_impl.cc b/services/preferences/persistent_pref_store_impl.cc
index 04635468..957abd78 100644
--- a/services/preferences/persistent_pref_store_impl.cc
+++ b/services/preferences/persistent_pref_store_impl.cc
@@ -101,7 +101,7 @@
 
     std::vector<mojom::PrefUpdatePtr> filtered_updates;
     for (const auto& update : updates) {
-      if (base::ContainsKey(observed_keys_, update->key)) {
+      if (base::Contains(observed_keys_, update->key)) {
         filtered_updates.push_back(update->Clone());
       }
     }
@@ -119,7 +119,7 @@
 
   void RequestValue(const std::string& key,
                     const std::vector<std::string>& path) override {
-    if (!base::ContainsKey(observed_keys_, key))
+    if (!base::Contains(observed_keys_, key))
       return;
 
     const base::Value* value = nullptr;
diff --git a/services/preferences/pref_store_impl.cc b/services/preferences/pref_store_impl.cc
index 9c146da..4ce24993 100644
--- a/services/preferences/pref_store_impl.cc
+++ b/services/preferences/pref_store_impl.cc
@@ -24,7 +24,7 @@
   }
 
   void OnPrefChanged(const std::string& key, const base::Value& value) const {
-    if (!base::ContainsKey(prefs_, key))
+    if (!base::Contains(prefs_, key))
       return;
 
     std::vector<mojom::PrefUpdatePtr> updates;
@@ -34,7 +34,7 @@
   }
 
   void OnPrefRemoved(const std::string& key) const {
-    if (!base::ContainsKey(prefs_, key))
+    if (!base::Contains(prefs_, key))
       return;
 
     std::vector<mojom::PrefUpdatePtr> updates;
diff --git a/services/preferences/scoped_pref_connection_builder.cc b/services/preferences/scoped_pref_connection_builder.cc
index 656b33c..8d2779a 100644
--- a/services/preferences/scoped_pref_connection_builder.cc
+++ b/services/preferences/scoped_pref_connection_builder.cc
@@ -47,7 +47,7 @@
                                                         observed_prefs_.end());
   std::vector<std::string> filtered_persistent_perf_names;
   for (const char* persistent_perf_name : persistent_perf_names) {
-    if (base::ContainsKey(observed_prefs, persistent_perf_name))
+    if (base::Contains(observed_prefs, persistent_perf_name))
       filtered_persistent_perf_names.emplace_back(persistent_perf_name);
   }
   incognito_connection_ = mojom::IncognitoPersistentPrefStoreConnection::New(
diff --git a/services/preferences/tracked/segregated_pref_store.cc b/services/preferences/tracked/segregated_pref_store.cc
index f62cc4d..2266fb8 100644
--- a/services/preferences/tracked/segregated_pref_store.cc
+++ b/services/preferences/tracked/segregated_pref_store.cc
@@ -204,16 +204,14 @@
 }
 
 PersistentPrefStore* SegregatedPrefStore::StoreForKey(const std::string& key) {
-  return (base::ContainsKey(selected_preference_names_, key)
-              ? selected_pref_store_
-              : default_pref_store_)
+  return (base::Contains(selected_preference_names_, key) ? selected_pref_store_
+                                                          : default_pref_store_)
       .get();
 }
 
 const PersistentPrefStore* SegregatedPrefStore::StoreForKey(
     const std::string& key) const {
-  return (base::ContainsKey(selected_preference_names_, key)
-              ? selected_pref_store_
-              : default_pref_store_)
+  return (base::Contains(selected_preference_names_, key) ? selected_pref_store_
+                                                          : default_pref_store_)
       .get();
 }
diff --git a/services/service_manager/public/cpp/connector.cc b/services/service_manager/public/cpp/connector.cc
index 78b85aef3..f3ad01d9 100644
--- a/services/service_manager/public/cpp/connector.cc
+++ b/services/service_manager/public/cpp/connector.cc
@@ -127,7 +127,7 @@
   if (service_overrides == local_binder_overrides_.end())
     return false;
 
-  return base::ContainsKey(service_overrides->second, interface_name);
+  return base::Contains(service_overrides->second, interface_name);
 }
 
 void Connector::ClearBinderOverrideForTesting(
diff --git a/services/service_manager/public/cpp/service_executable/main.cc b/services/service_manager/public/cpp/service_executable/main.cc
index ce13439..bb64e8b 100644
--- a/services/service_manager/public/cpp/service_executable/main.cc
+++ b/services/service_manager/public/cpp/service_executable/main.cc
@@ -45,7 +45,7 @@
         break;
       }
     }
-    if (apps_to_debug.empty() || base::ContainsValue(apps_to_debug, app)) {
+    if (apps_to_debug.empty() || base::Contains(apps_to_debug, app)) {
 #if defined(OS_WIN)
       base::string16 appw = base::UTF8ToUTF16(app);
       base::string16 message = base::UTF8ToUTF16(
diff --git a/services/service_manager/service_instance.cc b/services/service_manager/service_instance.cc
index 95ce2fb..e4d580f 100644
--- a/services/service_manager/service_instance.cc
+++ b/services/service_manager/service_instance.cc
@@ -286,7 +286,7 @@
     return false;
 
   const Manifest& source_manifest = source_instance.manifest();
-  const bool bindable_on_any_service = base::ContainsKey(
+  const bool bindable_on_any_service = base::Contains(
       source_manifest.interfaces_bindable_on_any_service, interface_name);
   const bool allowed_by_capabilities =
       AllowsInterface(source_manifest.required_capabilities, identity_.name(),
diff --git a/services/tracing/perfetto/consumer_host.cc b/services/tracing/perfetto/consumer_host.cc
index f840aa3..79c2b6f 100644
--- a/services/tracing/perfetto/consumer_host.cc
+++ b/services/tracing/perfetto/consumer_host.cc
@@ -274,7 +274,7 @@
 }
 
 bool ConsumerHost::TracingSession::IsExpectedPid(base::ProcessId pid) const {
-  return filtered_pids_.empty() || base::ContainsKey(filtered_pids_, pid);
+  return filtered_pids_.empty() || base::Contains(filtered_pids_, pid);
 }
 
 void ConsumerHost::TracingSession::ChangeTraceConfig(
diff --git a/services/tracing/tracing_service.cc b/services/tracing/tracing_service.cc
index 4ab07c9..1075972 100644
--- a/services/tracing/tracing_service.cc
+++ b/services/tracing/tracing_service.cc
@@ -54,7 +54,7 @@
 
     // Not the first service added for this PID, and the process has already
     // accepted a connection request.
-    if (base::ContainsKey(connected_pids_, pid))
+    if (base::Contains(connected_pids_, pid))
       return;
 
     // Let the Coordinator and the perfetto service know it should be expecting
diff --git a/services/video_capture/device_factory_media_to_mojo_adapter.cc b/services/video_capture/device_factory_media_to_mojo_adapter.cc
index d4dea9a8..5b8e3f02d 100644
--- a/services/video_capture/device_factory_media_to_mojo_adapter.cc
+++ b/services/video_capture/device_factory_media_to_mojo_adapter.cc
@@ -44,8 +44,8 @@
               : media::PIXEL_FORMAT_I420;
       translated_format.frame_size = format.frame_size;
       translated_format.frame_rate = format.frame_rate;
-      if (base::ContainsValue(translated_device_info.supported_formats,
-                              translated_format))
+      if (base::Contains(translated_device_info.supported_formats,
+                         translated_format))
         continue;
       translated_device_info.supported_formats.push_back(translated_format);
     }
diff --git a/services/video_capture/public/cpp/mock_receiver.cc b/services/video_capture/public/cpp/mock_receiver.cc
index 754ab458..2ecb3409 100644
--- a/services/video_capture/public/cpp/mock_receiver.cc
+++ b/services/video_capture/public/cpp/mock_receiver.cc
@@ -30,7 +30,7 @@
 void MockReceiver::OnNewBuffer(
     int32_t buffer_id,
     media::mojom::VideoBufferHandlePtr buffer_handle) {
-  CHECK(!base::ContainsValue(known_buffer_ids_, buffer_id));
+  CHECK(!base::Contains(known_buffer_ids_, buffer_id));
   known_buffer_ids_.push_back(buffer_id);
   DoOnNewBuffer(buffer_id, &buffer_handle);
 }
diff --git a/services/video_capture/shared_memory_virtual_device_mojo_adapter.cc b/services/video_capture/shared_memory_virtual_device_mojo_adapter.cc
index 615c039..2cecb0fe 100644
--- a/services/video_capture/shared_memory_virtual_device_mojo_adapter.cc
+++ b/services/video_capture/shared_memory_virtual_device_mojo_adapter.cc
@@ -85,7 +85,7 @@
     return;
   }
 
-  if (!base::ContainsValue(known_buffer_ids_, buffer_id)) {
+  if (!base::Contains(known_buffer_ids_, buffer_id)) {
     if (receiver_.is_bound()) {
       media::mojom::VideoBufferHandlePtr buffer_handle =
           media::mojom::VideoBufferHandle::New();
@@ -126,7 +126,7 @@
     ::media::mojom::VideoFrameInfoPtr frame_info) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   // Unknown buffer ID.
-  if (!base::ContainsValue(known_buffer_ids_, buffer_id)) {
+  if (!base::Contains(known_buffer_ids_, buffer_id)) {
     return;
   }
 
diff --git a/services/video_capture/test/virtual_device_unittest.cc b/services/video_capture/test/virtual_device_unittest.cc
index 441eb37..df0682b 100644
--- a/services/video_capture/test/virtual_device_unittest.cc
+++ b/services/video_capture/test/virtual_device_unittest.cc
@@ -160,7 +160,7 @@
       .Times(1)
       .WillOnce(Invoke([this](int32_t buffer_id) {
         // Verify that the returned |buffer_id| is a known buffer ID.
-        EXPECT_TRUE(base::ContainsValue(received_buffer_ids_, buffer_id));
+        EXPECT_TRUE(base::Contains(received_buffer_ids_, buffer_id));
       }));
   device_adapter_->RequestFrameBuffer(kTestFrameSize, kTestPixelFormat, nullptr,
                                       request_frame_buffer_callback.Get());
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 4d2bdf0..00a4ab24 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -4939,27 +4939,6 @@
             ]
         }
     ],
-    "SimplifyHttpsIndicatorPhase3": [
-        {
-            "platforms": [
-                "chromeos",
-                "linux",
-                "windows",
-                "mac"
-            ],
-            "experiments": [
-                {
-                    "name": "BothToLock",
-                    "params": {
-                        "treatment": "both-to-lock"
-                    },
-                    "enable_features": [
-                        "SimplifyHttpsIndicator"
-                    ]
-                }
-            ]
-        }
-    ],
     "SkipPassthroughTouchEventQueueFilter": [
         {
             "platforms": [
diff --git a/third_party/blink/public/platform/web_gesture_event.h b/third_party/blink/public/platform/web_gesture_event.h
index 46a34eb..bb9f0fb 100644
--- a/third_party/blink/public/platform/web_gesture_event.h
+++ b/third_party/blink/public/platform/web_gesture_event.h
@@ -21,7 +21,7 @@
 
 class WebGestureEvent : public WebInputEvent {
  public:
-  enum class InertialPhaseState {
+  enum class InertialPhaseState : uint8_t {
     kUnknownMomentum = 0,  // No phase information.
     kNonMomentum,          // Regular scrolling phase.
     kMomentum,             // Momentum phase.
@@ -83,29 +83,29 @@
     } two_finger_tap;
 
     struct {
-      // Initial motion that triggered the scroll.
-      float delta_x_hint;
-      float delta_y_hint;
-      // Default initialized to kScrollByPrecisePixel.
-      ui::input_types::ScrollGranularity delta_hint_units;
-      // If true, this event will skip hit testing to find a scroll
-      // target and instead just scroll the viewport.
-      bool target_viewport;
-      // The state of inertial phase scrolling. OSX has unique phases for normal
-      // and momentum scroll events. Should always be kUnknownMomentumPhase for
-      // touch based input as it generates GestureFlingStart instead.
-      InertialPhaseState inertial_phase;
-      // True if this event is generated from a wheel event with synthetic
-      // phase.
-      bool synthetic;
-      // number of pointers down.
-      int pointer_count;
       // If set, used to target a scrollable area directly instead of performing
       // a hit-test. Should be used for gestures queued up internally within
       // the renderer process. This is an ElementIdType instead of ElementId
       // due to the fact that ElementId has a non-trivial constructor that
       // can't easily participate in this union of structs.
       cc::ElementIdType scrollable_area_element_id;
+      // Initial motion that triggered the scroll.
+      float delta_x_hint;
+      float delta_y_hint;
+      // number of pointers down.
+      int pointer_count;
+      // Default initialized to kScrollByPrecisePixel.
+      ui::input_types::ScrollGranularity delta_hint_units;
+      // The state of inertial phase scrolling. OSX has unique phases for normal
+      // and momentum scroll events. Should always be kUnknownMomentumPhase for
+      // touch based input as it generates GestureFlingStart instead.
+      InertialPhaseState inertial_phase;
+      // If true, this event will skip hit testing to find a scroll
+      // target and instead just scroll the viewport.
+      bool target_viewport;
+      // True if this event is generated from a wheel event with synthetic
+      // phase.
+      bool synthetic;
     } scroll_begin;
 
     struct {
diff --git a/third_party/blink/public/platform/web_url_request.h b/third_party/blink/public/platform/web_url_request.h
index f066118..bdbfc0b 100644
--- a/third_party/blink/public/platform/web_url_request.h
+++ b/third_party/blink/public/platform/web_url_request.h
@@ -361,6 +361,10 @@
   // Returns true when the request is for revalidation.
   BLINK_PLATFORM_EXPORT bool IsRevalidating() const;
 
+  // Returns true if the CORS module should take into account the origin
+  // attached with the URLLoaderFactory.
+  BLINK_PLATFORM_EXPORT bool ShouldAlsoUseFactoryBoundOriginForCors() const;
+
   // Returns the DevTools ID to throttle the network request.
   BLINK_PLATFORM_EXPORT const base::Optional<base::UnguessableToken>&
   GetDevToolsToken() const;
diff --git a/third_party/blink/public/web/web_ax_object.h b/third_party/blink/public/web/web_ax_object.h
index 5b53e37..a1985d2d 100644
--- a/third_party/blink/public/web/web_ax_object.h
+++ b/third_party/blink/public/web/web_ax_object.h
@@ -194,6 +194,7 @@
       ax::mojom::TextDecorationStyle* text_strikethrough_style,
       ax::mojom::TextDecorationStyle* text_underline_style) const;
   BLINK_EXPORT WebURL Url() const;
+  BLINK_EXPORT WebAXObject ChooserPopup() const;
 
   // Retrieves the accessible name of the object, an enum indicating where the
   // name was derived from, and a list of related objects that were used to
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn
index f87dc3b2..c7b31b0 100644
--- a/third_party/blink/renderer/core/BUILD.gn
+++ b/third_party/blink/renderer/core/BUILD.gn
@@ -1868,6 +1868,7 @@
     "html/custom/custom_element_upgrade_sorter_test.cc",
     "html/forms/email_input_type_test.cc",
     "html/forms/external_popup_menu_test.cc",
+    "html/forms/file_chooser_test.cc",
     "html/forms/file_input_type_test.cc",
     "html/forms/form_controller_test.cc",
     "html/forms/form_data_test.cc",
diff --git a/third_party/blink/renderer/core/fetch/fetch_manager.cc b/third_party/blink/renderer/core/fetch/fetch_manager.cc
index 4fca93e..70deeea4 100644
--- a/third_party/blink/renderer/core/fetch/fetch_manager.cc
+++ b/third_party/blink/renderer/core/fetch/fetch_manager.cc
@@ -686,6 +686,8 @@
   request.SetRequestContext(fetch_request_data_->Context());
   request.SetHttpMethod(fetch_request_data_->Method());
   request.SetFetchWindowId(fetch_request_data_->WindowId());
+  request.SetShouldAlsoUseFactoryBoundOriginForCors(
+      fetch_request_data_->ShouldAlsoUseFactoryBoundOriginForCors());
 
   switch (fetch_request_data_->Mode()) {
     case FetchRequestMode::kSameOrigin:
diff --git a/third_party/blink/renderer/core/fetch/fetch_request_data.cc b/third_party/blink/renderer/core/fetch/fetch_request_data.cc
index ce69202..645bf4f 100644
--- a/third_party/blink/renderer/core/fetch/fetch_request_data.cc
+++ b/third_party/blink/renderer/core/fetch/fetch_request_data.cc
@@ -151,6 +151,8 @@
   request->keepalive_ = keepalive_;
   request->is_history_navigation_ = is_history_navigation_;
   request->window_id_ = window_id_;
+  request->should_also_use_factory_bound_origin_for_cors_ =
+      should_also_use_factory_bound_origin_for_cors_;
   return request;
 }
 
diff --git a/third_party/blink/renderer/core/fetch/fetch_request_data.h b/third_party/blink/renderer/core/fetch/fetch_request_data.h
index d0b6fef..3fbba56 100644
--- a/third_party/blink/renderer/core/fetch/fetch_request_data.h
+++ b/third_party/blink/renderer/core/fetch/fetch_request_data.h
@@ -114,6 +114,12 @@
   }
   const base::UnguessableToken& WindowId() const { return window_id_; }
   void SetWindowId(const base::UnguessableToken& id) { window_id_ = id; }
+  bool ShouldAlsoUseFactoryBoundOriginForCors() const {
+    return should_also_use_factory_bound_origin_for_cors_;
+  }
+  void SetShouldAlsoUseFactoryBoundOriginForCors(bool value) {
+    should_also_use_factory_bound_origin_for_cors_ = value;
+  }
 
   void Trace(blink::Visitor*);
 
@@ -155,6 +161,7 @@
   // the URL got revoked after creating the request.
   network::mojom::blink::URLLoaderFactoryPtr url_loader_factory_;
   base::UnguessableToken window_id_;
+  bool should_also_use_factory_bound_origin_for_cors_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(FetchRequestData);
 };
diff --git a/third_party/blink/renderer/core/fetch/request.cc b/third_party/blink/renderer/core/fetch/request.cc
index 00be562..f7ff972 100644
--- a/third_party/blink/renderer/core/fetch/request.cc
+++ b/third_party/blink/renderer/core/fetch/request.cc
@@ -55,6 +55,7 @@
   DOMWrapperWorld& world = script_state->World();
   if (world.IsIsolatedWorld()) {
     request->SetOrigin(world.IsolatedWorldSecurityOrigin());
+    request->SetShouldAlsoUseFactoryBoundOriginForCors(true);
   } else {
     request->SetOrigin(
         ExecutionContext::From(script_state)->GetSecurityOrigin());
diff --git a/third_party/blink/renderer/core/html/forms/file_chooser.h b/third_party/blink/renderer/core/html/forms/file_chooser.h
index 1042c13f5..594ee1c 100644
--- a/third_party/blink/renderer/core/html/forms/file_chooser.h
+++ b/third_party/blink/renderer/core/html/forms/file_chooser.h
@@ -96,7 +96,7 @@
   // mojom::blink::FileChooser callback
   void DidChooseFiles(mojom::blink::FileChooserResultPtr result);
 
-  WeakPersistent<FileChooserClient> client_;
+  Persistent<FileChooserClient> client_;
   mojom::blink::FileChooserParamsPtr params_;
   Persistent<ChromeClientImpl> chrome_client_impl_;
   mojom::blink::FileChooserPtr file_chooser_;
diff --git a/third_party/blink/renderer/core/html/forms/file_chooser_test.cc b/third_party/blink/renderer/core/html/forms/file_chooser_test.cc
new file mode 100644
index 0000000..321cd9f
--- /dev/null
+++ b/third_party/blink/renderer/core/html/forms/file_chooser_test.cc
@@ -0,0 +1,33 @@
+// 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/html/forms/file_chooser.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
+#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
+#include "third_party/blink/renderer/core/html/forms/mock_file_chooser.h"
+#include "third_party/blink/renderer/core/page/chrome_client_impl.h"
+
+namespace blink {
+
+class FileChooserTest : public testing::Test {
+ protected:
+  void SetUp() override { web_view_ = helper_.Initialize(); }
+
+  frame_test_helpers::WebViewHelper helper_;
+  WebViewImpl* web_view_;
+};
+
+TEST_F(FileChooserTest, NotGarbageCollected) {
+  LocalFrame* frame = helper_.LocalMainFrame()->GetFrame();
+  auto* client = MakeGarbageCollected<MockFileChooserClient>(frame);
+  mojom::blink::FileChooserParams params;
+  params.title = g_empty_string;
+  scoped_refptr<FileChooser> chooser = FileChooser::Create(client, params);
+  ThreadState::Current()->CollectAllGarbageForTesting();
+  // This tests the nullness of FileChooser::client_.
+  EXPECT_TRUE(chooser->FrameOrNull());
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/html/forms/mock_file_chooser.h b/third_party/blink/renderer/core/html/forms/mock_file_chooser.h
index 2058d12..ff28ea1 100644
--- a/third_party/blink/renderer/core/html/forms/mock_file_chooser.h
+++ b/third_party/blink/renderer/core/html/forms/mock_file_chooser.h
@@ -74,5 +74,28 @@
   base::OnceClosure reached_callback_;
 };
 
+// A FileChooserClient which makes FileChooser::OpenFileChooser() success.
+class MockFileChooserClient
+    : public GarbageCollectedFinalized<MockFileChooserClient>,
+      public FileChooserClient {
+  USING_GARBAGE_COLLECTED_MIXIN(MockFileChooserClient);
+
+ public:
+  explicit MockFileChooserClient(LocalFrame* frame) : frame_(frame) {}
+  void Trace(Visitor* visitor) override {
+    visitor->Trace(frame_);
+    FileChooserClient::Trace(visitor);
+  }
+
+ private:
+  // FilesChosen() and WillOpenPopup() are never called in the test.
+  void FilesChosen(FileChooserFileInfoList, const base::FilePath&) override {}
+  void WillOpenPopup() override {}
+
+  LocalFrame* FrameOrNull() const override { return frame_; }
+
+  Member<LocalFrame> frame_;
+};
+
 }  // namespace blink
 #endif  // THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_MOCK_FILE_CHOOSER_H_
diff --git a/third_party/blink/renderer/core/html/html_all_collection.idl b/third_party/blink/renderer/core/html/html_all_collection.idl
index 76d31705..6a007bf 100644
--- a/third_party/blink/renderer/core/html/html_all_collection.idl
+++ b/third_party/blink/renderer/core/html/html_all_collection.idl
@@ -27,6 +27,7 @@
 // https://html.spec.whatwg.org/C/#the-htmlallcollection-interface
 
 [
+    Exposed=Window,
     Custom=LegacyCallAsFunction,
     LegacyUnenumerableNamedProperties
 ] interface HTMLAllCollection {
diff --git a/third_party/blink/renderer/core/html/html_anchor_element.idl b/third_party/blink/renderer/core/html/html_anchor_element.idl
index bc7dc363..6520bac 100644
--- a/third_party/blink/renderer/core/html/html_anchor_element.idl
+++ b/third_party/blink/renderer/core/html/html_anchor_element.idl
@@ -19,8 +19,10 @@
  */
 
 // https://html.spec.whatwg.org/C/#the-a-element
-[HTMLConstructor]
-interface HTMLAnchorElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLAnchorElement : HTMLElement {
     [CEReactions, Reflect] attribute DOMString target;
     [CEReactions, Reflect] attribute DOMString download;
     [CEReactions, Reflect] attribute USVString ping;
diff --git a/third_party/blink/renderer/core/html/html_area_element.idl b/third_party/blink/renderer/core/html/html_area_element.idl
index a6d1728c..e213527 100644
--- a/third_party/blink/renderer/core/html/html_area_element.idl
+++ b/third_party/blink/renderer/core/html/html_area_element.idl
@@ -19,8 +19,10 @@
  */
 
 // https://html.spec.whatwg.org/C/#the-area-element
-[HTMLConstructor]
-interface HTMLAreaElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLAreaElement : HTMLElement {
     [CEReactions, Reflect] attribute DOMString alt;
     [CEReactions, Reflect] attribute DOMString coords;
     [CEReactions, Reflect] attribute DOMString download;
diff --git a/third_party/blink/renderer/core/html/html_base_element.idl b/third_party/blink/renderer/core/html/html_base_element.idl
index 5d6fec7..40e2384 100644
--- a/third_party/blink/renderer/core/html/html_base_element.idl
+++ b/third_party/blink/renderer/core/html/html_base_element.idl
@@ -18,8 +18,10 @@
  */
 
 // https://html.spec.whatwg.org/C/#the-base-element
-[HTMLConstructor]
-interface HTMLBaseElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLBaseElement : HTMLElement {
     [CEReactions, RaisesException=Setter] attribute URLString href;
     [CEReactions, Reflect] attribute DOMString target;
 };
diff --git a/third_party/blink/renderer/core/html/html_body_element.idl b/third_party/blink/renderer/core/html/html_body_element.idl
index c616fb17..53a8f4b 100644
--- a/third_party/blink/renderer/core/html/html_body_element.idl
+++ b/third_party/blink/renderer/core/html/html_body_element.idl
@@ -19,8 +19,10 @@
  */
 
 // https://html.spec.whatwg.org/C/#the-body-element
-[HTMLConstructor]
-interface HTMLBodyElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLBodyElement : HTMLElement {
     // obsolete members
     // https://html.spec.whatwg.org/C/#HTMLBodyElement-partial
     [CEReactions, Reflect] attribute [TreatNullAs=EmptyString] DOMString text;
diff --git a/third_party/blink/renderer/core/html/html_br_element.idl b/third_party/blink/renderer/core/html/html_br_element.idl
index 22ebfae..2751dd6 100644
--- a/third_party/blink/renderer/core/html/html_br_element.idl
+++ b/third_party/blink/renderer/core/html/html_br_element.idl
@@ -18,8 +18,10 @@
  */
 
 // https://html.spec.whatwg.org/C/#the-br-element
-[HTMLConstructor]
-interface HTMLBRElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLBRElement : HTMLElement {
     // obsolete members
     // https://html.spec.whatwg.org/C/#HTMLBRElement-partial
     [CEReactions, Reflect] attribute DOMString clear;
diff --git a/third_party/blink/renderer/core/html/html_data_element.idl b/third_party/blink/renderer/core/html/html_data_element.idl
index 3006a5c..6afc987 100644
--- a/third_party/blink/renderer/core/html/html_data_element.idl
+++ b/third_party/blink/renderer/core/html/html_data_element.idl
@@ -4,7 +4,9 @@
 
 // https://html.spec.whatwg.org/C/#the-data-element
 
-[HTMLConstructor]
-interface HTMLDataElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLDataElement : HTMLElement {
     [CEReactions, Reflect] attribute DOMString value;
 };
\ No newline at end of file
diff --git a/third_party/blink/renderer/core/html/html_details_element.idl b/third_party/blink/renderer/core/html/html_details_element.idl
index 70eb7308..20036a9 100644
--- a/third_party/blink/renderer/core/html/html_details_element.idl
+++ b/third_party/blink/renderer/core/html/html_details_element.idl
@@ -18,7 +18,9 @@
  */
 
 // https://html.spec.whatwg.org/C/#the-details-element
-[HTMLConstructor]
-interface HTMLDetailsElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLDetailsElement : HTMLElement {
     [CEReactions, Reflect] attribute boolean open;
 };
diff --git a/third_party/blink/renderer/core/html/html_dialog_element.idl b/third_party/blink/renderer/core/html/html_dialog_element.idl
index 2a69508..3137ce1 100644
--- a/third_party/blink/renderer/core/html/html_dialog_element.idl
+++ b/third_party/blink/renderer/core/html/html_dialog_element.idl
@@ -24,8 +24,10 @@
  */
 
 // https://html.spec.whatwg.org/C/#the-dialog-element
-[HTMLConstructor]
-interface HTMLDialogElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLDialogElement : HTMLElement {
     [CEReactions, Reflect] attribute boolean open;
     attribute DOMString returnValue;
     [CEReactions] void show();
diff --git a/third_party/blink/renderer/core/html/html_directory_element.idl b/third_party/blink/renderer/core/html/html_directory_element.idl
index 58b0922..fe91d06 100644
--- a/third_party/blink/renderer/core/html/html_directory_element.idl
+++ b/third_party/blink/renderer/core/html/html_directory_element.idl
@@ -18,7 +18,9 @@
  */
 
 // https://html.spec.whatwg.org/C/#htmldirectoryelement
-[HTMLConstructor]
-interface HTMLDirectoryElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLDirectoryElement : HTMLElement {
     [CEReactions, Reflect] attribute boolean compact;
 };
diff --git a/third_party/blink/renderer/core/html/html_div_element.idl b/third_party/blink/renderer/core/html/html_div_element.idl
index 04a0751..3ae6964 100644
--- a/third_party/blink/renderer/core/html/html_div_element.idl
+++ b/third_party/blink/renderer/core/html/html_div_element.idl
@@ -18,8 +18,10 @@
  */
 
 // https://html.spec.whatwg.org/C/#the-div-element
-[HTMLConstructor]
-interface HTMLDivElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLDivElement : HTMLElement {
     // obsolete members
     // https://html.spec.whatwg.org/C/#HTMLDivElement-partial
     [CEReactions, Reflect] attribute DOMString align;
diff --git a/third_party/blink/renderer/core/html/html_dlist_element.idl b/third_party/blink/renderer/core/html/html_dlist_element.idl
index ef594e14..bf5e720c 100644
--- a/third_party/blink/renderer/core/html/html_dlist_element.idl
+++ b/third_party/blink/renderer/core/html/html_dlist_element.idl
@@ -18,8 +18,10 @@
  */
 
 // https://html.spec.whatwg.org/C/#the-dl-element
-[HTMLConstructor]
-interface HTMLDListElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLDListElement : HTMLElement {
     // obsolete members
     // https://html.spec.whatwg.org/C/#HTMLDListElement-partial
     [CEReactions, Reflect] attribute boolean compact;
diff --git a/third_party/blink/renderer/core/html/html_document.idl b/third_party/blink/renderer/core/html/html_document.idl
index 938136e..24f6db8 100644
--- a/third_party/blink/renderer/core/html/html_document.idl
+++ b/third_party/blink/renderer/core/html/html_document.idl
@@ -22,6 +22,6 @@
 // writable, configurable, non-enumerable property named HTMLDocument
 // whose value is the Document interface object."
 // https://html.spec.whatwg.org/C/#the-window-object
-
+[Exposed=Window]
 interface HTMLDocument : Document {
 };
diff --git a/third_party/blink/renderer/core/html/html_embed_element.idl b/third_party/blink/renderer/core/html/html_embed_element.idl
index 1e698b5..800a6bc 100644
--- a/third_party/blink/renderer/core/html/html_embed_element.idl
+++ b/third_party/blink/renderer/core/html/html_embed_element.idl
@@ -22,6 +22,7 @@
 
 // TODO(yukishiino): HTMLEmbedElement should not have [OverrideBuiltins].
 [
+    Exposed=Window,
     OverrideBuiltins,
     ActiveScriptWrappable,
     HTMLConstructor
diff --git a/third_party/blink/renderer/core/html/html_font_element.idl b/third_party/blink/renderer/core/html/html_font_element.idl
index 8ff4ec16..b4f6d99 100644
--- a/third_party/blink/renderer/core/html/html_font_element.idl
+++ b/third_party/blink/renderer/core/html/html_font_element.idl
@@ -18,8 +18,10 @@
  */
 
 // https://html.spec.whatwg.org/C/#htmlfontelement
-[HTMLConstructor]
-interface HTMLFontElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLFontElement : HTMLElement {
     [CEReactions, Reflect] attribute [TreatNullAs=EmptyString] DOMString color;
     [CEReactions, Reflect] attribute DOMString face;
     [CEReactions, Reflect] attribute DOMString size;
diff --git a/third_party/blink/renderer/core/html/html_frame_element.idl b/third_party/blink/renderer/core/html/html_frame_element.idl
index 0248a35..5a52b78 100644
--- a/third_party/blink/renderer/core/html/html_frame_element.idl
+++ b/third_party/blink/renderer/core/html/html_frame_element.idl
@@ -20,8 +20,10 @@
 
 // https://html.spec.whatwg.org/C/#htmlframeelement
 
-[HTMLConstructor]
-interface HTMLFrameElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLFrameElement : HTMLElement {
     [CEReactions, Reflect] attribute DOMString name;
     [CEReactions, Reflect] attribute DOMString scrolling;
     [CEReactions, Reflect, URL, RaisesException=Setter] attribute URLString src;
diff --git a/third_party/blink/renderer/core/html/html_frame_set_element.idl b/third_party/blink/renderer/core/html/html_frame_set_element.idl
index 6a6733ed..2b8e2b11 100644
--- a/third_party/blink/renderer/core/html/html_frame_set_element.idl
+++ b/third_party/blink/renderer/core/html/html_frame_set_element.idl
@@ -22,6 +22,7 @@
 
 // FIXME: HTMLFrameSetElement should not have [OverrideBuiltins].
 [
+    Exposed=Window,
     HTMLConstructor,
     OverrideBuiltins
 ] interface HTMLFrameSetElement : HTMLElement {
diff --git a/third_party/blink/renderer/core/html/html_head_element.idl b/third_party/blink/renderer/core/html/html_head_element.idl
index 34b7b3c..f19f501 100644
--- a/third_party/blink/renderer/core/html/html_head_element.idl
+++ b/third_party/blink/renderer/core/html/html_head_element.idl
@@ -18,6 +18,8 @@
  */
 
 // https://html.spec.whatwg.org/C/#the-head-element
-[HTMLConstructor]
-interface HTMLHeadElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLHeadElement : HTMLElement {
 };
diff --git a/third_party/blink/renderer/core/html/html_heading_element.idl b/third_party/blink/renderer/core/html/html_heading_element.idl
index 8b7fe5d..b4e427da 100644
--- a/third_party/blink/renderer/core/html/html_heading_element.idl
+++ b/third_party/blink/renderer/core/html/html_heading_element.idl
@@ -18,8 +18,10 @@
  */
 
 // https://html.spec.whatwg.org/C/#the-h1,-h2,-h3,-h4,-h5,-and-h6-elements
-[HTMLConstructor]
-interface HTMLHeadingElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLHeadingElement : HTMLElement {
     // obsolete members
     // https://html.spec.whatwg.org/C/#HTMLHeadingElement-partial
     [CEReactions, Reflect] attribute DOMString align;
diff --git a/third_party/blink/renderer/core/html/html_hr_element.idl b/third_party/blink/renderer/core/html/html_hr_element.idl
index dda79b1..51538318 100644
--- a/third_party/blink/renderer/core/html/html_hr_element.idl
+++ b/third_party/blink/renderer/core/html/html_hr_element.idl
@@ -18,8 +18,10 @@
  */
 
 // https://html.spec.whatwg.org/C/#the-hr-element
-[HTMLConstructor]
-interface HTMLHRElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLHRElement : HTMLElement {
     // obsolete members
     // https://html.spec.whatwg.org/C/#HTMLHRElement-partial
     [CEReactions, Reflect] attribute DOMString align;
diff --git a/third_party/blink/renderer/core/html/html_html_element.idl b/third_party/blink/renderer/core/html/html_html_element.idl
index 5683c27..cd5f7112 100644
--- a/third_party/blink/renderer/core/html/html_html_element.idl
+++ b/third_party/blink/renderer/core/html/html_html_element.idl
@@ -18,8 +18,10 @@
  */
 
 // https://html.spec.whatwg.org/C/#the-html-element
-[HTMLConstructor]
-interface HTMLHtmlElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLHtmlElement : HTMLElement {
     // obsolete members
     // https://html.spec.whatwg.org/C/#HTMLHtmlElement-partial
     [CEReactions, Reflect] attribute DOMString version;
diff --git a/third_party/blink/renderer/core/html/html_image_element.idl b/third_party/blink/renderer/core/html/html_image_element.idl
index 4d332ec..a572a173 100644
--- a/third_party/blink/renderer/core/html/html_image_element.idl
+++ b/third_party/blink/renderer/core/html/html_image_element.idl
@@ -21,6 +21,7 @@
 // https://html.spec.whatwg.org/C/#the-img-element
 
 [
+    Exposed=Window,
     ActiveScriptWrappable,
     ConstructorCallWith=Document,
     HTMLConstructor,
diff --git a/third_party/blink/renderer/core/html/html_li_element.idl b/third_party/blink/renderer/core/html/html_li_element.idl
index 134b750b..c605235 100644
--- a/third_party/blink/renderer/core/html/html_li_element.idl
+++ b/third_party/blink/renderer/core/html/html_li_element.idl
@@ -18,8 +18,10 @@
  */
 
 // https://html.spec.whatwg.org/C/#the-li-element
-[HTMLConstructor]
-interface HTMLLIElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLLIElement : HTMLElement {
     [CEReactions, Reflect] attribute long value;
 
     // obsolete members
diff --git a/third_party/blink/renderer/core/html/html_link_element.idl b/third_party/blink/renderer/core/html/html_link_element.idl
index e812054..c2841765 100644
--- a/third_party/blink/renderer/core/html/html_link_element.idl
+++ b/third_party/blink/renderer/core/html/html_link_element.idl
@@ -20,8 +20,10 @@
  */
 
 // https://html.spec.whatwg.org/C/#the-link-element
-[HTMLConstructor]
-interface HTMLLinkElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLLinkElement : HTMLElement {
     // FIXME: The disabled attribute has been removed from the spec:
     // https://www.w3.org/Bugs/Public/show_bug.cgi?id=14703
     [Reflect, Measure] attribute boolean disabled;
diff --git a/third_party/blink/renderer/core/html/html_map_element.idl b/third_party/blink/renderer/core/html/html_map_element.idl
index 847c2e3..9c8fe9f 100644
--- a/third_party/blink/renderer/core/html/html_map_element.idl
+++ b/third_party/blink/renderer/core/html/html_map_element.idl
@@ -19,8 +19,10 @@
  */
 
 // https://html.spec.whatwg.org/C/#the-map-element
-[HTMLConstructor]
-interface HTMLMapElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLMapElement : HTMLElement {
     [CEReactions, Reflect] attribute DOMString name;
     readonly attribute HTMLCollection areas;
 };
diff --git a/third_party/blink/renderer/core/html/html_marquee_element.idl b/third_party/blink/renderer/core/html/html_marquee_element.idl
index d880323..54e6d4d 100644
--- a/third_party/blink/renderer/core/html/html_marquee_element.idl
+++ b/third_party/blink/renderer/core/html/html_marquee_element.idl
@@ -18,8 +18,10 @@
  */
 
 // https://html.spec.whatwg.org/C/#htmlmarqueeelement
-[HTMLConstructor]
-interface HTMLMarqueeElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLMarqueeElement : HTMLElement {
     [Reflect] attribute DOMString behavior;
     [Reflect] attribute DOMString bgColor;
     [Reflect] attribute DOMString direction;
diff --git a/third_party/blink/renderer/core/html/html_menu_element.idl b/third_party/blink/renderer/core/html/html_menu_element.idl
index 74c8a60..40c701c 100644
--- a/third_party/blink/renderer/core/html/html_menu_element.idl
+++ b/third_party/blink/renderer/core/html/html_menu_element.idl
@@ -18,8 +18,10 @@
  */
 
 // https://html.spec.whatwg.org/C/#the-menu-element
-[HTMLConstructor]
-interface HTMLMenuElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLMenuElement : HTMLElement {
     // obsolete members
     // https://html.spec.whatwg.org/C/#HTMLMenuElement-partial
     [CEReactions, Reflect] attribute boolean compact;
diff --git a/third_party/blink/renderer/core/html/html_meta_element.idl b/third_party/blink/renderer/core/html/html_meta_element.idl
index 437193f..09148a8 100644
--- a/third_party/blink/renderer/core/html/html_meta_element.idl
+++ b/third_party/blink/renderer/core/html/html_meta_element.idl
@@ -18,8 +18,10 @@
  */
 
 // https://html.spec.whatwg.org/C/#the-meta-element
-[HTMLConstructor]
-interface HTMLMetaElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLMetaElement : HTMLElement {
     [CEReactions, Reflect] attribute DOMString name;
     [CEReactions, Reflect=http_equiv] attribute DOMString httpEquiv;
     [CEReactions, Reflect] attribute DOMString content;
diff --git a/third_party/blink/renderer/core/html/html_meter_element.idl b/third_party/blink/renderer/core/html/html_meter_element.idl
index ad4c7d1..14e99617 100644
--- a/third_party/blink/renderer/core/html/html_meter_element.idl
+++ b/third_party/blink/renderer/core/html/html_meter_element.idl
@@ -18,8 +18,10 @@
  */
 
 // https://html.spec.whatwg.org/C/#the-meter-element
-[HTMLConstructor]
-interface HTMLMeterElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLMeterElement : HTMLElement {
     [CEReactions] attribute double value;
     [CEReactions] attribute double min;
     [CEReactions] attribute double max;
diff --git a/third_party/blink/renderer/core/html/html_mod_element.idl b/third_party/blink/renderer/core/html/html_mod_element.idl
index 0ed79d98..472717b 100644
--- a/third_party/blink/renderer/core/html/html_mod_element.idl
+++ b/third_party/blink/renderer/core/html/html_mod_element.idl
@@ -19,8 +19,10 @@
 
 // https://html.spec.whatwg.org/C/#the-ins-element
 // https://html.spec.whatwg.org/C/#the-del-element
-[HTMLConstructor]
-interface HTMLModElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLModElement : HTMLElement {
     [CEReactions, Reflect, URL] attribute DOMString cite;
     [CEReactions, Reflect] attribute DOMString dateTime;
 };
diff --git a/third_party/blink/renderer/core/html/html_object_element.idl b/third_party/blink/renderer/core/html/html_object_element.idl
index bca66e9..1279fd48 100644
--- a/third_party/blink/renderer/core/html/html_object_element.idl
+++ b/third_party/blink/renderer/core/html/html_object_element.idl
@@ -22,6 +22,7 @@
 
 // TODO(yukishiino): HTMLObjectElement should not have [OverrideBuiltins].
 [
+    Exposed=Window,
     OverrideBuiltins,
     ActiveScriptWrappable,
     HTMLConstructor
diff --git a/third_party/blink/renderer/core/html/html_olist_element.idl b/third_party/blink/renderer/core/html/html_olist_element.idl
index b47d8670..bc6ab71 100644
--- a/third_party/blink/renderer/core/html/html_olist_element.idl
+++ b/third_party/blink/renderer/core/html/html_olist_element.idl
@@ -18,8 +18,10 @@
  */
 
 // https://html.spec.whatwg.org/C/#the-ol-element
-[HTMLConstructor]
-interface HTMLOListElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLOListElement : HTMLElement {
     [CEReactions, Reflect] attribute boolean reversed;
     [CEReactions] attribute long start;
     [CEReactions, Reflect] attribute DOMString type;
diff --git a/third_party/blink/renderer/core/html/html_paragraph_element.idl b/third_party/blink/renderer/core/html/html_paragraph_element.idl
index 773d976..804adcc 100644
--- a/third_party/blink/renderer/core/html/html_paragraph_element.idl
+++ b/third_party/blink/renderer/core/html/html_paragraph_element.idl
@@ -18,8 +18,10 @@
  */
 
 // https://html.spec.whatwg.org/C/#the-p-element
-[HTMLConstructor]
-interface HTMLParagraphElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLParagraphElement : HTMLElement {
     // obsolete members
     // https://html.spec.whatwg.org/C/#HTMLParagraphElement-partial
     [CEReactions, Reflect] attribute DOMString align;
diff --git a/third_party/blink/renderer/core/html/html_param_element.idl b/third_party/blink/renderer/core/html/html_param_element.idl
index 1359fe70..5ed4a3a 100644
--- a/third_party/blink/renderer/core/html/html_param_element.idl
+++ b/third_party/blink/renderer/core/html/html_param_element.idl
@@ -18,8 +18,10 @@
  */
 
 // https://html.spec.whatwg.org/C/#the-param-element
-[HTMLConstructor]
-interface HTMLParamElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLParamElement : HTMLElement {
     [CEReactions, Reflect] attribute DOMString name;
     [CEReactions, Reflect] attribute DOMString value;
 
diff --git a/third_party/blink/renderer/core/html/html_picture_element.idl b/third_party/blink/renderer/core/html/html_picture_element.idl
index 4dced65..c09e2fc 100644
--- a/third_party/blink/renderer/core/html/html_picture_element.idl
+++ b/third_party/blink/renderer/core/html/html_picture_element.idl
@@ -3,6 +3,8 @@
 // found in the LICENSE file.
 
 // https://html.spec.whatwg.org/C/#the-picture-element
-[HTMLConstructor]
-interface HTMLPictureElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLPictureElement : HTMLElement {
 };
diff --git a/third_party/blink/renderer/core/html/html_pre_element.idl b/third_party/blink/renderer/core/html/html_pre_element.idl
index 3d527ff..80ba787 100644
--- a/third_party/blink/renderer/core/html/html_pre_element.idl
+++ b/third_party/blink/renderer/core/html/html_pre_element.idl
@@ -19,8 +19,10 @@
  */
 
 // https://html.spec.whatwg.org/C/#the-pre-element
-[HTMLConstructor]
-interface HTMLPreElement : HTMLElement {
+[
+    HTMLConstructor,
+    Exposed=Window
+] interface HTMLPreElement : HTMLElement {
     // obsolete members
     // https://html.spec.whatwg.org/C/#HTMLPreElement-partial
     [CEReactions, Reflect] attribute long width;
diff --git a/third_party/blink/renderer/core/html/html_progress_element.idl b/third_party/blink/renderer/core/html/html_progress_element.idl
index 6cb8ed6a..4c2c66df 100644
--- a/third_party/blink/renderer/core/html/html_progress_element.idl
+++ b/third_party/blink/renderer/core/html/html_progress_element.idl
@@ -18,8 +18,10 @@
  */
 
 // https://html.spec.whatwg.org/C/#the-progress-element
-[HTMLConstructor]
-interface HTMLProgressElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLProgressElement : HTMLElement {
     [CEReactions] attribute double value;
     [CEReactions] attribute double max;
     readonly attribute double position;
diff --git a/third_party/blink/renderer/core/html/html_quote_element.idl b/third_party/blink/renderer/core/html/html_quote_element.idl
index 26ebbc8..7b6e62dd 100644
--- a/third_party/blink/renderer/core/html/html_quote_element.idl
+++ b/third_party/blink/renderer/core/html/html_quote_element.idl
@@ -19,7 +19,9 @@
 
 // https://html.spec.whatwg.org/C/#the-blockquote-element
 // https://html.spec.whatwg.org/C/#the-q-element
-[HTMLConstructor]
-interface HTMLQuoteElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLQuoteElement : HTMLElement {
     [CEReactions, Reflect, URL] attribute DOMString cite;
 };
diff --git a/third_party/blink/renderer/core/html/html_script_element.idl b/third_party/blink/renderer/core/html/html_script_element.idl
index 475f5516..2d6feee4 100644
--- a/third_party/blink/renderer/core/html/html_script_element.idl
+++ b/third_party/blink/renderer/core/html/html_script_element.idl
@@ -18,8 +18,10 @@
  */
 
 // https://html.spec.whatwg.org/C/#the-script-element
-[HTMLConstructor]
-interface HTMLScriptElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLScriptElement : HTMLElement {
     [CEReactions, Reflect, URL, RaisesException=Setter] attribute ScriptURLString src;
     [CEReactions, Reflect] attribute DOMString type;
     [CEReactions, Reflect] attribute boolean noModule;
diff --git a/third_party/blink/renderer/core/html/html_source_element.idl b/third_party/blink/renderer/core/html/html_source_element.idl
index acf73961..6ab643a 100644
--- a/third_party/blink/renderer/core/html/html_source_element.idl
+++ b/third_party/blink/renderer/core/html/html_source_element.idl
@@ -24,8 +24,10 @@
  */
 
 // https://html.spec.whatwg.org/C/#the-source-element
-[HTMLConstructor]
-interface HTMLSourceElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLSourceElement : HTMLElement {
     [CEReactions, Reflect, URL, RaisesException=Setter] attribute URLString src;
     [CEReactions] attribute DOMString type;
 
diff --git a/third_party/blink/renderer/core/html/html_span_element.idl b/third_party/blink/renderer/core/html/html_span_element.idl
index 6fcc37d..1cb60a2 100644
--- a/third_party/blink/renderer/core/html/html_span_element.idl
+++ b/third_party/blink/renderer/core/html/html_span_element.idl
@@ -24,6 +24,8 @@
  */
 
 // https://html.spec.whatwg.org/C/#the-span-element
-[HTMLConstructor]
-interface HTMLSpanElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLSpanElement : HTMLElement {
 };
diff --git a/third_party/blink/renderer/core/html/html_style_element.idl b/third_party/blink/renderer/core/html/html_style_element.idl
index f2134900..5370a36 100644
--- a/third_party/blink/renderer/core/html/html_style_element.idl
+++ b/third_party/blink/renderer/core/html/html_style_element.idl
@@ -19,8 +19,10 @@
  */
 
 // https://html.spec.whatwg.org/C/#the-style-element
-[HTMLConstructor]
-interface HTMLStyleElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLStyleElement : HTMLElement {
     // TODO(foolip): The disabled attribute has been removed from the spec:
     // https://www.w3.org/Bugs/Public/show_bug.cgi?id=14703
     [Measure] attribute boolean disabled;
diff --git a/third_party/blink/renderer/core/html/html_table_caption_element.idl b/third_party/blink/renderer/core/html/html_table_caption_element.idl
index 030d384..386b675 100644
--- a/third_party/blink/renderer/core/html/html_table_caption_element.idl
+++ b/third_party/blink/renderer/core/html/html_table_caption_element.idl
@@ -19,8 +19,10 @@
  */
 
 // https://html.spec.whatwg.org/C/#the-caption-element
-[HTMLConstructor]
-interface HTMLTableCaptionElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLTableCaptionElement : HTMLElement {
     // obsolete members
     // https://html.spec.whatwg.org/C/#HTMLTableCaptionElement-partial
     [CEReactions, Reflect] attribute DOMString align;
diff --git a/third_party/blink/renderer/core/html/html_table_cell_element.idl b/third_party/blink/renderer/core/html/html_table_cell_element.idl
index 29d6d5a..d29dce03 100644
--- a/third_party/blink/renderer/core/html/html_table_cell_element.idl
+++ b/third_party/blink/renderer/core/html/html_table_cell_element.idl
@@ -19,8 +19,10 @@
  */
 
 // https://html.spec.whatwg.org/C/#attributes-common-to-td-and-th-elements
-[HTMLConstructor]
-interface HTMLTableCellElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLTableCellElement : HTMLElement {
     [CEReactions] attribute unsigned long colSpan;
     [CEReactions] attribute unsigned long rowSpan;
     // TODO(foolip): headers should be a [PutForwards=value] readonly attribute
diff --git a/third_party/blink/renderer/core/html/html_table_col_element.idl b/third_party/blink/renderer/core/html/html_table_col_element.idl
index 42afbc1..32295d3 100644
--- a/third_party/blink/renderer/core/html/html_table_col_element.idl
+++ b/third_party/blink/renderer/core/html/html_table_col_element.idl
@@ -20,8 +20,10 @@
 
 // https://html.spec.whatwg.org/C/#the-colgroup-element
 // https://html.spec.whatwg.org/C/#the-col-element
-[HTMLConstructor]
-interface HTMLTableColElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLTableColElement : HTMLElement {
     [CEReactions] attribute unsigned long span;
 
     // obsolete attributes
diff --git a/third_party/blink/renderer/core/html/html_table_element.idl b/third_party/blink/renderer/core/html/html_table_element.idl
index a057d4d..9d773aa 100644
--- a/third_party/blink/renderer/core/html/html_table_element.idl
+++ b/third_party/blink/renderer/core/html/html_table_element.idl
@@ -19,8 +19,10 @@
  */
 
 // https://html.spec.whatwg.org/C/#the-table-element
-[HTMLConstructor]
-interface HTMLTableElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLTableElement : HTMLElement {
     [CEReactions, RaisesException=Setter] attribute HTMLTableCaptionElement? caption;
     [CEReactions] HTMLTableCaptionElement createCaption();
     [CEReactions] void deleteCaption();
diff --git a/third_party/blink/renderer/core/html/html_table_row_element.idl b/third_party/blink/renderer/core/html/html_table_row_element.idl
index 9965d481..50afa319e 100644
--- a/third_party/blink/renderer/core/html/html_table_row_element.idl
+++ b/third_party/blink/renderer/core/html/html_table_row_element.idl
@@ -19,8 +19,10 @@
  */
 
 // https://html.spec.whatwg.org/C/#the-tr-element
-[HTMLConstructor]
-interface HTMLTableRowElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLTableRowElement : HTMLElement {
     readonly attribute long rowIndex;
     readonly attribute long sectionRowIndex;
     readonly attribute HTMLCollection cells;
diff --git a/third_party/blink/renderer/core/html/html_table_section_element.idl b/third_party/blink/renderer/core/html/html_table_section_element.idl
index b95a4946..4859cd2 100644
--- a/third_party/blink/renderer/core/html/html_table_section_element.idl
+++ b/third_party/blink/renderer/core/html/html_table_section_element.idl
@@ -21,8 +21,10 @@
 // https://html.spec.whatwg.org/C/#the-tbody-element
 // https://html.spec.whatwg.org/C/#the-thead-element
 // https://html.spec.whatwg.org/C/#the-tfoot-element
-[HTMLConstructor]
-interface HTMLTableSectionElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLTableSectionElement : HTMLElement {
     readonly attribute HTMLCollection rows;
     [CEReactions, RaisesException] HTMLElement insertRow(optional long index = -1);
     [CEReactions, RaisesException] void deleteRow(long index);
diff --git a/third_party/blink/renderer/core/html/html_template_element.idl b/third_party/blink/renderer/core/html/html_template_element.idl
index 2d8fdfb..ebfd32c 100644
--- a/third_party/blink/renderer/core/html/html_template_element.idl
+++ b/third_party/blink/renderer/core/html/html_template_element.idl
@@ -29,7 +29,9 @@
  */
 
 // https://html.spec.whatwg.org/C/#the-template-element
-[HTMLConstructor]
-interface HTMLTemplateElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLTemplateElement : HTMLElement {
     readonly attribute DocumentFragment content;
 };
diff --git a/third_party/blink/renderer/core/html/html_time_element.idl b/third_party/blink/renderer/core/html/html_time_element.idl
index 3f6e0c95..d0fd76bd 100644
--- a/third_party/blink/renderer/core/html/html_time_element.idl
+++ b/third_party/blink/renderer/core/html/html_time_element.idl
@@ -4,7 +4,9 @@
 
 // https://html.spec.whatwg.org/C/#the-time-element
 
-[HTMLConstructor]
-interface HTMLTimeElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLTimeElement : HTMLElement {
     [CEReactions, Reflect] attribute DOMString dateTime;
 };
\ No newline at end of file
diff --git a/third_party/blink/renderer/core/html/html_title_element.idl b/third_party/blink/renderer/core/html/html_title_element.idl
index c28e9c0..191b831 100644
--- a/third_party/blink/renderer/core/html/html_title_element.idl
+++ b/third_party/blink/renderer/core/html/html_title_element.idl
@@ -18,7 +18,9 @@
  */
 
 // https://html.spec.whatwg.org/C/#the-title-element
-[HTMLConstructor]
-interface HTMLTitleElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLTitleElement : HTMLElement {
     [CEReactions] attribute DOMString text;
 };
diff --git a/third_party/blink/renderer/core/html/html_ulist_element.idl b/third_party/blink/renderer/core/html/html_ulist_element.idl
index 7a0f2cd4..3a16e70 100644
--- a/third_party/blink/renderer/core/html/html_ulist_element.idl
+++ b/third_party/blink/renderer/core/html/html_ulist_element.idl
@@ -18,8 +18,10 @@
  */
 
 // https://html.spec.whatwg.org/C/#the-ul-element
-[HTMLConstructor]
-interface HTMLUListElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLUListElement : HTMLElement {
     // obsolete members
     // https://html.spec.whatwg.org/C/#HTMLUListElement-partial
     [CEReactions, Reflect] attribute boolean compact;
diff --git a/third_party/blink/renderer/core/html/time_ranges.idl b/third_party/blink/renderer/core/html/time_ranges.idl
index f153bee..1f2aa210 100644
--- a/third_party/blink/renderer/core/html/time_ranges.idl
+++ b/third_party/blink/renderer/core/html/time_ranges.idl
@@ -25,6 +25,7 @@
 
 // https://html.spec.whatwg.org/C/#time-ranges
 
+[Exposed=Window]
 interface TimeRanges {
     readonly attribute unsigned long length;
     [RaisesException] double start(unsigned long index);
diff --git a/third_party/blink/renderer/core/layout/BUILD.gn b/third_party/blink/renderer/core/layout/BUILD.gn
index 1b36cc86..2252fa4 100644
--- a/third_party/blink/renderer/core/layout/BUILD.gn
+++ b/third_party/blink/renderer/core/layout/BUILD.gn
@@ -349,7 +349,6 @@
     "ng/inline/ng_inline_item_result.h",
     "ng/inline/ng_inline_item_segment.cc",
     "ng/inline/ng_inline_item_segment.h",
-    "ng/inline/ng_inline_items.h",
     "ng/inline/ng_inline_items_builder.cc",
     "ng/inline/ng_inline_items_builder.h",
     "ng/inline/ng_inline_layout_algorithm.cc",
diff --git a/third_party/blink/renderer/core/layout/layout_text.cc b/third_party/blink/renderer/core/layout/layout_text.cc
index d091ba9..2a2510f 100644
--- a/third_party/blink/renderer/core/layout/layout_text.cc
+++ b/third_party/blink/renderer/core/layout/layout_text.cc
@@ -2404,23 +2404,23 @@
     DCHECK_EQ(item->GetLayoutObject(), this);
   }
 #endif
-  NGInlineItems* items = GetNGInlineItems();
+  base::span<NGInlineItem>* items = GetNGInlineItems();
   if (!items)
     return;
   valid_ng_items_ = true;
-  items->SetRange(begin, end);
+  *items = base::make_span(begin, end);
 }
 
 void LayoutText::ClearInlineItems() {
   valid_ng_items_ = false;
-  if (NGInlineItems* items = GetNGInlineItems())
-    items->Clear();
+  if (base::span<NGInlineItem>* items = GetNGInlineItems())
+    *items = base::span<NGInlineItem>();
 }
 
-const NGInlineItems& LayoutText::InlineItems() const {
+const base::span<NGInlineItem>& LayoutText::InlineItems() const {
   DCHECK(valid_ng_items_);
   DCHECK(GetNGInlineItems());
-  DCHECK(!GetNGInlineItems()->IsEmpty());
+  DCHECK(!GetNGInlineItems()->empty());
   return *GetNGInlineItems();
 }
 
diff --git a/third_party/blink/renderer/core/layout/layout_text.h b/third_party/blink/renderer/core/layout/layout_text.h
index 105eef1..3367b57 100644
--- a/third_party/blink/renderer/core/layout/layout_text.h
+++ b/third_party/blink/renderer/core/layout/layout_text.h
@@ -40,7 +40,6 @@
 class ContentCaptureManager;
 class InlineTextBox;
 class NGInlineItem;
-class NGInlineItems;
 class NGOffsetMapping;
 
 enum class OnlyWhitespaceOrNbsp : unsigned { kUnknown = 0, kNo = 1, kYes = 2 };
@@ -316,14 +315,16 @@
   void SetInlineItems(NGInlineItem* begin, NGInlineItem* end);
   void ClearInlineItems();
   bool HasValidInlineItems() const { return valid_ng_items_; }
-  const NGInlineItems& InlineItems() const;
+  const base::span<NGInlineItem>& InlineItems() const;
   // Inline items depends on context. It needs to be invalidated not only when
   // it was inserted/changed but also it was moved.
   void InvalidateInlineItems() { valid_ng_items_ = false; }
 
  protected:
-  virtual const NGInlineItems* GetNGInlineItems() const { return nullptr; }
-  virtual NGInlineItems* GetNGInlineItems() { return nullptr; }
+  virtual const base::span<NGInlineItem>* GetNGInlineItems() const {
+    return nullptr;
+  }
+  virtual base::span<NGInlineItem>* GetNGInlineItems() { return nullptr; }
   void WillBeDestroyed() override;
 
   void StyleWillChange(StyleDifference, const ComputedStyle&) final {}
diff --git a/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text.h b/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text.h
index 4e2517f..a03bdd4 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text.h
+++ b/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text.h
@@ -6,7 +6,6 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_LAYOUT_NG_TEXT_H_
 
 #include "third_party/blink/renderer/core/layout/layout_text.h"
-#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_items.h"
 
 namespace blink {
 
@@ -24,10 +23,12 @@
   bool IsLayoutNGObject() const override { return true; }
 
  private:
-  const NGInlineItems* GetNGInlineItems() const final { return &inline_items_; }
-  NGInlineItems* GetNGInlineItems() final { return &inline_items_; }
+  const base::span<NGInlineItem>* GetNGInlineItems() const final {
+    return &inline_items_;
+  }
+  base::span<NGInlineItem>* GetNGInlineItems() final { return &inline_items_; }
 
-  NGInlineItems inline_items_;
+  base::span<NGInlineItem> inline_items_;
 };
 
 DEFINE_LAYOUT_OBJECT_TYPE_CASTS(LayoutNGText, IsLayoutNGText());
diff --git a/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_fragment.h b/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_fragment.h
index 130a7b4..0612bfa 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_fragment.h
+++ b/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_fragment.h
@@ -6,7 +6,6 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_LAYOUT_NG_TEXT_FRAGMENT_H_
 
 #include "third_party/blink/renderer/core/layout/layout_text_fragment.h"
-#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_items.h"
 
 namespace blink {
 
@@ -24,15 +23,17 @@
   bool IsLayoutNGObject() const final { return true; }
 
  private:
-  const NGInlineItems* GetNGInlineItems() const final { return &inline_items_; }
-  NGInlineItems* GetNGInlineItems() final { return &inline_items_; }
+  const base::span<NGInlineItem>* GetNGInlineItems() const final {
+    return &inline_items_;
+  }
+  base::span<NGInlineItem>* GetNGInlineItems() final { return &inline_items_; }
 
   void InsertedIntoTree() final {
     valid_ng_items_ = false;
     LayoutText::InsertedIntoTree();
   }
 
-  NGInlineItems inline_items_;
+  base::span<NGInlineItem> inline_items_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items.h b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items.h
deleted file mode 100644
index 063bebd4d..0000000
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2018 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_LAYOUT_NG_INLINE_NG_INLINE_ITEMS_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_INLINE_ITEMS_H_
-
-#include "base/macros.h"
-#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
-
-namespace blink {
-
-class NGInlineItem;
-
-// A collection of |NGInlineItem| associated to |LayoutNGText|.
-//
-// ***** INLINE ITEMS OWNERSHIP *****
-// NGInlineItems in items_ are not owned by LayoutText but are pointers into the
-// LayoutNGBlockFlow's items_. Should not be accessed outside of layout.
-class NGInlineItems final {
- public:
-  NGInlineItems() = default;
-
-  void SetRange(NGInlineItem* begin, NGInlineItem* end) {
-    begin_ = begin;
-    end_ = end;
-  }
-  void Clear() { begin_ = end_ = nullptr; }
-
-  bool IsEmpty() const { return begin_ == end_; }
-
-  const NGInlineItem& front() const {
-    CHECK(!IsEmpty());
-    return *begin_;
-  }
-
-  const NGInlineItem* begin() const { return begin_; }
-  const NGInlineItem* end() const { return end_; }
-
- private:
-  NGInlineItem* begin_ = nullptr;
-  NGInlineItem* end_ = nullptr;
-
-  DISALLOW_COPY_AND_ASSIGN(NGInlineItems);
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_INLINE_ITEMS_H_
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.cc
index 2e450da..7e73000 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.cc
@@ -280,7 +280,7 @@
     const NGInlineNodeData& original_data,
     LayoutText* layout_text) {
   DCHECK(layout_text);
-  const NGInlineItems& items = layout_text->InlineItems();
+  const base::span<NGInlineItem>& items = layout_text->InlineItems();
   const NGInlineItem& old_item0 = items.front();
   if (!old_item0.Length())
     return false;
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc
index a5ac387d..9666bfd 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc
@@ -9,7 +9,6 @@
 #include "third_party/blink/renderer/core/dom/dom_token_list.h"
 #include "third_party/blink/renderer/core/dom/text.h"
 #include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_child_layout_context.h"
-#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_items.h"
 #include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.h"
 #include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h"
 #include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h"
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context.cc b/third_party/blink/renderer/core/loader/frame_fetch_context.cc
index 54b373b..eaff097 100644
--- a/third_party/blink/renderer/core/loader/frame_fetch_context.cc
+++ b/third_party/blink/renderer/core/loader/frame_fetch_context.cc
@@ -433,6 +433,14 @@
 
   if (GetResourceFetcherProperties().IsDetached())
     return;
+
+  if (!frame_or_imported_document_->GetDocumentLoader()) {
+    // When HTML imports are involved, it is dangerous to rely on the
+    // factory bound origin.
+    DCHECK(frame_or_imported_document_->GetDocument().ImportsController());
+    request.SetShouldAlsoUseFactoryBoundOriginForCors(false);
+  }
+
   GetLocalFrameClient()->DispatchWillSendRequest(request);
   FrameScheduler* frame_scheduler = GetFrame()->GetFrameScheduler();
   if (!for_redirect && frame_scheduler) {
diff --git a/third_party/blink/renderer/core/loader/resource/script_resource.cc b/third_party/blink/renderer/core/loader/resource/script_resource.cc
index a6d55d092..dec020f 100644
--- a/third_party/blink/renderer/core/loader/resource/script_resource.cc
+++ b/third_party/blink/renderer/core/loader/resource/script_resource.cc
@@ -415,7 +415,7 @@
     return;
   }
 
-  static bool script_streaming_enabled =
+  static const bool script_streaming_enabled =
       base::FeatureList::IsEnabled(features::kScriptStreaming);
   if (!script_streaming_enabled) {
     return;
diff --git a/third_party/blink/renderer/core/page/chrome_client_impl_test.cc b/third_party/blink/renderer/core/page/chrome_client_impl_test.cc
index 61bc163..2154985 100644
--- a/third_party/blink/renderer/core/page/chrome_client_impl_test.cc
+++ b/third_party/blink/renderer/core/page/chrome_client_impl_test.cc
@@ -230,29 +230,6 @@
   EXPECT_TRUE(CanOpenDateTimeChooser());
 }
 
-// A FileChooserClient which makes FileChooser::OpenFileChooser() success.
-class MockFileChooserClient
-    : public GarbageCollectedFinalized<MockFileChooserClient>,
-      public FileChooserClient {
-  USING_GARBAGE_COLLECTED_MIXIN(MockFileChooserClient);
-
- public:
-  explicit MockFileChooserClient(LocalFrame* frame) : frame_(frame) {}
-  void Trace(Visitor* visitor) override {
-    visitor->Trace(frame_);
-    FileChooserClient::Trace(visitor);
-  }
-
- private:
-  // FilesChosen() and WillOpenPopup() are never called in the test.
-  void FilesChosen(FileChooserFileInfoList, const base::FilePath&) override {}
-  void WillOpenPopup() override {}
-
-  LocalFrame* FrameOrNull() const override { return frame_; }
-
-  Member<LocalFrame> frame_;
-};
-
 class FileChooserQueueTest : public testing::Test {
  protected:
   void SetUp() override {
diff --git a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
index 0050a7d..119d760f 100644
--- a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
+++ b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
@@ -417,6 +417,11 @@
   if (HasBeenDisposed() || GetScrollOffset() == new_offset)
     return;
 
+  TRACE_EVENT2("blink", "PaintLayerScrollableArea::UpdateScrollOffset", "x",
+               new_offset.Width(), "y", new_offset.Height());
+  TRACE_EVENT_INSTANT1("blink", "Type", TRACE_EVENT_SCOPE_THREAD, "type",
+                       scroll_type);
+
   scroll_offset_ = new_offset;
 
   LocalFrame* frame = GetLayoutBox()->GetFrame();
diff --git a/third_party/blink/renderer/core/scroll/scrollable_area.cc b/third_party/blink/renderer/core/scroll/scrollable_area.cc
index 63898f41..1b806dc 100644
--- a/third_party/blink/renderer/core/scroll/scrollable_area.cc
+++ b/third_party/blink/renderer/core/scroll/scrollable_area.cc
@@ -210,6 +210,13 @@
     return;
   }
 
+  TRACE_EVENT2("blink", "ScrollableArea::SetScrollOffset", "x", offset.Width(),
+               "y", offset.Height());
+  TRACE_EVENT_INSTANT1("blink", "Type", TRACE_EVENT_SCOPE_THREAD, "type",
+                       scroll_type);
+  TRACE_EVENT_INSTANT1("blink", "Behavior", TRACE_EVENT_SCOPE_THREAD,
+                       "behavior", behavior);
+
   if (behavior == kScrollBehaviorAuto)
     behavior = ScrollBehaviorStyle();
 
diff --git a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc
index ae159f05..465a82d 100644
--- a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc
+++ b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc
@@ -1065,6 +1065,7 @@
   request.SetSkipServiceWorker(is_isolated_world_);
   request.SetExternalRequestStateFromRequestorAddressSpace(
       execution_context.GetSecurityContext().AddressSpace());
+  request.SetShouldAlsoUseFactoryBoundOriginForCors(is_isolated_world_);
 
   probe::WillLoadXHR(&execution_context, method_, url_, async_, http_body.get(),
                      request_headers_, with_credentials_);
diff --git a/third_party/blink/renderer/devtools/front_end/elements/module.json b/third_party/blink/renderer/devtools/front_end/elements/module.json
index 52c4827..739a586 100644
--- a/third_party/blink/renderer/devtools/front_end/elements/module.json
+++ b/third_party/blink/renderer/devtools/front_end/elements/module.json
@@ -54,40 +54,6 @@
         {
             "type": "setting",
             "category": "Elements",
-            "order": 0,
-            "title": "Color format:",
-            "settingName": "colorFormat",
-            "settingType": "enum",
-            "defaultValue": "original",
-            "options": [
-                {
-                    "title": "Set color format as authored",
-                    "text": "As authored",
-                    "value": "original"
-                },
-                {
-                    "title": "Set color format to HEX",
-                    "text": "HEX: #dac0de",
-                    "value": "hex",
-                    "raw": true
-                },
-                {
-                    "title": "Set color format to RGB",
-                    "text": "RGB: rgb(128, 255, 255)",
-                    "value": "rgb",
-                    "raw": true
-                },
-                {
-                    "title": "Set color format to HSL",
-                    "text": "HSL: hsl(300, 80%, 90%)",
-                    "value": "hsl",
-                    "raw": true
-                }
-            ]
-        },
-        {
-            "type": "setting",
-            "category": "Elements",
             "order": 1,
             "title": "Show user agent shadow DOM",
             "settingName": "showUAShadowDOM",
diff --git a/third_party/blink/renderer/devtools/front_end/main/module.json b/third_party/blink/renderer/devtools/front_end/main/module.json
index fc5bb819..21c0bf0 100644
--- a/third_party/blink/renderer/devtools/front_end/main/module.json
+++ b/third_party/blink/renderer/devtools/front_end/main/module.json
@@ -272,6 +272,39 @@
         {
             "type": "setting",
             "category": "Appearance",
+            "title": "Color format:",
+            "settingName": "colorFormat",
+            "settingType": "enum",
+            "defaultValue": "original",
+            "options": [
+                {
+                    "title": "Set color format as authored",
+                    "text": "As authored",
+                    "value": "original"
+                },
+                {
+                    "title": "Set color format to HEX",
+                    "text": "HEX: #dac0de",
+                    "value": "hex",
+                    "raw": true
+                },
+                {
+                    "title": "Set color format to RGB",
+                    "text": "RGB: rgb(128, 255, 255)",
+                    "value": "rgb",
+                    "raw": true
+                },
+                {
+                    "title": "Set color format to HSL",
+                    "text": "HSL: hsl(300, 80%, 90%)",
+                    "value": "hsl",
+                    "raw": true
+                }
+            ]
+        },
+        {
+            "type": "setting",
+            "category": "Appearance",
             "title": "Enable Ctrl + 1-9 shortcut to switch panels",
             "title-mac": "Enable \u2318 + 1-9 shortcut to switch panels",
             "settingName": "shortcutPanelSwitch",
diff --git a/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPropertiesSection.js b/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPropertiesSection.js
index d81eec2..bbfb68d 100644
--- a/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPropertiesSection.js
+++ b/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPropertiesSection.js
@@ -113,20 +113,27 @@
       return 1;
     if (propertyB.symbol && !propertyA.symbol)
       return -1;
+    if (propertyA.private && !propertyB.private)
+      return 1;
+    if (propertyB.private && !propertyA.private)
+      return -1;
     return String.naturalOrderComparator(a, b);
   }
 
   /**
-   * @param {?string} name
+   * @param {string} name
+   * @param {boolean=} isPrivate
    * @return {!Element}
    */
-  static createNameElement(name) {
-    const nameElement = createElementWithClass('span', 'name');
+  static createNameElement(name, isPrivate) {
     if (/^\s|\s$|^$|\n/.test(name))
-      nameElement.createTextChildren('"', name.replace(/\n/g, '\u21B5'), '"');
-    else
-      nameElement.textContent = name;
-    return nameElement;
+      return UI.html`<span class="name">"${name.replace(/\n/g, '\u21B5')}"</span>`;
+    if (isPrivate) {
+      return UI.html`<span class="name">
+        <span class="private-property-hash">${name[0]}</span>${name.substring(1)}
+      </span>`;
+    }
+    return UI.html`<span class="name">${name}</span>`;
   }
 
   /**
@@ -798,7 +805,7 @@
   }
 
   update() {
-    this.nameElement = ObjectUI.ObjectPropertiesSection.createNameElement(this.property.name);
+    this.nameElement = ObjectUI.ObjectPropertiesSection.createNameElement(this.property.name, this.property.private);
     if (!this.property.enumerable)
       this.nameElement.classList.add('object-properties-section-dimmed');
     if (this.property.synthetic)
@@ -851,7 +858,7 @@
     const parentPath =
         (this.parent.nameElement && !this.parent.property.synthetic) ? this.parent.nameElement.title : '';
 
-    if (useDotNotation.test(name))
+    if (this.property.private || useDotNotation.test(name))
       this.nameElement.title = parentPath ? `${parentPath}.${name}` : name;
     else if (isInteger.test(name))
       this.nameElement.title = parentPath + '[' + name + ']';
diff --git a/third_party/blink/renderer/devtools/front_end/object_ui/RemoteObjectPreviewFormatter.js b/third_party/blink/renderer/devtools/front_end/object_ui/RemoteObjectPreviewFormatter.js
index 37c61c7..b6c126e7 100644
--- a/third_party/blink/renderer/devtools/front_end/object_ui/RemoteObjectPreviewFormatter.js
+++ b/third_party/blink/renderer/devtools/front_end/object_ui/RemoteObjectPreviewFormatter.js
@@ -18,14 +18,16 @@
      * @return {number}
      */
     function sortValue(property) {
+      // TODO(einbinder) expose whether preview properties are actually internal.
       const internalName = ObjectUI.RemoteObjectPreviewFormatter._internalName;
       if (property.name === internalName.PromiseStatus)
         return 1;
       else if (property.name === internalName.PromiseValue)
         return 2;
-      else if (property.name === internalName.GeneratorStatus || internalName.PrimitiveValue)
+      else if (property.name === internalName.GeneratorStatus || property.name === internalName.PrimitiveValue)
         return 3;
-      else if (property.type !== 'function')
+      // TODO(einbinder) expose whether preview properties are actually private.
+      else if (property.type !== 'function' && !property.name.startsWith('#'))
         return 4;
       return 5;
     }
diff --git a/third_party/blink/renderer/devtools/front_end/object_ui/objectPropertiesSection.css b/third_party/blink/renderer/devtools/front_end/object_ui/objectPropertiesSection.css
index 94b99dd..71f40d7 100644
--- a/third_party/blink/renderer/devtools/front_end/object_ui/objectPropertiesSection.css
+++ b/third_party/blink/renderer/devtools/front_end/object_ui/objectPropertiesSection.css
@@ -42,6 +42,10 @@
     font-style: italic;
 }
 
+.object-properties-section .private-property-hash {
+    color: #222;
+}
+
 .object-properties-section-root-element {
     display: flex;
     flex-direction: row;
diff --git a/third_party/blink/renderer/devtools/front_end/resources/AppManifestView.js b/third_party/blink/renderer/devtools/front_end/resources/AppManifestView.js
index f7963f5..ac759917 100644
--- a/third_party/blink/renderer/devtools/front_end/resources/AppManifestView.js
+++ b/third_party/blink/renderer/devtools/front_end/resources/AppManifestView.js
@@ -10,6 +10,8 @@
     super(true);
     this.registerRequiredCSS('resources/appManifestView.css');
 
+    Common.moduleSetting('colorFormat').addChangeListener(this._updateManifest.bind(this, true));
+
     this._emptyView = new UI.EmptyWidget(Common.UIString('No manifest detected'));
     this._emptyView.appendLink(
         'https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/?utm_source=devtools');
@@ -141,10 +143,12 @@
     this._themeColorSwatch.classList.toggle('hidden', !stringProperty('theme_color'));
     const themeColor = Common.Color.parse(stringProperty('theme_color') || 'white') || Common.Color.parse('white');
     this._themeColorSwatch.setColor(/** @type {!Common.Color} */ (themeColor));
+    this._themeColorSwatch.setFormat(Common.Color.detectColorFormat(this._themeColorSwatch.color()));
     this._backgroundColorSwatch.classList.toggle('hidden', !stringProperty('background_color'));
     const backgroundColor =
         Common.Color.parse(stringProperty('background_color') || 'white') || Common.Color.parse('white');
     this._backgroundColorSwatch.setColor(/** @type {!Common.Color} */ (backgroundColor));
+    this._backgroundColorSwatch.setFormat(Common.Color.detectColorFormat(this._backgroundColorSwatch.color()));
 
     this._orientationField.textContent = stringProperty('orientation');
     const displayType = stringProperty('display');
diff --git a/third_party/blink/renderer/devtools/front_end/sdk/RemoteObject.js b/third_party/blink/renderer/devtools/front_end/sdk/RemoteObject.js
index c4c6b3c..b44adf8e0 100644
--- a/third_party/blink/renderer/devtools/front_end/sdk/RemoteObject.js
+++ b/third_party/blink/renderer/devtools/front_end/sdk/RemoteObject.js
@@ -500,11 +500,9 @@
       this._runtimeModel.exceptionThrown(Date.now(), response.exceptionDetails);
       return /** @type {!SDK.GetPropertiesResult} */ ({properties: null, internalProperties: null});
     }
-    const properties = response.result;
-    const internalProperties = response.internalProperties;
+    const {result: properties = [], internalProperties = [], privateProperties = []} = response;
     const result = [];
-    for (let i = 0; properties && i < properties.length; ++i) {
-      const property = properties[i];
+    for (const property of properties) {
       const propertyValue = property.value ? this._runtimeModel.createRemoteObject(property.value) : null;
       const propertySymbol = property.symbol ? this._runtimeModel.createRemoteObject(property.symbol) : null;
       const remoteProperty = new SDK.RemoteObjectProperty(
@@ -519,19 +517,22 @@
       }
       result.push(remoteProperty);
     }
-    let internalPropertiesResult = null;
-    if (internalProperties) {
-      internalPropertiesResult = [];
-      for (let i = 0; i < internalProperties.length; i++) {
-        const property = internalProperties[i];
-        if (!property.value)
-          continue;
-        if (property.name === '[[StableObjectId]]')
-          continue;
-        const propertyValue = this._runtimeModel.createRemoteObject(property.value);
-        internalPropertiesResult.push(new SDK.RemoteObjectProperty(
-            property.name, propertyValue, true, false, undefined, undefined, undefined, true));
-      }
+    for (const property of privateProperties) {
+      const propertyValue = this._runtimeModel.createRemoteObject(property.value);
+      const remoteProperty = new SDK.RemoteObjectProperty(
+          property.name, propertyValue, true, true, true, false, undefined, false, undefined, true);
+      result.push(remoteProperty);
+    }
+
+    const internalPropertiesResult = [];
+    for (const property of internalProperties) {
+      if (!property.value)
+        continue;
+      if (property.name === '[[StableObjectId]]')
+        continue;
+      const propertyValue = this._runtimeModel.createRemoteObject(property.value);
+      internalPropertiesResult.push(new SDK.RemoteObjectProperty(
+          property.name, propertyValue, true, false, undefined, undefined, undefined, true));
     }
     return {properties: result, internalProperties: internalPropertiesResult};
   }
@@ -773,8 +774,9 @@
    * @param {?SDK.RemoteObject=} symbol
    * @param {boolean=} synthetic
    * @param {function(string):!Promise<?SDK.RemoteObject>=} syntheticSetter
+   * @param {boolean=} isPrivate
    */
-  constructor(name, value, enumerable, writable, isOwn, wasThrown, symbol, synthetic, syntheticSetter) {
+  constructor(name, value, enumerable, writable, isOwn, wasThrown, symbol, synthetic, syntheticSetter, isPrivate) {
     this.name = name;
     if (value !== null)
       this.value = value;
@@ -788,6 +790,7 @@
     this.synthetic = !!synthetic;
     if (syntheticSetter)
       this.syntheticSetter = syntheticSetter;
+    this.private = !!isPrivate;
   }
 
   /**
diff --git a/third_party/blink/renderer/devtools/front_end/source_frame/FontView.js b/third_party/blink/renderer/devtools/front_end/source_frame/FontView.js
index d9030c6..22786038 100644
--- a/third_party/blink/renderer/devtools/front_end/source_frame/FontView.js
+++ b/third_party/blink/renderer/devtools/front_end/source_frame/FontView.js
@@ -39,6 +39,7 @@
     this.registerRequiredCSS('source_frame/fontView.css');
     this.element.classList.add('font-view');
     this._url = contentProvider.contentURL();
+    UI.ARIAUtils.setAccessibleName(this.element, ls`Preview of font from ${this._url}`);
     this._mimeType = mimeType;
     this._contentProvider = contentProvider;
     this._mimeTypeLabel = new UI.ToolbarText(mimeType);
@@ -79,6 +80,7 @@
       fontPreview.createTextChild(SourceFrame.FontView._fontPreviewLines[i]);
     }
     this.fontPreviewElement = fontPreview.cloneNode(true);
+    UI.ARIAUtils.markAsHidden(this.fontPreviewElement);
     this.fontPreviewElement.style.overflow = 'hidden';
     this.fontPreviewElement.style.setProperty('font-family', uniqueFontName);
     this.fontPreviewElement.style.setProperty('visibility', 'hidden');
diff --git a/third_party/blink/renderer/devtools/front_end/source_frame/ImageView.js b/third_party/blink/renderer/devtools/front_end/source_frame/ImageView.js
index b69709b20..c6f5e86d 100644
--- a/third_party/blink/renderer/devtools/front_end/source_frame/ImageView.js
+++ b/third_party/blink/renderer/devtools/front_end/source_frame/ImageView.js
@@ -37,6 +37,7 @@
   constructor(mimeType, contentProvider) {
     super(Common.UIString('Image'));
     this.registerRequiredCSS('source_frame/imageView.css');
+    this.element.tabIndex = 0;
     this.element.classList.add('image-view');
     this._url = contentProvider.contentURL();
     this._parsedURL = new Common.ParsedURL(this._url);
@@ -58,6 +59,7 @@
     this._container = this.element.createChild('div', 'image');
     this._imagePreviewElement = this._container.createChild('img', 'resource-image-view');
     this._imagePreviewElement.addEventListener('contextmenu', this._contextMenu.bind(this), true);
+    this._imagePreviewElement.alt = ls`Image from ${this._url}`;
   }
 
   /**
diff --git a/third_party/blink/renderer/devtools/front_end/source_frame/JSONView.js b/third_party/blink/renderer/devtools/front_end/source_frame/JSONView.js
index 7199d3e..53fe818 100644
--- a/third_party/blink/renderer/devtools/front_end/source_frame/JSONView.js
+++ b/third_party/blink/renderer/devtools/front_end/source_frame/JSONView.js
@@ -68,7 +68,6 @@
     searchableView.setPlaceholder(Common.UIString('Find'));
     jsonView._searchableView = searchableView;
     jsonView.show(searchableView.element);
-    jsonView.element.setAttribute('tabIndex', 0);
     return searchableView;
   }
 
@@ -172,6 +171,7 @@
     this._treeOutline.setEditable(false);
     this._treeOutline.expand();
     this.element.appendChild(this._treeOutline.element);
+    this._treeOutline.firstChild().select(true /* omitFocus */, false /* selectedByUser */);
   }
 
   /**
diff --git a/third_party/blink/renderer/devtools/front_end/source_frame/XMLView.js b/third_party/blink/renderer/devtools/front_end/source_frame/XMLView.js
index cc0434b6..ad6a40a 100644
--- a/third_party/blink/renderer/devtools/front_end/source_frame/XMLView.js
+++ b/third_party/blink/renderer/devtools/front_end/source_frame/XMLView.js
@@ -27,6 +27,7 @@
     this._searchConfig;
 
     SourceFrame.XMLView.Node.populate(this._treeOutline, parsedXML, this);
+    this._treeOutline.firstChild().select(true /* omitFocus */, false /* selectedByUser */);
   }
 
   /**
@@ -39,7 +40,6 @@
     searchableView.setPlaceholder(Common.UIString('Find'));
     xmlView._searchableView = searchableView;
     xmlView.show(searchableView.element);
-    xmlView.contentElement.setAttribute('tabIndex', 0);
     return searchableView;
   }
 
@@ -223,7 +223,7 @@
     super('', !closeTag && !!node.childElementCount);
     this._node = node;
     this._closeTag = closeTag;
-    this.selectable = false;
+    this.selectable = true;
     /** @type {!Array.<!Object>} */
     this._highlightChanges = [];
     this._xmlView = xmlView;
diff --git a/third_party/blink/renderer/devtools/front_end/source_frame/source_frame_strings.grdp b/third_party/blink/renderer/devtools/front_end/source_frame/source_frame_strings.grdp
index a1d41c7..9be107aa 100644
--- a/third_party/blink/renderer/devtools/front_end/source_frame/source_frame_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/source_frame/source_frame_strings.grdp
@@ -18,12 +18,18 @@
   <message name="IDS_DEVTOOLS_4cfa6c981549e990fe2344e4c805405e" desc="">
     Find
   </message>
+  <message name="IDS_DEVTOOLS_53cd8180752335dce4f9b9ed493ef58d" desc="">
+    Image from <ph name="THIS__URL">$1s</ph>
+  </message>
   <message name="IDS_DEVTOOLS_59cc7cb8dfb2491cc5dfe8ebc546d797" desc="">
     Pretty print
   </message>
   <message name="IDS_DEVTOOLS_5ada9c9e1dad2e7e20aaa7688d7bd6c7" desc="">
     Line <ph name="LOCATION_______">$1s</ph>, Column <ph name="LOCATION_______">$2s</ph>
   </message>
+  <message name="IDS_DEVTOOLS_69614e5ef242926a61b58cebd303d4f4" desc="">
+    Preview of font from <ph name="THIS__URL">$1s</ph>
+  </message>
   <message name="IDS_DEVTOOLS_6efb3f8d955fc3395726044acec66129" desc="">
     <ph name="THIS__IMAGEPREVIEWELEMENT_NATURALWIDTH">$1d</ph> × <ph name="THIS__IMAGEPREVIEWELEMENT_NATURALHEIGHT">$2d</ph>
   </message>
diff --git a/third_party/blink/renderer/devtools/front_end/sources/WatchExpressionsSidebarPane.js b/third_party/blink/renderer/devtools/front_end/sources/WatchExpressionsSidebarPane.js
index f709857..2224871 100644
--- a/third_party/blink/renderer/devtools/front_end/sources/WatchExpressionsSidebarPane.js
+++ b/third_party/blink/renderer/devtools/front_end/sources/WatchExpressionsSidebarPane.js
@@ -371,7 +371,7 @@
     headerElement.appendChild(deleteButton);
 
     const titleElement = headerElement.createChild('div', 'watch-expression-title');
-    this._nameElement = ObjectUI.ObjectPropertiesSection.createNameElement(this._expression);
+    this._nameElement = ObjectUI.ObjectPropertiesSection.createNameElement(/** @type {string} */ (this._expression));
     if (!!exceptionDetails || !result) {
       this._valueElement = createElementWithClass('span', 'watch-expression-error value');
       titleElement.classList.add('dimmed');
diff --git a/third_party/blink/renderer/devtools/front_end/ui/UIUtils.js b/third_party/blink/renderer/devtools/front_end/ui/UIUtils.js
index d2aa44d..03d4a526 100644
--- a/third_party/blink/renderer/devtools/front_end/ui/UIUtils.js
+++ b/third_party/blink/renderer/devtools/front_end/ui/UIUtils.js
@@ -2037,6 +2037,11 @@
  * @return {!DocumentFragment}
  */
 UI.createExpandableText = function(text, maxLength) {
+  const clickHandler = () => {
+    if (expandElement.parentElement)
+      expandElement.parentElement.insertBefore(createTextNode(text.slice(maxLength)), expandElement);
+    expandElement.remove();
+  };
   const fragment = createDocumentFragment();
   fragment.textContent = text.slice(0, maxLength);
   const expandElement = fragment.createChild('span');
@@ -2044,11 +2049,13 @@
   if (text.length < 10000000) {
     expandElement.setAttribute('data-text', ls`Show more (${totalBytes})`);
     expandElement.classList.add('expandable-inline-button');
-    expandElement.addEventListener('click', () => {
-      if (expandElement.parentElement)
-        expandElement.parentElement.insertBefore(createTextNode(text.slice(maxLength)), expandElement);
-      expandElement.remove();
+    expandElement.addEventListener('click', clickHandler);
+    expandElement.addEventListener('keydown', event => {
+      if (event.key === 'Enter' || event.key === ' ')
+        clickHandler();
     });
+    UI.ARIAUtils.markAsButton(expandElement);
+
   } else {
     expandElement.setAttribute('data-text', ls`long text was truncated (${totalBytes})`);
     expandElement.classList.add('undisplayable-text');
@@ -2059,6 +2066,11 @@
   copyButton.addEventListener('click', () => {
     InspectorFrontendHost.copyText(text);
   });
+  copyButton.addEventListener('keydown', event => {
+    if (event.key === 'Enter' || event.key === ' ')
+      InspectorFrontendHost.copyText(text);
+  });
+  UI.ARIAUtils.markAsButton(copyButton);
   return fragment;
 };
 
diff --git a/third_party/blink/renderer/devtools/front_end/ui/inspectorCommon.css b/third_party/blink/renderer/devtools/front_end/ui/inspectorCommon.css
index 525ae586..038351fa 100644
--- a/third_party/blink/renderer/devtools/front_end/ui/inspectorCommon.css
+++ b/third_party/blink/renderer/devtools/front_end/ui/inspectorCommon.css
@@ -428,6 +428,10 @@
     background-color: #d5d5d5;
 }
 
+.expandable-inline-button[data-keyboard-focus="true"] {
+    background-color: #bbbbbb;
+}
+
 ::selection {
     background-color: #bbdefb;
 }
diff --git a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
index e8ba582..3422407 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
@@ -503,7 +503,7 @@
 
   if (const auto* input = ToHTMLInputElementOrNull(*GetNode())) {
     const AtomicString& type = input->type();
-    if (input->DataList())
+    if (input->DataList() && type != input_type_names::kColor)
       return ax::mojom::Role::kTextFieldWithComboBox;
     if (type == input_type_names::kButton) {
       if ((GetNode()->parentNode() &&
@@ -1844,6 +1844,24 @@
   return KURL();
 }
 
+AXObject* AXNodeObject::ChooserPopup() const {
+  // When color & date chooser popups are visible, they can be found in the tree
+  // as a WebArea child of the <input> control itself.
+  switch (native_role_) {
+    case ax::mojom::Role::kColorWell:
+    case ax::mojom::Role::kDate:
+    case ax::mojom::Role::kDateTime: {
+      for (const auto& child : children_) {
+        if (child->IsWebArea())
+          return child;
+      }
+      return nullptr;
+    }
+    default:
+      return nullptr;
+  }
+}
+
 String AXNodeObject::StringValue() const {
   Node* node = this->GetNode();
   if (!node)
diff --git a/third_party/blink/renderer/modules/accessibility/ax_node_object.h b/third_party/blink/renderer/modules/accessibility/ax_node_object.h
index 5efdd785..78e47d46 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_node_object.h
+++ b/third_party/blink/renderer/modules/accessibility/ax_node_object.h
@@ -152,6 +152,7 @@
   bool MinValueForRange(float* out_value) const override;
   bool StepValueForRange(float* out_value) const override;
   KURL Url() const override;
+  AXObject* ChooserPopup() const override;
   String StringValue() const override;
 
   // ARIA attributes.
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.h b/third_party/blink/renderer/modules/accessibility/ax_object.h
index cbe8c12..2df6e99 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object.h
+++ b/third_party/blink/renderer/modules/accessibility/ax_object.h
@@ -658,6 +658,7 @@
     return AXObjectVector();
   }
   virtual KURL Url() const { return KURL(); }
+  virtual AXObject* ChooserPopup() const { return nullptr; }
 
   // Load inline text boxes for just this node, even if
   // settings->inlineTextBoxAccessibilityEnabled() is false.
diff --git a/third_party/blink/renderer/modules/csspaint/paint_worklet.cc b/third_party/blink/renderer/modules/csspaint/paint_worklet.cc
index 1affba91..4f6bd2d 100644
--- a/third_party/blink/renderer/modules/csspaint/paint_worklet.cc
+++ b/third_party/blink/renderer/modules/csspaint/paint_worklet.cc
@@ -205,7 +205,7 @@
   if (!RuntimeEnabledFeatures::OffMainThreadCSSPaintEnabled()) {
     return MakeGarbageCollected<PaintWorkletGlobalScopeProxy>(
         To<Document>(GetExecutionContext())->GetFrame(), ModuleResponsesMap(),
-        pending_generator_registry_, GetNumberOfGlobalScopes() + 1);
+        GetNumberOfGlobalScopes() + 1);
   }
 
   if (!proxy_client_) {
diff --git a/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.cc b/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.cc
index 9ab00290..8290a5e 100644
--- a/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.cc
+++ b/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.cc
@@ -97,12 +97,10 @@
 PaintWorkletGlobalScope* PaintWorkletGlobalScope::Create(
     LocalFrame* frame,
     std::unique_ptr<GlobalScopeCreationParams> creation_params,
-    WorkerReportingProxy& reporting_proxy,
-    PaintWorkletPendingGeneratorRegistry* pending_generator_registry) {
+    WorkerReportingProxy& reporting_proxy) {
   DCHECK(!RuntimeEnabledFeatures::OffMainThreadCSSPaintEnabled());
   auto* global_scope = MakeGarbageCollected<PaintWorkletGlobalScope>(
-      frame, std::move(creation_params), reporting_proxy,
-      pending_generator_registry);
+      frame, std::move(creation_params), reporting_proxy);
   global_scope->ScriptController()->Initialize(NullURL());
   MainThreadDebugger::Instance()->ContextCreated(
       global_scope->ScriptController()->GetScriptState(),
@@ -122,10 +120,8 @@
 PaintWorkletGlobalScope::PaintWorkletGlobalScope(
     LocalFrame* frame,
     std::unique_ptr<GlobalScopeCreationParams> creation_params,
-    WorkerReportingProxy& reporting_proxy,
-    PaintWorkletPendingGeneratorRegistry* pending_generator_registry)
-    : WorkletGlobalScope(std::move(creation_params), reporting_proxy, frame),
-      pending_generator_registry_(pending_generator_registry) {}
+    WorkerReportingProxy& reporting_proxy)
+    : WorkletGlobalScope(std::move(creation_params), reporting_proxy, frame) {}
 
 PaintWorkletGlobalScope::PaintWorkletGlobalScope(
     std::unique_ptr<GlobalScopeCreationParams> creation_params,
@@ -145,7 +141,6 @@
   } else {
     MainThreadDebugger::Instance()->ContextWillBeDestroyed(
         ScriptController()->GetScriptState());
-    pending_generator_registry_ = nullptr;
   }
   WorkletGlobalScope::Dispose();
 }
@@ -246,7 +241,6 @@
 
 void PaintWorkletGlobalScope::Trace(blink::Visitor* visitor) {
   visitor->Trace(paint_definitions_);
-  visitor->Trace(pending_generator_registry_);
   WorkletGlobalScope::Trace(visitor);
 }
 
diff --git a/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.h b/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.h
index e4035eb..0c1e72c 100644
--- a/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.h
+++ b/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.h
@@ -8,7 +8,6 @@
 #include "third_party/blink/renderer/bindings/core/v8/script_value.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/workers/worklet_global_scope.h"
-#include "third_party/blink/renderer/modules/csspaint/paint_worklet_pending_generator_registry.h"
 #include "third_party/blink/renderer/modules/modules_export.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
 #include "third_party/blink/renderer/platform/wtf/casting.h"
@@ -29,8 +28,7 @@
   static PaintWorkletGlobalScope* Create(
       LocalFrame*,
       std::unique_ptr<GlobalScopeCreationParams>,
-      WorkerReportingProxy&,
-      PaintWorkletPendingGeneratorRegistry*);
+      WorkerReportingProxy&);
 
   // Creates an worklet-thread bound PaintWorkletGlobalScope.
   static PaintWorkletGlobalScope* Create(
@@ -39,8 +37,7 @@
 
   PaintWorkletGlobalScope(LocalFrame*,
                           std::unique_ptr<GlobalScopeCreationParams>,
-                          WorkerReportingProxy&,
-                          PaintWorkletPendingGeneratorRegistry*);
+                          WorkerReportingProxy&);
   PaintWorkletGlobalScope(std::unique_ptr<GlobalScopeCreationParams>,
                           WorkerThread*);
   ~PaintWorkletGlobalScope() override;
@@ -66,12 +63,6 @@
   typedef HeapHashMap<String, Member<CSSPaintDefinition>> DefinitionMap;
   DefinitionMap paint_definitions_;
 
-  // Only used for main-thread bound PaintWorkletGlobalScopes.
-  // TODO(smcgruer): Move elsewhere for worklet-thread bound
-  // PaintWorkletGlobalScope.
-  Member<PaintWorkletPendingGeneratorRegistry> pending_generator_registry_ =
-      nullptr;
-
   // Tracks whether this PaintWorkletGlobalScope has been registered with a
   // PaintWorkletProxyClient. Only used in worklet-thread bound
   // PaintWorkletGlobalScopes.
diff --git a/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.cc b/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.cc
index a709bdd..857eaee 100644
--- a/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.cc
+++ b/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.cc
@@ -29,7 +29,6 @@
 PaintWorkletGlobalScopeProxy::PaintWorkletGlobalScopeProxy(
     LocalFrame* frame,
     WorkletModuleResponsesMap* module_responses_map,
-    PaintWorkletPendingGeneratorRegistry* pending_generator_registry,
     size_t global_scope_number) {
   DCHECK(IsMainThread());
   Document* document = frame->GetDocument();
@@ -54,8 +53,7 @@
       base::UnguessableToken::Create(), nullptr /* worker_settings */,
       kV8CacheOptionsDefault, module_responses_map);
   global_scope_ = PaintWorkletGlobalScope::Create(
-      frame, std::move(creation_params), *reporting_proxy_,
-      pending_generator_registry);
+      frame, std::move(creation_params), *reporting_proxy_);
 }
 
 void PaintWorkletGlobalScopeProxy::FetchAndInvokeScript(
diff --git a/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.h b/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.h
index bf264607..813ab341 100644
--- a/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.h
+++ b/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.h
@@ -29,7 +29,6 @@
 
   PaintWorkletGlobalScopeProxy(LocalFrame*,
                                WorkletModuleResponsesMap*,
-                               PaintWorkletPendingGeneratorRegistry*,
                                size_t global_scope_number);
   ~PaintWorkletGlobalScopeProxy() override = default;
 
diff --git a/third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.h b/third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.h
index d1e3a48f..764bdf2 100644
--- a/third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.h
+++ b/third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.h
@@ -16,6 +16,8 @@
 
 namespace blink {
 
+class DocumentPaintDefinition;
+class PaintWorklet;
 class WorkletGlobalScope;
 
 // Mediates between the (multiple) PaintWorkletGlobalScopes on the worklet
diff --git a/third_party/blink/renderer/modules/exported/web_ax_object.cc b/third_party/blink/renderer/modules/exported/web_ax_object.cc
index 1117ee3..47d9fac1 100644
--- a/third_party/blink/renderer/modules/exported/web_ax_object.cc
+++ b/third_party/blink/renderer/modules/exported/web_ax_object.cc
@@ -1032,6 +1032,15 @@
   return private_->Url();
 }
 
+WebAXObject WebAXObject::ChooserPopup() const {
+  if (IsDetached())
+    return WebAXObject();
+  AXObject* target = private_->ChooserPopup();
+  if (!target || target->IsDetached())
+    return WebAXObject();
+  return WebAXObject(target);
+}
+
 WebString WebAXObject::GetName(ax::mojom::NameFrom& out_name_from,
                                WebVector<WebAXObject>& out_name_objects) const {
   if (IsDetached())
diff --git a/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.cc b/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.cc
index a6181fa7..9e4fcd5b 100644
--- a/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.cc
+++ b/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.cc
@@ -34,6 +34,7 @@
   DCHECK(!isContextLost());
   DCHECK(GetDrawingBuffer());
 
+  bound_dispatch_indirect_buffer_ = nullptr;
   bound_atomic_counter_buffer_ = nullptr;
   bound_shader_storage_buffer_ = nullptr;
 
@@ -345,6 +346,8 @@
       return GetIntParameter(script_state, pname);
     case GL_MAX_SHADER_STORAGE_BLOCK_SIZE:
       return GetInt64Parameter(script_state, pname);
+    case GL_DISPATCH_INDIRECT_BUFFER_BINDING:
+      return WebGLAny(script_state, bound_dispatch_indirect_buffer_.Get());
 
     default:
       return WebGL2RenderingContextBase::getParameter(script_state, pname);
@@ -392,6 +395,7 @@
 }
 
 void WebGL2ComputeRenderingContextBase::Trace(blink::Visitor* visitor) {
+  visitor->Trace(bound_dispatch_indirect_buffer_);
   visitor->Trace(bound_atomic_counter_buffer_);
   visitor->Trace(bound_indexed_atomic_counter_buffers_);
   visitor->Trace(bound_shader_storage_buffer_);
@@ -439,6 +443,7 @@
     const char* function_name,
     GLenum target) {
   switch (target) {
+    case GL_DISPATCH_INDIRECT_BUFFER:
     case GL_ATOMIC_COUNTER_BUFFER:
     case GL_SHADER_STORAGE_BUFFER:
       return true;
@@ -453,6 +458,9 @@
     GLenum target) {
   WebGLBuffer* buffer = nullptr;
   switch (target) {
+    case GL_DISPATCH_INDIRECT_BUFFER:
+      buffer = bound_dispatch_indirect_buffer_.Get();
+      break;
     case GL_ATOMIC_COUNTER_BUFFER:
       buffer = bound_atomic_counter_buffer_.Get();
       break;
@@ -482,6 +490,9 @@
     return false;
 
   switch (target) {
+    case GL_DISPATCH_INDIRECT_BUFFER:
+      bound_dispatch_indirect_buffer_ = buffer;
+      break;
     case GL_ATOMIC_COUNTER_BUFFER:
       bound_atomic_counter_buffer_ = buffer;
       break;
@@ -499,6 +510,8 @@
 }
 
 void WebGL2ComputeRenderingContextBase::RemoveBoundBuffer(WebGLBuffer* buffer) {
+  if (bound_dispatch_indirect_buffer_ == buffer)
+    bound_dispatch_indirect_buffer_ = nullptr;
   if (bound_atomic_counter_buffer_ == buffer)
     bound_atomic_counter_buffer_ = nullptr;
   if (bound_shader_storage_buffer_ == buffer)
@@ -516,6 +529,7 @@
   switch (buffer->GetInitialTarget()) {
     case GL_ELEMENT_ARRAY_BUFFER:
       switch (target) {
+        case GL_DISPATCH_INDIRECT_BUFFER:
         case GL_ATOMIC_COUNTER_BUFFER:
         case GL_SHADER_STORAGE_BUFFER:
           SynthesizeGLError(
@@ -527,6 +541,7 @@
           break;
       }
       break;
+    case GL_DISPATCH_INDIRECT_BUFFER:
     case GL_ATOMIC_COUNTER_BUFFER:
     case GL_SHADER_STORAGE_BUFFER:
       if (target == GL_ELEMENT_ARRAY_BUFFER) {
diff --git a/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.h b/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.h
index a713d1f4..2d39ac9 100644
--- a/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.h
+++ b/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.h
@@ -100,6 +100,7 @@
                                              GLuint index,
                                              WebGLBuffer*) override;
 
+  Member<WebGLBuffer> bound_dispatch_indirect_buffer_;
   Member<WebGLBuffer> bound_atomic_counter_buffer_;
   Member<WebGLBuffer> bound_shader_storage_buffer_;
 
diff --git a/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.idl b/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.idl
index e039327..625d5a6 100644
--- a/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.idl
+++ b/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.idl
@@ -5,6 +5,8 @@
 interface mixin WebGL2ComputeRenderingContextBase {
     // TODO(jiajia.qin@intel.com): add more enums and apis
     const GLenum COMPUTE_SHADER                         = 0x91B9;
+    const GLenum DISPATCH_INDIRECT_BUFFER               = 0x90EE;
+    const GLenum DISPATCH_INDIRECT_BUFFER_BINDING       = 0x90EF;
     const GLenum UNIFORM                                = 0x92E1;
     const GLenum UNIFORM_BLOCK                          = 0x92E2;
     const GLenum PROGRAM_INPUT                          = 0x92E3;
diff --git a/third_party/blink/renderer/platform/exported/web_input_event.cc b/third_party/blink/renderer/platform/exported/web_input_event.cc
index 4852aad..a70c412 100644
--- a/third_party/blink/renderer/platform/exported/web_input_event.cc
+++ b/third_party/blink/renderer/platform/exported/web_input_event.cc
@@ -58,7 +58,7 @@
 };
 
 struct SameSizeAsWebGestureEvent : public SameSizeAsWebInputEvent {
-  int gesture_data[18];
+  int gesture_data[15];
 };
 
 struct SameSizeAsWebTouchEvent : public SameSizeAsWebInputEvent {
diff --git a/third_party/blink/renderer/platform/exported/web_url_request.cc b/third_party/blink/renderer/platform/exported/web_url_request.cc
index cb97966..1a7c46b 100644
--- a/third_party/blink/renderer/platform/exported/web_url_request.cc
+++ b/third_party/blink/renderer/platform/exported/web_url_request.cc
@@ -409,6 +409,10 @@
   return resource_request_->IsRevalidating();
 }
 
+bool WebURLRequest::ShouldAlsoUseFactoryBoundOriginForCors() const {
+  return resource_request_->ShouldAlsoUseFactoryBoundOriginForCors();
+}
+
 const base::Optional<base::UnguessableToken>& WebURLRequest::GetDevToolsToken()
     const {
   return resource_request_->GetDevToolsToken();
diff --git a/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.cc b/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.cc
index f5fc85e..40fee4c0 100644
--- a/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.cc
+++ b/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.cc
@@ -41,10 +41,11 @@
     unsigned texture_id,
     base::WeakPtr<WebGraphicsContext3DProviderWrapper>&&
         context_provider_wrapper,
-    IntSize mailbox_size) {
+    IntSize mailbox_size,
+    bool is_origin_top_left) {
   return base::AdoptRef(new AcceleratedStaticBitmapImage(
       mailbox, sync_token, texture_id, std::move(context_provider_wrapper),
-      mailbox_size));
+      mailbox_size, is_origin_top_left));
 }
 
 scoped_refptr<AcceleratedStaticBitmapImage>
@@ -55,11 +56,12 @@
     GLenum texture_target,
     base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper,
     PlatformThreadId context_thread_id,
+    bool is_origin_top_left,
     std::unique_ptr<viz::SingleReleaseCallback> release_callback) {
   return base::AdoptRef(new AcceleratedStaticBitmapImage(
       mailbox, sync_token, sk_image_info, texture_target,
       std::move(context_provider_wrapper), context_thread_id,
-      std::move(release_callback)));
+      is_origin_top_left, std::move(release_callback)));
 }
 
 AcceleratedStaticBitmapImage::AcceleratedStaticBitmapImage(
@@ -78,11 +80,12 @@
     unsigned texture_id,
     base::WeakPtr<WebGraphicsContext3DProviderWrapper>&&
         context_provider_wrapper,
-    IntSize mailbox_size)
+    IntSize mailbox_size,
+    bool is_origin_top_left)
     : paint_image_content_id_(cc::PaintImage::GetNextContentId()) {
   texture_holder_ = std::make_unique<MailboxTextureHolder>(
       mailbox, sync_token, texture_id, std::move(context_provider_wrapper),
-      mailbox_size);
+      mailbox_size, is_origin_top_left);
 }
 
 AcceleratedStaticBitmapImage::AcceleratedStaticBitmapImage(
@@ -93,12 +96,13 @@
     base::WeakPtr<WebGraphicsContext3DProviderWrapper>&&
         context_provider_wrapper,
     PlatformThreadId context_thread_id,
+    bool is_origin_top_left,
     std::unique_ptr<viz::SingleReleaseCallback> release_callback)
     : paint_image_content_id_(cc::PaintImage::GetNextContentId()),
       release_callback_(std::move(release_callback)) {
   texture_holder_ = std::make_unique<MailboxTextureHolder>(
       mailbox, sync_token, std::move(context_provider_wrapper),
-      context_thread_id, sk_image_info, texture_target);
+      context_thread_id, sk_image_info, texture_target, is_origin_top_left);
 }
 
 namespace {
diff --git a/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h b/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h
index 1a78056e..be932226 100644
--- a/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h
+++ b/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h
@@ -44,7 +44,8 @@
       const gpu::SyncToken&,
       unsigned texture_id,
       base::WeakPtr<WebGraphicsContext3DProviderWrapper>&&,
-      IntSize mailbox_size);
+      IntSize mailbox_size,
+      bool is_origin_top_left);
 
   // |release_callback| is an optional callback to be invoked when this image
   // is destroyed. It can be invoked on any thread.
@@ -57,6 +58,7 @@
       GLenum texture_target,
       base::WeakPtr<WebGraphicsContext3DProviderWrapper>,
       PlatformThreadId context_thread_id,
+      bool is_origin_top_left,
       std::unique_ptr<viz::SingleReleaseCallback> release_callback);
 
   bool CurrentFrameKnownToBeOpaque() override;
@@ -120,7 +122,8 @@
       const gpu::SyncToken&,
       unsigned texture_id,
       base::WeakPtr<WebGraphicsContext3DProviderWrapper>&&,
-      IntSize mailbox_size);
+      IntSize mailbox_size,
+      bool is_origin_top_left);
   AcceleratedStaticBitmapImage(
       const gpu::Mailbox&,
       const gpu::SyncToken&,
@@ -128,6 +131,7 @@
       GLenum texture_target,
       base::WeakPtr<WebGraphicsContext3DProviderWrapper>&&,
       PlatformThreadId context_thread_id,
+      bool is_origin_top_left,
       std::unique_ptr<viz::SingleReleaseCallback> release_callback);
 
   void CreateImageFromMailboxIfNeeded();
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource.cc b/third_party/blink/renderer/platform/graphics/canvas_resource.cc
index c5ff1924..2eb4228 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_resource.cc
+++ b/third_party/blink/renderer/platform/graphics/canvas_resource.cc
@@ -673,11 +673,13 @@
     base::WeakPtr<CanvasResourceProvider> provider,
     SkFilterQuality filter_quality,
     const CanvasColorParams& color_params,
-    bool is_overlay_candidate)
+    bool is_overlay_candidate,
+    bool is_origin_top_left)
     : CanvasResource(std::move(provider), filter_quality, color_params),
       context_provider_wrapper_(std::move(context_provider_wrapper)),
       is_overlay_candidate_(is_overlay_candidate),
       size_(size),
+      is_origin_top_left_(is_origin_top_left),
       owning_thread_id_(Thread::Current()->ThreadId()),
       owning_thread_task_runner_(Thread::Current()->GetTaskRunner()) {
   if (!context_provider_wrapper_)
@@ -717,11 +719,12 @@
     base::WeakPtr<CanvasResourceProvider> provider,
     SkFilterQuality filter_quality,
     const CanvasColorParams& color_params,
-    bool is_overlay_candidate) {
+    bool is_overlay_candidate,
+    bool is_origin_top_left) {
   TRACE_EVENT0("blink", "CanvasResourceSharedImage::Create");
   auto resource = base::AdoptRef(new CanvasResourceSharedImage(
       size, std::move(context_provider_wrapper), std::move(provider),
-      filter_quality, color_params, is_overlay_candidate));
+      filter_quality, color_params, is_overlay_candidate, is_origin_top_left));
   return resource->IsValid() ? resource : nullptr;
 }
 
@@ -832,7 +835,7 @@
   auto sync_token = is_cross_thread() ? sync_token_ : GetSyncToken();
   image = AcceleratedStaticBitmapImage::CreateFromCanvasMailbox(
       shared_image_mailbox_, sync_token, image_info, texture_target_,
-      context_provider_wrapper_, owning_thread_id_,
+      context_provider_wrapper_, owning_thread_id_, is_origin_top_left_,
       std::move(release_callback));
 
   DCHECK(image);
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource.h b/third_party/blink/renderer/platform/graphics/canvas_resource.h
index be1d451..8e3d792 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_resource.h
+++ b/third_party/blink/renderer/platform/graphics/canvas_resource.h
@@ -309,7 +309,8 @@
       base::WeakPtr<CanvasResourceProvider>,
       SkFilterQuality,
       const CanvasColorParams&,
-      bool is_overlay_candidate);
+      bool is_overlay_candidate,
+      bool is_origin_top_left);
   ~CanvasResourceSharedImage() override;
 
   bool IsRecycleable() const final { return true; }
@@ -359,7 +360,8 @@
                             base::WeakPtr<CanvasResourceProvider>,
                             SkFilterQuality,
                             const CanvasColorParams&,
-                            bool is_overlay_candidate);
+                            bool is_overlay_candidate,
+                            bool is_origin_top_left);
   void SetGLFilterIfNeeded();
 
   base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper_;
@@ -373,6 +375,7 @@
   bool needs_gl_filter_reset_ = true;
   bool is_origin_clean_ = true;
   GLenum texture_target_ = GL_TEXTURE_2D;
+  bool is_origin_top_left_ = false;
 
   const PlatformThreadId owning_thread_id_;
   const scoped_refptr<base::SingleThreadTaskRunner> owning_thread_task_runner_;
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
index 2705a3d..6217bf0 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
+++ b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
@@ -500,7 +500,7 @@
     TRACE_EVENT0("blink", "CanvasResourceProviderSharedImage::CreateResource");
     return CanvasResourceSharedImage::Create(
         Size(), ContextProviderWrapper(), CreateWeakPtr(), FilterQuality(),
-        ColorParams(), is_overlay_candidate_);
+        ColorParams(), is_overlay_candidate_, is_origin_top_left_);
   }
 
  protected:
diff --git a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
index 7fd2418..1da5879d 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
+++ b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
@@ -605,7 +605,7 @@
   // in DrawingBuffer.
   return AcceleratedStaticBitmapImage::CreateFromWebGLContextImage(
       sk_image_mailbox, sk_image_sync_token, texture_id,
-      context_provider_->GetWeakPtr(), size_);
+      context_provider_->GetWeakPtr(), size_, opengl_flip_y_extension_);
 }
 
 scoped_refptr<DrawingBuffer::ColorBuffer>
diff --git a/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.cc b/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.cc
index 30b91ad..b686032 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.cc
+++ b/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.cc
@@ -684,7 +684,7 @@
 
   return AcceleratedStaticBitmapImage::CreateFromWebGLContextImage(
       buffer->mailbox, buffer->produce_sync_token, texture_id,
-      drawing_buffer_->ContextProviderWeakPtr(), size_);
+      drawing_buffer_->ContextProviderWeakPtr(), size_, false);
 }
 
 void XRWebGLDrawingBuffer::MailboxReleased(
@@ -737,7 +737,7 @@
   scoped_refptr<StaticBitmapImage> image =
       AcceleratedStaticBitmapImage::CreateFromWebGLContextImage(
           color_buffer->mailbox, color_buffer->produce_sync_token, texture_id,
-          drawing_buffer_->ContextProviderWeakPtr(), color_buffer->size);
+          drawing_buffer_->ContextProviderWeakPtr(), color_buffer->size, false);
 
   mirror_client_->OnMirrorImageAvailable(std::move(image),
                                          std::move(release_callback));
diff --git a/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.cc b/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.cc
index 73a43d8f..19ab2ddd 100644
--- a/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.cc
+++ b/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.cc
@@ -38,8 +38,9 @@
     unsigned texture_id_to_delete_after_mailbox_consumed,
     base::WeakPtr<WebGraphicsContext3DProviderWrapper>&&
         context_provider_wrapper,
-    IntSize mailbox_size)
-    : TextureHolder(std::move(context_provider_wrapper)),
+    IntSize mailbox_size,
+    bool is_origin_top_left)
+    : TextureHolder(std::move(context_provider_wrapper), is_origin_top_left),
       mailbox_(mailbox),
       sync_token_(sync_token),
       texture_id_(texture_id_to_delete_after_mailbox_consumed),
@@ -58,8 +59,9 @@
         context_provider_wrapper,
     PlatformThreadId context_thread_id,
     const SkImageInfo& sk_image_info,
-    GLenum texture_target)
-    : TextureHolder(std::move(context_provider_wrapper)),
+    GLenum texture_target,
+    bool is_origin_top_left)
+    : TextureHolder(std::move(context_provider_wrapper), is_origin_top_left),
       mailbox_(mailbox),
       sync_token_(sync_token),
       texture_id_(0),
@@ -74,7 +76,8 @@
 MailboxTextureHolder::MailboxTextureHolder(
     std::unique_ptr<TextureHolder> texture_holder,
     GLenum filter)
-    : TextureHolder(texture_holder->ContextProviderWrapper()),
+    : TextureHolder(texture_holder->ContextProviderWrapper(),
+                    texture_holder->IsOriginTopLeft()),
       texture_id_(0),
       is_converted_from_skia_texture_(true),
       thread_id_(0) {
diff --git a/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.h b/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.h
index f6893207..9f0d7f9 100644
--- a/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.h
+++ b/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.h
@@ -46,7 +46,8 @@
                        const gpu::SyncToken&,
                        unsigned texture_id_to_delete_after_mailbox_consumed,
                        base::WeakPtr<WebGraphicsContext3DProviderWrapper>&&,
-                       IntSize mailbox_size);
+                       IntSize mailbox_size,
+                       bool is_origin_top_left);
   // This function turns a texture-backed SkImage into a mailbox and a
   // syncToken.
   MailboxTextureHolder(std::unique_ptr<TextureHolder>, GLenum filter);
@@ -58,7 +59,8 @@
                        base::WeakPtr<WebGraphicsContext3DProviderWrapper>&&,
                        PlatformThreadId context_thread_id,
                        const SkImageInfo& sk_image_info,
-                       GLenum texture_target);
+                       GLenum texture_target,
+                       bool is_origin_top_left);
 
  private:
   void InitCommon();
diff --git a/third_party/blink/renderer/platform/graphics/skia_texture_holder.cc b/third_party/blink/renderer/platform/graphics/skia_texture_holder.cc
index 988b001..a8659fd 100644
--- a/third_party/blink/renderer/platform/graphics/skia_texture_holder.cc
+++ b/third_party/blink/renderer/platform/graphics/skia_texture_holder.cc
@@ -14,18 +14,28 @@
 #include "third_party/skia/include/gpu/GrBackendSurface.h"
 #include "third_party/skia/include/gpu/GrContext.h"
 
+namespace {
+bool IsSkImageOriginTopLeft(sk_sp<SkImage> image) {
+  GrSurfaceOrigin origin;
+  image->getBackendTexture(false, &origin);
+  return origin == kTopLeft_GrSurfaceOrigin;
+}
+}  // namespace
+
 namespace blink {
 
 SkiaTextureHolder::SkiaTextureHolder(
     sk_sp<SkImage> image,
     base::WeakPtr<WebGraphicsContext3DProviderWrapper>&&
         context_provider_wrapper)
-    : TextureHolder(std::move(context_provider_wrapper)),
+    : TextureHolder(std::move(context_provider_wrapper),
+                    IsSkImageOriginTopLeft(image)),
       image_(std::move(image)) {}
 
 SkiaTextureHolder::SkiaTextureHolder(
     std::unique_ptr<TextureHolder> texture_holder)
-    : TextureHolder(SharedGpuContext::ContextProviderWrapper()) {
+    : TextureHolder(SharedGpuContext::ContextProviderWrapper(),
+                    texture_holder->IsOriginTopLeft()) {
   DCHECK(texture_holder->IsMailboxTextureHolder());
   const gpu::Mailbox mailbox = texture_holder->GetMailbox();
   const gpu::SyncToken sync_token = texture_holder->GetSyncToken();
@@ -65,10 +75,13 @@
   GrBackendTexture backend_texture(sk_image_info.width(),
                                    sk_image_info.height(), GrMipMapped::kNo,
                                    texture_info);
+
+  GrSurfaceOrigin origin = IsOriginTopLeft() ? kTopLeft_GrSurfaceOrigin
+                                             : kBottomLeft_GrSurfaceOrigin;
+
   image_ = SkImage::MakeFromAdoptedTexture(
-      shared_gr_context, backend_texture, kBottomLeft_GrSurfaceOrigin,
-      sk_image_info.colorType(), sk_image_info.alphaType(),
-      sk_image_info.refColorSpace());
+      shared_gr_context, backend_texture, origin, sk_image_info.colorType(),
+      sk_image_info.alphaType(), sk_image_info.refColorSpace());
 }
 
 SkiaTextureHolder::~SkiaTextureHolder() {
diff --git a/third_party/blink/renderer/platform/graphics/texture_holder.h b/third_party/blink/renderer/platform/graphics/texture_holder.h
index 4c934f11..0e97f57d 100644
--- a/third_party/blink/renderer/platform/graphics/texture_holder.h
+++ b/third_party/blink/renderer/platform/graphics/texture_holder.h
@@ -61,13 +61,18 @@
                : nullptr;
   }
 
+  bool IsOriginTopLeft() const { return is_origin_top_left_; }
+
  protected:
   TextureHolder(base::WeakPtr<WebGraphicsContext3DProviderWrapper>&&
-                    context_provider_wrapper)
-      : context_provider_wrapper_(std::move(context_provider_wrapper)) {}
+                    context_provider_wrapper,
+                bool is_origin_top_left)
+      : context_provider_wrapper_(std::move(context_provider_wrapper)),
+        is_origin_top_left_(is_origin_top_left) {}
 
  private:
   base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper_;
+  bool is_origin_top_left_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_request.h b/third_party/blink/renderer/platform/loader/fetch/resource_request.h
index 9c5e9bc..8ace9ecc 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_request.h
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_request.h
@@ -379,6 +379,13 @@
   }
   bool IsAutomaticUpgrade() const { return is_automatic_upgrade_; }
 
+  bool ShouldAlsoUseFactoryBoundOriginForCors() const {
+    return should_also_use_factory_bound_origin_for_cors_;
+  }
+  void SetShouldAlsoUseFactoryBoundOriginForCors(bool value) {
+    should_also_use_factory_bound_origin_for_cors_ = value;
+  }
+
   void SetAllowStaleResponse(bool value) { allow_stale_response_ = value; }
   bool AllowsStaleResponse() const { return allow_stale_response_; }
 
@@ -493,6 +500,7 @@
   bool is_revalidating_ = false;
 
   bool is_automatic_upgrade_ = false;
+  bool should_also_use_factory_bound_origin_for_cors_ = false;
 
   base::Optional<base::UnguessableToken> devtools_token_;
   base::Optional<String> devtools_id_;
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 2c1c2b2c..23709bf 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -4147,8 +4147,6 @@
 # These are timing out.
 crbug.com/835717 virtual/omt-worker-fetch/external/wpt/content-security-policy/inside-worker/dedicated-script.html [ Skip ]
 crbug.com/835717 virtual/omt-worker-fetch/external/wpt/content-security-policy/inside-worker/dedicated-inheritance.html [ Skip ]
-# This is failing because of the lack of CSP support.
-crbug.com/940316 virtual/omt-worker-fetch/external/wpt/content-security-policy/inside-worker/shared-script.html [ Failure Pass ]
 
 # PlzDedicatedWorker
 crbug.com/971173 virtual/omt-worker-fetch/external/wpt/referrer-policy/no-referrer-when-downgrade/http-rp/same-origin/http-http/module-worker/keep-origin-redirect/insecure-protocol.http.html [ Failure ]
@@ -4217,8 +4215,6 @@
 crbug.com/971173 virtual/omt-worker-fetch/external/wpt/referrer-policy/unset-referrer-policy/meta-referrer/same-origin/http-http/worker-request/no-redirect/insecure-protocol.http.html [ Failure ]
 
 crbug.com/971581 virtual/omt-worker-fetch/external/wpt/fetch/api/request/destination/fetch-destination-no-load-event.https.html [ Timeout ]
-crbug.com/971581 virtual/omt-worker-fetch/external/wpt/fetch/api/request/destination/fetch-destination-worker.https.html [ Failure ]
-crbug.com/971581 virtual/omt-worker-fetch/external/wpt/fetch/sec-metadata/worker.tentative.https.sub.html [ Failure ]
 
 # This fails because AllowedByNoSniff::MimeTypeAsScript() blocks the nested worker's
 # worker script, because the script url has a .html file extension.
@@ -4227,14 +4223,6 @@
 
 crbug.com/435547 http/tests/cachestorage/serviceworker/ignore-search-with-credentials.html [ Skip ]
 
-# Off-the-main-thread service worker script fetch.
-# This fails because CORS check?: Error message is like:
-# Access to XMLHttpRequest at 'foobar://abcd' (redirected from 'http://web-platform.test:8001/xhr/resources/redirect.py?location=foobar://abcd&code=301') from origin 'http://web-platform.test:8001' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
-# Following tests are crashing because module script fetcher for service worker
-# doesn't set CSP correctly.
-crbug.com/937757 external/wpt/service-workers/service-worker/update-registration-with-type.https.html [ Crash ]
-crbug.com/937757 virtual/omt-worker-fetch/external/wpt/service-workers/service-worker/update-registration-with-type.https.html [ Crash ]
-
 crbug.com/697971 [ Mac10.12 ] fast/text/selection/flexbox-selection-nested.html [ Skip ]
 crbug.com/697971 [ Mac10.12 ] fast/text/selection/flexbox-selection.html [ Skip ]
 
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/request/destination/fetch-destination-worker.https.html b/third_party/blink/web_tests/external/wpt/fetch/api/request/destination/fetch-destination-worker.https.html
index 8421d4a..5935c1f 100644
--- a/third_party/blink/web_tests/external/wpt/fetch/api/request/destination/fetch-destination-worker.https.html
+++ b/third_party/blink/web_tests/external/wpt/fetch/api/request/destination/fetch-destination-worker.https.html
@@ -46,9 +46,15 @@
 // worker destination
 /////////////////////
 promise_test(async t => {
-    // We can use an html file as we don't really care about the worker successfully loading.
+    // We can use an html file as we don't really care about the dedicated worker successfully loading.
     let worker = new frame.contentWindow.Worker("dummy.html?t=worker&dest=worker");
     await waitOnMessageFromSW(t);
-}, 'Worker fetches with a "worker" Request.destination');
+}, 'DedicatedWorker fetches with a "worker" Request.destination');
+
+promise_test(async t => {
+    // We can use an html file as we don't really care about the shared worker successfully loading.
+    let worker = new frame.contentWindow.SharedWorker("dummy.html?t=sharedworker&dest=sharedworker");
+    await waitOnMessageFromSW(t);
+}, 'SharedWorker fetches with a "sharedworker" Request.destination');
 
 </script>
diff --git a/third_party/blink/web_tests/http/tests/devtools/console/console-log-side-effects-expected.txt b/third_party/blink/web_tests/http/tests/devtools/console/console-log-side-effects-expected.txt
index c5f07cae..c3baeeeb 100644
--- a/third_party/blink/web_tests/http/tests/devtools/console/console-log-side-effects-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/console/console-log-side-effects-expected.txt
@@ -13,7 +13,7 @@
 console-log-side-effects.js:34 Boolean {true}
 console-log-side-effects.js:35 String {"foo"}
 console-log-side-effects.js:36 {}
-console-log-side-effects.js:37 Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
+console-log-side-effects.js:37 Window {parent: Window, postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, …}
 console-log-side-effects.js:43 
 console-log-side-effects.js:47 {foo: 1, bar: 2}
 console-log-side-effects.js:48 (3) [1, 2, 3]
diff --git a/third_party/blink/web_tests/http/tests/devtools/console/console-object-preview-expected.txt b/third_party/blink/web_tests/http/tests/devtools/console/console-object-preview-expected.txt
index 0eaf3e4..06fb11b4 100644
--- a/third_party/blink/web_tests/http/tests/devtools/console/console-object-preview-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/console/console-object-preview-expected.txt
@@ -31,6 +31,7 @@
 console-object-preview.js:86 Object with exactly 5 properties: expected to be lossless
 console-object-preview.js:87 {a: 1, b: 2, c: 3, d: 4, e: 5}
 console-object-preview.js:89 {null: null, undef: undefined, regexp: /^[regexp]$/g, bool: false}
+console-object-preview.js:96 IHavePrivateProperties {regularProperty: 3, #privateProperty1: 1, #privateProperty2: 2}
 Expanded all messages
 console-object-preview.js:10 Mutating object in a loop
 console-object-preview.js:14 {a: 0, b: 0, c: 0}a: 0b: 0c: 2__proto__: Object
@@ -63,4 +64,5 @@
 console-object-preview.js:86 Object with exactly 5 properties: expected to be lossless
 console-object-preview.js:87 {a: 1, b: 2, c: 3, d: 4, e: 5}a: 1b: 2c: 3d: 4e: 5__proto__: Object
 console-object-preview.js:89 {null: null, undef: undefined, regexp: /^[regexp]$/g, bool: false}bool: falsenull: nullregexp: /^[regexp]$/gundef: undefined__proto__: Object
+console-object-preview.js:96 IHavePrivateProperties {regularProperty: 3, #privateProperty1: 1, #privateProperty2: 2}regularProperty: 3#privateProperty1: 1#privateProperty2: 2__proto__: Object
 
diff --git a/third_party/blink/web_tests/http/tests/devtools/console/console-object-preview.js b/third_party/blink/web_tests/http/tests/devtools/console/console-object-preview.js
index 621b74226..e922951e7 100644
--- a/third_party/blink/web_tests/http/tests/devtools/console/console-object-preview.js
+++ b/third_party/blink/web_tests/http/tests/devtools/console/console-object-preview.js
@@ -87,6 +87,13 @@
           console.log({a:1, b:2, c:3, d:4, e:5});
 
           console.log({null:null, undef:undefined, regexp: \/^[regexp]$\/g, bool: false});
+
+          class IHavePrivateProperties {
+              #privateProperty1 = 1;
+              #privateProperty2 = 2;
+              regularProperty = 3;
+          }
+          console.log(new IHavePrivateProperties)
   `);
 
   ConsoleTestRunner.dumpConsoleMessages();
diff --git a/third_party/blink/web_tests/http/tests/devtools/console/viewport-testing/console-key-expand-expected.txt b/third_party/blink/web_tests/http/tests/devtools/console/viewport-testing/console-key-expand-expected.txt
index 4146390..7c3dbdc6 100644
--- a/third_party/blink/web_tests/http/tests/devtools/console/viewport-testing/console-key-expand-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/console/viewport-testing/console-key-expand-expected.txt
@@ -97,20 +97,14 @@
 active text: x: 1
 
 ArrowDown:
-
-ArrowDown:
-Viewport virtual selection: 2
-activeElement: DIV.console-message-wrapper.console-from-api.console-info-level.console-selected
-active text: console-key-expand.js:70 after
+Viewport virtual selection: 1
+activeElement: LI.parent.object-properties-section-root-element.selected
+active text: {y: 2}
 
 ArrowRight:
-Viewport virtual selection: 2
-activeElement: DIV.console-message-wrapper.console-from-api.console-info-level.console-selected
-active text: console-key-expand.js:70 after
-
-ArrowDown:
-
-ArrowDown:
+Viewport virtual selection: 1
+activeElement: LI.parent.object-properties-section-root-element.selected.expanded
+active text: {y: 2}
 
 ArrowDown:
 
@@ -121,13 +115,13 @@
 
 ArrowUp:
 Viewport virtual selection: 1
-activeElement: LI.parent.object-properties-section-root-element.selected
+activeElement: LI.parent.object-properties-section-root-element.expanded.selected
 active text: {y: 2}
 
 ArrowLeft:
 Viewport virtual selection: 1
-activeElement: DIV.console-message-wrapper.console-from-api.console-info-level.console-selected
-active text: console-key-expand.js:70 text {x: 1}x: 1 {y: 2}y: 2
+activeElement: LI.parent.object-properties-section-root-element.selected
+active text: {y: 2}
 
 ArrowLeft:
 Viewport virtual selection: 1
diff --git a/third_party/blink/web_tests/http/tests/devtools/console/viewport-testing/console-key-expand.js b/third_party/blink/web_tests/http/tests/devtools/console/viewport-testing/console-key-expand.js
index dc796f1..23d5254 100644
--- a/third_party/blink/web_tests/http/tests/devtools/console/viewport-testing/console-key-expand.js
+++ b/third_party/blink/web_tests/http/tests/devtools/console/viewport-testing/console-key-expand.js
@@ -70,6 +70,9 @@
       next();
     },
 
+    // Note:
+    // During this test expanded objects
+    // do not include the __proto__ property.
     async function testExpandingObjects(next) {
       await clearAndLog(`console.log("before");console.log("text", obj1, obj2);console.log("after");`, 3);
       forceSelect(1);
@@ -78,24 +81,21 @@
       press('ArrowRight');
       dumpFocus(true, 1, true /* skipObjectCheck */);
 
-      // Expand object.
+      // Expand obj1.
       press('ArrowRight');
       dumpFocus(true, 1, true /* skipObjectCheck */);
       await ConsoleTestRunner.waitForRemoteObjectsConsoleMessagesPromise();
       press('ArrowDown');
       dumpFocus(true, 1, true /* skipObjectCheck */);
       press('ArrowDown');
-      press('ArrowDown');
       dumpFocus(true, 1, true /* skipObjectCheck */);
 
-      // Expand array.
+      // Expand obj2.
       press('ArrowRight');
       dumpFocus(true, 1, true /* skipObjectCheck */);
       await ConsoleTestRunner.waitForRemoteObjectsConsoleMessagesPromise();
       press('ArrowDown');
       press('ArrowDown');
-      press('ArrowDown');
-      press('ArrowDown');
       dumpFocus(true, 1, true /* skipObjectCheck */);
 
       press('ArrowUp');
diff --git a/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-getProperties-expected.txt b/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-getProperties-expected.txt
index c709018..58ac828 100644
--- a/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-getProperties-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-getProperties-expected.txt
@@ -13,6 +13,7 @@
     }
     isOwn : true
     name : "foo"
+    private : false
     setter : {
         description : "set foo(value) { }"
         objectId : <string>
@@ -33,6 +34,7 @@
     }
     isOwn : true
     name : "foo"
+    private : false
     synthetic : false
     wasThrown : false
     writable : false
diff --git a/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-localStorage-getProperties-expected.txt b/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-localStorage-getProperties-expected.txt
index f8cce45..7f97890 100644
--- a/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-localStorage-getProperties-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-localStorage-getProperties-expected.txt
@@ -4,6 +4,7 @@
     enumerable : true
     isOwn : true
     name : "testProperty"
+    private : false
     synthetic : false
     value : {
         description : "testPropertyValue"
diff --git a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
index f1bf8407..44d97f3 100644
--- a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
+++ b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -1461,6 +1461,8 @@
     attribute DEPTH_STENCIL_ATTACHMENT
     attribute DEPTH_TEST
     attribute DEPTH_WRITEMASK
+    attribute DISPATCH_INDIRECT_BUFFER
+    attribute DISPATCH_INDIRECT_BUFFER_BINDING
     attribute DITHER
     attribute DONT_CARE
     attribute DRAW_BUFFER0
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
index 15435bf..16929ff 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -1513,6 +1513,8 @@
 [Worker]     attribute DEPTH_STENCIL_ATTACHMENT
 [Worker]     attribute DEPTH_TEST
 [Worker]     attribute DEPTH_WRITEMASK
+[Worker]     attribute DISPATCH_INDIRECT_BUFFER
+[Worker]     attribute DISPATCH_INDIRECT_BUFFER_BINDING
 [Worker]     attribute DITHER
 [Worker]     attribute DONT_CARE
 [Worker]     attribute DRAW_BUFFER0
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
index ca7b4494..ec744c4c 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -8270,6 +8270,8 @@
     attribute DEPTH_STENCIL_ATTACHMENT
     attribute DEPTH_TEST
     attribute DEPTH_WRITEMASK
+    attribute DISPATCH_INDIRECT_BUFFER
+    attribute DISPATCH_INDIRECT_BUFFER_BINDING
     attribute DITHER
     attribute DONT_CARE
     attribute DRAW_BUFFER0
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
index f80d638e..3bcd6c8 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -1370,6 +1370,8 @@
 [Worker]     attribute DEPTH_STENCIL_ATTACHMENT
 [Worker]     attribute DEPTH_TEST
 [Worker]     attribute DEPTH_WRITEMASK
+[Worker]     attribute DISPATCH_INDIRECT_BUFFER
+[Worker]     attribute DISPATCH_INDIRECT_BUFFER_BINDING
 [Worker]     attribute DITHER
 [Worker]     attribute DONT_CARE
 [Worker]     attribute DRAW_BUFFER0
diff --git a/third_party/inspector_protocol/README.chromium b/third_party/inspector_protocol/README.chromium
index 688a760..386a859 100644
--- a/third_party/inspector_protocol/README.chromium
+++ b/third_party/inspector_protocol/README.chromium
@@ -2,7 +2,7 @@
 Short Name: inspector_protocol
 URL: https://chromium.googlesource.com/deps/inspector_protocol/
 Version: 0
-Revision: e8ba1a7665bdcd8336915d5ca4b390e0cf6b1f6f
+Revision: 91eb1c8784ab3d88ca1e327ffa727d922dd2ce70
 License: BSD
 License File: LICENSE
 Security Critical: yes
diff --git a/third_party/inspector_protocol/encoding/README.md b/third_party/inspector_protocol/encoding/README.md
index beeb850f..5e6d033 100644
--- a/third_party/inspector_protocol/encoding/README.md
+++ b/third_party/inspector_protocol/encoding/README.md
@@ -1,10 +1,29 @@
 # Inspector Protocol Encoding Library
 
-### Notice
+This library implements the encoding layer for the inspector protocol.
+The following facilities are provided:
 
-Code in this directory (including tests and library) is not used in production
-yet, and won't be for a little while. Below is a rough sketch as to the overall
-plan as well as the goals.
+- Some tools for portability, including a simple span implementation.
+  The library itself does not depend on anything except the C++ standard
+  libraries. For the JSON features, dependencies are injected via a
+  json::Platform object. See the json namespace in encoding.h
+
+- CBOR-based encoding/decoding functionality for a binary format. See the
+  comment at the top of the cbor namespace in encoding.h for details.
+
+- JSON encoder/decoder. See the json namespace in encoding.h for details.
+
+- CBOR and JSON parsers use a streaming API. See StreamingParserHandler
+  in encoding.h.
+
+- Two-way conversions between CBOR-based binary and JSON. See the
+  json::ConvertCBORToJSON / json::ConvertJSONToCBOR functions in encoding.h
+
+The library is designed for portability and users of the inspector protocol
+should link it into their programs. We do so in Chromium, V8, and
+internally at Google.
+
+TODO(johannes): Update the design documentation below.
 
 ## Objective
 
diff --git a/third_party/inspector_protocol/encoding/encoding.cc b/third_party/inspector_protocol/encoding/encoding.cc
index 2272e09e..2f69cfbd 100644
--- a/third_party/inspector_protocol/encoding/encoding.cc
+++ b/third_party/inspector_protocol/encoding/encoding.cc
@@ -846,7 +846,7 @@
           // value 0).
           // The represented allowed values range is -1 to -2^31.
           // They are mapped into the encoded range of 0 to 2^31-1.
-          // We check the the payload in token_start_internal_value_ against
+          // We check the payload in token_start_internal_value_ against
           // that range (2^31-1 is also known as
           // std::numeric_limits<int32_t>::max()).
           if (!bytes_read || token_start_internal_value_ >
@@ -1384,7 +1384,7 @@
         // Disallow overlong encodings for ascii characters, as these
         // would include " and other characters significant to JSON
         // string termination / control.
-        if (codepoint < 0x7f)
+        if (codepoint <= 0x7f)
           continue;
         // Invalid in UTF8, and can't be represented in UTF16 anyway.
         if (codepoint > 0x10ffff)
diff --git a/third_party/inspector_protocol/encoding/encoding.h b/third_party/inspector_protocol/encoding/encoding.h
index 6864f252..127c08828 100644
--- a/third_party/inspector_protocol/encoding/encoding.h
+++ b/third_party/inspector_protocol/encoding/encoding.h
@@ -5,6 +5,7 @@
 #ifndef INSPECTOR_PROTOCOL_ENCODING_ENCODING_H_
 #define INSPECTOR_PROTOCOL_ENCODING_ENCODING_H_
 
+#include <algorithm>
 #include <cstddef>
 #include <cstdint>
 #include <cstring>
@@ -14,6 +15,19 @@
 #include <vector>
 
 namespace inspector_protocol_encoding {
+// This library is designed to be portable. The only allowed dependency
+// are the C/C++ standard libraries, up to C++11. We support both 32 bit
+// and 64 architectures.
+//
+// Types used below:
+// uint8_t: a byte, e.g. for raw bytes or UTF8 characters
+// uint16_t: two bytes, e.g. for UTF16 characters
+// For input parameters:
+//   span<uint8_t>: pointer to bytes and length
+//   span<uint16_t>: pointer to UTF16 chars and length
+// For output parameters:
+//   std::vector<uint8_t> - Owned segment of bytes / utf8 characters and length.
+//   std::string - Same, for compatibility, even though char is signed.
 
 // =============================================================================
 // span - sequence of bytes
@@ -72,6 +86,22 @@
   return span<uint8_t>(reinterpret_cast<const uint8_t*>(v.data()), v.size());
 }
 
+// Less than / equality comparison functions for sorting / searching for byte
+// spans. These are similar to absl::string_view's < and == operators.
+inline bool SpanLessThan(span<uint8_t> x, span<uint8_t> y) noexcept {
+  auto min_size = std::min(x.size(), y.size());
+  const int r = min_size == 0 ? 0 : memcmp(x.data(), y.data(), min_size);
+  return (r < 0) || (r == 0 && x.size() < y.size());
+}
+
+inline bool SpanEquals(span<uint8_t> x, span<uint8_t> y) noexcept {
+  auto len = x.size();
+  if (len != y.size())
+    return false;
+  return x.data() == y.data() || len == 0 ||
+         std::memcmp(x.data(), y.data(), len) == 0;
+}
+
 // =============================================================================
 // Status and Error codes
 // =============================================================================
diff --git a/third_party/inspector_protocol/encoding/encoding_test.cc b/third_party/inspector_protocol/encoding/encoding_test.cc
index 7458eacf..b8c05795 100644
--- a/third_party/inspector_protocol/encoding/encoding_test.cc
+++ b/third_party/inspector_protocol/encoding/encoding_test.cc
@@ -121,6 +121,28 @@
   EXPECT_EQ(3u, SpanFrom("foo").size());
 }
 
+TEST(SpanComparisons, ByteWiseLexicographicalOrder) {
+  // Compare the empty span.
+  EXPECT_FALSE(SpanLessThan(span<uint8_t>(), span<uint8_t>()));
+  EXPECT_TRUE(SpanEquals(span<uint8_t>(), span<uint8_t>()));
+
+  // Compare message with itself.
+  std::string msg = "Hello, world";
+  EXPECT_FALSE(SpanLessThan(SpanFrom(msg), SpanFrom(msg)));
+  EXPECT_TRUE(SpanEquals(SpanFrom(msg), SpanFrom(msg)));
+
+  // Compare message and copy.
+  EXPECT_FALSE(SpanLessThan(SpanFrom(msg), SpanFrom(std::string(msg))));
+  EXPECT_TRUE(SpanEquals(SpanFrom(msg), SpanFrom(std::string(msg))));
+
+  // Compare two messages. |lesser_msg| < |msg| because of the first
+  // byte ('A' < 'H').
+  std::string lesser_msg = "A lesser message.";
+  EXPECT_TRUE(SpanLessThan(SpanFrom(lesser_msg), SpanFrom(msg)));
+  EXPECT_FALSE(SpanLessThan(SpanFrom(msg), SpanFrom(lesser_msg)));
+  EXPECT_FALSE(SpanEquals(SpanFrom(msg), SpanFrom(lesser_msg)));
+}
+
 // =============================================================================
 // Status and Error codes
 // =============================================================================
@@ -1325,6 +1347,25 @@
   writer->HandleString16(SpanFrom(UTF8ToUTF16(SpanFrom(utf8))));
 }
 
+TEST(JsonEncoder, OverlongEncodings) {
+  std::string out;
+  Status status;
+  std::unique_ptr<StreamingParserHandler> writer =
+      NewJSONEncoder(&GetTestPlatform(), &out, &status);
+
+  // We encode 0x7f, which is the DEL ascii character, as a 4 byte UTF8
+  // sequence. This is called an overlong encoding, because only 1 byte
+  // is needed to represent 0x7f as UTF8.
+  std::vector<uint8_t> chars = {
+      0xf0,  // Starts 4 byte utf8 sequence
+      0x80,  // continuation byte
+      0x81,  // continuation byte w/ payload bit 7 set to 1.
+      0xbf,  // continuation byte w/ payload bits 0-6 set to 11111.
+  };
+  writer->HandleString8(SpanFrom(chars));
+  EXPECT_EQ("\"\"", out);  // Empty string means that 0x7f was rejected (good).
+}
+
 TEST(JsonStdStringWriterTest, HelloWorld) {
   std::string out;
   Status status;
@@ -1561,6 +1602,13 @@
       "string16: a\x7f\n"
       "map end\n",
       log_.str());
+
+  // We've seen an implementation of UTF16ToUTF8 which would replace the DEL
+  // character with ' ', so this simple roundtrip tests the routines in
+  // encoding_test_helper.h, to make test failures of the above easier to
+  // diagnose.
+  std::vector<uint16_t> utf16 = UTF8ToUTF16(SpanFrom(json));
+  EXPECT_EQ(json, UTF16ToUTF8(SpanFrom(utf16)));
 }
 
 TEST_F(JsonParserTest, Whitespace) {
diff --git a/third_party/inspector_protocol/lib/Allocator_h.template b/third_party/inspector_protocol/lib/Allocator_h.template
index 15eaaaff..d94c4ca5 100644
--- a/third_party/inspector_protocol/lib/Allocator_h.template
+++ b/third_party/inspector_protocol/lib/Allocator_h.template
@@ -11,8 +11,6 @@
 namespace {{namespace}} {
 {% endfor %}
 
-enum NotNullTagEnum { NotNullLiteral };
-
 #define PROTOCOL_DISALLOW_COPY(ClassName) \
     private: \
         ClassName(const ClassName&) = delete; \
diff --git a/third_party/inspector_protocol/lib/DispatcherBase_h.template b/third_party/inspector_protocol/lib/DispatcherBase_h.template
index 7d859c4..4aa0688a 100644
--- a/third_party/inspector_protocol/lib/DispatcherBase_h.template
+++ b/third_party/inspector_protocol/lib/DispatcherBase_h.template
@@ -25,6 +25,9 @@
         kFallThrough = 2,
     };
 
+    // For historical reasons, these error codes correspond to commonly used
+    // XMLRPC codes (e.g. see METHOD_NOT_FOUND in
+    // https://github.com/python/cpython/blob/master/Lib/xmlrpc/client.py).
     enum ErrorCode {
         kParseError = -32700,
         kInvalidRequest = -32600,
diff --git a/third_party/inspector_protocol/lib/Forward_h.template b/third_party/inspector_protocol/lib/Forward_h.template
index ff5e685..746ba20b 100644
--- a/third_party/inspector_protocol/lib/Forward_h.template
+++ b/third_party/inspector_protocol/lib/Forward_h.template
@@ -28,7 +28,6 @@
 class ErrorSupport;
 class FundamentalValue;
 class ListValue;
-template<typename T> class Maybe;
 class Object;
 using Response = DispatchResponse;
 class SerializedValue;
diff --git a/third_party/inspector_protocol/lib/Maybe_h.template b/third_party/inspector_protocol/lib/Maybe_h.template
index 22cfac6b..8dfee7e9 100644
--- a/third_party/inspector_protocol/lib/Maybe_h.template
+++ b/third_party/inspector_protocol/lib/Maybe_h.template
@@ -7,53 +7,19 @@
 #ifndef {{"_".join(config.protocol.namespace)}}_Maybe_h
 #define {{"_".join(config.protocol.namespace)}}_Maybe_h
 
-// This macro allows to test for the version of the GNU C++ compiler.
-// Note that this also applies to compilers that masquerade as GCC,
-// for example clang and the Intel C++ compiler for Linux.
-// Use like:
-//  #if IP_GNUC_PREREQ(4, 3, 1)
-//   ...
-//  #endif
-#if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
-#define IP_GNUC_PREREQ(major, minor, patchlevel)                      \
-  ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= \
-   ((major)*10000 + (minor)*100 + (patchlevel)))
-#elif defined(__GNUC__) && defined(__GNUC_MINOR__)
-#define IP_GNUC_PREREQ(major, minor, patchlevel) \
-  ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >=  \
-   ((major)*10000 + (minor)*100 + (patchlevel)))
-#else
-#define IP_GNUC_PREREQ(major, minor, patchlevel) 0
-#endif
-
-#if defined(__mips64)
-#define IP_TARGET_ARCH_MIPS64 1
-#elif defined(__MIPSEB__) || defined(__MIPSEL__)
-#define IP_TARGET_ARCH_MIPS 1
-#endif
-
-// Allowing the use of noexcept by removing the keyword on older compilers that
-// do not support adding noexcept to default members.
-#if ((IP_GNUC_PREREQ(4, 9, 0) && !defined(IP_TARGET_ARCH_MIPS) && \
-      !defined(IP_TARGET_ARCH_MIPS64)) ||                         \
-     (defined(__clang__) && __cplusplus > 201300L))
-#define IP_NOEXCEPT noexcept
-#else
-#define IP_NOEXCEPT
-#endif
-
 //#include "Forward.h"
 
 {% for namespace in config.protocol.namespace %}
 namespace {{namespace}} {
 {% endfor %}
 
+namespace detail {
 template<typename T>
-class Maybe {
+class PtrMaybe {
 public:
-    Maybe() : m_value() { }
-    Maybe(std::unique_ptr<T> value) : m_value(std::move(value)) { }
-    Maybe(Maybe&& other) IP_NOEXCEPT : m_value(std::move(other.m_value)) {}
+    PtrMaybe() = default;
+    PtrMaybe(std::unique_ptr<T> value) : m_value(std::move(value)) { }
+    PtrMaybe(PtrMaybe&& other) noexcept : m_value(std::move(other.m_value)) {}
     void operator=(std::unique_ptr<T> value) { m_value = std::move(value); }
     T* fromJust() const { DCHECK(m_value); return m_value.get(); }
     T* fromMaybe(T* defaultValue) const { return m_value ? m_value.get() : defaultValue; }
@@ -64,76 +30,48 @@
 };
 
 template<typename T>
-class MaybeBase {
+class ValueMaybe {
 public:
-    MaybeBase() : m_isJust(false) { }
-    MaybeBase(T value) : m_isJust(true), m_value(value) { }
-    MaybeBase(MaybeBase&& other) IP_NOEXCEPT
+    ValueMaybe() : m_isJust(false), m_value() { }
+    ValueMaybe(T value) : m_isJust(true), m_value(std::move(value)) { }
+    ValueMaybe(ValueMaybe&& other) noexcept
         : m_isJust(other.m_isJust),
           m_value(std::move(other.m_value)) {}
     void operator=(T value) { m_value = value; m_isJust = true; }
-    T fromJust() const { DCHECK(m_isJust); return m_value; }
-    T fromMaybe(const T& defaultValue) const { return m_isJust ? m_value : defaultValue; }
+    const T& fromJust() const { DCHECK(m_isJust); return m_value; }
+    const T& fromMaybe(const T& defaultValue) const { return m_isJust ? m_value : defaultValue; }
     bool isJust() const { return m_isJust; }
-    T takeJust() { DCHECK(m_isJust); return m_value; }
-
-protected:
+    T takeJust() { DCHECK(m_isJust); return std::move(m_value); }
+private:
     bool m_isJust;
     T m_value;
 };
 
-template<>
-class Maybe<bool> : public MaybeBase<bool> {
-public:
-    Maybe() { m_value = false; }
-    Maybe(bool value) : MaybeBase(value) { }
-    Maybe(Maybe&& other) IP_NOEXCEPT : MaybeBase(std::move(other)) {}
-    using MaybeBase::operator=;
-};
+template <typename T>
+struct MaybeTypedef { typedef PtrMaybe<T> type; };
 
-template<>
-class Maybe<int> : public MaybeBase<int> {
-public:
-    Maybe() { m_value = 0; }
-    Maybe(int value) : MaybeBase(value) { }
-    Maybe(Maybe&& other) IP_NOEXCEPT : MaybeBase(std::move(other)) {}
-    using MaybeBase::operator=;
-};
+template <>
+struct MaybeTypedef<bool> { typedef ValueMaybe<bool> type; };
 
-template<>
-class Maybe<double> : public MaybeBase<double> {
-public:
-    Maybe() { m_value = 0; }
-    Maybe(double value) : MaybeBase(value) { }
-    Maybe(Maybe&& other) IP_NOEXCEPT : MaybeBase(std::move(other)) {}
-    using MaybeBase::operator=;
-};
+template <>
+struct MaybeTypedef<int> { typedef ValueMaybe<int> type; };
 
-template<>
-class Maybe<String> : public MaybeBase<String> {
-public:
-    Maybe() { }
-    Maybe(const String& value) : MaybeBase(value) { }
-    Maybe(Maybe&& other) IP_NOEXCEPT : MaybeBase(std::move(other)) {}
-    using MaybeBase::operator=;
-};
+template <>
+struct MaybeTypedef<double> { typedef ValueMaybe<double> type; };
 
-template<>
-class Maybe<Binary> : public MaybeBase<Binary> {
-public:
-    Maybe() { }
-    Maybe(Binary value) : MaybeBase(value) { }
-    Maybe(Maybe&& other) IP_NOEXCEPT : MaybeBase(std::move(other)) {}
-    using MaybeBase::operator=;
-};
+template <>
+struct MaybeTypedef<String> { typedef ValueMaybe<String> type; };
+
+template <>
+struct MaybeTypedef<Binary> { typedef ValueMaybe<Binary> type; };
+
+}  // namespace detail
+
+template <typename T>
+using Maybe = typename detail::MaybeTypedef<T>::type;
 
 {% for namespace in config.protocol.namespace %}
 } // namespace {{namespace}}
 {% endfor %}
 
-#undef IP_GNUC_PREREQ
-#undef IP_TARGET_ARCH_MIPS64
-#undef IP_TARGET_ARCH_MIPS
-#undef IP_NOEXCEPT
-
 #endif // !defined({{"_".join(config.protocol.namespace)}}_Maybe_h)
diff --git a/third_party/inspector_protocol/lib/encoding_cpp.template b/third_party/inspector_protocol/lib/encoding_cpp.template
index 23cf19b1..7b0eaa8 100644
--- a/third_party/inspector_protocol/lib/encoding_cpp.template
+++ b/third_party/inspector_protocol/lib/encoding_cpp.template
@@ -854,7 +854,7 @@
           // value 0).
           // The represented allowed values range is -1 to -2^31.
           // They are mapped into the encoded range of 0 to 2^31-1.
-          // We check the the payload in token_start_internal_value_ against
+          // We check the payload in token_start_internal_value_ against
           // that range (2^31-1 is also known as
           // std::numeric_limits<int32_t>::max()).
           if (!bytes_read || token_start_internal_value_ >
@@ -1392,7 +1392,7 @@
         // Disallow overlong encodings for ascii characters, as these
         // would include " and other characters significant to JSON
         // string termination / control.
-        if (codepoint < 0x7f)
+        if (codepoint <= 0x7f)
           continue;
         // Invalid in UTF8, and can't be represented in UTF16 anyway.
         if (codepoint > 0x10ffff)
diff --git a/third_party/inspector_protocol/lib/encoding_h.template b/third_party/inspector_protocol/lib/encoding_h.template
index 2c6cfc1..78727503 100644
--- a/third_party/inspector_protocol/lib/encoding_h.template
+++ b/third_party/inspector_protocol/lib/encoding_h.template
@@ -9,6 +9,7 @@
 #ifndef {{"_".join(config.protocol.namespace)}}_encoding_h
 #define {{"_".join(config.protocol.namespace)}}_encoding_h
 
+#include <algorithm>
 #include <cstddef>
 #include <cstdint>
 #include <cstring>
@@ -23,6 +24,19 @@
 
 // ===== encoding/encoding.h =====
 
+// This library is designed to be portable. The only allowed dependency
+// are the C/C++ standard libraries, up to C++11. We support both 32 bit
+// and 64 architectures.
+//
+// Types used below:
+// uint8_t: a byte, e.g. for raw bytes or UTF8 characters
+// uint16_t: two bytes, e.g. for UTF16 characters
+// For input parameters:
+//   span<uint8_t>: pointer to bytes and length
+//   span<uint16_t>: pointer to UTF16 chars and length
+// For output parameters:
+//   std::vector<uint8_t> - Owned segment of bytes / utf8 characters and length.
+//   std::string - Same, for compatibility, even though char is signed.
 
 // =============================================================================
 // span - sequence of bytes
@@ -81,6 +95,22 @@
   return span<uint8_t>(reinterpret_cast<const uint8_t*>(v.data()), v.size());
 }
 
+// Less than / equality comparison functions for sorting / searching for byte
+// spans. These are similar to absl::string_view's < and == operators.
+inline bool SpanLessThan(span<uint8_t> x, span<uint8_t> y) noexcept {
+  auto min_size = std::min(x.size(), y.size());
+  const int r = min_size == 0 ? 0 : memcmp(x.data(), y.data(), min_size);
+  return (r < 0) || (r == 0 && x.size() < y.size());
+}
+
+inline bool SpanEquals(span<uint8_t> x, span<uint8_t> y) noexcept {
+  auto len = x.size();
+  if (len != y.size())
+    return false;
+  return x.data() == y.data() || len == 0 ||
+         std::memcmp(x.data(), y.data(), len) == 0;
+}
+
 // =============================================================================
 // Status and Error codes
 // =============================================================================
diff --git a/third_party/protobuf/BUILD.gn b/third_party/protobuf/BUILD.gn
index e63be06..8891e1f 100644
--- a/third_party/protobuf/BUILD.gn
+++ b/third_party/protobuf/BUILD.gn
@@ -216,8 +216,7 @@
     "//libassistant/*",
 
     # Perfetto uses the full library for testing.
-    "//third_party/perfetto/protos/ftrace:full",
-    "//third_party/perfetto/gn:protobuf_full_deps",
+    "//third_party/perfetto/gn:protobuf_full",
 
     # Some tests inside ChromeOS need reflection to parse golden files.
     # Not included in production code.
diff --git a/third_party/webxr_test_pages/webxr-samples/magic-window.html b/third_party/webxr_test_pages/webxr-samples/magic-window.html
index 08fbc20..d011dd5 100644
--- a/third_party/webxr_test_pages/webxr-samples/magic-window.html
+++ b/third_party/webxr_test_pages/webxr-samples/magic-window.html
@@ -221,13 +221,8 @@
           }
 
           for (let view of pose.views) {
-            // TODO(crbug.com/966077): This appears to be returning null for inline.
-            if (session.mode.startsWith('immersive')) {
-              let viewport = session.renderState.baseLayer.getViewport(view);
-              gl.viewport(viewport.x, viewport.y,
-                          viewport.width, viewport.height);
-            }
-
+            let viewport = session.renderState.baseLayer.getViewport(view);
+            gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
             scene.draw(view.projectionMatrix, view.transform.inverse.matrix);
           }
         }
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index fb8ca22a..05f2c18b 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -669,6 +669,7 @@
 
     'tryserver.chromium.chrome': {
       'chromeos-betty-chrome': 'official_cros_chrome_sdk_headless_ozone',
+      'linux-chrome': 'official_goma',
       'linux-chromeos-chrome': 'official_goma_chromeos_minimal_symbols',
     },
 
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index e7b156a..92e762d 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -33471,6 +33471,7 @@
   <int value="-1605567628" label="disable-overlay-scrollbar"/>
   <int value="-1604051051" label="SpecialLocale:disabled"/>
   <int value="-1603404046" label="V8VmFuture:disabled"/>
+  <int value="-1601374850" label="DialMediaRouteProvider:disabled"/>
   <int value="-1599538279" label="enable-md-policy-page"/>
   <int value="-1596859081" label="WebAuthenticationPINSupport:enabled"/>
   <int value="-1596559650" label="max-tiles-for-interest-area"/>
@@ -33675,6 +33676,7 @@
   <int value="-1340055960" label="enable-streamlined-hosted-apps"/>
   <int value="-1338306372" label="BrowserTouchBar:enabled"/>
   <int value="-1337185440" label="enable-webvr"/>
+  <int value="-1336110789" label="CastMediaRouteProvider:disabled"/>
   <int value="-1335017208" label="KeyboardLockAPI:enabled"/>
   <int value="-1334327410" label="ash-enable-touch-view-testing"/>
   <int value="-1332267458" label="RemoveNavigationHistory:enabled"/>
@@ -34064,6 +34066,7 @@
   <int value="-771080109" label="GrantNotificationsToDSE:disabled"/>
   <int value="-770319039" label="enable-touch-editing"/>
   <int value="-769865314" label="AutofillCacheQueryResponses:disabled"/>
+  <int value="-766805224" label="MirroringService:enabled"/>
   <int value="-763900417" label="CCTModuleUseIntentExtras:enabled"/>
   <int value="-763759697" label="enable-audio-support-for-desktop-share"/>
   <int value="-763730918" label="CCTTargetTranslateLanguage:disabled"/>
@@ -34251,6 +34254,7 @@
   <int value="-478462945" label="enable-ephemeral-apps"/>
   <int value="-477101783" label="HandwritingGesture:disabled"/>
   <int value="-475049740" label="disable-vr-shell"/>
+  <int value="-475042780" label="DialMediaRouteProvider:enabled"/>
   <int value="-474806100" label="DataReductionProxyMainMenu:enabled"/>
   <int value="-474322576" label="disable-quick-unlock-pin"/>
   <int value="-473087416" label="DragTabsInTabletMode:enabled"/>
@@ -34711,6 +34715,7 @@
   <int value="219117936" label="AllowReaderForAccessibility:enabled"/>
   <int value="222184258"
       label="AutofillEnforceMinRequiredFieldsForHeuristics:disabled"/>
+  <int value="223591010" label="CastMediaRouteProvider:enabled"/>
   <int value="223662457" label="BackgroundLoadingForDownloads:enabled"/>
   <int value="229476202" label="CryptAuthV2Enrollment:enabled"/>
   <int value="233721248" label="DownloadRename:disabled"/>
@@ -34860,6 +34865,7 @@
   <int value="453102772" label="OfflinePagesLoadSignalCollecting:disabled"/>
   <int value="455698038"
       label="disable-gesture-requirement-for-media-playback"/>
+  <int value="455754036" label="MirroringService:disabled"/>
   <int value="457881889" label="enable-autoplay-muted-videos"/>
   <int value="458410433" label="disable-views-rect-based-targeting"/>
   <int value="460136092" label="MidiManagerAndroid:disabled"/>
diff --git a/ui/events/blink/blink_event_util.cc b/ui/events/blink/blink_event_util.cc
index 42b3cb0..ebb47db 100644
--- a/ui/events/blink/blink_event_util.cc
+++ b/ui/events/blink/blink_event_util.cc
@@ -24,7 +24,6 @@
 #include "ui/events/gesture_detection/motion_event.h"
 #include "ui/events/gesture_event_details.h"
 #include "ui/events/keycodes/dom/keycode_converter.h"
-#include "ui/events/types/scroll_types.h"
 #include "ui/gfx/geometry/angle_conversions.h"
 #include "ui/gfx/geometry/safe_integer_conversions.h"
 #include "ui/gfx/geometry/vector2d.h"
diff --git a/ui/events/blink/blink_event_util.h b/ui/events/blink/blink_event_util.h
index 7e392ae..fc2c81c 100644
--- a/ui/events/blink/blink_event_util.h
+++ b/ui/events/blink/blink_event_util.h
@@ -13,6 +13,7 @@
 #include "third_party/blink/public/platform/web_touch_event.h"
 #include "ui/events/event_constants.h"
 #include "ui/events/gesture_detection/motion_event.h"
+#include "ui/events/types/scroll_types.h"
 
 namespace gfx {
 class PointF;
@@ -25,9 +26,6 @@
 struct GestureEventData;
 struct GestureEventDetails;
 class MotionEvent;
-namespace input_types {
-enum class ScrollGranularity;
-}
 
 bool CanCoalesce(const blink::WebInputEvent& event_to_coalesce,
                  const blink::WebInputEvent& event);
diff --git a/ui/events/types/scroll_types.h b/ui/events/types/scroll_types.h
index f9af006..5ebf76f6 100644
--- a/ui/events/types/scroll_types.h
+++ b/ui/events/types/scroll_types.h
@@ -9,7 +9,7 @@
 
 namespace input_types {
 
-enum class ScrollGranularity {
+enum class ScrollGranularity : uint8_t {
   kScrollByPrecisePixel = 0,
   kFirstScrollGranularity = kScrollByPrecisePixel,
   kScrollByPixel,
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/exif_parser.js b/ui/file_manager/file_manager/foreground/js/metadata/exif_parser.js
index 16dca93f..1738e5d 100644
--- a/ui/file_manager/file_manager/foreground/js/metadata/exif_parser.js
+++ b/ui/file_manager/file_manager/foreground/js/metadata/exif_parser.js
@@ -20,470 +20,463 @@
     FILE_MANAGER_HOST__EXIF_PARSER +
     '/foreground/js/metadata/exif_constants.js');
 
-/**
- * @param {MetadataParserLogger} parent Parent object.
- * @constructor
- * @extends {ImageParser}
- */
-function ExifParser(parent) {
-  ImageParser.call(this, parent, 'jpeg', /\.jpe?g$/i);
-}
+/** @final */
+var ExifParser = class extends ImageParser {
+  /**
+   * @param {!MetadataParserLogger} parent Parent object.
+   */
+  constructor(parent) {
+    super(parent, 'jpeg', /\.jpe?g$/i);
+  }
 
-ExifParser.prototype = {
-  __proto__: ImageParser.prototype
-};
+  /**
+   * @param {File} file File object to parse.
+   * @param {!Object} metadata Metadata object for the file.
+   * @param {function(!Object)} callback Callback to be called on success.
+   * @param {function((Event|string))} errorCallback Error callback.
+   */
+  parse(file, metadata, callback, errorCallback) {
+    this.requestSlice(file, callback, errorCallback, metadata, 0);
+  }
 
-/**
- * @param {File} file File object to parse.
- * @param {!Object} metadata Metadata object for the file.
- * @param {function(!Object)} callback Callback to be called on success.
- * @param {function((Event|string))} errorCallback Error callback.
- */
-ExifParser.prototype.parse = function(file, metadata, callback, errorCallback) {
-  this.requestSlice(file, callback, errorCallback, metadata, 0);
-};
-
-/**
- * @param {File} file File object to parse.
- * @param {function(!Object)} callback Callback to be called on success.
- * @param {function((Event|string))} errorCallback Error callback.
- * @param {!Object} metadata Metadata object.
- * @param {number} filePos Position to slice at.
- * @param {number=} opt_length Number of bytes to slice. By default 1 KB.
- */
-ExifParser.prototype.requestSlice = function(
-    file, callback, errorCallback, metadata, filePos, opt_length) {
-  // Read at least 1Kb so that we do not issue too many read requests.
-  opt_length = Math.max(1024, opt_length || 0);
-
-  const self = this;
-  const reader = new FileReader();
-  reader.onerror = errorCallback;
-  reader.onload = () => {
-    self.parseSlice(
-        file, callback, errorCallback, metadata, filePos,
-        /** @type{ArrayBuffer} */ (reader.result));
-  };
-  reader.readAsArrayBuffer(file.slice(filePos, filePos + opt_length));
-};
-
-/**
- * @param {File} file File object to parse.
- * @param {function(!Object)} callback Callback to be called on success.
- * @param {function((Event|string))} errorCallback Error callback.
- * @param {!Object} metadata Metadata object.
- * @param {number} filePos Position to slice at.
- * @param {ArrayBuffer} buf Buffer to be parsed.
- */
-ExifParser.prototype.parseSlice = function(
-    file, callback, errorCallback, metadata, filePos, buf) {
-  try {
-    const br = new ByteReader(buf);
-
-    if (!br.canRead(4)) {
-      // We never ask for less than 4 bytes. This can only mean we reached EOF.
-      throw new Error('Unexpected EOF @' + (filePos + buf.byteLength));
-    }
-
-    if (filePos === 0) {
-      // First slice, check for the SOI mark.
-      const firstMark = this.readMark(br);
-      if (firstMark !== Exif.Mark.SOI) {
-        throw new Error('Invalid file header: ' + firstMark.toString(16));
-      }
-    }
+  /**
+   * @param {File} file File object to parse.
+   * @param {function(!Object)} callback Callback to be called on success.
+   * @param {function((Event|string))} errorCallback Error callback.
+   * @param {!Object} metadata Metadata object.
+   * @param {number} filePos Position to slice at.
+   * @param {number=} opt_length Number of bytes to slice. By default 1 KB.
+   */
+  requestSlice(file, callback, errorCallback, metadata, filePos, opt_length) {
+    // Read at least 1Kb so that we do not issue too many read requests.
+    opt_length = Math.max(1024, opt_length || 0);
 
     const self = this;
-
-    /**
-     * @param {number=} opt_offset
-     * @param {number=} opt_bytes
-     */
-    const reread = (opt_offset, opt_bytes) => {
-      self.requestSlice(
-          file, callback, errorCallback, metadata,
-          filePos + br.tell() + (opt_offset || 0), opt_bytes);
+    const reader = new FileReader();
+    reader.onerror = errorCallback;
+    reader.onload = () => {
+      self.parseSlice(
+          file, callback, errorCallback, metadata, filePos,
+          /** @type{ArrayBuffer} */ (reader.result));
     };
-
-    while (true) {
-      if (!br.canRead(4)) {
-        // Cannot read the mark and the length, request a minimum-size slice.
-        reread();
-        return;
-      }
-
-      const mark = this.readMark(br);
-      if (mark === Exif.Mark.SOS) {
-        throw new Error('SOS marker found before SOF');
-      }
-
-      const markLength = this.readMarkLength(br);
-
-      const nextSectionStart = br.tell() + markLength;
-      if (!br.canRead(markLength)) {
-        // Get the entire section.
-        if (filePos + br.tell() + markLength > file.size) {
-          throw new Error(
-              'Invalid section length @' + (filePos + br.tell() - 2));
-        }
-        reread(-4, markLength + 4);
-        return;
-      }
-
-      if (mark === Exif.Mark.EXIF) {
-        this.parseExifSection(metadata, buf, br);
-      } else if (ExifParser.isSOF_(mark)) {
-        // The most reliable size information is encoded in the SOF section.
-        br.seek(1, ByteReader.SEEK_CUR);  // Skip the precision byte.
-        const height = br.readScalar(2);
-        const width = br.readScalar(2);
-        ExifParser.setImageSize(metadata, width, height);
-        callback(metadata);  // We are done!
-        return;
-      }
-
-      br.seek(nextSectionStart, ByteReader.SEEK_BEG);
-    }
-  } catch (e) {
-    errorCallback(e.toString());
+    reader.readAsArrayBuffer(file.slice(filePos, filePos + opt_length));
   }
-};
-
-/**
- * @private
- * @param {number} mark Mark to be checked.
- * @return {boolean} True if the mark is SOF.
- */
-ExifParser.isSOF_ = mark => {
-  // There are 13 variants of SOF fragment format distinguished by the last
-  // hex digit of the mark, but the part we want is always the same.
-  if ((mark & ~0xF) !== Exif.Mark.SOF) {
-    return false;
-  }
-
-  // If the last digit is 4, 8 or 12 it is not really a SOF.
-  const type = mark & 0xF;
-  return (type !== 4 && type !== 8 && type !== 12);
-};
-
-/**
- * @param {Object} metadata Metadata object.
- * @param {ArrayBuffer} buf Buffer to be parsed.
- * @param {ByteReader} br Byte reader to be used.
- */
-ExifParser.prototype.parseExifSection = function(metadata, buf, br) {
-  const magic = br.readString(6);
-  if (magic !== 'Exif\0\0') {
-    // Some JPEG files may have sections marked with EXIF_MARK_EXIF
-    // but containing something else (e.g. XML text). Ignore such sections.
-    this.vlog('Invalid EXIF magic: ' + magic + br.readString(100));
-    return;
-  }
-
-  // Offsets inside the EXIF block are based after the magic string.
-  // Create a new ByteReader based on the current position to make offset
-  // calculations simpler.
-  br = new ByteReader(buf, br.tell());
-
-  const order = br.readScalar(2);
-  if (order === Exif.Align.LITTLE) {
-    br.setByteOrder(ByteReader.LITTLE_ENDIAN);
-  } else if (order !== Exif.Align.BIG) {
-    this.log('Invalid alignment value: ' + order.toString(16));
-    return;
-  }
-
-  const tag = br.readScalar(2);
-  if (tag !== Exif.Tag.TIFF) {
-    this.log('Invalid TIFF tag: ' + tag.toString(16));
-    return;
-  }
-
-  metadata.littleEndian = (order === Exif.Align.LITTLE);
-  metadata.ifd = {
-    image: {},
-    thumbnail: {},
-  };
-  let directoryOffset = br.readScalar(4);
-
-  // Image directory.
-  this.vlog('Read image directory.');
-  br.seek(directoryOffset);
-  directoryOffset = this.readDirectory(br, metadata.ifd.image);
-  metadata.imageTransform = this.parseOrientation(metadata.ifd.image);
-
-  // Thumbnail Directory chained from the end of the image directory.
-  if (directoryOffset) {
-    this.vlog('Read thumbnail directory.');
-    br.seek(directoryOffset);
-    this.readDirectory(br, metadata.ifd.thumbnail);
-    // If no thumbnail orientation is encoded, assume same orientation as
-    // the primary image.
-    metadata.thumbnailTransform =
-        this.parseOrientation(metadata.ifd.thumbnail) ||
-        metadata.imageTransform;
-  }
-
-  // EXIF Directory may be specified as a tag in the image directory.
-  if (Exif.Tag.EXIFDATA in metadata.ifd.image) {
-    this.vlog('Read EXIF directory.');
-    directoryOffset = metadata.ifd.image[Exif.Tag.EXIFDATA].value;
-    br.seek(directoryOffset);
-    metadata.ifd.exif = {};
-    this.readDirectory(br, metadata.ifd.exif);
-  }
-
-  // GPS Directory may also be linked from the image directory.
-  if (Exif.Tag.GPSDATA in metadata.ifd.image) {
-    this.vlog('Read GPS directory.');
-    directoryOffset = metadata.ifd.image[Exif.Tag.GPSDATA].value;
-    br.seek(directoryOffset);
-    metadata.ifd.gps = {};
-    this.readDirectory(br, metadata.ifd.gps);
-  }
-
-  // Thumbnail may be linked from the image directory.
-  if (Exif.Tag.JPG_THUMB_OFFSET in metadata.ifd.thumbnail &&
-      Exif.Tag.JPG_THUMB_LENGTH in metadata.ifd.thumbnail) {
-    this.vlog('Read thumbnail image.');
-    br.seek(metadata.ifd.thumbnail[Exif.Tag.JPG_THUMB_OFFSET].value);
-    metadata.thumbnailURL =
-        br.readImage(metadata.ifd.thumbnail[Exif.Tag.JPG_THUMB_LENGTH].value);
-  } else {
-    this.vlog('Image has EXIF data, but no JPG thumbnail.');
-  }
-};
-
-/**
- * @param {Object} metadata Metadata object.
- * @param {number} width Width in pixels.
- * @param {number} height Height in pixels.
- */
-ExifParser.setImageSize = (metadata, width, height) => {
-  if (metadata.imageTransform && metadata.imageTransform.rotate90) {
-    metadata.width = height;
-    metadata.height = width;
-  } else {
-    metadata.width = width;
-    metadata.height = height;
-  }
-};
-
-/**
- * @param {ByteReader} br Byte reader to be used for reading.
- * @return {number} Mark value.
- */
-ExifParser.prototype.readMark = br => {
-  return br.readScalar(2);
-};
-
-/**
- * @param {ByteReader} br Bye reader to be used for reading.
- * @return {number} Size of the mark at the current position.
- */
-ExifParser.prototype.readMarkLength = br => {
-  // Length includes the 2 bytes used to store the length.
-  return br.readScalar(2) - 2;
-};
-
-/**
- * @param {ByteReader} br Byte reader to be used for reading.
- * @param {Object<number, Object>} tags Map of tags to be written to.
- * @return {number} Directory offset.
- */
-ExifParser.prototype.readDirectory = function(br, tags) {
-  const entryCount = br.readScalar(2);
-  for (let i = 0; i < entryCount; i++) {
-    const tagId = /** @type Exif.Tag<number> */ (br.readScalar(2));
-    const tag = tags[tagId] = {id: tagId};
-    tag.format = br.readScalar(2);
-    tag.componentCount = br.readScalar(4);
-    this.readTagValue(br, tag);
-  }
-
-  return br.readScalar(4);
-};
-
-/**
- * @param {ByteReader} br Byte reader to be used for reading.
- * @param {ExifEntry} tag Tag object.
- */
-ExifParser.prototype.readTagValue = function(br, tag) {
-  const self = this;
 
   /**
-   * @param {number} size
-   * @param {function(number)=} opt_readFunction
-   * @param {boolean=} opt_signed
+   * @param {File} file File object to parse.
+   * @param {function(!Object)} callback Callback to be called on success.
+   * @param {function((Event|string))} errorCallback Error callback.
+   * @param {!Object} metadata Metadata object.
+   * @param {number} filePos Position to slice at.
+   * @param {ArrayBuffer} buf Buffer to be parsed.
    */
-  function safeRead(size, opt_readFunction, opt_signed) {
+  parseSlice(file, callback, errorCallback, metadata, filePos, buf) {
     try {
-      unsafeRead(size, opt_readFunction, opt_signed);
-    } catch (ex) {
-      self.log(
-          'error reading tag 0x' + tag.id.toString(16) + '/' + tag.format +
-          ', size ' + tag.componentCount + '*' + size + ' ' +
-          (ex.stack || '<no stack>') + ': ' + ex);
-      tag.value = null;
+      const br = new ByteReader(buf);
+
+      if (!br.canRead(4)) {
+        // We never ask for less than 4 bytes. This can only mean we reached
+        // EOF.
+        throw new Error('Unexpected EOF @' + (filePos + buf.byteLength));
+      }
+
+      if (filePos === 0) {
+        // First slice, check for the SOI mark.
+        const firstMark = this.readMark(br);
+        if (firstMark !== Exif.Mark.SOI) {
+          throw new Error('Invalid file header: ' + firstMark.toString(16));
+        }
+      }
+
+      const self = this;
+
+      /**
+       * @param {number=} opt_offset
+       * @param {number=} opt_bytes
+       */
+      const reread = (opt_offset, opt_bytes) => {
+        self.requestSlice(
+            file, callback, errorCallback, metadata,
+            filePos + br.tell() + (opt_offset || 0), opt_bytes);
+      };
+
+      while (true) {
+        if (!br.canRead(4)) {
+          // Cannot read the mark and the length, request a minimum-size slice.
+          reread();
+          return;
+        }
+
+        const mark = this.readMark(br);
+        if (mark === Exif.Mark.SOS) {
+          throw new Error('SOS marker found before SOF');
+        }
+
+        const markLength = this.readMarkLength(br);
+
+        const nextSectionStart = br.tell() + markLength;
+        if (!br.canRead(markLength)) {
+          // Get the entire section.
+          if (filePos + br.tell() + markLength > file.size) {
+            throw new Error(
+                'Invalid section length @' + (filePos + br.tell() - 2));
+          }
+          reread(-4, markLength + 4);
+          return;
+        }
+
+        if (mark === Exif.Mark.EXIF) {
+          this.parseExifSection(metadata, buf, br);
+        } else if (ExifParser.isSOF_(mark)) {
+          // The most reliable size information is encoded in the SOF section.
+          br.seek(1, ByteReader.SEEK_CUR);  // Skip the precision byte.
+          const height = br.readScalar(2);
+          const width = br.readScalar(2);
+          ExifParser.setImageSize(metadata, width, height);
+          callback(metadata);  // We are done!
+          return;
+        }
+
+        br.seek(nextSectionStart, ByteReader.SEEK_BEG);
+      }
+    } catch (e) {
+      errorCallback(e.toString());
     }
   }
 
   /**
-   * @param {number} size
-   * @param {function(number)=} opt_readFunction
-   * @param {boolean=} opt_signed
+   * @private
+   * @param {number} mark Mark to be checked.
+   * @return {boolean} True if the mark is SOF.
    */
-  function unsafeRead(size, opt_readFunction, opt_signed) {
-    const readFunction = opt_readFunction || (size => {
-                           return br.readScalar(size, opt_signed);
-                         });
+  static isSOF_(mark) {
+    // There are 13 variants of SOF fragment format distinguished by the last
+    // hex digit of the mark, but the part we want is always the same.
+    if ((mark & ~0xF) !== Exif.Mark.SOF) {
+      return false;
+    }
 
-    const totalSize = tag.componentCount * size;
-    if (totalSize < 1) {
-      // This is probably invalid exif data, skip it.
-      tag.componentCount = 1;
-      tag.value = br.readScalar(4);
+    // If the last digit is 4, 8 or 12 it is not really a SOF.
+    const type = mark & 0xF;
+    return (type !== 4 && type !== 8 && type !== 12);
+  }
+
+  /**
+   * @param {Object} metadata Metadata object.
+   * @param {ArrayBuffer} buf Buffer to be parsed.
+   * @param {ByteReader} br Byte reader to be used.
+   */
+  parseExifSection(metadata, buf, br) {
+    const magic = br.readString(6);
+    if (magic !== 'Exif\0\0') {
+      // Some JPEG files may have sections marked with EXIF_MARK_EXIF
+      // but containing something else (e.g. XML text). Ignore such sections.
+      this.vlog('Invalid EXIF magic: ' + magic + br.readString(100));
       return;
     }
 
-    if (totalSize > 4) {
-      // If the total size is > 4, the next 4 bytes will be a pointer to the
-      // actual data.
-      br.pushSeek(br.readScalar(4));
+    // Offsets inside the EXIF block are based after the magic string.
+    // Create a new ByteReader based on the current position to make offset
+    // calculations simpler.
+    br = new ByteReader(buf, br.tell());
+
+    const order = br.readScalar(2);
+    if (order === Exif.Align.LITTLE) {
+      br.setByteOrder(ByteReader.LITTLE_ENDIAN);
+    } else if (order !== Exif.Align.BIG) {
+      this.log('Invalid alignment value: ' + order.toString(16));
+      return;
     }
 
-    if (tag.componentCount === 1) {
-      tag.value = readFunction(size);
+    const tag = br.readScalar(2);
+    if (tag !== Exif.Tag.TIFF) {
+      this.log('Invalid TIFF tag: ' + tag.toString(16));
+      return;
+    }
+
+    metadata.littleEndian = (order === Exif.Align.LITTLE);
+    metadata.ifd = {
+      image: {},
+      thumbnail: {},
+    };
+    let directoryOffset = br.readScalar(4);
+
+    // Image directory.
+    this.vlog('Read image directory.');
+    br.seek(directoryOffset);
+    directoryOffset = this.readDirectory(br, metadata.ifd.image);
+    metadata.imageTransform = this.parseOrientation(metadata.ifd.image);
+
+    // Thumbnail Directory chained from the end of the image directory.
+    if (directoryOffset) {
+      this.vlog('Read thumbnail directory.');
+      br.seek(directoryOffset);
+      this.readDirectory(br, metadata.ifd.thumbnail);
+      // If no thumbnail orientation is encoded, assume same orientation as
+      // the primary image.
+      metadata.thumbnailTransform =
+          this.parseOrientation(metadata.ifd.thumbnail) ||
+          metadata.imageTransform;
+    }
+
+    // EXIF Directory may be specified as a tag in the image directory.
+    if (Exif.Tag.EXIFDATA in metadata.ifd.image) {
+      this.vlog('Read EXIF directory.');
+      directoryOffset = metadata.ifd.image[Exif.Tag.EXIFDATA].value;
+      br.seek(directoryOffset);
+      metadata.ifd.exif = {};
+      this.readDirectory(br, metadata.ifd.exif);
+    }
+
+    // GPS Directory may also be linked from the image directory.
+    if (Exif.Tag.GPSDATA in metadata.ifd.image) {
+      this.vlog('Read GPS directory.');
+      directoryOffset = metadata.ifd.image[Exif.Tag.GPSDATA].value;
+      br.seek(directoryOffset);
+      metadata.ifd.gps = {};
+      this.readDirectory(br, metadata.ifd.gps);
+    }
+
+    // Thumbnail may be linked from the image directory.
+    if (Exif.Tag.JPG_THUMB_OFFSET in metadata.ifd.thumbnail &&
+        Exif.Tag.JPG_THUMB_LENGTH in metadata.ifd.thumbnail) {
+      this.vlog('Read thumbnail image.');
+      br.seek(metadata.ifd.thumbnail[Exif.Tag.JPG_THUMB_OFFSET].value);
+      metadata.thumbnailURL =
+          br.readImage(metadata.ifd.thumbnail[Exif.Tag.JPG_THUMB_LENGTH].value);
     } else {
-      // Read multiple components into an array.
-      tag.value = [];
-      for (let i = 0; i < tag.componentCount; i++) {
-        tag.value[i] = readFunction(size);
-      }
-    }
-
-    if (totalSize > 4) {
-      // Go back to the previous position if we had to jump to the data.
-      br.popSeek();
-    } else if (totalSize < 4) {
-      // Otherwise, if the value wasn't exactly 4 bytes, skip over the
-      // unread data.
-      br.seek(4 - totalSize, ByteReader.SEEK_CUR);
+      this.vlog('Image has EXIF data, but no JPG thumbnail.');
     }
   }
 
-  switch (tag.format) {
-    case 1:  // Byte
-    case 7:  // Undefined
-      safeRead(1);
-      break;
+  /**
+   * @param {Object} metadata Metadata object.
+   * @param {number} width Width in pixels.
+   * @param {number} height Height in pixels.
+   */
+  static setImageSize(metadata, width, height) {
+    if (metadata.imageTransform && metadata.imageTransform.rotate90) {
+      metadata.width = height;
+      metadata.height = width;
+    } else {
+      metadata.width = width;
+      metadata.height = height;
+    }
+  }
 
-    case 2:  // String
-      safeRead(1);
-      if (tag.componentCount === 0) {
-        tag.value = '';
-      } else if (tag.componentCount === 1) {
-        tag.value = String.fromCharCode(/** @type {number} */ (tag.value));
+  /**
+   * @param {ByteReader} br Byte reader to be used for reading.
+   * @return {number} Mark value.
+   */
+  readMark(br) {
+    return br.readScalar(2);
+  }
+
+  /**
+   * @param {ByteReader} br Bye reader to be used for reading.
+   * @return {number} Size of the mark at the current position.
+   */
+  readMarkLength(br) {
+    // Length includes the 2 bytes used to store the length.
+    return br.readScalar(2) - 2;
+  }
+
+  /**
+   * @param {ByteReader} br Byte reader to be used for reading.
+   * @param {Object<number, Object>} tags Map of tags to be written to.
+   * @return {number} Directory offset.
+   */
+  readDirectory(br, tags) {
+    const entryCount = br.readScalar(2);
+    for (let i = 0; i < entryCount; i++) {
+      const tagId = /** @type Exif.Tag<number> */ (br.readScalar(2));
+      const tag = tags[tagId] = {id: tagId};
+      tag.format = br.readScalar(2);
+      tag.componentCount = br.readScalar(4);
+      this.readTagValue(br, tag);
+    }
+
+    return br.readScalar(4);
+  }
+
+  /**
+   * @param {ByteReader} br Byte reader to be used for reading.
+   * @param {ExifEntry} tag Tag object.
+   */
+  readTagValue(br, tag) {
+    const self = this;
+
+    /**
+     * @param {number} size
+     * @param {function(number)=} opt_readFunction
+     * @param {boolean=} opt_signed
+     */
+    function safeRead(size, opt_readFunction, opt_signed) {
+      try {
+        unsafeRead(size, opt_readFunction, opt_signed);
+      } catch (ex) {
+        self.log(
+            'error reading tag 0x' + tag.id.toString(16) + '/' + tag.format +
+            ', size ' + tag.componentCount + '*' + size + ' ' +
+            (ex.stack || '<no stack>') + ': ' + ex);
+        tag.value = null;
+      }
+    }
+
+    /**
+     * @param {number} size
+     * @param {function(number)=} opt_readFunction
+     * @param {boolean=} opt_signed
+     */
+    function unsafeRead(size, opt_readFunction, opt_signed) {
+      const readFunction = opt_readFunction || (size => {
+                             return br.readScalar(size, opt_signed);
+                           });
+
+      const totalSize = tag.componentCount * size;
+      if (totalSize < 1) {
+        // This is probably invalid exif data, skip it.
+        tag.componentCount = 1;
+        tag.value = br.readScalar(4);
+        return;
+      }
+
+      if (totalSize > 4) {
+        // If the total size is > 4, the next 4 bytes will be a pointer to the
+        // actual data.
+        br.pushSeek(br.readScalar(4));
+      }
+
+      if (tag.componentCount === 1) {
+        tag.value = readFunction(size);
       } else {
-        tag.value = String.fromCharCode.apply(
-            null, /** @type{Array<number>} */ (tag.value));
+        // Read multiple components into an array.
+        tag.value = [];
+        for (let i = 0; i < tag.componentCount; i++) {
+          tag.value[i] = readFunction(size);
+        }
       }
-      this.validateAndFixStringTag_(tag);
-      break;
 
-    case 3:  // Short
-      safeRead(2);
-      break;
+      if (totalSize > 4) {
+        // Go back to the previous position if we had to jump to the data.
+        br.popSeek();
+      } else if (totalSize < 4) {
+        // Otherwise, if the value wasn't exactly 4 bytes, skip over the
+        // unread data.
+        br.seek(4 - totalSize, ByteReader.SEEK_CUR);
+      }
+    }
 
-    case 4:  // Long
-      safeRead(4);
-      break;
+    switch (tag.format) {
+      case 1:  // Byte
+      case 7:  // Undefined
+        safeRead(1);
+        break;
 
-    case 9:  // Signed Long
-      safeRead(4, undefined, true);
-      break;
+      case 2:  // String
+        safeRead(1);
+        if (tag.componentCount === 0) {
+          tag.value = '';
+        } else if (tag.componentCount === 1) {
+          tag.value = String.fromCharCode(/** @type {number} */ (tag.value));
+        } else {
+          tag.value = String.fromCharCode.apply(
+              null, /** @type{Array<number>} */ (tag.value));
+        }
+        this.validateAndFixStringTag_(tag);
+        break;
 
-    case 5:  // Rational
-      safeRead(8, () => {
-        return [br.readScalar(4), br.readScalar(4)];
-      });
-      break;
+      case 3:  // Short
+        safeRead(2);
+        break;
 
-    case 10:  // Signed Rational
-      safeRead(8, () => {
-        return [br.readScalar(4, true), br.readScalar(4, true)];
-      });
-      break;
+      case 4:  // Long
+        safeRead(4);
+        break;
 
-    default:  // ???
-      this.vlog(
-          'Unknown tag format 0x' + Number(tag.id).toString(16) + ': ' +
-          tag.format);
-      safeRead(4);
-      break;
+      case 9:  // Signed Long
+        safeRead(4, undefined, true);
+        break;
+
+      case 5:  // Rational
+        safeRead(8, () => {
+          return [br.readScalar(4), br.readScalar(4)];
+        });
+        break;
+
+      case 10:  // Signed Rational
+        safeRead(8, () => {
+          return [br.readScalar(4, true), br.readScalar(4, true)];
+        });
+        break;
+
+      default:  // ???
+        this.vlog(
+            'Unknown tag format 0x' + Number(tag.id).toString(16) + ': ' +
+            tag.format);
+        safeRead(4);
+        break;
+    }
+
+    this.vlog(
+        'Read tag: 0x' + tag.id.toString(16) + '/' + tag.format + ': ' +
+        tag.value);
   }
 
-  this.vlog(
-      'Read tag: 0x' + tag.id.toString(16) + '/' + tag.format + ': ' +
-      tag.value);
-};
-
-/**
- * Validates string tag value, and fix it if necessary.
- * @param {!ExifEntry} tag A tag to be validated and fixed.
- * @private
- */
-ExifParser.prototype.validateAndFixStringTag_ = function(tag) {
-  if (tag.format === 2) {  // string
-    // String should end with null character.
-    if (tag.value.charAt(tag.value.length - 1) !== '\0') {
-      tag.value += '\0';
-      tag.componentCount = tag.value.length;
-      this.vlog(
-          'Invalid format: 0x' + tag.id.toString(16) + '/' + tag.format +
-          ': Did not end with null character. Null character is appended.');
+  /**
+   * Validates string tag value, and fix it if necessary.
+   * @param {!ExifEntry} tag A tag to be validated and fixed.
+   * @private
+   */
+  validateAndFixStringTag_(tag) {
+    if (tag.format === 2) {  // string
+      // String should end with null character.
+      if (tag.value.charAt(tag.value.length - 1) !== '\0') {
+        tag.value += '\0';
+        tag.componentCount = tag.value.length;
+        this.vlog(
+            'Invalid format: 0x' + tag.id.toString(16) + '/' + tag.format +
+            ': Did not end with null character. Null character is appended.');
+      }
     }
   }
+
+  /**
+   * Transform exif-encoded orientation into a set of parameters compatible with
+   * CSS and canvas transforms (scaleX, scaleY, rotation).
+   *
+   * @param {Object} ifd Exif property dictionary (image or thumbnail).
+   * @return {Object} Orientation object.
+   */
+  parseOrientation(ifd) {
+    if (ifd[Exif.Tag.ORIENTATION]) {
+      const index = (ifd[Exif.Tag.ORIENTATION].value || 1) - 1;
+      return {
+        scaleX: ExifParser.SCALEX[index],
+        scaleY: ExifParser.SCALEY[index],
+        rotate90: ExifParser.ROTATE90[index]
+      };
+    }
+    return null;
+  }
 };
 
 /**
  * Map from the exif orientation value to the horizontal scale value.
- * @const
- * @type {Array<number>}
+ * @const {Array<number>}
  */
 ExifParser.SCALEX = [1, -1, -1, 1, 1, 1, -1, -1];
 
 /**
  * Map from the exif orientation value to the vertical scale value.
- * @const
- * @type {Array<number>}
+ * @const {Array<number>}
  */
 ExifParser.SCALEY = [1, 1, -1, -1, -1, 1, 1, -1];
 
 /**
  * Map from the exit orientation value to the rotation value.
- * @const
- * @type {Array<number>}
+ * @const {Array<number>}
  */
 ExifParser.ROTATE90 = [0, 0, 0, 0, 1, 1, 1, 1];
 
-/**
- * Transform exif-encoded orientation into a set of parameters compatible with
- * CSS and canvas transforms (scaleX, scaleY, rotation).
- *
- * @param {Object} ifd Exif property dictionary (image or thumbnail).
- * @return {Object} Orientation object.
- */
-ExifParser.prototype.parseOrientation = ifd => {
-  if (ifd[Exif.Tag.ORIENTATION]) {
-    const index = (ifd[Exif.Tag.ORIENTATION].value || 1) - 1;
-    return {
-      scaleX: ExifParser.SCALEX[index],
-      scaleY: ExifParser.SCALEY[index],
-      rotate90: ExifParser.ROTATE90[index]
-    };
-  }
-  return null;
-};
-
 registerParserClass(ExifParser);
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/metadata_provider.js b/ui/file_manager/file_manager/foreground/js/metadata/metadata_provider.js
index ce1322e..3c6caef 100644
--- a/ui/file_manager/file_manager/foreground/js/metadata/metadata_provider.js
+++ b/ui/file_manager/file_manager/foreground/js/metadata/metadata_provider.js
@@ -3,36 +3,39 @@
 // found in the LICENSE file.
 
 /**
- * @param {!Array<string>} validPropertyNames
- * @constructor
- * @struct
+ * @abstract
  */
-function MetadataProvider(validPropertyNames) {
+class MetadataProvider {
   /**
-   * Set of valid property names. Key is the name of property and value is
-   * always true.
-   * @private {!Object<boolean>}
-   * @const
+   * @param {!Array<string>} validPropertyNames
    */
-  this.validPropertyNames_ = {};
-  for (let i = 0; i < validPropertyNames.length; i++) {
-    this.validPropertyNames_[validPropertyNames[i]] = true;
+  constructor(validPropertyNames) {
+    /**
+     * Set of valid property names. Key is the name of property and value is
+     * always true.
+     * @private @const {!Object<boolean>}
+     */
+    this.validPropertyNames_ = {};
+    for (let i = 0; i < validPropertyNames.length; i++) {
+      this.validPropertyNames_[validPropertyNames[i]] = true;
+    }
   }
+
+  checkPropertyNames(names) {
+    // Check if the property name is correct or not.
+    for (let i = 0; i < names.length; i++) {
+      assert(this.validPropertyNames_[names[i]]);
+    }
+  }
+
+  /**
+   * Obtains the metadata for the request.
+   * @abstract
+   * @param {!Array<!MetadataRequest>} requests
+   * @return {!Promise<!Array<!MetadataItem>>} Promise with obtained metadata.
+   *     It should not return rejected promise. Instead it should return
+   *     undefined property for property error, and should return empty
+   *     MetadataItem for entry error.
+   */
+  get(requests) {}
 }
-
-MetadataProvider.prototype.checkPropertyNames = function(names) {
-  // Check if the property name is correct or not.
-  for (let i = 0; i < names.length; i++) {
-    assert(this.validPropertyNames_[names[i]]);
-  }
-};
-
-/**
- * Obtains the metadata for the request.
- * @param {!Array<!MetadataRequest>} requests
- * @return {!Promise<!Array<!MetadataItem>>} Promise with obtained metadata. It
- *     should not return rejected promise. Instead it should return undefined
- *     property for property error, and should return empty MetadataItem for
- *     entry error.
- */
-MetadataProvider.prototype.get;
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/mock_metadata.js b/ui/file_manager/file_manager/foreground/js/metadata/mock_metadata.js
index f47e56a..5bc9fd3b6 100644
--- a/ui/file_manager/file_manager/foreground/js/metadata/mock_metadata.js
+++ b/ui/file_manager/file_manager/foreground/js/metadata/mock_metadata.js
@@ -6,14 +6,14 @@
  * Returns a mock of metadata model.
  *
  * @extends {MetadataModel}
+ * @final
  */
 class MockMetadataModel {
   /** @param {Object} initial_properties */
   constructor(initial_properties) {
     /**
      * Dummy properties, which can be overwritten by a test.
-     * @public {Object}
-     * @const
+     * @public @const {Object}
      */
     this.properties = initial_properties;
   }
diff --git a/ui/file_manager/file_manager/foreground/js/ui/dialog_footer.js b/ui/file_manager/file_manager/foreground/js/ui/dialog_footer.js
index f4112fd0..707223c 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/dialog_footer.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/dialog_footer.js
@@ -4,88 +4,78 @@
 
 /**
  * Footer shown when the Files app is opened as a file/folder selecting dialog.
- * @param {DialogType} dialogType Dialog type.
- * @param {!Element} container Container of the dialog footer.
- * @param {!Element} filenameInput Filename input element.
- * @constructor
  */
-function DialogFooter(dialogType, container, filenameInput) {
+class DialogFooter {
   /**
-   * Root element of the footer.
-   * @type {!Element}
-   * @const
+   * @param {DialogType} dialogType Dialog type.
+   * @param {!Element} container Container of the dialog footer.
+   * @param {!Element} filenameInput Filename input element.
    */
-  this.element = container;
+  constructor(dialogType, container, filenameInput) {
+    /**
+     * Root element of the footer.
+     * @public @const {!Element}
+     */
+    this.element = container;
 
-  /**
-   * Dialog type.
-   * @type {DialogType}
-   * @const
-   * @private
-   */
-  this.dialogType_ = dialogType;
+    /**
+     * Dialog type.
+     * @private @const {DialogType}
+     */
+    this.dialogType_ = dialogType;
 
-  /**
-   * OK button in the footer.
-   * @const
-   * @type {!HTMLButtonElement}
-   */
-  this.okButton = /** @type {!HTMLButtonElement} */
-      (container.querySelector('.ok'));
+    /**
+     * OK button in the footer.
+     * @public @const {!HTMLButtonElement}
+     */
+    this.okButton =
+        /** @type {!HTMLButtonElement} */ (container.querySelector('.ok'));
 
-  /**
-   * OK button's label in the footer.
-   * @const
-   * @type {!HTMLSpanElement}
-   */
-  this.okButtonLabel = /** @type {!HTMLSpanElement} */
-      (this.okButton.querySelector('span'));
+    /**
+     * OK button's label in the footer.
+     * @public @const {!HTMLSpanElement}
+     */
+    this.okButtonLabel = /** @type {!HTMLSpanElement} */
+        (this.okButton.querySelector('span'));
 
-  /**
-   * Cancel button in the footer.
-   * @const
-   * @type {!HTMLButtonElement}
-   */
-  this.cancelButton = /** @type {!HTMLButtonElement} */
-      (container.querySelector('.cancel'));
+    /**
+     * Cancel button in the footer.
+     * @public @const {!HTMLButtonElement}
+     */
+    this.cancelButton = /** @type {!HTMLButtonElement} */
+        (container.querySelector('.cancel'));
 
-  /**
-   * New folder button in the footer.
-   * @const
-   * @type {!HTMLButtonElement}
-   */
-  this.newFolderButton = /** @type {!HTMLButtonElement} */
-      (container.querySelector('#new-folder-button'));
+    /**
+     * New folder button in the footer.
+     * @public @const {!HTMLButtonElement}
+     */
+    this.newFolderButton = /** @type {!HTMLButtonElement} */
+        (container.querySelector('#new-folder-button'));
 
-  /**
-   * File type selector in the footer.
-   * @const
-   * @type {!HTMLSelectElement}
-   */
-  this.fileTypeSelector = /** @type {!HTMLSelectElement} */
-      (container.querySelector('.file-type'));
+    /**
+     * File type selector in the footer.
+     * @public @const {!HTMLSelectElement}
+     */
+    this.fileTypeSelector = /** @type {!HTMLSelectElement} */
+        (container.querySelector('.file-type'));
 
-  /**
-   * @const
-   * @type {!CrInputElement}
-   */
-  this.filenameInput = /** @type {!CrInputElement} */ (filenameInput);
+    /** @public @const {!CrInputElement} */
+    this.filenameInput = /** @type {!CrInputElement} */ (filenameInput);
 
-  // Initialize the element styles.
-  container.classList.add('button-panel');
+    // Initialize the element styles.
+    container.classList.add('button-panel');
 
-  // Set initial label for OK button. The label can be updated dynamically
-  // depending on dialog types.
-  this.okButtonLabel.textContent = DialogFooter.getOKButtonLabel_(dialogType);
+    // Set initial label for OK button. The label can be updated dynamically
+    // depending on dialog types.
+    this.okButtonLabel.textContent = DialogFooter.getOKButtonLabel_(dialogType);
 
-  // Register event handlers.
-  this.filenameInput.addEventListener(
-      'keydown', this.onFilenameInputKeyDown_.bind(this));
-  this.filenameInput.addEventListener(
-      'focus', this.onFilenameInputFocus_.bind(this));
-}
+    // Register event handlers.
+    this.filenameInput.addEventListener(
+        'keydown', this.onFilenameInputKeyDown_.bind(this));
+    this.filenameInput.addEventListener(
+        'focus', this.onFilenameInputFocus_.bind(this));
+  }
 
-DialogFooter.prototype = {
   /**
    * @return {number} Selected filter index. The index is 1 based and 0 means
    *     'any file types'. Keep the meaniing consistent with the index passed to
@@ -94,137 +84,136 @@
   get selectedFilterIndex() {
     return ~~this.fileTypeSelector.value;
   }
-};
 
-/**
- * Finds the dialog footer element for the dialog type.
- * @param {DialogType} dialogType Dialog type.
- * @param {!Document} document Document.
- * @return {!DialogFooter} Dialog footer created with the found element.
- */
-DialogFooter.findDialogFooter = (dialogType, document) => {
-  return new DialogFooter(
-      dialogType, queryRequiredElement('.dialog-footer'),
-      queryRequiredElement('#filename-input-box cr-input'));
-};
-
-/**
- * Obtains the label of OK button for the dialog type.
- * @param {DialogType} dialogType Dialog type.
- * @return {string} OK button label.
- * @private
- */
-DialogFooter.getOKButtonLabel_ = dialogType => {
-  switch (dialogType) {
-    case DialogType.SELECT_UPLOAD_FOLDER:
-      return str('UPLOAD_LABEL');
-
-    case DialogType.SELECT_SAVEAS_FILE:
-      return str('SAVE_LABEL');
-
-    case DialogType.SELECT_FOLDER:
-    case DialogType.SELECT_OPEN_FILE:
-    case DialogType.SELECT_OPEN_MULTI_FILE:
-    case DialogType.FULL_PAGE:
-      return str('OPEN_LABEL');
-
-    default:
-      throw new Error('Unknown dialog type: ' + dialogType);
+  /**
+   * Finds the dialog footer element for the dialog type.
+   * @param {DialogType} dialogType Dialog type.
+   * @param {!Document} document Document.
+   * @return {!DialogFooter} Dialog footer created with the found element.
+   */
+  static findDialogFooter(dialogType, document) {
+    return new DialogFooter(
+        dialogType, queryRequiredElement('.dialog-footer'),
+        queryRequiredElement('#filename-input-box cr-input'));
   }
-};
 
-/**
- * Fills the file type list or hides it.
- * @param {!Array<{extensions: Array<string>, description: string}>} fileTypes
- *     List of file type.
- * @param {boolean} includeAllFiles Whether the filter includes the 'all files'
- *     item or not.
- */
-DialogFooter.prototype.initFileTypeFilter = function(
-    fileTypes, includeAllFiles) {
-  for (let i = 0; i < fileTypes.length; i++) {
-    const fileType = fileTypes[i];
-    const option = document.createElement('option');
-    let description = fileType.description;
-    if (!description) {
-      // See if all the extensions in the group have the same description.
-      for (let j = 0; j !== fileType.extensions.length; j++) {
-        const currentDescription = FileListModel.getFileTypeString(
-            FileType.getTypeForName('.' + fileType.extensions[j]));
+  /**
+   * Obtains the label of OK button for the dialog type.
+   * @param {DialogType} dialogType Dialog type.
+   * @return {string} OK button label.
+   * @private
+   */
+  static getOKButtonLabel_(dialogType) {
+    switch (dialogType) {
+      case DialogType.SELECT_UPLOAD_FOLDER:
+        return str('UPLOAD_LABEL');
+
+      case DialogType.SELECT_SAVEAS_FILE:
+        return str('SAVE_LABEL');
+
+      case DialogType.SELECT_FOLDER:
+      case DialogType.SELECT_OPEN_FILE:
+      case DialogType.SELECT_OPEN_MULTI_FILE:
+      case DialogType.FULL_PAGE:
+        return str('OPEN_LABEL');
+
+      default:
+        throw new Error('Unknown dialog type: ' + dialogType);
+    }
+  }
+
+  /**
+   * Fills the file type list or hides it.
+   * @param {!Array<{extensions: Array<string>, description: string}>} fileTypes
+   *     List of file type.
+   * @param {boolean} includeAllFiles Whether the filter includes the 'all
+   *     files' item or not.
+   */
+  initFileTypeFilter(fileTypes, includeAllFiles) {
+    for (let i = 0; i < fileTypes.length; i++) {
+      const fileType = fileTypes[i];
+      const option = document.createElement('option');
+      let description = fileType.description;
+      if (!description) {
+        // See if all the extensions in the group have the same description.
+        for (let j = 0; j !== fileType.extensions.length; j++) {
+          const currentDescription = FileListModel.getFileTypeString(
+              FileType.getTypeForName('.' + fileType.extensions[j]));
+          if (!description) {
+            // Set the first time.
+            description = currentDescription;
+          } else if (description != currentDescription) {
+            // No single description, fall through to the extension list.
+            description = null;
+            break;
+          }
+        }
+
         if (!description) {
-          // Set the first time.
-          description = currentDescription;
-        } else if (description != currentDescription) {
-          // No single description, fall through to the extension list.
-          description = null;
-          break;
+          // Convert ['jpg', 'png'] to '*.jpg, *.png'.
+          description = fileType.extensions
+                            .map(s => {
+                              return '*.' + s;
+                            })
+                            .join(', ');
         }
       }
+      option.innerText = description;
+      option.value = i + 1;
 
-      if (!description) {
-        // Convert ['jpg', 'png'] to '*.jpg, *.png'.
-        description = fileType.extensions
-                          .map(s => {
-                            return '*.' + s;
-                          })
-                          .join(', ');
+      if (fileType.selected) {
+        option.selected = true;
       }
-    }
-    option.innerText = description;
-    option.value = i + 1;
 
-    if (fileType.selected) {
-      option.selected = true;
+      this.fileTypeSelector.appendChild(option);
     }
 
-    this.fileTypeSelector.appendChild(option);
-  }
-
-  if (includeAllFiles) {
-    const option = document.createElement('option');
-    option.innerText = str('ALL_FILES_FILTER');
-    option.value = 0;
-    if (this.dialogType_ === DialogType.SELECT_SAVEAS_FILE) {
-      option.selected = true;
+    if (includeAllFiles) {
+      const option = document.createElement('option');
+      option.innerText = str('ALL_FILES_FILTER');
+      option.value = 0;
+      if (this.dialogType_ === DialogType.SELECT_SAVEAS_FILE) {
+        option.selected = true;
+      }
+      this.fileTypeSelector.appendChild(option);
     }
-    this.fileTypeSelector.appendChild(option);
+
+    const options = this.fileTypeSelector.querySelectorAll('option');
+    if (options.length >= 2) {
+      // There is in fact no choice, show the selector.
+      this.fileTypeSelector.hidden = false;
+    }
   }
 
-  const options = this.fileTypeSelector.querySelectorAll('option');
-  if (options.length >= 2) {
-    // There is in fact no choice, show the selector.
-    this.fileTypeSelector.hidden = false;
+  /**
+   * @param {Event} event Focus event.
+   * @private
+   */
+  onFilenameInputFocus_(event) {
+    // On focus we want to select everything but the extension, but
+    // Chrome will select-all after the focus event completes.  We
+    // schedule a timeout to alter the focus after that happens.
+    setTimeout(() => {
+      this.selectTargetNameInFilenameInput();
+    }, 0);
   }
-};
 
-/**
- * @param {Event} event Focus event.
- * @private
- */
-DialogFooter.prototype.onFilenameInputFocus_ = function(event) {
-  // On focus we want to select everything but the extension, but
-  // Chrome will select-all after the focus event completes.  We
-  // schedule a timeout to alter the focus after that happens.
-  setTimeout(() => {
-    this.selectTargetNameInFilenameInput();
-  }, 0);
-};
-
-/**
- * @param {Event} event Key event.
- * @private
- */
-DialogFooter.prototype.onFilenameInputKeyDown_ = function(event) {
-  if ((util.getKeyModifiers(event) + event.keyCode) === '13' /* Enter */) {
-    this.okButton.click();
+  /**
+   * @param {Event} event Key event.
+   * @private
+   */
+  onFilenameInputKeyDown_(event) {
+    if ((util.getKeyModifiers(event) + event.keyCode) === '13' /* Enter */) {
+      this.okButton.click();
+    }
   }
-};
 
-DialogFooter.prototype.selectTargetNameInFilenameInput = function() {
-  const selectionEnd = this.filenameInput.value.lastIndexOf('.');
-  if (selectionEnd == -1) {
-    this.filenameInput.select();
-  } else {
-    this.filenameInput.select(0, selectionEnd);
+  selectTargetNameInFilenameInput() {
+    const selectionEnd = this.filenameInput.value.lastIndexOf('.');
+    if (selectionEnd == -1) {
+      this.filenameInput.select();
+    } else {
+      this.filenameInput.select(0, selectionEnd);
+    }
   }
-};
+}
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_tap_handler.js b/ui/file_manager/file_manager/foreground/js/ui/file_tap_handler.js
index 968b69b..269cb38 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/file_tap_handler.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/file_tap_handler.js
@@ -11,68 +11,221 @@
  *
  * @constructor
  */
-function FileTapHandler() {
-  /**
-   * Whether the pointer is currently down and at the same place as the initial
-   * position.
-   * @type {boolean}
-   * @private
-   */
-  this.tapStarted_ = false;
+class FileTapHandler {
+  constructor() {
+    /**
+     * Whether the pointer is currently down and at the same place as the
+     * initial position.
+     * @private {boolean}
+     */
+    this.tapStarted_ = false;
+
+    /** @private {boolean} */
+    this.isLongTap_ = false;
+
+    /** @private {boolean} */
+    this.isTwoFingerTap_ = false;
+
+    /** @private {boolean} */
+    this.hasLongPressProcessed_ = false;
+
+    /** @private {number} */
+    this.longTapDetectorTimerId_ = -1;
+
+    /**
+     * The absolute sum of all touch y deltas.
+     * @private {number}
+     */
+    this.totalMoveY_ = 0;
+
+    /**
+     * The absolute sum of all touch x deltas.
+     * @private {number}
+     */
+    this.totalMoveX_ = 0;
+
+    /**
+     * If defined, the identifier of the single touch that is active.  Note that
+     * 0 is a valid touch identifier - it should not be treated equivalently to
+     * undefined.
+     * @private {number|undefined}
+     */
+    this.activeTouchId_ = undefined;
+
+    /**
+     * The index of the item which is being touched by the active touch. This is
+     * valid only when |activeTouchId_| is defined.
+     * @private {number}
+     */
+    this.activeItemIndex_ = -1;
+
+    /** @private {?number} */
+    this.lastMoveX_ = null;
+
+    /** @private {?number} */
+    this.lastMoveY_ = null;
+
+    /** @private {?number} */
+    this.lastTouchX_ = null;
+
+    /** @private {?number} */
+    this.lastTouchY_ = null;
+
+    /** @private {?number} */
+    this.startTouchX_ = null;
+
+    /** @private {?number} */
+    this.startTouchY_ = null;
+  }
 
   /**
-   * @type {boolean}
-   * @private
+   * Handles touch events.
+   * The propagation of the |event| will be cancelled if the |callback| takes
+   * any action, so as to avoid receiving mouse click events for the tapping and
+   * processing them duplicatedly.
+   * @param {!Event} event a touch event.
+   * @param {number} index of the target item in the file list.
+   * @param {function(!Event, number, !FileTapHandler.TapEvent)} callback called
+   *     when a tap event is detected. Should return true if it has taken any
+   *     action, and false if it ignroes the event.
+   * @return {boolean} true if a tap or longtap event was detected and the
+   *     callback processed it. False otherwise.
    */
-  this.isLongTap_ = false;
+  handleTouchEvents(event, index, callback) {
+    switch (event.type) {
+      case 'touchstart':
+        // Only track the position of the single touch. However, we detect a
+        // two-finger tap for opening a context menu of the target.
+        if (event.touches.length == 2) {
+          this.isTwoFingerTap_ = true;
+          return false;
+        } else if (event.touches.length > 2) {
+          this.tapStarted_ = false;
+          return false;
+        }
+
+        // It's still possible there could be an active "touch" if the user is
+        // simultaneously using a mouse and a touch input.
+        // TODO(yamaguchi): add this after adding handler for touchcancel that
+        // can reset this.activeTouchId_ to undefined.
+        // if (this.activeTouchId_ !== undefined)
+        //   return;
+        var touch = event.targetTouches[0];
+        this.activeTouchId_ = touch.identifier;
+        this.startTouchX_ = this.lastTouchX_ = touch.clientX;
+        this.startTouchY_ = this.lastTouchY_ = touch.clientY;
+        this.totalMoveX_ = 0;
+        this.totalMoveY_ = 0;
+
+        this.tapStarted_ = true;
+        this.activeItemIndex_ = index;
+        this.isLongTap_ = false;
+        this.isTwoFingerTap_ = false;
+        this.hasLongPressProcessed_ = false;
+        this.longTapDetectorTimerId_ = setTimeout(() => {
+          this.longTapDetectorTimerId_ = -1;
+          if (!this.tapStarted_) {
+            return;
+          }
+          this.isLongTap_ = true;
+          if (callback(event, index, FileTapHandler.TapEvent.LONG_PRESS)) {
+            this.hasLongPressProcessed_ = true;
+          }
+        }, FileTapHandler.LONG_PRESS_THRESHOLD_MILLISECONDS);
+        break;
+
+      case 'touchmove':
+        if (this.activeTouchId_ === undefined) {
+          break;
+        }
+        var touch = this.findActiveTouch_(event.changedTouches);
+        if (!touch) {
+          break;
+        }
+
+        const clientX = touch.clientX;
+        const clientY = touch.clientY;
+
+        const moveX = this.lastTouchX_ - clientX;
+        const moveY = this.lastTouchY_ - clientY;
+        this.totalMoveX_ += Math.abs(moveX);
+        this.totalMoveY_ += Math.abs(moveY);
+        this.lastTouchX_ = clientX;
+        this.lastTouchY_ = clientY;
+
+        const couldBeTap =
+            this.totalMoveY_ <= FileTapHandler.MAX_TRACKING_FOR_TAP_ ||
+            this.totalMoveX_ <= FileTapHandler.MAX_TRACKING_FOR_TAP_;
+
+        if (!couldBeTap) {
+          // If the pointer is slided, it is a drag. It is no longer a tap.
+          this.tapStarted_ = false;
+        }
+        this.lastMoveX_ = moveX;
+        this.lastMoveY_ = moveY;
+        break;
+
+      case 'touchend':
+        if (!this.tapStarted_) {
+          break;
+        }
+        // Mark as no longer being touched.
+        // Two-finger tap event is issued when either of the 2 touch points is
+        // released. Stop tracking the tap to avoid issuing duplicate events.
+        this.tapStarted_ = false;
+        this.activeTouchId_ = undefined;
+        if (this.longTapDetectorTimerId_ != -1) {
+          clearTimeout(this.longTapDetectorTimerId_);
+          this.longTapDetectorTimerId_ = -1;
+        }
+        if (this.isLongTap_) {
+          // The item at the touch start position is treated as the target item,
+          // rather than the one at the touch end position. Note that |index| is
+          // the latter.
+          if (this.hasLongPressProcessed_ ||
+              callback(
+                  event, this.activeItemIndex_,
+                  FileTapHandler.TapEvent.LONG_TAP)) {
+            event.preventDefault();
+            return true;
+          }
+        } else {
+          // The item at the touch start position of the active touch is treated
+          // as the target item. In case of the two-finger tap, the first touch
+          // point points to the target.
+          if (callback(
+                  event, this.activeItemIndex_,
+                  this.isTwoFingerTap_ ?
+                      FileTapHandler.TapEvent.TWO_FINGER_TAP :
+                      FileTapHandler.TapEvent.TAP)) {
+            event.preventDefault();
+            return true;
+          }
+        }
+        break;
+    }
+    return false;
+  }
 
   /**
-   * @type {boolean}
+   * Given a list of Touches, find the one matching our activeTouch
+   * identifier. Note that Chrome currently always uses 0 as the identifier.
+   * In that case we'll end up always choosing the first element in the list.
+   * @param {TouchList} touches The list of Touch objects to search.
+   * @return {!Touch|undefined} The touch matching our active ID if any.
    * @private
    */
-  this.isTwoFingerTap_ = false;
-
-  /**
-   * @type {boolean}
-   * @private
-   */
-  this.hasLongPressProcessed_ = false;
-
-  /**
-   * @type {number}
-   * @private
-   */
-  this.longTapDetectorTimerId_ = -1;
-
-  /**
-   * The absolute sum of all touch y deltas.
-   * @type {number}
-   * @private
-   */
-  this.totalMoveY_ = 0;
-
-  /**
-   * The absolute sum of all touch x deltas.
-   * @type {number}
-   * @private
-   */
-  this.totalMoveX_ = 0;
-
-  /**
-   * If defined, the identifer of the single touch that is active.  Note that
-   * 0 is a valid touch identifier - it should not be treated equivalently to
-   * undefined.
-   * @type {number|undefined}
-   * @private
-   */
-  this.activeTouchId_ = undefined;
-
-  /**
-   * The index of the item which is being touched by the active touch. This is
-   * valid only when |activeTouchId_| is defined.
-   * @type {number}
-   */
-  this.activeItemIndex_ = -1;
+  findActiveTouch_(touches) {
+    assert(this.activeTouchId_ !== undefined, 'Expecting an active touch');
+    // A TouchList isn't actually an array, so we shouldn't use
+    // Array.prototype.filter/some, etc.
+    for (let i = 0; i < touches.length; i++) {
+      if (touches[i].identifier == this.activeTouchId_) {
+        return touches[i];
+      }
+    }
+    return undefined;
+  }
 }
 
 /**
@@ -103,151 +256,3 @@
   LONG_TAP: 'longtap',
   TWO_FINGER_TAP: 'twofingertap'
 };
-
-/**
- * Handles touch events.
- * The propagation of the |event| will be cancelled if the |callback| takes any
- * action, so as to avoid receiving mouse click events for the tapping and
- * processing them duplicatedly.
- * @param {!Event} event a touch event.
- * @param {number} index of the target item in the file list.
- * @param {function(!Event, number, !FileTapHandler.TapEvent)} callback called
- *     when a tap event is detected. Should return ture if it has taken any
- *     action, and false if it ignroes the event.
- * @return {boolean} true if a tap or longtap event was detected and the
- *     callback processed it. False otherwise.
- */
-FileTapHandler.prototype.handleTouchEvents = function(event, index, callback) {
-  switch (event.type) {
-    case 'touchstart':
-      // Only track the position of the single touch. However, we detect a
-      // two-finger tap for opening a context menu of the target.
-      if (event.touches.length == 2) {
-        this.isTwoFingerTap_ = true;
-        return false;
-      } else if (event.touches.length > 2) {
-        this.tapStarted_ = false;
-        return false;
-      }
-
-      // It's still possible there could be an active "touch" if the user is
-      // simultaneously using a mouse and a touch input.
-      // TODO(yamaguchi): add this after adding handler for touchcancel that
-      // can reset this.activeTouchId_ to undefined.
-      // if (this.activeTouchId_ !== undefined)
-      //   return;
-      var touch = event.targetTouches[0];
-      this.activeTouchId_ = touch.identifier;
-      this.startTouchX_ = this.lastTouchX_ = touch.clientX;
-      this.startTouchY_ = this.lastTouchY_ = touch.clientY;
-      this.totalMoveX_ = 0;
-      this.totalMoveY_ = 0;
-
-      this.tapStarted_ = true;
-      this.activeItemIndex_ = index;
-      this.isLongTap_ = false;
-      this.isTwoFingerTap_ = false;
-      this.hasLongPressProcessed_ = false;
-      this.longTapDetectorTimerId_ = setTimeout(() => {
-        this.longTapDetectorTimerId_ = -1;
-        if (!this.tapStarted_) {
-          return;
-        }
-        this.isLongTap_ = true;
-        if (callback(event, index, FileTapHandler.TapEvent.LONG_PRESS)) {
-          this.hasLongPressProcessed_ = true;
-        }
-      }, FileTapHandler.LONG_PRESS_THRESHOLD_MILLISECONDS);
-      break;
-
-    case 'touchmove':
-      if (this.activeTouchId_ === undefined) {
-        break;
-      }
-      var touch = this.findActiveTouch_(event.changedTouches);
-      if (!touch) {
-        break;
-      }
-
-      const clientX = touch.clientX;
-      const clientY = touch.clientY;
-
-      const moveX = this.lastTouchX_ - clientX;
-      const moveY = this.lastTouchY_ - clientY;
-      this.totalMoveX_ += Math.abs(moveX);
-      this.totalMoveY_ += Math.abs(moveY);
-      this.lastTouchX_ = clientX;
-      this.lastTouchY_ = clientY;
-
-      const couldBeTap =
-          this.totalMoveY_ <= FileTapHandler.MAX_TRACKING_FOR_TAP_ ||
-          this.totalMoveX_ <= FileTapHandler.MAX_TRACKING_FOR_TAP_;
-
-      if (!couldBeTap) {
-        // If the pointer is slided, it is a drag. It is no longer a tap.
-        this.tapStarted_ = false;
-      }
-      this.lastMoveX_ = moveX;
-      this.lastMoveY_ = moveY;
-      break;
-
-    case 'touchend':
-      if (!this.tapStarted_) {
-        break;
-      }
-      // Mark as no longer being touched.
-      // Two-finger tap event is issued when either of the 2 touch points is
-      // released. Stop tracking the tap to avoid issuing duplicate events.
-      this.tapStarted_ = false;
-      this.activeTouchId_ = undefined;
-      if (this.longTapDetectorTimerId_ != -1) {
-        clearTimeout(this.longTapDetectorTimerId_);
-        this.longTapDetectorTimerId_ = -1;
-      }
-      if (this.isLongTap_) {
-        // The item at the touch start position is treated as the target item,
-        // rather than the one at the touch end position. Note that |index| is
-        // the latter.
-        if (this.hasLongPressProcessed_ ||
-            callback(
-                event, this.activeItemIndex_,
-                FileTapHandler.TapEvent.LONG_TAP)) {
-          event.preventDefault();
-          return true;
-        }
-      } else {
-        // The item at the touch start position of the active touch is treated
-        // as the target item. In case of the two-finger tap, the first touch
-        // point points to the target.
-        if (callback(
-                event, this.activeItemIndex_,
-                this.isTwoFingerTap_ ? FileTapHandler.TapEvent.TWO_FINGER_TAP :
-                                       FileTapHandler.TapEvent.TAP)) {
-          event.preventDefault();
-          return true;
-        }
-      }
-      break;
-  }
-  return false;
-};
-
-/**
- * Given a list of Touches, find the one matching our activeTouch
- * identifier. Note that Chrome currently always uses 0 as the identifier.
- * In that case we'll end up always choosing the first element in the list.
- * @param {TouchList} touches The list of Touch objects to search.
- * @return {!Touch|undefined} The touch matching our active ID if any.
- * @private
- */
-FileTapHandler.prototype.findActiveTouch_ = function(touches) {
-  assert(this.activeTouchId_ !== undefined, 'Expecting an active touch');
-  // A TouchList isn't actually an array, so we shouldn't use
-  // Array.prototype.filter/some, etc.
-  for (let i = 0; i < touches.length; i++) {
-    if (touches[i].identifier == this.activeTouchId_) {
-      return touches[i];
-    }
-  }
-  return undefined;
-};
diff --git a/ui/file_manager/file_manager/foreground/js/ui/files_confirm_dialog.js b/ui/file_manager/file_manager/foreground/js/ui/files_confirm_dialog.js
index 35079bb..369c197 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/files_confirm_dialog.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/files_confirm_dialog.js
@@ -4,21 +4,14 @@
 
 /**
  * Confirm dialog.
- * @param {!HTMLElement} parentNode
- * @constructor
- * @extends {cr.ui.dialogs.ConfirmDialog}
  */
-const FilesConfirmDialog = function(parentNode) {
-  cr.ui.dialogs.ConfirmDialog.call(this, parentNode);
-};
-
-FilesConfirmDialog.prototype.__proto__ = cr.ui.dialogs.ConfirmDialog.prototype;
-
-/**
- * @protected
- * @override
- */
-FilesConfirmDialog.prototype.initDom = function() {
-  cr.ui.dialogs.ConfirmDialog.prototype.initDom.call(this);
-  this.frame.classList.add('files-confirm-dialog');
-};
+class FilesConfirmDialog extends cr.ui.dialogs.ConfirmDialog {
+  /**
+   * @protected
+   * @override
+   */
+  initDom() {
+    super.initDom();
+    this.frame.classList.add('files-confirm-dialog');
+  }
+}
diff --git a/ui/file_manager/file_manager/foreground/js/ui/files_menu.js b/ui/file_manager/file_manager/foreground/js/ui/files_menu.js
index c3952896..f8e69d9a 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/files_menu.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/files_menu.js
@@ -5,45 +5,46 @@
 cr.define('cr.ui', () => {
   /**
    * Menu item with ripple animation.
-   * @constructor
-   * @extends {cr.ui.MenuItem}
-   *
-   * TODO(mtomasz): Upstream to cr.ui.MenuItem.
    */
-  const FilesMenuItem = cr.ui.define(cr.ui.MenuItem);
+  class FilesMenuItem extends cr.ui.MenuItem {
+    constructor() {
+      super();
 
-  FilesMenuItem.prototype = {
-    __proto__: cr.ui.MenuItem.prototype,
+      /** @private {boolean} */
+      this.animating_ = false;
+
+      /** @private {(boolean|undefined)} */
+      this.hidden_ = undefined;
+
+      /** @private {?HTMLElement} */
+      this.label_ = null;
+
+      /** @private {?HTMLElement} */
+      this.iconStart_ = null;
+
+      /** @private {?HTMLElement} */
+      this.ripple_ = null;
+
+      throw new Error('Designed to decorate elements');
+    }
 
     /**
-     * @private {boolean}
+     * Decorates the element.
+     * @param {!Element} element Element to be decorated.
+     * @return {!cr.ui.FilesMenuItem} Decorated element.
      */
-    animating_: false,
-
-    /**
-     * @private {(boolean|undefined)}
-     */
-    hidden_: undefined,
-
-    /**
-     * @private {HTMLElement}
-     */
-    label_: null,
-
-    /**
-     * @private {HTMLElement}
-     */
-    iconStart_: null,
-
-    /**
-     * @private {HTMLElement}
-     */
-    ripple_: null,
-
+    static decorate(element) {
+      element.__proto__ = FilesMenuItem.prototype;
+      element = /** @type {!cr.ui.FilesMenuItem} */ (element);
+      element.decorate();
+      return element;
+    }
     /**
      * @override
      */
-    decorate: function() {
+    decorate() {
+      this.animating_ = false;
+
       // Custom menu item can have sophisticated content (elements).
       if (!this.children.length) {
         this.label_ =
@@ -65,14 +66,14 @@
       this.appendChild(this.ripple_);
 
       this.addEventListener('activate', this.onActivated_.bind(this));
-    },
+    }
 
     /**
      * Handles activate event.
      * @param {Event} event
      * @private
      */
-    onActivated_: function(event) {
+    onActivated_(event) {
       // Perform ripple animation if it's activated by keyboard.
       if (event.originalEvent instanceof KeyboardEvent) {
         this.ripple_.simulatedRipple();
@@ -105,7 +106,7 @@
       player.addEventListener(
           'finish',
           this.setMenuAsAnimating_.bind(this, menu, false /* not animating */));
-    },
+    }
 
     /**
      * Sets menu as animating.
@@ -113,7 +114,7 @@
      * @param {boolean} value True to set it as animating.
      * @private
      */
-    setMenuAsAnimating_: function(menu, value) {
+    setMenuAsAnimating_(menu, value) {
       menu.classList.toggle('animating', value);
 
       for (let i = 0; i < menu.menuItems.length; i++) {
@@ -126,14 +127,14 @@
       if (!value) {
         menu.classList.remove('toolbar-menu');
       }
-    },
+    }
 
     /**
      * Sets thie menu item as animating.
      * @param {boolean} value True to set this as animating.
      * @private
      */
-    setAnimating_: function(value) {
+    setAnimating_(value) {
       this.animating_ = value;
 
       if (this.animating_) {
@@ -145,7 +146,7 @@
         this.hidden = this.hidden_;
         this.hidden_ = undefined;
       }
-    },
+    }
 
     /**
      * @return {boolean}
@@ -157,7 +158,7 @@
 
       return Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'hidden')
           .get.call(this);
-    },
+    }
 
     /**
      * Overrides hidden property to block the change of hidden property while
@@ -172,28 +173,28 @@
 
       Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'hidden')
           .set.call(this, value);
-    },
+    }
 
     /**
      * @return {string}
      */
     get label() {
       return this.label_.textContent;
-    },
+    }
 
     /**
      * @param {string} value
      */
     set label(value) {
       this.label_.textContent = value;
-    },
+    }
 
     /**
      * @return {string}
      */
     get iconStartImage() {
       return this.iconStart_.style.backgroundImage;
-    },
+    }
 
     /**
      * @param {string} value
@@ -201,7 +202,7 @@
     set iconStartImage(value) {
       this.iconStart_.setAttribute('style', 'background-image: ' + value);
     }
-  };
+  }
 
   return {
     FilesMenuItem: FilesMenuItem,
diff --git a/ui/file_manager/file_manager/foreground/js/ui/gear_menu.js b/ui/file_manager/file_manager/foreground/js/ui/gear_menu.js
index 349be8c..61a7ab5 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/gear_menu.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/gear_menu.js
@@ -2,130 +2,130 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-/**
- * @param {!HTMLElement} element
- * @constructor
- * @struct
- */
-function GearMenu(element) {
+class GearMenu {
   /**
-   * @type {!HTMLMenuItemElement}
-   * @const
+   * @param {!HTMLElement} element
    */
-  this.syncButton = /** @type {!HTMLMenuItemElement} */
-      (queryRequiredElement('#gear-menu-drive-sync-settings', element));
+  constructor(element) {
+    /**
+     * @type {!HTMLMenuItemElement}
+     * @const
+     */
+    this.syncButton = /** @type {!HTMLMenuItemElement} */
+        (queryRequiredElement('#gear-menu-drive-sync-settings', element));
 
-  /**
-   * @type {!HTMLElement}
-   * @const
-   */
-  this.volumeSpaceInfo = queryRequiredElement('#volume-space-info', element);
+    /**
+     * @type {!HTMLElement}
+     * @const
+     */
+    this.volumeSpaceInfo = queryRequiredElement('#volume-space-info', element);
 
-  /**
-   * @type {!HTMLElement}
-   * @const
-   * @private
-   */
-  this.volumeSpaceInfoSeparator_ =
-      queryRequiredElement('#volume-space-info-separator', element);
+    /**
+     * @type {!HTMLElement}
+     * @const
+     * @private
+     */
+    this.volumeSpaceInfoSeparator_ =
+        queryRequiredElement('#volume-space-info-separator', element);
 
-  /**
-   * @type {!HTMLElement}
-   * @const
-   * @private
-   */
-  this.volumeSpaceInfoLabel_ =
-      queryRequiredElement('#volume-space-info-label', element);
+    /**
+     * @type {!HTMLElement}
+     * @const
+     * @private
+     */
+    this.volumeSpaceInfoLabel_ =
+        queryRequiredElement('#volume-space-info-label', element);
 
-  /**
-   * @type {!HTMLElement}
-   * @const
-   * @private
-   */
-  this.volumeSpaceInnerBar_ =
-      queryRequiredElement('#volume-space-info-bar', element);
+    /**
+     * @type {!HTMLElement}
+     * @const
+     * @private
+     */
+    this.volumeSpaceInnerBar_ =
+        queryRequiredElement('#volume-space-info-bar', element);
 
-  /**
-   * @type {!HTMLElement}
-   * @const
-   * @private
-   */
-  this.volumeSpaceOuterBar_ =
-      assertInstanceof(this.volumeSpaceInnerBar_.parentElement, HTMLElement);
+    /**
+     * @type {!HTMLElement}
+     * @const
+     * @private
+     */
+    this.volumeSpaceOuterBar_ =
+        assertInstanceof(this.volumeSpaceInnerBar_.parentElement, HTMLElement);
 
-  /**
-   * @type {!HTMLElement}
-   * @const
-   * @private
-   */
-  this.newServiceMenuItem_ =
-      queryRequiredElement('#gear-menu-newservice', element);
+    /**
+     * @type {!HTMLElement}
+     * @const
+     * @private
+     */
+    this.newServiceMenuItem_ =
+        queryRequiredElement('#gear-menu-newservice', element);
 
-  /**
-   * Volume space info.
-   * @type {Promise<chrome.fileManagerPrivate.MountPointSizeStats>}
-   * @private
-   */
-  this.spaceInfoPromise_ = null;
+    /**
+     * Volume space info.
+     * @type {Promise<chrome.fileManagerPrivate.MountPointSizeStats>}
+     * @private
+     */
+    this.spaceInfoPromise_ = null;
 
-  // Initialize attributes.
-  this.syncButton.checkable = true;
-}
-
-/**
- * @param {!string} commandId Element id of the command that new service menu
- *     should trigger.
- * @param {!string} label Text that should be displayed to user in the menu.
- */
-GearMenu.prototype.setNewServiceCommand = function(commandId, label) {
-  this.newServiceMenuItem_.textContent = label;
-  // Only change command if needed because it does some parsing when setting.
-  if ('#' + this.newServiceMenuItem_.command.id === commandId) {
-    return;
-  }
-  this.newServiceMenuItem_.command = commandId;
-};
-
-/**
- * @param {Promise<chrome.fileManagerPrivate.MountPointSizeStats>}
- * spaceInfoPromise Promise to be fulfilled with space info.
- * @param {boolean} showLoadingCaption Whether show loading caption or not.
- */
-GearMenu.prototype.setSpaceInfo = function(
-    spaceInfoPromise, showLoadingCaption) {
-  this.spaceInfoPromise_ = spaceInfoPromise;
-
-  if (!spaceInfoPromise || loadTimeData.getBoolean('HIDE_SPACE_INFO')) {
-    this.volumeSpaceInfo.hidden = true;
-    this.volumeSpaceInfoSeparator_.hidden = true;
-    return;
+    // Initialize attributes.
+    this.syncButton.checkable = true;
   }
 
-  this.volumeSpaceInfo.hidden = false;
-  this.volumeSpaceInfoSeparator_.hidden = false;
-  this.volumeSpaceInnerBar_.setAttribute('pending', '');
-  if (showLoadingCaption) {
-    this.volumeSpaceInfoLabel_.innerText = str('WAITING_FOR_SPACE_INFO');
-    this.volumeSpaceInnerBar_.style.width = '100%';
-  }
-
-  spaceInfoPromise.then(spaceInfo => {
-    if (this.spaceInfoPromise_ != spaceInfoPromise) {
+  /**
+   * @param {!string} commandId Element id of the command that new service menu
+   *     should trigger.
+   * @param {!string} label Text that should be displayed to user in the menu.
+   */
+  setNewServiceCommand(commandId, label) {
+    this.newServiceMenuItem_.textContent = label;
+    // Only change command if needed because it does some parsing when setting.
+    if ('#' + this.newServiceMenuItem_.command.id === commandId) {
       return;
     }
-    this.volumeSpaceInnerBar_.removeAttribute('pending');
-    if (spaceInfo) {
-      const sizeStr = util.bytesToString(spaceInfo.remainingSize);
-      this.volumeSpaceInfoLabel_.textContent = strf('SPACE_AVAILABLE', sizeStr);
+    this.newServiceMenuItem_.command = commandId;
+  }
 
-      const usedSpace = spaceInfo.totalSize - spaceInfo.remainingSize;
-      this.volumeSpaceInnerBar_.style.width =
-          (100 * usedSpace / spaceInfo.totalSize) + '%';
+  /**
+   * @param {Promise<chrome.fileManagerPrivate.MountPointSizeStats>}
+   * spaceInfoPromise Promise to be fulfilled with space info.
+   * @param {boolean} showLoadingCaption Whether show loading caption or not.
+   */
+  setSpaceInfo(spaceInfoPromise, showLoadingCaption) {
+    this.spaceInfoPromise_ = spaceInfoPromise;
 
-      this.volumeSpaceOuterBar_.hidden = false;
-    } else {
-      this.volumeSpaceOuterBar_.hidden = true;
-      this.volumeSpaceInfoLabel_.textContent = str('FAILED_SPACE_INFO');
+    if (!spaceInfoPromise || loadTimeData.getBoolean('HIDE_SPACE_INFO')) {
+      this.volumeSpaceInfo.hidden = true;
+      this.volumeSpaceInfoSeparator_.hidden = true;
+      return;
     }
-  });
-};
+
+    this.volumeSpaceInfo.hidden = false;
+    this.volumeSpaceInfoSeparator_.hidden = false;
+    this.volumeSpaceInnerBar_.setAttribute('pending', '');
+    if (showLoadingCaption) {
+      this.volumeSpaceInfoLabel_.innerText = str('WAITING_FOR_SPACE_INFO');
+      this.volumeSpaceInnerBar_.style.width = '100%';
+    }
+
+    spaceInfoPromise.then(spaceInfo => {
+      if (this.spaceInfoPromise_ != spaceInfoPromise) {
+        return;
+      }
+      this.volumeSpaceInnerBar_.removeAttribute('pending');
+      if (spaceInfo) {
+        const sizeStr = util.bytesToString(spaceInfo.remainingSize);
+        this.volumeSpaceInfoLabel_.textContent =
+            strf('SPACE_AVAILABLE', sizeStr);
+
+        const usedSpace = spaceInfo.totalSize - spaceInfo.remainingSize;
+        this.volumeSpaceInnerBar_.style.width =
+            (100 * usedSpace / spaceInfo.totalSize) + '%';
+
+        this.volumeSpaceOuterBar_.hidden = false;
+      } else {
+        this.volumeSpaceOuterBar_.hidden = true;
+        this.volumeSpaceInfoLabel_.textContent = str('FAILED_SPACE_INFO');
+      }
+    });
+  }
+}
diff --git a/ui/file_manager/file_manager/foreground/js/ui/list_container.js b/ui/file_manager/file_manager/foreground/js/ui/list_container.js
index f2eb1d3..f232d4b 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/list_container.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/list_container.js
@@ -2,149 +2,374 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-/**
- * @constructor
- * @struct
- */
-function TextSearchState() {
-  /**
-   * @type {string}
-   */
-  this.text = '';
+class TextSearchState {
+  constructor() {
+    /** @public {string} */
+    this.text = '';
 
-  /**
-   * @type {!Date}
-   */
-  this.date = new Date();
+    /** @public {!Date} */
+    this.date = new Date();
+  }
 }
 
 /**
  * List container for the file table and the grid view.
- * @param {!HTMLElement} element Element of the container.
- * @param {!FileTable} table File table.
- * @param {!FileGrid} grid File grid.
- * @constructor
- * @struct
  */
-function ListContainer(element, table, grid) {
+class ListContainer {
   /**
-   * The container element of the file list.
-   * @type {!HTMLElement}
-   * @const
+   * @param {!HTMLElement} element Element of the container.
+   * @param {!FileTable} table File table.
+   * @param {!FileGrid} grid File grid.
    */
-  this.element = element;
+  constructor(element, table, grid) {
+    /**
+     * The container element of the file list.
+     * @type {!HTMLElement}
+     * @const
+     */
+    this.element = element;
+
+    /**
+     * The file table.
+     * @type {!FileTable}
+     * @const
+     */
+    this.table = table;
+
+    /**
+     * The file grid.
+     * @type {!FileGrid}
+     * @const
+     */
+    this.grid = grid;
+
+    /**
+     * Current file list.
+     * @type {ListContainer.ListType}
+     */
+    this.currentListType = ListContainer.ListType.UNINITIALIZED;
+
+    /**
+     * The input element to rename entry.
+     * @type {!HTMLInputElement}
+     * @const
+     */
+    this.renameInput =
+        assertInstanceof(document.createElement('input'), HTMLInputElement);
+    this.renameInput.className = 'rename entry-name';
+
+    /**
+     * Spinner on file list which is shown while loading.
+     * @type {!HTMLElement}
+     * @const
+     */
+    this.spinner = queryRequiredElement('.loading-indicator', element);
+
+    /**
+     * @type {FileListModel}
+     */
+    this.dataModel = null;
+
+    /**
+     * @type {ListThumbnailLoader}
+     */
+    this.listThumbnailLoader = null;
+
+    /**
+     * @type {cr.ui.ListSelectionModel|cr.ui.ListSingleSelectionModel}
+     */
+    this.selectionModel = null;
+
+    /**
+     * Data model which is used as a placefolder in inactive file list.
+     * @type {FileListModel}
+     */
+    this.emptyDataModel = null;
+
+    /**
+     * Selection model which is used as a placefolder in inactive file list.
+     * @type {!cr.ui.ListSelectionModel}
+     * @const
+     * @private
+     */
+    this.emptySelectionModel_ = new cr.ui.ListSelectionModel();
+
+    /**
+     * @type {!TextSearchState}
+     * @const
+     */
+    this.textSearchState = new TextSearchState();
+
+    /**
+     * Whtehter to allow or cancel a context menu event.
+     * @type {boolean}
+     * @private
+     */
+    this.allowContextMenuByTouch_ = false;
+
+    // Overriding the default role 'list' to 'listbox' for better accessibility
+    // on ChromeOS.
+    this.table.list.setAttribute('role', 'listbox');
+    this.table.list.id = 'file-list';
+    this.grid.setAttribute('role', 'listbox');
+    this.grid.id = 'file-list';
+    this.element.addEventListener('keydown', this.onKeyDown_.bind(this));
+    this.element.addEventListener('keypress', this.onKeyPress_.bind(this));
+    this.element.addEventListener('mousemove', this.onMouseMove_.bind(this));
+    this.element.addEventListener(
+        'contextmenu', this.onContextMenu_.bind(this), /* useCapture */ true);
+
+    this.element.addEventListener('touchstart', function(e) {
+      if (e.touches.length > 1) {
+        this.allowContextMenuByTouch_ = true;
+      }
+    }.bind(this), {passive: true});
+    this.element.addEventListener('touchend', function(e) {
+      if (e.touches.length == 0) {
+        // contextmenu event will be sent right after touchend.
+        setTimeout(function() {
+          this.allowContextMenuByTouch_ = false;
+        }.bind(this));
+      }
+    }.bind(this));
+    this.element.addEventListener('contextmenu', function(e) {
+      // Block context menu triggered by touch event unless it is right after
+      // multi-touch, or we are currently selecting a file.
+      if (this.currentList.selectedItem && !this.allowContextMenuByTouch_ &&
+          e.sourceCapabilities && e.sourceCapabilities.firesTouchEvents) {
+        e.stopPropagation();
+      }
+    }.bind(this), true);
+  }
 
   /**
-   * The file table.
-   * @type {!FileTable}
-   * @const
+   * @return {!FileTable|!FileGrid}
    */
-  this.table = table;
+  get currentView() {
+    switch (this.currentListType) {
+      case ListContainer.ListType.DETAIL:
+        return this.table;
+      case ListContainer.ListType.THUMBNAIL:
+        return this.grid;
+    }
+    assertNotReached();
+  }
 
   /**
-   * The file grid.
-   * @type {!FileGrid}
-   * @const
+   * @return {!cr.ui.List}
    */
-  this.grid = grid;
+  get currentList() {
+    switch (this.currentListType) {
+      case ListContainer.ListType.DETAIL:
+        return this.table.list;
+      case ListContainer.ListType.THUMBNAIL:
+        return this.grid;
+    }
+    assertNotReached();
+  }
 
   /**
-   * Current file list.
-   * @type {ListContainer.ListType}
+   * Notifies beginning of batch update to the UI.
    */
-  this.currentListType = ListContainer.ListType.UNINITIALIZED;
+  startBatchUpdates() {
+    this.table.startBatchUpdates();
+    this.grid.startBatchUpdates();
+  }
 
   /**
-   * The input element to rename entry.
-   * @type {!HTMLInputElement}
-   * @const
+   * Notifies end of batch update to the UI.
    */
-  this.renameInput =
-      assertInstanceof(document.createElement('input'), HTMLInputElement);
-  this.renameInput.className = 'rename entry-name';
+  endBatchUpdates() {
+    this.table.endBatchUpdates();
+    this.grid.endBatchUpdates();
+  }
 
   /**
-   * Spinner on file list which is shown while loading.
-   * @type {!HTMLElement}
-   * @const
+   * Sets the current list type.
+   * @param {ListContainer.ListType} listType New list type.
    */
-  this.spinner = queryRequiredElement('.loading-indicator', element);
+  setCurrentListType(listType) {
+    assert(this.dataModel);
+    assert(this.selectionModel);
+
+    this.startBatchUpdates();
+    this.currentListType = listType;
+
+    this.element.classList.toggle(
+        'list-view', listType === ListContainer.ListType.DETAIL);
+    this.element.classList.toggle(
+        'thumbnail-view', listType === ListContainer.ListType.THUMBNAIL);
+
+    // TODO(dzvorygin): style.display and dataModel setting order shouldn't
+    // cause any UI bugs. Currently, the only right way is first to set display
+    // style and only then set dataModel.
+    // Always sharing the data model between the detail/thumb views confuses
+    // them.  Instead we maintain this bogus data model, and hook it up to the
+    // view that is not in use.
+    switch (listType) {
+      case ListContainer.ListType.DETAIL:
+        this.table.dataModel = this.dataModel;
+        this.table.setListThumbnailLoader(this.listThumbnailLoader);
+        this.table.selectionModel = this.selectionModel;
+        this.table.hidden = false;
+        this.grid.hidden = true;
+        this.grid.selectionModel = this.emptySelectionModel_;
+        this.grid.setListThumbnailLoader(null);
+        this.grid.dataModel = this.emptyDataModel;
+        break;
+
+      case ListContainer.ListType.THUMBNAIL:
+        this.grid.dataModel = this.dataModel;
+        this.grid.setListThumbnailLoader(this.listThumbnailLoader);
+        this.grid.selectionModel = this.selectionModel;
+        this.grid.hidden = false;
+        this.table.hidden = true;
+        this.table.selectionModel = this.emptySelectionModel_;
+        this.table.setListThumbnailLoader(null);
+        this.table.dataModel = this.emptyDataModel;
+        break;
+
+      default:
+        assertNotReached();
+        break;
+    }
+    this.endBatchUpdates();
+  }
 
   /**
-   * @type {FileListModel}
+   * Clears hover highlighting in the list container until next mouse move.
    */
-  this.dataModel = null;
+  clearHover() {
+    this.element.classList.add('nohover');
+  }
 
   /**
-   * @type {ListThumbnailLoader}
+   * Finds list item element from the ancestor node.
+   * @param {!HTMLElement} node
+   * @return {cr.ui.ListItem}
    */
-  this.listThumbnailLoader = null;
+  findListItemForNode(node) {
+    const item = this.currentList.getListItemAncestor(node);
+    // TODO(serya): list should check that.
+    return item && this.currentList.isItem(item) ?
+        assertInstanceof(item, cr.ui.ListItem) :
+        null;
+  }
 
   /**
-   * @type {cr.ui.ListSelectionModel|cr.ui.ListSingleSelectionModel}
+   * Focuses the active file list in the list container.
    */
-  this.selectionModel = null;
+  focus() {
+    switch (this.currentListType) {
+      case ListContainer.ListType.DETAIL:
+        this.table.list.focus();
+        break;
+      case ListContainer.ListType.THUMBNAIL:
+        this.grid.focus();
+        break;
+      default:
+        assertNotReached();
+        break;
+    }
+  }
 
   /**
-   * Data model which is used as a placefolder in inactive file list.
-   * @type {FileListModel}
-   */
-  this.emptyDataModel = null;
-
-  /**
-   * Selection model which is used as a placefolder in inactive file list.
-   * @type {!cr.ui.ListSelectionModel}
-   * @const
+   * Check if our context menu has any items that can be activated
+   * @return {boolean} True if the menu has action item. Otherwise, false.
    * @private
    */
-  this.emptySelectionModel_ = new cr.ui.ListSelectionModel();
+  contextMenuHasActions_() {
+    const menu = document.querySelector('#file-context-menu');
+    const menuItems = menu.querySelectorAll('cr-menu-item, hr');
+    for (const item of menuItems) {
+      if (!item.hasAttribute('hidden') && !item.hasAttribute('disabled') &&
+          (window.getComputedStyle(item).display != 'none')) {
+        return true;
+      }
+    }
+    return false;
+  }
 
   /**
-   * @type {!TextSearchState}
-   * @const
-   */
-  this.textSearchState = new TextSearchState();
-
-  /**
-   * Whtehter to allow or cancel a context menu event.
-   * @type {boolean}
+   * Contextmenu event handler to prevent change of focus on long-tapping the
+   * header of the file list.
+   * @param {!Event} e Menu event.
    * @private
    */
-  this.allowContextMenuByTouch_ = false;
-
-  // Overriding the default role 'list' to 'listbox' for better accessibility
-  // on ChromeOS.
-  this.table.list.setAttribute('role', 'listbox');
-  this.table.list.id = 'file-list';
-  this.grid.setAttribute('role', 'listbox');
-  this.grid.id = 'file-list';
-  this.element.addEventListener('keydown', this.onKeyDown_.bind(this));
-  this.element.addEventListener('keypress', this.onKeyPress_.bind(this));
-  this.element.addEventListener('mousemove', this.onMouseMove_.bind(this));
-  this.element.addEventListener(
-      'contextmenu', this.onContextMenu_.bind(this), /* useCapture */ true);
-
-  this.element.addEventListener('touchstart', function(e) {
-    if (e.touches.length > 1) {
-      this.allowContextMenuByTouch_ = true;
-    }
-  }.bind(this), {passive: true});
-  this.element.addEventListener('touchend', function(e) {
-    if (e.touches.length == 0) {
-      // contextmenu event will be sent right after touchend.
-      setTimeout(function() {
-        this.allowContextMenuByTouch_ = false;
-      }.bind(this));
-    }
-  }.bind(this));
-  this.element.addEventListener('contextmenu', function(e) {
-    // Block context menu triggered by touch event unless it is right after
-    // multi-touch, or we are currently selecting a file.
-    if (this.currentList.selectedItem && !this.allowContextMenuByTouch_ &&
-        e.sourceCapabilities && e.sourceCapabilities.firesTouchEvents) {
+  onContextMenu_(e) {
+    // Inhibit the context menu being shown if it only hosts
+    // disabled items https://crbug.com/917975
+    if (this.contextMenuHasActions_() === false) {
+      e.preventDefault();
       e.stopPropagation();
+      return;
     }
-  }.bind(this), true);
+    if (!this.allowContextMenuByTouch_ && e.sourceCapabilities &&
+        e.sourceCapabilities.firesTouchEvents) {
+      this.focus();
+    }
+  }
+
+  /**
+   * KeyDown event handler for the div#list-container element.
+   * @param {!Event} event Key event.
+   * @private
+   */
+  onKeyDown_(event) {
+    // Ignore keydown handler in the rename input box.
+    if (event.srcElement.tagName == 'INPUT') {
+      event.stopImmediatePropagation();
+      return;
+    }
+
+    switch (event.key) {
+      case 'Home':
+      case 'End':
+      case 'ArrowUp':
+      case 'ArrowDown':
+      case 'ArrowLeft':
+      case 'ArrowRight':
+        // When navigating with keyboard we hide the distracting mouse hover
+        // highlighting until the user moves the mouse again.
+        this.clearHover();
+        break;
+    }
+  }
+
+  /**
+   * KeyPress event handler for the div#list-container element.
+   * @param {!Event} event Key event.
+   * @private
+   */
+  onKeyPress_(event) {
+    // Ignore keypress handler in the rename input box.
+    if (event.srcElement.tagName == 'INPUT' || event.ctrlKey || event.metaKey ||
+        event.altKey) {
+      event.stopImmediatePropagation();
+      return;
+    }
+
+    const now = new Date();
+    const character = String.fromCharCode(event.charCode).toLowerCase();
+    const text =
+        now - this.textSearchState.date > 1000 ? '' : this.textSearchState.text;
+    this.textSearchState.text = text + character;
+    this.textSearchState.date = now;
+
+    if (this.textSearchState.text) {
+      cr.dispatchSimpleEvent(this.element, ListContainer.EventType.TEXT_SEARCH);
+    }
+  }
+
+  /**
+   * Mousemove event handler for the div#list-container element.
+   * @param {Event} event Mouse event.
+   * @private
+   */
+  onMouseMove_(event) {
+    // The user grabbed the mouse, restore the hover highlighting.
+    this.element.classList.remove('nohover');
+  }
 }
 
 /**
@@ -183,234 +408,3 @@
     Object.keys(ListContainer.ListType).length ===
         ListContainer.ListTypesForUMA.length,
     'Members in ListTypesForUMA do not match those in ListType.');
-
-ListContainer.prototype = /** @struct */ {
-  /**
-   * @return {!FileTable|!FileGrid}
-   */
-  get currentView() {
-    switch (this.currentListType) {
-      case ListContainer.ListType.DETAIL:
-        return this.table;
-      case ListContainer.ListType.THUMBNAIL:
-        return this.grid;
-    }
-    assertNotReached();
-  },
-
-  /**
-   * @return {!cr.ui.List}
-   */
-  get currentList() {
-    switch (this.currentListType) {
-      case ListContainer.ListType.DETAIL:
-        return this.table.list;
-      case ListContainer.ListType.THUMBNAIL:
-        return this.grid;
-    }
-    assertNotReached();
-  }
-};
-
-/**
- * Notifies begginig of batch update to the UI.
- */
-ListContainer.prototype.startBatchUpdates = function() {
-  this.table.startBatchUpdates();
-  this.grid.startBatchUpdates();
-};
-
-/**
- * Notifies end of batch update to the UI.
- */
-ListContainer.prototype.endBatchUpdates = function() {
-  this.table.endBatchUpdates();
-  this.grid.endBatchUpdates();
-};
-
-/**
- * Sets the current list type.
- * @param {ListContainer.ListType} listType New list type.
- */
-ListContainer.prototype.setCurrentListType = function(listType) {
-  assert(this.dataModel);
-  assert(this.selectionModel);
-
-  this.startBatchUpdates();
-  this.currentListType = listType;
-
-  this.element.classList.toggle(
-      'list-view', listType === ListContainer.ListType.DETAIL);
-  this.element.classList.toggle(
-      'thumbnail-view', listType === ListContainer.ListType.THUMBNAIL);
-
-  // TODO(dzvorygin): style.display and dataModel setting order shouldn't
-  // cause any UI bugs. Currently, the only right way is first to set display
-  // style and only then set dataModel.
-  // Always sharing the data model between the detail/thumb views confuses
-  // them.  Instead we maintain this bogus data model, and hook it up to the
-  // view that is not in use.
-  switch (listType) {
-    case ListContainer.ListType.DETAIL:
-      this.table.dataModel = this.dataModel;
-      this.table.setListThumbnailLoader(this.listThumbnailLoader);
-      this.table.selectionModel = this.selectionModel;
-      this.table.hidden = false;
-      this.grid.hidden = true;
-      this.grid.selectionModel = this.emptySelectionModel_;
-      this.grid.setListThumbnailLoader(null);
-      this.grid.dataModel = this.emptyDataModel;
-      break;
-
-    case ListContainer.ListType.THUMBNAIL:
-      this.grid.dataModel = this.dataModel;
-      this.grid.setListThumbnailLoader(this.listThumbnailLoader);
-      this.grid.selectionModel = this.selectionModel;
-      this.grid.hidden = false;
-      this.table.hidden = true;
-      this.table.selectionModel = this.emptySelectionModel_;
-      this.table.setListThumbnailLoader(null);
-      this.table.dataModel = this.emptyDataModel;
-      break;
-
-    default:
-      assertNotReached();
-      break;
-  }
-  this.endBatchUpdates();
-};
-
-/**
- * Clears hover highlighting in the list container until next mouse move.
- */
-ListContainer.prototype.clearHover = function() {
-  this.element.classList.add('nohover');
-};
-
-/**
- * Finds list item element from the ancestor node.
- * @param {!HTMLElement} node
- * @return {cr.ui.ListItem}
- */
-ListContainer.prototype.findListItemForNode = function(node) {
-  const item = this.currentList.getListItemAncestor(node);
-  // TODO(serya): list should check that.
-  return item && this.currentList.isItem(item) ?
-      assertInstanceof(item, cr.ui.ListItem) :
-      null;
-};
-
-/**
- * Focuses the active file list in the list container.
- */
-ListContainer.prototype.focus = function() {
-  switch (this.currentListType) {
-    case ListContainer.ListType.DETAIL:
-      this.table.list.focus();
-      break;
-    case ListContainer.ListType.THUMBNAIL:
-      this.grid.focus();
-      break;
-    default:
-      assertNotReached();
-      break;
-  }
-};
-
-/**
- * Check if our context menu has any items that can be activated
- * @return {boolean} True if the menu has action item. Otherwise, false.
- * @private
- */
-ListContainer.prototype.contextMenuHasActions_ = () => {
-  const menu = document.querySelector('#file-context-menu');
-  const menuItems = menu.querySelectorAll('cr-menu-item, hr');
-  for (const item of menuItems) {
-    if (!item.hasAttribute('hidden') && !item.hasAttribute('disabled') &&
-        (window.getComputedStyle(item).display != 'none')) {
-      return true;
-    }
-  }
-  return false;
-};
-
-/**
- * Contextmenu event handler to prevent change of focus on long-tapping the
- * header of the file list.
- * @param {!Event} e Menu event.
- * @private
- */
-ListContainer.prototype.onContextMenu_ = function(e) {
-  // Inhibit the context menu being shown if it only hosts
-  // disabled items https://crbug.com/917975
-  if (this.contextMenuHasActions_() === false) {
-    e.preventDefault();
-    e.stopPropagation();
-    return;
-  }
-  if (!this.allowContextMenuByTouch_ && e.sourceCapabilities &&
-      e.sourceCapabilities.firesTouchEvents) {
-    this.focus();
-  }
-};
-
-/**
- * KeyDown event handler for the div#list-container element.
- * @param {!Event} event Key event.
- * @private
- */
-ListContainer.prototype.onKeyDown_ = function(event) {
-  // Ignore keydown handler in the rename input box.
-  if (event.srcElement.tagName == 'INPUT') {
-    event.stopImmediatePropagation();
-    return;
-  }
-
-  switch (event.key) {
-    case 'Home':
-    case 'End':
-    case 'ArrowUp':
-    case 'ArrowDown':
-    case 'ArrowLeft':
-    case 'ArrowRight':
-      // When navigating with keyboard we hide the distracting mouse hover
-      // highlighting until the user moves the mouse again.
-      this.clearHover();
-      break;
-  }
-};
-
-/**
- * KeyPress event handler for the div#list-container element.
- * @param {!Event} event Key event.
- * @private
- */
-ListContainer.prototype.onKeyPress_ = function(event) {
-  // Ignore keypress handler in the rename input box.
-  if (event.srcElement.tagName == 'INPUT' || event.ctrlKey || event.metaKey ||
-      event.altKey) {
-    event.stopImmediatePropagation();
-    return;
-  }
-
-  const now = new Date();
-  const character = String.fromCharCode(event.charCode).toLowerCase();
-  const text =
-      now - this.textSearchState.date > 1000 ? '' : this.textSearchState.text;
-  this.textSearchState.text = text + character;
-  this.textSearchState.date = now;
-
-  if (this.textSearchState.text) {
-    cr.dispatchSimpleEvent(this.element, ListContainer.EventType.TEXT_SEARCH);
-  }
-};
-
-/**
- * Mousemove event handler for the div#list-container element.
- * @param {Event} event Mouse event.
- * @private
- */
-ListContainer.prototype.onMouseMove_ = function(event) {
-  // The user grabbed the mouse, restore the hover highlighting.
-  this.element.classList.remove('nohover');
-};
diff --git a/ui/file_manager/file_manager/foreground/js/ui/multi_menu.js b/ui/file_manager/file_manager/foreground/js/ui/multi_menu.js
index 770a4b3f..e06d978 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/multi_menu.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/multi_menu.js
@@ -6,30 +6,81 @@
 
 cr.define('cr.ui', () => {
   /** @const */
-  const Menu = cr.ui.Menu;
-
-  /** @const */
   const HideType = cr.ui.HideType;
 
-  /** @const */
-  const positionPopupAroundElement = cr.ui.positionPopupAroundElement;
-
   /**
    * Creates a new menu button element.
-   * @param {Object=} opt_propertyBag Optional properties.
-   * @constructor
    * @extends {HTMLButtonElement}
    * @implements {EventListener}
    */
-  const MultiMenuButton = cr.ui.define('button');
+  class MultiMenuButton {
+    constructor() {
+      /**
+       * Whether to show the menu on press of the Up or Down arrow keys.
+       * @private {boolean}
+       */
+      this.respondToArrowKeys = true;
 
-  MultiMenuButton.prototype = {
-    __proto__: HTMLButtonElement.prototype,
+      /**
+       * Whether a sub-menu is positioned on the left of its parent.
+       * @private {boolean|null} Used to direct the arrow key navigation.
+       */
+      this.subMenuOnLeft = null;
+
+      /**
+       * Property that hosts sub-menus for filling with overflow items.
+       * @public {cr.ui.Menu|null} Used for menu-items that overflow parent
+       * menu.
+       */
+      this.overflow = null;
+
+      /**
+       * Reference to the menu that the user is currently navigating.
+       * @private {cr.ui.Menu|null} Used to route events to the correct menu.
+       */
+      this.currentMenu = null;
+
+      /**
+       * Padding used when restricting menu height when the window is too small
+       * to show the entire menu.
+       * @private {number}
+       */
+      this.menuEndGap_ = 0;  // padding on cr.menu + 2px
+
+      /** @private {boolean} */
+      this.invertLeftRight = false;
+
+      /** @private {cr.ui.AnchorType} */
+      this.anchorType = cr.ui.AnchorType.BELOW;
+
+      /** @private {?Date|?number} */
+      this.hideTimestamp_ = null;
+
+      /** @private {?EventTracker} */
+      this.showingEvents_ = null;
+
+      /** @private {?cr.ui.Menu} */
+      this.menu_ = null;
+
+      throw new Error('Designed to decorate elements');
+    }
+
+    /**
+     * Decorates the element.
+     * @param {!Element} element Element to be decorated.
+     * @return {!cr.ui.MultiMenuButton} Decorated element.
+     */
+    static decorate(element) {
+      element.__proto__ = MultiMenuButton.prototype;
+      element = /** @type {!cr.ui.MultiMenuButton} */ (element);
+      element.decorate();
+      return element;
+    }
 
     /**
      * Initializes the menu button.
      */
-    decorate: function() {
+    decorate() {
       // Listen to the touch events on the document so that we can handle it
       // before cancelled by other UI components.
       this.ownerDocument.addEventListener('touchstart', this, {passive: true});
@@ -38,6 +89,9 @@
       this.addEventListener('dblclick', this);
       this.addEventListener('blur', this);
 
+      this.menuEndGap_ = 18;  // padding on cr.menu + 2px
+      this.respondToArrowKeys = true;
+
       // Adding the 'custom-appearance' class prevents widgets.css from
       // changing the appearance of this element.
       this.classList.add('custom-appearance');
@@ -54,7 +108,7 @@
 
       this.anchorType = cr.ui.AnchorType.BELOW;
       this.invertLeftRight = false;
-    },
+    }
 
     /**
      * The menu associated with the menu button.
@@ -62,11 +116,11 @@
      */
     get menu() {
       return this.menu_;
-    },
+    }
     set menu(menu) {
       if (typeof menu == 'string' && menu[0] == '#') {
         menu = assert(this.ownerDocument.getElementById(menu.slice(1)));
-        cr.ui.decorate(menu, Menu);
+        cr.ui.decorate(menu, cr.ui.Menu);
       }
 
       this.menu_ = menu;
@@ -75,41 +129,7 @@
           this.setAttribute('menu', '#' + menu.id);
         }
       }
-    },
-
-    /**
-     * Whether to show the menu on press of the Up or Down arrow keys.
-     */
-    respondToArrowKeys: true,
-
-    /**
-     * Whether a sub-menu is positioned on the left of its parent.
-     * @type {boolean|null} Used to direct the arrow key navigation.
-     * @private
-     */
-    subMenuOnLeft: null,
-
-    /**
-     * Property that hosts sub-menus for filling with overflow items.
-     * @type {cr.ui.Menu|null} Used for menu-items that overflow parent menu.
-     * @public
-     */
-    overflow: null,
-
-    /**
-     * Reference to the menu that the user is currently navigating.
-     * @type {cr.ui.Menu|null} Used to route events to the correct menu.
-     * @private
-     */
-    currentMenu: null,
-
-    /**
-     * Padding used when restricting menu height when the window is too small
-     * to show the entire menu.
-     * @type {number}
-     * @private
-     */
-    menuEndGap_: 18,  // padding on cr.menu + 2px
+    }
 
     /**
      * Checks if the menu(s) should be closed based on the target of a mouse
@@ -118,7 +138,7 @@
      * @return {boolean}
      * @private
      */
-    shouldDismissMenu_: function(e) {
+    shouldDismissMenu_(e) {
       // All menus are dismissed when clicking outside the menus. If we are
       // showing a sub-menu, we need to detect if the target is the top
       // level menu, or in the sub menu when the sub menu is being shown.
@@ -127,14 +147,14 @@
       return e.target instanceof Node && !this.contains(e.target) &&
           !this.menu.contains(e.target) &&
           !(this.menu.subMenu && this.menu.subMenu.contains(e.target));
-    },
+    }
 
     /**
      * Position the sub menu adjacent to the cr-menu-item that triggered it.
      * @param {cr.ui.MenuItem} item The menu item to position against.
      * @param {cr.ui.Menu} subMenu The child (sub) menu to be positioned.
      */
-    positionSubMenu_: function(item, subMenu) {
+    positionSubMenu_(item, subMenu) {
       // The sub-menu needs to sit aligned to the top and side of
       // the menu-item passed in. It also needs to fit inside the viewport
       const itemRect = item.getBoundingClientRect();
@@ -163,14 +183,14 @@
       } else {
         style.overflowY = 'auto';
       }
-    },
+    }
 
     /**
      * Get the subMenu hanging off a menu-item if it exists.
      * @param {cr.ui.MenuItem} item The menu item.
      * @return {cr.ui.Menu|null}
      */
-    getSubMenuFromItem: function(item) {
+    getSubMenuFromItem(item) {
       if (!item) {
         return null;
       }
@@ -180,12 +200,12 @@
       }
       return /** @type {!cr.ui.Menu|null} */ (
           document.querySelector(subMenuId));
-    },
+    }
 
     /**
      * Display any sub-menu hanging off the current selection.
      */
-    showSubMenu: function() {
+    showSubMenu() {
       if (!this.isMenuShown()) {
         return;
       }
@@ -199,13 +219,13 @@
         subMenu.parentMenuItem = item;
         this.moveSelectionToSubMenu_(subMenu);
       }
-    },
+    }
 
     /**
      * Find any sub-menu hanging off the event target and show/hide it.
      * @param {Event} e The event object.
      */
-    manageSubMenu: function(e) {
+    manageSubMenu(e) {
       const item = this.menu.findMenuItem_(e.target);
       const subMenu = this.getSubMenuFromItem(item);
       if (!subMenu) {
@@ -232,7 +252,7 @@
           this.currentMenu = this.menu;
           break;
       }
-    },
+    }
 
     /**
      * Change the selection from the top level menu to the first item
@@ -240,31 +260,31 @@
      * @param {cr.ui.Menu} subMenu sub-menu that should take selection.
      * @private
      */
-    moveSelectionToSubMenu_: function(subMenu) {
+    moveSelectionToSubMenu_(subMenu) {
       this.menu.selectedItem = null;
       this.currentMenu = subMenu;
       subMenu.selectedIndex = 0;
       subMenu.focusSelectedItem();
-    },
+    }
 
     /**
      * Change the selection from the sub menu to the top level menu.
      * @param {cr.ui.Menu} subMenu sub-menu that should lose selection.
      * @private
      */
-    moveSelectionToTopMenu_: function(subMenu) {
+    moveSelectionToTopMenu_(subMenu) {
       subMenu.selectedItem = null;
       this.currentMenu = this.menu;
       this.menu.selectedItem = subMenu.parentMenuItem;
       this.menu.focusSelectedItem();
-    },
+    }
 
     /**
      * Do we have a menu visible to handle a keyboard event.
      * @return {boolean} True if there's a visible menu.
      * @private
      */
-    hasVisibleMenu_: function() {
+    hasVisibleMenu_() {
       if (this.currentMenu == this.menu && this.isMenuShown()) {
         return true;
       } else if (this.currentMenu) {
@@ -273,13 +293,13 @@
         }
       }
       return false;
-    },
+    }
 
     /**
      * Handles event callbacks.
      * @param {Event} e The event object.
      */
-    handleEvent: function(e) {
+    handleEvent(e) {
       if (!this.menu) {
         return;
       }
@@ -413,12 +433,12 @@
           this.manageSubMenu(e);
           break;
       }
-    },
+    }
 
     /**
      * Add event listeners to any sub menus.
      */
-    addSubMenuListeners: function() {
+    addSubMenuListeners() {
       const items = this.menu.querySelectorAll('cr-menu-item[sub-menu]');
       items.forEach((menuItem) => {
         const subMenuId = menuItem.getAttribute('sub-menu');
@@ -429,7 +449,7 @@
           }
         }
       });
-    },
+    }
 
     /**
      * Shows the menu.
@@ -438,7 +458,7 @@
      * @param {{x: number, y: number}=} opt_mousePos The position of the mouse
      *     when shown (in screen coordinates).
      */
-    showMenu: function(shouldSetFocus, opt_mousePos) {
+    showMenu(shouldSetFocus, opt_mousePos) {
       this.hideMenu();
 
       this.menu.updateCommands(this);
@@ -459,7 +479,7 @@
 
       // When the menu is shown we steal all keyboard events.
       const doc = this.ownerDocument;
-      const win = doc.defaultView;
+      const win = assert(doc.defaultView);
       this.showingEvents_.add(doc, 'keydown', this, true);
       this.showingEvents_.add(doc, 'mousedown', this, true);
       this.showingEvents_.add(doc, 'focus', this, true);
@@ -474,12 +494,12 @@
         this.menu.focusSelectedItem();
       }
       this.currentMenu = this.menu;
-    },
+    }
 
     /**
      * Hides any sub-menu that is active.
      */
-    hideSubMenu_: function() {
+    hideSubMenu_() {
       const items =
           this.menu.querySelectorAll('cr-menu-item[sub-menu][sub-menu-shown]');
       items.forEach((menuItem) => {
@@ -494,7 +514,7 @@
         }
       });
       this.currentMenu = this.menu;
-    },
+    }
 
     /**
      * Hides the menu. If your menu can go out of scope, make sure to call this
@@ -502,9 +522,9 @@
      * @param {cr.ui.HideType=} opt_hideType Type of hide.
      *     default: cr.ui.HideType.INSTANT.
      */
-    hideMenu: function(opt_hideType) {
+    hideMenu(opt_hideType) {
       this.hideMenuInternal_(true, opt_hideType);
-    },
+    }
 
     /**
      * Hides the menu. If your menu can go out of scope, make sure to call this
@@ -512,9 +532,9 @@
      * @param {cr.ui.HideType=} opt_hideType Type of hide.
      *     default: cr.ui.HideType.INSTANT.
      */
-    hideMenuWithoutTakingFocus_: function(opt_hideType) {
+    hideMenuWithoutTakingFocus_(opt_hideType) {
       this.hideMenuInternal_(false, opt_hideType);
-    },
+    }
 
     /**
      * Hides the menu. If your menu can go out of scope, make sure to call this
@@ -523,7 +543,7 @@
      * @param {cr.ui.HideType=} opt_hideType Type of hide.
      *     default: cr.ui.HideType.INSTANT.
      */
-    hideMenuInternal_: function(shouldTakeFocus, opt_hideType) {
+    hideMenuInternal_(shouldTakeFocus, opt_hideType) {
       if (!this.isMenuShown()) {
         return;
       }
@@ -553,22 +573,22 @@
       // to be shown again.
       this.hideTimestamp_ = cr.isWindows ? Date.now() : 0;
       this.currentMenu = null;
-    },
+    }
 
     /**
      * Whether the menu is shown.
      */
-    isMenuShown: function() {
+    isMenuShown() {
       return this.hasAttribute('menu-shown');
-    },
+    }
 
     /**
      * Positions the menu below the menu button. We check the menu fits
      * in the viewport, and enable scrolling if required.
      * @private
      */
-    positionMenu_: function() {
-      positionPopupAroundElement(
+    positionMenu_() {
+      cr.ui.positionPopupAroundElement(
           this, this.menu, this.anchorType, this.invertLeftRight);
       // Check if menu is larger than the viewport and adjust its height
       // and enable scrolling if so. Note: style.bottom would have been set to
@@ -591,12 +611,12 @@
       } else {
         style.overflowY = 'auto';
       }
-    },
+    }
 
     /**
      * Handles the keydown event for the menu button.
      */
-    handleKeyDown: function(e) {
+    handleKeyDown(e) {
       switch (e.key) {
         case 'ArrowDown':
         case 'ArrowUp':
@@ -620,7 +640,9 @@
           break;
       }
     }
-  };
+  }
+
+  MultiMenuButton.prototype.__proto__ = HTMLButtonElement.prototype;
 
   // Export
   return {
diff --git a/ui/file_manager/file_manager/foreground/js/ui/providers_menu.js b/ui/file_manager/file_manager/foreground/js/ui/providers_menu.js
index 729efc0..1b42e6d7 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/providers_menu.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/providers_menu.js
@@ -4,109 +4,110 @@
 
 /**
  * Fills out the menu for mounting or installing new providers.
- *
- * @param {!ProvidersModel} model
- * @param {!cr.ui.Menu} menu
- * @constructor
- * @struct
  */
-function ProvidersMenu(model, menu) {
+class ProvidersMenu {
   /**
-   * @private {!ProvidersModel}}
-   * @const
+   * @param {!ProvidersModel} model
+   * @param {!cr.ui.Menu} menu
    */
-  this.model_ = model;
+  constructor(model, menu) {
+    /**
+     * @private {!ProvidersModel}}
+     * @const
+     */
+    this.model_ = model;
 
-  /**
-   * @private {!cr.ui.Menu}
-   * @const
-   */
-  this.menu_ = menu;
+    /**
+     * @private {!cr.ui.Menu}
+     * @const
+     */
+    this.menu_ = menu;
 
-  this.menu_.addSeparator();
+    this.menu_.addSeparator();
 
-  /**
-   * @private {!Element}
-   * @const
-   */
-  this.separator_ = assert(this.menu_.firstElementChild);
+    /**
+     * @private {!Element}
+     * @const
+     */
+    this.separator_ = assert(this.menu_.firstElementChild);
 
-  const installItem = this.addMenuItem_();
-  installItem.command = '#install-new-extension';
+    const installItem = this.addMenuItem_();
+    installItem.command = '#install-new-extension';
 
-  this.menu_.addEventListener('update', this.onUpdate_.bind(this));
-}
-
-/**
- * @private
- */
-ProvidersMenu.prototype.clearProviders_ = function() {
-  let childNode = this.menu_.firstElementChild;
-  while (childNode !== this.separator_) {
-    const node = childNode;
-    childNode = childNode.nextElementSibling;
-    this.menu_.removeChild(node);
+    this.menu_.addEventListener('update', this.onUpdate_.bind(this));
   }
-};
 
-/**
- * @return {!cr.ui.FilesMenuItem}
- * @private
- */
-ProvidersMenu.prototype.addMenuItem_ = function() {
-  const menuItem = this.menu_.addMenuItem({});
-  cr.ui.decorate(/** @type {!Element} */ (menuItem), cr.ui.FilesMenuItem);
-  return /** @type {!cr.ui.FilesMenuItem} */ (menuItem);
-};
+  /**
+   * @private
+   */
+  clearProviders_() {
+    let childNode = this.menu_.firstElementChild;
+    while (childNode !== this.separator_) {
+      const node = childNode;
+      childNode = childNode.nextElementSibling;
+      this.menu_.removeChild(node);
+    }
+  }
 
-/**
- * @param {string} providerId ID of the provider.
- * @param {!chrome.fileManagerPrivate.IconSet} iconSet Set of icons for the
- * provider.
- * @param {string} name Already localized name of the provider.
- * @private
- */
-ProvidersMenu.prototype.addProvider_ = function(providerId, iconSet, name) {
-  const item = this.addMenuItem_();
-  item.label = name;
+  /**
+   * @return {!cr.ui.FilesMenuItem}
+   * @private
+   */
+  addMenuItem_() {
+    const menuItem = this.menu_.addMenuItem({});
+    cr.ui.decorate(/** @type {!Element} */ (menuItem), cr.ui.FilesMenuItem);
+    return /** @type {!cr.ui.FilesMenuItem} */ (menuItem);
+  }
 
-  const iconImage = util.iconSetToCSSBackgroundImageValue(iconSet);
-  item.iconStartImage = iconImage;
+  /**
+   * @param {string} providerId ID of the provider.
+   * @param {!chrome.fileManagerPrivate.IconSet} iconSet Set of icons for the
+   * provider.
+   * @param {string} name Already localized name of the provider.
+   * @private
+   */
+  addProvider_(providerId, iconSet, name) {
+    const item = this.addMenuItem_();
+    item.label = name;
 
-  item.addEventListener(
-      'activate', this.onItemActivate_.bind(this, providerId));
+    const iconImage = util.iconSetToCSSBackgroundImageValue(iconSet);
+    item.iconStartImage = iconImage;
 
-  // Move the element before the separator.
-  this.menu_.insertBefore(item, this.separator_);
-};
+    item.addEventListener(
+        'activate', this.onItemActivate_.bind(this, providerId));
 
-/**
- * @param {!Event} event
- * @private
- */
-ProvidersMenu.prototype.onUpdate_ = function(event) {
-  this.model_.getMountableProviders().then(providers => {
-    this.clearProviders_();
-    providers.forEach(provider => {
-      this.addProvider_(provider.providerId, provider.iconSet, provider.name);
+    // Move the element before the separator.
+    this.menu_.insertBefore(item, this.separator_);
+  }
+
+  /**
+   * @param {!Event} event
+   * @private
+   */
+  onUpdate_(event) {
+    this.model_.getMountableProviders().then(providers => {
+      this.clearProviders_();
+      providers.forEach(provider => {
+        this.addProvider_(provider.providerId, provider.iconSet, provider.name);
+      });
     });
-  });
-};
+  }
 
-/**
- * @param {string} providerId
- * @param {!Event} event
- * @private
- */
-ProvidersMenu.prototype.onItemActivate_ = function(providerId, event) {
-  this.model_.requestMount(providerId);
-};
+  /**
+   * @param {string} providerId
+   * @param {!Event} event
+   * @private
+   */
+  onItemActivate_(providerId, event) {
+    this.model_.requestMount(providerId);
+  }
 
-/**
- *  Sends an 'update' event to the sub menu to trigger
- *  a reload of its content.
- */
-ProvidersMenu.prototype.updateSubMenu = function() {
-  const updateEvent = new Event('update');
-  this.menu_.dispatchEvent(updateEvent);
-};
+  /**
+   *  Sends an 'update' event to the sub menu to trigger
+   *  a reload of its content.
+   */
+  updateSubMenu() {
+    const updateEvent = new Event('update');
+    this.menu_.dispatchEvent(updateEvent);
+  }
+}
diff --git a/ui/file_manager/file_manager/test/js/chrome_api_test_impl.js b/ui/file_manager/file_manager/test/js/chrome_api_test_impl.js
index e624a6f1..850834f4 100644
--- a/ui/file_manager/file_manager/test/js/chrome_api_test_impl.js
+++ b/ui/file_manager/file_manager/test/js/chrome_api_test_impl.js
@@ -12,25 +12,29 @@
 // All testing functions in namespace 'test'.
 var test = test || {};
 
-/** @constructor */
-test.Event = function() {
-  this.listeners_ = [];
-};
-/** @param {function()} callback */
-test.Event.prototype.addListener = function(callback) {
-  this.listeners_.push(callback);
-};
-/** @param {function()} callback */
-test.Event.prototype.removeListener = function(callback) {
-  this.listeners_ = this.listeners_.filter(l => l !== callback);
-};
-/** @param {...*} args */
-test.Event.prototype.dispatchEvent = function(...args) {
-  setTimeout(() => {
-    for (let listener of this.listeners_) {
-      listener(...args);
-    }
-  }, 0);
+test.Event = class {
+  constructor() {
+    this.listeners_ = [];
+  }
+
+  /** @param {function()} callback */
+  addListener(callback) {
+    this.listeners_.push(callback);
+  }
+
+  /** @param {function()} callback */
+  removeListener(callback) {
+    this.listeners_ = this.listeners_.filter(l => l !== callback);
+  }
+
+  /** @param {...*} args */
+  dispatchEvent(...args) {
+    setTimeout(() => {
+      for (let listener of this.listeners_) {
+        listener(...args);
+      }
+    }, 0);
+  }
 };
 
 /**
@@ -183,15 +187,11 @@
 
 // domAutomationController is provided in tests, but is
 // useful for debugging tests in browser.
-
-/**
- * @constructor
- * @extends {DomAutomationController}
- */
-function ConsoleDomAutomationController() {}
-ConsoleDomAutomationController.prototype.send = (json) => {
-  console.debug('domAutomationController.send', json);
-};
+class ConsoleDomAutomationController extends DomAutomationController {
+  send(json) {
+    console.debug('domAutomationController.send', json);
+  }
+}
 
 window.domAutomationController =
     window.domAutomationController || new ConsoleDomAutomationController();
diff --git a/ui/file_manager/file_manager/test/js/test_util.js b/ui/file_manager/file_manager/test/js/test_util.js
index 97f99c7..88e178a9 100644
--- a/ui/file_manager/file_manager/test/js/test_util.js
+++ b/ui/file_manager/file_manager/test/js/test_util.js
@@ -66,71 +66,85 @@
 
 /**
  * File system entry information for tests.
- *
- * @param {test.EntryType} type Entry type.
- * @param {string} sourceFileName Source file name that provides file contents.
- * @param {string} targetPath Path of entry on the test file system.
- * @param {string} mimeType Mime type.
- * @param {test.SharedOption} sharedOption Shared option.
- * @param {string} lastModifiedTime Last modified time as a text to be shown in
- *     the last modified column.
- * @param {string} nameText File name to be shown in the name column.
- * @param {string} sizeText Size text to be shown in the size column.
- * @param {string} typeText Type name to be shown in the type column.
- * @constructor
  */
-test.TestEntryInfo = function(
-    type, sourceFileName, targetPath, mimeType, sharedOption, lastModifiedTime,
-    nameText, sizeText, typeText) {
-  this.type = type;
-  this.sourceFileName = sourceFileName || '';
-  this.targetPath = targetPath;
-  this.mimeType = mimeType || '';
-  this.sharedOption = sharedOption;
-  this.lastModifiedTime = lastModifiedTime;
-  this.nameText = nameText;
-  this.sizeText = sizeText;
-  this.typeText = typeText;
-  Object.freeze(this);
-};
+test.TestEntryInfo = class {
+  /**
+   * @param {test.EntryType} type Entry type.
+   * @param {string} sourceFileName Source file name that provides file
+   *     contents.
+   * @param {string} targetPath Path of entry on the test file system.
+   * @param {string} mimeType Mime type.
+   * @param {test.SharedOption} sharedOption Shared option.
+   * @param {string} lastModifiedTime Last modified time as a text to be shown
+   *     in the last modified column.
+   * @param {string} nameText File name to be shown in the name column.
+   * @param {string} sizeText Size text to be shown in the size column.
+   * @param {string} typeText Type name to be shown in the type column.
+   */
+  constructor(
+      type, sourceFileName, targetPath, mimeType, sharedOption,
+      lastModifiedTime, nameText, sizeText, typeText) {
+    this.type = type;
+    this.sourceFileName = sourceFileName || '';
+    this.targetPath = targetPath;
+    this.mimeType = mimeType || '';
+    this.sharedOption = sharedOption;
+    this.lastModifiedTime = lastModifiedTime;
+    this.nameText = nameText;
+    this.sizeText = sizeText;
+    this.typeText = typeText;
+  }
 
-test.TestEntryInfo.getExpectedRows = function(entries) {
-  return entries.map(function(entry) {
-    return entry.getExpectedRow();
-  });
-};
+  /**
+   * @param {!Array<!test.TestEntryInfo>} entries
+   * @return {!Array<Object>}
+   */
+  static getExpectedRows(entries) {
+    return entries.map(function(entry) {
+      return entry.getExpectedRow();
+    });
+  }
 
-/**
- * Returns 4-typle name, size, type, date as shown in file list.
- */
-test.TestEntryInfo.prototype.getExpectedRow = function() {
-  return [this.nameText, this.sizeText, this.typeText, this.lastModifiedTime];
-};
+  /**
+   * Returns 4-typle name, size, type, date as shown in file list.
+   */
+  getExpectedRow() {
+    return [this.nameText, this.sizeText, this.typeText, this.lastModifiedTime];
+  }
 
-test.TestEntryInfo.getMockFileSystemPopulateRows = function(entries, prefix) {
-  return entries.map(function(entry) {
-    return entry.getMockFileSystemPopulateRow(prefix);
-  });
-};
 
-/**
- * Returns object {fullPath: ..., metadata: {...}, content: ...} as used in
- * MockFileSystem.populate.
- */
-test.TestEntryInfo.prototype.getMockFileSystemPopulateRow = function(prefix) {
-  var suffix = this.type == test.EntryType.DIRECTORY ? '/' : '';
-  var content = test.DATA[this.sourceFileName];
-  var size = content && content.size || 0;
-  return {
-    fullPath: prefix + this.targetPath + suffix,
-    metadata: {
-      size: size,
-      modificationTime: new Date(Date.parse(this.lastModifiedTime)),
-      contentMimeType: this.mimeType,
-      hosted: this.mimeType == 'application/vnd.google-apps.document',
-    },
-    content: content
-  };
+  /**
+   * @param {!Array<!test.TestEntryInfo>} entries
+   * @param {string} prefix
+   * @return {!Array}
+   */
+  static getMockFileSystemPopulateRows(entries, prefix) {
+    return entries.map(function(entry) {
+      return entry.getMockFileSystemPopulateRow(prefix);
+    });
+  }
+
+  /**
+   * Returns object {fullPath: ..., metadata: {...}, content: ...} as used in
+   * MockFileSystem.populate.
+   * @param {string} prefix
+   * @return {!Object}
+   */
+  getMockFileSystemPopulateRow(prefix) {
+    const suffix = this.type == test.EntryType.DIRECTORY ? '/' : '';
+    const content = test.DATA[this.sourceFileName];
+    const size = content && content.size || 0;
+    return {
+      fullPath: prefix + this.targetPath + suffix,
+      metadata: {
+        size: size,
+        modificationTime: new Date(Date.parse(this.lastModifiedTime)),
+        contentMimeType: this.mimeType,
+        hosted: this.mimeType == 'application/vnd.google-apps.document',
+      },
+      content: content
+    };
+  }
 };
 
 /**
diff --git a/ui/file_manager/gallery/js/image_editor/image_view_unittest.js b/ui/file_manager/gallery/js/image_editor/image_view_unittest.js
index d42385fe..6ca7759 100644
--- a/ui/file_manager/gallery/js/image_editor/image_view_unittest.js
+++ b/ui/file_manager/gallery/js/image_editor/image_view_unittest.js
@@ -3,11 +3,11 @@
 // found in the LICENSE file.
 
 function testImageView() {
-  var mockFileSystem = new MockFileSystem('volumeId');
-  var mockEntry = new MockFileEntry(mockFileSystem, '/test.jpg');
+  const mockFileSystem = new MockFileSystem('volumeId');
+  const mockEntry = new MockFileEntry(mockFileSystem, '/test.jpg');
 
   // Item has full size cache.
-  var itemWithFullCache = new MockGalleryItem(mockEntry, null, {});
+  const itemWithFullCache = new MockGalleryItem(mockEntry, null, {});
   itemWithFullCache.contentImage =
       assertInstanceof(document.createElement('canvas'), HTMLCanvasElement);
   assertEquals(
@@ -15,7 +15,7 @@
       ImageView.getLoadTarget(itemWithFullCache, new ImageView.Effect.None()));
 
   // Item with content thumbnail.
-  var itemWithContentThumbnail =
+  const itemWithContentThumbnail =
       new MockGalleryItem(mockEntry, null, {thumbnail: {url: 'url'}});
   assertEquals(
       ImageView.LoadTarget.THUMBNAIL,
@@ -23,7 +23,7 @@
           itemWithContentThumbnail, new ImageView.Effect.None()));
 
   // Item with external thumbnail.
-  var itemWithExternalThumbnail =
+  const itemWithExternalThumbnail =
       new MockGalleryItem(mockEntry, null, {external: {thumbnailUrl: 'url'}});
   assertEquals(
       ImageView.LoadTarget.THUMBNAIL,
@@ -31,7 +31,7 @@
           itemWithExternalThumbnail, new ImageView.Effect.None()));
 
   // Item with external thumbnail but present locally.
-  var itemWithExternalThumbnailPresent = new MockGalleryItem(
+  const itemWithExternalThumbnailPresent = new MockGalleryItem(
       mockEntry, null, {external: {thumbnailUrl: 'url', present: true}});
   assertEquals(
       ImageView.LoadTarget.MAIN_IMAGE,
@@ -39,7 +39,7 @@
           itemWithExternalThumbnailPresent, new ImageView.Effect.None()));
 
   // Item with external thumbnail shown by slide effect.
-  var itemWithExternalThumbnailSlide =
+  const itemWithExternalThumbnailSlide =
       new MockGalleryItem(mockEntry, null, {external: {thumbnailUrl: 'url'}});
   assertEquals(
       ImageView.LoadTarget.THUMBNAIL,
@@ -47,7 +47,7 @@
           itemWithExternalThumbnailSlide, new ImageView.Effect.Slide(1)));
 
   // Item with external thumbnail shown by zoom to screen effect.
-  var itemWithExternalThumbnailZoomToScreen =
+  const itemWithExternalThumbnailZoomToScreen =
       new MockGalleryItem(mockEntry, null, {external: {thumbnailUrl: 'url'}});
   assertEquals(
       ImageView.LoadTarget.THUMBNAIL,
@@ -56,7 +56,7 @@
           new ImageView.Effect.ZoomToScreen(new ImageRect(0, 0, 100, 100))));
 
   // Item with external thumbnail shown by zoom effect.
-  var itemWithExternalThumbnailZoom =
+  const itemWithExternalThumbnailZoom =
       new MockGalleryItem(mockEntry, null, {external: {thumbnailUrl: 'url'}});
   assertEquals(
       ImageView.LoadTarget.MAIN_IMAGE,
@@ -65,7 +65,7 @@
           new ImageView.Effect.Zoom(0, 0, new ImageRect(0, 0, 1, 1))));
 
   // Item without cache/thumbnail.
-  var itemWithoutCacheOrThumbnail = new MockGalleryItem(mockEntry, null, {});
+  const itemWithoutCacheOrThumbnail = new MockGalleryItem(mockEntry, null, {});
   assertEquals(
       ImageView.LoadTarget.MAIN_IMAGE,
       ImageView.getLoadTarget(
@@ -73,45 +73,45 @@
 }
 
 function testLoadVideo(callback) {
-  var container = assertInstanceof(document.createElement('div'), HTMLElement);
+  const container =
+      assertInstanceof(document.createElement('div'), HTMLElement);
   // We re-use the image-container for video, it starts with this class.
   container.classList.add('image-container');
 
-  var viewport = new Viewport(window);
+  const viewport = new Viewport(window);
 
-  /**
-   * Mock volume manager.
-   * @constructor
-   * @extends MetadataProvider
-   */
-  function MockDownloadVolumeManager() {
-    this.__proto__.getVolumeInfo =
-        function(entry) {
-          return {volumeType: VolumeManagerCommon.VolumeType.DOWNLOADS};
-        };
+  class MockMetadataProvider extends MetadataProvider {
+    constructor() {
+      super([]);
+    }
+
+    /** @override */
+    async get() {
+      return [];
+    }
   }
 
-  var metadataModel = new MetadataModel(new MockDownloadVolumeManager());
-  var imageView = new ImageView(container, viewport, metadataModel);
+  const metadataModel = new MetadataModel(new MockMetadataProvider());
+  const imageView = new ImageView(container, viewport, metadataModel);
 
-  var downloads = new MockFileSystem('file:///downloads');
-  var getGalleryItem = function(path) {
+  const downloads = new MockFileSystem('file:///downloads');
+  const getGalleryItem = function(path) {
     return new MockGalleryItem(
         new MockFileEntry(downloads, path), null, {size: 100});
   };
-  var item = getGalleryItem('/test.webm');
-  var effect = new ImageView.Effect.None();
-  var displayDone = function() {
+  const item = getGalleryItem('/test.webm');
+  const effect = new ImageView.Effect.None();
+  const displayDone = function() {
     assertTrue(container.classList.contains('image-container'));
     assertTrue(container.classList.contains('video-container'));
-    var video = container.firstElementChild;
+    const video = container.firstElementChild;
     assertTrue(video instanceof HTMLVideoElement);
-    var source = video.firstElementChild;
+    const source = video.firstElementChild;
     assertTrue(source instanceof HTMLSourceElement);
     assertTrue(source.src.startsWith(
         'filesystem:file:///downloads/test.webm?nocache='));
     callback();
   };
-  var loadDone = function() {};
+  const loadDone = function() {};
   imageView.load(item, effect, displayDone, loadDone);
 }
diff --git a/ui/file_manager/image_loader/cache.js b/ui/file_manager/image_loader/cache.js
index e31a332..e7a5c01 100644
--- a/ui/file_manager/image_loader/cache.js
+++ b/ui/file_manager/image_loader/cache.js
@@ -27,7 +27,7 @@
  * @type {number}
  * @const
  */
-ImageCache.DB_VERSION = 12;
+ImageCache.DB_VERSION = 14;
 
 /**
  * Memory limit for images data in bytes.
@@ -200,13 +200,15 @@
  * Saves an image in the cache.
  *
  * @param {string} key Cache key.
- * @param {string} data Image data.
+ * @param {number} timestamp Last modification timestamp. Used to detect
+ *     if the image cache entry is out of date.
  * @param {number} width Image width.
  * @param {number} height Image height.
- * @param {number} timestamp Last modification timestamp. Used to detect
- *     if the cache entry becomes out of date.
+ * @param {?string} ifd Image ifd, null if none.
+ * @param {string} data Image data.
  */
-ImageCache.prototype.saveImage = function(key, data, width, height, timestamp) {
+ImageCache.prototype.saveImage = function(
+    key, timestamp, width, height, ifd, data) {
   if (!this.db_) {
     console.warn('Cache database not available.');
     return;
@@ -218,8 +220,11 @@
       timestamp: timestamp,
       width: width,
       height: height,
+      ifd: ifd,
       size: data.length,
-      lastLoadTimestamp: Date.now()};
+      lastLoadTimestamp: Date.now(),
+    };
+
     var dataEntry = {key: key, data: data};
 
     var transaction = this.db_.transaction(['settings', 'metadata', 'data'],
@@ -241,13 +246,13 @@
 };
 
 /**
- * Loads an image from the cache (if available) or returns null.
+ * Loads an image from the cache.
  *
  * @param {string} key Cache key.
  * @param {number} timestamp Last modification timestamp. If different
- *     that the one in cache, then the entry will be invalidated.
- * @param {function(string, number, number)} onSuccess Success callback with
- *     the image's data, width, height.
+ *     than the one in cache, then the entry will be invalidated.
+ * @param {function(number, number, ?string, string)} onSuccess Success
+ *     callback with the image width, height, ?ifd, and data.
  * @param {function()} onFailure Failure callback.
  */
 ImageCache.prototype.loadImage = function(
@@ -296,7 +301,9 @@
       // image data.
       metadataEntry.lastLoadTimestamp = Date.now();
       metadataStore.put(metadataEntry);  // Added asynchronously.
-      onSuccess(dataEntry.data, metadataEntry.width, metadataEntry.height);
+      onSuccess(
+          metadataEntry.width, metadataEntry.height, metadataEntry.ifd,
+          dataEntry.data);
     }
   }.bind(this);
 
diff --git a/ui/file_manager/image_loader/image_loader_client.js b/ui/file_manager/image_loader/image_loader_client.js
index 8a0b7a0..4b8e2bf 100644
--- a/ui/file_manager/image_loader/image_loader_client.js
+++ b/ui/file_manager/image_loader/image_loader_client.js
@@ -22,7 +22,12 @@
   /**
    * LRU cache for images.
    * @type {!LRUCache.<{
-   *     data: string, width:number, height:number, timestamp: ?number}>}
+   *   timestamp: ?number,
+   *   width: number,
+   *   height: number,
+   *   ifd: ?string,
+   *   data: string
+   * }>}
    * @private
    */
   this.cache_ = new LRUCache(ImageLoaderClient.CACHE_MEMORY_LIMIT);
@@ -120,6 +125,7 @@
         callback(new LoadImageResponse(LoadImageResponseStatus.SUCCESS, null, {
           width: cachedValue.width,
           height: cachedValue.height,
+          ifd: cachedValue.ifd,
           data: cachedValue.data,
         }));
         return null;
diff --git a/ui/file_manager/image_loader/image_loader_client_unittest.js b/ui/file_manager/image_loader/image_loader_client_unittest.js
index b10d951..054785f 100644
--- a/ui/file_manager/image_loader/image_loader_client_unittest.js
+++ b/ui/file_manager/image_loader/image_loader_client_unittest.js
@@ -36,7 +36,7 @@
     if (callback) {
       callback(new LoadImageResponse(
           LoadImageResponseStatus.SUCCESS, message.taskId || -1,
-          {data: 'ImageData', width: 100, height: 100}));
+          {width: 100, height: 100, ifd: null, data: 'ImageData'}));
     }
   };
 
diff --git a/ui/file_manager/image_loader/load_image_request.js b/ui/file_manager/image_loader/load_image_request.js
index f6e0006..404ac91 100644
--- a/ui/file_manager/image_loader/load_image_request.js
+++ b/ui/file_manager/image_loader/load_image_request.js
@@ -34,7 +34,8 @@
   /**
    * @param {!LoadImageResponseStatus} status
    * @param {?number} taskId or null if fulfilled by the client-side cache.
-   * @param {{width:number, height:number, data:string}=} opt_result
+   * @param {{width:number, height:number, ifd:?string, data:string}=}
+   *    opt_result
    */
   constructor(status, taskId, opt_result) {
     /** @type {!LoadImageResponseStatus} */
@@ -46,14 +47,16 @@
       return;
     }
 
+    // Response result defined only when status == SUCCESS.
     assert(opt_result);
 
-    // Properties only defined when status == SUCCESS.
-
     /** @type {number|undefined} */
     this.width = opt_result.width;
     /** @type {number|undefined} */
     this.height = opt_result.height;
+    /** @type {?string} */
+    this.ifd = opt_result.ifd;
+
     /**
      * The (compressed) image data as a data URL.
      * @type {string|undefined}
@@ -69,24 +72,30 @@
    *        then null is used. Currently this disables any caching in the
    *        ImageLoader, but disables only *expiration* in the client unless a
    *        timestamp is presented on a later request.
-   * @return {?{timestamp: ?number,
-   *            width: number,
-   *            height: number,
-   *            data:!string}}
+   * @return {?{
+   *   timestamp: ?number,
+   *   width: number,
+   *   height: number,
+   *   ifd: ?string,
+   *   data: string
+   * }}
    */
   static cacheValue(response, timestamp) {
     if (response.status === LoadImageResponseStatus.ERROR) {
       return null;
     }
 
+    // Response result defined only when status == SUCCESS.
     assert(response.width);
     assert(response.height);
     assert(response.data);
+
     return {
-      timestamp: timestamp ? timestamp : null,
+      timestamp: timestamp || null,
       width: response.width,
       height: response.height,
-      data: response.data
+      ifd: response.ifd,
+      data: response.data,
     };
   }
 }
diff --git a/ui/file_manager/image_loader/request.js b/ui/file_manager/image_loader/request.js
index 9a7d90d..ba9386b1 100644
--- a/ui/file_manager/image_loader/request.js
+++ b/ui/file_manager/image_loader/request.js
@@ -60,6 +60,14 @@
   this.contentType_ = null;
 
   /**
+   * IFD data of the fetched image. Only RAW images provide non-null ifd
+   * data at this time; images on Drive might provide ifd in future.
+   * @type {?string}
+   * @private
+   */
+  this.ifd_ = null;
+
+  /**
    * Used to download remote images using http:// or https:// protocols.
    * @type {AuthorizedXHR}
    * @private
@@ -136,7 +144,8 @@
 };
 
 /**
- * Tries to load the image from cache if exists and sends the response.
+ * Tries to load the image from cache, if it exists in the cache, and sends
+ * the response. Fails if the image is not found in the cache.
  *
  * @param {function()} onSuccess Success callback.
  * @param {function()} onFailure Failure callback.
@@ -144,8 +153,9 @@
 ImageRequest.prototype.loadFromCacheAndProcess = function(
     onSuccess, onFailure) {
   this.loadFromCache_(
-      function(data, width, height) {  // Found in cache.
-        this.sendImageData_(data, width, height);
+      function(width, height, ifd, data) {  // Found in cache.
+        this.ifd_ = ifd;
+        this.sendImageData_(width, height, data);
         onSuccess();
       }.bind(this),
       onFailure);  // Not found in cache.
@@ -153,6 +163,7 @@
 
 /**
  * Tries to download the image, resizes and sends the response.
+ *
  * @param {function()} callback Completion callback.
  */
 ImageRequest.prototype.downloadAndProcess = function(callback) {
@@ -168,12 +179,13 @@
 /**
  * Fetches the image from the persistent cache.
  *
- * @param {function(string, number, number)} onSuccess Success callback.
+ * @param {function(number, number, ?string, string)} onSuccess
+ *    Success callback with the image width, height, ?ifd, and data.
  * @param {function()} onFailure Failure callback.
  * @private
  */
 ImageRequest.prototype.loadFromCache_ = function(onSuccess, onFailure) {
-  let cacheKey = LoadImageRequest.cacheKey(this.request_);
+  const cacheKey = LoadImageRequest.cacheKey(this.request_);
 
   if (!cacheKey) {
     // Cache key is not provided for the request.
@@ -189,43 +201,39 @@
     return;
   }
 
-  if (!this.request_.timestamp) {
+  const timestamp = this.request_.timestamp;
+  if (!timestamp) {
     // Persistent cache is available only when a timestamp is provided.
     onFailure();
     return;
   }
 
-  this.cache_.loadImage(cacheKey,
-                        this.request_.timestamp,
-                        onSuccess,
-                        onFailure);
+  this.cache_.loadImage(cacheKey, timestamp, onSuccess, onFailure);
 };
 
 /**
  * Saves the image to the persistent cache.
  *
- * @param {string} data The image's data.
  * @param {number} width Image width.
  * @param {number} height Image height.
+ * @param {string} data Image data.
  * @private
  */
-ImageRequest.prototype.saveToCache_ = function(data, width, height) {
-  if (!this.request_.cache || !this.request_.timestamp) {
+ImageRequest.prototype.saveToCache_ = function(width, height, data) {
+  const timestamp = this.request_.timestamp;
+
+  if (!this.request_.cache || !timestamp) {
     // Persistent cache is available only when a timestamp is provided.
     return;
   }
 
-  let cacheKey = LoadImageRequest.cacheKey(this.request_);
+  const cacheKey = LoadImageRequest.cacheKey(this.request_);
   if (!cacheKey) {
     // Cache key is not provided for the request.
     return;
   }
 
-  this.cache_.saveImage(cacheKey,
-                        data,
-                        width,
-                        height,
-                        this.request_.timestamp);
+  this.cache_.saveImage(cacheKey, timestamp, width, height, this.ifd_, data);
 };
 
 /**
@@ -283,6 +291,7 @@
       this.image_.src = url;
       this.request_.orientation = data.orientation;
       this.request_.colorSpace = data.colorSpace;
+      this.ifd_ = data.ifd;
     }.bind(this), function() {
       // The error has already been logged in PiexLoader.
       onFailure();
@@ -524,15 +533,16 @@
  * @private
  */
 ImageRequest.prototype.sendImage_ = function(imageChanged) {
-  var imageData;
-  var width;
-  var height;
+  let width;
+  let height;
+  let data;
+
   if (!imageChanged) {
     // The image hasn't been processed, so the raw data can be directly
     // forwarded for speed (no need to encode the image again).
-    imageData = this.image_.src;
     width = this.image_.width;
     height = this.image_.height;
+    data = this.image_.src;
   } else {
     // The image has been resized or rotated, therefore the canvas has to be
     // encoded to get the correct compressed image data.
@@ -544,30 +554,32 @@
       case 'image/png':
       case 'image/svg':
       case 'image/bmp':
-        imageData = this.canvas_.toDataURL('image/png');
+        data = this.canvas_.toDataURL('image/png');
         break;
       case 'image/jpeg':
       default:
-        imageData = this.canvas_.toDataURL('image/jpeg', 0.9);
+        data = this.canvas_.toDataURL('image/jpeg', 0.9);
+        break;
     }
   }
 
-  // Send and store in the persistent cache.
-  this.sendImageData_(imageData, width, height);
-  this.saveToCache_(imageData, width, height);
+  // Send the image data and also save it in the persistent cache.
+  this.sendImageData_(width, height, data);
+  this.saveToCache_(width, height, data);
 };
 
 /**
  * Sends the resized image via the callback.
- * @param {string} data Compressed image data.
- * @param {number} width Width.
- * @param {number} height Height.
+ *
+ * @param {number} width Image width.
+ * @param {number} height Image height.
+ * @param {string} data Image data.
  * @private
  */
-ImageRequest.prototype.sendImageData_ = function(data, width, height) {
+ImageRequest.prototype.sendImageData_ = function(width, height, data) {
+  const result = {width, height, ifd: this.ifd_, data};
   this.sendResponse_(new LoadImageResponse(
-      LoadImageResponseStatus.SUCCESS, this.getClientTaskId(),
-      {width: width, height: height, data: data}));
+      LoadImageResponseStatus.SUCCESS, this.getClientTaskId(), result));
 };
 
 /**
diff --git a/ui/gl/BUILD.gn b/ui/gl/BUILD.gn
index a54c5b0..f1c69fa 100644
--- a/ui/gl/BUILD.gn
+++ b/ui/gl/BUILD.gn
@@ -142,6 +142,8 @@
     "scoped_binders.h",
     "scoped_make_current.cc",
     "scoped_make_current.h",
+    "shader_tracking.cc",
+    "shader_tracking.h",
     "sync_control_vsync_provider.cc",
     "sync_control_vsync_provider.h",
     "trace_util.cc",
diff --git a/ui/gl/gl_gl_api_implementation.cc b/ui/gl/gl_gl_api_implementation.cc
index ae6655c..eb548c2f 100644
--- a/ui/gl/gl_gl_api_implementation.cc
+++ b/ui/gl/gl_gl_api_implementation.cc
@@ -15,6 +15,7 @@
 #include "ui/gl/gl_surface.h"
 #include "ui/gl/gl_switches.h"
 #include "ui/gl/gl_version_info.h"
+#include "ui/gl/shader_tracking.h"
 
 namespace gl {
 
@@ -467,6 +468,34 @@
   }
 }
 
+void RealGLApi::glUseProgramFn(GLuint program) {
+  ui::gl::ShaderTracking* shader_tracking =
+      ui::gl::ShaderTracking::GetInstance();
+  if (shader_tracking) {
+    std::vector<char> buffers[2];
+    char* strings[2] = {nullptr, nullptr};
+    if (program) {
+      // The following only works with ANGLE backend because ANGLE makes sure
+      // a program's shaders are not actually deleted and source can still be
+      // queried even if glDeleteShaders() has been called on them.
+
+      // Also, in theory, different shaders can be attached to the program
+      // after the last link, but for now, ignore such corner case patterns.
+      GLsizei count = 0;
+      GLuint shaders[2] = {0};
+      glGetAttachedShadersFn(program, 2, &count, shaders);
+      for (GLsizei ii = 0; ii < std::min(2, count); ++ii) {
+        buffers[ii].resize(ui::gl::ShaderTracking::kMaxShaderSize);
+        glGetShaderSourceFn(shaders[ii], ui::gl::ShaderTracking::kMaxShaderSize,
+                            nullptr, buffers[ii].data());
+        strings[ii] = buffers[ii].data();
+      }
+    }
+    shader_tracking->SetShaders(strings[0], strings[1]);
+  }
+  GLApiBase::glUseProgramFn(program);
+}
+
 void RealGLApi::InitializeFilteredExtensionsIfNeeded() {
   DCHECK(disabled_exts_.size());
   if (filtered_exts_.size())
diff --git a/ui/gl/gl_gl_api_implementation.h b/ui/gl/gl_gl_api_implementation.h
index 6fd49e02..574f463 100644
--- a/ui/gl/gl_gl_api_implementation.h
+++ b/ui/gl/gl_gl_api_implementation.h
@@ -123,6 +123,8 @@
   void glClearDepthFn(GLclampd depth) override;
   void glDepthRangeFn(GLclampd z_near, GLclampd z_far) override;
 
+  void glUseProgramFn(GLuint program) override;
+
   void set_gl_workarounds(const GLWorkarounds& workarounds);
   void set_version(std::unique_ptr<GLVersionInfo> version);
   void ClearCachedGLExtensions();
diff --git a/ui/gl/gl_switches.cc b/ui/gl/gl_switches.cc
index a725579..ddce7874 100644
--- a/ui/gl/gl_switches.cc
+++ b/ui/gl/gl_switches.cc
@@ -174,4 +174,10 @@
 const base::Feature kSwapChainFrameStatistics{
     "SwapChainFrameStatistics", base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Track current program's shaders at glUseProgram() call for crash report
+// purpose. Only effective on Windows because the attached shaders may only
+// be reliably retrieved with ANGLE backend.
+const base::Feature kTrackCurrentShaders{"TrackCurrentShaders",
+                                         base::FEATURE_DISABLED_BY_DEFAULT};
+
 }  // namespace features
diff --git a/ui/gl/gl_switches.h b/ui/gl/gl_switches.h
index c49c263..add27a51 100644
--- a/ui/gl/gl_switches.h
+++ b/ui/gl/gl_switches.h
@@ -76,6 +76,7 @@
 GL_EXPORT extern const base::Feature kDirectCompositionUseNV12DecodeSwapChain;
 GL_EXPORT extern const base::Feature kDefaultANGLEOpenGL;
 GL_EXPORT extern const base::Feature kSwapChainFrameStatistics;
+extern const base::Feature kTrackCurrentShaders;
 
 }  // namespace features
 
diff --git a/ui/gl/shader_tracking.cc b/ui/gl/shader_tracking.cc
new file mode 100644
index 0000000..eb4480c
--- /dev/null
+++ b/ui/gl/shader_tracking.cc
@@ -0,0 +1,42 @@
+// Copyright (c) 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 "ui/gl/shader_tracking.h"
+
+#include "base/logging.h"
+#include "ui/gl/gl_switches.h"
+
+namespace ui {
+namespace gl {
+
+// static
+ShaderTracking* ShaderTracking::GetInstance() {
+#if defined(OS_WIN)
+  // Shaders can only be reliably retrieved with ANGLE backend. Therefore,
+  // limit to Windows platform only.
+  static bool enabled =
+      base::FeatureList::IsEnabled(features::kTrackCurrentShaders);
+  if (enabled) {
+    static base::NoDestructor<ShaderTracking> instance;
+    return instance.get();
+  }
+#endif  // OS_WIN
+  return nullptr;
+}
+
+void ShaderTracking::GetShaders(std::string* shader0, std::string* shader1) {
+  DCHECK(shader0 && shader1);
+  base::AutoLock auto_lock(lock_);
+  *shader0 = shaders_[0];
+  *shader1 = shaders_[1];
+}
+
+void ShaderTracking::SetShaders(const char* shader0, const char* shader1) {
+  base::AutoLock auto_lock(lock_);
+  shaders_[0] = shader0 ? shader0 : "";
+  shaders_[1] = shader1 ? shader1 : "";
+}
+
+}  // namespace gl
+}  // namespace ui
diff --git a/ui/gl/shader_tracking.h b/ui/gl/shader_tracking.h
new file mode 100644
index 0000000..b83ac6fc
--- /dev/null
+++ b/ui/gl/shader_tracking.h
@@ -0,0 +1,44 @@
+// Copyright (c) 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 UI_GL_SHADER_TRACKING_H_
+#define UI_GL_SHADER_TRACKING_H_
+
+#include <string>
+
+#include "base/macros.h"
+#include "base/no_destructor.h"
+#include "base/synchronization/lock.h"
+#include "build/build_config.h"
+#include "ui/gl/gl_export.h"
+
+namespace ui {
+namespace gl {
+
+class GL_EXPORT ShaderTracking {
+ public:
+  static ShaderTracking* GetInstance();
+
+  static const size_t kMaxShaderSize = 1024;
+
+  void GetShaders(std::string* shader0, std::string* shader1);
+
+  void SetShaders(const char* shader0, const char* shader1);
+
+ private:
+  friend base::NoDestructor<ShaderTracking>;
+
+  ShaderTracking() {}
+  ~ShaderTracking() {}
+
+  mutable base::Lock lock_;
+  std::string shaders_[2];
+
+  DISALLOW_COPY_AND_ASSIGN(ShaderTracking);
+};
+
+}  // namespace gl
+}  // namespace ui
+
+#endif  // UI_GL_SHADER_TRACKING_H_
diff --git a/ui/views/accessible_pane_view.cc b/ui/views/accessible_pane_view.cc
index 2e2229db..73b501c 100644
--- a/ui/views/accessible_pane_view.cc
+++ b/ui/views/accessible_pane_view.cc
@@ -255,4 +255,8 @@
   return nullptr;
 }
 
+BEGIN_METADATA(AccessiblePaneView)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
 }  // namespace views
diff --git a/ui/views/accessible_pane_view.h b/ui/views/accessible_pane_view.h
index d4d0c8ab..1c70cd36d 100644
--- a/ui/views/accessible_pane_view.h
+++ b/ui/views/accessible_pane_view.h
@@ -25,6 +25,8 @@
                                         public FocusChangeListener,
                                         public FocusTraversable {
  public:
+  METADATA_HEADER(AccessiblePaneView);
+
   AccessiblePaneView();
   ~AccessiblePaneView() override;
 
diff --git a/ui/views/animation/ink_drop_host_view.cc b/ui/views/animation/ink_drop_host_view.cc
index 64a1451..a6fcea7 100644
--- a/ui/views/animation/ink_drop_host_view.cc
+++ b/ui/views/animation/ink_drop_host_view.cc
@@ -195,4 +195,8 @@
   return gfx::ScaleToCeiledSize(gfx::Size(small_size), kLargeInkDropScale);
 }
 
+BEGIN_METADATA(InkDropHostView)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
 }  // namespace views
diff --git a/ui/views/animation/ink_drop_host_view.h b/ui/views/animation/ink_drop_host_view.h
index 3087973..fce6c3d 100644
--- a/ui/views/animation/ink_drop_host_view.h
+++ b/ui/views/animation/ink_drop_host_view.h
@@ -38,6 +38,8 @@
 // A view that provides InkDropHost functionality.
 class VIEWS_EXPORT InkDropHostView : public View {
  public:
+  METADATA_HEADER(InkDropHostView);
+
   // Used in SetInkDropMode() to specify whether the ink drop effect is enabled
   // or not for the view. In case of having an ink drop, it also specifies
   // whether the default event handler for the ink drop should be installed or
diff --git a/ui/views/bubble/bubble_dialog_delegate_view.cc b/ui/views/bubble/bubble_dialog_delegate_view.cc
index ee6f0497..96d3642 100644
--- a/ui/views/bubble/bubble_dialog_delegate_view.cc
+++ b/ui/views/bubble/bubble_dialog_delegate_view.cc
@@ -116,10 +116,6 @@
 
 }  // namespace
 
-// static
-const char BubbleDialogDelegateView::kViewClassName[] =
-    "BubbleDialogDelegateView";
-
 BubbleDialogDelegateView::~BubbleDialogDelegateView() {
   if (GetWidget())
     GetWidget()->RemoveObserver(this);
@@ -181,10 +177,6 @@
   return frame;
 }
 
-const char* BubbleDialogDelegateView::GetClassName() const {
-  return kViewClassName;
-}
-
 bool BubbleDialogDelegateView::AcceleratorPressed(
     const ui::Accelerator& accelerator) {
   if (accelerator.key_code() == ui::VKEY_DOWN ||
@@ -517,4 +509,8 @@
     button->SetHighlighted(highlighted);
 }
 
+BEGIN_METADATA(BubbleDialogDelegateView)
+METADATA_PARENT_CLASS(DialogDelegateView)
+END_METADATA()
+
 }  // namespace views
diff --git a/ui/views/bubble/bubble_dialog_delegate_view.h b/ui/views/bubble/bubble_dialog_delegate_view.h
index bb495e3..cd25d7c 100644
--- a/ui/views/bubble/bubble_dialog_delegate_view.h
+++ b/ui/views/bubble/bubble_dialog_delegate_view.h
@@ -39,8 +39,7 @@
 class VIEWS_EXPORT BubbleDialogDelegateView : public DialogDelegateView,
                                               public WidgetObserver {
  public:
-  // Internal class name.
-  static const char kViewClassName[];
+  METADATA_HEADER(BubbleDialogDelegateView);
 
   enum class CloseReason {
     DEACTIVATION,
@@ -58,7 +57,6 @@
   bool ShouldShowCloseButton() const override;
   ClientView* CreateClientView(Widget* widget) override;
   NonClientFrameView* CreateNonClientFrameView(Widget* widget) override;
-  const char* GetClassName() const override;
   bool AcceleratorPressed(const ui::Accelerator& accelerator) override;
 
   // WidgetObserver:
diff --git a/ui/views/bubble/footnote_container_view.cc b/ui/views/bubble/footnote_container_view.cc
index 4277f03..5fec2842 100644
--- a/ui/views/bubble/footnote_container_view.cc
+++ b/ui/views/bubble/footnote_container_view.cc
@@ -76,4 +76,8 @@
   SetVisible(child->GetVisible());
 }
 
+BEGIN_METADATA(FootnoteContainerView)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
 }  // namespace views
diff --git a/ui/views/bubble/footnote_container_view.h b/ui/views/bubble/footnote_container_view.h
index 2b4bea9..40b4c1f 100644
--- a/ui/views/bubble/footnote_container_view.h
+++ b/ui/views/bubble/footnote_container_view.h
@@ -13,6 +13,8 @@
 // background with rounded corners at the bottom.
 class FootnoteContainerView : public View {
  public:
+  METADATA_HEADER(FootnoteContainerView);
+
   FootnoteContainerView(const gfx::Insets& margins,
                         View* child_view,
                         float corner_radius);
diff --git a/ui/views/bubble/info_bubble.cc b/ui/views/bubble/info_bubble.cc
index bce2529..aeaa6c71 100644
--- a/ui/views/bubble/info_bubble.cc
+++ b/ui/views/bubble/info_bubble.cc
@@ -125,4 +125,8 @@
   }
 }
 
+BEGIN_METADATA(InfoBubble)
+METADATA_PARENT_CLASS(BubbleDialogDelegateView)
+END_METADATA()
+
 }  // namespace views
diff --git a/ui/views/bubble/info_bubble.h b/ui/views/bubble/info_bubble.h
index c1f092d..7d607e76 100644
--- a/ui/views/bubble/info_bubble.h
+++ b/ui/views/bubble/info_bubble.h
@@ -17,6 +17,8 @@
 // Class to create and manage an information bubble for errors or tooltips.
 class InfoBubble : public BubbleDialogDelegateView {
  public:
+  METADATA_HEADER(InfoBubble);
+
   InfoBubble(View* anchor, const base::string16& message);
   ~InfoBubble() override;
 
diff --git a/ui/views/bubble/tooltip_icon.cc b/ui/views/bubble/tooltip_icon.cc
index 0ff1e6bd..289e921 100644
--- a/ui/views/bubble/tooltip_icon.cc
+++ b/ui/views/bubble/tooltip_icon.cc
@@ -28,10 +28,6 @@
   HideBubble();
 }
 
-const char* TooltipIcon::GetClassName() const {
-  return "TooltipIcon";
-}
-
 void TooltipIcon::OnMouseEntered(const ui::MouseEvent& event) {
   mouse_inside_ = true;
   show_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(150), this,
@@ -113,4 +109,8 @@
   bubble_ = nullptr;
 }
 
+BEGIN_METADATA(TooltipIcon)
+METADATA_PARENT_CLASS(ImageView)
+END_METADATA()
+
 }  // namespace views
diff --git a/ui/views/bubble/tooltip_icon.h b/ui/views/bubble/tooltip_icon.h
index 97dbe04..cb10e59 100644
--- a/ui/views/bubble/tooltip_icon.h
+++ b/ui/views/bubble/tooltip_icon.h
@@ -25,12 +25,13 @@
                                  public MouseWatcherListener,
                                  public WidgetObserver {
  public:
+  METADATA_HEADER(TooltipIcon);
+
   explicit TooltipIcon(const base::string16& tooltip,
                        int tooltip_icon_size = 16);
   ~TooltipIcon() override;
 
   // ImageView:
-  const char* GetClassName() const override;
   void OnMouseEntered(const ui::MouseEvent& event) override;
   void OnMouseExited(const ui::MouseEvent& event) override;
   bool OnMousePressed(const ui::MouseEvent& event) override;
diff --git a/ui/views/controls/animated_image_view.cc b/ui/views/controls/animated_image_view.cc
index bb379bc3..aca500c 100644
--- a/ui/views/controls/animated_image_view.cc
+++ b/ui/views/controls/animated_image_view.cc
@@ -90,9 +90,6 @@
   canvas->Restore();
 }
 
-const char* AnimatedImageView::GetClassName() const {
-  return "AnimatedImageView";
-}
 
 void AnimatedImageView::NativeViewHierarchyChanged() {
   ui::Compositor* compositor = GetWidget()->GetCompositor();
@@ -142,4 +139,8 @@
   }
 }
 
+BEGIN_METADATA(AnimatedImageView)
+METADATA_PARENT_CLASS(ImageViewBase)
+END_METADATA()
+
 }  // namespace views
diff --git a/ui/views/controls/animated_image_view.h b/ui/views/controls/animated_image_view.h
index f3868c2..58ea3ee 100644
--- a/ui/views/controls/animated_image_view.h
+++ b/ui/views/controls/animated_image_view.h
@@ -34,6 +34,8 @@
 class VIEWS_EXPORT AnimatedImageView : public ImageViewBase,
                                        public ui::CompositorAnimationObserver {
  public:
+  METADATA_HEADER(AnimatedImageView);
+
   enum class State {
     kPlaying,  // The animation is currently playing.
     kStopped   // The animation is stopped and paint will raster the first
@@ -60,7 +62,6 @@
 
   // Overridden from View:
   void OnPaint(gfx::Canvas* canvas) override;
-  const char* GetClassName() const override;
   void NativeViewHierarchyChanged() override;
   void RemovedFromWidget() override;
 
diff --git a/ui/views/controls/button/button.cc b/ui/views/controls/button/button.cc
index cd9b168..da79ddb 100644
--- a/ui/views/controls/button/button.cc
+++ b/ui/views/controls/button/button.cc
@@ -70,10 +70,6 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// Button, static public:
-
-// static
-const char Button::kViewClassName[] = "Button";
 
 // static
 const Button* Button::AsButton(const views::View* view) {
@@ -227,10 +223,6 @@
 ////////////////////////////////////////////////////////////////////////////////
 // Button, View overrides:
 
-const char* Button::GetClassName() const {
-  return kViewClassName;
-}
-
 bool Button::OnMousePressed(const ui::MouseEvent& event) {
   return button_controller_->OnMousePressed(event);
 }
@@ -599,4 +591,8 @@
   StateChanged(state());
 }
 
+BEGIN_METADATA(Button)
+METADATA_PARENT_CLASS(InkDropHostView)
+END_METADATA()
+
 }  // namespace views
diff --git a/ui/views/controls/button/button.h b/ui/views/controls/button/button.h
index c923869f..f705c85 100644
--- a/ui/views/controls/button/button.h
+++ b/ui/views/controls/button/button.h
@@ -47,6 +47,8 @@
 class VIEWS_EXPORT Button : public InkDropHostView,
                             public gfx::AnimationDelegate {
  public:
+  METADATA_HEADER(Button);
+
   ~Button() override;
 
   // Button states for various button sub-types.
@@ -72,9 +74,6 @@
     CLICK_NONE,
   };
 
-  // The menu button's class name.
-  static const char kViewClassName[];
-
   static const Button* AsButton(const View* view);
   static Button* AsButton(View* view);
 
@@ -165,7 +164,6 @@
   void RemoveButtonObserver(ButtonObserver* observer);
 
   // Overridden from View:
-  const char* GetClassName() const override;
   bool OnMousePressed(const ui::MouseEvent& event) override;
   bool OnMouseDragged(const ui::MouseEvent& event) override;
   void OnMouseReleased(const ui::MouseEvent& event) override;
diff --git a/ui/views/controls/button/checkbox.cc b/ui/views/controls/button/checkbox.cc
index f0f8889..1f216af 100644
--- a/ui/views/controls/button/checkbox.cc
+++ b/ui/views/controls/button/checkbox.cc
@@ -31,9 +31,6 @@
 
 namespace views {
 
-// static
-const char Checkbox::kViewClassName[] = "Checkbox";
-
 Checkbox::Checkbox(const base::string16& label, ButtonListener* listener)
     : LabelButton(listener, label), checked_(false), label_ax_id_(0) {
   SetHorizontalAlignment(gfx::ALIGN_LEFT);
@@ -92,10 +89,6 @@
       node_data.GetString16Attribute(ax::mojom::StringAttribute::kName));
 }
 
-const char* Checkbox::GetClassName() const {
-  return kViewClassName;
-}
-
 void Checkbox::GetAccessibleNodeData(ui::AXNodeData* node_data) {
   LabelButton::GetAccessibleNodeData(node_data);
   node_data->role = ax::mojom::Role::kCheckBox;
diff --git a/ui/views/controls/button/checkbox.h b/ui/views/controls/button/checkbox.h
index 68ea1f7..47b500e0 100644
--- a/ui/views/controls/button/checkbox.h
+++ b/ui/views/controls/button/checkbox.h
@@ -26,8 +26,6 @@
  public:
   METADATA_HEADER(Checkbox);
 
-  static const char kViewClassName[];
-
   // |force_md| forces MD even when --secondary-ui-md flag is not set.
   explicit Checkbox(const base::string16& label,
                     ButtonListener* listener = nullptr);
@@ -51,7 +49,6 @@
 
  protected:
   // LabelButton:
-  const char* GetClassName() const override;
   void OnThemeChanged() override;
   std::unique_ptr<InkDrop> CreateInkDrop() override;
   std::unique_ptr<InkDropRipple> CreateInkDropRipple() const override;
diff --git a/ui/views/controls/button/image_button.cc b/ui/views/controls/button/image_button.cc
index 8616381d..e7717ed 100644
--- a/ui/views/controls/button/image_button.cc
+++ b/ui/views/controls/button/image_button.cc
@@ -24,8 +24,6 @@
 static constexpr int kDefaultWidth = 16;
 static constexpr int kDefaultHeight = 14;
 
-const char ImageButton::kViewClassName[] = "ImageButton";
-
 ////////////////////////////////////////////////////////////////////////////////
 // ImageButton, public:
 
@@ -109,10 +107,6 @@
 ////////////////////////////////////////////////////////////////////////////////
 // ImageButton, View overrides:
 
-const char* ImageButton::GetClassName() const {
-  return kViewClassName;
-}
-
 gfx::Size ImageButton::CalculatePreferredSize() const {
   gfx::Size size(kDefaultWidth, kDefaultHeight);
   if (!images_[STATE_NORMAL].isNull()) {
diff --git a/ui/views/controls/button/image_button.h b/ui/views/controls/button/image_button.h
index 473f65f..bcad731 100644
--- a/ui/views/controls/button/image_button.h
+++ b/ui/views/controls/button/image_button.h
@@ -23,8 +23,6 @@
  public:
   METADATA_HEADER(ImageButton);
 
-  static const char kViewClassName[];
-
   // An enum describing the horizontal alignment of images on Buttons.
   enum HorizontalAlignment {
     ALIGN_LEFT = 0,
@@ -77,7 +75,6 @@
   }
 
   // Overridden from View:
-  const char* GetClassName() const override;
   gfx::Size CalculatePreferredSize() const override;
   views::PaintInfo::ScaleType GetPaintScaleType() const override;
 
diff --git a/ui/views/controls/button/label_button.cc b/ui/views/controls/button/label_button.cc
index 90e6f9e1..e5a9620 100644
--- a/ui/views/controls/button/label_button.cc
+++ b/ui/views/controls/button/label_button.cc
@@ -29,9 +29,6 @@
 
 namespace views {
 
-// static
-const char LabelButton::kViewClassName[] = "LabelButton";
-
 LabelButton::LabelButton(ButtonListener* listener,
                          const base::string16& text,
                          int button_context)
@@ -295,10 +292,6 @@
   Button::Layout();
 }
 
-const char* LabelButton::GetClassName() const {
-  return kViewClassName;
-}
-
 void LabelButton::EnableCanvasFlippingForRTLUI(bool flip) {
   Button::EnableCanvasFlippingForRTLUI(flip);
   image_->EnableCanvasFlippingForRTLUI(flip);
diff --git a/ui/views/controls/button/label_button.h b/ui/views/controls/button/label_button.h
index 93538c10..c183274e 100644
--- a/ui/views/controls/button/label_button.h
+++ b/ui/views/controls/button/label_button.h
@@ -31,8 +31,6 @@
  public:
   METADATA_HEADER(LabelButton);
 
-  static const char kViewClassName[];
-
   // Creates a LabelButton with ButtonPressed() events sent to |listener| and
   // label |text|. |button_context| is a value from views::style::TextContext
   // and determines the appearance of |text|.
@@ -93,7 +91,6 @@
   gfx::Size CalculatePreferredSize() const override;
   int GetHeightForWidth(int w) const override;
   void Layout() override;
-  const char* GetClassName() const override;
   void EnableCanvasFlippingForRTLUI(bool flip) override;
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
   void AddLayerBeneathView(ui::Layer* new_layer) override;
diff --git a/ui/views/controls/button/menu_button.cc b/ui/views/controls/button/menu_button.cc
index 32bf07c7..895da043 100644
--- a/ui/views/controls/button/menu_button.cc
+++ b/ui/views/controls/button/menu_button.cc
@@ -11,8 +11,6 @@
 #include "ui/views/controls/button/menu_button_controller.h"
 
 namespace views {
-// static
-const char MenuButton::kViewClassName[] = "MenuButton";
 
 MenuButton::MenuButton(const base::string16& text,
                        MenuButtonListener* menu_button_listener,
@@ -35,14 +33,14 @@
   return button_controller()->IsTriggerableEventType(event);
 }
 
-const char* MenuButton::GetClassName() const {
-  return kViewClassName;
-}
-
 void MenuButton::NotifyClick(const ui::Event& event) {
   // Notify MenuButtonListener via MenuButtonController, instead of
   // ButtonListener::ButtonPressed.
   button_controller()->Activate(&event);
 }
 
+BEGIN_METADATA(MenuButton)
+METADATA_PARENT_CLASS(LabelButton)
+END_METADATA()
+
 }  // namespace views
diff --git a/ui/views/controls/button/menu_button.h b/ui/views/controls/button/menu_button.h
index 61423f0..71afb70f 100644
--- a/ui/views/controls/button/menu_button.h
+++ b/ui/views/controls/button/menu_button.h
@@ -23,7 +23,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 class VIEWS_EXPORT MenuButton : public LabelButton {
  public:
-  static const char kViewClassName[];
+  METADATA_HEADER(MenuButton);
 
   // How much padding to put on the left and right of the menu marker.
   static constexpr int kMenuMarkerPaddingLeft = 3;
@@ -44,9 +44,6 @@
   // TODO(cyan): Remove this method and move into MenuButtonController.
   virtual bool IsTriggerableEventType(const ui::Event& event);
 
-  // View:
-  const char* GetClassName() const override;
-
  protected:
   // Button:
   void NotifyClick(const ui::Event& event) final;
diff --git a/ui/views/controls/button/radio_button.cc b/ui/views/controls/button/radio_button.cc
index e7189a592..975862f 100644
--- a/ui/views/controls/button/radio_button.cc
+++ b/ui/views/controls/button/radio_button.cc
@@ -16,9 +16,6 @@
 
 namespace views {
 
-// static
-const char RadioButton::kViewClassName[] = "RadioButton";
-
 RadioButton::RadioButton(const base::string16& label, int group_id)
     : Checkbox(label, nullptr) {
   SetGroup(group_id);
@@ -26,10 +23,6 @@
 
 RadioButton::~RadioButton() = default;
 
-const char* RadioButton::GetClassName() const {
-  return kViewClassName;
-}
-
 void RadioButton::GetAccessibleNodeData(ui::AXNodeData* node_data) {
   Checkbox::GetAccessibleNodeData(node_data);
   node_data->role = ax::mojom::Role::kRadioButton;
@@ -114,4 +107,8 @@
     parent()->GetViewsInGroup(group, views);
 }
 
+BEGIN_METADATA(RadioButton)
+METADATA_PARENT_CLASS(Checkbox)
+END_METADATA()
+
 }  // namespace views
diff --git a/ui/views/controls/button/radio_button.h b/ui/views/controls/button/radio_button.h
index eda57860..3bb6d4a5 100644
--- a/ui/views/controls/button/radio_button.h
+++ b/ui/views/controls/button/radio_button.h
@@ -16,14 +16,12 @@
 // platform specific objects to replicate the native platforms looks and feel.
 class VIEWS_EXPORT RadioButton : public Checkbox {
  public:
-  // The button's class name.
-  static const char kViewClassName[];
+  METADATA_HEADER(RadioButton);
 
   RadioButton(const base::string16& label, int group_id);
   ~RadioButton() override;
 
   // Overridden from View:
-  const char* GetClassName() const override;
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
   View* GetSelectedViewForGroup(int group) override;
   bool IsGroupFocusTraversable() const override;
diff --git a/ui/views/controls/button/toggle_button.cc b/ui/views/controls/button/toggle_button.cc
index 57a0eaf..5e6f4a4 100644
--- a/ui/views/controls/button/toggle_button.cc
+++ b/ui/views/controls/button/toggle_button.cc
@@ -67,9 +67,6 @@
   static constexpr int kShadowBlur = 2;
 
   // views::View:
-  const char* GetClassName() const override {
-    return "ToggleButton::ThumbView";
-  }
 
   void OnPaint(gfx::Canvas* canvas) override {
     const float dsf = canvas->UndoDeviceScaleFactor();
@@ -111,9 +108,6 @@
   DISALLOW_COPY_AND_ASSIGN(ThumbView);
 };
 
-// static
-const char ToggleButton::kViewClassName[] = "ToggleButton";
-
 ToggleButton::ToggleButton(ButtonListener* listener) : Button(listener) {
   slide_animation_.SetSlideDuration(80 /* ms */);
   slide_animation_.SetTweenType(gfx::Tween::LINEAR);
@@ -200,10 +194,6 @@
   return SkColorSetA(GetNativeTheme()->GetSystemColor(color_id), kTrackAlpha);
 }
 
-const char* ToggleButton::GetClassName() const {
-  return kViewClassName;
-}
-
 bool ToggleButton::CanAcceptEvent(const ui::Event& event) {
   return GetAcceptsEvents() && Button::CanAcceptEvent(event);
 }
diff --git a/ui/views/controls/button/toggle_button.h b/ui/views/controls/button/toggle_button.h
index e8b77da..54fa757 100644
--- a/ui/views/controls/button/toggle_button.h
+++ b/ui/views/controls/button/toggle_button.h
@@ -17,8 +17,6 @@
  public:
   METADATA_HEADER(ToggleButton);
 
-  static const char kViewClassName[];
-
   explicit ToggleButton(ButtonListener* listener);
   ~ToggleButton() override;
 
@@ -49,7 +47,6 @@
   SkColor GetTrackColor(bool is_on) const;
 
   // views::View:
-  const char* GetClassName() const override;
   bool CanAcceptEvent(const ui::Event& event) override;
   void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
   void OnThemeChanged() override;
diff --git a/ui/views/controls/combobox/combobox.cc b/ui/views/controls/combobox/combobox.cc
index 107b9e7a..caf05ca 100644
--- a/ui/views/controls/combobox/combobox.cc
+++ b/ui/views/controls/combobox/combobox.cc
@@ -117,9 +117,6 @@
 
 }  // namespace
 
-// static
-const char Combobox::kViewClassName[] = "views/Combobox";
-
 // Adapts a ui::ComboboxModel to a ui::MenuModel.
 class Combobox::ComboboxMenuModel : public ui::MenuModel {
  public:
@@ -358,10 +355,6 @@
   return gfx::Size(total_width, content_size_.height() + insets.height());
 }
 
-const char* Combobox::GetClassName() const {
-  return kViewClassName;
-}
-
 bool Combobox::SkipDefaultKeyEventProcessing(const ui::KeyEvent& e) {
   // Escape should close the drop down list when it is active, not host UI.
   if (e.key_code() != ui::VKEY_ESCAPE ||
diff --git a/ui/views/controls/combobox/combobox.h b/ui/views/controls/combobox/combobox.h
index de84ae9..2377176 100644
--- a/ui/views/controls/combobox/combobox.h
+++ b/ui/views/controls/combobox/combobox.h
@@ -41,8 +41,6 @@
  public:
   METADATA_HEADER(Combobox);
 
-  // The combobox's class name.
-  static const char kViewClassName[];
   static constexpr int kDefaultComboboxTextContext = style::CONTEXT_BUTTON;
   static constexpr int kDefaultComboboxTextStyle = style::STYLE_PRIMARY;
 
@@ -86,7 +84,6 @@
 
   // Overridden from View:
   gfx::Size CalculatePreferredSize() const override;
-  const char* GetClassName() const override;
   bool SkipDefaultKeyEventProcessing(const ui::KeyEvent& e) override;
   bool OnKeyPressed(const ui::KeyEvent& e) override;
   void OnPaint(gfx::Canvas* canvas) override;
diff --git a/ui/views/controls/editable_combobox/editable_combobox.cc b/ui/views/controls/editable_combobox/editable_combobox.cc
index 56ba44e..410cb92 100644
--- a/ui/views/controls/editable_combobox/editable_combobox.cc
+++ b/ui/views/controls/editable_combobox/editable_combobox.cc
@@ -110,9 +110,6 @@
 
 }  // namespace
 
-// static
-const char EditableCombobox::kViewClassName[] = "EditableCombobox";
-
 // Adapts a ui::ComboboxModel to a ui::MenuModel to be used by EditableCombobox.
 // Also provides a filtering capability.
 class EditableCombobox::EditableComboboxMenuModel
@@ -346,10 +343,6 @@
 ////////////////////////////////////////////////////////////////////////////////
 // EditableCombobox, View overrides:
 
-const char* EditableCombobox::GetClassName() const {
-  return kViewClassName;
-}
-
 void EditableCombobox::Layout() {
   View::Layout();
   if (arrow_) {
@@ -492,4 +485,8 @@
                           MenuAnchorPosition::kTopLeft, source_type);
 }
 
+BEGIN_METADATA(EditableCombobox)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
 }  // namespace views
diff --git a/ui/views/controls/editable_combobox/editable_combobox.h b/ui/views/controls/editable_combobox/editable_combobox.h
index e1491c5..c0f59314 100644
--- a/ui/views/controls/editable_combobox/editable_combobox.h
+++ b/ui/views/controls/editable_combobox/editable_combobox.h
@@ -40,13 +40,13 @@
                                       public ViewObserver,
                                       public ButtonListener {
  public:
+  METADATA_HEADER(EditableCombobox);
+
   enum class Type {
     kRegular,
     kPassword,
   };
 
-  // The class name.
-  static const char kViewClassName[];
   static constexpr int kDefaultTextContext = style::CONTEXT_BUTTON;
   static constexpr int kDefaultTextStyle = style::STYLE_PRIMARY;
 
@@ -117,7 +117,6 @@
   void ShowDropDownMenu(ui::MenuSourceType source_type = ui::MENU_SOURCE_NONE);
 
   // Overridden from View:
-  const char* GetClassName() const override;
   void Layout() override;
   void OnThemeChanged() override;
 
diff --git a/ui/views/controls/focus_ring.cc b/ui/views/controls/focus_ring.cc
index 95c79c9..31f5a88 100644
--- a/ui/views/controls/focus_ring.cc
+++ b/ui/views/controls/focus_ring.cc
@@ -25,8 +25,6 @@
 
 }  // namespace
 
-const char FocusRing::kViewClassName[] = "FocusRing";
-
 // static
 std::unique_ptr<FocusRing> FocusRing::Install(View* parent) {
   auto ring = base::WrapUnique<FocusRing>(new FocusRing());
@@ -63,10 +61,6 @@
   SchedulePaint();
 }
 
-const char* FocusRing::GetClassName() const {
-  return kViewClassName;
-}
-
 void FocusRing::Layout() {
   // The focus ring handles its own sizing, which is simply to fill the parent
   // and extend a little beyond its borders.
@@ -179,4 +173,8 @@
   return path;
 }
 
+BEGIN_METADATA(FocusRing)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
 }  // namespace views
diff --git a/ui/views/controls/focus_ring.h b/ui/views/controls/focus_ring.h
index f5e22f6..561e8ec 100644
--- a/ui/views/controls/focus_ring.h
+++ b/ui/views/controls/focus_ring.h
@@ -37,7 +37,7 @@
 // these take care of repainting it when the state changes.
 class VIEWS_EXPORT FocusRing : public View, public ViewObserver {
  public:
-  static const char kViewClassName[];
+  METADATA_HEADER(FocusRing);
 
   using ViewPredicate = std::function<bool(View* view)>;
 
@@ -77,7 +77,6 @@
   void SetColor(base::Optional<SkColor> color);
 
   // View:
-  const char* GetClassName() const override;
   void Layout() override;
   void ViewHierarchyChanged(
       const ViewHierarchyChangedDetails& details) override;
diff --git a/ui/views/controls/image_view.cc b/ui/views/controls/image_view.cc
index 2e9c406..8ca173c 100644
--- a/ui/views/controls/image_view.cc
+++ b/ui/views/controls/image_view.cc
@@ -23,9 +23,6 @@
 
 }  // namespace
 
-// static
-const char ImageView::kViewClassName[] = "ImageView";
-
 ImageView::ImageView() = default;
 
 ImageView::~ImageView() = default;
@@ -76,10 +73,6 @@
   OnPaintImage(canvas);
 }
 
-const char* ImageView::GetClassName() const {
-  return kViewClassName;
-}
-
 void ImageView::OnPaintImage(gfx::Canvas* canvas) {
   last_paint_scale_ = canvas->image_scale();
   last_painted_bitmap_pixels_ = nullptr;
@@ -130,4 +123,8 @@
   return scaled_image_;
 }
 
+BEGIN_METADATA(ImageView)
+METADATA_PARENT_CLASS(ImageViewBase)
+END_METADATA()
+
 }  // namespace views
diff --git a/ui/views/controls/image_view.h b/ui/views/controls/image_view.h
index e80a97a..0df833d 100644
--- a/ui/views/controls/image_view.h
+++ b/ui/views/controls/image_view.h
@@ -27,8 +27,7 @@
 /////////////////////////////////////////////////////////////////////////////
 class VIEWS_EXPORT ImageView : public ImageViewBase {
  public:
-  // Internal class name.
-  static const char kViewClassName[];
+  METADATA_HEADER(ImageView);
 
   ImageView();
   ~ImageView() override;
@@ -47,7 +46,6 @@
 
   // Overridden from View:
   void OnPaint(gfx::Canvas* canvas) override;
-  const char* GetClassName() const override;
 
  protected:
   // Overridden from ImageViewBase:
diff --git a/ui/views/controls/image_view_base.h b/ui/views/controls/image_view_base.h
index 3784c9c..e8bc0b2 100644
--- a/ui/views/controls/image_view_base.h
+++ b/ui/views/controls/image_view_base.h
@@ -53,7 +53,6 @@
   // Overridden from View:
   void OnPaint(gfx::Canvas* canvas) override = 0;
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
-  const char* GetClassName() const override = 0;
   base::string16 GetTooltipText(const gfx::Point& p) const override;
   gfx::Size CalculatePreferredSize() const override;
   views::PaintInfo::ScaleType GetPaintScaleType() const override;
diff --git a/ui/views/controls/label.cc b/ui/views/controls/label.cc
index 24d08c79..29635eab 100644
--- a/ui/views/controls/label.cc
+++ b/ui/views/controls/label.cc
@@ -44,8 +44,6 @@
 
 namespace views {
 
-const char Label::kViewClassName[] = "Label";
-
 Label::Label() : Label(base::string16()) {
 }
 
@@ -379,10 +377,6 @@
   ClearDisplayText();
 }
 
-const char* Label::GetClassName() const {
-  return kViewClassName;
-}
-
 View* Label::GetTooltipHandlerForPoint(const gfx::Point& point) {
   if (!handles_tooltips_ ||
       (tooltip_text_.empty() && !ShouldShowDefaultTooltip()))
@@ -970,4 +964,8 @@
                                              IDS_APP_SELECT_ALL);
 }
 
+BEGIN_METADATA(Label)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
 }  // namespace views
diff --git a/ui/views/controls/label.h b/ui/views/controls/label.h
index 50e30e5..4d9c4a4 100644
--- a/ui/views/controls/label.h
+++ b/ui/views/controls/label.h
@@ -14,6 +14,7 @@
 #include "ui/gfx/render_text.h"
 #include "ui/gfx/text_constants.h"
 #include "ui/views/context_menu_controller.h"
+#include "ui/views/metadata/metadata_header_macros.h"
 #include "ui/views/selection_controller_delegate.h"
 #include "ui/views/style/typography.h"
 #include "ui/views/view.h"
@@ -31,8 +32,7 @@
                            public SelectionControllerDelegate,
                            public ui::SimpleMenuModel::Delegate {
  public:
-  // Internal class name.
-  static const char kViewClassName[];
+  METADATA_HEADER(Label);
 
   // Helper to construct a Label that doesn't use the views typography spec.
   // Using this causes Label to obtain colors from ui::NativeTheme and line
@@ -230,7 +230,6 @@
   gfx::Size GetMinimumSize() const override;
   int GetHeightForWidth(int w) const override;
   void Layout() override;
-  const char* GetClassName() const override;
   View* GetTooltipHandlerForPoint(const gfx::Point& point) override;
   bool CanProcessEventsWithinSubtree() const override;
   WordLookupClient* GetWordLookupClient() override;
diff --git a/ui/views/controls/link.cc b/ui/views/controls/link.cc
index 476a77af1..33e40630 100644
--- a/ui/views/controls/link.cc
+++ b/ui/views/controls/link.cc
@@ -23,7 +23,6 @@
 
 namespace views {
 
-const char Link::kViewClassName[] = "Link";
 constexpr int Link::kFocusBorderPadding;
 
 Link::Link(const base::string16& title, int text_context, int text_style)
@@ -67,10 +66,6 @@
   return insets;
 }
 
-const char* Link::GetClassName() const {
-  return kViewClassName;
-}
-
 gfx::NativeCursor Link::GetCursor(const ui::MouseEvent& event) {
   if (!GetEnabled())
     return gfx::kNullCursor;
@@ -279,4 +274,8 @@
                : ui::NativeTheme::kColorId_LinkEnabled);
 }
 
+BEGIN_METADATA(Link)
+METADATA_PARENT_CLASS(Label)
+END_METADATA()
+
 }  // namespace views
diff --git a/ui/views/controls/link.h b/ui/views/controls/link.h
index 3379ee9..8f4f6af9 100644
--- a/ui/views/controls/link.h
+++ b/ui/views/controls/link.h
@@ -26,7 +26,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 class VIEWS_EXPORT Link : public Label {
  public:
-  static const char kViewClassName[];
+  METADATA_HEADER(Link);
 
   // The padding for the focus ring border when rendering a focused Link with
   // FocusStyle::RING.
@@ -56,7 +56,6 @@
   // Label:
   void PaintFocusRing(gfx::Canvas* canvas) const override;
   gfx::Insets GetInsets() const override;
-  const char* GetClassName() const override;
   gfx::NativeCursor GetCursor(const ui::MouseEvent& event) override;
   bool CanProcessEventsWithinSubtree() const override;
   bool OnMousePressed(const ui::MouseEvent& event) override;
diff --git a/ui/views/controls/menu/menu_item_view.cc b/ui/views/controls/menu/menu_item_view.cc
index 1e27d88..abb9d1a 100644
--- a/ui/views/controls/menu/menu_item_view.cc
+++ b/ui/views/controls/menu/menu_item_view.cc
@@ -98,9 +98,6 @@
 // static
 int MenuItemView::pref_menu_height_;
 
-// static
-const char MenuItemView::kViewClassName[] = "MenuItemView";
-
 MenuItemView::MenuItemView(MenuDelegate* delegate)
     : delegate_(delegate),
       controller_(nullptr),
@@ -765,10 +762,6 @@
     delete item;
 }
 
-const char* MenuItemView::GetClassName() const {
-  return kViewClassName;
-}
-
 // Calculates all sizes that we can from the OS.
 //
 // This is invoked prior to Running a menu.
@@ -1405,4 +1398,8 @@
       [](const auto* item) { return item->HasChecksOrRadioButtons(); });
 }
 
+BEGIN_METADATA(MenuItemView)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
 }  // namespace views
diff --git a/ui/views/controls/menu/menu_item_view.h b/ui/views/controls/menu/menu_item_view.h
index 6d22433..690d667 100644
--- a/ui/views/controls/menu/menu_item_view.h
+++ b/ui/views/controls/menu/menu_item_view.h
@@ -74,10 +74,9 @@
 
 class VIEWS_EXPORT MenuItemView : public View {
  public:
-  friend class MenuController;
+  METADATA_HEADER(MenuItemView);
 
-  // The menu item view's class name.
-  static const char kViewClassName[];
+  friend class MenuController;
 
   // ID used to identify menu items.
   static const int kMenuItemViewID;
@@ -384,7 +383,6 @@
 
   // View:
   void ChildPreferredSizeChanged(View* child) override;
-  const char* GetClassName() const override;
 
   // Returns the preferred size (and padding) of any children.
   virtual gfx::Size GetChildPreferredSize() const;
diff --git a/ui/views/controls/menu/menu_scroll_view_container.cc b/ui/views/controls/menu/menu_scroll_view_container.cc
index 7ae246a..3e7c6460 100644
--- a/ui/views/controls/menu/menu_scroll_view_container.cc
+++ b/ui/views/controls/menu/menu_scroll_view_container.cc
@@ -358,4 +358,8 @@
   }
 }
 
+BEGIN_METADATA(MenuScrollViewContainer)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
 }  // namespace views
diff --git a/ui/views/controls/menu/menu_scroll_view_container.h b/ui/views/controls/menu/menu_scroll_view_container.h
index 24f0196..6dbb6b9d 100644
--- a/ui/views/controls/menu/menu_scroll_view_container.h
+++ b/ui/views/controls/menu/menu_scroll_view_container.h
@@ -20,6 +20,8 @@
 // the preferred height of the SubmenuView is bigger than our bounds.
 class MenuScrollViewContainer : public View {
  public:
+  METADATA_HEADER(MenuScrollViewContainer);
+
   explicit MenuScrollViewContainer(SubmenuView* content_view);
 
   // Returns the buttons for scrolling up/down.
diff --git a/ui/views/controls/menu/menu_separator.cc b/ui/views/controls/menu/menu_separator.cc
index aa27d3c..b48d8091 100644
--- a/ui/views/controls/menu/menu_separator.cc
+++ b/ui/views/controls/menu/menu_separator.cc
@@ -88,4 +88,8 @@
                    height);
 }
 
+BEGIN_METADATA(MenuSeparator)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
 }  // namespace views
diff --git a/ui/views/controls/menu/menu_separator.h b/ui/views/controls/menu/menu_separator.h
index 4e91f17..a331914 100644
--- a/ui/views/controls/menu/menu_separator.h
+++ b/ui/views/controls/menu/menu_separator.h
@@ -15,6 +15,8 @@
 
 class VIEWS_EXPORT MenuSeparator : public View {
  public:
+  METADATA_HEADER(MenuSeparator);
+
   explicit MenuSeparator(ui::MenuSeparatorType type) : type_(type) {}
 
   // View overrides.
diff --git a/ui/views/controls/menu/submenu_view.cc b/ui/views/controls/menu/submenu_view.cc
index caa47b1..0713d6e2 100644
--- a/ui/views/controls/menu/submenu_view.cc
+++ b/ui/views/controls/menu/submenu_view.cc
@@ -34,9 +34,6 @@
 
 namespace views {
 
-// static
-const char SubmenuView::kViewClassName[] = "SubmenuView";
-
 SubmenuView::SubmenuView(MenuItemView* parent)
     : parent_menu_item_(parent),
       host_(nullptr),
@@ -482,10 +479,6 @@
     controller->Cancel(MenuController::ExitType::kDestroyed);
 }
 
-const char* SubmenuView::GetClassName() const {
-  return kViewClassName;
-}
-
 void SubmenuView::OnBoundsChanged(const gfx::Rect& previous_bounds) {
   SchedulePaint();
 }
@@ -543,4 +536,8 @@
   return false;
 }
 
+BEGIN_METADATA(SubmenuView)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
 }  // namespace views
diff --git a/ui/views/controls/menu/submenu_view.h b/ui/views/controls/menu/submenu_view.h
index 3009bd4..84ecd3c 100644
--- a/ui/views/controls/menu/submenu_view.h
+++ b/ui/views/controls/menu/submenu_view.h
@@ -44,10 +44,9 @@
                                  public PrefixDelegate,
                                  public ScrollDelegate {
  public:
-  using MenuItems = std::vector<MenuItemView*>;
+  METADATA_HEADER(SubmenuView);
 
-  // The submenu's class name.
-  static const char kViewClassName[];
+  using MenuItems = std::vector<MenuItemView*>;
 
   // Creates a SubmenuView for the specified menu item.
   explicit SubmenuView(MenuItemView* parent);
@@ -172,8 +171,6 @@
   }
 
  protected:
-  // Overridden from View:
-  const char* GetClassName() const override;
 
   // View method. Overridden to schedule a paint. We do this so that when
   // scrolling occurs, everything is repainted correctly.
diff --git a/ui/views/controls/message_box_view.cc b/ui/views/controls/message_box_view.cc
index 73b3997b..20217e8 100644
--- a/ui/views/controls/message_box_view.cc
+++ b/ui/views/controls/message_box_view.cc
@@ -72,9 +72,6 @@
 ///////////////////////////////////////////////////////////////////////////////
 // MessageBoxView, public:
 
-// static
-const char MessageBoxView::kViewClassName[] = "MessageBoxView";
-
 MessageBoxView::InitParams::InitParams(const base::string16& message)
     : options(NO_OPTIONS),
       message(message),
@@ -178,10 +175,6 @@
   return true;
 }
 
-const char* MessageBoxView::GetClassName() const {
-  return kViewClassName;
-}
-
 ///////////////////////////////////////////////////////////////////////////////
 // MessageBoxView, private:
 
@@ -303,4 +296,8 @@
   return horizontal_insets;
 }
 
+BEGIN_METADATA(MessageBoxView)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
 }  // namespace views
diff --git a/ui/views/controls/message_box_view.h b/ui/views/controls/message_box_view.h
index 48262a5..214bf73f 100644
--- a/ui/views/controls/message_box_view.h
+++ b/ui/views/controls/message_box_view.h
@@ -29,8 +29,7 @@
 // and Cancel buttons.
 class VIEWS_EXPORT MessageBoxView : public View {
  public:
-  // Internal class name.
-  static const char kViewClassName[];
+  METADATA_HEADER(MessageBoxView);
 
   enum Options {
     NO_OPTIONS = 0,
@@ -94,7 +93,6 @@
       const ViewHierarchyChangedDetails& details) override;
   // Handles Ctrl-C and writes the message in the system clipboard.
   bool AcceleratorPressed(const ui::Accelerator& accelerator) override;
-  const char* GetClassName() const override;
 
  private:
   // Sets up the layout manager and initializes the message labels and prompt
diff --git a/ui/views/controls/native/native_view_host.cc b/ui/views/controls/native/native_view_host.cc
index 9d2c42e2..d6116fd 100644
--- a/ui/views/controls/native/native_view_host.cc
+++ b/ui/views/controls/native/native_view_host.cc
@@ -14,7 +14,6 @@
 namespace views {
 
 // static
-const char NativeViewHost::kViewClassName[] = "NativeViewHost";
 const char kWidgetNativeViewHostKey[] = "WidgetNativeViewHost";
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -195,10 +194,6 @@
   }
 }
 
-const char* NativeViewHost::GetClassName() const {
-  return kViewClassName;
-}
-
 void NativeViewHost::OnFocus() {
   if (native_view_)
     native_wrapper_->SetFocus();
@@ -256,4 +251,8 @@
   }
 }
 
+BEGIN_METADATA(NativeViewHost)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
 }  // namespace views
diff --git a/ui/views/controls/native/native_view_host.h b/ui/views/controls/native/native_view_host.h
index c643413..2a6cfc54 100644
--- a/ui/views/controls/native/native_view_host.h
+++ b/ui/views/controls/native/native_view_host.h
@@ -28,8 +28,7 @@
 // the platform-specific work of manipulating the underlying OS widget type.
 class VIEWS_EXPORT NativeViewHost : public View {
  public:
-  // The NativeViewHost's class name.
-  static const char kViewClassName[];
+  METADATA_HEADER(NativeViewHost);
 
   NativeViewHost();
   ~NativeViewHost() override;
@@ -104,7 +103,6 @@
   void OnVisibleBoundsChanged() override;
   void ViewHierarchyChanged(
       const ViewHierarchyChangedDetails& details) override;
-  const char* GetClassName() const override;
 
  private:
   friend class test::NativeViewHostTestBase;
diff --git a/ui/views/controls/progress_bar.cc b/ui/views/controls/progress_bar.cc
index deb1d931..e37b7c9 100644
--- a/ui/views/controls/progress_bar.cc
+++ b/ui/views/controls/progress_bar.cc
@@ -42,9 +42,6 @@
 
 }  // namespace
 
-// static
-const char ProgressBar::kViewClassName[] = "ProgressBar";
-
 ProgressBar::ProgressBar(int preferred_height, bool allow_round_corner)
     : preferred_height_(preferred_height),
       allow_round_corner_(allow_round_corner) {
@@ -65,10 +62,6 @@
   return pref_size;
 }
 
-const char* ProgressBar::GetClassName() const {
-  return kViewClassName;
-}
-
 void ProgressBar::OnPaint(gfx::Canvas* canvas) {
   if (IsIndeterminate())
     return OnPaintIndeterminate(canvas);
@@ -212,4 +205,8 @@
   canvas->DrawPath(slice_path, slice_flags);
 }
 
+BEGIN_METADATA(ProgressBar)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
 }  // namespace views
diff --git a/ui/views/controls/progress_bar.h b/ui/views/controls/progress_bar.h
index 58909de1..131451fb 100644
--- a/ui/views/controls/progress_bar.h
+++ b/ui/views/controls/progress_bar.h
@@ -20,6 +20,8 @@
 // Progress bar is a control that indicates progress visually.
 class VIEWS_EXPORT ProgressBar : public View, public gfx::AnimationDelegate {
  public:
+  METADATA_HEADER(ProgressBar);
+
   // The preferred height parameter makes it easier to use a ProgressBar with
   // layout managers that size to preferred size.
   explicit ProgressBar(int preferred_height = 5,
@@ -29,7 +31,6 @@
   // Overridden from View:
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
   gfx::Size CalculatePreferredSize() const override;
-  const char* GetClassName() const override;
   void OnPaint(gfx::Canvas* canvas) override;
 
   double current_value() const { return current_value_; }
@@ -49,8 +50,6 @@
   int preferred_height() const { return preferred_height_; }
 
  private:
-  static const char kViewClassName[];
-
   // gfx::AnimationDelegate:
   void AnimationProgressed(const gfx::Animation* animation) override;
   void AnimationEnded(const gfx::Animation* animation) override;
diff --git a/ui/views/controls/resize_area.cc b/ui/views/controls/resize_area.cc
index 51c8f95..e0045d3 100644
--- a/ui/views/controls/resize_area.cc
+++ b/ui/views/controls/resize_area.cc
@@ -12,8 +12,6 @@
 
 namespace views {
 
-const char ResizeArea::kViewClassName[] = "ResizeArea";
-
 ResizeArea::ResizeArea(ResizeAreaDelegate* delegate)
     : delegate_(delegate),
       initial_position_(0) {
@@ -21,10 +19,6 @@
 
 ResizeArea::~ResizeArea() = default;
 
-const char* ResizeArea::GetClassName() const {
-  return kViewClassName;
-}
-
 gfx::NativeCursor ResizeArea::GetCursor(const ui::MouseEvent& event) {
   return GetEnabled() ? GetNativeEastWestResizeCursor() : gfx::kNullCursor;
 }
@@ -85,4 +79,8 @@
   initial_position_ = point.x();
 }
 
+BEGIN_METADATA(ResizeArea)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
 }  // namespace views
diff --git a/ui/views/controls/resize_area.h b/ui/views/controls/resize_area.h
index 31dc6e3..77567910 100644
--- a/ui/views/controls/resize_area.h
+++ b/ui/views/controls/resize_area.h
@@ -17,13 +17,12 @@
 // An invisible area that acts like a horizontal resizer.
 class VIEWS_EXPORT ResizeArea : public View {
  public:
-  static const char kViewClassName[];
+  METADATA_HEADER(ResizeArea);
 
   explicit ResizeArea(ResizeAreaDelegate* delegate);
   ~ResizeArea() override;
 
   // views::View:
-  const char* GetClassName() const override;
   gfx::NativeCursor GetCursor(const ui::MouseEvent& event) override;
   void OnGestureEvent(ui::GestureEvent* event) override;
   bool OnMousePressed(const ui::MouseEvent& event) override;
diff --git a/ui/views/controls/scroll_view.cc b/ui/views/controls/scroll_view.cc
index a773958..494d79a0 100644
--- a/ui/views/controls/scroll_view.cc
+++ b/ui/views/controls/scroll_view.cc
@@ -24,8 +24,6 @@
 
 namespace views {
 
-const char ScrollView::kViewClassName[] = "ScrollView";
-
 namespace {
 
 class ScrollCornerView : public View {
@@ -114,8 +112,6 @@
   explicit Viewport(ScrollView* scroll_view) : scroll_view_(scroll_view) {}
   ~Viewport() override = default;
 
-  const char* GetClassName() const override { return "ScrollView::Viewport"; }
-
   void ScrollRectToVisible(const gfx::Rect& rect) override {
     if (children().empty() || !parent())
       return;
@@ -623,10 +619,6 @@
   }
 }
 
-const char* ScrollView::GetClassName() const {
-  return kViewClassName;
-}
-
 void ScrollView::OnThemeChanged() {
   UpdateBorder();
   if (use_color_id_)
@@ -953,6 +945,10 @@
           offset.x() < horiz_sb_->GetMaxPosition() && draw_overflow_indicator_);
 }
 
+BEGIN_METADATA(ScrollView)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
 // VariableRowHeightScrollHelper ----------------------------------------------
 
 VariableRowHeightScrollHelper::VariableRowHeightScrollHelper(
diff --git a/ui/views/controls/scroll_view.h b/ui/views/controls/scroll_view.h
index e83fd36..c26cbc3 100644
--- a/ui/views/controls/scroll_view.h
+++ b/ui/views/controls/scroll_view.h
@@ -43,7 +43,7 @@
 
 class VIEWS_EXPORT ScrollView : public View, public ScrollBarController {
  public:
-  static const char kViewClassName[];
+  METADATA_HEADER(ScrollView);
 
   ScrollView();
 
@@ -130,7 +130,6 @@
   bool OnMouseWheel(const ui::MouseWheelEvent& e) override;
   void OnScrollEvent(ui::ScrollEvent* event) override;
   void OnGestureEvent(ui::GestureEvent* event) override;
-  const char* GetClassName() const override;
   void OnThemeChanged() override;
 
   // ScrollBarController overrides:
diff --git a/ui/views/controls/scrollbar/base_scroll_bar_button.cc b/ui/views/controls/scrollbar/base_scroll_bar_button.cc
index d9adbdd..122d1c1 100644
--- a/ui/views/controls/scrollbar/base_scroll_bar_button.cc
+++ b/ui/views/controls/scrollbar/base_scroll_bar_button.cc
@@ -42,4 +42,8 @@
   Button::NotifyClick(event);
 }
 
+BEGIN_METADATA(BaseScrollBarButton)
+METADATA_PARENT_CLASS(Button)
+END_METADATA()
+
 }  // namespace views
diff --git a/ui/views/controls/scrollbar/base_scroll_bar_button.h b/ui/views/controls/scrollbar/base_scroll_bar_button.h
index 245d60f0..052f5f1 100644
--- a/ui/views/controls/scrollbar/base_scroll_bar_button.h
+++ b/ui/views/controls/scrollbar/base_scroll_bar_button.h
@@ -24,6 +24,8 @@
 ///////////////////////////////////////////////////////////////////////////////
 class VIEWS_EXPORT BaseScrollBarButton : public Button {
  public:
+  METADATA_HEADER(BaseScrollBarButton);
+
   explicit BaseScrollBarButton(ButtonListener* listener);
   ~BaseScrollBarButton() override;
 
diff --git a/ui/views/controls/scrollbar/base_scroll_bar_thumb.cc b/ui/views/controls/scrollbar/base_scroll_bar_thumb.cc
index f6f78dbd..3221a12a 100644
--- a/ui/views/controls/scrollbar/base_scroll_bar_thumb.cc
+++ b/ui/views/controls/scrollbar/base_scroll_bar_thumb.cc
@@ -130,4 +130,8 @@
   return scroll_bar_->IsHorizontal();
 }
 
+BEGIN_METADATA(BaseScrollBarThumb)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
 }  // namespace views
diff --git a/ui/views/controls/scrollbar/base_scroll_bar_thumb.h b/ui/views/controls/scrollbar/base_scroll_bar_thumb.h
index a8f29da..e43da46 100644
--- a/ui/views/controls/scrollbar/base_scroll_bar_thumb.h
+++ b/ui/views/controls/scrollbar/base_scroll_bar_thumb.h
@@ -29,6 +29,8 @@
 ///////////////////////////////////////////////////////////////////////////////
 class VIEWS_EXPORT BaseScrollBarThumb : public View {
  public:
+  METADATA_HEADER(BaseScrollBarThumb);
+
   explicit BaseScrollBarThumb(ScrollBar* scroll_bar);
   ~BaseScrollBarThumb() override;
 
diff --git a/ui/views/controls/scrollbar/cocoa_scroll_bar.h b/ui/views/controls/scrollbar/cocoa_scroll_bar.h
index a839959..42c1d11 100644
--- a/ui/views/controls/scrollbar/cocoa_scroll_bar.h
+++ b/ui/views/controls/scrollbar/cocoa_scroll_bar.h
@@ -24,6 +24,8 @@
                                     public ui::ImplicitAnimationObserver,
                                     public gfx::AnimationDelegate {
  public:
+  METADATA_HEADER(CocoaScrollBar);
+
   explicit CocoaScrollBar(bool horizontal);
   ~CocoaScrollBar() override;
 
diff --git a/ui/views/controls/scrollbar/cocoa_scroll_bar.mm b/ui/views/controls/scrollbar/cocoa_scroll_bar.mm
index a3cc7582..8d59d89 100644
--- a/ui/views/controls/scrollbar/cocoa_scroll_bar.mm
+++ b/ui/views/controls/scrollbar/cocoa_scroll_bar.mm
@@ -551,4 +551,8 @@
   return &static_cast<CocoaScrollBar*>(scroll_bar)->hide_scrollbar_timer_;
 }
 
+BEGIN_METADATA(CocoaScrollBar)
+METADATA_PARENT_CLASS(ScrollBar)
+END_METADATA()
+
 }  // namespace views
diff --git a/ui/views/controls/scrollbar/overlay_scroll_bar.cc b/ui/views/controls/scrollbar/overlay_scroll_bar.cc
index 1e2940af..06f70c9 100644
--- a/ui/views/controls/scrollbar/overlay_scroll_bar.cc
+++ b/ui/views/controls/scrollbar/overlay_scroll_bar.cc
@@ -192,4 +192,8 @@
       base::BindOnce(&OverlayScrollBar::Hide, base::Unretained(this)));
 }
 
+BEGIN_METADATA(OverlayScrollBar)
+METADATA_PARENT_CLASS(ScrollBar)
+END_METADATA()
+
 }  // namespace views
diff --git a/ui/views/controls/scrollbar/overlay_scroll_bar.h b/ui/views/controls/scrollbar/overlay_scroll_bar.h
index 3ae0c0b..d39b609 100644
--- a/ui/views/controls/scrollbar/overlay_scroll_bar.h
+++ b/ui/views/controls/scrollbar/overlay_scroll_bar.h
@@ -15,6 +15,8 @@
 // The transparent scrollbar which overlays its contents.
 class VIEWS_EXPORT OverlayScrollBar : public ScrollBar {
  public:
+  METADATA_HEADER(OverlayScrollBar);
+
   explicit OverlayScrollBar(bool horizontal);
   ~OverlayScrollBar() override;
 
diff --git a/ui/views/controls/scrollbar/scroll_bar.cc b/ui/views/controls/scrollbar/scroll_bar.cc
index 2679f2ad..098033e2 100644
--- a/ui/views/controls/scrollbar/scroll_bar.cc
+++ b/ui/views/controls/scrollbar/scroll_bar.cc
@@ -455,4 +455,9 @@
       return base::nullopt;
   }
 }
+
+BEGIN_METADATA(ScrollBar)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
 }  // namespace views
diff --git a/ui/views/controls/scrollbar/scroll_bar.h b/ui/views/controls/scrollbar/scroll_bar.h
index de7b944..d2b54f58 100644
--- a/ui/views/controls/scrollbar/scroll_bar.h
+++ b/ui/views/controls/scrollbar/scroll_bar.h
@@ -75,6 +75,8 @@
                                public ContextMenuController,
                                public ui::SimpleMenuModel::Delegate {
  public:
+  METADATA_HEADER(ScrollBar);
+
   // An enumeration of different amounts of incremental scroll, representing
   // events sent from different parts of the UI/keyboard.
   enum class ScrollAmount {
diff --git a/ui/views/controls/scrollbar/scroll_bar_views.cc b/ui/views/controls/scrollbar/scroll_bar_views.cc
index 37c2fd7..bef64bf 100644
--- a/ui/views/controls/scrollbar/scroll_bar_views.cc
+++ b/ui/views/controls/scrollbar/scroll_bar_views.cc
@@ -31,7 +31,6 @@
   ~ScrollBarButton() override;
 
   gfx::Size CalculatePreferredSize() const override;
-  const char* GetClassName() const override { return "ScrollBarButton"; }
 
  protected:
   void PaintButtonContents(gfx::Canvas* canvas) override;
@@ -51,7 +50,6 @@
   ~ScrollBarThumb() override;
 
   gfx::Size CalculatePreferredSize() const override;
-  const char* GetClassName() const override { return "ScrollBarThumb"; }
 
  protected:
   void OnPaint(gfx::Canvas* canvas) override;
@@ -197,8 +195,6 @@
 ////////////////////////////////////////////////////////////////////////////////
 // ScrollBarViews, public:
 
-const char ScrollBarViews::kViewClassName[] = "ScrollBarViews";
-
 ScrollBarViews::ScrollBarViews(bool horizontal) : ScrollBar(horizontal) {
   using Type = ScrollBarButton::Type;
   SetThumb(new ScrollBarThumb(this));
@@ -280,10 +276,6 @@
                    IsHorizontal() ? GetThickness() : 0);
 }
 
-const char* ScrollBarViews::GetClassName() const {
-  return kViewClassName;
-}
-
 int ScrollBarViews::GetThickness() const {
   const ui::NativeTheme* theme = GetNativeTheme();
   return IsHorizontal() ? GetHorizontalScrollBarHeight(theme)
@@ -339,4 +331,8 @@
   return std::max(track_size.height(), button_size.height());
 }
 
+BEGIN_METADATA(ScrollBarViews)
+METADATA_PARENT_CLASS(ScrollBar)
+END_METADATA()
+
 }  // namespace views
diff --git a/ui/views/controls/scrollbar/scroll_bar_views.h b/ui/views/controls/scrollbar/scroll_bar_views.h
index 847a7811..b7f1ada 100644
--- a/ui/views/controls/scrollbar/scroll_bar_views.h
+++ b/ui/views/controls/scrollbar/scroll_bar_views.h
@@ -22,7 +22,7 @@
 // Views implementation for the scrollbar.
 class VIEWS_EXPORT ScrollBarViews : public ScrollBar, public ButtonListener {
  public:
-  static const char kViewClassName[];
+  METADATA_HEADER(ScrollBarViews);
 
   // Creates new scrollbar, either horizontal or vertical.
   explicit ScrollBarViews(bool horizontal);
@@ -35,7 +35,6 @@
   void Layout() override;
   void OnPaint(gfx::Canvas* canvas) override;
   gfx::Size CalculatePreferredSize() const override;
-  const char* GetClassName() const override;
 
   // ScrollBar overrides:
   int GetThickness() const override;
diff --git a/ui/views/controls/separator.cc b/ui/views/controls/separator.cc
index 4e1c570..d3f8e8b3 100644
--- a/ui/views/controls/separator.cc
+++ b/ui/views/controls/separator.cc
@@ -11,9 +11,6 @@
 namespace views {
 
 // static
-const char Separator::kViewClassName[] = "Separator";
-
-// static
 const int Separator::kThickness = 1;
 
 Separator::Separator() = default;
@@ -63,8 +60,8 @@
   View::OnPaint(canvas);
 }
 
-const char* Separator::GetClassName() const {
-  return kViewClassName;
-}
+BEGIN_METADATA(Separator)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
 
 }  // namespace views
diff --git a/ui/views/controls/separator.h b/ui/views/controls/separator.h
index b0674fc..ae03677 100644
--- a/ui/views/controls/separator.h
+++ b/ui/views/controls/separator.h
@@ -17,8 +17,7 @@
 // other views.
 class VIEWS_EXPORT Separator : public View {
  public:
-  // The separator's class name.
-  static const char kViewClassName[];
+  METADATA_HEADER(Separator);
 
   // The separator's thickness in dip.
   static const int kThickness;
@@ -34,7 +33,6 @@
   gfx::Size CalculatePreferredSize() const override;
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
   void OnPaint(gfx::Canvas* canvas) override;
-  const char* GetClassName() const override;
 
  private:
   int preferred_height_ = kThickness;
diff --git a/ui/views/controls/slider.cc b/ui/views/controls/slider.cc
index 75432a2..f16860ad8 100644
--- a/ui/views/controls/slider.cc
+++ b/ui/views/controls/slider.cc
@@ -59,9 +59,6 @@
 
 }  // namespace
 
-// static
-const char Slider::kViewClassName[] = "Slider";
-
 Slider::Slider(SliderListener* listener)
     : listener_(listener),
       highlight_animation_(this),
@@ -196,10 +193,6 @@
     listener_->SliderDragEnded(this);
 }
 
-const char* Slider::GetClassName() const {
-  return kViewClassName;
-}
-
 gfx::Size Slider::CalculatePreferredSize() const {
   constexpr int kSizeMajor = 200;
   constexpr int kSizeMinor = 40;
@@ -360,4 +353,8 @@
   }
 }
 
+BEGIN_METADATA(Slider)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
 }  // namespace views
diff --git a/ui/views/controls/slider.h b/ui/views/controls/slider.h
index 64869aa..ea68bac4 100644
--- a/ui/views/controls/slider.h
+++ b/ui/views/controls/slider.h
@@ -44,8 +44,7 @@
 
 class VIEWS_EXPORT Slider : public View, public gfx::AnimationDelegate {
  public:
-  // Internal class name.
-  static const char kViewClassName[];
+  METADATA_HEADER(Slider);
 
   explicit Slider(SliderListener* listener);
   ~Slider() override;
@@ -92,7 +91,6 @@
   void OnSliderDragEnded();
 
   // views::View:
-  const char* GetClassName() const override;
   gfx::Size CalculatePreferredSize() const override;
   bool OnMousePressed(const ui::MouseEvent& event) override;
   bool OnMouseDragged(const ui::MouseEvent& event) override;
diff --git a/ui/views/controls/styled_label.cc b/ui/views/controls/styled_label.cc
index ee21d283..b0a9b38 100644
--- a/ui/views/controls/styled_label.cc
+++ b/ui/views/controls/styled_label.cc
@@ -116,9 +116,6 @@
 
 // StyledLabel ----------------------------------------------------------------
 
-// static
-const char StyledLabel::kViewClassName[] = "StyledLabel";
-
 StyledLabel::StyledLabel(const base::string16& text,
                          StyledLabelListener* listener)
     : specified_line_height_(0),
@@ -206,10 +203,6 @@
   SetSize(CalculateAndDoLayout(max_width, true));
 }
 
-const char* StyledLabel::GetClassName() const {
-  return kViewClassName;
-}
-
 void StyledLabel::GetAccessibleNodeData(ui::AXNodeData* node_data) {
   if (text_context_ == style::CONTEXT_DIALOG_TITLE)
     node_data->role = ax::mojom::Role::kTitleBar;
@@ -528,4 +521,8 @@
   offset->set_x(0);
 }
 
+BEGIN_METADATA(StyledLabel)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
 }  // namespace views
diff --git a/ui/views/controls/styled_label.h b/ui/views/controls/styled_label.h
index e4ca7cc..e624a61 100644
--- a/ui/views/controls/styled_label.h
+++ b/ui/views/controls/styled_label.h
@@ -34,8 +34,7 @@
 // In this case, leading whitespace is ignored.
 class VIEWS_EXPORT StyledLabel : public View, public LinkListener {
  public:
-  // Internal class name.
-  static const char kViewClassName[];
+  METADATA_HEADER(StyledLabel);
 
   // TestApi is used for tests to get internal implementation details.
   class VIEWS_EXPORT TestApi {
@@ -139,7 +138,6 @@
   void SizeToFit(int max_width);
 
   // View:
-  const char* GetClassName() const override;
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
   gfx::Size CalculatePreferredSize() const override;
   int GetHeightForWidth(int w) const override;
diff --git a/ui/views/controls/tabbed_pane/tabbed_pane.cc b/ui/views/controls/tabbed_pane/tabbed_pane.cc
index 7cc8c5f0..047da5a 100644
--- a/ui/views/controls/tabbed_pane/tabbed_pane.cc
+++ b/ui/views/controls/tabbed_pane/tabbed_pane.cc
@@ -69,9 +69,6 @@
 
 }  // namespace
 
-// static
-const char TabbedPane::kViewClassName[] = "TabbedPane";
-
 // A subclass of Tab that implements the Harmony visual styling.
 class MdTab : public Tab {
  public:
@@ -823,12 +820,12 @@
   return MoveSelectionBy(accelerator.IsShiftDown() ? -1 : 1);
 }
 
-const char* TabbedPane::GetClassName() const {
-  return kViewClassName;
-}
-
 void TabbedPane::GetAccessibleNodeData(ui::AXNodeData* node_data) {
   node_data->role = ax::mojom::Role::kTabList;
 }
 
+BEGIN_METADATA(TabbedPane)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
 }  // namespace views
diff --git a/ui/views/controls/tabbed_pane/tabbed_pane.h b/ui/views/controls/tabbed_pane/tabbed_pane.h
index 7d0ab36..8f6a5cf 100644
--- a/ui/views/controls/tabbed_pane/tabbed_pane.h
+++ b/ui/views/controls/tabbed_pane/tabbed_pane.h
@@ -28,6 +28,8 @@
 // may require additional polish.
 class VIEWS_EXPORT TabbedPane : public View {
  public:
+  METADATA_HEADER(TabbedPane);
+
   // The orientation of the tab alignment.
   enum class Orientation {
     kHorizontal,
@@ -40,9 +42,6 @@
     kHighlight,  // Highlight background and text of the selected tab.
   };
 
-  // Internal class name.
-  static const char kViewClassName[];
-
   explicit TabbedPane(Orientation orientation = Orientation::kHorizontal,
                       TabStripStyle style = TabStripStyle::kBorder);
   ~TabbedPane() override;
@@ -75,7 +74,6 @@
 
   // Overridden from View:
   gfx::Size CalculatePreferredSize() const override;
-  const char* GetClassName() const override;
 
   // Gets the orientation of the tab alignment.
   Orientation GetOrientation() const;
diff --git a/ui/views/controls/textfield/textfield.cc b/ui/views/controls/textfield/textfield.cc
index 71c439d7..b0a329a 100644
--- a/ui/views/controls/textfield/textfield.cc
+++ b/ui/views/controls/textfield/textfield.cc
@@ -249,9 +249,6 @@
 }  // namespace
 
 // static
-const char Textfield::kViewClassName[] = "Textfield";
-
-// static
 base::TimeDelta Textfield::GetCaretBlinkInterval() {
 #if defined(OS_WIN)
   static const size_t system_value = ::GetCaretBlinkTime();
@@ -636,10 +633,6 @@
   return minimum_size;
 }
 
-const char* Textfield::GetClassName() const {
-  return kViewClassName;
-}
-
 void Textfield::SetBorder(std::unique_ptr<Border> b) {
   use_focus_ring_ = false;
   if (focus_ring_)
@@ -2389,4 +2382,8 @@
     GetInputMethod()->OnTextInputTypeChanged(this);
 }
 
+BEGIN_METADATA(Textfield)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
 }  // namespace views
diff --git a/ui/views/controls/textfield/textfield.h b/ui/views/controls/textfield/textfield.h
index 0a88abf..85342f138 100644
--- a/ui/views/controls/textfield/textfield.h
+++ b/ui/views/controls/textfield/textfield.h
@@ -71,8 +71,7 @@
                                public ui::TouchEditable,
                                public ui::TextInputClient {
  public:
-  // The textfield's class name.
-  static const char kViewClassName[];
+  METADATA_HEADER(Textfield);
 
   // Returns the text cursor blink time, or 0 for no blinking.
   static base::TimeDelta GetCaretBlinkInterval();
@@ -260,7 +259,6 @@
   int GetBaseline() const override;
   gfx::Size CalculatePreferredSize() const override;
   gfx::Size GetMinimumSize() const override;
-  const char* GetClassName() const override;
   void SetBorder(std::unique_ptr<Border> b) override;
   gfx::NativeCursor GetCursor(const ui::MouseEvent& event) override;
   bool OnMousePressed(const ui::MouseEvent& event) override;
diff --git a/ui/views/controls/throbber.cc b/ui/views/controls/throbber.cc
index 0987bec..47d384c 100644
--- a/ui/views/controls/throbber.cc
+++ b/ui/views/controls/throbber.cc
@@ -86,6 +86,10 @@
   return timer_.IsRunning();
 }
 
+BEGIN_METADATA(Throbber)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
 // Smoothed throbber ---------------------------------------------------------
 
 // Delay after work starts before starting throbber, in milliseconds.
@@ -128,4 +132,8 @@
   Throbber::Stop();
 }
 
+BEGIN_METADATA(SmoothedThrobber)
+METADATA_PARENT_CLASS(Throbber)
+END_METADATA()
+
 }  // namespace views
diff --git a/ui/views/controls/throbber.h b/ui/views/controls/throbber.h
index 8ba2b9f..c9be504 100644
--- a/ui/views/controls/throbber.h
+++ b/ui/views/controls/throbber.h
@@ -17,6 +17,7 @@
 
 class VIEWS_EXPORT Throbber : public View {
  public:
+  METADATA_HEADER(Throbber);
   Throbber();
   ~Throbber() override;
 
@@ -51,6 +52,7 @@
 // a small amount of work time has passed.
 class VIEWS_EXPORT SmoothedThrobber : public Throbber {
  public:
+  METADATA_HEADER(SmoothedThrobber);
   SmoothedThrobber();
   ~SmoothedThrobber() override;
 
diff --git a/ui/views/controls/tree/tree_view.cc b/ui/views/controls/tree/tree_view.cc
index 005ab7f..870553c 100644
--- a/ui/views/controls/tree/tree_view.cc
+++ b/ui/views/controls/tree/tree_view.cc
@@ -56,9 +56,6 @@
 // How much children are indented from their parent.
 static constexpr int kIndent = 20;
 
-// static
-const char TreeView::kViewClassName[] = "TreeView";
-
 namespace {
 
 bool EventIsDoubleTapOrClick(const ui::LocatedEvent& event) {
@@ -440,10 +437,6 @@
   node_data->SetName(selected_node_->model_node()->GetTitle());
 }
 
-const char* TreeView::GetClassName() const {
-  return kViewClassName;
-}
-
 void TreeView::TreeNodesAdded(TreeModel* model,
                               TreeModelNode* parent,
                               size_t start,
@@ -1164,4 +1157,8 @@
   return max_width;
 }
 
+BEGIN_METADATA(TreeView)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
 }  // namespace views
diff --git a/ui/views/controls/tree/tree_view.h b/ui/views/controls/tree/tree_view.h
index 382b2b9..facb792 100644
--- a/ui/views/controls/tree/tree_view.h
+++ b/ui/views/controls/tree/tree_view.h
@@ -43,8 +43,7 @@
                               public FocusChangeListener,
                               public PrefixDelegate {
  public:
-  // The tree view's class name.
-  static const char kViewClassName[];
+  METADATA_HEADER(TreeView);
 
   TreeView();
   ~TreeView() override;
@@ -139,7 +138,6 @@
   void ShowContextMenu(const gfx::Point& p,
                        ui::MenuSourceType source_type) override;
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
-  const char* GetClassName() const override;
 
   // TreeModelObserver overrides:
   void TreeNodesAdded(ui::TreeModel* model,
diff --git a/ui/views/controls/webview/webview.cc b/ui/views/controls/webview/webview.cc
index fa63248..13f2f862d 100644
--- a/ui/views/controls/webview/webview.cc
+++ b/ui/views/controls/webview/webview.cc
@@ -46,9 +46,6 @@
   *GetCreatorForTesting() = WebView::WebContentsCreator();
 }
 
-// static
-const char WebView::kViewClassName[] = "WebView";
-
 ////////////////////////////////////////////////////////////////////////////////
 // WebView, public:
 
@@ -145,10 +142,6 @@
 ////////////////////////////////////////////////////////////////////////////////
 // WebView, View overrides:
 
-const char* WebView::GetClassName() const {
-  return kViewClassName;
-}
-
 void WebView::OnBoundsChanged(const gfx::Rect& previous_bounds) {
   if (crashed_overlay_view_)
     crashed_overlay_view_->SetBoundsRect(gfx::Rect(size()));
@@ -458,4 +451,8 @@
   render_widget_host_view->EnableAutoResize(min_size_, max_size_);
 }
 
+BEGIN_METADATA(WebView)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
 }  // namespace views
diff --git a/ui/views/controls/webview/webview.h b/ui/views/controls/webview/webview.h
index e85d9df5..48ce5978 100644
--- a/ui/views/controls/webview/webview.h
+++ b/ui/views/controls/webview/webview.h
@@ -39,7 +39,7 @@
                                public content::WebContentsDelegate,
                                public content::WebContentsObserver {
  public:
-  static const char kViewClassName[];
+  METADATA_HEADER(WebView);
 
   explicit WebView(content::BrowserContext* browser_context);
   ~WebView() override;
@@ -92,9 +92,6 @@
     allow_accelerators_ = allow_accelerators;
   }
 
-  // Overridden from View:
-  const char* GetClassName() const override;
-
   // Overridden from content::WebContentsDelegate:
   void ResizeDueToAutoResize(content::WebContents* source,
                              const gfx::Size& new_size) override;
diff --git a/ui/views/metadata/metadata_header_macros.h b/ui/views/metadata/metadata_header_macros.h
index 532c01a..c10bc2c 100644
--- a/ui/views/metadata/metadata_header_macros.h
+++ b/ui/views/metadata/metadata_header_macros.h
@@ -13,4 +13,10 @@
   METADATA_ACCESSORS_INTERNAL(class_name) \
   METADATA_CLASS_INTERNAL(class_name)
 
+// A version of METADATA_HEADER for View, the root of the metadata hierarchy.
+// Here METADATA_ACCESSORS_INTERNAL_BASE is called.
+#define METADATA_HEADER_BASE(class_name)       \
+  METADATA_ACCESSORS_INTERNAL_BASE(class_name) \
+  METADATA_CLASS_INTERNAL(class_name)
+
 #endif  // UI_VIEWS_METADATA_METADATA_HEADER_MACROS_H_
diff --git a/ui/views/metadata/metadata_impl_macros.h b/ui/views/metadata/metadata_impl_macros.h
index 215750e..2eedd00f 100644
--- a/ui/views/metadata/metadata_impl_macros.h
+++ b/ui/views/metadata/metadata_impl_macros.h
@@ -11,6 +11,7 @@
 
 // Generate the implementation of the metadata accessors and internal class with
 // additional macros for defining the class' properties.
+
 #define BEGIN_METADATA(class_name)                                          \
   views::metadata::ClassMetaData* class_name::METADATA_CLASS_NAME_INTERNAL( \
       class_name)::meta_data_ = nullptr;                                    \
@@ -27,6 +28,11 @@
     return MetaData();                                                      \
   }                                                                         \
                                                                             \
+  const char* class_name::GetClassName() const {                            \
+    return class_name::kViewClassName;                                      \
+  }                                                                         \
+  const char class_name::kViewClassName[] = #class_name;                    \
+                                                                            \
   void METADATA_FUNCTION_PREFIX_INTERNAL(class_name)::BuildMetaData() {     \
     SetTypeName(std::string(#class_name));
 
diff --git a/ui/views/metadata/metadata_macros_internal.h b/ui/views/metadata/metadata_macros_internal.h
index d29da82..6f283f95 100644
--- a/ui/views/metadata/metadata_macros_internal.h
+++ b/ui/views/metadata/metadata_macros_internal.h
@@ -18,6 +18,16 @@
 
 // Metadata Accessors ---------------------------------------------------------
 #define METADATA_ACCESSORS_INTERNAL(class_name)      \
+  static const char kViewClassName[];                \
+  const char* GetClassName() const override;         \
+  static views::metadata::ClassMetaData* MetaData(); \
+  views::metadata::ClassMetaData* GetClassMetaData() override;
+
+// A version of METADATA_ACCESSORS_INTERNAL for View, the root of the metadata
+// hierarchy; here GetClassName() is not declared as an override.
+#define METADATA_ACCESSORS_INTERNAL_BASE(class_name) \
+  static const char kViewClassName[];                \
+  virtual const char* GetClassName() const;          \
   static views::metadata::ClassMetaData* MetaData(); \
   views::metadata::ClassMetaData* GetClassMetaData() override;
 
diff --git a/ui/views/metadata/metadata_unittest.cc b/ui/views/metadata/metadata_unittest.cc
index 18d899ce..8fad27f 100644
--- a/ui/views/metadata/metadata_unittest.cc
+++ b/ui/views/metadata/metadata_unittest.cc
@@ -109,7 +109,6 @@
       GetMemberMetaData(&test_obj, "FloatProperty");
 
   ASSERT_TRUE(member_data);
-
   base::string16 member_value = member_data->GetValueAsString(&test_obj);
   CHECK_EQ(member_value, base::NumberToString16(start_value));
 }
@@ -183,25 +182,3 @@
   CHECK(std::find(cache_meta.begin(), cache_meta.end(), test_class_meta) !=
         cache_meta.end());
 }
-
-// View subclass with no properties to test MetaData Iterator
-// when members vector is empty.
-class MetadataTestViewNoProperties : public views::View {
- public:
-  METADATA_HEADER(MetadataTestViewNoProperties);
-
-  MetadataTestViewNoProperties() = default;
-  ~MetadataTestViewNoProperties() override = default;
-};
-
-BEGIN_METADATA(MetadataTestViewNoProperties)
-METADATA_PARENT_CLASS(views::View)
-END_METADATA()
-
-TEST_F(MetadataTest, NoPropertyClassIterator) {
-  views::View test_view;
-  MetadataTestViewNoProperties test_no_prop_view;
-
-  CHECK(test_view.GetClassMetaData()->begin() ==
-        test_no_prop_view.GetClassMetaData()->begin());
-}
diff --git a/ui/views/touchui/touch_selection_menu_views.cc b/ui/views/touchui/touch_selection_menu_views.cc
index aea8ce8..4f12977 100644
--- a/ui/views/touchui/touch_selection_menu_views.cc
+++ b/ui/views/touchui/touch_selection_menu_views.cc
@@ -183,4 +183,8 @@
     client_->RunContextMenu();
 }
 
+BEGIN_METADATA(TouchSelectionMenuViews)
+METADATA_PARENT_CLASS(BubbleDialogDelegateView)
+END_METADATA()
+
 }  // namespace views
diff --git a/ui/views/touchui/touch_selection_menu_views.h b/ui/views/touchui/touch_selection_menu_views.h
index a9882f2..b396471 100644
--- a/ui/views/touchui/touch_selection_menu_views.h
+++ b/ui/views/touchui/touch_selection_menu_views.h
@@ -22,6 +22,8 @@
 class VIEWS_EXPORT TouchSelectionMenuViews : public BubbleDialogDelegateView,
                                              public ButtonListener {
  public:
+  METADATA_HEADER(TouchSelectionMenuViews);
+
   TouchSelectionMenuViews(TouchSelectionMenuRunnerViews* owner,
                           ui::TouchSelectionMenuClient* client,
                           aura::Window* context);
diff --git a/ui/views/view.cc b/ui/views/view.cc
index 4e71a3d7..6b8b0fb4 100644
--- a/ui/views/view.cc
+++ b/ui/views/view.cc
@@ -115,9 +115,6 @@
 
 }  // namespace internal
 
-// static
-const char View::kViewClassName[] = "View";
-
 ////////////////////////////////////////////////////////////////////////////////
 // View, public:
 
@@ -684,10 +681,6 @@
 
 // Attributes ------------------------------------------------------------------
 
-const char* View::GetClassName() const {
-  return kViewClassName;
-}
-
 const View* View::GetAncestorWithClassName(const std::string& name) const {
   for (const View* view = this; view; view = view->parent_) {
     if (!strcmp(view->GetClassName(), name.c_str()))
diff --git a/ui/views/view.h b/ui/views/view.h
index 3d90ae1c..94dcf00d 100644
--- a/ui/views/view.h
+++ b/ui/views/view.h
@@ -44,6 +44,7 @@
 #include "ui/gfx/geometry/vector2d.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/views/metadata/metadata_header_macros.h"
+#include "ui/views/metadata/metadata_impl_macros.h"
 #include "ui/views/paint_info.h"
 #include "ui/views/view_targeter.h"
 #include "ui/views/views_export.h"
@@ -278,7 +279,7 @@
  public:
   using Views = std::vector<View*>;
 
-  METADATA_HEADER(View);
+  METADATA_HEADER_BASE(View);
 
   enum class FocusBehavior {
     // Use when the View is never focusable. Default.
@@ -723,15 +724,6 @@
 
   // Attributes ----------------------------------------------------------------
 
-  // The view class name.
-  static const char kViewClassName[];
-
-  // Return the receiving view's class name. A view class is a string which
-  // uniquely identifies the view class. It is intended to be used as a way to
-  // find out during run time if a view can be safely cast to a specific view
-  // subclass. The default implementation returns kViewClassName.
-  virtual const char* GetClassName() const;
-
   // Returns the first ancestor, starting at this, whose class name is |name|.
   // Returns null if no ancestor has the class name |name|.
   const View* GetAncestorWithClassName(const std::string& name) const;
diff --git a/ui/views/widget/root_view.cc b/ui/views/widget/root_view.cc
index c114bc4..85d907cc 100644
--- a/ui/views/widget/root_view.cc
+++ b/ui/views/widget/root_view.cc
@@ -141,9 +141,6 @@
   DISALLOW_COPY_AND_ASSIGN(PostEventDispatchHandler);
 };
 
-// static
-const char RootView::kViewClassName[] = "RootView";
-
 ////////////////////////////////////////////////////////////////////////////////
 // RootView, public:
 
@@ -319,10 +316,6 @@
   return GetVisible();
 }
 
-const char* RootView::GetClassName() const {
-  return kViewClassName;
-}
-
 void RootView::SchedulePaintInRect(const gfx::Rect& rect) {
   if (layer()) {
     layer()->SchedulePaint(rect);
@@ -755,5 +748,8 @@
   return details;
 }
 
+BEGIN_METADATA(RootView)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
 }  // namespace internal
 }  // namespace views
diff --git a/ui/views/widget/root_view.h b/ui/views/widget/root_view.h
index 224a1a4d..02d3810 100644
--- a/ui/views/widget/root_view.h
+++ b/ui/views/widget/root_view.h
@@ -52,7 +52,7 @@
                               public FocusTraversable,
                               public ui::EventProcessor {
  public:
-  static const char kViewClassName[];
+  METADATA_HEADER(RootView);
 
   // Creation and lifetime -----------------------------------------------------
   explicit RootView(Widget* widget);
@@ -107,7 +107,6 @@
   const Widget* GetWidget() const override;
   Widget* GetWidget() override;
   bool IsDrawn() const override;
-  const char* GetClassName() const override;
   void SchedulePaintInRect(const gfx::Rect& rect) override;
   bool OnMousePressed(const ui::MouseEvent& event) override;
   bool OnMouseDragged(const ui::MouseEvent& event) override;
diff --git a/ui/views/widget/widget_delegate.cc b/ui/views/widget/widget_delegate.cc
index 570fefd..96563f1 100644
--- a/ui/views/widget/widget_delegate.cc
+++ b/ui/views/widget/widget_delegate.cc
@@ -190,8 +190,6 @@
 ////////////////////////////////////////////////////////////////////////////////
 // WidgetDelegateView:
 
-// static
-const char WidgetDelegateView::kViewClassName[] = "WidgetDelegateView";
 
 WidgetDelegateView::WidgetDelegateView() {
   // A WidgetDelegate should be deleted on DeleteDelegate.
@@ -216,8 +214,8 @@
   return this;
 }
 
-const char* WidgetDelegateView::GetClassName() const {
-  return kViewClassName;
-}
+BEGIN_METADATA(WidgetDelegateView)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
 
 }  // namespace views
diff --git a/ui/views/widget/widget_delegate.h b/ui/views/widget/widget_delegate.h
index 1f82752..7758573 100644
--- a/ui/views/widget/widget_delegate.h
+++ b/ui/views/widget/widget_delegate.h
@@ -212,8 +212,7 @@
 // view's hierarchy and is expected to be deleted on DeleteDelegate call.
 class VIEWS_EXPORT WidgetDelegateView : public WidgetDelegate, public View {
  public:
-  // Internal class name.
-  static const char kViewClassName[];
+  METADATA_HEADER(WidgetDelegateView);
 
   WidgetDelegateView();
   ~WidgetDelegateView() override;
@@ -224,9 +223,6 @@
   const Widget* GetWidget() const override;
   views::View* GetContentsView() override;
 
-  // View:
-  const char* GetClassName() const override;
-
  private:
   DISALLOW_COPY_AND_ASSIGN(WidgetDelegateView);
 };
diff --git a/ui/views/window/client_view.cc b/ui/views/window/client_view.cc
index 88842b6..646b1ea 100644
--- a/ui/views/window/client_view.cc
+++ b/ui/views/window/client_view.cc
@@ -12,10 +12,6 @@
 
 namespace views {
 
-// static
-const char ClientView::kViewClassName[] =
-    "ui/views/window/ClientView";
-
 ///////////////////////////////////////////////////////////////////////////////
 // ClientView, public:
 
@@ -70,9 +66,6 @@
     contents_view_->SetBounds(0, 0, width(), height());
 }
 
-const char* ClientView::GetClassName() const {
-  return kViewClassName;
-}
 
 void ClientView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
   node_data->role = ax::mojom::Role::kClient;
@@ -97,4 +90,8 @@
   }
 }
 
+BEGIN_METADATA(ClientView)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
 }  // namespace views
diff --git a/ui/views/window/client_view.h b/ui/views/window/client_view.h
index c0b4e5b..b237a754 100644
--- a/ui/views/window/client_view.h
+++ b/ui/views/window/client_view.h
@@ -22,8 +22,7 @@
 //  "DialogClientView".
 class VIEWS_EXPORT ClientView : public View {
  public:
-  // Internal class name
-  static const char kViewClassName[];
+  METADATA_HEADER(ClientView);
 
   // Constructs a ClientView object for the specified widget with the specified
   // contents. Since this object is created during the process of creating
@@ -61,7 +60,6 @@
   gfx::Size GetMinimumSize() const override;
   gfx::Size GetMaximumSize() const override;
   void Layout() override;
-  const char* GetClassName() const override;
 
  protected:
   // Overridden from View:
diff --git a/ui/views/window/dialog_client_view.cc b/ui/views/window/dialog_client_view.cc
index 84f4db07..2c4fc63 100644
--- a/ui/views/window/dialog_client_view.cc
+++ b/ui/views/window/dialog_client_view.cc
@@ -454,4 +454,8 @@
     extra_view_->SetGroup(kButtonGroup);
 }
 
+BEGIN_METADATA(DialogClientView)
+METADATA_PARENT_CLASS(ClientView)
+END_METADATA()
+
 }  // namespace views
diff --git a/ui/views/window/dialog_client_view.h b/ui/views/window/dialog_client_view.h
index e36af7a..1c946197 100644
--- a/ui/views/window/dialog_client_view.h
+++ b/ui/views/window/dialog_client_view.h
@@ -33,6 +33,8 @@
                                       public ButtonListener,
                                       public DialogObserver {
  public:
+  METADATA_HEADER(DialogClientView);
+
   DialogClientView(Widget* widget, View* contents_view);
   ~DialogClientView() override;
 
diff --git a/ui/views/window/non_client_view.cc b/ui/views/window/non_client_view.cc
index 3c583973..656a6998 100644
--- a/ui/views/window/non_client_view.cc
+++ b/ui/views/window/non_client_view.cc
@@ -17,13 +17,6 @@
 
 namespace views {
 
-// static
-const char NonClientFrameView::kViewClassName[] =
-    "ui/views/window/NonClientFrameView";
-
-const char NonClientView::kViewClassName[] =
-    "ui/views/window/NonClientView";
-
 // The frame view and the client view are always at these specific indices,
 // because the RootView message dispatch sends messages to items higher in the
 // z-order first and we always want the client view to have first crack at
@@ -195,10 +188,6 @@
   node_data->SetName(accessible_name_);
 }
 
-const char* NonClientView::GetClassName() const {
-  return kViewClassName;
-}
-
 View* NonClientView::GetTooltipHandlerForPoint(const gfx::Point& point) {
   // The same logic as for |TargetForRect()| applies here.
   if (frame_view_->parent() == this) {
@@ -244,6 +233,10 @@
   return ViewTargeterDelegate::TargetForRect(root, rect);
 }
 
+BEGIN_METADATA(NonClientView)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
 ////////////////////////////////////////////////////////////////////////////////
 // NonClientFrameView, public:
 
@@ -308,10 +301,6 @@
   node_data->role = ax::mojom::Role::kClient;
 }
 
-const char* NonClientFrameView::GetClassName() const {
-  return kViewClassName;
-}
-
 void NonClientFrameView::OnThemeChanged() {
   SchedulePaint();
 }
@@ -333,4 +322,8 @@
   return !GetWidget()->client_view()->bounds().Intersects(rect);
 }
 
+BEGIN_METADATA(NonClientFrameView)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
 }  // namespace views
diff --git a/ui/views/window/non_client_view.h b/ui/views/window/non_client_view.h
index 080e99d..222ca7c 100644
--- a/ui/views/window/non_client_view.h
+++ b/ui/views/window/non_client_view.h
@@ -23,8 +23,7 @@
 class VIEWS_EXPORT NonClientFrameView : public View,
                                         public ViewTargeterDelegate {
  public:
-  // Internal class name.
-  static const char kViewClassName[];
+  METADATA_HEADER(NonClientFrameView);
 
   enum {
     // Various edges of the frame border have a 1 px shadow along their edges;
@@ -89,7 +88,6 @@
 
   // View:
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
-  const char* GetClassName() const override;
   void OnThemeChanged() override;
 
  protected:
@@ -141,8 +139,7 @@
 //
 class VIEWS_EXPORT NonClientView : public View, public ViewTargeterDelegate {
  public:
-  // Internal class name.
-  static const char kViewClassName[];
+  METADATA_HEADER(NonClientView);
 
   NonClientView();
   ~NonClientView() override;
@@ -217,7 +214,6 @@
   gfx::Size GetMaximumSize() const override;
   void Layout() override;
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
-  const char* GetClassName() const override;
 
   views::View* GetTooltipHandlerForPoint(const gfx::Point& point) override;