diff --git a/DEPS b/DEPS
index 2476cb9..ca5677ab 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': 'cc82972af115b2fecc857c39d55c308009eeca3a',
+  'skia_revision': '5ec1b8ff3f45e5bbd9d21cdf60217e417118d0ed',
   # 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,11 +150,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': '2d0a9acb05511a8fdaf0cd27d0da22599516a68b',
+  'angle_revision': 'f1a40a848d29e696e5e00aea4b9a26940b9df23d',
   # 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': 'f60a2d59c9f2cee2f3749ee9bf03bdb1bf2bccaa',
+  'swiftshader_revision': '83818b444fc39e43649616d4b207a5085766d1fa',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
@@ -189,7 +189,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling freetype
   # and whatever else without interference from each other.
-  'freetype_revision': '711b593e4b589fbd726a4962ad492fc4e416355d',
+  'freetype_revision': '7fde521bd918d2299cce80c306ecc2cac9f51303',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling HarfBuzz
   # and whatever else without interference from each other.
@@ -201,7 +201,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '93cd912aa60ef771f5aef978e3ba7f886c02bf9b',
+  'catapult_revision': '9ba3fdcb3aef252bea4b93c7beb3205a17c3e984',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -269,11 +269,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'shaderc_revision': '3c76b8aa36fad139c871859d75056b222d31489c',
+  'shaderc_revision': 'facd09210436eaa51f0cb610d9dbb2bab5b91b4b',
   # 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': '7eb6be186be60a536a9f529b514bb5c5fd79293d',
+  'dawn_revision': '2b82eb290220668cc1459a591558d20d03614800',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -1355,7 +1355,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '6f0b34abee8dba611c253738d955c59f703c147a',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '54c9d89f69c50ae180e818528081404582a59a9c',
+    Var('webrtc_git') + '/src.git' + '@' + 'e323359d6f0ace0022d1eefebe7a74833338f665',
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
@@ -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@bc9865fc3dd2157d95ed2fb2096bee529b0d70a9',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@0379d9c272d6debca36b43b96f0f088bdefe5e10',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index 07da425d..a77f3c3 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -1293,7 +1293,6 @@
     "//ash/assistant/ui",
     "//ash/assistant/ui:constants",
     "//ash/assistant/util",
-    "//ash/autotest",
     "//ash/components/cursor",
     "//ash/components/fast_ink",
     "//ash/components/shortcut_viewer",
@@ -1428,7 +1427,6 @@
   ]
 
   allow_circular_includes_from = [
-    "//ash/autotest",
     "//components/exo",
     "//components/exo/wayland",
   ]
diff --git a/ash/autotest/BUILD.gn b/ash/autotest/BUILD.gn
deleted file mode 100644
index 25d4d7d..0000000
--- a/ash/autotest/BUILD.gn
+++ /dev/null
@@ -1,19 +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.
-
-# Only include files that are needed for JS autotest / integration tests.
-
-assert(is_chromeos)
-
-source_set("autotest") {
-  sources = [
-    "shelf_integration_test_api.cc",
-    "shelf_integration_test_api.h",
-  ]
-
-  deps = [
-    "//ash/public/cpp",
-    "//base",
-  ]
-}
diff --git a/ash/autotest/README.md b/ash/autotest/README.md
deleted file mode 100644
index 110c07e..0000000
--- a/ash/autotest/README.md
+++ /dev/null
@@ -1,6 +0,0 @@
-Autotest
---------
-This directory contains files that are needed for JS autotest APIs, and/or any
-other integration tests.
-These files are part of release builds, but the API / Mojo service is only
-enabled if the "--use-test-config" switch is passed to Chrome.
diff --git a/ash/autotest/shelf_integration_test_api.cc b/ash/autotest/shelf_integration_test_api.cc
deleted file mode 100644
index bf0057a..0000000
--- a/ash/autotest/shelf_integration_test_api.cc
+++ /dev/null
@@ -1,72 +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 "ash/autotest/shelf_integration_test_api.h"
-
-#include <memory>
-#include <utility>
-
-#include "ash/root_window_controller.h"
-#include "ash/shelf/shelf.h"
-#include "ash/shell.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
-
-namespace ash {
-
-namespace {
-
-// Returns the Shelf instance for the display with the given |display_id|.
-Shelf* GetShelfForDisplay(int64_t display_id) {
-  // The controller may be null for invalid ids or for displays being removed.
-  RootWindowController* root_window_controller =
-      Shell::GetRootWindowControllerWithDisplayId(display_id);
-  return root_window_controller ? root_window_controller->shelf() : nullptr;
-}
-}  // namespace
-
-ShelfIntegrationTestApi::ShelfIntegrationTestApi() = default;
-ShelfIntegrationTestApi::~ShelfIntegrationTestApi() = default;
-
-// static
-void ShelfIntegrationTestApi::BindRequest(
-    mojom::ShelfIntegrationTestApiRequest request) {
-  mojo::MakeStrongBinding(std::make_unique<ShelfIntegrationTestApi>(),
-                          std::move(request));
-}
-
-void ShelfIntegrationTestApi::GetAutoHideBehavior(
-    int64_t display_id,
-    GetAutoHideBehaviorCallback callback) {
-  Shelf* shelf = GetShelfForDisplay(display_id);
-  DCHECK(shelf);
-  std::move(callback).Run(shelf->auto_hide_behavior());
-}
-
-void ShelfIntegrationTestApi::SetAutoHideBehavior(
-    int64_t display_id,
-    ShelfAutoHideBehavior behavior,
-    SetAutoHideBehaviorCallback callback) {
-  Shelf* shelf = GetShelfForDisplay(display_id);
-  DCHECK(shelf);
-  shelf->SetAutoHideBehavior(behavior);
-  std::move(callback).Run();
-}
-
-void ShelfIntegrationTestApi::GetAlignment(int64_t display_id,
-                                           GetAlignmentCallback callback) {
-  Shelf* shelf = GetShelfForDisplay(display_id);
-  DCHECK(shelf);
-  std::move(callback).Run(shelf->alignment());
-}
-
-void ShelfIntegrationTestApi::SetAlignment(int64_t display_id,
-                                           ShelfAlignment alignment,
-                                           SetAlignmentCallback callback) {
-  Shelf* shelf = GetShelfForDisplay(display_id);
-  DCHECK(shelf);
-  shelf->SetAlignment(alignment);
-  std::move(callback).Run();
-}
-
-}  // namespace ash
diff --git a/ash/autotest/shelf_integration_test_api.h b/ash/autotest/shelf_integration_test_api.h
deleted file mode 100644
index 07bef13..0000000
--- a/ash/autotest/shelf_integration_test_api.h
+++ /dev/null
@@ -1,42 +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 ASH_AUTOTEST_SHELF_INTEGRATION_TEST_API_H_
-#define ASH_AUTOTEST_SHELF_INTEGRATION_TEST_API_H_
-
-#include "ash/ash_export.h"
-#include "ash/public/interfaces/shelf_integration_test_api.mojom.h"
-#include "base/macros.h"
-
-namespace ash {
-
-// Allows tests to access private state of the shelf.
-class ASH_EXPORT ShelfIntegrationTestApi
-    : public mojom::ShelfIntegrationTestApi {
- public:
-  // Binds the mojom::ShelfIntegrationTestApiRequest interface request to this
-  // object.
-  static void BindRequest(mojom::ShelfIntegrationTestApiRequest request);
-
-  ShelfIntegrationTestApi();
-  ~ShelfIntegrationTestApi() override;
-
-  // mojom::ShelfIntegrationTestApi:
-  void GetAutoHideBehavior(int64_t display_id,
-                           GetAutoHideBehaviorCallback callback) override;
-  void SetAutoHideBehavior(int64_t display_id,
-                           ShelfAutoHideBehavior behavior,
-                           SetAutoHideBehaviorCallback callback) override;
-  void GetAlignment(int64_t display_id, GetAlignmentCallback callback) override;
-  void SetAlignment(int64_t display_id,
-                    ShelfAlignment behavior,
-                    SetAlignmentCallback callback) override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ShelfIntegrationTestApi);
-};
-
-}  // namespace ash
-
-#endif  // ASH_AUTOTEST_SHELF_INTEGRATION_TEST_API_H_
diff --git a/ash/mojo_interface_factory.cc b/ash/mojo_interface_factory.cc
index 52602bd..ab6fca97 100644
--- a/ash/mojo_interface_factory.cc
+++ b/ash/mojo_interface_factory.cc
@@ -14,13 +14,11 @@
 #include "ash/assistant/assistant_notification_controller.h"
 #include "ash/assistant/assistant_screen_context_controller.h"
 #include "ash/assistant/assistant_setup_controller.h"
-#include "ash/autotest/shelf_integration_test_api.h"
 #include "ash/display/cros_display_config.h"
 #include "ash/ime/ime_controller.h"
 #include "ash/login/login_screen_controller.h"
 #include "ash/media/media_controller_impl.h"
 #include "ash/public/cpp/ash_features.h"
-#include "ash/public/cpp/ash_switches.h"
 #include "ash/public/cpp/voice_interaction_controller.h"
 #include "ash/shell.h"
 #include "ash/shell_delegate.h"
@@ -29,7 +27,6 @@
 #include "ash/system/night_light/night_light_controller.h"
 #include "ash/tray_action/tray_action.h"
 #include "base/bind.h"
-#include "base/command_line.h"
 #include "base/lazy_instance.h"
 #include "base/single_thread_task_runner.h"
 #include "chromeos/constants/chromeos_switches.h"
@@ -101,11 +98,6 @@
   Shell::Get()->night_light_controller()->BindRequest(std::move(request));
 }
 
-void BindShelfIntegrationTestApiRequestOnMainThread(
-    mojom::ShelfIntegrationTestApiRequest request) {
-  ShelfIntegrationTestApi::BindRequest(std::move(request));
-}
-
 void BindTrayActionRequestOnMainThread(mojom::TrayActionRequest request) {
   Shell::Get()->tray_action()->BindRequest(std::move(request));
 }
@@ -172,13 +164,6 @@
   registry->AddInterface(base::BindRepeating(&BindVpnListRequestOnMainThread),
                          main_thread_task_runner);
 
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kAshEnableTestInterfaces)) {
-    registry->AddInterface(
-        base::BindRepeating(&BindShelfIntegrationTestApiRequestOnMainThread),
-        main_thread_task_runner);
-  }
-
   // Inject additional optional interfaces.
   if (g_register_interfaces_callback.Get()) {
     std::move(g_register_interfaces_callback.Get())
diff --git a/ash/public/cpp/BUILD.gn b/ash/public/cpp/BUILD.gn
index cd58ff410..59e9970 100644
--- a/ash/public/cpp/BUILD.gn
+++ b/ash/public/cpp/BUILD.gn
@@ -216,16 +216,13 @@
   ]
 
   public_deps = [
-    "//ash/public/interfaces:interfaces_internal",
+    "//ash/public/interfaces",
     "//base",
     "//components/session_manager:base",
     "//components/user_manager",
     "//ui/gfx",
   ]
 
-  allow_circular_includes_from =
-      [ "//ash/public/interfaces:interfaces_internal" ]
-
   output_name = "ash_public_cpp"
 }
 
@@ -236,7 +233,7 @@
   ]
 
   deps = [
-    "//ash/public/interfaces:interfaces_internal",
+    "//ash/public/interfaces",
     "//base",
     "//chromeos/services/multidevice_setup/public/mojom",
     "//chromeos/services/network_config/public/mojom",
diff --git a/ash/public/cpp/ash_switches.cc b/ash/public/cpp/ash_switches.cc
index b93aa484..c08ec24 100644
--- a/ash/public/cpp/ash_switches.cc
+++ b/ash/public/cpp/ash_switches.cc
@@ -47,15 +47,6 @@
 // enter tablet mode.
 const char kAshEnableTabletMode[] = "enable-touchview";
 
-// Used to expose additional test-only interfaces.
-// Historical note: this name was originally used by the window-service to
-// enable additional test only interfaces, which also enabled test functionality
-// in ash. While the window-service is no more, autotest lives on. The string
-// value matches that used by the window-service.
-// TODO(crbug.com/958247): this is only necessary because of
-// ShelfIntegrationTestApi, that likely can be removed.
-const char kAshEnableTestInterfaces[] = "use-test-config";
-
 // Enable the wayland server.
 const char kAshEnableWaylandServer[] = "enable-wayland-server";
 
diff --git a/ash/public/cpp/ash_switches.h b/ash/public/cpp/ash_switches.h
index 00279851..f7a1e5b 100644
--- a/ash/public/cpp/ash_switches.h
+++ b/ash/public/cpp/ash_switches.h
@@ -25,7 +25,6 @@
 ASH_PUBLIC_EXPORT extern const char kAshEnableMagnifierKeyScroller[];
 ASH_PUBLIC_EXPORT extern const char kAshEnablePaletteOnAllDisplays[];
 ASH_PUBLIC_EXPORT extern const char kAshEnableTabletMode[];
-ASH_PUBLIC_EXPORT extern const char kAshEnableTestInterfaces[];
 ASH_PUBLIC_EXPORT extern const char kAshEnableWaylandServer[];
 ASH_PUBLIC_EXPORT extern const char kAshForceEnableStylusTools[];
 ASH_PUBLIC_EXPORT extern const char kAshPowerButtonPosition[];
diff --git a/ash/public/cpp/manifest.cc b/ash/public/cpp/manifest.cc
index a588903..2da67c0 100644
--- a/ash/public/cpp/manifest.cc
+++ b/ash/public/cpp/manifest.cc
@@ -13,7 +13,6 @@
 #include "ash/public/interfaces/cros_display_config.mojom.h"
 #include "ash/public/interfaces/ime_controller.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"
 #include "ash/public/interfaces/voice_interaction_controller.mojom.h"
 #include "ash/public/interfaces/vpn_list.mojom.h"
@@ -59,8 +58,6 @@
                   mojom::CrosDisplayConfigController, mojom::ImeController,
                   mojom::NightLightController, mojom::TrayAction,
                   mojom::VoiceInteractionController, mojom::VpnList>())
-          .ExposeCapability("test", service_manager::Manifest::InterfaceList<
-                                        mojom::ShelfIntegrationTestApi>())
           .RequireCapability("*", "accessibility")
           .RequireCapability("*", "app")
           .RequireCapability(content::mojom::kServiceName, "navigation")
diff --git a/ash/public/cpp/shelf_integration_test_api_struct_mojom_traits.h b/ash/public/cpp/shelf_integration_test_api_struct_mojom_traits.h
deleted file mode 100644
index b045ad4b..0000000
--- a/ash/public/cpp/shelf_integration_test_api_struct_mojom_traits.h
+++ /dev/null
@@ -1,88 +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 ASH_PUBLIC_CPP_SHELF_INTEGRATION_TEST_API_STRUCT_MOJOM_TRAITS_H_
-#define ASH_PUBLIC_CPP_SHELF_INTEGRATION_TEST_API_STRUCT_MOJOM_TRAITS_H_
-
-#include "ash/public/interfaces/shelf_integration_test_api.mojom-shared.h"
-
-namespace mojo {
-template <>
-struct EnumTraits<ash::mojom::ShelfAutoHideBehavior,
-                  ash::ShelfAutoHideBehavior> {
-  static ash::mojom::ShelfAutoHideBehavior ToMojom(
-      ash::ShelfAutoHideBehavior input) {
-    switch (input) {
-      case ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS:
-        return ash::mojom::ShelfAutoHideBehavior::
-            SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS;
-      case ash::SHELF_AUTO_HIDE_BEHAVIOR_NEVER:
-        return ash::mojom::ShelfAutoHideBehavior::
-            SHELF_AUTO_HIDE_BEHAVIOR_NEVER;
-      case ash::SHELF_AUTO_HIDE_ALWAYS_HIDDEN:
-        return ash::mojom::ShelfAutoHideBehavior::SHELF_AUTO_HIDE_ALWAYS_HIDDEN;
-    }
-    NOTREACHED();
-    return ash::mojom::ShelfAutoHideBehavior::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS;
-  }
-
-  static bool FromMojom(ash::mojom::ShelfAutoHideBehavior input,
-                        ash::ShelfAutoHideBehavior* out) {
-    switch (input) {
-      case ash::mojom::ShelfAutoHideBehavior::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS:
-        *out = ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS;
-        return true;
-      case ash::mojom::ShelfAutoHideBehavior::SHELF_AUTO_HIDE_BEHAVIOR_NEVER:
-        *out = ash::SHELF_AUTO_HIDE_BEHAVIOR_NEVER;
-        return true;
-      case ash::mojom::ShelfAutoHideBehavior::SHELF_AUTO_HIDE_ALWAYS_HIDDEN:
-        *out = ash::SHELF_AUTO_HIDE_ALWAYS_HIDDEN;
-        return true;
-    }
-    NOTREACHED();
-    return false;
-  }
-};
-
-template <>
-struct EnumTraits<ash::mojom::ShelfAlignment, ash::ShelfAlignment> {
-  static ash::mojom::ShelfAlignment ToMojom(ash::ShelfAlignment input) {
-    switch (input) {
-      case ash::SHELF_ALIGNMENT_BOTTOM:
-        return ash::mojom::ShelfAlignment::SHELF_ALIGNMENT_BOTTOM;
-      case ash::SHELF_ALIGNMENT_LEFT:
-        return ash::mojom::ShelfAlignment::SHELF_ALIGNMENT_LEFT;
-      case ash::SHELF_ALIGNMENT_RIGHT:
-        return ash::mojom::ShelfAlignment::SHELF_ALIGNMENT_RIGHT;
-      case ash::SHELF_ALIGNMENT_BOTTOM_LOCKED:
-        return ash::mojom::ShelfAlignment::SHELF_ALIGNMENT_BOTTOM_LOCKED;
-    }
-    NOTREACHED();
-    return ash::mojom::ShelfAlignment::SHELF_ALIGNMENT_BOTTOM;
-  }
-
-  static bool FromMojom(ash::mojom::ShelfAlignment input,
-                        ash::ShelfAlignment* out) {
-    switch (input) {
-      case ash::mojom::ShelfAlignment::SHELF_ALIGNMENT_BOTTOM:
-        *out = ash::SHELF_ALIGNMENT_BOTTOM;
-        return true;
-      case ash::mojom::ShelfAlignment::SHELF_ALIGNMENT_LEFT:
-        *out = ash::SHELF_ALIGNMENT_LEFT;
-        return true;
-      case ash::mojom::ShelfAlignment::SHELF_ALIGNMENT_RIGHT:
-        *out = ash::SHELF_ALIGNMENT_RIGHT;
-        return true;
-      case ash::mojom::ShelfAlignment::SHELF_ALIGNMENT_BOTTOM_LOCKED:
-        *out = ash::SHELF_ALIGNMENT_BOTTOM_LOCKED;
-        return true;
-    }
-    NOTREACHED();
-    return false;
-  }
-};
-
-}  // namespace mojo
-
-#endif  // ASH_PUBLIC_CPP_SHELF_INTEGRATION_TEST_API_STRUCT_MOJOM_TRAITS_H_
diff --git a/ash/public/interfaces/BUILD.gn b/ash/public/interfaces/BUILD.gn
index 6fc0e57..12d9fd51 100644
--- a/ash/public/interfaces/BUILD.gn
+++ b/ash/public/interfaces/BUILD.gn
@@ -4,15 +4,7 @@
 
 import("//mojo/public/tools/bindings/mojom.gni")
 
-# Depend upon //ash/public/cpp, which has a public_dep on this. The two targets
-# must be bundled together as the typemaps depend upon //ash/public/cpp,
-# and //ash/public/cpp needs to depend on this for generated code (such as
-# enums and constants).
-mojom("interfaces_internal") {
-  visibility = [
-    "//ash/public/cpp:*",
-    "//ash/public/interfaces:test_interfaces",
-  ]
+mojom("interfaces") {
   disable_variants = true
 
   sources = [
@@ -27,7 +19,6 @@
     "ime_controller.mojom",
     "ime_info.mojom",
     "night_light_controller.mojom",
-    "shelf_integration_test_api.mojom",
     "tray_action.mojom",
     "voice_interaction_controller.mojom",
     "vpn_list.mojom",
@@ -55,7 +46,7 @@
     "//url/mojom:url_mojom_gurl",
   ]
 
-  component_output_prefix = "ash_public_interfaces_internal"
+  component_output_prefix = "ash_public_interfaces"
   export_class_attribute = "ASH_PUBLIC_EXPORT"
   export_define = "ASH_PUBLIC_IMPLEMENTATION=1"
   export_header = "ash/public/cpp/ash_public_export.h"
@@ -69,7 +60,7 @@
     "status_area_widget_test_api.test-mojom",
   ]
   deps = [
-    "//ash/public/interfaces:interfaces_internal",
+    ":interfaces",
     "//components/account_id/interfaces",
     "//mojo/public/mojom/base",
     "//ui/gfx/geometry/mojo",
diff --git a/ash/public/interfaces/shelf_integration_test_api.mojom b/ash/public/interfaces/shelf_integration_test_api.mojom
deleted file mode 100644
index 43bf312..0000000
--- a/ash/public/interfaces/shelf_integration_test_api.mojom
+++ /dev/null
@@ -1,50 +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.
-
-module ash.mojom;
-
-// These values match ash::ShelfAutoHideBehavior.
-enum ShelfAutoHideBehavior {
-  SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS,  // Always auto-hide.
-  SHELF_AUTO_HIDE_BEHAVIOR_NEVER,   // Never auto-hide.
-  SHELF_AUTO_HIDE_ALWAYS_HIDDEN,    // Always hide.
-};
-
-// These values match ash::ShelfAlignment.
-enum ShelfAlignment {
-  SHELF_ALIGNMENT_BOTTOM,         // Bottom alignment.
-  SHELF_ALIGNMENT_LEFT,           // Left alignment.
-  SHELF_ALIGNMENT_RIGHT,          // Right alignment.
-  SHELF_ALIGNMENT_BOTTOM_LOCKED,  // Bottom alignment, set temporarily and not
-                                  // saved to preferences.
-};
-
-// Test interface used to interact with the Shelf from integration tests.
-// Note this interface applies the shelf properties from the call
-// arguments and might be lost if tests do something that triggers
-// applying shelf properties from prefs, such as switching user,
-// entering/exiting tablet mode, changing display config, etc.
-interface ShelfIntegrationTestApi {
-  // Returns the auto hide behavior.
-  // |display_id| represents the display that contains the shelf. |display_id|
-  // must be valid.
-  GetAutoHideBehavior(int64 display_id) => (ShelfAutoHideBehavior behavior);
-
-  // Sets the auto hide behavior.
-  // |display_id| represents the display that contains the shelf. |display_id|
-  // must be valid.
-  // |behavior| is the new behavior.
-  SetAutoHideBehavior(int64 display_id, ShelfAutoHideBehavior behavior) => ();
-
-  // Sets the alignment.
-  // |display_id| represents the display that contains the shelf. |display_id|
-  // must be valid.
-  // |alignment| is the new alignment.
-  SetAlignment(int64 display_id, ShelfAlignment alignment) => ();
-
-  // Returns the alignment.
-  // |display_id| represents the display that contains the shelf. |display_id|
-  // must be valid.
-  GetAlignment(int64 display_id) => (ShelfAlignment alignment);
-};
diff --git a/ash/public/interfaces/shelf_integration_test_api.typemap b/ash/public/interfaces/shelf_integration_test_api.typemap
deleted file mode 100644
index b0af960..0000000
--- a/ash/public/interfaces/shelf_integration_test_api.typemap
+++ /dev/null
@@ -1,13 +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.
-
-mojom = "//ash/public/interfaces/shelf_integration_test_api.mojom"
-public_headers = [ "//ash/public/cpp/shelf_types.h" ]
-traits_headers =
-    [ "//ash/public/cpp/shelf_integration_test_api_struct_mojom_traits.h" ]
-
-type_mappings = [
-  "ash.mojom.ShelfAlignment=ash::ShelfAlignment",
-  "ash.mojom.ShelfAutoHideBehavior=ash::ShelfAutoHideBehavior",
-]
diff --git a/ash/public/interfaces/typemaps.gni b/ash/public/interfaces/typemaps.gni
deleted file mode 100644
index 085a6c0..0000000
--- a/ash/public/interfaces/typemaps.gni
+++ /dev/null
@@ -1,5 +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.
-
-typemaps = [ "//ash/public/interfaces/shelf_integration_test_api.typemap" ]
diff --git a/ash/wallpaper/wallpaper_controller_impl.cc b/ash/wallpaper/wallpaper_controller_impl.cc
index 48162422..030f26f 100644
--- a/ash/wallpaper/wallpaper_controller_impl.cc
+++ b/ash/wallpaper/wallpaper_controller_impl.cc
@@ -1561,17 +1561,11 @@
       use_small ? WALLPAPER_LAYOUT_CENTER : WALLPAPER_LAYOUT_CENTER_CROPPED;
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
   base::FilePath file_path;
-  base::Optional<user_manager::UserType> active_user_type =
-      Shell::Get()->session_controller()->GetUserType();
 
   // The wallpaper is determined in the following order:
   // Guest wallpaper, child wallpaper, customized default wallpaper, and regular
   // default wallpaper.
-  // TODO(wzang|xdai): The current code intentionally distinguishes between
-  // |active_user_type| and |user_type|. We should try to unify them.
-  if (user_type == user_manager::USER_TYPE_GUEST ||
-      (active_user_type &&
-       *active_user_type == user_manager::USER_TYPE_GUEST)) {
+  if (user_type == user_manager::USER_TYPE_GUEST) {
     const std::string switch_string =
         use_small ? chromeos::switches::kGuestWallpaperSmall
                   : chromeos::switches::kGuestWallpaperLarge;
diff --git a/ash/wallpaper/wallpaper_controller_unittest.cc b/ash/wallpaper/wallpaper_controller_unittest.cc
index f18bb7c..76e0620 100644
--- a/ash/wallpaper/wallpaper_controller_unittest.cc
+++ b/ash/wallpaper/wallpaper_controller_unittest.cc
@@ -375,13 +375,15 @@
                          base::Time::Now().LocalMidnight());
   }
 
-  // Helper function to create a |WallpaperUserInfo| structwith default values.
-  // In addition, clear the wallpaper count and the decoding request list. May
-  // be called multiple times for the same |account_id|.
-  WallpaperUserInfo InitializeUser(const AccountId& account_id) {
+  // Creates a |WallpaperUserInfo| struct for |account_id| and optional |type|.
+  // Additionally, clear the wallpaper count and the decoding request list.
+  // This may be called multiple times for the same |account_id|.
+  WallpaperUserInfo InitializeUser(
+      const AccountId& account_id,
+      user_manager::UserType type = user_manager::USER_TYPE_REGULAR) {
     WallpaperUserInfo wallpaper_user_info;
     wallpaper_user_info.account_id = account_id;
-    wallpaper_user_info.type = user_manager::USER_TYPE_REGULAR;
+    wallpaper_user_info.type = type;
     wallpaper_user_info.is_ephemeral = false;
     wallpaper_user_info.has_gaia_account = true;
     ClearWallpaperCount();
@@ -1356,9 +1358,10 @@
   // instead of the regular default wallpaper.
   UpdateDisplay("1600x1200");
   RunAllTasksUntilIdle();
-  controller_->SetDefaultWallpaper(InitializeUser(account_id_1),
-                                   wallpaper_files_id_1,
-                                   true /*show_wallpaper=*/);
+
+  controller_->SetDefaultWallpaper(
+      InitializeUser(account_id_1, user_manager::USER_TYPE_GUEST),
+      wallpaper_files_id_1, true /*show_wallpaper=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(1, GetWallpaperCount());
   EXPECT_EQ(controller_->GetWallpaperType(), DEFAULT);
@@ -1371,9 +1374,9 @@
 
   UpdateDisplay("800x600");
   RunAllTasksUntilIdle();
-  controller_->SetDefaultWallpaper(InitializeUser(account_id_1),
-                                   wallpaper_files_id_1,
-                                   true /*show_wallpaper=*/);
+  controller_->SetDefaultWallpaper(
+      InitializeUser(account_id_1, user_manager::USER_TYPE_GUEST),
+      wallpaper_files_id_1, true /*show_wallpaper=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(1, GetWallpaperCount());
   EXPECT_EQ(controller_->GetWallpaperType(), DEFAULT);
diff --git a/ash/wm/splitview/split_view_controller.cc b/ash/wm/splitview/split_view_controller.cc
index 3db41ca..72cadb99 100644
--- a/ash/wm/splitview/split_view_controller.cc
+++ b/ash/wm/splitview/split_view_controller.cc
@@ -261,7 +261,9 @@
         CurrentValueBetween(starting_position_, ending_position_);
     split_view_controller_->NotifyDividerPositionChanged();
     split_view_controller_->UpdateSnappedWindowsAndDividerBounds();
-    split_view_controller_->SetWindowsTransformDuringResizing();
+    // Updating the window may stop animation.
+    if (is_animating())
+      split_view_controller_->SetWindowsTransformDuringResizing();
   }
 
   SplitViewController* split_view_controller_;
@@ -672,8 +674,11 @@
   const bool is_divider_animating = IsDividerAnimating();
   if (is_resizing_ || is_divider_animating) {
     is_resizing_ = false;
-    if (is_divider_animating)
-      StopAndShoveAnimatedDivider();
+    if (is_divider_animating) {
+      // Don't call StopAndShoveAnimatedDivider as it will call observers.
+      divider_snap_animation_->Stop();
+      divider_position_ = divider_snap_animation_->ending_position();
+    }
     EndResizeImpl();
   }
 
diff --git a/base/DEPS b/base/DEPS
index 133105cd..29883dd4 100644
--- a/base/DEPS
+++ b/base/DEPS
@@ -14,4 +14,7 @@
 
   # ICU dependendencies must be separate from the rest of base.
   "-i18n",
+
+  # //base/util can use //base but not vice versa.
+  "-util",
 ]
diff --git a/base/callback.h b/base/callback.h
index 4aad5e8..5b01b9f 100644
--- a/base/callback.h
+++ b/base/callback.h
@@ -125,11 +125,6 @@
     return !operator==(other);
   }
 
-  // TODO(http://crbug.com/937566): Deprecated, use == or != instead.
-  bool Equals(const RepeatingCallback& other) const {
-    return EqualsInternal(other);
-  }
-
   R Run(Args... args) const & {
     PolymorphicInvoke f =
         reinterpret_cast<PolymorphicInvoke>(this->polymorphic_invoke());
diff --git a/base/callback_unittest.nc b/base/callback_unittest.nc
index 3261529..cdc48af 100644
--- a/base/callback_unittest.nc
+++ b/base/callback_unittest.nc
@@ -15,16 +15,16 @@
 class Child : Parent {
 };
 
-#if defined(NCTEST_EQUALS_REQUIRES_SAMETYPE)  // [r"fatal error: no viable conversion from 'RepeatingCallback<int \(\)>' to 'const RepeatingCallback<void \(\)>'"]
+#if defined(NCTEST_EQUALS_REQUIRES_SAMETYPE)  // [r"fatal error: invalid operands to binary expression \('Callback<void \(\)>' \(aka 'RepeatingCallback<void \(\)>'\) and 'Callback<int \(\)>' \(aka 'RepeatingCallback<int \(\)>'\)\)"]
 
 // Attempting to call comparison function on two callbacks of different type.
 //
 // This should be a compile time failure because each callback type should be
 // considered distinct.
 void WontCompile() {
-  Closure c1;
+  Callback<void()> c1;
   Callback<int()> c2;
-  c1.Equals(c2);
+  c1 == c2;
 }
 
 #elif defined(NCTEST_CONSTRUCTION_FROM_SUBTYPE)  // [r"fatal error: no viable conversion from 'Callback<base::Parent \(\)>' to 'Callback<base::Child \(\)>'"]
diff --git a/build/android/lint/suppressions.xml b/build/android/lint/suppressions.xml
index 193c9cb..03d8749b 100644
--- a/build/android/lint/suppressions.xml
+++ b/build/android/lint/suppressions.xml
@@ -352,9 +352,6 @@
     <ignore regexp="The resource `R.string.search_widget_title.*` appears to be unused"/>
     <!-- 1 resource used by android tv to generate resources.zip file -->
     <ignore regexp="chromecast/internal/shell/browser/android/java/res/drawable-hdpi/ic_settings_cast.png"/>
-    <!-- TODO(crbug.com/909915): Remove this after full Lite mode launch. -->
-    <!-- 12 resources used by Data Saver during rebranding to Lite mode -->
-    <ignore regexp="The resource `R.string..*lite_mode` appears to be unused"/>
     <!-- Module titles may only be used by the Play Store. -->
     <ignore regexp="The resource `R.string.*_module_title` appears to be unused"/>
     <!-- Old-style and new-style WebAPKs use same resources for simplicity. Old-style WebAPKs do
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index 06d15ba..94c08710 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-8911081207211170128
\ No newline at end of file
+8911053143154176352
\ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index 625f04a..2c1ae0c 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-8911085935913886544
\ No newline at end of file
+8911052059797671584
\ No newline at end of file
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index 1cd97302..447c1e4 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -135,14 +135,6 @@
   "java/src/org/chromium/chrome/browser/bookmarkswidget/BookmarkWidgetProvider.java",
   "java/src/org/chromium/chrome/browser/bookmarkswidget/BookmarkWidgetProxy.java",
   "java/src/org/chromium/chrome/browser/bookmarkswidget/BookmarkWidgetService.java",
-  "java/src/org/chromium/chrome/browser/browseractions/BrowserActionActivity.java",
-  "java/src/org/chromium/chrome/browser/browseractions/BrowserActionsContextMenuHelper.java",
-  "java/src/org/chromium/chrome/browser/browseractions/BrowserActionsContextMenuItemDelegate.java",
-  "java/src/org/chromium/chrome/browser/browseractions/BrowserActionsCustomContextMenuItem.java",
-  "java/src/org/chromium/chrome/browser/browseractions/BrowserActionsService.java",
-  "java/src/org/chromium/chrome/browser/browseractions/BrowserActionsTabCreatorManager.java",
-  "java/src/org/chromium/chrome/browser/browseractions/BrowserActionsTabModelSelector.java",
-  "java/src/org/chromium/chrome/browser/browseractions/BrowserActionsTabPersistencePolicy.java",
   "java/src/org/chromium/chrome/browser/browserservices/BrowserServicesMetrics.java",
   "java/src/org/chromium/chrome/browser/browserservices/BrowserSessionContentHandler.java",
   "java/src/org/chromium/chrome/browser/browserservices/BrowserSessionContentUtils.java",
@@ -1379,6 +1371,7 @@
   "java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfInfoBarController.java",
   "java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfModelObserverBridge.java",
   "java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfShareActivity.java",
+  "java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfMetrics.java",
   "java/src/org/chromium/chrome/browser/send_tab_to_self/TargetDeviceInfo.java",
   "java/src/org/chromium/chrome/browser/services/AccountsChangedReceiver.java",
   "java/src/org/chromium/chrome/browser/services/AndroidEduAndChildAccountHelper.java",
diff --git a/chrome/android/chrome_junit_test_java_sources.gni b/chrome/android/chrome_junit_test_java_sources.gni
index 9277cf0..76edd56 100644
--- a/chrome/android/chrome_junit_test_java_sources.gni
+++ b/chrome/android/chrome_junit_test_java_sources.gni
@@ -20,7 +20,6 @@
   "junit/src/org/chromium/chrome/browser/background_sync/BackgroundSyncBackgroundTaskSchedulerTest.java",
   "junit/src/org/chromium/chrome/browser/background_sync/BackgroundSyncBackgroundTaskTest.java",
   "junit/src/org/chromium/chrome/browser/background_task_scheduler/NativeBackgroundTaskTest.java",
-  "junit/src/org/chromium/chrome/browser/browseractions/BrowserActionsIntentTest.java",
   "junit/src/org/chromium/chrome/browser/browserservices/ClearDataDialogResultRecorderTest.java",
   "junit/src/org/chromium/chrome/browser/browserservices/ClientAppBroadcastReceiverTest.java",
   "junit/src/org/chromium/chrome/browser/browserservices/ClientAppDataRegisterTest.java",
diff --git a/chrome/android/chrome_test_java_sources.gni b/chrome/android/chrome_test_java_sources.gni
index 200c567..e17aba2 100644
--- a/chrome/android/chrome_test_java_sources.gni
+++ b/chrome/android/chrome_test_java_sources.gni
@@ -62,7 +62,6 @@
   "javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkModelTest.java",
   "javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkPersonalizedSigninPromoTest.java",
   "javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkTest.java",
-  "javatests/src/org/chromium/chrome/browser/browseractions/BrowserActionActivityTest.java",
   "javatests/src/org/chromium/chrome/browser/browserservices/OriginVerifierTest.java",
   "javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClientTest.java",
   "javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityTest.java",
diff --git a/chrome/android/features/create_stripped_java_factory.py b/chrome/android/features/create_stripped_java_factory.py
index 69be0a3a..92df562 100755
--- a/chrome/android/features/create_stripped_java_factory.py
+++ b/chrome/android/features/create_stripped_java_factory.py
@@ -14,104 +14,161 @@
 resulting target. The real factory uses the feature's internal implementations,
 which is why it is not included in the feature's public_java target.
 
-This script generates stripped down factory files from real factory files to
-reduce the burden of maintenance. It checks to make sure that these factory
-files are as simple as possible and replaces multi-line java return statements
-with 'return null;'.
+This script generates a stripped down factory file from real factory file to
+reduce the burden of maintenance. The stripped down factory will have dummy
+implementations of all public methods of the real factory.
 
-In order to keep the regex simple and easily understood, the java factory files
-have a few strict requirements. This avoids the need to take care of every
-corner case involving comments or strings. Since the generated factory file is
-only used during the build, and the real one is used at runtime, it is
-sufficient to have the build pass with simple modifications.
-
-We require that these factory files to:
-  - Contain exactly one top-level class.
-    - No inner classes.
-  - Contain a private constructor with no arguments (it won't be used).
-  - Contain only public static methods apart from the constructor.
-    - Only void and object return types are supported (no primitives).
-  - Avoid explicitly importing internal classes and their dependencies.
-    - The factory should be in the same package as the internal classes it
-      instantiates.
+This script requires that the real factory file has exactly one top-level class.
 """
 
 import argparse
-import re
-import os
+import datetime
 import sys
+import os
 
 sys.path.append(os.path.join(os.path.dirname(__file__),
                              os.pardir, os.pardir, os.pardir,
                              'build', 'android', 'gyp'))
 from util import build_utils
 
+sys.path.append(
+    os.path.join(
+        os.path.dirname(__file__), os.pardir, os.pardir, os.pardir,
+        'third_party', 'javalang', 'src'))
+import javalang
 
-# Matches multi-line public static methods:
-# '^(    public static ' - Matches the first part of the method signature.
-# '(?!void)' - Do not match methods signatures that return void.
-# '[^{]+ {)' - Matches the rest of the method signature until the opening brace.
-# '.+?' - Non-greedy match to only match one method body.
-# '^(    })$' - Matches the closing brace of the method.
-_RE_PUBLIC_STATIC_NOT_VOID_METHOD = re.compile(
-    r'^(    public static (?!void)[^{]+ {).+?^(    })$',
-    re.DOTALL | re.MULTILINE)
-# Replacement string to replace the entire method body with a null return.
-_RETURN_NULL = r'''\g<1>
-      return null;
-\g<2>'''
+_PARAM_TEMPLATE = '{TYPE} {NAME}'
+_METHOD_TEMPLATE = ('{MODIFIERS} {RETURN_TYPE} {NAME} ({PARAMS}) '
+                    '{{ return {RETURN_VAL}; }}')
+_FILE_TEMPLATE = '''\
+// Copyright {YEAR} The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// This file is autogenerated by
+//     {SCRIPT_NAME}
+// Please do not change its content.
 
-# Matches multi-line public static void methods:
-# Same as for public static methods, explicitly specify void return type.
-_RE_PUBLIC_STATIC_VOID_METHOD = re.compile(
-    r'^(    public static void [^{]+ {).+?^(    })$', re.DOTALL | re.MULTILINE)
-# Replacement string to replace the entire method body with an empty return.
-_RETURN = r'''\g<1>
-      return;
-\g<2>'''
+package {PACKAGE};
 
-_RE_CLASS = re.compile(r'\bclass (\w+)\b')
-_PRIVATE_CONSTRUCTOR = 'private {0}() {{}}\n'
+{IMPORTS}
+
+{MODIFIERS} class {CLASS_NAME} {{
+{METHODS}
+}}
+'''
 
 
-def _ParseArgs(args):
+def _GetScriptName():
+  script_components = os.path.abspath(__file__).split(os.path.sep)
+  chrome_index = 0
+  for idx, value in enumerate(script_components):
+    if value == 'chrome':
+      chrome_index = idx
+      break
+  return os.sep.join(script_components[chrome_index:])
+
+
+def _GetDefaultReturnVal(type_name):
+  if type_name in ('byte', 'short', 'int', 'long', 'float', 'double'):
+    return '0'
+  elif type_name == 'boolean':
+    return 'false'
+  elif type_name == 'void':
+    return ''
+  else:
+    return 'null'
+
+
+def _ParseImports(imports):
+  """Returns dict mapping from type name to import path."""
+  import_dict = {}
+  for import_ in imports:
+    if import_.static:
+      continue
+    assert not import_.wildcard
+    name = import_.path.split('.')[-1]
+    import_dict[name] = import_.path
+  return import_dict
+
+
+def _ParsePublicMethodsSignatureTypes(clazz):
+  """Returns set of type names used in the signatures of all public methods of
+  the given class.
+  """
+  types = set()
+  for method in clazz.methods:
+    if 'public' in method.modifiers:
+      types.update([p.type.name for p in method.parameters])
+      # If return type is void return_type will be none.
+      if method.return_type:
+        types.add(method.return_type.name)
+  return types
+
+
+def _FormatMethod(method):
+  params = []
+  for param in method.parameters:
+    param_dict = {
+        'TYPE': param.type.name,
+        'NAME': param.name,
+    }
+    params.append(_PARAM_TEMPLATE.format(**param_dict))
+  return_type = method.return_type.name if method.return_type else 'void'
+  method_dict = {
+      'MODIFIERS': ' '.join(method.modifiers),
+      'RETURN_TYPE': return_type,
+      'NAME': method.name,
+      'PARAMS': ', '.join(params),
+      'RETURN_VAL': _GetDefaultReturnVal(return_type),
+  }
+  return (_METHOD_TEMPLATE.format(**method_dict))
+
+
+def _FormatPublicMethods(clazz):
+  methods = []
+  for method in clazz.methods:
+    if 'public' in method.modifiers:
+      methods.append(_FormatMethod(method))
+  return methods
+
+
+def _FilterAndFormatImports(import_dict, signature_types):
+  """Returns formatted imports required by the passed signature types."""
+  formatted_imports = [
+      'import %s;' % import_dict[t] for t in signature_types if t in import_dict
+  ]
+  return sorted(formatted_imports)
+
+
+def main(args):
   parser = argparse.ArgumentParser()
   parser.add_argument('--input', required=True, help='Input java file path.')
   parser.add_argument('--output', required=True, help='Output java file path.')
   options = parser.parse_args(args)
-  return options
 
-
-def _EnsureSimpleFactory(content):
-  """Assert that the java factory file is very simple.
-
-  This is important since we are using the build system to swap out .class
-  files of corresponding generated and internal java factory files. Keeping the
-  factory files as simple as possible minimizes the overhead of reasoning about
-  the factory code. It is already sufficiently complex to deduce which file a
-  target is actually using when calling one of these factories.
-  """
-  classes = _RE_CLASS.findall(content)
-  assert len(classes) == 1, 'Factory must contain exactly one class.'
-  class_name = classes[0]
-  assert _PRIVATE_CONSTRUCTOR.format(class_name) in content, (
-      'Factory must have a private constructor with no arguments.')
-
-
-def _ReplaceMethodBodies(content):
-  content = _RE_PUBLIC_STATIC_NOT_VOID_METHOD.sub(_RETURN_NULL, content)
-  content = _RE_PUBLIC_STATIC_VOID_METHOD.sub(_RETURN, content)
-  return content
-
-
-def main(args):
-  options = _ParseArgs(args)
   with open(options.input, 'r') as f:
     content = f.read()
-  _EnsureSimpleFactory(content)
-  replaced_content = _ReplaceMethodBodies(content)
+
+  java_ast = javalang.parse.parse(content)
+  assert len(java_ast.types) == 1, 'Can only process Java files with one class'
+  clazz = java_ast.types[0]
+  import_dict = _ParseImports(java_ast.imports)
+  signature_types = _ParsePublicMethodsSignatureTypes(clazz)
+  formatted_public_methods = _FormatPublicMethods(clazz)
+  formatted_imports = _FilterAndFormatImports(import_dict, signature_types)
+
+  file_dict = {
+      'YEAR': str(datetime.date.today().year),
+      'SCRIPT_NAME': _GetScriptName(),
+      'PACKAGE': java_ast.package.name,
+      'IMPORTS': '\n'.join(formatted_imports),
+      'MODIFIERS': ' '.join(clazz.modifiers),
+      'CLASS_NAME': clazz.name,
+      'METHODS': '\n'.join(['    ' + m for m in formatted_public_methods])
+  }
   with build_utils.AtomicOutput(options.output) as f:
-    f.write(replaced_content)
+    f.write(_FILE_TEMPLATE.format(**file_dict))
 
 
 if __name__ == '__main__':
diff --git a/chrome/android/features/create_stripped_java_factory.pydeps b/chrome/android/features/create_stripped_java_factory.pydeps
index db7ee793..b8cada7 100644
--- a/chrome/android/features/create_stripped_java_factory.pydeps
+++ b/chrome/android/features/create_stripped_java_factory.pydeps
@@ -4,4 +4,12 @@
 ../../../build/android/gyp/util/build_utils.py
 ../../../build/android/gyp/util/md5_check.py
 ../../../build/gn_helpers.py
+../../../third_party/javalang/src/javalang/__init__.py
+../../../third_party/javalang/src/javalang/ast.py
+../../../third_party/javalang/src/javalang/javadoc.py
+../../../third_party/javalang/src/javalang/parse.py
+../../../third_party/javalang/src/javalang/parser.py
+../../../third_party/javalang/src/javalang/tokenizer.py
+../../../third_party/javalang/src/javalang/tree.py
+../../../third_party/javalang/src/javalang/util.py
 create_stripped_java_factory.py
diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml
index 948cf72..7b44476 100644
--- a/chrome/android/java/AndroidManifest.xml
+++ b/chrome/android/java/AndroidManifest.xml
@@ -882,23 +882,6 @@
             {{ self.supports_vr() }}
         </activity>
 
-        <!-- Activities for Browser Actions -->
-        <activity android:name="org.chromium.chrome.browser.browseractions.BrowserActionActivity"
-            android:theme="@style/Theme.Chromium.Activity.Fullscreen.Transparent"
-            android:exported="true"
-            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|mcc|mnc|screenLayout|smallestScreenSize">
-            <intent-filter>
-                <action android:name="androidx.browser.browseractions.browser_action_open" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <data android:scheme="http" />
-                <data android:scheme="https" />
-            </intent-filter>
-        </activity>
-
-        <service android:name="org.chromium.chrome.browser.browseractions.BrowserActionsService"
-            android:exported="false">
-        </service>
-
         <!-- Components for Trusted Web Activities -->
         <receiver android:name="org.chromium.chrome.browser.browserservices.ClientAppBroadcastReceiver"
             android:exported="true">
diff --git a/chrome/android/java/monochrome_public_bundle__base_bundle_module.AndroidManifest.expected b/chrome/android/java/monochrome_public_bundle__base_bundle_module.AndroidManifest.expected
index 64d14ff..ef8684df 100644
--- a/chrome/android/java/monochrome_public_bundle__base_bundle_module.AndroidManifest.expected
+++ b/chrome/android/java/monochrome_public_bundle__base_bundle_module.AndroidManifest.expected
@@ -251,18 +251,6 @@
         android:theme="@style/Theme.Chromium.DialogWhenLarge"/>
     <activity
         android:configChanges="orientation|keyboardHidden|keyboard|screenSize|mcc|mnc|screenLayout|smallestScreenSize"
-        android:exported="true"
-        android:name="org.chromium.chrome.browser.browseractions.BrowserActionActivity"
-        android:theme="@style/Theme.Chromium.Activity.Fullscreen.Transparent">
-      <intent-filter>
-        <action android:name="androidx.browser.browseractions.browser_action_open"/>
-        <category android:name="android.intent.category.DEFAULT"/>
-        <data android:scheme="http"/>
-        <data android:scheme="https"/>
-      </intent-filter>
-    </activity>
-    <activity
-        android:configChanges="orientation|keyboardHidden|keyboard|screenSize|mcc|mnc|screenLayout|smallestScreenSize"
         android:name="org.chromium.chrome.browser.bookmarks.BookmarkAddActivity"
         android:theme="@style/Theme.Chromium.DialogWhenLarge"
         android:windowSoftInputMode="stateHidden">
@@ -1427,9 +1415,6 @@
         android:permission="android.permission.BIND_REMOTEVIEWS"/>
     <service
         android:exported="false"
-        android:name="org.chromium.chrome.browser.browseractions.BrowserActionsService"/>
-    <service
-        android:exported="false"
         android:name="org.chromium.chrome.browser.crash.ChromeMinidumpUploadJobService"
         android:permission="android.permission.BIND_JOB_SERVICE"/>
     <service
diff --git a/chrome/android/java/res/values/ids.xml b/chrome/android/java/res/values/ids.xml
index 174ce3e..b958b01 100644
--- a/chrome/android/java/res/values/ids.xml
+++ b/chrome/android/java/res/values/ids.xml
@@ -115,18 +115,6 @@
     <item type="id" name="menu_item_original_background" />
     <item type="id" name="menu_item_background_drawable_position" />
 
-    <!-- Menu item IDs for Browser Action menu -->
-    <item type="id" name="browser_actions_open_in_background" />
-    <item type="id" name="browser_actions_open_in_incognito_tab" />
-    <item type="id" name="browser_actions_save_link_as" />
-    <item type="id" name="browser_actions_copy_address" />
-    <item type="id" name="browser_actions_share" />
-    <item type="id" name="browser_actions_custom_item_one" />
-    <item type="id" name="browser_actions_custom_item_two" />
-    <item type="id" name="browser_actions_custom_item_three" />
-    <item type="id" name="browser_actions_custom_item_four" />
-    <item type="id" name="browser_actions_custom_item_five" />
-
     <!-- VR constants -->
     <item type="id" name="vr_overlay_view" />
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
index c0728ae3..6c4b0d9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -57,8 +57,6 @@
 import org.chromium.chrome.browser.IntentHandler.TabOpenType;
 import org.chromium.chrome.browser.appmenu.AppMenuPropertiesDelegate;
 import org.chromium.chrome.browser.bookmarks.BookmarkUtils;
-import org.chromium.chrome.browser.browseractions.BrowserActionsService;
-import org.chromium.chrome.browser.browseractions.BrowserActionsTabModelSelector;
 import org.chromium.chrome.browser.compositor.CompositorViewHolder;
 import org.chromium.chrome.browser.compositor.layouts.Layout;
 import org.chromium.chrome.browser.compositor.layouts.LayoutManager;
@@ -860,7 +858,6 @@
         @LaunchIntentDispatcher.Action
         int action = maybeDispatchExplicitMainViewIntent(
                 intentForDispatching, sExplicitMainViewIntentDispatchedOnNewIntent);
-        BrowserActionsService.recordTabOpenedNotificationClicked(intent);
         if (action != LaunchIntentDispatcher.Action.CONTINUE) {
             // Pressing back button in CCT should bring user to the caller activity.
             moveTaskToBack(true);
@@ -995,8 +992,6 @@
             RecordUserAction.record("MobileStartup.UserEnteredTabSwitcher");
         }
 
-        BrowserActionsService.onTabbedModeForegrounded();
-
         resetSavedInstanceState();
     }
 
@@ -1074,10 +1069,6 @@
         if (getActivityTab() == null && !isOverviewVisible) {
             toggleOverview();
         }
-
-        if (BrowserActionsService.shouldToggleOverview(getIntent(), isOverviewVisible)) {
-            toggleOverview();
-        }
     }
 
     private boolean isMainIntentFromLauncher(Intent intent) {
@@ -1219,11 +1210,9 @@
 
             boolean hasTabWaitingForReparenting =
                     AsyncTabParamsManager.hasParamsWithTabToReparent();
-            boolean hasBrowserActionTabs = BrowserActionsTabModelSelector.isInitialized()
-                    && BrowserActionsTabModelSelector.getInstance().getTotalTabCount() != 0;
             mCreatedTabOnStartup = getCurrentTabModel().getCount() > 0
                     || mTabModelSelectorImpl.getRestoredTabCount() > 0 || mIntentWithEffect
-                    || hasBrowserActionTabs || hasTabWaitingForReparenting;
+                    || hasTabWaitingForReparenting;
 
             // We always need to try to restore tabs. The set of tabs might be empty, but at least
             // it will trigger the notification that tab restore is complete which is needed by
@@ -1232,10 +1221,6 @@
 
             mMainIntentMetrics.setIgnoreEvents(true);
             mTabModelSelectorImpl.restoreTabs(activeTabBeingRestored);
-            if (hasBrowserActionTabs) {
-                BrowserActionsTabModelSelector.getInstance().mergeBrowserActionsTabModel(
-                        this, !mIntentWithEffect);
-            }
             mMainIntentMetrics.setIgnoreEvents(false);
 
             // Only create an initial tab if no tabs were restored and no intent was handled.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionActivity.java
deleted file mode 100644
index 94df9acf..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionActivity.java
+++ /dev/null
@@ -1,194 +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.
-
-package org.chromium.chrome.browser.browseractions;
-
-import android.app.PendingIntent;
-import android.content.Intent;
-import android.graphics.Point;
-import android.net.Uri;
-import android.os.Bundle;
-import android.support.customtabs.browseractions.BrowserActionItem;
-import android.support.customtabs.browseractions.BrowserActionsIntent;
-import android.text.TextUtils;
-import android.view.Menu;
-import android.view.View;
-
-import org.chromium.base.Log;
-import org.chromium.base.VisibleForTesting;
-import org.chromium.base.task.PostTask;
-import org.chromium.chrome.browser.IntentHandler;
-import org.chromium.chrome.browser.UrlConstants;
-import org.chromium.chrome.browser.contextmenu.ContextMenuParams;
-import org.chromium.chrome.browser.download.items.OfflineContentAggregatorNotificationBridgeUiFactory;
-import org.chromium.chrome.browser.firstrun.FirstRunStatus;
-import org.chromium.chrome.browser.gsa.GSAState;
-import org.chromium.chrome.browser.init.AsyncInitializationActivity;
-import org.chromium.chrome.browser.rappor.RapporServiceBridge;
-import org.chromium.chrome.browser.util.IntentUtils;
-import org.chromium.content_public.browser.UiThreadTaskTraits;
-import org.chromium.content_public.common.Referrer;
-import org.chromium.ui.base.MenuSourceType;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * A transparent {@link AsyncInitializationActivity} that displays the Browser Actions context menu.
- */
-public class BrowserActionActivity extends AsyncInitializationActivity {
-    private static final String TAG = "cr_BrowserActions";
-
-    private int mType;
-    private Uri mUri;
-    @VisibleForTesting
-    String mUntrustedCreatorPackageName;
-    @VisibleForTesting
-    List<BrowserActionItem> mActions = new ArrayList<>();
-    private PendingIntent mOnBrowserActionSelectedCallback;
-    private BrowserActionsContextMenuHelper mHelper;
-
-    @Override
-    protected void triggerLayoutInflation() {
-        View view = new View(this);
-        setContentView(view);
-        openContextMenu(view);
-        onInitialLayoutInflationComplete();
-    }
-
-    @Override
-    protected boolean isStartedUpCorrectly(Intent intent) {
-        if (intent == null
-                || !BrowserActionsIntent.ACTION_BROWSER_ACTIONS_OPEN.equals(intent.getAction())) {
-            return false;
-        }
-        mUri = Uri.parse(IntentHandler.getUrlFromIntent(intent));
-        mType = IntentUtils.safeGetIntExtra(
-                intent, BrowserActionsIntent.EXTRA_TYPE, BrowserActionsIntent.URL_TYPE_NONE);
-        mUntrustedCreatorPackageName = BrowserActionsIntent.getUntrustedCreatorPackageName(intent);
-        mOnBrowserActionSelectedCallback = IntentUtils.safeGetParcelableExtra(
-                intent, BrowserActionsIntent.EXTRA_SELECTED_ACTION_PENDING_INTENT);
-        ArrayList<Bundle> bundles = IntentUtils.getParcelableArrayListExtra(
-                intent, BrowserActionsIntent.EXTRA_MENU_ITEMS);
-        if (bundles != null) {
-            mActions = BrowserActionsIntent.parseBrowserActionItems(bundles);
-        }
-        if (mUri == null) {
-            Log.e(TAG, "Missing url");
-            return false;
-        } else if (!UrlConstants.HTTP_SCHEME.equals(mUri.getScheme())
-                && !UrlConstants.HTTPS_SCHEME.equals(mUri.getScheme())) {
-            Log.e(TAG, "Url should only be HTTP or HTTPS scheme");
-            return false;
-        } else if (mUntrustedCreatorPackageName == null) {
-            Log.e(TAG, "Missing creator's package name");
-            return false;
-        } else if (!TextUtils.equals(mUntrustedCreatorPackageName, getPackageName())
-                && (intent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
-            Log.e(TAG, "Intent should not be started with FLAG_ACTIVITY_NEW_TASK");
-            return false;
-        } else if ((intent.getFlags() & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0) {
-            Log.e(TAG, "Intent should not be started with FLAG_ACTIVITY_NEW_DOCUMENT");
-            return false;
-        } else {
-            return true;
-        }
-    }
-
-    /**
-     * Opens a Browser Actions context menu based on the parsed data.
-     */
-    @Override
-    public void openContextMenu(View view) {
-        ContextMenuParams params = createContextMenuParams();
-        Runnable listener = new Runnable() {
-            @Override
-            public void run() {
-                if (FirstRunStatus.getFirstRunFlowComplete()) {
-                    startDelayedNativeInitialization();
-                }
-            }
-        };
-        mHelper = new BrowserActionsContextMenuHelper(this, params, mActions,
-                mUntrustedCreatorPackageName, mOnBrowserActionSelectedCallback, listener);
-        mHelper.displayBrowserActionsMenu(view);
-        return;
-    }
-
-    @Override
-    @VisibleForTesting
-    protected boolean isStartupDelayed() {
-        return super.isStartupDelayed();
-    }
-
-    /**
-     * @return The {@link BrowserActionsContextMenuHelper} for testing.
-     */
-    @VisibleForTesting
-    BrowserActionsContextMenuHelper getHelperForTesting() {
-        return mHelper;
-    }
-
-    /**
-     * Creates a {@link ContextMenuParams} with given Uri and type.
-     * @return The ContextMenuParams used to construct context menu.
-     */
-    private ContextMenuParams createContextMenuParams() {
-        Referrer referrer =
-                IntentHandler.constructValidReferrerForAuthority(mUntrustedCreatorPackageName);
-
-        Point displaySize = new Point();
-        getWindowManager().getDefaultDisplay().getSize(displaySize);
-        float density = getResources().getDisplayMetrics().density;
-        int touchX = (int) ((displaySize.x / 2f) / density);
-        int touchY = (int) ((displaySize.y / 2f) / density);
-
-        return new ContextMenuParams(mType, mUri.toString(), mUri.toString(), mUri.toString(),
-                mUri.toString(), mUri.toString(), mUri.toString(), false /* imageWasFetchedLoFi */,
-                referrer, false /* canSaveMedia */, touchX, touchY,
-                MenuSourceType.MENU_SOURCE_TOUCH);
-    }
-
-    @Override
-    protected boolean shouldDelayBrowserStartup() {
-        return true;
-    }
-
-    @Override
-    public boolean shouldStartGpuProcess() {
-        return true;
-    }
-
-    @Override
-    public void onContextMenuClosed(Menu menu) {
-        super.onContextMenuClosed(menu);
-        if (mHelper != null) {
-            mHelper.onContextMenuClosed();
-        }
-    }
-
-    @Override
-    public void finishNativeInitialization() {
-        super.finishNativeInitialization();
-        OfflineContentAggregatorNotificationBridgeUiFactory.instance();
-        recordClientPackageName();
-        mHelper.onNativeInitialized();
-    }
-
-    private void recordClientPackageName() {
-        if (TextUtils.isEmpty(mUntrustedCreatorPackageName)) return;
-        PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> {
-            RapporServiceBridge.sampleString(
-                    "BrowserActions.ServiceClient.PackageName", mUntrustedCreatorPackageName);
-            if (GSAState.isGsaPackageName(mUntrustedCreatorPackageName)) return;
-            RapporServiceBridge.sampleString("BrowserActions.ServiceClient.PackageNameThirdParty",
-                    mUntrustedCreatorPackageName);
-        });
-    }
-
-    @Override
-    protected boolean requiresFirstRunToBeCompleted(Intent intent) {
-        return false;
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsContextMenuHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsContextMenuHelper.java
deleted file mode 100644
index 6c260d96..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsContextMenuHelper.java
+++ /dev/null
@@ -1,420 +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.
-
-package org.chromium.chrome.browser.browseractions;
-
-import android.app.Activity;
-import android.app.PendingIntent;
-import android.app.PendingIntent.CanceledException;
-import android.app.ProgressDialog;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.res.Resources;
-import android.content.res.Resources.NotFoundException;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.os.Build;
-import android.support.annotation.IntDef;
-import android.support.customtabs.browseractions.BrowserActionItem;
-import android.support.customtabs.browseractions.BrowserActionsIntent;
-import android.support.v4.content.res.ResourcesCompat;
-import android.support.v7.content.res.AppCompatResources;
-import android.util.Pair;
-import android.util.SparseArray;
-import android.view.ContextMenu;
-import android.view.ContextMenu.ContextMenuInfo;
-import android.view.View;
-import android.view.View.OnAttachStateChangeListener;
-import android.view.View.OnCreateContextMenuListener;
-
-import org.chromium.base.Callback;
-import org.chromium.base.ContextUtils;
-import org.chromium.base.Log;
-import org.chromium.base.VisibleForTesting;
-import org.chromium.base.metrics.CachedMetrics.EnumeratedHistogramSample;
-import org.chromium.base.metrics.RecordUserAction;
-import org.chromium.chrome.R;
-import org.chromium.chrome.browser.contextmenu.ChromeContextMenuItem;
-import org.chromium.chrome.browser.contextmenu.ContextMenuItem;
-import org.chromium.chrome.browser.contextmenu.ContextMenuParams;
-import org.chromium.chrome.browser.contextmenu.ContextMenuUi;
-import org.chromium.chrome.browser.contextmenu.PlatformContextMenuUi;
-import org.chromium.chrome.browser.contextmenu.ShareContextMenuItem;
-import org.chromium.chrome.browser.contextmenu.TabularContextMenuUi;
-import org.chromium.chrome.browser.firstrun.FirstRunStatus;
-import org.chromium.ui.base.WindowAndroid.OnCloseContextMenuListener;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * A helper class that handles generating context menus for Browser Actions.
- */
-public class BrowserActionsContextMenuHelper implements OnCreateContextMenuListener,
-                                                        OnCloseContextMenuListener,
-                                                        OnAttachStateChangeListener {
-    /** Notified about events happening for Browser Actions tests. */
-    public interface BrowserActionsTestDelegate {
-        /** Called when menu is shown. */
-        void onBrowserActionsMenuShown();
-
-        /** Called when {@link BrowserActionActivity#finishNativeInitialization} is done. */
-        void onFinishNativeInitialization();
-
-        /** Called when Browser Actions start opening a tab in background */
-        void onOpenTabInBackgroundStart();
-
-        /** Called when Browser Actions start downloading a url */
-        void onDownloadStart();
-
-        /** Initializes data needed for testing. */
-        void initialize(SparseArray<PendingIntent> customActions,
-                List<Pair<Integer, List<ContextMenuItem>>> items,
-                ProgressDialog progressDialog);
-    }
-
-    /**
-     * Defines the actions shown on the Browser Actions context menu.
-     * Note: these values must match the BrowserActionsMenuOption enum in enums.xml.
-     * And the values are persisted to logs so they cannot be renumbered or reused.
-     */
-    @IntDef({BrowserActionsActionId.OPEN_IN_NEW_CHROME_TAB,
-            BrowserActionsActionId.OPEN_IN_INCOGNITO_TAB, BrowserActionsActionId.DOWNLOAD_PAGE,
-            BrowserActionsActionId.COPY_LINK, BrowserActionsActionId.SHARE,
-            BrowserActionsActionId.APP_PROVIDED})
-    @Retention(RetentionPolicy.SOURCE)
-    private @interface BrowserActionsActionId {
-        int OPEN_IN_NEW_CHROME_TAB = 0;
-        int OPEN_IN_INCOGNITO_TAB = 1;
-        int DOWNLOAD_PAGE = 2;
-        int COPY_LINK = 3;
-        int SHARE = 4;
-        // Actions for selecting custom items.
-        int APP_PROVIDED = 5;
-
-        int NUM_ENTRIES = 6;
-    }
-
-    static final List<Integer> CUSTOM_BROWSER_ACTIONS_ID_GROUP =
-            Arrays.asList(R.id.browser_actions_custom_item_one,
-                    R.id.browser_actions_custom_item_two, R.id.browser_actions_custom_item_three,
-                    R.id.browser_actions_custom_item_four, R.id.browser_actions_custom_item_five);
-
-    private static final String TAG = "cr_BrowserActions";
-    private static final boolean IS_NEW_UI_ENABLED = true;
-
-    // Items list that could be included in the Browser Actions context menu for type {@code LINK}.
-    private final List<? extends ContextMenuItem> mBrowserActionsLinkGroup;
-
-    // Map each custom item's id with its PendingIntent action.
-    private final SparseArray<PendingIntent> mCustomItemActionMap = new SparseArray<>();
-
-    private final ContextMenuParams mCurrentContextMenuParams;
-    private final BrowserActionsContextMenuItemDelegate mMenuItemDelegate;
-    private final Activity mActivity;
-    private final Callback<Integer> mItemSelectedCallback;
-    private final Runnable mOnMenuShown;
-    private final Runnable mOnMenuClosed;
-    private final Runnable mOnMenuShownListener;
-    private final Callback<Boolean> mOnShareClickedRunnable;
-    private final PendingIntent mOnBrowserActionSelectedCallback;
-    private final EnumeratedHistogramSample mActionHistogram;
-
-    private final List<Pair<Integer, List<ContextMenuItem>>> mItems;
-
-    private final ProgressDialog mProgressDialog;
-
-    private BrowserActionsTestDelegate mTestDelegate;
-    private int mPendingItemId;
-    private boolean mIsNativeInitialized;
-    private boolean mShouldFinishActivity;
-
-    public BrowserActionsContextMenuHelper(Activity activity, ContextMenuParams params,
-            List<BrowserActionItem> customItems, String sourcePackageName,
-            PendingIntent onBrowserActionSelectedCallback, final Runnable listener) {
-        mActivity = activity;
-        mCurrentContextMenuParams = params;
-        mOnMenuShownListener = listener;
-        mShouldFinishActivity = true;
-
-        mOnMenuShown = new Runnable() {
-            @Override
-            public void run() {
-                mOnMenuShownListener.run();
-                if (mTestDelegate != null) {
-                    mTestDelegate.onBrowserActionsMenuShown();
-                }
-            }
-        };
-        mOnMenuClosed = new Runnable() {
-            @Override
-            public void run() {
-                if (mPendingItemId == 0 && mShouldFinishActivity) {
-                    mActivity.finish();
-                }
-            }
-        };
-        mItemSelectedCallback = new Callback<Integer>() {
-            @Override
-            public void onResult(Integer result) {
-                onItemSelected(result, true);
-            }
-        };
-        mOnShareClickedRunnable = new Callback<Boolean>() {
-            @Override
-            public void onResult(Boolean isShareLink) {
-                mMenuItemDelegate.share(true, mCurrentContextMenuParams.getLinkUrl(), false);
-            }
-        };
-        ShareContextMenuItem shareItem = new ShareContextMenuItem(R.drawable.ic_share_white_24dp,
-                R.string.browser_actions_share, R.id.browser_actions_share, true);
-        shareItem.setCreatorPackageName(sourcePackageName);
-        if (FirstRunStatus.getFirstRunFlowComplete()) {
-            mBrowserActionsLinkGroup = Arrays.asList(
-                    new ChromeContextMenuItem(
-                            ChromeContextMenuItem.Item.BROWSER_ACTIONS_OPEN_IN_BACKGROUND),
-                    new ChromeContextMenuItem(
-                            ChromeContextMenuItem.Item.BROWSER_ACTIONS_OPEN_IN_INCOGNITO_TAB),
-                    new ChromeContextMenuItem(
-                            ChromeContextMenuItem.Item.BROWSER_ACTION_SAVE_LINK_AS),
-                    new ChromeContextMenuItem(
-                            ChromeContextMenuItem.Item.BROWSER_ACTIONS_COPY_ADDRESS),
-                    shareItem);
-        } else {
-            mBrowserActionsLinkGroup =
-                    Arrays.asList(new ChromeContextMenuItem(
-                                          ChromeContextMenuItem.Item.BROWSER_ACTIONS_COPY_ADDRESS),
-                            shareItem);
-        }
-        mMenuItemDelegate = new BrowserActionsContextMenuItemDelegate(mActivity, sourcePackageName);
-        mOnBrowserActionSelectedCallback = onBrowserActionSelectedCallback;
-        mProgressDialog = new ProgressDialog(mActivity);
-        mActionHistogram = new EnumeratedHistogramSample(
-                "BrowserActions.SelectedOption", BrowserActionsActionId.NUM_ENTRIES);
-
-        mItems = buildContextMenuItems(customItems, sourcePackageName);
-    }
-
-    /**
-     * Sets the {@link BrowserActionsTestDelegate} for testing.
-     * @param testDelegate The delegate used to notified Browser Actions events.
-     */
-    @VisibleForTesting
-    void setTestDelegateForTesting(BrowserActionsTestDelegate testDelegate) {
-        mTestDelegate = testDelegate;
-        mTestDelegate.initialize(mCustomItemActionMap, mItems, mProgressDialog);
-    }
-
-    /**
-     * Builds items for Browser Actions context menu.
-     */
-    private List<Pair<Integer, List<ContextMenuItem>>> buildContextMenuItems(
-            List<BrowserActionItem> customItems, String sourcePackageName) {
-        List<Pair<Integer, List<ContextMenuItem>>> menuItems = new ArrayList<>();
-        List<ContextMenuItem> items = new ArrayList<>();
-        items.addAll(mBrowserActionsLinkGroup);
-        addBrowserActionItems(items, customItems, sourcePackageName);
-
-        menuItems.add(new Pair<>(R.string.contextmenu_link_title, items));
-        return menuItems;
-    }
-
-    /**
-     * Adds custom items to the context menu list and populates custom item action map.
-     * @param items List of {@link ContextMenuItem} to display the context menu.
-     * @param customItems List of {@link BrowserActionItem} for custom items.
-     * @param sourcePackageName The package name of the requested app.
-     */
-    private void addBrowserActionItems(List<ContextMenuItem> items,
-            List<BrowserActionItem> customItems, String sourcePackageName) {
-        PackageManager pm = ContextUtils.getApplicationContext().getPackageManager();
-        Resources resources = null;
-        try {
-            resources = pm.getResourcesForApplication(sourcePackageName);
-        } catch (NameNotFoundException e) {
-            Log.e(TAG, "Fail to find the resources", e);
-        }
-        for (int i = 0; i < customItems.size() && i < BrowserActionsIntent.MAX_CUSTOM_ITEMS; i++) {
-            Drawable drawable = null;
-            if (resources != null && customItems.get(i).getIconId() != 0) {
-                try {
-                    drawable = ResourcesCompat.getDrawable(
-                            resources, customItems.get(i).getIconId(), null);
-                } catch (NotFoundException e1) {
-                    try {
-                        Context context = mActivity.createPackageContext(sourcePackageName,
-                                Context.CONTEXT_IGNORE_SECURITY | Context.CONTEXT_INCLUDE_CODE);
-                        drawable = AppCompatResources.getDrawable(
-                                context, customItems.get(i).getIconId());
-                    } catch (NameNotFoundException e2) {
-                        Log.e(TAG, "Cannot find the package name %s", sourcePackageName, e2);
-                    } catch (NotFoundException e3) {
-                        Log.e(TAG, "Cannot get Drawable for %s", customItems.get(i).getTitle(), e3);
-                    }
-                }
-            }
-            items.add(new BrowserActionsCustomContextMenuItem(
-                    CUSTOM_BROWSER_ACTIONS_ID_GROUP.get(i), customItems.get(i).getTitle(), drawable,
-                    customItems.get(i).getIconUri()));
-            mCustomItemActionMap.put(
-                    CUSTOM_BROWSER_ACTIONS_ID_GROUP.get(i), customItems.get(i).getAction());
-        }
-    }
-
-    boolean onItemSelected(int itemId, boolean recordMetrics) {
-        if (itemId == R.id.browser_actions_open_in_background) {
-            if (mIsNativeInitialized) {
-                handleOpenInBackground();
-            } else {
-                mPendingItemId = itemId;
-                waitNativeInitialized();
-            }
-        } else if (itemId == R.id.browser_actions_open_in_incognito_tab) {
-            mMenuItemDelegate.onOpenInIncognitoTab(mCurrentContextMenuParams.getLinkUrl());
-            notifyBrowserActionSelected(BrowserActionsIntent.ITEM_OPEN_IN_INCOGNITO);
-        } else if (itemId == R.id.browser_actions_save_link_as) {
-            if (mIsNativeInitialized) {
-                handleDownload();
-            } else {
-                mPendingItemId = itemId;
-                waitNativeInitialized();
-            }
-        } else if (itemId == R.id.browser_actions_copy_address) {
-            mMenuItemDelegate.onSaveToClipboard(mCurrentContextMenuParams.getLinkUrl());
-            notifyBrowserActionSelected(BrowserActionsIntent.ITEM_COPY);
-        } else if (itemId == R.id.browser_actions_share) {
-            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) {
-                mShouldFinishActivity = false;
-            }
-            mMenuItemDelegate.share(
-                    false, mCurrentContextMenuParams.getLinkUrl(), !mShouldFinishActivity);
-            notifyBrowserActionSelected(BrowserActionsIntent.ITEM_SHARE);
-        } else if (mCustomItemActionMap.indexOfKey(itemId) >= 0) {
-            mMenuItemDelegate.onCustomItemSelected(mCustomItemActionMap.get(itemId));
-        }
-        if (recordMetrics) recordBrowserActionsSelection(itemId);
-        return true;
-    }
-
-    private void recordBrowserActionsSelection(int itemId) {
-        @BrowserActionsActionId
-        final int actionId;
-        if (itemId == R.id.browser_actions_open_in_background) {
-            actionId = BrowserActionsActionId.OPEN_IN_NEW_CHROME_TAB;
-        } else if (itemId == R.id.browser_actions_open_in_incognito_tab) {
-            actionId = BrowserActionsActionId.OPEN_IN_INCOGNITO_TAB;
-        } else if (itemId == R.id.browser_actions_save_link_as) {
-            actionId = BrowserActionsActionId.DOWNLOAD_PAGE;
-        } else if (itemId == R.id.browser_actions_copy_address) {
-            actionId = BrowserActionsActionId.COPY_LINK;
-        } else if (itemId == R.id.browser_actions_share) {
-            actionId = BrowserActionsActionId.SHARE;
-        } else {
-            actionId = BrowserActionsActionId.APP_PROVIDED;
-        }
-        mActionHistogram.record(actionId);
-    }
-
-    private void notifyBrowserActionSelected(int menuId) {
-        if (mOnBrowserActionSelectedCallback == null) return;
-        Intent additionalData = new Intent();
-        additionalData.setData(Uri.parse(String.valueOf(menuId)));
-        try {
-            mOnBrowserActionSelectedCallback.send(mActivity, 0, additionalData, null, null);
-        } catch (CanceledException e) {
-            Log.e(TAG, "Browser Actions failed to send default items' pending intent.");
-        }
-    }
-
-    /**
-     * Display a progress dialog to wait for native libraries initialized.
-     */
-    private void waitNativeInitialized() {
-        mProgressDialog.setMessage(
-                mActivity.getString(R.string.browser_actions_loading_native_message));
-        mProgressDialog.show();
-    }
-
-    private void dismissProgressDialog() {
-        if (mProgressDialog != null && mProgressDialog.isShowing()) {
-            mProgressDialog.dismiss();
-        }
-    }
-
-    /**
-     * Displays the Browser Actions context menu.
-     * @param view The view to show the context menu if old UI is used.
-     */
-    public void displayBrowserActionsMenu(final View view) {
-        if (IS_NEW_UI_ENABLED) {
-            ContextMenuUi menuUi = new TabularContextMenuUi(mOnShareClickedRunnable);
-            menuUi.displayMenu(mActivity, mCurrentContextMenuParams, mItems, mItemSelectedCallback,
-                    mOnMenuShown, mOnMenuClosed);
-        } else {
-            view.setOnCreateContextMenuListener(BrowserActionsContextMenuHelper.this);
-            assert view.getWindowToken() == null;
-            view.addOnAttachStateChangeListener(this);
-        }
-    }
-
-    @Override
-    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
-        ContextMenuUi menuUi = new PlatformContextMenuUi(menu);
-        menuUi.displayMenu(mActivity, mCurrentContextMenuParams, mItems, mItemSelectedCallback,
-                mOnMenuShown, mOnMenuClosed);
-    }
-
-    @Override
-    public void onContextMenuClosed() {
-        mOnMenuClosed.run();
-    }
-
-    @Override
-    public void onViewAttachedToWindow(View view) {
-        if (view.showContextMenu()) {
-            mOnMenuShown.run();
-        }
-    }
-
-    @Override
-    public void onViewDetachedFromWindow(View v) {}
-
-    /**
-     * Finishes all pending actions which requires Chrome native libraries.
-     */
-    public void onNativeInitialized() {
-        mIsNativeInitialized = true;
-        RecordUserAction.record("BrowserActions.MenuOpened");
-        if (mTestDelegate != null) {
-            mTestDelegate.onFinishNativeInitialization();
-        }
-        if (mPendingItemId != 0) {
-            dismissProgressDialog();
-            onItemSelected(mPendingItemId, false);
-            mPendingItemId = 0;
-            if (mShouldFinishActivity) mActivity.finish();
-        }
-    }
-
-    private void handleOpenInBackground() {
-        mMenuItemDelegate.onOpenInBackground(mCurrentContextMenuParams.getLinkUrl());
-        if (mTestDelegate != null) {
-            mTestDelegate.onOpenTabInBackgroundStart();
-        }
-        notifyBrowserActionSelected(BrowserActionsIntent.ITEM_OPEN_IN_NEW_TAB);
-    }
-
-    private void handleDownload() {
-        mMenuItemDelegate.startDownload(mCurrentContextMenuParams.getLinkUrl());
-        if (mTestDelegate != null) {
-            mTestDelegate.onDownloadStart();
-        }
-        notifyBrowserActionSelected(BrowserActionsIntent.ITEM_DOWNLOAD);
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsContextMenuItemDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsContextMenuItemDelegate.java
deleted file mode 100644
index 1394442..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsContextMenuItemDelegate.java
+++ /dev/null
@@ -1,122 +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.
-
-package org.chromium.chrome.browser.browseractions;
-
-import android.app.Activity;
-import android.app.PendingIntent;
-import android.app.PendingIntent.CanceledException;
-import android.content.ClipData;
-import android.content.ClipboardManager;
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-import android.provider.Browser;
-
-import org.chromium.base.Log;
-import org.chromium.chrome.browser.IntentHandler;
-import org.chromium.chrome.browser.offlinepages.OfflinePageBridge;
-import org.chromium.chrome.browser.offlinepages.OfflinePageOrigin;
-import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.chrome.browser.share.ShareHelper;
-import org.chromium.chrome.browser.share.ShareParams;
-import org.chromium.chrome.browser.tabmodel.TabLaunchType;
-import org.chromium.chrome.browser.util.IntentUtils;
-
-/**
- * A delegate responsible for taking actions based on browser action context menu selections.
- */
-public class BrowserActionsContextMenuItemDelegate {
-    private static final String TAG = "BrowserActionsItem";
-
-    private final Activity mActivity;
-    private final String mSourcePackageName;
-
-    /**
-     * Builds a {@link BrowserActionsContextMenuItemDelegate} instance.
-     * @param activity The activity displays the context menu.
-     * @param sourcePackageName The package name of the app which requests the Browser Actions.
-     */
-    public BrowserActionsContextMenuItemDelegate(Activity activity, String sourcePackageName) {
-        mActivity = activity;
-        mSourcePackageName = sourcePackageName;
-    }
-
-    /**
-     * Called when the {@code text} should be saved to the clipboard.
-     * @param text The text to save to the clipboard.
-     */
-    public void onSaveToClipboard(String text) {
-        ClipboardManager clipboardManager =
-                (ClipboardManager) mActivity.getSystemService(Context.CLIPBOARD_SERVICE);
-        ClipData data = ClipData.newPlainText("url", text);
-        clipboardManager.setPrimaryClip(data);
-    }
-
-    /**
-     * Called when the {@code linkUrl} should be opened in Chrome incognito tab.
-     * @param linkUrl The url to open.
-     */
-    public void onOpenInIncognitoTab(String linkUrl) {
-        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(linkUrl));
-        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        intent.setPackage(mActivity.getPackageName());
-        intent.putExtra(IntentHandler.EXTRA_OPEN_NEW_INCOGNITO_TAB, true);
-        intent.putExtra(Browser.EXTRA_APPLICATION_ID, mActivity.getPackageName());
-        IntentHandler.addTrustedIntentExtras(intent);
-        IntentHandler.setTabLaunchType(intent, TabLaunchType.FROM_EXTERNAL_APP);
-        IntentUtils.safeStartActivity(mActivity, intent);
-    }
-
-    /**
-     * Called when the {@code linkUrl} should be opened in Chrome in the background.
-     * @param linkUrl The url to open.
-     */
-    public void onOpenInBackground(String linkUrl) {
-        BrowserActionsService.openLinkInBackground(linkUrl, mSourcePackageName);
-    }
-
-    /**
-     * Called when a custom item of Browser action menu is selected.
-     * @param action The PendingIntent action to be launched.
-     */
-    public void onCustomItemSelected(PendingIntent action) {
-        try {
-            action.send();
-        } catch (CanceledException e) {
-            Log.e(TAG, "Browser Action in Chrome failed to send pending intent.");
-        }
-    }
-
-    /**
-     * Called when the page of the {@code linkUrl} should be downloaded.
-     * @param linkUrl The url of the page to download.
-     */
-    public void startDownload(String linkUrl) {
-        OfflinePageBridge offlinePageBridge =
-                OfflinePageBridge.getForProfile(Profile.getLastUsedProfile().getOriginalProfile());
-        OfflinePageOrigin origin = new OfflinePageOrigin(mActivity, mSourcePackageName);
-        // TODO(ltian): Support single file download here. crbug.com/754807.
-        offlinePageBridge.savePageLater(
-                linkUrl, OfflinePageBridge.BROWSER_ACTIONS_NAMESPACE, true, origin);
-    }
-
-    /**
-     * Called when the {@code linkUrl} should be shared.
-     * @param shareDirectly Whether to share directly with the previous app shared with.
-     * @param linkUrl The url to share.
-     * @param shouldCloseActivity Whether to close activity after sharing.
-     */
-    public void share(Boolean shareDirectly, String linkUrl, boolean shouldCloseActivity) {
-        Runnable onShareDialogDismissed = shouldCloseActivity ? mActivity::finish : null;
-        ShareParams params = new ShareParams.Builder(mActivity, linkUrl, linkUrl)
-                                     .setShareDirectly(shareDirectly)
-                                     .setSaveLastUsed(!shareDirectly)
-                                     .setSourcePackageName(mSourcePackageName)
-                                     .setIsExternalUrl(true)
-                                     .setOnDialogDismissed(onShareDialogDismissed)
-                                     .build();
-        ShareHelper.share(params);
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsCustomContextMenuItem.java b/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsCustomContextMenuItem.java
deleted file mode 100644
index 0900a9a..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsCustomContextMenuItem.java
+++ /dev/null
@@ -1,87 +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.
-
-package org.chromium.chrome.browser.browseractions;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.support.annotation.IdRes;
-import android.support.customtabs.browseractions.BrowserActionItem;
-import android.support.customtabs.browseractions.BrowserServiceImageReadTask;
-
-import org.chromium.base.Callback;
-import org.chromium.base.VisibleForTesting;
-import org.chromium.base.task.AsyncTask;
-import org.chromium.chrome.browser.contextmenu.ContextMenuItem;
-
-/**
- * A class represents Browser Actions context menu with custom title and icon.
- */
-public class BrowserActionsCustomContextMenuItem implements ContextMenuItem {
-    @IdRes
-    private final int mMenuId;
-    private final String mTitle;
-    private final Uri mIconUri;
-    private Drawable mIcon;
-
-    /**
-     * Constructor to build a custom context menu item from {@link BrowserActionItem}.
-     * @param id The {@link IdRes} of the custom context menu item.
-     * @param title The title of the custom context menu item.
-     * @param icon The icon of the custom context menu item.
-     * @param iconUri The {@link Uri} used to access the icon of the custom context menu item.
-     */
-    BrowserActionsCustomContextMenuItem(@IdRes int id, String title, Drawable icon, Uri iconUri) {
-        mMenuId = id;
-        mTitle = title;
-        mIcon = icon;
-        mIconUri = iconUri;
-    }
-
-    @Override
-    public int getMenuId() {
-        return mMenuId;
-    }
-
-    @Override
-    public CharSequence getTitle(Context context) {
-        return mTitle;
-    }
-
-    @Override
-    public void getDrawableAsync(Context context, Callback<Drawable> callback) {
-        if (mIconUri != null) {
-            BrowserServiceImageReadTask task =
-                    new BrowserServiceImageReadTask(context.getContentResolver()) {
-                        @Override
-                        protected void onBitmapFileReady(Bitmap bitmap) {
-                            Drawable drawable = new BitmapDrawable(context.getResources(), bitmap);
-                            callback.onResult(drawable);
-                        }
-
-                    };
-            task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, mIconUri);
-        } else {
-            callback.onResult(mIcon);
-        }
-    }
-
-    /**
-     * Set the drawable icon of custom context menu item.
-     */
-    @VisibleForTesting
-    void setDrawable(Drawable drawable) {
-        mIcon = drawable;
-    }
-
-    /**
-     * @return the {@link Uri} used to access the icon of custom context menu item.
-     */
-    public Uri getIconUri() {
-        return mIconUri;
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsService.java b/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsService.java
deleted file mode 100644
index c8cbe8b..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsService.java
+++ /dev/null
@@ -1,386 +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.
-
-package org.chromium.chrome.browser.browseractions;
-
-import android.app.Activity;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.app.Service;
-import android.content.Context;
-import android.content.Intent;
-import android.os.IBinder;
-import android.text.TextUtils;
-
-import org.chromium.base.ApplicationStatus;
-import org.chromium.base.Callback;
-import org.chromium.base.ContextUtils;
-import org.chromium.base.VisibleForTesting;
-import org.chromium.base.metrics.RecordHistogram;
-import org.chromium.base.metrics.RecordUserAction;
-import org.chromium.chrome.R;
-import org.chromium.chrome.browser.ChromeTabbedActivity;
-import org.chromium.chrome.browser.IntentHandler;
-import org.chromium.chrome.browser.document.ChromeLauncherActivity;
-import org.chromium.chrome.browser.notifications.ChromeNotification;
-import org.chromium.chrome.browser.notifications.ChromeNotificationBuilder;
-import org.chromium.chrome.browser.notifications.ForegroundServiceUtils;
-import org.chromium.chrome.browser.notifications.NotificationBuilderFactory;
-import org.chromium.chrome.browser.notifications.NotificationConstants;
-import org.chromium.chrome.browser.notifications.NotificationMetadata;
-import org.chromium.chrome.browser.notifications.NotificationUmaTracker;
-import org.chromium.chrome.browser.notifications.PendingIntentProvider;
-import org.chromium.chrome.browser.notifications.channels.ChannelDefinitions;
-import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tabmodel.TabLaunchType;
-import org.chromium.chrome.browser.tabmodel.TabModelSelectorImpl;
-import org.chromium.chrome.browser.tabmodel.TabPersistentStore.TabModelSelectorMetadata;
-import org.chromium.chrome.browser.tabmodel.TabPersistentStore.TabPersistentStoreObserver;
-import org.chromium.chrome.browser.util.IntentUtils;
-import org.chromium.content_public.browser.LoadUrlParams;
-import org.chromium.content_public.common.Referrer;
-import org.chromium.ui.widget.Toast;
-
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * The foreground service responsible for creating notifications for Browser Actions and keep the
- * process alive during tab creation.
- */
-public class BrowserActionsService extends Service {
-    public static final String ACTION_TAB_CREATION_START =
-            "org.chromium.chrome.browser.browseractions.ACTION_TAB_CREATION_START";
-    public static final String ACTION_TAB_CREATION_CHROME_DISPLAYED =
-            "org.chromium.chrome.browser.browseractions.ACTION_TAB_CREATION_CHROME_DISPLAYED";
-    public static final String EXTRA_TAB_ID = "org.chromium.chrome.browser.browseractions.TAB_ID";
-    public static final String EXTRA_LINK_URL =
-            "org.chromium.chrome.browser.browseractions.LINK_URL";
-    public static final String EXTRA_SOURCE_PACKAGE_NAME =
-            "org.chromium.chrome.browser.browseractions.SOURCE_PACKAGE_NAME";
-
-    public static final String PREF_HAS_BROWSER_ACTIONS_NOTIFICATION =
-            "org.chromium.chrome.browser.browseractions.HAS_BROWSER_ACTIONS_NOTIFICATION";
-
-    public static final String PREF_NUM_TAB_CREATED_IN_BACKGROUND =
-            "org.chromium.chrome.browser.browseractions.NUM_TAB_CREATED_IN_BACKGROUND";
-
-    /**
-     * Extra that indicates whether to show a Tab for single url or the tab switcher for
-     * multiple urls.
-     */
-    public static final String EXTRA_IS_SINGLE_URL =
-            "org.chromium.chrome.browser.browseractions.is_single_url";
-
-    private static Intent sNotificationIntent;
-
-    private static int sTitleResId;
-
-    private static Set<Integer> sPendingTabIds = new HashSet<Integer>();
-    private static int sPendingCreatedUrlNum;
-
-    private BrowserActionsTabModelSelector mBrowserActionsSelector;
-    private TabModelSelectorImpl mTabbedModeTabModelSelector;
-    private TabPersistentStoreObserver mObserver;
-
-    @Override
-    public IBinder onBind(Intent intent) {
-        return null;
-    }
-
-    @VisibleForTesting
-    static Intent getNotificationIntent() {
-        return sNotificationIntent;
-    }
-
-    @VisibleForTesting
-    static int getTitleResId() {
-        return sTitleResId;
-    }
-
-    @Override
-    public int onStartCommand(Intent intent, int flags, int startId) {
-        if (TextUtils.equals(intent.getAction(), ACTION_TAB_CREATION_START)) {
-            createNotification(false, Tab.INVALID_TAB_ID);
-
-            String url = IntentUtils.safeGetStringExtra(intent, EXTRA_LINK_URL);
-            String sourcePackageName =
-                    IntentUtils.safeGetStringExtra(intent, EXTRA_SOURCE_PACKAGE_NAME);
-            openTabInBackground(url, sourcePackageName);
-            Toast.makeText(this, R.string.browser_actions_open_in_background_toast_message,
-                         Toast.LENGTH_SHORT)
-                    .show();
-            updateNumTabCreatedInBackground();
-        } else if (TextUtils.equals(intent.getAction(), ACTION_TAB_CREATION_CHROME_DISPLAYED)) {
-            clearPendingStatus();
-            removeObserver();
-            stopForeground(true);
-        }
-        // The service will not be restarted if Chrome get killed.
-        return START_NOT_STICKY;
-    }
-
-    private static void clearPendingStatus() {
-        sPendingTabIds.clear();
-        sPendingCreatedUrlNum = 0;
-    }
-
-    private void createNotification(boolean isUpdate, int tabId) {
-        sendBrowserActionsNotification(isUpdate, tabId);
-        if (isUpdate) {
-            ContextUtils.getAppSharedPreferences()
-                    .edit()
-                    .putBoolean(PREF_HAS_BROWSER_ACTIONS_NOTIFICATION, true)
-                    .apply();
-        }
-    }
-
-    private void backgroundServiceIfNecessary() {
-        if (sPendingTabIds.isEmpty() && sPendingCreatedUrlNum == 0) {
-            stopForeground(false);
-            removeObserver();
-        }
-    }
-
-    private void removeObserver() {
-        if (mObserver == null) return;
-        if (mBrowserActionsSelector != null) {
-            mBrowserActionsSelector.removeTabPersistentStoreObserver(mObserver);
-        }
-        if (mTabbedModeTabModelSelector != null) {
-            mTabbedModeTabModelSelector.removeTabPersistentStoreObserver(mObserver);
-        }
-    }
-
-    @VisibleForTesting
-    static boolean isBackgroundService() {
-        return sPendingTabIds.isEmpty() && sPendingCreatedUrlNum == 0;
-    }
-
-    private void openTabInBackground(String linkUrl, String sourcePackageName) {
-        Referrer referrer = IntentHandler.constructValidReferrerForAuthority(sourcePackageName);
-        LoadUrlParams loadUrlParams = new LoadUrlParams(linkUrl);
-        loadUrlParams.setReferrer(referrer);
-        Tab tab = launchTabInRunningTabbedActivity(loadUrlParams);
-        if (tab != null) {
-            int tabId = tab.getId();
-            assert tabId != Tab.INVALID_TAB_ID;
-            sPendingTabIds.add(tabId);
-            createNotification(true, tabId);
-            return;
-        }
-        launchTabInBrowserActionsModel(loadUrlParams);
-    }
-
-    private Tab launchTabInRunningTabbedActivity(LoadUrlParams loadUrlParams) {
-        for (Activity activity : ApplicationStatus.getRunningActivities()) {
-            if (!(activity instanceof ChromeTabbedActivity)) continue;
-
-            ChromeTabbedActivity chromeActivity = (ChromeTabbedActivity) activity;
-            if (chromeActivity.getTabModelSelector() != null) {
-                mTabbedModeTabModelSelector =
-                        (TabModelSelectorImpl) chromeActivity.getTabModelSelector();
-                mTabbedModeTabModelSelector.addTabPersistentStoreObserver(
-                        getTabPersistentStoreObserver());
-                Tab tab = mTabbedModeTabModelSelector.openNewTab(
-                        loadUrlParams, TabLaunchType.FROM_BROWSER_ACTIONS, null, false);
-                assert tab != null;
-                return tab;
-            }
-        }
-        return null;
-    }
-
-    private TabPersistentStoreObserver getTabPersistentStoreObserver() {
-        if (mObserver == null) {
-            mObserver = new TabPersistentStoreObserver() {
-                @Override
-                public void onMetadataSavedAsynchronously(
-                        TabModelSelectorMetadata modelSelectorMetadata) {
-                    removeSavedTabs(modelSelectorMetadata.normalModelMetadata.ids);
-                    backgroundServiceIfNecessary();
-                }
-            };
-        }
-        return mObserver;
-    }
-
-    private void launchTabInBrowserActionsModel(LoadUrlParams loadUrlParams) {
-        mBrowserActionsSelector = BrowserActionsTabModelSelector.getInstance();
-        mBrowserActionsSelector.addTabPersistentStoreObserver(getTabPersistentStoreObserver());
-        Callback<Integer> tabCreatedCallback = new Callback<Integer>() {
-            @Override
-            public void onResult(Integer tabId) {
-                // Service has been changed to background by opening Chrome so nothing needs to
-                // update.
-                if (sPendingCreatedUrlNum == 0) return;
-                sPendingCreatedUrlNum--;
-                if (tabId != Tab.INVALID_TAB_ID) sPendingTabIds.add(tabId);
-                backgroundServiceIfNecessary();
-                createNotification(true, Tab.INVALID_TAB_ID);
-            }
-        };
-        sPendingCreatedUrlNum++;
-        mBrowserActionsSelector.openNewTab(loadUrlParams, tabCreatedCallback);
-    }
-
-    private void removeSavedTabs(List<Integer> savedTabIds) {
-        for (Integer tabId : savedTabIds) sPendingTabIds.remove(tabId);
-    }
-
-    private void sendBrowserActionsNotification(boolean isUpdate, int tabId) {
-        ChromeNotification notification =
-                createNotificationBuilder(isUpdate, tabId).buildChromeNotification();
-
-        ForegroundServiceUtils.getInstance().startForeground(this, notification.getMetadata().id,
-                notification.getNotification(), 0 /* foregroundServiceType */);
-
-        if (!isUpdate) {
-            NotificationUmaTracker.getInstance().onNotificationShown(
-                    NotificationUmaTracker.SystemNotificationType.BROWSER_ACTIONS,
-                    notification.getNotification());
-        }
-    }
-
-    private ChromeNotificationBuilder createNotificationBuilder(boolean isUpdate, int tabId) {
-        NotificationMetadata metadata = new NotificationMetadata(
-                NotificationUmaTracker.SystemNotificationType.BROWSER_ACTIONS,
-                null /* notificationTag */, NotificationConstants.NOTIFICATION_ID_BROWSER_ACTIONS);
-        ChromeNotificationBuilder builder =
-                NotificationBuilderFactory
-                        .createChromeNotificationBuilder(true /* preferCompat */,
-                                ChannelDefinitions.ChannelId.BROWSER,
-                                null /* remoteAppPackageName */, metadata)
-                        .setSmallIcon(R.drawable.infobar_chrome)
-                        .setLocalOnly(true)
-                        .setAutoCancel(true)
-                        .setContentText(this.getString(R.string.browser_actions_notification_text));
-        sTitleResId = getNotificationTitleId(isUpdate);
-        builder.setContentTitle(this.getString(sTitleResId));
-        sNotificationIntent = buildNotificationIntent(isUpdate, tabId);
-        PendingIntentProvider notifyPendingIntent = PendingIntentProvider.getActivity(
-                this, 0, sNotificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
-        builder.setContentIntent(notifyPendingIntent);
-        return builder;
-    }
-
-    private int getNotificationTitleId(boolean isUpdate) {
-        if (isUpdate) {
-            assert sTitleResId != 0;
-        } else if (hasBrowserActionsNotification()) {
-            sTitleResId = R.string.browser_actions_multi_links_open_notification_title;
-        } else {
-            sTitleResId = R.string.browser_actions_single_link_open_notification_title;
-        }
-        return sTitleResId;
-    }
-
-    /**
-     * TODO(ltian:) fix ChromeTabbedActivity.processUrlViewIntent to handle Intent after browser
-     * actions tab merging and use Tab.createBringTabToFrontIntent to create Intent for single url
-     * in case of browser actions tab merging.
-     */
-    private Intent buildNotificationIntent(boolean isUpdate, int tabId) {
-        boolean multipleUrls = hasBrowserActionsNotification();
-        Intent intent;
-        if (!multipleUrls && tabId != Tab.INVALID_TAB_ID) {
-            intent = IntentUtils.createBringTabToFrontIntent(tabId);
-        } else {
-            intent = new Intent(this, ChromeLauncherActivity.class);
-            IntentHandler.addTrustedIntentExtras(intent);
-        }
-        if (isUpdate) {
-            intent.putExtra(EXTRA_IS_SINGLE_URL, !multipleUrls);
-        }
-        return intent;
-    }
-
-    @VisibleForTesting
-    static boolean hasBrowserActionsNotification() {
-        return ContextUtils.getAppSharedPreferences().getBoolean(
-                PREF_HAS_BROWSER_ACTIONS_NOTIFICATION, false);
-    }
-
-    private static void updateNumTabCreatedInBackground() {
-        int tabNum =
-                ContextUtils.getAppSharedPreferences().getInt(PREF_NUM_TAB_CREATED_IN_BACKGROUND, 0)
-                + 1;
-        ContextUtils.getAppSharedPreferences()
-                .edit()
-                .putInt(PREF_NUM_TAB_CREATED_IN_BACKGROUND, tabNum)
-                .apply();
-    }
-
-    /**
-     * Called when Chrome tabbed mode come to the foreground.
-     */
-    public static void onTabbedModeForegrounded() {
-        // If Chrome is shown, force the foreground service to be killed so notification bound to it
-        // will be dismissed.
-        if (!sPendingTabIds.isEmpty() || sPendingCreatedUrlNum > 0) {
-            Context context = ContextUtils.getApplicationContext();
-            Intent intent = new Intent(context, BrowserActionsService.class);
-            intent.setAction(ACTION_TAB_CREATION_CHROME_DISPLAYED);
-            context.startService(intent);
-        } else {
-            NotificationManager notificationManager =
-                    (NotificationManager) ContextUtils.getApplicationContext().getSystemService(
-                            Context.NOTIFICATION_SERVICE);
-            notificationManager.cancel(NotificationConstants.NOTIFICATION_ID_BROWSER_ACTIONS);
-        }
-
-        ContextUtils.getAppSharedPreferences()
-                .edit()
-                .putBoolean(PREF_HAS_BROWSER_ACTIONS_NOTIFICATION, false)
-                .apply();
-        int tabNum = ContextUtils.getAppSharedPreferences().getInt(
-                PREF_NUM_TAB_CREATED_IN_BACKGROUND, 0);
-        if (tabNum != 0) {
-            RecordHistogram.recordCountHistogram(
-                    "BrowserActions.NumTabCreatedInBackground", tabNum);
-            ContextUtils.getAppSharedPreferences()
-                    .edit()
-                    .remove(PREF_NUM_TAB_CREATED_IN_BACKGROUND)
-                    .apply();
-        }
-    }
-
-    /**
-     * Checks whether Chrome should display tab switcher via Browser Actions Intent.
-     * @param intent The intent to open the Chrome.
-     * @param isOverviewVisible Whether tab switcher is shown.
-     */
-    public static boolean shouldToggleOverview(Intent intent, boolean isOverviewVisible) {
-        if (!IntentHandler.wasIntentSenderChrome(intent)) return false;
-        if (!IntentUtils.safeHasExtra(intent, EXTRA_IS_SINGLE_URL)) return false;
-        boolean isSingleUrl = IntentUtils.safeGetBooleanExtra(intent, EXTRA_IS_SINGLE_URL, false);
-        return isSingleUrl == isOverviewVisible;
-    }
-
-    /**
-     * Checks whether an Intent is sent from the notification of opening tabs in background. If
-     * so record user action of clicking the notification.
-     * @param intent The {@link Intent} to check.
-     */
-    public static void recordTabOpenedNotificationClicked(Intent intent) {
-        if (IntentUtils.safeHasExtra(intent, EXTRA_IS_SINGLE_URL)) {
-            RecordUserAction.record("BrowserActions.TabOpenedNotificationClicked");
-        }
-    }
-
-    /**
-     * Sends a {@link Intent} to open a tab in {@link BrowserActionsService}.
-     * @param linkUrl The url to be opened.
-     * @param packageName The source package name which requests the tab creation.
-     */
-    public static void openLinkInBackground(String linkUrl, String packageName) {
-        Context context = ContextUtils.getApplicationContext();
-        Intent intent = new Intent(context, BrowserActionsService.class);
-        intent.setAction(ACTION_TAB_CREATION_START);
-        intent.putExtra(EXTRA_LINK_URL, linkUrl);
-        intent.putExtra(EXTRA_SOURCE_PACKAGE_NAME, packageName);
-        context.startService(intent);
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsTabCreatorManager.java b/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsTabCreatorManager.java
deleted file mode 100644
index 27fb36e7..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsTabCreatorManager.java
+++ /dev/null
@@ -1,99 +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.
-
-package org.chromium.chrome.browser.browseractions;
-
-import android.content.Context;
-
-import org.chromium.base.ContextUtils;
-import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tab.TabBuilder;
-import org.chromium.chrome.browser.tab.TabDelegateFactory;
-import org.chromium.chrome.browser.tab.TabState;
-import org.chromium.chrome.browser.tabmodel.TabCreatorManager;
-import org.chromium.chrome.browser.tabmodel.TabLaunchType;
-import org.chromium.chrome.browser.tabmodel.TabModel;
-import org.chromium.content_public.browser.LoadUrlParams;
-import org.chromium.content_public.browser.WebContents;
-import org.chromium.ui.base.WindowAndroid;
-
-/**
- * The manager returns a {@link BrowserActionsTabCreator} to create Tabs for Browser Actions.
- */
-public class BrowserActionsTabCreatorManager implements TabCreatorManager {
-    private final BrowserActionsTabCreator mTabCreator;
-
-    public BrowserActionsTabCreatorManager() {
-        mTabCreator = new BrowserActionsTabCreator();
-    }
-
-    /**
-     * This class creates various kinds of new tabs specific for Browser Actions.
-     * The created tabs are not bound with {@link ChromeActivity}.
-     */
-    public class BrowserActionsTabCreator extends TabCreator {
-        private TabModel mTabModel;
-
-        @Override
-        public boolean createsTabsAsynchronously() {
-            return false;
-        }
-
-        @Override
-        public Tab createNewTab(LoadUrlParams loadUrlParams, @TabLaunchType int type, Tab parent) {
-            assert type == TabLaunchType.FROM_BROWSER_ACTIONS
-                    || type
-                            == TabLaunchType.FROM_RESTORE
-                : "tab launch type should be FROM_BROWSER_ACTIONS or FROM_RESTORE";
-            Context context = ContextUtils.getApplicationContext();
-            WindowAndroid windowAndroid = new WindowAndroid(context);
-            Tab tab = TabBuilder.createForLazyLoad(loadUrlParams)
-                              .setWindow(windowAndroid)
-                              .setLaunchType(type)
-                              .build();
-            tab.initialize(null, new TabDelegateFactory(), true, null, false);
-            mTabModel.addTab(tab, -1, type);
-            return tab;
-        }
-
-        @Override
-        public Tab createFrozenTab(TabState state, int id, int index) {
-            Context context = ContextUtils.getApplicationContext();
-            WindowAndroid windowAndroid = new WindowAndroid(context);
-            Tab tab = TabBuilder.createFromFrozenState().setId(id).setWindow(windowAndroid).build();
-            tab.initialize(null, new TabDelegateFactory(), true, state, false);
-            mTabModel.addTab(tab, index, TabLaunchType.FROM_RESTORE);
-            return tab;
-        }
-
-        @Override
-        public Tab launchUrl(String url, @TabLaunchType int type) {
-            throw new UnsupportedOperationException("Browser Actions does not support launchUrl");
-        }
-
-        @Override
-        public boolean createTabWithWebContents(
-                Tab parent, WebContents webContents, @TabLaunchType int type, String url) {
-            throw new UnsupportedOperationException(
-                    "Browser Actions does not support createTabWithWebContents");
-        }
-
-        /**
-         * Sets the tab model to use when creating tabs.
-         * @param model The new {@link TabModel} to use.
-         */
-        public void setTabModel(TabModel model) {
-            mTabModel = model;
-        }
-    }
-
-    @Override
-    public TabCreator getTabCreator(boolean incognito) {
-        if (incognito) {
-            throw new IllegalStateException(
-                    "Browser Actions does not support background incognito tabs");
-        }
-        return mTabCreator;
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsTabModelSelector.java b/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsTabModelSelector.java
deleted file mode 100644
index a695600..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsTabModelSelector.java
+++ /dev/null
@@ -1,257 +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.
-
-package org.chromium.chrome.browser.browseractions;
-
-import org.chromium.base.Callback;
-import org.chromium.base.ThreadUtils;
-import org.chromium.base.task.PostTask;
-import org.chromium.base.task.TaskTraits;
-import org.chromium.chrome.browser.ChromeActivity;
-import org.chromium.chrome.browser.browseractions.BrowserActionsTabCreatorManager.BrowserActionsTabCreator;
-import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tabmodel.ChromeTabCreator;
-import org.chromium.chrome.browser.tabmodel.EmptyTabModel;
-import org.chromium.chrome.browser.tabmodel.EmptyTabModelObserver;
-import org.chromium.chrome.browser.tabmodel.TabCreatorManager;
-import org.chromium.chrome.browser.tabmodel.TabLaunchType;
-import org.chromium.chrome.browser.tabmodel.TabModel;
-import org.chromium.chrome.browser.tabmodel.TabModelDelegate;
-import org.chromium.chrome.browser.tabmodel.TabModelImpl;
-import org.chromium.chrome.browser.tabmodel.TabModelObserver;
-import org.chromium.chrome.browser.tabmodel.TabModelOrderController;
-import org.chromium.chrome.browser.tabmodel.TabModelSelectorBase;
-import org.chromium.chrome.browser.tabmodel.TabModelUtils;
-import org.chromium.chrome.browser.tabmodel.TabPersistentStore;
-import org.chromium.chrome.browser.tabmodel.TabPersistentStore.TabPersistentStoreObserver;
-import org.chromium.chrome.browser.tabmodel.TabSelectionType;
-import org.chromium.content_public.browser.LoadUrlParams;
-import org.chromium.content_public.browser.UiThreadTaskTraits;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * The tab model selector creates Tabs for Browser Actions. Tabs created by it are not shown in the
- * foreground and don't need {@link TabContentMananger}.
- */
-public class BrowserActionsTabModelSelector
-        extends TabModelSelectorBase implements TabModelDelegate {
-    /** The singleton reference. */
-    private static BrowserActionsTabModelSelector sInstance;
-    private static final Object sInstanceLock = new Object();
-
-    private final TabCreatorManager mTabCreatorManager;
-
-    private final TabPersistentStore mTabSaver;
-
-    private final TabModelOrderController mOrderController;
-
-    private final List<LoadUrlParams> mPendingUrls = new ArrayList<>();
-
-    private Runnable mTabCreationRunnable;
-
-    /**
-     * Builds a {@link BrowserActionsTabModelSelector} instance.
-     */
-    private BrowserActionsTabModelSelector() {
-        super();
-        mTabCreatorManager = new BrowserActionsTabCreatorManager();
-        final TabPersistentStoreObserver persistentStoreObserver =
-                new TabPersistentStoreObserver() {
-                    @Override
-                    public void onStateLoaded() {
-                        markTabStateInitialized();
-                    }
-                };
-        BrowserActionsTabPersistencePolicy persistencePolicy =
-                new BrowserActionsTabPersistencePolicy();
-        mTabSaver = new TabPersistentStore(
-                persistencePolicy, this, mTabCreatorManager, persistentStoreObserver);
-        mOrderController = new TabModelOrderController(this);
-    }
-
-    /**
-     * @return The singleton instance of {@link BrowserActionsTabModelSelector}.
-     */
-    public static BrowserActionsTabModelSelector getInstance() {
-        synchronized (sInstanceLock) {
-            ThreadUtils.assertOnUiThread();
-            if (sInstance == null) {
-                sInstance = new BrowserActionsTabModelSelector();
-                sInstance.initializeSelector();
-            }
-            return sInstance;
-        }
-    }
-
-    /**
-     * @return Whether {@link BrowserActionsTabModelSelector} has been initialized.
-     */
-    public static boolean isInitialized() {
-        return sInstance != null;
-    }
-
-    /**
-     * Initializes the selectors for the {@link BrowserActionsTabModelSelector}.
-     */
-    public void initializeSelector() {
-        BrowserActionsTabCreator regularTabCreator =
-                (BrowserActionsTabCreator) mTabCreatorManager.getTabCreator(false);
-        TabModelImpl normalModel = new TabModelImpl(false, false, regularTabCreator, null, null,
-                mOrderController, null, mTabSaver, this, false);
-        TabModel incognitoModel = EmptyTabModel.getInstance();
-        initialize(false, normalModel, incognitoModel);
-        regularTabCreator.setTabModel(getCurrentModel());
-    }
-
-    @Override
-    public void markTabStateInitialized() {
-        super.markTabStateInitialized();
-        // Add observer when tab model is restored to prevent restored tabs updating tab model.
-        TabModelObserver tabModelObserver = new EmptyTabModelObserver() {
-            @Override
-            public void didAddTab(Tab tab, @TabLaunchType int type) {
-                if (tab != null) {
-                    mTabSaver.addTabToSaveQueue(tab);
-                }
-            }
-        };
-        getModel(false).addObserver(tabModelObserver);
-        if (mTabCreationRunnable != null) {
-            PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, mTabCreationRunnable);
-        }
-        mTabCreationRunnable = null;
-    }
-
-    /**
-     * Creates a new Tab with given url in Browser Actions tab model.
-     * @param loadUrlParams The url params to be opened.
-     * @param tabCreatedCallback The {@link Callback} to run when tab is created.
-     */
-    public void openNewTab(LoadUrlParams loadUrlParams, Callback<Integer> tabCreatedCallback) {
-        // If tab model is restored, directly create a new tab.
-        if (isTabStateInitialized()) {
-            createNewTab(loadUrlParams, tabCreatedCallback);
-            return;
-        }
-        if (mTabCreationRunnable == null) {
-            mTabCreationRunnable = new Runnable() {
-                @Override
-                public void run() {
-                    for (int i = 0; i < mPendingUrls.size(); i++) {
-                        createNewTab(mPendingUrls.get(i), tabCreatedCallback);
-                    }
-                    mPendingUrls.clear();
-                }
-            };
-            PostTask.postTask(TaskTraits.USER_BLOCKING, () -> {
-                mTabSaver.loadState(true);
-                mTabSaver.restoreTabs(false);
-            });
-        }
-        mPendingUrls.add(loadUrlParams);
-    }
-
-    private void createNewTab(LoadUrlParams params, Callback<Integer> tabCreatedCallback) {
-        Tab tab = openNewTab(params, TabLaunchType.FROM_BROWSER_ACTIONS, null, false);
-        tabCreatedCallback.onResult(tab.getId());
-    }
-
-    @Override
-    public void requestToShowTab(Tab tab, @TabSelectionType int type) {}
-
-    @Override
-    public boolean closeAllTabsRequest(boolean incognito) {
-        return false;
-    }
-
-    @Override
-    public boolean isCurrentModel(TabModel model) {
-        return false;
-    }
-
-    @Override
-    public boolean isInOverviewMode() {
-        return false;
-    }
-
-    @Override
-    public boolean isSessionRestoreInProgress() {
-        return false;
-    }
-
-    /**
-     * @return Return the current tab model. For Browser Actions, it always returns the normal tab
-     * model.
-     */
-    public TabModelImpl getModel() {
-        return (TabModelImpl) getModel(false);
-    }
-
-    /**
-     * Save the whole tab list to the disk.
-     */
-    public void saveState() {
-        commitAllTabClosures();
-        mTabSaver.saveState();
-    }
-
-    @Override
-    public Tab openNewTab(
-            LoadUrlParams loadUrlParams, @TabLaunchType int type, Tab parent, boolean incognito) {
-        if (!isTabStateInitialized()) {
-            assert type == TabLaunchType.FROM_RESTORE;
-        }
-        return mTabCreatorManager.getTabCreator(incognito).createNewTab(
-                loadUrlParams, type, parent);
-    }
-
-    /**
-     * Merge tabs from {@link BrowserActionsTabModelSelector} to the selector in a {@link
-     * ChromeActivity}.
-     * @param activity The ChromeActivity all tabs will be merged to.
-     * @param shouldSelectTab Whether the last tab should be set as the active tab.
-     */
-    public void mergeBrowserActionsTabModel(ChromeActivity activity, boolean shouldSelectTab) {
-        assert isInitialized() : "Browser Actions tab model should be initialized at this point";
-        TabModel chromeNormalTabModel = activity.getTabModelSelector().getModel(false);
-        TabModel browserActionsNormlTabModel = getModel(false);
-        while (browserActionsNormlTabModel.getCount() > 0) {
-            Tab tab = browserActionsNormlTabModel.getTabAt(0);
-            browserActionsNormlTabModel.removeTab(tab);
-            tab.attach(activity,
-                    ((ChromeTabCreator) activity.getTabCreator(false))
-                            .createDefaultTabDelegateFactory());
-            chromeNormalTabModel.addTab(tab, -1, TabLaunchType.FROM_BROWSER_ACTIONS);
-        }
-        saveState();
-        if (shouldSelectTab) {
-            TabModelUtils.setIndex(chromeNormalTabModel, chromeNormalTabModel.getCount() - 1);
-        }
-    }
-
-    @Override
-    public void destroy() {
-        super.destroy();
-        mTabSaver.destroy();
-        sInstance = null;
-    }
-
-    /**
-     * Add a {@link TabPersistentStoreObserver} to {@link TabPersistentStore}.
-     * @param observer The observer to add.
-     */
-    public void addTabPersistentStoreObserver(TabPersistentStoreObserver observer) {
-        mTabSaver.addObserver(observer);
-    }
-
-    /**
-     * Remove a {@link TabPersistentStoreObserver} from {@link TabPersistentStore}.
-     * @param observer The observer to remove.
-     */
-    public void removeTabPersistentStoreObserver(TabPersistentStoreObserver observer) {
-        mTabSaver.removeObserver(observer);
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsTabPersistencePolicy.java b/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsTabPersistencePolicy.java
deleted file mode 100644
index 2f30c1b..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsTabPersistencePolicy.java
+++ /dev/null
@@ -1,76 +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.
-
-package org.chromium.chrome.browser.browseractions;
-
-import android.support.annotation.Nullable;
-
-import org.chromium.base.Callback;
-import org.chromium.base.task.TaskRunner;
-import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager;
-import org.chromium.chrome.browser.tabmodel.TabPersistencePolicy;
-import org.chromium.chrome.browser.tabmodel.TabPersistentStore;
-import org.chromium.chrome.browser.tabmodel.TabbedModeTabPersistencePolicy;
-
-import java.io.File;
-import java.util.List;
-
-/**
- * Handles the Browser Actions Tab specific behaviors of tab persistence.
- */
-public class BrowserActionsTabPersistencePolicy implements TabPersistencePolicy {
-    @Override
-    public File getOrCreateStateDirectory() {
-        return TabbedModeTabPersistencePolicy.getOrCreateTabbedModeStateDirectory();
-    }
-
-    @Override
-    public String getStateFileName() {
-        return TabPersistentStore.getStateFileName("_browser_actions");
-    }
-
-    @Override
-    public boolean shouldMergeOnStartup() {
-        return false;
-    }
-
-    @Override
-    @Nullable
-    public List<String> getStateToBeMergedFileNames() {
-        return null;
-    }
-
-    @Override
-    public boolean performInitialization(TaskRunner taskRunner) {
-        return false;
-    }
-
-    @Override
-    public void waitForInitializationToFinish() {}
-
-    @Override
-    public boolean isMergeInProgress() {
-        return false;
-    }
-
-    @Override
-    public void setMergeInProgress(boolean isStarted) {
-        assert false : "Merge not supported in Browser Actions";
-    }
-
-    @Override
-    public void cancelCleanupInProgress() {}
-
-    @Override
-    public void cleanupUnusedFiles(Callback<List<String>> filesToDelete) {}
-
-    @Override
-    public void setTabContentManager(TabContentManager cache) {}
-
-    @Override
-    public void notifyStateLoaded(int tabCountAtStartup) {}
-
-    @Override
-    public void destroy() {}
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/browseractions/OWNERS
deleted file mode 100644
index bd9a469..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/OWNERS
+++ /dev/null
@@ -1,7 +0,0 @@
-mvanouwerkerk@chromium.org
-peconn@chromium.org
-pshmakov@chromium.org
-yusufo@chromium.org
-
-# COMPONENT: UI>Browser>Mobile>CustomTabs
-# OS: Android
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityUmaRecorder.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityUmaRecorder.java
index ca7392f..1f51aa3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityUmaRecorder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityUmaRecorder.java
@@ -60,7 +60,7 @@
      * Records the time that a Trusted Web Activity has been in resumed state.
      */
     public void recordTwaOpenTime(long durationMs) {
-        recordDuration(durationMs, "BrowserServices.TwaOpenTime");
+        recordDuration(durationMs, "BrowserServices.TwaOpenTime.V2");
     }
 
     /**
@@ -68,7 +68,7 @@
      * the Trusted Web Activity.
      */
     public void recordTimeInVerifiedOrigin(long durationMs) {
-        recordDuration(durationMs, "TrustedWebActivity.TimeInVerifiedOrigin");
+        recordDuration(durationMs, "TrustedWebActivity.TimeInVerifiedOrigin.V2");
     }
 
     /**
@@ -76,11 +76,11 @@
      * the Trusted Web Activity.
      */
     public void recordTimeOutOfVerifiedOrigin(long durationMs) {
-        recordDuration(durationMs, "TrustedWebActivity.TimeOutOfVerifiedOrigin");
+        recordDuration(durationMs, "TrustedWebActivity.TimeOutOfVerifiedOrigin.V2");
     }
 
     private void recordDuration(long durationMs, String histogramName) {
-        RecordHistogram.recordTimesHistogram(histogramName, durationMs);
+        RecordHistogram.recordLongTimesHistogram(histogramName, durationMs);
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
index 20c3416..952e38c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
@@ -138,12 +138,6 @@
     private ContentCaptureConsumer mContentCaptureConsumer;
 
     /**
-     * Last MOVE MotionEvent dispatched to this object for a currently active gesture. If there is
-     * no active gesture, this is null.
-     */
-    private @Nullable MotionEvent mLastMoveEvent;
-
-    /**
      * This view is created on demand to display debugging information.
      */
     private static class DebugOverlay extends View {
@@ -243,37 +237,6 @@
             public void onContentChanged(Tab tab) {
                 CompositorViewHolder.this.onContentChanged();
             }
-
-            @Override
-            public void onWebContentsSwapped(Tab tab, boolean didStartLoad, boolean didFinishLoad) {
-                /**
-                 * After swapping web contents, any gesture active in the old ContentView is
-                 * cancelled. We still want to continue a previously running gesture in the new
-                 * ContentView, so we synthetically dispatch a new ACTION_DOWN MotionEvent with the
-                 * coordinates of where we estimate the pointer currently is (the coordinates of
-                 * the last ACTION_MOVE MotionEvent received before the swap).
-                 *
-                 * We wait for layout to happen as the newly created ContentView currently has a
-                 * width and height of zero, which would result in the event not being dispatched.
-                 */
-                mView.addOnLayoutChangeListener(new OnLayoutChangeListener() {
-                    @Override
-                    public void onLayoutChange(View v, int left, int top, int right, int bottom,
-                            int oldLeft, int oldTop, int oldRight, int oldBottom) {
-                        v.removeOnLayoutChangeListener(this);
-                        if (mLastMoveEvent == null) return;
-                        MotionEvent downEvent = MotionEvent.obtain(mLastMoveEvent);
-                        downEvent.setAction(MotionEvent.ACTION_DOWN);
-                        CompositorViewHolder.this.dispatchTouchEvent(downEvent);
-                        for (int i = 1; i < mLastMoveEvent.getPointerCount(); i++) {
-                            MotionEvent pointerDownEvent = MotionEvent.obtain(mLastMoveEvent);
-                            pointerDownEvent.setAction(MotionEvent.ACTION_POINTER_DOWN
-                                    | (i << MotionEvent.ACTION_POINTER_INDEX_SHIFT));
-                            CompositorViewHolder.this.dispatchTouchEvent(pointerDownEvent);
-                        }
-                    }
-                });
-            }
         };
 
         addOnLayoutChangeListener(new OnLayoutChangeListener() {
@@ -595,22 +558,6 @@
         return ret;
     }
 
-    @Override
-    public boolean dispatchTouchEvent(MotionEvent e) {
-        updateLastMoveEvent(e);
-        return super.dispatchTouchEvent(e);
-    }
-
-    private void updateLastMoveEvent(MotionEvent e) {
-        if (e.getActionMasked() == MotionEvent.ACTION_MOVE) {
-            mLastMoveEvent = e;
-        }
-        if (e.getActionMasked() == MotionEvent.ACTION_CANCEL
-                || e.getActionMasked() == MotionEvent.ACTION_UP) {
-            mLastMoveEvent = null;
-        }
-    }
-
     /**
      * @return The {@link LayoutManager} associated with this view.
      */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuItem.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuItem.java
index a4e1458..6fbf8f5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuItem.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuItem.java
@@ -34,9 +34,7 @@
             Item.COPY_LINK_TEXT, Item.SAVE_LINK_AS, Item.LOAD_ORIGINAL_IMAGE, Item.SAVE_IMAGE,
             Item.OPEN_IMAGE, Item.OPEN_IMAGE_IN_NEW_TAB, Item.OPEN_IMAGE_IN_EPHEMERAL_TAB,
             Item.SEARCH_BY_IMAGE, Item.CALL, Item.SEND_MESSAGE, Item.ADD_TO_CONTACTS, Item.COPY,
-            Item.SAVE_VIDEO, Item.OPEN_IN_CHROME, Item.BROWSER_ACTIONS_OPEN_IN_BACKGROUND,
-            Item.BROWSER_ACTIONS_OPEN_IN_INCOGNITO_TAB, Item.BROWSER_ACTION_SAVE_LINK_AS,
-            Item.BROWSER_ACTIONS_COPY_ADDRESS})
+            Item.SAVE_VIDEO, Item.OPEN_IN_CHROME})
     @Retention(RetentionPolicy.SOURCE)
     public @interface Item {
         // Values are numerated from 0 and can't have gaps.
@@ -69,13 +67,8 @@
         int SAVE_VIDEO = 20;
         // Other
         int OPEN_IN_CHROME = 21;
-        // Browser Action Items
-        int BROWSER_ACTIONS_OPEN_IN_BACKGROUND = 22;
-        int BROWSER_ACTIONS_OPEN_IN_INCOGNITO_TAB = 23;
-        int BROWSER_ACTION_SAVE_LINK_AS = 24;
-        int BROWSER_ACTIONS_COPY_ADDRESS = 25;
         // ALWAYS UPDATE!
-        int NUM_ENTRIES = 26;
+        int NUM_ENTRIES = 22;
     }
 
     /**
@@ -104,10 +97,6 @@
             R.id.contextmenu_copy, // Item.COPY
             R.id.contextmenu_save_video, // Item.SAVE_VIDEO
             R.id.contextmenu_open_in_chrome, // Item.OPEN_IN_CHROME
-            R.id.browser_actions_open_in_background, // Item.BROWSER_ACTIONS_OPEN_IN_BACKGROUND
-            R.id.browser_actions_open_in_incognito_tab, // Item.BROWSER_ACTIONS_OPEN_IN_INCOGNITO_TAB
-            R.id.browser_actions_save_link_as, // Item.BROWSER_ACTION_SAVE_LINK_AS
-            R.id.browser_actions_copy_address, // Item.BROWSER_ACTIONS_COPY_ADDRESS
     };
 
     /**
@@ -136,10 +125,6 @@
             R.string.contextmenu_copy, // Item.COPY:
             R.string.contextmenu_save_video, // Item.SAVE_VIDEO:
             R.string.menu_open_in_chrome, // Item.OPEN_IN_CHROME:
-            R.string.browser_actions_open_in_background, // Item.BROWSER_ACTIONS_OPEN_IN_BACKGROUND:
-            R.string.browser_actions_open_in_incognito_tab, // Item.BROWSER_ACTIONS_OPEN_IN_INCOGNITO_TAB:
-            R.string.browser_actions_save_link_as, // Item.BROWSER_ACTION_SAVE_LINK_AS:
-            R.string.browser_actions_copy_address, // Item.BROWSER_ACTIONS_COPY_ADDRESS:
     };
 
     private final @Item int mItem;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/DevicePickerBottomSheetContent.java b/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/DevicePickerBottomSheetContent.java
index 88f1d8a..8c2185a2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/DevicePickerBottomSheetContent.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/DevicePickerBottomSheetContent.java
@@ -14,8 +14,10 @@
 import android.widget.ListView;
 import android.widget.TextView;
 
+import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeActivity;
+import org.chromium.chrome.browser.send_tab_to_self.SendTabToSelfMetrics.SendTabToSelfShareClickResult;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet;
 import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet.BottomSheetContent;
@@ -44,6 +46,13 @@
 
         createToolbarView();
         createContentView();
+        recordNumberOfDevicesDisplayed();
+    }
+
+    private void recordNumberOfDevicesDisplayed() {
+        // This histogram is used across multiple platforms and should be
+        // kept consistent.
+        RecordHistogram.recordCount100Histogram("SendTabToSelf.DeviceCount", mAdapter.getCount());
     }
 
     private void createToolbarView() {
@@ -127,6 +136,8 @@
 
     @Override
     public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+        SendTabToSelfShareClickResult.recordClickResult(
+                SendTabToSelfShareClickResult.ClickType.CLICK_ITEM);
         TargetDeviceInfo targetDeviceInfo = mAdapter.getItem(position);
 
         Tab tab = mActivity.getActivityTabProvider().get();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/NotificationManager.java b/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/NotificationManager.java
index f63b5900..fa7db929 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/NotificationManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/NotificationManager.java
@@ -34,6 +34,8 @@
 import org.chromium.chrome.browser.notifications.PendingIntentProvider;
 import org.chromium.chrome.browser.notifications.channels.ChannelDefinitions;
 import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.browser.send_tab_to_self.SendTabToSelfMetrics.SendTabToSelfShareNotificationInteraction;
+import org.chromium.chrome.browser.send_tab_to_self.SendTabToSelfMetrics.SendTabToSelfShareNotificationInteraction.InteractionType;
 
 /**
  * Manages all SendTabToSelf related notifications for Android. This includes displaying, handling
@@ -47,7 +49,7 @@
         @Override
         public void onReceive(Context context, Intent intent) {
             String guid = intent.getStringExtra(NOTIFICATION_GUID_EXTRA);
-            hideNotification(guid);
+            hideNotification(guid, InteractionType.DISMISSED);
             SendTabToSelfAndroidBridge.dismissEntry(Profile.getLastUsedProfile(), guid);
         }
     }
@@ -58,7 +60,7 @@
         public void onReceive(Context context, Intent intent) {
             openUrl(intent.getData());
             String guid = intent.getStringExtra(NOTIFICATION_GUID_EXTRA);
-            hideNotification(guid);
+            hideNotification(guid, InteractionType.OPENED);
             SendTabToSelfAndroidBridge.deleteEntry(Profile.getLastUsedProfile(), guid);
         }
     }
@@ -68,7 +70,7 @@
         @Override
         public void onReceive(Context context, Intent intent) {
             String guid = intent.getStringExtra(NOTIFICATION_GUID_EXTRA);
-            hideNotification(guid);
+            hideNotification(guid, InteractionType.DISMISSED_REMOTELY);
             SendTabToSelfAndroidBridge.dismissEntry(Profile.getLastUsedProfile(), guid);
         }
     }
@@ -99,17 +101,31 @@
      *
      * @param guid The GUID of the notification to hide.
      */
+    private static void hideNotification(@Nullable String guid, @InteractionType int type) {
+        if (hideNotification(guid)) {
+            SendTabToSelfShareNotificationInteraction.recordClickResult(type);
+        }
+    }
+
+    /**
+     * Hides a notification.
+     *
+     * @param guid The GUID of the notification to hide.
+     * @return whether the notification was hidden. False if there is corresponding notification to
+     * hide.
+     */
     @CalledByNative
-    private static void hideNotification(@Nullable String guid) {
+    private static boolean hideNotification(@Nullable String guid) {
         NotificationSharedPrefManager.ActiveNotification activeNotification =
                 NotificationSharedPrefManager.findActiveNotification(guid);
         if (!NotificationSharedPrefManager.removeActiveNotification(guid)) {
-            return;
+            return false;
         }
         Context context = ContextUtils.getApplicationContext();
         NotificationManagerProxy manager = new NotificationManagerProxyImpl(context);
         manager.cancel(
                 NotificationConstants.GROUP_SEND_TAB_TO_SELF, activeNotification.notificationId);
+        return true;
     }
 
     /**
@@ -130,6 +146,8 @@
         }
 
         // Post notification.
+        SendTabToSelfShareNotificationInteraction.recordClickResult(
+                SendTabToSelfShareNotificationInteraction.InteractionType.SHOWN);
         Context context = ContextUtils.getApplicationContext();
         NotificationManagerProxy manager = new NotificationManagerProxyImpl(context);
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfMetrics.java b/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfMetrics.java
new file mode 100644
index 0000000..48114ab
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfMetrics.java
@@ -0,0 +1,63 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.send_tab_to_self;
+
+import android.support.annotation.IntDef;
+
+import org.chromium.base.metrics.RecordHistogram;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Class that captures all the metrics needed for Send Tab To Self on Android.
+ */
+public class SendTabToSelfMetrics {
+    /**
+     * Metrics captured when a user initiates and completes the sending flow.
+     */
+    public static class SendTabToSelfShareClickResult {
+        @Retention(RetentionPolicy.SOURCE)
+        @IntDef({ClickType.SHOW_ITEM, ClickType.CLICK_ITEM, ClickType.SHOW_DEVICE_LIST})
+        @interface ClickType {
+            // These values are used for UMA. Don't reuse or reorder values.
+            // If you add something, update NUM_ENTRIES.This must be kept in sync with
+            // send_tab_to_self_desktop_util.h
+            int SHOW_ITEM = 0;
+            int CLICK_ITEM = 1;
+            int SHOW_DEVICE_LIST = 2;
+            int NUM_ENTRIES = 3;
+        }
+
+        public static void recordClickResult(@ClickType int result) {
+            RecordHistogram.recordEnumeratedHistogram(
+                    "SendTabToSelf.AndroidShareSheet.ClickResult", result, ClickType.NUM_ENTRIES);
+        }
+    }
+
+    /**
+     * Metrics captured when a user completes the receiving flow.
+     */
+    public static class SendTabToSelfShareNotificationInteraction {
+        @Retention(RetentionPolicy.SOURCE)
+        @IntDef({InteractionType.OPENED, InteractionType.DISMISSED, InteractionType.SHOWN,
+                InteractionType.DISMISSED_REMOTELY})
+        @interface InteractionType {
+            // These values are used for UMA. Don't reuse or reorder values.
+            // If you add something, update NUM_ENTRIES. This must be kept in sync with
+            // send_tab_to_self_metrics.h
+            int OPENED = 0;
+            int DISMISSED = 1;
+            int SHOWN = 2;
+            int DISMISSED_REMOTELY = 3;
+            int NUM_ENTRIES = 4;
+        }
+
+        public static void recordClickResult(@InteractionType int result) {
+            RecordHistogram.recordEnumeratedHistogram(
+                    "SendTabToSelf.Notification", result, InteractionType.NUM_ENTRIES);
+        }
+    }
+}
\ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfShareActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfShareActivity.java
index 923f9ec..5958b59a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfShareActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfShareActivity.java
@@ -6,6 +6,7 @@
 
 import org.chromium.base.VisibleForTesting;
 import org.chromium.chrome.browser.ChromeActivity;
+import org.chromium.chrome.browser.send_tab_to_self.SendTabToSelfMetrics.SendTabToSelfShareClickResult;
 import org.chromium.chrome.browser.share.ShareActivity;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet.BottomSheetContent;
@@ -25,6 +26,8 @@
             return;
         }
 
+        SendTabToSelfShareClickResult.recordClickResult(
+                SendTabToSelfShareClickResult.ClickType.SHOW_DEVICE_LIST);
         triggeringActivity.getBottomSheetController().requestShowContent(
                 createBottomSheetContent(triggeringActivity, entry), true);
         // TODO(crbug.com/968246): Remove the need to call this explicitly and instead have it
@@ -38,6 +41,12 @@
     }
 
     public static boolean featureIsAvailable(Tab currentTab) {
-        return SendTabToSelfAndroidBridge.isFeatureAvailable(currentTab.getWebContents());
+        boolean shouldShow =
+                SendTabToSelfAndroidBridge.isFeatureAvailable(currentTab.getWebContents());
+        if (shouldShow) {
+            SendTabToSelfShareClickResult.recordClickResult(
+                    SendTabToSelfShareClickResult.ClickType.SHOW_ITEM);
+        }
+        return shouldShow;
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabbedModeTabPersistencePolicy.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabbedModeTabPersistencePolicy.java
index 3040145..d350837 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabbedModeTabPersistencePolicy.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabbedModeTabPersistencePolicy.java
@@ -22,8 +22,6 @@
 import org.chromium.base.task.AsyncTask;
 import org.chromium.base.task.BackgroundOnlyAsyncTask;
 import org.chromium.base.task.TaskRunner;
-import org.chromium.chrome.browser.browseractions.BrowserActionsTabModelSelector;
-import org.chromium.chrome.browser.browseractions.BrowserActionsTabPersistencePolicy;
 import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager;
 import org.chromium.chrome.browser.tab.TabState;
 import org.chromium.chrome.browser.util.FeatureUtilities;
@@ -121,11 +119,7 @@
         if (FeatureUtilities.isTabModelMergingEnabled()) {
             mergedFileNames.add(getStateFileName(mOtherSelectorIndex));
         }
-        if (!BrowserActionsTabModelSelector.isInitialized()) {
-            BrowserActionsTabPersistencePolicy browserActionsPersistencePolicy =
-                    new BrowserActionsTabPersistencePolicy();
-            mergedFileNames.add(browserActionsPersistencePolicy.getStateFileName());
-        }
+        // TODO(peconn): Can I clean up this code now that Browser Actions are gone?
         return mergedFileNames;
     }
 
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd
index f634190..5c7b8df 100644
--- a/chrome/android/java/strings/android_chrome_strings.grd
+++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -1291,9 +1291,6 @@
       </message>
 
       <!-- Lite Mode-->
-      <message name="IDS_DATA_SAVER_IPH_REBRAND_LITE_MODE" desc="An onscreen notification to the user that the Chrome feature previously named 'Data Saver' is now named 'Lite mode'.">
-        Data Saver is now Lite mode
-      </message>
       <message name="IDS_DATA_REDUCTION_TITLE_LITE_MODE" desc="Menu item for Lite mode, which allows users to save mobile data by compressing network traffic.">
         Lite mode
       </message>
@@ -2181,38 +2178,6 @@
         Refreshing page
       </message>
 
-      <!-- Browser Action strings -->
-      <message name="IDS_BROWSER_ACTIONS_OPEN_IN_BACKGROUND" desc="Browser Actions menu item to open the selected link in a Chrome tab in the background. [CHAR-LIMIT=30]">
-        Open in new Chrome tab
-      </message>
-      <message name="IDS_BROWSER_ACTIONS_OPEN_IN_INCOGNITO_TAB" desc="Browser Actions menu item to open the selected link in a Chrome incognito tab. [CHAR-LIMIT=30]">
-        Open in incognito tab
-      </message>
-      <message name="IDS_BROWSER_ACTIONS_SAVE_LINK_AS" desc="Browser Actions menu item to download the page of the selected link. [CHAR-LIMIT=30]">
-        Download link
-      </message>
-      <message name="IDS_BROWSER_ACTIONS_COPY_ADDRESS" desc="Browser Actions menu item to copy the url address of the selected link. [CHAR-LIMIT=30]">
-        Copy link
-      </message>
-      <message name="IDS_BROWSER_ACTIONS_SHARE" desc="Browser Actions menu item to share the url address of the selected link. [CHAR-LIMIT=30]">
-        Share...
-      </message>
-      <message name="IDS_BROWSER_ACTIONS_OPEN_IN_BACKGROUND_TOAST_MESSAGE" desc="Browser Actions toast message when to open a link in new Chrome tab in the backgoround. [CHAR-LIMIT=30]">
-        Link opened in Chrome
-      </message>
-      <message name="IDS_BROWSER_ACTIONS_SINGLE_LINK_OPEN_NOTIFICATION_TITLE" desc="Content title displayed in the notification when one link is opened in the background from Browser Actions. [CHAR-LIMIT=30]">
-        Link opened in Chrome
-      </message>
-      <message name="IDS_BROWSER_ACTIONS_MULTI_LINKS_OPEN_NOTIFICATION_TITLE" desc="Content title displayed in the notification when multiple links are opened in the background from Browser Actions. [CHAR-LIMIT=41]">
-        Multiple links opened in Chrome
-      </message>
-      <message name="IDS_BROWSER_ACTIONS_NOTIFICATION_TEXT" desc="Context text displayed in the notification when links are opened in the background from Browser Actions. [CHAR-LIMIT=30]">
-        Tap to view
-      </message>
-      <message name="IDS_BROWSER_ACTIONS_LOADING_NATIVE_MESSAGE" desc="Message on the progress dialog used when waiting for loading native library before downloading a url. [CHAR-LIMIT=30]">
-        Please wait…
-      </message>
-
       <!-- App banner accessibility strings, used for touch exploration -->
       <message name="IDS_APP_BANNER_VIEW_NATIVE_APP_INSTALL_ACCESSIBILITY" desc="Accessibility text: Indicates that clicking on the button will either purchase the app or install it.">
         Get the app from the Google Play Store: <ph name="APP_ACTION">%s<ex>Install</ex></ph>
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/browseractions/BrowserActionActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/browseractions/BrowserActionActivityTest.java
deleted file mode 100644
index d59d08f..0000000
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/browseractions/BrowserActionActivityTest.java
+++ /dev/null
@@ -1,788 +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.
-
-package org.chromium.chrome.browser.browseractions;
-
-import android.annotation.TargetApi;
-import android.app.Activity;
-import android.app.Instrumentation;
-import android.app.Instrumentation.ActivityMonitor;
-import android.app.PendingIntent;
-import android.app.ProgressDialog;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.StrictMode;
-import android.support.annotation.DrawableRes;
-import android.support.customtabs.browseractions.BrowserActionItem;
-import android.support.customtabs.browseractions.BrowserActionsIntent;
-import android.support.customtabs.browseractions.BrowserServiceFileProvider;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.util.Pair;
-import android.util.SparseArray;
-
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import org.chromium.base.ActivityState;
-import org.chromium.base.ApplicationStatus;
-import org.chromium.base.Callback;
-import org.chromium.base.ContextUtils;
-import org.chromium.base.test.util.CallbackHelper;
-import org.chromium.base.test.util.Feature;
-import org.chromium.base.test.util.MinAndroidSdkLevel;
-import org.chromium.chrome.R;
-import org.chromium.chrome.browser.ChromeTabbedActivity;
-import org.chromium.chrome.browser.browseractions.BrowserActionsContextMenuHelper.BrowserActionsTestDelegate;
-import org.chromium.chrome.browser.contextmenu.ChromeContextMenuItem;
-import org.chromium.chrome.browser.contextmenu.ContextMenuItem;
-import org.chromium.chrome.browser.contextmenu.ShareContextMenuItem;
-import org.chromium.chrome.browser.customtabs.CustomTabActivityTestRule;
-import org.chromium.chrome.browser.customtabs.CustomTabsTestUtils;
-import org.chromium.chrome.browser.firstrun.FirstRunStatus;
-import org.chromium.chrome.browser.multiwindow.MultiWindowTestHelper;
-import org.chromium.chrome.browser.multiwindow.MultiWindowUtils;
-import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tabmodel.EmptyTabModelObserver;
-import org.chromium.chrome.browser.tabmodel.TabLaunchType;
-import org.chromium.chrome.browser.tabmodel.TabModel;
-import org.chromium.chrome.browser.tabmodel.TabModelObserver;
-import org.chromium.chrome.browser.util.IntentUtils;
-import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
-import org.chromium.content_public.browser.LoadUrlParams;
-import org.chromium.content_public.browser.test.util.Criteria;
-import org.chromium.content_public.browser.test.util.CriteriaHelper;
-import org.chromium.content_public.browser.test.util.TestThreadUtils;
-import org.chromium.net.test.EmbeddedTestServer;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Callable;
-
-/**
- * Instrumentation tests for context menu of a {@link BrowserActionActivity}.
- */
-@RunWith(ChromeJUnit4ClassRunner.class)
-public class BrowserActionActivityTest {
-    private static final String TEST_PAGE = "/chrome/test/data/android/google.html";
-    private static final String TEST_PAGE_2 = "/chrome/test/data/android/test.html";
-    private static final String TEST_PAGE_3 = "/chrome/test/data/android/simple.html";
-    private static final String CUSTOM_ITEM_TITLE_1 = "Custom item with drawable icon";
-    private static final String CUSTOM_ITEM_TITLE_2 = "Custom item with vector drawable icon";
-    private static final String CUSTOM_ITEM_TITLE_3 = "Custom item wit invalid icon id";
-    private static final String CUSTOM_ITEM_TITLE_4 = "Custom item without icon";
-    @DrawableRes
-    private static final int CUSTOM_ITEM_ICON_BITMAP_DRAWABLE_ID_1 = R.drawable.star_green;
-    @DrawableRes
-    private static final int CUSTOM_ITEM_ICON_BITMAP_DRAWABLE_ID_2 = R.drawable.star_gray;
-    @DrawableRes
-    private static final int CUSTOM_ITEM_ICON_VECTOR_DRAWABLE_ID = R.drawable.ic_add;
-    @DrawableRes
-    private static final int CUSTOM_ITEM_ICON_INVALID_DRAWABLE_ID = -1;
-
-    private final CallbackHelper mOnBrowserActionsMenuShownCallback = new CallbackHelper();
-    private final CallbackHelper mOnFinishNativeInitializationCallback = new CallbackHelper();
-    private final CallbackHelper mOnOpenTabInBackgroundStartCallback = new CallbackHelper();
-    private final CallbackHelper mOnDownloadStartCallback = new CallbackHelper();
-
-    private final CallbackHelper mDidAddTabCallback = new CallbackHelper();
-
-    private SparseArray<PendingIntent> mCustomActions;
-    private List<Pair<Integer, List<ContextMenuItem>>> mItems;
-    private ProgressDialog mProgressDialog;
-    private TestDelegate mTestDelegate;
-    private TabModelObserver mTestObserver;
-    private EmbeddedTestServer mTestServer;
-    private String mTestPage;
-    private String mTestPage2;
-    private String mTestPage3;
-    @Rule
-    public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
-    @Rule
-    public CustomTabActivityTestRule mCustomTabActivityTestRule = new CustomTabActivityTestRule();
-
-    private class TestDelegate implements BrowserActionsTestDelegate {
-        @Override
-        public void onBrowserActionsMenuShown() {
-            mOnBrowserActionsMenuShownCallback.notifyCalled();
-        }
-
-        @Override
-        public void onFinishNativeInitialization() {
-            mOnFinishNativeInitializationCallback.notifyCalled();
-        }
-
-        @Override
-        public void onOpenTabInBackgroundStart() {
-            mOnOpenTabInBackgroundStartCallback.notifyCalled();
-        }
-
-        @Override
-        public void initialize(SparseArray<PendingIntent> customActions,
-                List<Pair<Integer, List<ContextMenuItem>>> items,
-                ProgressDialog progressDialog) {
-            mCustomActions = customActions;
-            mItems = items;
-            mProgressDialog = progressDialog;
-        }
-
-        @Override
-        public void onDownloadStart() {
-            mOnDownloadStartCallback.notifyCalled();
-        }
-    }
-
-    @Before
-    public void setUp() throws Exception {
-        TestThreadUtils.runOnUiThreadBlocking(
-                () -> { FirstRunStatus.setFirstRunFlowComplete(true); });
-        mTestDelegate = new TestDelegate();
-        mTestObserver = new EmptyTabModelObserver() {
-            @Override
-            public void didAddTab(Tab tab, @TabLaunchType int type) {
-                mDidAddTabCallback.notifyCalled();
-            }
-        };
-        Context appContext = InstrumentationRegistry.getInstrumentation()
-                                     .getTargetContext()
-                                     .getApplicationContext();
-        mTestServer = EmbeddedTestServer.createAndStartServer(appContext);
-        mTestPage = mTestServer.getURL(TEST_PAGE);
-        mTestPage2 = mTestServer.getURL(TEST_PAGE_2);
-        mTestPage3 = mTestServer.getURL(TEST_PAGE_3);
-    }
-
-    @After
-    public void tearDown() throws Exception {
-        TestThreadUtils.runOnUiThreadBlocking(
-                () -> { FirstRunStatus.setFirstRunFlowComplete(false); });
-        mTestServer.stopAndDestroyServer();
-    }
-
-    private void assertDrawableNull(Context context, ContextMenuItem item) {
-        item.getDrawableAsync(context, new Callback<Drawable>() {
-            @Override
-            public void onResult(Drawable drawable) {
-                Assert.assertNull(drawable);
-            }
-        });
-    }
-
-    private void assertDrawableNotNull(Context context, ContextMenuItem item) {
-        item.getDrawableAsync(context, new Callback<Drawable>() {
-            @Override
-            public void onResult(Drawable drawable) {
-                Assert.assertNotNull(drawable);
-            }
-        });
-    }
-
-    @Test
-    @SmallTest
-    /**
-     * TODO(ltian): move this to a separate test class only for {@link
-     * BrowserActionsContextMenuHelper}.
-     */
-    public void testMenuShownCorrectlyWithFREComplete() throws Exception {
-        List<BrowserActionItem> items = createCustomItems();
-        BrowserActionActivity activity = startBrowserActionActivity(mTestPage, items, 0);
-
-        // Menu should be shown before native finish loading.
-        mOnBrowserActionsMenuShownCallback.waitForCallback(0);
-        Assert.assertEquals(0, mOnFinishNativeInitializationCallback.getCallCount());
-        Assert.assertEquals(0, mOnOpenTabInBackgroundStartCallback.getCallCount());
-
-        // Let the initialization completes.
-        mOnFinishNativeInitializationCallback.waitForCallback(0);
-        Assert.assertEquals(1, mOnBrowserActionsMenuShownCallback.getCallCount());
-        Assert.assertEquals(1, mOnFinishNativeInitializationCallback.getCallCount());
-
-        Context context = InstrumentationRegistry.getTargetContext();
-        Assert.assertEquals(context.getPackageName(), activity.mUntrustedCreatorPackageName);
-
-        // Check menu populated correctly.
-        List<Pair<Integer, List<ContextMenuItem>>> menus = mItems;
-        Assert.assertEquals(1, menus.size());
-        List<ContextMenuItem> contextMenuItems = menus.get(0).second;
-        Assert.assertEquals(5 + items.size(), contextMenuItems.size());
-        for (int i = 0; i < 4; i++) {
-            Assert.assertTrue(contextMenuItems.get(i) instanceof ChromeContextMenuItem);
-        }
-        Assert.assertTrue(contextMenuItems.get(4) instanceof ShareContextMenuItem);
-        Assert.assertTrue(contextMenuItems.get(5) instanceof BrowserActionsCustomContextMenuItem);
-        // Load custom items correctly.
-        for (int i = 0; i < items.size(); i++) {
-            Assert.assertEquals(
-                    items.get(i).getTitle(), contextMenuItems.get(5 + i).getTitle(context));
-            Assert.assertEquals(items.get(i).getAction(),
-                    mCustomActions.get(
-                            BrowserActionsContextMenuHelper.CUSTOM_BROWSER_ACTIONS_ID_GROUP.get(
-                                    i)));
-        }
-        assertDrawableNotNull(context, contextMenuItems.get(5));
-        assertDrawableNotNull(context, contextMenuItems.get(6));
-        assertDrawableNull(context, contextMenuItems.get(7));
-        assertDrawableNull(context, contextMenuItems.get(8));
-    }
-
-    @Test
-    @SmallTest
-    public void testMenuShownCorrectlyWithFRENotComplete() throws Exception {
-        TestThreadUtils.runOnUiThreadBlocking(
-                () -> { FirstRunStatus.setFirstRunFlowComplete(false); });
-        List<BrowserActionItem> items = createCustomItems();
-        BrowserActionActivity activity = startBrowserActionActivity(mTestPage, items, 0);
-
-        // Menu should be shown before native finish loading.
-        Assert.assertTrue(activity.isStartupDelayed());
-        mOnBrowserActionsMenuShownCallback.waitForCallback(0);
-        Assert.assertEquals(1, mOnBrowserActionsMenuShownCallback.getCallCount());
-        // startupDelayed should still be true because native initalized is skipped.
-        Assert.assertTrue(activity.isStartupDelayed());
-        Assert.assertEquals(0, mOnFinishNativeInitializationCallback.getCallCount());
-
-        Context context = InstrumentationRegistry.getTargetContext();
-        Assert.assertEquals(context.getPackageName(), activity.mUntrustedCreatorPackageName);
-
-        // Check menu populated correctly that only copy, share and custom items are shown.
-        List<Pair<Integer, List<ContextMenuItem>>> menus = mItems;
-        Assert.assertEquals(1, menus.size());
-        List<ContextMenuItem> contextMenuItems = menus.get(0).second;
-        Assert.assertEquals(2 + items.size(), contextMenuItems.size());
-        Assert.assertTrue(contextMenuItems.get(0) instanceof ChromeContextMenuItem);
-        Assert.assertTrue(contextMenuItems.get(1) instanceof ShareContextMenuItem);
-        for (int i = 0; i < items.size(); i++) {
-            Assert.assertEquals(
-                    items.get(i).getTitle(), contextMenuItems.get(2 + i).getTitle(context));
-            Assert.assertEquals(items.get(i).getAction(),
-                    mCustomActions.get(
-                            BrowserActionsContextMenuHelper.CUSTOM_BROWSER_ACTIONS_ID_GROUP.get(
-                                    i)));
-        }
-        assertDrawableNotNull(context, contextMenuItems.get(2));
-        assertDrawableNotNull(context, contextMenuItems.get(3));
-        assertDrawableNull(context, contextMenuItems.get(4));
-        assertDrawableNull(context, contextMenuItems.get(5));
-    }
-
-    @Test
-    @SmallTest
-    public void testCustomIconShownFromProviderCorrectly() throws Exception {
-        List<BrowserActionItem> items = createCustomItemsWithProvider();
-        startBrowserActionActivity(mTestPage, items, 0);
-        mOnBrowserActionsMenuShownCallback.waitForCallback(0);
-
-        List<Pair<Integer, List<ContextMenuItem>>> menus = mItems;
-        List<ContextMenuItem> contextMenuItems = menus.get(0).second;
-        ContentResolver resolver = InstrumentationRegistry.getTargetContext().getContentResolver();
-
-        Assert.assertTrue(contextMenuItems.get(5) instanceof BrowserActionsCustomContextMenuItem);
-        BrowserActionsCustomContextMenuItem customItems =
-                (BrowserActionsCustomContextMenuItem) contextMenuItems.get(5);
-        CallbackHelper imageShownCallback = new CallbackHelper();
-        Context context = InstrumentationRegistry.getTargetContext();
-        Callback<Drawable> callback = new Callback<Drawable>() {
-            @Override
-            public void onResult(Drawable drawable) {
-                Assert.assertNotNull(drawable);
-                imageShownCallback.notifyCalled();
-            }
-        };
-        customItems.getDrawableAsync(context, callback);
-        imageShownCallback.waitForCallback(0);
-    }
-
-    @Test
-    @SmallTest
-    public void testOpenTabInBackgroundWithInitialization() throws Exception {
-        testItemHandlingWithInitialzation(
-                R.id.browser_actions_open_in_background, mOnOpenTabInBackgroundStartCallback);
-    }
-
-    @Test
-    @SmallTest
-    public void testDownloadWithInitialization() throws Exception {
-        testItemHandlingWithInitialzation(
-                R.id.browser_actions_save_link_as, mOnDownloadStartCallback);
-    }
-
-    private void testItemHandlingWithInitialzation(int itemid, CallbackHelper callback)
-            throws Exception {
-        final BrowserActionActivity activity = startBrowserActionActivity(mTestPage);
-        mOnBrowserActionsMenuShownCallback.waitForCallback(0);
-        // Download an url before initialization finishes.
-        TestThreadUtils.runOnUiThreadBlocking(
-                () -> { activity.getHelperForTesting().onItemSelected(itemid, false); });
-
-        // If native initialization is not finished, A ProgressDialog should be displayed and
-        // chosen item should be pending until initialization is finished.
-        if (mOnFinishNativeInitializationCallback.getCallCount() == 0) {
-            Assert.assertTrue(mProgressDialog.isShowing());
-            mOnFinishNativeInitializationCallback.waitForCallback(0);
-        }
-        callback.waitForCallback(0);
-        Assert.assertEquals(1, mOnFinishNativeInitializationCallback.getCallCount());
-        Assert.assertFalse(mProgressDialog.isShowing());
-        Assert.assertEquals(1, callback.getCallCount());
-    }
-
-    @Test
-    @SmallTest
-    public void testOpenSingleTabInBackgroundWhenChromeAvailable() throws Exception {
-        // Start ChromeTabbedActivity first.
-        mActivityTestRule.startMainActivityWithURL(mTestPage);
-
-        // Load Browser Actions menu completely.
-        final BrowserActionActivity activity = startBrowserActionActivity(mTestPage2);
-        mOnBrowserActionsMenuShownCallback.waitForCallback(0);
-        mOnFinishNativeInitializationCallback.waitForCallback(0);
-        Assert.assertEquals(1, mActivityTestRule.getActivity().getCurrentTabModel().getCount());
-        // No notification should be shown.
-        Assert.assertFalse(BrowserActionsService.hasBrowserActionsNotification());
-
-        // Open a tab in the background.
-        openTabInBackground(activity);
-        // Notification for single tab should be shown.
-        Assert.assertEquals(R.string.browser_actions_single_link_open_notification_title,
-                BrowserActionsService.getTitleResId());
-
-        // Tabs should always be added at the end of the model.
-        Assert.assertEquals(2, mActivityTestRule.getActivity().getCurrentTabModel().getCount());
-        Assert.assertEquals(mTestPage,
-                mActivityTestRule.getActivity().getCurrentTabModel().getTabAt(0).getUrl());
-        Assert.assertEquals(mTestPage2,
-                mActivityTestRule.getActivity().getCurrentTabModel().getTabAt(1).getUrl());
-        int prevTabId = mActivityTestRule.getActivity().getCurrentTabModel().getTabAt(0).getId();
-        int newTabId = mActivityTestRule.getActivity().getCurrentTabModel().getTabAt(1).getId();
-        // TODO(ltian): overwrite delegate prevent creating notifcation for test.
-        Intent notificationIntent = BrowserActionsService.getNotificationIntent();
-        notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
-        // Force ChromeTabbedActivity dismissed to make sure it calls onStop then calls onStart next
-        // time it is started by an Intent.
-        Intent customTabIntent = CustomTabsTestUtils.createMinimalCustomTabIntent(
-                InstrumentationRegistry.getTargetContext(), mTestPage);
-        mCustomTabActivityTestRule.startCustomTabActivityWithIntent(customTabIntent);
-
-        // The Intent of the Browser Actions notification should not toggle overview mode and should
-        mActivityTestRule.startActivityCompletely(notificationIntent);
-        Assert.assertFalse(
-                mActivityTestRule.getActivity().getOverviewModeBehavior().overviewVisible());
-        Assert.assertNotEquals(prevTabId, mActivityTestRule.getActivity().getActivityTab().getId());
-        Assert.assertEquals(newTabId, mActivityTestRule.getActivity().getActivityTab().getId());
-    }
-
-    @Test
-    @SmallTest
-    public void testOpenMulitpleTabsInBackgroundWhenChromeAvailable() throws Exception {
-        // Start ChromeTabbedActivity first.
-        mActivityTestRule.startMainActivityWithURL(mTestPage);
-
-        // Open two tabs in the background.
-        final BrowserActionActivity activity1 = startBrowserActionActivity(mTestPage2);
-        mOnBrowserActionsMenuShownCallback.waitForCallback(0);
-        mOnFinishNativeInitializationCallback.waitForCallback(0);
-        Assert.assertEquals(1, mActivityTestRule.getActivity().getCurrentTabModel().getCount());
-        Assert.assertFalse(BrowserActionsService.hasBrowserActionsNotification());
-        openTabInBackground(activity1);
-        Assert.assertEquals(R.string.browser_actions_single_link_open_notification_title,
-                BrowserActionsService.getTitleResId());
-
-        final BrowserActionActivity activity2 = startBrowserActionActivity(mTestPage3, 1);
-        mOnBrowserActionsMenuShownCallback.waitForCallback(1);
-        Assert.assertEquals(2, mActivityTestRule.getActivity().getCurrentTabModel().getCount());
-        openTabInBackground(activity2);
-        // Notification title should be shown for multiple tabs.
-        CriteriaHelper.pollUiThread(new Criteria() {
-            @Override
-            public boolean isSatisfied() {
-                return R.string.browser_actions_multi_links_open_notification_title
-                        == BrowserActionsService.getTitleResId();
-            }
-        });
-
-        // Tabs should always be added at the end of the model.
-        int tabCount = mActivityTestRule.getActivity().getCurrentTabModel().getCount();
-        Assert.assertEquals(mTestPage,
-                mActivityTestRule.getActivity()
-                        .getCurrentTabModel()
-                        .getTabAt(tabCount - 3)
-                        .getUrl());
-        Assert.assertEquals(mTestPage2,
-                mActivityTestRule.getActivity()
-                        .getCurrentTabModel()
-                        .getTabAt(tabCount - 2)
-                        .getUrl());
-        Assert.assertEquals(mTestPage3,
-                mActivityTestRule.getActivity()
-                        .getCurrentTabModel()
-                        .getTabAt(tabCount - 1)
-                        .getUrl());
-        Intent notificationIntent = BrowserActionsService.getNotificationIntent();
-        notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
-        // Force ChromeTabbedActivity dismissed to make sure it calls onStop then calls onStart next
-        // time it is started by an Intent.
-        Intent customTabIntent = CustomTabsTestUtils.createMinimalCustomTabIntent(
-                InstrumentationRegistry.getTargetContext(), mTestPage);
-        mCustomTabActivityTestRule.startCustomTabActivityWithIntent(customTabIntent);
-
-        // The Intent of the Browser Actions notification should toggle overview mode.
-        mActivityTestRule.startActivityCompletely(notificationIntent);
-        if (mActivityTestRule.getActivity().isTablet()) {
-            Assert.assertFalse(
-                    mActivityTestRule.getActivity().getOverviewModeBehavior().overviewVisible());
-        } else {
-            Assert.assertTrue(
-                    mActivityTestRule.getActivity().getOverviewModeBehavior().overviewVisible());
-        }
-    }
-
-    @Test
-    @SmallTest
-    public void testOpenSingleTabInBackgroundWhenChromeNotAvailable() throws Exception {
-        // Load Browser Actions menu completely.
-        final BrowserActionActivity activity = startBrowserActionActivity(mTestPage);
-        mOnBrowserActionsMenuShownCallback.waitForCallback(0);
-        mOnFinishNativeInitializationCallback.waitForCallback(0);
-        // No notification should be shown.
-        Assert.assertFalse(BrowserActionsService.hasBrowserActionsNotification());
-
-        BrowserActionsTabModelSelector selector = TestThreadUtils.runOnUiThreadBlocking(
-                new Callable<BrowserActionsTabModelSelector>() {
-                    @Override
-                    public BrowserActionsTabModelSelector call() {
-                        return BrowserActionsTabModelSelector.getInstance();
-                    }
-                });
-        // Open a tab in the background.
-        selector.getModel(false).addObserver(mTestObserver);
-        openTabInBackground(activity);
-        Assert.assertEquals(R.string.browser_actions_single_link_open_notification_title,
-                BrowserActionsService.getTitleResId());
-        mDidAddTabCallback.waitForCallback(0);
-        // New tab should be added to the BrowserActionTabModelSelector.
-        Assert.assertEquals(1, selector.getCurrentModel().getCount());
-        Tab newTab = selector.getCurrentModel().getTabAt(0);
-        Assert.assertEquals(mTestPage, newTab.getUrl());
-
-        // Browser Actions tabs should be merged into Chrome tab model when Chrome starts.
-        Intent notificationIntent = BrowserActionsService.getNotificationIntent();
-        notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        mActivityTestRule.startActivityCompletely(notificationIntent);
-        TabModel currentModel =
-                mActivityTestRule.getActivity().getTabModelSelector().getCurrentModel();
-        CriteriaHelper.pollUiThread(new Criteria() {
-            @Override
-            public boolean isSatisfied() {
-                return currentModel.getCount() == 1;
-            }
-        });
-        Assert.assertEquals(newTab.getId(), currentModel.getTabAt(0).getId());
-    }
-
-    @Test
-    @SmallTest
-    public void testOpenMultipleTabsInBackgroundWhenChromeNotAvailable() throws Exception {
-        // Load Browser Actions menu completely and open a tab in the background.
-        final BrowserActionActivity activity1 = startBrowserActionActivity(mTestPage);
-        mOnBrowserActionsMenuShownCallback.waitForCallback(0);
-        mOnFinishNativeInitializationCallback.waitForCallback(0);
-
-        BrowserActionsTabModelSelector selector = TestThreadUtils.runOnUiThreadBlocking(
-                new Callable<BrowserActionsTabModelSelector>() {
-                    @Override
-                    public BrowserActionsTabModelSelector call() {
-                        return BrowserActionsTabModelSelector.getInstance();
-                    }
-                });
-        selector.getModel(false).addObserver(mTestObserver);
-        openTabInBackground(activity1);
-        Assert.assertEquals(R.string.browser_actions_single_link_open_notification_title,
-                BrowserActionsService.getTitleResId());
-        mDidAddTabCallback.waitForCallback(0);
-        Assert.assertEquals(1, selector.getCurrentModel().getCount());
-
-        // Load Browser Actions menu again and open another tab in the background.
-        final BrowserActionActivity activity2 = startBrowserActionActivity(mTestPage2, 1);
-        mOnBrowserActionsMenuShownCallback.waitForCallback(1);
-        mOnFinishNativeInitializationCallback.waitForCallback(1);
-        openTabInBackground(activity2);
-        // Notification title should be shown for multiple tabs.
-        CriteriaHelper.pollUiThread(new Criteria() {
-            @Override
-            public boolean isSatisfied() {
-                return R.string.browser_actions_multi_links_open_notification_title
-                        == BrowserActionsService.getTitleResId();
-            }
-        });
-
-        // BrowserActionTabModelSelector should have two tabs and tabs should be added sequentially.
-        mDidAddTabCallback.waitForCallback(1);
-        Assert.assertEquals(2, selector.getCurrentModel().getCount());
-        Tab newTab1 = selector.getCurrentModel().getTabAt(0);
-        Tab newTab2 = selector.getCurrentModel().getTabAt(1);
-        Assert.assertEquals(mTestPage, newTab1.getUrl());
-        Assert.assertEquals(mTestPage2, newTab2.getUrl());
-
-        // Browser Actions tabs should be merged into Chrome tab model when Chrome starts.
-        Intent notificationIntent = BrowserActionsService.getNotificationIntent();
-        notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        mActivityTestRule.startActivityCompletely(notificationIntent);
-        TabModel currentModel =
-                mActivityTestRule.getActivity().getTabModelSelector().getCurrentModel();
-        CriteriaHelper.pollUiThread(new Criteria() {
-            @Override
-            public boolean isSatisfied() {
-                return currentModel.getCount() == 2;
-            }
-        });
-        Assert.assertEquals(newTab1.getId(), currentModel.getTabAt(0).getId());
-        Assert.assertEquals(newTab2.getId(), currentModel.getTabAt(1).getId());
-        Assert.assertEquals(1, currentModel.index());
-
-        // Tab switcher should be shown on phones.
-        if (mActivityTestRule.getActivity().isTablet()) {
-            Assert.assertFalse(
-                    mActivityTestRule.getActivity().getOverviewModeBehavior().overviewVisible());
-        } else {
-            Assert.assertTrue(
-                    mActivityTestRule.getActivity().getOverviewModeBehavior().overviewVisible());
-        }
-    }
-
-    private void openTabInBackground(BrowserActionActivity activity) {
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
-            try {
-                activity.getHelperForTesting().onItemSelected(
-                        R.id.browser_actions_open_in_background, false);
-            } finally {
-                StrictMode.setThreadPolicy(oldPolicy);
-            }
-        });
-        CriteriaHelper.pollUiThread(new Criteria() {
-            @Override
-            public boolean isSatisfied() {
-                return BrowserActionsService.hasBrowserActionsNotification()
-                        && BrowserActionsService.isBackgroundService();
-            }
-        });
-    }
-
-    @Test
-    @SmallTest
-    @Feature({"TabPersistentStore", "MultiWindow"})
-    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
-    @MinAndroidSdkLevel(24)
-    public void testTabMergingWhenChromeNotAvailable() throws Exception {
-        // Start two ChromeTabbedActivitys in MultiWindow mode.
-        mActivityTestRule.startMainActivityWithURL(mTestPage);
-        ChromeTabbedActivity activity1 = mActivityTestRule.getActivity();
-        MultiWindowUtils.getInstance().setIsInMultiWindowModeForTesting(true);
-        ChromeTabbedActivity activity2 =
-                MultiWindowTestHelper.createSecondChromeTabbedActivity(activity1);
-        CriteriaHelper.pollUiThread(new Criteria() {
-            @Override
-            public boolean isSatisfied() {
-                return activity2.areTabModelsInitialized()
-                        && activity2.getTabModelSelector().isTabStateInitialized()
-                        && activity2.getActivityTab() != null;
-            }
-        });
-        String cta2ActivityTabUrl = activity2.getActivityTab().getUrl();
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            activity2.getTabCreator(false).createNewTab(
-                    new LoadUrlParams(mTestPage2), TabLaunchType.FROM_CHROME_UI, null);
-        });
-
-        // Save state and destroy both activities.
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            activity1.saveState();
-            activity2.saveState();
-            activity1.finishAndRemoveTask();
-            activity2.finishAndRemoveTask();
-        });
-
-        CriteriaHelper.pollUiThread(new Criteria() {
-            @Override
-            public boolean isSatisfied() {
-                return ApplicationStatus.getStateForActivity(activity1) == ActivityState.DESTROYED
-                        && ApplicationStatus.getStateForActivity(activity2)
-                        == ActivityState.DESTROYED;
-            }
-        });
-
-        // Load Browser Actions menu and open a tab in the background completely.
-        final BrowserActionActivity activity3 = startBrowserActionActivity(mTestPage3);
-        mOnBrowserActionsMenuShownCallback.waitForCallback(0);
-        mOnFinishNativeInitializationCallback.waitForCallback(0);
-        openTabInBackground(activity3);
-
-        // Save the Browser Actions tab states and destroy the selector and activity.
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            BrowserActionsTabModelSelector selector = BrowserActionsTabModelSelector.getInstance();
-            selector.saveState();
-            selector.destroy();
-        });
-        activity3.finish();
-
-        // Relaunch a new ChromeTabbedActivity. Tabs from multi-windows should be merged and
-        // Browser Actions tabs should be append at the end.
-        Intent intent = createChromeTabbedActivityIntent(ContextUtils.getApplicationContext());
-        ChromeTabbedActivity newActivity =
-                (ChromeTabbedActivity) InstrumentationRegistry.getInstrumentation()
-                        .startActivitySync(intent);
-        // Wait for the tab state to be initialized.
-        CriteriaHelper.pollUiThread(new Criteria() {
-            @Override
-            public boolean isSatisfied() {
-                return newActivity.areTabModelsInitialized()
-                        && newActivity.getTabModelSelector().isTabStateInitialized();
-            }
-        });
-        TabModel model = newActivity.getTabModelSelector().getModel(false);
-        Assert.assertEquals(4, model.getCount());
-        Assert.assertEquals(mTestPage, model.getTabAt(0).getUrl());
-        Assert.assertEquals(cta2ActivityTabUrl, model.getTabAt(1).getUrl());
-        Assert.assertEquals(mTestPage2, model.getTabAt(2).getUrl());
-        Assert.assertEquals(mTestPage3, model.getTabAt(3).getUrl());
-    }
-
-    // TODO(ltian): create a test util class and change this to a static function in it to share
-    // with TabModelMergingTest.
-    private Intent createChromeTabbedActivityIntent(Context context) {
-        Intent intent = new Intent();
-        intent.setClass(context, ChromeTabbedActivity.class);
-        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        return intent;
-    }
-
-    private BrowserActionActivity startBrowserActionActivity(String url) throws Exception {
-        return startBrowserActionActivity(url, 0);
-    }
-
-    private BrowserActionActivity startBrowserActionActivity(String url, int expectedCallCount)
-            throws Exception {
-        Context context = InstrumentationRegistry.getTargetContext();
-        return startBrowserActionActivity(url, new ArrayList<>(), expectedCallCount);
-    }
-
-    private BrowserActionActivity startBrowserActionActivity(
-            String url, List<BrowserActionItem> items, int expectedCallCount) throws Exception {
-        final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
-        ActivityMonitor browserActionMonitor =
-                new ActivityMonitor(BrowserActionActivity.class.getName(), null, false);
-        instrumentation.addMonitor(browserActionMonitor);
-
-        // The BrowserActionActivity shouldn't have started yet.
-        Assert.assertEquals(expectedCallCount, mOnBrowserActionsMenuShownCallback.getCallCount());
-        Assert.assertEquals(
-                expectedCallCount, mOnFinishNativeInitializationCallback.getCallCount());
-        Assert.assertEquals(expectedCallCount, mOnOpenTabInBackgroundStartCallback.getCallCount());
-
-        // Fire an Intent to start the BrowserActionActivity.
-        sendBrowserActionIntent(url, items);
-
-        Activity activity = instrumentation.waitForMonitorWithTimeout(
-                browserActionMonitor, CriteriaHelper.DEFAULT_MAX_TIME_TO_POLL);
-        Assert.assertNotNull("Activity didn't start", activity);
-        Assert.assertTrue("Wrong activity started", activity instanceof BrowserActionActivity);
-        instrumentation.removeMonitor(browserActionMonitor);
-        ((BrowserActionActivity) activity)
-                .getHelperForTesting()
-                .setTestDelegateForTesting(mTestDelegate);
-        return (BrowserActionActivity) activity;
-    }
-
-    private void sendBrowserActionIntent(String url, List<BrowserActionItem> items) {
-        Context context = InstrumentationRegistry.getTargetContext();
-        Intent intent = new Intent(BrowserActionsIntent.ACTION_BROWSER_ACTIONS_OPEN);
-        intent.setData(Uri.parse(url));
-        intent.putExtra(BrowserActionsIntent.EXTRA_TYPE, BrowserActionsIntent.URL_TYPE_NONE);
-        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, new Intent(), 0);
-        intent.putExtra(BrowserActionsIntent.EXTRA_APP_ID, pendingIntent);
-
-        ArrayList<Bundle> customItemBundles = new ArrayList<>();
-        List<Uri> uris = new ArrayList<>();
-        for (BrowserActionItem item : items) {
-            Bundle customItemBundle = new Bundle();
-            customItemBundle.putString(BrowserActionsIntent.KEY_TITLE, item.getTitle());
-            if (item.getIconId() != 0) {
-                customItemBundle.putInt(BrowserActionsIntent.KEY_ICON_ID, item.getIconId());
-            }
-            if (item.getIconUri() != null) {
-                Uri uri = item.getIconUri();
-                customItemBundle.putParcelable(BrowserActionsIntent.KEY_ICON_URI, uri);
-                uris.add(uri);
-            }
-            customItemBundle.putParcelable(BrowserActionsIntent.KEY_ACTION, item.getAction());
-            customItemBundles.add(customItemBundle);
-        }
-        intent.putParcelableArrayListExtra(
-                BrowserActionsIntent.EXTRA_MENU_ITEMS, customItemBundles);
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
-        intent.setClass(context, BrowserActionActivity.class);
-        if (!uris.isEmpty()) {
-            BrowserServiceFileProvider.grantReadPermission(
-                    intent, uris, InstrumentationRegistry.getContext());
-        }
-        // Android Test Rule auto adds {@link Intent.FLAG_ACTIVITY_NEW_TASK} which violates {@link
-        // BrowserActionsIntent} policy. Add an extra to skip Intent.FLAG_ACTIVITY_NEW_TASK check
-        // for test.
-        IntentUtils.safeStartActivity(context, intent);
-    }
-
-    private PendingIntent createCustomItemAction(String url) {
-        Context context = InstrumentationRegistry.getTargetContext();
-        Intent customIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
-        return PendingIntent.getActivity(context, 0, customIntent, 0);
-    }
-
-    private List<BrowserActionItem> createCustomItems() {
-        List<BrowserActionItem> items = new ArrayList<>();
-        PendingIntent action1 = createCustomItemAction(mTestPage);
-        BrowserActionItem item1 = new BrowserActionItem(
-                CUSTOM_ITEM_TITLE_1, action1, CUSTOM_ITEM_ICON_BITMAP_DRAWABLE_ID_1);
-        PendingIntent action2 = createCustomItemAction(mTestPage);
-        BrowserActionItem item2 = new BrowserActionItem(
-                CUSTOM_ITEM_TITLE_2, action2, CUSTOM_ITEM_ICON_VECTOR_DRAWABLE_ID);
-        PendingIntent action3 = createCustomItemAction(mTestPage);
-        BrowserActionItem item3 = new BrowserActionItem(
-                CUSTOM_ITEM_TITLE_3, action3, CUSTOM_ITEM_ICON_INVALID_DRAWABLE_ID);
-        PendingIntent action4 = createCustomItemAction(mTestPage);
-        BrowserActionItem item4 = new BrowserActionItem(CUSTOM_ITEM_TITLE_4, action4);
-        items.add(item1);
-        items.add(item2);
-        items.add(item3);
-        items.add(item4);
-        return items;
-    }
-
-    private List<BrowserActionItem> createCustomItemsWithProvider() {
-        List<BrowserActionItem> items = new ArrayList<>();
-        PendingIntent action1 = createCustomItemAction(mTestPage);
-        Context context = InstrumentationRegistry.getTargetContext();
-        Bitmap bm = BitmapFactory.decodeResource(
-                context.getResources(), CUSTOM_ITEM_ICON_BITMAP_DRAWABLE_ID_1);
-
-        Uri uri = BrowserServiceFileProvider.generateUri(context, bm, CUSTOM_ITEM_TITLE_1, 1);
-        BrowserActionItem item = new BrowserActionItem(CUSTOM_ITEM_TITLE_1, action1, uri);
-        items.add(item);
-        return items;
-    }
-}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/portals/PortalsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/portals/PortalsTest.java
index 9020bf6..d1bfab8 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/portals/PortalsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/portals/PortalsTest.java
@@ -6,7 +6,6 @@
 
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.MediumTest;
-import android.view.View;
 
 import org.junit.After;
 import org.junit.Assert;
@@ -25,17 +24,14 @@
 import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.content_public.browser.WebContents;
-import org.chromium.content_public.browser.test.util.Coordinates;
 import org.chromium.content_public.browser.test.util.JavaScriptUtils;
-import org.chromium.content_public.browser.test.util.TouchCommon;
 import org.chromium.net.test.EmbeddedTestServer;
 
 /**
  * Tests for the chrome/ layer support of the HTML portal element.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, "enable-features=Portals",
-        "enable-blink-features=OverscrollCustomization"})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, "enable-features=Portals"})
 public class PortalsTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
@@ -168,31 +164,4 @@
         executeScriptAndAwaitSwap(tab, "reactivatePredecessor();");
         JavaScriptUtils.executeJavaScriptAndWaitForResult(tab.getWebContents(), "removePortal();");
     }
-
-    /**
-     * Tests that a drag that started in the predecessor page causes a scroll in the activated page
-     * after a scroll triggered activation.
-     */
-    @Test
-    @MediumTest
-    @Feature({"Portals"})
-    public void testTouchTransfer() throws Exception {
-        mActivityTestRule.startMainActivityWithURL(
-                mTestServer.getURL("/chrome/test/data/android/portals/touch-transfer.html"));
-
-        ChromeActivity activity = mActivityTestRule.getActivity();
-        View contentView = activity.getActivityTab().getContentView();
-
-        int dragStartX = 30;
-        int dragStartY = contentView.getHeight() / 2;
-        int dragEndX = dragStartX;
-        int dragEndY = 30;
-        long downTime = System.currentTimeMillis();
-        TouchCommon.dragStart(activity, dragStartX, dragStartY, downTime);
-        TouchCommon.dragTo(activity, dragStartX, dragEndX, dragStartY, dragEndY, 100, downTime);
-        TouchCommon.dragEnd(activity, dragEndX, dragEndY, downTime);
-
-        WebContents contents = mActivityTestRule.getWebContents();
-        Assert.assertTrue(Coordinates.createFor(contents).getScrollYPixInt() > 0);
-    }
 }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/browseractions/BrowserActionsIntentTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/browseractions/BrowserActionsIntentTest.java
deleted file mode 100644
index da81eb3..0000000
--- a/chrome/android/junit/src/org/chromium/chrome/browser/browseractions/BrowserActionsIntentTest.java
+++ /dev/null
@@ -1,151 +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.
-
-package org.chromium.chrome.browser.browseractions;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.when;
-
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-import android.support.annotation.DrawableRes;
-import android.support.customtabs.browseractions.BrowserActionItem;
-import android.support.customtabs.browseractions.BrowserActionsIntent;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-
-import org.chromium.base.test.BaseRobolectricTestRunner;
-import org.chromium.base.test.util.Feature;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Unit tests for BrowserActionsIntent.
- */
-@RunWith(BaseRobolectricTestRunner.class)
-@Config(manifest = Config.NONE)
-public class BrowserActionsIntentTest {
-    private static final String HTTP_SCHEME_TEST_URL = "http://www.example.com";
-    private static final String HTTPS_SCHEME_TEST_URL = "https://www.example.com";
-    private static final String CHROME_SCHEME_TEST_URL = "chrome://example";
-    private static final String CONTENT_SCHEME_TEST_URL = "content://example";
-    private static final String SENDER_PACKAGE_NAME = "some.other.app.package.sender_name";
-    private static final String RECEIVER_PACKAGE_NAME = "some.other.app.package.receiver_name";
-    private static final String CUSTOM_ITEM_WITHOUT_ICON_TITLE = "Custom item without icon";
-    private static final String CUSTOM_ITEM_WITH_ICON_TITLE = "Custom item with icon";
-    @DrawableRes
-    private static final int CUSTOM_ITEM_WITH_ICON_ICONID = 1;
-
-    private Context mContext;
-    @Mock
-    private BrowserActionActivity mActivity;
-    @Mock
-    private PendingIntent mPendingIntent;
-
-    @Before
-    public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
-        mContext = RuntimeEnvironment.application;
-        mActivity = Mockito.mock(BrowserActionActivity.class);
-        when(mActivity.getPackageName()).thenReturn(RECEIVER_PACKAGE_NAME);
-        when(mActivity.isStartedUpCorrectly(any(Intent.class))).thenCallRealMethod();
-        when(mPendingIntent.getCreatorPackage()).thenReturn(SENDER_PACKAGE_NAME);
-    }
-
-    @Test
-    @Feature({"BrowserActions"})
-    public void testStartedUpCorrectly() {
-        assertFalse(mActivity.isStartedUpCorrectly(null));
-        assertFalse(mActivity.isStartedUpCorrectly(new Intent()));
-
-        Intent mIntent = createBaseBrowserActionsIntent(HTTP_SCHEME_TEST_URL);
-        assertTrue(mActivity.isStartedUpCorrectly(mIntent));
-
-        mIntent = createBaseBrowserActionsIntent(HTTP_SCHEME_TEST_URL);
-        mIntent.removeExtra(BrowserActionsIntent.EXTRA_APP_ID);
-        assertFalse(mActivity.isStartedUpCorrectly(mIntent));
-
-        mIntent = createBaseBrowserActionsIntent(HTTPS_SCHEME_TEST_URL);
-        assertTrue(mActivity.isStartedUpCorrectly(mIntent));
-
-        mIntent = createBaseBrowserActionsIntent(CHROME_SCHEME_TEST_URL);
-        assertFalse(mActivity.isStartedUpCorrectly(mIntent));
-
-        mIntent = createBaseBrowserActionsIntent(CONTENT_SCHEME_TEST_URL);
-        assertFalse(mActivity.isStartedUpCorrectly(mIntent));
-
-        mIntent = createBaseBrowserActionsIntent(HTTP_SCHEME_TEST_URL);
-        mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        assertFalse(mActivity.isStartedUpCorrectly(mIntent));
-
-        mIntent = createBaseBrowserActionsIntent(HTTP_SCHEME_TEST_URL);
-        mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
-        assertFalse(mActivity.isStartedUpCorrectly(mIntent));
-
-        mIntent = createBrowserActionsIntentWithCustomItems(
-                HTTP_SCHEME_TEST_URL, createCustomItems());
-        assertTrue(mActivity.isStartedUpCorrectly(mIntent));
-        testParseCustomItems(mActivity.mActions);
-    }
-
-    /**
-     * A convenient method to create a simple Intent for Browser Actions without custom item.
-     * @param url The url for the data of the Intent.
-     * @return The simple Intent for Browser Actions.
-     */
-    private Intent createBaseBrowserActionsIntent(String url) {
-        return createBrowserActionsIntentWithCustomItems(url, new ArrayList<>());
-    }
-
-    /**
-     * Creates an Intent for Browser Actions which contains a url and a list of custom items.
-     * @param url The url for the data of the Intent.
-     * @param items A List of custom items for Browser Actions menu.
-     * @return The Intent for Browser Actions.
-     */
-    private Intent createBrowserActionsIntentWithCustomItems(
-            String url, ArrayList<BrowserActionItem> items) {
-        return new BrowserActionsIntent.Builder(mContext, Uri.parse(url))
-                .setCustomItems(items)
-                .build()
-                .getIntent()
-                .putExtra(BrowserActionsIntent.EXTRA_APP_ID, mPendingIntent);
-    }
-
-    private ArrayList<BrowserActionItem> createCustomItems() {
-        BrowserActionItem item1 =
-                new BrowserActionItem(CUSTOM_ITEM_WITHOUT_ICON_TITLE, mPendingIntent);
-        BrowserActionItem item2 = new BrowserActionItem(
-                CUSTOM_ITEM_WITH_ICON_TITLE, mPendingIntent, CUSTOM_ITEM_WITH_ICON_ICONID);
-        ArrayList<BrowserActionItem> items = new ArrayList<>();
-        items.add(item1);
-        items.add(item2);
-        return items;
-    }
-
-    private void testParseCustomItems(List<BrowserActionItem> items) {
-        assertEquals(2, mActivity.mActions.size());
-
-        assertEquals(CUSTOM_ITEM_WITHOUT_ICON_TITLE, mActivity.mActions.get(0).getTitle());
-        assertEquals(0, mActivity.mActions.get(0).getIconId());
-        assertEquals(mPendingIntent, mActivity.mActions.get(0).getAction());
-
-        assertEquals(CUSTOM_ITEM_WITH_ICON_TITLE, mActivity.mActions.get(1).getTitle());
-        assertEquals(CUSTOM_ITEM_WITH_ICON_ICONID, mActivity.mActions.get(1).getIconId());
-        assertEquals(mPendingIntent, mActivity.mActions.get(1).getAction());
-    }
-}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfShareActivityTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfShareActivityTest.java
index 44fcc27..c8fa8bf4 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfShareActivityTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfShareActivityTest.java
@@ -11,6 +11,7 @@
 
 import android.support.test.filters.SmallTest;
 
+import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Rule;
@@ -20,6 +21,7 @@
 import org.mockito.MockitoAnnotations;
 import org.robolectric.annotation.Config;
 
+import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.base.test.util.JniMocker;
 import org.chromium.chrome.browser.ActivityTabProvider;
@@ -72,6 +74,12 @@
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
         mocker.mock(SendTabToSelfAndroidBridgeJni.TEST_HOOKS, mNativeMock);
+        RecordHistogram.setDisabledForTests(true);
+    }
+
+    @After
+    public void tearDown() {
+        RecordHistogram.setDisabledForTests(false);
     }
 
     @Test
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt
index 76d95cf..18dd791b 100644
--- a/chrome/android/profiles/newest.txt
+++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-77.0.3819.0_rc-r1-merged.afdo.bz2
\ No newline at end of file
+chromeos-chrome-amd64-77.0.3820.0_rc-r1-merged.afdo.bz2
\ No newline at end of file
diff --git a/chrome/app/chrome_content_browser_overlay_manifest.cc b/chrome/app/chrome_content_browser_overlay_manifest.cc
index f132c2b..ebd79bf9 100644
--- a/chrome/app/chrome_content_browser_overlay_manifest.cc
+++ b/chrome/app/chrome_content_browser_overlay_manifest.cc
@@ -121,7 +121,6 @@
                               safe_browsing::mojom::SafeBrowsing>())
         .RequireCapability("apps", "app_service")
         .RequireCapability("ash", "system_ui")
-        // Used by ShelfTestApi and ShelfIntegrationTestApi
         .RequireCapability("ash", "test")
         .RequireCapability("ash", "display")
         .RequireCapability("assistant", "assistant")
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 87e04fc..5954305 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -7483,7 +7483,6 @@
         <message name="IDS_TRANSLATE_BUBBLE_COULD_NOT_TRANSLATE_TITLE" desc="Title text for the translate bubble label when the page could not be translated.">
           This page could not be translated
         </message>
-
         <if expr="not use_titlecase">
           <message name="IDS_TRANSLATE_BUBBLE_ADVANCED_LINK" desc="Text to show for the translate bubble link label to jump to the advanced panel.">
             Options
@@ -7494,6 +7493,12 @@
           <message name="IDS_TRANSLATE_BUBBLE_ADVANCED_MENU_BUTTON" desc="Text to show for the translate bubble menu button to jump to the advanced panel, specifically to change which languages are translated between.">
             Change languages
           </message>
+          <message name="IDS_TRANSLATE_BUBBLE_CHANGE_TARGET_LANGUAGE" desc="Text for the menu item that lets the user open a dialog to choose another target language for translation, from a list of available languages.">
+            More languages...
+          </message>
+          <message name="IDS_TRANSLATE_BUBBLE_CHANGE_SOURCE_LANGUAGE" desc="Text for the menu item that lets the user open a dialog to choose another source language for translation, from a list of available languages.">
+            Page is not in <ph name="language">$1<ex>French</ex></ph> ?
+          </message>
           <message name="IDS_TRANSLATE_BUBBLE_ACCEPT" desc="Text to show for the translate bubble button to accept translation.">
             Translate
           </message>
@@ -7542,6 +7547,12 @@
           <message name="IDS_TRANSLATE_BUBBLE_LANGUAGE_SETTINGS" desc="Text to show for the translate bubble link label next to jump to the language setting page.">
             Language settings
           </message>
+          <message name="IDS_TRANSLATE_BUBBLE_ADVANCED_TARGET" desc="Text to show in the advanced source language view for TAB UI">
+            Language to translate into
+          </message>
+          <message name="IDS_TRANSLATE_BUBBLE_ADVANCED_SOURCE" desc="Text to show in the advanced source language view for TAB UI">
+            Page language to translate
+          </message>
         </if>
         <if expr="use_titlecase">
           <message name="IDS_TRANSLATE_BUBBLE_ADVANCED_LINK" desc="In Title Case: Text to show for the translate bubble link label to jump to the advanced panel.">
@@ -7553,6 +7564,12 @@
           <message name="IDS_TRANSLATE_BUBBLE_ADVANCED_MENU_BUTTON" desc="In Title Case: Text to show for the translate bubble menu button to jump to the advanced panel, specifically to change which languages are translated between.">
             Change Languages
           </message>
+          <message name="IDS_TRANSLATE_BUBBLE_CHANGE_TARGET_LANGUAGE" desc="Text to show for the translate bubble menu button which invokes the target language menu.">
+            More Languages...
+          </message>
+          <message name="IDS_TRANSLATE_BUBBLE_CHANGE_SOURCE_LANGUAGE" desc="Text to show for the translate bubble menu button which invokes the source language menu.">
+            Page Is Not In <ph name="language">$1<ex>French</ex></ph> ?
+          </message>
           <message name="IDS_TRANSLATE_BUBBLE_ACCEPT" desc="In Title Case: Text to show for the translate bubble button to accept translation.">
             Translate
           </message>
@@ -7601,10 +7618,19 @@
           <message name="IDS_TRANSLATE_BUBBLE_LANGUAGE_SETTINGS" desc="In Title Case: Text to show for the translate bubble link label next to jump to the language setting page.">
             Language Settings
           </message>
+          <message name="IDS_TRANSLATE_BUBBLE_ADVANCED_TARGET" desc="Text to show in the advanced source language view for TAB UI">
+            Language To Translate Into
+          </message>
+          <message name="IDS_TRANSLATE_BUBBLE_ADVANCED_SOURCE" desc="Text to show in the advanced source language view for TAB UI">
+            Page Language To Translate
+          </message>
         </if>
         <message name="IDS_TRANSLATE_BUBBLE_UNKNOWN_LANGUAGE" desc="Text to show for the translate bubble link label when the page source language cannot be determined. Used in place of a language name, so should be capitalized as such (e.g. &quot;Unknown&quot; for English, &quot;sconosciuto&quot; for Italian)" meaning="Noun to use in place of a language name in part of a translate bubble message.">
           Unknown
         </message>
+        <message name="IDS_TRANSLATE_BUBBLE_RESET" desc="Text to show for the language combobox to revert to its original state in the advanced view under TAB UI">
+            Reset
+        </message>
       </if>
 
       <!-- Web and message center notifications -->
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS
index cd7a488..fdc6c18 100644
--- a/chrome/browser/DEPS
+++ b/chrome/browser/DEPS
@@ -24,8 +24,8 @@
   # Use identity_manager.h instead of the below files;
   # see https://groups.google.com/a/chromium.org/d/msg/chromium-dev/dgFLuxqZt1o/iEqkyoQQBwAJ for help and info.
   "!components/signin/core/browser/fake_profile_oauth2_token_service.h",
-  "!components/signin/core/browser/signin_manager.h",
-  "!components/signin/core/browser/signin_manager_base.h",
+  "!components/signin/core/browser/primary_account_manager.h",
+  "!components/signin/core/browser/primary_account_policy_manager.h",
   "+content/public/browser",
   "+content/public/common",
   "+courgette",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 89ae12f..a39580c 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1582,7 +1582,7 @@
     defined(OS_CHROMEOS)
     {"translate-ui-bubble-options", flag_descriptions::kTranslateBubbleUIName,
      flag_descriptions::kTranslateBubbleUIDescription, kOsDesktop,
-     FEATURE_WITH_PARAMS_VALUE_TYPE(language::kUseButtonTranslateBubbleUI,
+     FEATURE_WITH_PARAMS_VALUE_TYPE(language::kUseButtonTranslateBubbleUi,
                                     kTranslateBubbleUIVariations,
                                     "UseButtonTranslateBubbleUI")},
 #endif  // OS_LINUX || OS_MACOSX || OS_WIN || OS_CHROMEOS
@@ -3908,6 +3908,9 @@
      flag_descriptions::kEnableAutofillCreditCardUploadFeedbackDescription,
      kOsWin | kOsMac | kOsLinux,
      FEATURE_VALUE_TYPE(autofill::features::kAutofillCreditCardUploadFeedback)},
+    {"periodic-background-sync", flag_descriptions::kPeriodicBackgroundSyncName,
+     flag_descriptions::kPeriodicBackgroundSyncDescription, kOsAll,
+     FEATURE_VALUE_TYPE(features::kPeriodicBackgroundSync)},
 
     // NOTE: Adding a new flag requires adding a corresponding entry to enum
     // "LoginCustomFlags" in tools/metrics/histograms/enums.xml. See "Flag
diff --git a/chrome/browser/about_flags_browsertest.cc b/chrome/browser/about_flags_browsertest.cc
index 29197cf..af136e218 100644
--- a/chrome/browser/about_flags_browsertest.cc
+++ b/chrome/browser/about_flags_browsertest.cc
@@ -60,7 +60,8 @@
 class AboutFlagsBrowserTest : public InProcessBrowserTest {};
 
 // Tests experiments with origin values in chrome://flags page.
-IN_PROC_BROWSER_TEST_F(AboutFlagsBrowserTest, OriginFlag) {
+// TODO(crbug.com/972121): renable the test when flakiness is resolved.
+IN_PROC_BROWSER_TEST_F(AboutFlagsBrowserTest, DISABLED_OriginFlag) {
   ui_test_utils::NavigateToURL(browser(), GURL("chrome://flags"));
 
   const base::CommandLine::SwitchMap switches =
diff --git a/chrome/browser/android/signin/signin_manager_android.cc b/chrome/browser/android/signin/signin_manager_android.cc
index 836d548..6ff3228f 100644
--- a/chrome/browser/android/signin/signin_manager_android.cc
+++ b/chrome/browser/android/signin/signin_manager_android.cc
@@ -155,8 +155,9 @@
 
   // TODO(crbug.com/889902): Migrate to IdentityManager once there's an
   // API mapping for SigninManager::SignIn().
-  IdentityManagerFactory::GetForProfile(profile_)->GetSigninManager()->SignIn(
-      base::android::ConvertJavaStringToUTF8(env, username));
+  IdentityManagerFactory::GetForProfile(profile_)
+      ->GetPrimaryAccountManager()
+      ->SignIn(base::android::ConvertJavaStringToUTF8(env, username));
 }
 
 void SigninManagerAndroid::SignOut(JNIEnv* env,
diff --git a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_apitest.cc b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_apitest.cc
index 0327d4a..238340e 100644
--- a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_apitest.cc
+++ b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_apitest.cc
@@ -4,7 +4,6 @@
 
 #include "base/macros.h"
 
-#include "ash/public/cpp/ash_switches.h"
 #include "build/build_config.h"
 #include "chrome/browser/chromeos/arc/arc_session_manager.h"
 #include "chrome/browser/chromeos/arc/arc_util.h"
@@ -29,8 +28,6 @@
     ExtensionApiTest::SetUpCommandLine(command_line);
     // Make ARC enabled for tests.
     arc::SetArcAvailableCommandLineForTesting(command_line);
-    // Enable certain Mojo services like ShelfIntegrationTestApi.
-    command_line->AppendSwitch(ash::switches::kAshEnableTestInterfaces);
   }
 
   void SetUpInProcessBrowserTestFixture() override {
diff --git a/chrome/browser/component_updater/cros_component_installer_chromeos.cc b/chrome/browser/component_updater/cros_component_installer_chromeos.cc
index fc1fd89a..f12a4b12 100644
--- a/chrome/browser/component_updater/cros_component_installer_chromeos.cc
+++ b/chrome/browser/component_updater/cros_component_installer_chromeos.cc
@@ -36,7 +36,7 @@
 const ComponentConfig kConfigs[] = {
     {"epson-inkjet-printer-escpr", "3.0",
      "1913a5e0a6cad30b6f03e176177e0d7ed62c5d6700a9c66da556d7c3f5d6a47e"},
-    {"cros-termina", "760.1",
+    {"cros-termina", "770.1",
      "e9d960f84f628e1f42d05de4046bb5b3154b6f1f65c08412c6af57a29aecaffb"},
     {"rtanalytics-light", "11.0",
      "69f09d33c439c2ab55bbbe24b47ab55cb3f6c0bd1f1ef46eefea3216ec925038"},
diff --git a/chrome/browser/crash_upload_list/crash_upload_list_crashpad.cc b/chrome/browser/crash_upload_list/crash_upload_list_crashpad.cc
index 52a4fa3..dc44b99d 100644
--- a/chrome/browser/crash_upload_list/crash_upload_list_crashpad.cc
+++ b/chrome/browser/crash_upload_list/crash_upload_list_crashpad.cc
@@ -41,11 +41,6 @@
 
 CrashUploadListCrashpad::~CrashUploadListCrashpad() = default;
 
-base::TaskTraits CrashUploadListCrashpad::LoadingTaskTraits() {
-  return {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
-          base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN};
-}
-
 std::vector<UploadList::UploadInfo> CrashUploadListCrashpad::LoadUploadList() {
   std::vector<crash_reporter::Report> reports;
   crash_reporter::GetReports(&reports);
diff --git a/chrome/browser/crash_upload_list/crash_upload_list_crashpad.h b/chrome/browser/crash_upload_list/crash_upload_list_crashpad.h
index f3b6d7a..4fc0c29b 100644
--- a/chrome/browser/crash_upload_list/crash_upload_list_crashpad.h
+++ b/chrome/browser/crash_upload_list/crash_upload_list_crashpad.h
@@ -21,7 +21,6 @@
  protected:
   ~CrashUploadListCrashpad() override;
 
-  base::TaskTraits LoadingTaskTraits() override;
   std::vector<UploadInfo> LoadUploadList() override;
   void ClearUploadList(const base::Time& begin, const base::Time& end) override;
   void RequestSingleUpload(const std::string& local_id) override;
diff --git a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc
index 8e7a0466..3a1ab10 100644
--- a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc
+++ b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc
@@ -172,7 +172,7 @@
   }
 
   // Derived classes can override this method to set the required authenticated
-  // user in the SigninManager class.
+  // user in the IdentityManager class.
   virtual void SetAuthenticatedUser() {
     identity::MakePrimaryAccountAvailable(
         IdentityManagerFactory::GetForProfile(browser()->profile()),
diff --git a/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc b/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc
index 599b76f..4ea68809 100644
--- a/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc
+++ b/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc
@@ -201,7 +201,7 @@
   }
 
   // Derived classes can override this method to set the required authenticated
-  // user in the SigninManager class.
+  // user in the IdentityManager class.
   virtual void SetAuthenticatedUser() {
     auto* identity_manager =
         IdentityManagerFactory::GetForProfile(browser()->profile());
diff --git a/chrome/browser/extensions/service_worker_apitest.cc b/chrome/browser/extensions/service_worker_apitest.cc
index 4b47ee65..8cfbf09 100644
--- a/chrome/browser/extensions/service_worker_apitest.cc
+++ b/chrome/browser/extensions/service_worker_apitest.cc
@@ -261,6 +261,19 @@
     return running_worker_id;
   }
 
+  bool ExtensionHasRenderProcessHost(const ExtensionId& extension_id) {
+    ProcessMap* process_map = ProcessMap::Get(browser()->profile());
+    content::RenderProcessHost::iterator it =
+        content::RenderProcessHost::AllHostsIterator();
+    while (!it.IsAtEnd()) {
+      if (process_map->Contains(extension_id, it.GetCurrentValue()->GetID())) {
+        return true;
+      }
+      it.Advance();
+    }
+    return false;
+  }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerBasedBackgroundTest);
 };
@@ -1629,66 +1642,6 @@
   ASSERT_TRUE(RunExtensionTest("service_worker/mime_handler_view"));
 }
 
-IN_PROC_BROWSER_TEST_F(ServiceWorkerLazyBackgroundTest,
-                       PRE_FilteredEventsAfterRestart) {
-  LazyBackgroundObserver lazy_observer;
-  ResultCatcher catcher;
-  const Extension* extension = LoadExtensionWithFlags(
-      test_data_dir_.AppendASCII(
-          "service_worker/filtered_events_after_restart"),
-      kFlagNone);
-  ASSERT_TRUE(extension);
-  EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
-
-  // |extension|'s background page opens a tab to its resource.
-  content::WebContents* extension_web_contents =
-      browser()->tab_strip_model()->GetActiveWebContents();
-  EXPECT_TRUE(content::WaitForLoadStop(extension_web_contents));
-  EXPECT_EQ(extension->GetResourceURL("page.html").spec(),
-            extension_web_contents->GetURL().spec());
-  {
-    // Let the service worker start and register a filtered listener to
-    // chrome.webNavigation.onCommitted event.
-    ExtensionTestMessageListener add_listener_done("listener-added", false);
-    add_listener_done.set_failure_message("FAILURE");
-    content::ExecuteScriptAsync(extension_web_contents,
-                                "window.runServiceWorkerAsync()");
-    EXPECT_TRUE(add_listener_done.WaitUntilSatisfied());
-
-    base::RunLoop run_loop;
-    content::StoragePartition* storage_partition =
-        content::BrowserContext::GetDefaultStoragePartition(
-            browser()->profile());
-    content::StopServiceWorkerForScope(
-        storage_partition->GetServiceWorkerContext(),
-        // The service worker is registered at the top level scope.
-        extension->url(), run_loop.QuitClosure());
-    run_loop.Run();
-  }
-
-  // Close the tab to |extension|'s resource. This will also close the
-  // extension's event page.
-  browser()->tab_strip_model()->CloseWebContentsAt(
-      browser()->tab_strip_model()->active_index(), TabStripModel::CLOSE_NONE);
-  lazy_observer.Wait();
-}
-
-IN_PROC_BROWSER_TEST_F(ServiceWorkerLazyBackgroundTest,
-                       FilteredEventsAfterRestart) {
-  // Create a tab to a.html, expect it to navigate to b.html. The service worker
-  // will see two webNavigation.onCommitted events.
-  ASSERT_TRUE(StartEmbeddedTestServer());
-  GURL page_url = embedded_test_server()->GetURL(
-      "/extensions/api_test/service_worker/filtered_events_after_restart/"
-      "a.html");
-  ExtensionTestMessageListener worker_filtered_event_listener(
-      "PASS_FROM_WORKER", false);
-  worker_filtered_event_listener.set_failure_message("FAIL_FROM_WORKER");
-  content::WebContents* web_contents = AddTab(browser(), page_url);
-  EXPECT_TRUE(web_contents);
-  EXPECT_TRUE(worker_filtered_event_listener.WaitUntilSatisfied());
-}
-
 IN_PROC_BROWSER_TEST_F(ServiceWorkerBasedBackgroundTest,
                        ProcessManagerRegistrationOnShutdown) {
   // Note that StopServiceWorkerForScope call below expects the worker to be
@@ -1774,15 +1727,7 @@
 // tabs.onMoved before browser restarted in PRE_EventsAfterRestart.
 IN_PROC_BROWSER_TEST_F(ServiceWorkerBasedBackgroundTest, EventsAfterRestart) {
   // Verify there is no RenderProcessHost for the extension.
-  ProcessMap* process_map = ProcessMap::Get(browser()->profile());
-  ASSERT_TRUE(process_map);
-  content::RenderProcessHost::iterator it =
-      content::RenderProcessHost::AllHostsIterator();
-  while (!it.IsAtEnd()) {
-    EXPECT_FALSE(
-        process_map->Contains(kTestExtensionId, it.GetCurrentValue()->GetID()));
-    it.Advance();
-  }
+  EXPECT_FALSE(ExtensionHasRenderProcessHost(kTestExtensionId));
 
   ExtensionTestMessageListener moved_tab_listener("moved-tab", false);
   // Add a tab, then move it.
@@ -1800,6 +1745,51 @@
       << message_;
 }
 
+IN_PROC_BROWSER_TEST_F(ServiceWorkerBasedBackgroundTest,
+                       PRE_FilteredEventsAfterRestart) {
+  ExtensionTestMessageListener listener_added("ready", false);
+  const Extension* extension = LoadExtensionWithFlags(
+      test_data_dir_.AppendASCII("service_worker/worker_based_background/"
+                                 "filtered_events_after_restart"),
+      kFlagNone);
+  ASSERT_TRUE(extension);
+  EXPECT_EQ(kTestExtensionId, extension->id());
+  ProcessManager* pm = ProcessManager::Get(browser()->profile());
+  // TODO(crbug.com/969884): This will break once keep alive counts
+  // for service workers are tracked by the Process Manager.
+  EXPECT_LT(pm->GetLazyKeepaliveCount(extension), 1);
+  EXPECT_TRUE(pm->GetLazyKeepaliveActivities(extension).empty());
+  EXPECT_TRUE(listener_added.WaitUntilSatisfied());
+}
+
+// After browser restarts, this test step ensures that opening a tab fires
+// tabs.onCreated event listener to the extension without explicitly loading the
+// extension. This is because the extension registered a listener for
+// tabs.onMoved before browser restarted in PRE_EventsAfterRestart.
+IN_PROC_BROWSER_TEST_F(ServiceWorkerBasedBackgroundTest,
+                       FilteredEventsAfterRestart) {
+  // Verify there is no RenderProcessHost for the extension.
+  // TODO(crbug.com/971309): This is currently broken because the test
+  // infrastructure opens a tab, which dispatches an event to our
+  // extension, even though the filter doesn't include that URL. The
+  // referenced bug is about moving filtering into the EventRouter so they
+  // get filtered before being dispatched.
+  EXPECT_TRUE(ExtensionHasRenderProcessHost(kTestExtensionId));
+
+  // Create a tab to a.html, expect it to navigate to b.html. The service worker
+  // will see two webNavigation.onCommitted events.
+  GURL page_url = embedded_test_server()->GetURL(
+      "/extensions/api_test/service_worker/worker_based_background/"
+      "filtered_events_after_restart/"
+      "a.html");
+  ExtensionTestMessageListener worker_filtered_event_listener(
+      "PASS_FROM_WORKER", false);
+  worker_filtered_event_listener.set_failure_message("FAIL_FROM_WORKER");
+  content::WebContents* web_contents = AddTab(browser(), page_url);
+  EXPECT_TRUE(web_contents);
+  EXPECT_TRUE(worker_filtered_event_listener.WaitUntilSatisfied());
+}
+
 // Tests that console messages logged by extension service workers, both via
 // the typical console.* methods and via our custom bindings console, are
 // passed through the normal ServiceWorker console messaging and are
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index bc30092e..87aab73 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -2663,6 +2663,11 @@
     "expiry_milestone": 78
   },
   {
+    "name": "periodic-background-sync",
+    "owners": [ "nator" ],
+    "expiry_milestone": 80
+  },
+  {
     "name": "postscript-printing",
     "owners": [ "//printing/OWNERS" ],
     "expiry_milestone": 76
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index b965cb44..a0d4bfcf 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -1489,6 +1489,10 @@
     "Performs a one-off irreversible migration of passwords from the "
     "gnome-keyring or kwallet into the profile directory.";
 
+const char kPeriodicBackgroundSyncName[] = "Periodic Background Sync";
+const char kPeriodicBackgroundSyncDescription[] =
+    "If enabled, web apps can periodically sync content in the background.";
+
 const char kPerMethodCanMakePaymentQuotaName[] =
     "Per-method canMakePayment() quota.";
 const char kPerMethodCanMakePaymentQuotaDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 05445679..c0743d91 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -890,6 +890,9 @@
 extern const char kPasswordsMigrateLinuxToLoginDBName[];
 extern const char kPasswordsMigrateLinuxToLoginDBDescription[];
 
+extern const char kPeriodicBackgroundSyncName[];
+extern const char kPeriodicBackgroundSyncDescription[];
+
 extern const char kPerMethodCanMakePaymentQuotaName[];
 extern const char kPerMethodCanMakePaymentQuotaDescription[];
 
diff --git a/chrome/browser/net/errorpage_browsertest.cc b/chrome/browser/net/errorpage_browsertest.cc
index 4977414..158779b 100644
--- a/chrome/browser/net/errorpage_browsertest.cc
+++ b/chrome/browser/net/errorpage_browsertest.cc
@@ -324,6 +324,12 @@
                content::URLLoaderInterceptor::RequestParams* params) {
               // Add an interceptor that serves LinkDoctor responses
               if (google_util::LinkDoctorBaseURL() == params->url_request.url) {
+                // The origin header should exist and be opaque.
+                std::string origin;
+                bool has_origin = params->url_request.headers.GetHeader(
+                    net::HttpRequestHeaders::kOrigin, &origin);
+                EXPECT_TRUE(has_origin);
+                EXPECT_EQ(origin, "null");
                 // Send RequestCreated so that anyone blocking on
                 // WaitForRequests can continue.
                 base::PostTaskWithTraits(
diff --git a/chrome/browser/search/BUILD.gn b/chrome/browser/search/BUILD.gn
index f93d86e..338bfa8 100644
--- a/chrome/browser/search/BUILD.gn
+++ b/chrome/browser/search/BUILD.gn
@@ -2,8 +2,6 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//build/compiled_action.gni")
-
 local_ntp_resources = "//chrome/browser/resources/local_ntp"
 
 action("local_ntp_code_generate") {
@@ -40,30 +38,10 @@
   ]
 }
 
-executable("generate_colors_info") {
-  sources = [
-    "chrome_colors/generate_colors_info.cc",
-    "chrome_colors/selected_colors_info.h",
-  ]
-  deps = [
-    "//base",
-    "//skia",
-  ]
-}
-
-compiled_action("generate_chrome_colors_info") {
-  tool = ":generate_colors_info"
-  outputs = [
-    "$target_gen_dir/chrome_colors/generated_color_info.h",
-  ]
-  args = rebase_path(outputs, root_build_dir)
-}
-
 source_set("generated") {
   sources = get_target_outputs(":local_ntp_code_generate")
 
   public_deps = [
-    ":generate_chrome_colors_info",
     ":local_ntp_code_generate",
   ]
 }
diff --git a/chrome/browser/signin/chrome_signin_client.cc b/chrome/browser/signin/chrome_signin_client.cc
index 37a32295..934b784 100644
--- a/chrome/browser/signin/chrome_signin_client.cc
+++ b/chrome/browser/signin/chrome_signin_client.cc
@@ -198,10 +198,10 @@
       !keep_window_opened) {
     if (signout_source_metric ==
         signin_metrics::SIGNIN_PREF_CHANGED_DURING_SIGNIN) {
-      // SIGNIN_PREF_CHANGED_DURING_SIGNIN will be triggered when SigninManager
-      // is initialized before window opening, there is no need to close window.
-      // Call OnCloseBrowsersSuccess to continue sign out and show UserManager
-      // afterwards.
+      // SIGNIN_PREF_CHANGED_DURING_SIGNIN will be triggered when
+      // IdentityManager is initialized before window opening, there is no need
+      // to close window. Call OnCloseBrowsersSuccess to continue sign out and
+      // show UserManager afterwards.
       should_display_user_manager_ = false;  // Don't show UserManager twice.
       OnCloseBrowsersSuccess(signout_source_metric, profile_->GetPath());
     } else {
diff --git a/chrome/browser/signin/chrome_signin_client_unittest.cc b/chrome/browser/signin/chrome_signin_client_unittest.cc
index 82e050d..201e474 100644
--- a/chrome/browser/signin/chrome_signin_client_unittest.cc
+++ b/chrome/browser/signin/chrome_signin_client_unittest.cc
@@ -262,7 +262,7 @@
   CreateClient(profile.get());
   ASSERT_TRUE(signin_util::IsUserSignoutAllowedForProfile(profile.get()));
 
-  // Verify SigninManager gets callback indicating sign-out is always allowed.
+  // Verify IdentityManager gets callback indicating sign-out is always allowed.
   signin_metrics::SignoutDelete delete_metric =
       signin_metrics::SignoutDelete::IGNORE_METRIC;
   EXPECT_CALL(
@@ -288,7 +288,7 @@
   signin_util::SetUserSignoutAllowedForProfile(profile.get(), false);
   ASSERT_FALSE(signin_util::IsUserSignoutAllowedForProfile(profile.get()));
 
-  // Verify SigninManager gets callback indicating sign-out is disallowed iff
+  // Verify IdentityManager gets callback indicating sign-out is disallowed iff
   // the source of the sign-out is a user-action.
   SigninClient::SignoutDecision signout_decision =
       IsSignoutDisallowedByPolicy(signout_source)
diff --git a/chrome/browser/signin/identity_manager_factory.cc b/chrome/browser/signin/identity_manager_factory.cc
index 9942d0a..98c576a 100644
--- a/chrome/browser/signin/identity_manager_factory.cc
+++ b/chrome/browser/signin/identity_manager_factory.cc
@@ -18,7 +18,7 @@
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/signin/core/browser/gaia_cookie_manager_service.h"
 #include "components/signin/core/browser/identity_manager_wrapper.h"
-#include "components/signin/core/browser/signin_manager.h"
+#include "components/signin/core/browser/primary_account_policy_manager.h"
 #include "services/identity/public/cpp/accounts_cookie_mutator.h"
 #include "services/identity/public/cpp/accounts_cookie_mutator_impl.h"
 #include "services/identity/public/cpp/accounts_mutator.h"
@@ -44,10 +44,10 @@
 std::unique_ptr<identity::PrimaryAccountMutator> BuildPrimaryAccountMutator(
     Profile* profile,
     AccountTrackerService* account_tracker_service,
-    SigninManagerBase* signin_manager) {
+    PrimaryAccountManager* primary_account_manager) {
 #if !defined(OS_CHROMEOS)
   return std::make_unique<identity::PrimaryAccountMutatorImpl>(
-      account_tracker_service, signin_manager, profile->GetPrefs());
+      account_tracker_service, primary_account_manager, profile->GetPrefs());
 #else
   return nullptr;
 #endif
@@ -60,34 +60,34 @@
     Profile* profile,
     AccountTrackerService* account_tracker_service,
     ProfileOAuth2TokenService* token_service,
-    SigninManagerBase* signin_manager) {
+    PrimaryAccountManager* primary_account_manager) {
 #if !defined(OS_ANDROID)
   return std::make_unique<identity::AccountsMutatorImpl>(
-      token_service, account_tracker_service, signin_manager,
+      token_service, account_tracker_service, primary_account_manager,
       profile->GetPrefs());
 #else
   return nullptr;
 #endif
 }
 
-std::unique_ptr<SigninManagerBase> BuildSigninManager(
+std::unique_ptr<PrimaryAccountManager> BuildPrimaryAccountManager(
     Profile* profile,
     AccountTrackerService* account_tracker_service,
     ProfileOAuth2TokenService* token_service) {
-  std::unique_ptr<SigninManagerBase> signin_manager;
+  std::unique_ptr<PrimaryAccountManager> primary_account_manager;
   SigninClient* client =
       ChromeSigninClientFactory::GetInstance()->GetForProfile(profile);
 #if defined(OS_CHROMEOS)
-  signin_manager = std::make_unique<SigninManagerBase>(
+  primary_account_manager = std::make_unique<PrimaryAccountManager>(
       client, token_service, account_tracker_service,
       AccountConsistencyModeManager::GetMethodForProfile(profile));
 #else
-  signin_manager = std::make_unique<SigninManager>(
+  primary_account_manager = std::make_unique<PrimaryAccountPolicyManager>(
       client, token_service, account_tracker_service,
       AccountConsistencyModeManager::GetMethodForProfile(profile));
 #endif
-  signin_manager->Initialize(g_browser_process->local_state());
-  return signin_manager;
+  primary_account_manager->Initialize(g_browser_process->local_state());
+  return primary_account_manager;
 }
 
 std::unique_ptr<AccountTrackerService> BuildAccountTrackerService(
@@ -179,16 +179,17 @@
   auto gaia_cookie_manager_service = std::make_unique<GaiaCookieManagerService>(
       token_service.get(), ChromeSigninClientFactory::GetForProfile(profile));
 
-  std::unique_ptr<SigninManagerBase> signin_manager = BuildSigninManager(
-      profile, account_tracker_service.get(), token_service.get());
+  std::unique_ptr<PrimaryAccountManager> primary_account_manager =
+      BuildPrimaryAccountManager(profile, account_tracker_service.get(),
+                                 token_service.get());
 
   std::unique_ptr<identity::PrimaryAccountMutator> primary_account_mutator =
       BuildPrimaryAccountMutator(profile, account_tracker_service.get(),
-                                 signin_manager.get());
+                                 primary_account_manager.get());
 
   std::unique_ptr<identity::AccountsMutator> accounts_mutator =
       BuildAccountsMutator(profile, account_tracker_service.get(),
-                           token_service.get(), signin_manager.get());
+                           token_service.get(), primary_account_manager.get());
 
   auto accounts_cookie_mutator =
       std::make_unique<identity::AccountsCookieMutatorImpl>(
@@ -205,10 +206,10 @@
 
   auto identity_manager = std::make_unique<IdentityManagerWrapper>(
       std::move(account_tracker_service), std::move(token_service),
-      std::move(gaia_cookie_manager_service), std::move(signin_manager),
-      std::move(account_fetcher_service), std::move(primary_account_mutator),
-      std::move(accounts_mutator), std::move(accounts_cookie_mutator),
-      std::move(diagnostics_provider));
+      std::move(gaia_cookie_manager_service),
+      std::move(primary_account_manager), std::move(account_fetcher_service),
+      std::move(primary_account_mutator), std::move(accounts_mutator),
+      std::move(accounts_cookie_mutator), std::move(diagnostics_provider));
 
   for (Observer& observer : observer_list_)
     observer.IdentityManagerCreated(identity_manager.get());
diff --git a/chrome/browser/signin/signin_ui_util.cc b/chrome/browser/signin/signin_ui_util.cc
index 7785e87..831c5a5b 100644
--- a/chrome/browser/signin/signin_ui_util.cc
+++ b/chrome/browser/signin/signin_ui_util.cc
@@ -64,8 +64,8 @@
 
 #if defined(OS_CHROMEOS)
     if (user_manager::UserManager::IsInitialized()) {
-      // On CrOS user email is sanitized and then passed to the signin manager.
-      // Original email (containing dots) is stored as "display email".
+      // On CrOS user email is sanitized and then passed to the identity
+      // manager. Original email (containing dots) is stored as "display email".
       user_display_name = user_manager::UserManager::Get()->GetUserDisplayEmail(
           AccountId::FromUserEmail(user_display_name));
     }
diff --git a/chrome/browser/ssl/ssl_config_service_manager_pref_unittest.cc b/chrome/browser/ssl/ssl_config_service_manager_pref_unittest.cc
index 0c0b959..f4b614fdc 100644
--- a/chrome/browser/ssl/ssl_config_service_manager_pref_unittest.cc
+++ b/chrome/browser/ssl/ssl_config_service_manager_pref_unittest.cc
@@ -7,8 +7,8 @@
 
 #include "base/command_line.h"
 #include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
 #include "base/values.h"
 #include "chrome/browser/ssl/ssl_config_service_manager.h"
 #include "chrome/common/chrome_switches.h"
@@ -85,7 +85,7 @@
   }
 
  protected:
-  base::MessageLoop message_loop_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
 
   TestingPrefServiceSimple local_state_;
 
diff --git a/chrome/browser/supervised_user/child_accounts/family_info_fetcher_unittest.cc b/chrome/browser/supervised_user/child_accounts/family_info_fetcher_unittest.cc
index 154bc48..e7f0d7e2 100644
--- a/chrome/browser/supervised_user/child_accounts/family_info_fetcher_unittest.cc
+++ b/chrome/browser/supervised_user/child_accounts/family_info_fetcher_unittest.cc
@@ -12,8 +12,8 @@
 #include <vector>
 
 #include "base/json/json_writer.h"
-#include "base/message_loop/message_loop.h"
 #include "base/test/mock_callback.h"
+#include "base/test/scoped_task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/values.h"
 #include "net/base/net_errors.h"
@@ -176,7 +176,7 @@
     SendResponse(net::ERR_ABORTED, std::string());
   }
 
-  base::MessageLoop message_loop_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
   identity::IdentityTestEnvironment identity_test_env_;
   network::TestURLLoaderFactory test_url_loader_factory_;
   std::unique_ptr<FamilyInfoFetcher> fetcher_;
diff --git a/chrome/browser/supervised_user/child_accounts/permission_request_creator_apiary_unittest.cc b/chrome/browser/supervised_user/child_accounts/permission_request_creator_apiary_unittest.cc
index 1435ff0..0bb284bd 100644
--- a/chrome/browser/supervised_user/child_accounts/permission_request_creator_apiary_unittest.cc
+++ b/chrome/browser/supervised_user/child_accounts/permission_request_creator_apiary_unittest.cc
@@ -9,7 +9,7 @@
 
 #include "base/bind.h"
 #include "base/json/json_writer.h"
-#include "base/message_loop/message_loop.h"
+#include "base/test/scoped_task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/values.h"
 #include "net/base/net_errors.h"
@@ -85,7 +85,7 @@
 
   MOCK_METHOD1(OnRequestCreated, void(bool success));
 
-  base::MessageLoop message_loop_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
   std::string account_id_;
   identity::IdentityTestEnvironment identity_test_env_;
   network::TestURLLoaderFactory test_url_loader_factory_;
diff --git a/chrome/browser/supervised_user/kids_management_url_checker_client_unittest.cc b/chrome/browser/supervised_user/kids_management_url_checker_client_unittest.cc
index c6c658b..17ca4bb 100644
--- a/chrome/browser/supervised_user/kids_management_url_checker_client_unittest.cc
+++ b/chrome/browser/supervised_user/kids_management_url_checker_client_unittest.cc
@@ -9,8 +9,8 @@
 
 #include "base/bind.h"
 #include "base/json/json_writer.h"
-#include "base/message_loop/message_loop.h"
 #include "base/test/scoped_feature_list.h"
+#include "base/test/scoped_task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/values.h"
 #include "net/http/http_status_code.h"
@@ -108,7 +108,7 @@
                void(const GURL& url,
                     safe_search_api::ClientClassification classification));
 
-  base::MessageLoop message_loop_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
   std::string account_id_;
   identity::IdentityTestEnvironment identity_test_env_;
   network::TestURLLoaderFactory test_url_loader_factory_;
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index a75c2bd..e518a16 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -3900,6 +3900,8 @@
 
   if (is_chromeos) {
     sources += [
+      "ash/ash_test_util.cc",
+      "ash/ash_test_util.h",
       "ash/fake_tablet_mode_controller.cc",
       "ash/fake_tablet_mode_controller.h",
       "ash/test_login_screen.cc",
diff --git a/chrome/browser/ui/ash/ash_test_util.cc b/chrome/browser/ui/ash/ash_test_util.cc
new file mode 100644
index 0000000..2be6d2b
--- /dev/null
+++ b/chrome/browser/ui/ash/ash_test_util.cc
@@ -0,0 +1,78 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/ash/ash_test_util.h"
+
+#include "ash/public/cpp/window_properties.h"
+#include "ash/public/cpp/window_state_type.h"
+#include "base/run_loop.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_observer.h"
+#include "ui/base/test/ui_controls.h"
+#include "ui/wm/core/window_util.h"
+
+namespace test {
+namespace {
+// Wait until the window's state changes to given the snapped state.
+// The window should stay alive, so no need to observer destroying.
+class SnapWaiter : public aura::WindowObserver {
+ public:
+  SnapWaiter(aura::Window* window, ash::WindowStateType type)
+      : window_(window), type_(type) {
+    window->AddObserver(this);
+  }
+  ~SnapWaiter() override { window_->RemoveObserver(this); }
+
+  // aura::WindowObserver:
+  void OnWindowPropertyChanged(aura::Window* window,
+                               const void* key,
+                               intptr_t old) override {
+    if (key == ash::kWindowStateTypeKey && IsSnapped())
+      run_loop_.Quit();
+  }
+
+  void Wait() { run_loop_.Run(); }
+
+  bool IsSnapped() const {
+    return window_->GetProperty(ash::kWindowStateTypeKey) == type_;
+  }
+
+ private:
+  aura::Window* window_;
+  ash::WindowStateType type_;
+  base::RunLoop run_loop_;
+
+  DISALLOW_COPY_AND_ASSIGN(SnapWaiter);
+};
+
+}  // namespace
+
+void ActivateAndSnapWindow(aura::Window* window, ash::WindowStateType type) {
+  DCHECK(window);
+  if (!wm::IsActiveWindow(window))
+    wm::ActivateWindow(window);
+
+  ASSERT_TRUE(wm::IsActiveWindow(window));
+
+  SnapWaiter snap_waiter(window, type);
+  ASSERT_TRUE(type == ash::WindowStateType::kRightSnapped ||
+              type == ash::WindowStateType::kLeftSnapped);
+
+  // Early return if it's already snapped.
+  if (snap_waiter.IsSnapped())
+    return;
+
+  ui_controls::SendKeyPress(window,
+                            type == ash::WindowStateType::kLeftSnapped
+                                ? ui::VKEY_OEM_4
+                                : ui::VKEY_OEM_6,
+                            /*control=*/false,
+                            /*shift=*/false,
+                            /*alt=*/true,
+                            /*command=*/false);
+  snap_waiter.Wait();
+}
+
+}  // namespace test
diff --git a/chrome/browser/ui/ash/ash_test_util.h b/chrome/browser/ui/ash/ash_test_util.h
new file mode 100644
index 0000000..7fd082b6
--- /dev/null
+++ b/chrome/browser/ui/ash/ash_test_util.h
@@ -0,0 +1,23 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_ASH_ASH_TEST_UTIL_H_
+#define CHROME_BROWSER_UI_ASH_ASH_TEST_UTIL_H_
+
+namespace aura {
+class Window;
+}
+
+namespace ash {
+enum class WindowStateType;
+}
+
+namespace test {
+
+// The snap window. This will activate the |window|.
+void ActivateAndSnapWindow(aura::Window* window, ash::WindowStateType type);
+
+}  // namespace test
+
+#endif  // CHROME_BROWSER_UI_ASH_ASH_TEST_UTIL_H_
diff --git a/chrome/browser/ui/ash/split_view_interactive_uitest.cc b/chrome/browser/ui/ash/split_view_interactive_uitest.cc
index f52e9c40..f29aa3e 100644
--- a/chrome/browser/ui/ash/split_view_interactive_uitest.cc
+++ b/chrome/browser/ui/ash/split_view_interactive_uitest.cc
@@ -2,157 +2,168 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ash/public/cpp/ash_switches.h"
 #include "ash/public/cpp/test/shell_test_api.h"
-#include "ash/shell.h"
-#include "ash/wm/splitview/split_view_controller.h"
+#include "ash/public/cpp/window_state_type.h"
+#include "base/command_line.h"
 #include "base/macros.h"
 #include "base/run_loop.h"
 #include "base/system/sys_info.h"
 #include "base/task/post_task.h"
 #include "base/test/bind_test_util.h"
+#include "chrome/browser/ui/ash/ash_test_util.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/common/webui_url_constants.h"
 #include "chrome/test/base/interactive_test_utils.h"
+#include "chrome/test/base/perf/drag_event_generator.h"
 #include "chrome/test/base/perf/performance_test.h"
 #include "ui/aura/window.h"
-#include "ui/aura/window_tree_host.h"
 #include "ui/compositor/compositor.h"
-#include "ui/compositor/compositor_switches.h"
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
-#include "ui/gl/gl_switches.h"
-#include "ui/views/widget/widget.h"
-#include "ui/views/widget/widget_observer.h"
+#include "ui/wm/core/wm_core_switches.h"
 
 namespace {
 
-class SplitViewTest : public UIPerformanceTest {
+class SplitViewTest
+    : public UIPerformanceTest,
+      public testing::WithParamInterface<::testing::tuple<bool, bool>> {
  public:
   SplitViewTest() = default;
   ~SplitViewTest() override = default;
 
   // UIPerformanceTest:
   void SetUpCommandLine(base::CommandLine* command_line) override {
-    command_line->AppendSwitch(ash::switches::kAshEnableTabletMode);
+    // We're not interested in window transition animation in this test,
+    // so just disable it.
+    command_line->AppendSwitch(wm::switches::kWindowAnimationsDisabled);
+  }
+  void SetUpOnMainThread() override {
+    UIPerformanceTest::SetUpOnMainThread();
+
+    use_ntp_ = std::get<0>(GetParam());
+    use_touch_ = std::get<1>(GetParam());
+
+    if (use_ntp_)
+      ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL));
+  }
+
+  bool use_touch() const { return use_touch_; }
+
+  void SetUMAToObserve(std::string name) { uma_name_ = std::move(name); }
+
+  Browser* CreateBrowserMaybeWithNtp() {
+    Browser* new_browser = CreateBrowser(browser()->profile());
+    if (use_ntp_)
+      ui_test_utils::NavigateToURL(new_browser,
+                                   GURL(chrome::kChromeUINewTabURL));
+    return new_browser;
+  }
+
+  void WaitForWarmup() {
+    // If running on device, wait a bit so that the display is actually powered
+    // on.
+    // TODO: this should be better factored.
+    base::TimeDelta warmup = base::TimeDelta::FromSeconds(
+        base::SysInfo::IsRunningOnChromeOS() ? 5 : 0);
+    // Give ntp at least 1 seconds to be fully resized.
+    if (use_ntp_ && warmup.is_zero())
+      warmup += base::TimeDelta::FromSeconds(1);
+
+    if (!warmup.is_zero()) {
+      base::RunLoop run_loop;
+      base::PostDelayedTask(FROM_HERE, run_loop.QuitClosure(), warmup);
+      run_loop.Run();
+    }
   }
 
  private:
   std::vector<std::string> GetUMAHistogramNames() const override {
-    return {"Ash.SplitViewResize.PresentationTime.TabletMode.MultiWindow"};
+    return {uma_name_};
   }
 
+  bool use_ntp_;
+  bool use_touch_;
+  std::string uma_name_;
+
   DISALLOW_COPY_AND_ASSIGN(SplitViewTest);
 };
 
-// Used to wait for a window resize to show up on screen.
-class WidgetResizeWaiter : public views::WidgetObserver {
- public:
-  explicit WidgetResizeWaiter(views::Widget* widget) : widget_(widget) {
-    widget_->AddObserver(this);
-  }
+IN_PROC_BROWSER_TEST_P(SplitViewTest, ResizeTwoWindows) {
+  SetUMAToObserve(
+      "Ash.SplitViewResize.PresentationTime.TabletMode.MultiWindow");
 
-  ~WidgetResizeWaiter() override {
-    widget_->RemoveObserver(this);
-    EXPECT_FALSE(waiting_for_frame_);
-  }
-
-  void WaitForDisplay() {
-    do {
-      if (waiting_for_frame_) {
-        run_loop_ = std::make_unique<base::RunLoop>();
-        run_loop_->Run();
-        EXPECT_FALSE(waiting_for_frame_);
-      }
-      ash::ShellTestApi().WaitForNoPointerHoldLock();
-    } while (waiting_for_frame_);
-  }
-
- private:
-  void OnFramePresented(const gfx::PresentationFeedback& feedback) {
-    waiting_for_frame_ = false;
-    if (run_loop_)
-      run_loop_->Quit();
-  }
-
-  // views::WidgetObserver:
-  void OnWidgetBoundsChanged(views::Widget* widget,
-                             const gfx::Rect& new_bounds) override {
-    ui::Compositor* compositor =
-        widget->GetNativeWindow()->GetHost()->compositor();
-    ASSERT_TRUE(compositor);
-    waiting_for_frame_ = true;
-    compositor->RequestPresentationTimeForNextFrame(base::BindOnce(
-        &WidgetResizeWaiter::OnFramePresented, base::Unretained(this)));
-  }
-
-  views::Widget* widget_;
-  bool waiting_for_frame_ = false;
-  std::unique_ptr<base::RunLoop> run_loop_;
-
-  DISALLOW_COPY_AND_ASSIGN(WidgetResizeWaiter);
-};
-
-IN_PROC_BROWSER_TEST_F(SplitViewTest, SplitViewResize) {
   // This test is intended to gauge performance of resizing windows while in
   // tablet mode split view. It does the following:
   // . creates two browser windows.
-  // . enters tablet mode.
   // . snaps one to the left, one to the right.
+  // . enters tablet mode.
   // . drags the resizer, which triggers resizing both browsers.
-  browser()->window()->Maximize();
 
-  Browser* browser2 = CreateBrowser(browser()->profile());
-  browser2->window()->Show();
-  browser2->window()->Maximize();
+  aura::Window* browser_window = browser()->window()->GetNativeWindow();
+  test::ActivateAndSnapWindow(browser_window,
+                              ash::WindowStateType::kLeftSnapped);
 
-  // If running on device, wait a bit so that the display is actually powered
-  // on.
-  // TODO: this should be better factored.
-  if (base::SysInfo::IsRunningOnChromeOS()) {
-    base::RunLoop run_loop;
-    base::PostDelayedTask(FROM_HERE, run_loop.QuitClosure(),
-                          base::TimeDelta::FromSeconds(5));
-    run_loop.Run();
-  }
-
+  Browser* browser2 = CreateBrowserMaybeWithNtp();
+  aura::Window* browser2_window = browser2->window()->GetNativeWindow();
+  test::ActivateAndSnapWindow(browser2_window,
+                              ash::WindowStateType::kRightSnapped);
   ash::ShellTestApi().EnableTabletModeWindowManager(true);
 
-  views::Widget* browser_widget =
-      BrowserView::GetBrowserViewForBrowser(browser())->GetWidget();
-  views::Widget* browser2_widget =
-      BrowserView::GetBrowserViewForBrowser(browser2)->GetWidget();
-  ash::Shell* shell = ash::Shell::Get();
-  shell->split_view_controller()->SnapWindow(browser2_widget->GetNativeWindow(),
-                                             ash::SplitViewController::LEFT);
-  shell->split_view_controller()->SnapWindow(browser_widget->GetNativeWindow(),
-                                             ash::SplitViewController::RIGHT);
-
-  ash::ShellTestApi().WaitForNoPointerHoldLock();
+  WaitForWarmup();
 
   const gfx::Size display_size =
       display::Screen::GetScreen()->GetPrimaryDisplay().bounds().size();
-  const gfx::Point start_position(display_size.width() / 2,
-                                  display_size.height() / 2);
+  const gfx::Point start_position(gfx::Rect(display_size).CenterPoint());
   TRACE_EVENT_ASYNC_BEGIN0("ui", "Interaction.ui_WindowResize", this);
-  ASSERT_TRUE(
-      ui_test_utils::SendMouseMoveSync(
-          gfx::Point(start_position.x(), start_position.y())) &&
-      ui_test_utils::SendMouseEventsSync(ui_controls::LEFT, ui_controls::DOWN));
-
-  constexpr int kNumIncrements = 20;
-  int width = browser_widget->GetWindowBoundsInScreen().width();
-  for (int i = 0; i < kNumIncrements; ++i) {
-    const gfx::Point resize_point(start_position.x() - i - 1,
-                                  start_position.y());
-    WidgetResizeWaiter observer(browser_widget);
-    ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(resize_point));
-    observer.WaitForDisplay();
-    ++width;
-    EXPECT_EQ(width, browser_widget->GetWindowBoundsInScreen().width());
-  }
+  gfx::Point end_position(start_position);
+  end_position.set_x(end_position.x() - 60);
+  ui_test_utils::DragEventGenerator generator(
+      std::make_unique<ui_test_utils::InterpolatedProducer>(
+          start_position, end_position,
+          base::TimeDelta::FromMilliseconds(1000)),
+      use_touch());
+  generator.Wait();
   TRACE_EVENT_ASYNC_END0("ui", "Interaction.ui_WindowResize", this);
+
+  ash::ShellTestApi().EnableTabletModeWindowManager(false);
 }
 
+IN_PROC_BROWSER_TEST_P(SplitViewTest, ResizeWithOverview) {
+  SetUMAToObserve(
+      "Ash.SplitViewResize.PresentationTime.TabletMode.WithOverview");
+
+  Browser* browser2 = CreateBrowserMaybeWithNtp();
+
+  aura::Window* browser2_window = browser2->window()->GetNativeWindow();
+  test::ActivateAndSnapWindow(browser2_window,
+                              ash::WindowStateType::kRightSnapped);
+
+  ash::ShellTestApi().EnableTabletModeWindowManager(true);
+  ash::ShellTestApi().WaitForOverviewAnimationState(
+      ash::OverviewAnimationState::kEnterAnimationComplete);
+
+  WaitForWarmup();
+
+  const gfx::Point start_position =
+      display::Screen::GetScreen()->GetPrimaryDisplay().bounds().CenterPoint();
+  TRACE_EVENT_ASYNC_BEGIN0("ui", "Interaction.ui_WindowResize", this);
+  gfx::Point end_position(start_position);
+  end_position.set_x(end_position.x() - 60);
+  ui_test_utils::DragEventGenerator generator(
+      std::make_unique<ui_test_utils::InterpolatedProducer>(
+          start_position, end_position,
+          base::TimeDelta::FromMilliseconds(1000)),
+      use_touch());
+  generator.Wait();
+  TRACE_EVENT_ASYNC_END0("ui", "Interaction.ui_WindowResize", this);
+
+  ash::ShellTestApi().EnableTabletModeWindowManager(false);
+}
+
+INSTANTIATE_TEST_SUITE_P(,
+                         SplitViewTest,
+                         ::testing::Combine(/*ntp=*/testing::Bool(),
+                                            /*touch=*/testing::Bool()));
+
 }  // namespace
diff --git a/chrome/browser/ui/ash/window_resize_interactive_uitest.cc b/chrome/browser/ui/ash/window_resize_interactive_uitest.cc
index 46cebb5..9696aff 100644
--- a/chrome/browser/ui/ash/window_resize_interactive_uitest.cc
+++ b/chrome/browser/ui/ash/window_resize_interactive_uitest.cc
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ash/public/cpp/window_properties.h"
 #include "ash/public/cpp/window_state_type.h"
 #include "base/command_line.h"
 #include "base/macros.h"
 #include "base/run_loop.h"
 #include "base/task/post_task.h"
+#include "chrome/browser/ui/ash/ash_test_util.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/test/base/interactive_test_utils.h"
@@ -107,41 +107,6 @@
   DISALLOW_COPY_AND_ASSIGN(MultiPointProducer);
 };
 
-// Wait until the window's state changed to given snapped state.
-// The window should stay alive, so no need to observer destroying.
-class SnapWaiter : public aura::WindowObserver {
- public:
-  SnapWaiter(aura::Window* window, ash::WindowStateType type)
-      : window_(window), type_(type) {
-    window->AddObserver(this);
-  }
-  ~SnapWaiter() override { window_->RemoveObserver(this); }
-
-  // aura::WindowObserver:
-  void OnWindowPropertyChanged(aura::Window* window,
-                               const void* key,
-                               intptr_t old) override {
-    if (key == ash::kWindowStateTypeKey && IsSnapped())
-      run_loop_.Quit();
-  }
-
-  void Wait() {
-    if (!IsSnapped())
-      run_loop_.Run();
-  }
-
- private:
-  bool IsSnapped() const {
-    return window_->GetProperty(ash::kWindowStateTypeKey) == type_;
-  }
-
-  aura::Window* window_;
-  ash::WindowStateType type_;
-  base::RunLoop run_loop_;
-
-  DISALLOW_COPY_AND_ASSIGN(SnapWaiter);
-};
-
 }  // namespace
 
 // Test window resize performance in clamshell mode.
@@ -191,13 +156,8 @@
 
 IN_PROC_BROWSER_TEST_P(WindowResizeTest, Single) {
   aura::Window* browser_window = browser()->window()->GetNativeWindow();
-  SnapWaiter snap_waiter(browser_window, ash::WindowStateType::kLeftSnapped);
-  ui_controls::SendKeyPress(browser_window, ui::VKEY_OEM_4,
-                            /*control=*/false,
-                            /*shift=*/false,
-                            /*alt=*/true,
-                            /*command=*/false);
-  snap_waiter.Wait();
+  test::ActivateAndSnapWindow(browser_window,
+                              ash::WindowStateType::kLeftSnapped);
 
   gfx::Rect bounds = browser_window->GetBoundsInScreen();
   gfx::Point start_point = gfx::Point(bounds.right_center());
@@ -221,15 +181,8 @@
 
 IN_PROC_BROWSER_TEST_P(WindowResizeTest, Multi) {
   aura::Window* browser_window = browser()->window()->GetNativeWindow();
-  {
-    SnapWaiter snap_waiter(browser_window, ash::WindowStateType::kLeftSnapped);
-    ui_controls::SendKeyPress(browser_window, ui::VKEY_OEM_4,
-                              /*control=*/false,
-                              /*shift=*/false,
-                              /*alt=*/true,
-                              /*command=*/false);
-    snap_waiter.Wait();
-  }
+  test::ActivateAndSnapWindow(browser_window,
+                              ash::WindowStateType::kLeftSnapped);
 
   Browser* browser2 = CreateBrowser(browser()->profile());
   if (use_ntp()) {
@@ -237,18 +190,10 @@
     ui_test_utils::NavigateToURL(browser2, ntp_url);
   }
 
+  aura::Window* browser_window2 = browser2->window()->GetNativeWindow();
   // Snap Right
-  {
-    aura::Window* browser_window2 = browser2->window()->GetNativeWindow();
-    SnapWaiter snap_waiter(browser_window2,
-                           ash::WindowStateType::kRightSnapped);
-    ui_controls::SendKeyPress(browser_window2, ui::VKEY_OEM_6,
-                              /*control=*/false,
-                              /*shift=*/false,
-                              /*alt=*/true,
-                              /*command=*/false);
-    snap_waiter.Wait();
-  }
+  test::ActivateAndSnapWindow(browser_window2,
+                              ash::WindowStateType::kRightSnapped);
 
   gfx::Rect bounds = browser_window->GetBoundsInScreen();
   gfx::Point start_point = gfx::Point(bounds.right_center());
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc
index 38ac6e4..66a5381 100644
--- a/chrome/browser/ui/browser.cc
+++ b/chrome/browser/ui/browser.cc
@@ -103,6 +103,8 @@
 #include "chrome/browser/ui/bluetooth/bluetooth_chooser_desktop.h"
 #include "chrome/browser/ui/bluetooth/bluetooth_scanning_prompt_controller.h"
 #include "chrome/browser/ui/bluetooth/bluetooth_scanning_prompt_desktop.h"
+#include "chrome/browser/ui/bookmarks/bookmark_tab_helper.h"
+#include "chrome/browser/ui/bookmarks/bookmark_utils.h"
 #include "chrome/browser/ui/browser_command_controller.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_content_setting_bubble_model_delegate.h"
@@ -146,6 +148,7 @@
 #include "chrome/browser/ui/tabs/tab_menu_model.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/tabs/tab_utils.h"
+#include "chrome/browser/ui/ui_features.h"
 #include "chrome/browser/ui/web_applications/app_browser_controller.h"
 #include "chrome/browser/ui/webui/signin/login_ui_service.h"
 #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
@@ -220,8 +223,6 @@
 #include "ui/base/window_open_disposition.h"
 #include "ui/gfx/geometry/point.h"
 #include "ui/shell_dialogs/selected_file_info.h"
-#include "chrome/browser/ui/bookmarks/bookmark_tab_helper.h"
-#include "chrome/browser/ui/bookmarks/bookmark_utils.h"
 
 #if defined(OS_WIN)
 #include <shellapi.h>
@@ -1372,12 +1373,17 @@
     return nullptr;
   }
 
-  if (source &&
-      (nav_params.disposition == WindowOpenDisposition::NEW_FOREGROUND_TAB ||
-       nav_params.disposition == WindowOpenDisposition::NEW_BACKGROUND_TAB)) {
-    nav_params.group = tab_strip_model()->GetTabGroupForTab(
-        tab_strip_model()->GetIndexOfWebContents(source));
+  if (base::FeatureList::IsEnabled(features::kTabGroups)) {
+    if (source &&
+        (nav_params.disposition == WindowOpenDisposition::NEW_FOREGROUND_TAB ||
+         nav_params.disposition == WindowOpenDisposition::NEW_BACKGROUND_TAB)) {
+      const int source_index = tab_strip_model()->GetIndexOfWebContents(source);
+      nav_params.group = tab_strip_model()->GetTabGroupForTab(source_index);
+      if (!nav_params.group)
+        nav_params.group = tab_strip_model()->AddToNewGroup({source_index});
+    }
   }
+
   Navigate(&nav_params);
 
   if (is_popup && nav_params.navigated_or_inserted_contents) {
diff --git a/chrome/browser/ui/browser_browsertest.cc b/chrome/browser/ui/browser_browsertest.cc
index ed95d35..97629385 100644
--- a/chrome/browser/ui/browser_browsertest.cc
+++ b/chrome/browser/ui/browser_browsertest.cc
@@ -62,6 +62,7 @@
 #include "chrome/browser/ui/startup/startup_browser_creator_impl.h"
 #include "chrome/browser/ui/tabs/pinned_tab_codec.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/browser/ui/ui_features.h"
 #include "chrome/common/buildflags.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
@@ -809,14 +810,18 @@
 IN_PROC_BROWSER_TEST_F(BrowserTest, NewTabFromLinkOpensInGroup) {
   ASSERT_TRUE(embedded_test_server()->Start());
 
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(features::kTabGroups);
+
   // Add a grouped tab.
-  TabStripModel* model = browser()->tab_strip_model();
+  TabStripModel* const model = browser()->tab_strip_model();
   ui_test_utils::NavigateToURL(browser(),
                                embedded_test_server()->GetURL("/empty.html"));
-  model->AddToNewGroup({0});
+  const TabGroupId group_id = model->AddToNewGroup({0});
 
   // Open a new background tab.
-  WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents();
+  WebContents* const contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
   OpenURLFromTab(
       contents,
       OpenURLParams(embedded_test_server()->GetURL("/empty.html"), Referrer(),
@@ -824,8 +829,7 @@
                     ui::PAGE_TRANSITION_TYPED, false));
 
   // It should have inherited the tab group from the first tab.
-  EXPECT_EQ(browser()->tab_strip_model()->GetTabGroupForTab(0),
-            browser()->tab_strip_model()->GetTabGroupForTab(1));
+  EXPECT_EQ(group_id, browser()->tab_strip_model()->GetTabGroupForTab(1));
 }
 
 // BeforeUnloadAtQuitWithTwoWindows is a regression test for
diff --git a/chrome/browser/ui/browser_commands.cc b/chrome/browser/ui/browser_commands.cc
index 0838033..55e9bf8 100644
--- a/chrome/browser/ui/browser_commands.cc
+++ b/chrome/browser/ui/browser_commands.cc
@@ -635,8 +635,10 @@
   reopen_tab_iph->NewTabOpened();
 
   if (browser->is_type_tabbed()) {
-    AddTabAt(browser, GURL(), -1, true);
-    browser->tab_strip_model()->GetActiveWebContents()->RestoreFocus();
+    TabStripModel* const model = browser->tab_strip_model();
+    const auto group_id = model->GetTabGroupForTab(model->active_index());
+    AddTabAt(browser, GURL(), -1, true, group_id);
+    model->GetActiveWebContents()->RestoreFocus();
   } else {
     ScopedTabbedBrowserDisplayer displayer(browser->profile());
     Browser* b = displayer.browser();
diff --git a/chrome/browser/ui/search/local_ntp_js_browsertest.cc b/chrome/browser/ui/search/local_ntp_js_browsertest.cc
index b736d62..c29829a7 100644
--- a/chrome/browser/ui/search/local_ntp_js_browsertest.cc
+++ b/chrome/browser/ui/search/local_ntp_js_browsertest.cc
@@ -4,6 +4,7 @@
 
 #include <string>
 
+#include "build/build_config.h"
 #include "chrome/browser/search/search.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/search/instant_test_utils.h"
@@ -61,9 +62,17 @@
   EXPECT_TRUE(success);
 }
 
+// TODO(crbug.com/971853): renable the windows on Windows when flakiness is
+// resolved.
+#if defined(OS_WIN)
+#define MAYBE_CustomBackgroundsTests DISABLED_CustomBackgroundsTests
+#else
+#define MAYBE_CustomBackgroundsTests CustomBackgroundsTests
+#endif
+
 // This runs a bunch of pure JS-side tests for custom backgrounds, i.e. those
 // that don't require any interaction from the native side.
-IN_PROC_BROWSER_TEST_F(LocalNTPJavascriptTest, CustomBackgroundsTests) {
+IN_PROC_BROWSER_TEST_F(LocalNTPJavascriptTest, MAYBE_CustomBackgroundsTests) {
   content::WebContents* active_tab = local_ntp_test_utils::OpenNewTab(
       browser(), GURL(chrome::kChromeUINewTabURL));
   ASSERT_TRUE(search::IsInstantNTP(active_tab));
diff --git a/chrome/browser/ui/translate/translate_bubble_model.h b/chrome/browser/ui/translate/translate_bubble_model.h
index b58c821..c4130e6 100644
--- a/chrome/browser/ui/translate/translate_bubble_model.h
+++ b/chrome/browser/ui/translate/translate_bubble_model.h
@@ -30,6 +30,16 @@
     // The view state when the detailed settings is shown. This view appears
     // when the user click a link 'Advanced' on other views.
     VIEW_STATE_ADVANCED,
+    // The view state for TAB ui when the source language combobox is shown.
+    // This view appears when the user selects "Page is not in {source
+    // language}"
+    // under option menu.
+    VIEW_STATE_SOURCE_LANGUAGE,
+
+    // The view state for TAB ui when the source language combobox is shown.
+    // This view appears when the user selects "More options..." under option
+    // menu.
+    VIEW_STATE_TARGET_LANGUAGE
   };
 
   virtual ~TranslateBubbleModel() {}
diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
index edb36212..5fcb6a2 100644
--- a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
+++ b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
@@ -131,6 +131,13 @@
       CreateCaptionButton(VIEW_ID_RESTORE_BUTTON, IDS_APP_ACCNAME_RESTORE);
   close_button_ =
       CreateCaptionButton(VIEW_ID_CLOSE_BUTTON, IDS_APP_ACCNAME_CLOSE);
+
+  // Because currently focus mode uses a vertically-expanded titlebar, there is
+  // no need to add extra space for a grab handle. However, traditional PWA and
+  // full browser mode require the extra space when the window is not maximized.
+  constexpr int kTopResizeFrameArea = 5;
+  drag_handle_padding_ =
+      browser_view->browser()->is_focus_mode() ? 0 : kTopResizeFrameArea;
 }
 
 GlassBrowserFrameView::~GlassBrowserFrameView() {
@@ -433,8 +440,7 @@
   // When maximized, the OS sizes the window such that the border extends beyond
   // the screen edges. In that case, we must return the default value.
   if ((!frame()->IsFullscreen() && !IsMaximized()) || restored) {
-    constexpr int kTopResizeFrameArea = 5;
-    return kTopResizeFrameArea;
+    return drag_handle_padding_;
   }
 
   // Mouse and touch locations are floored but GetSystemMetricsInDIP is rounded,
diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view.h b/chrome/browser/ui/views/frame/glass_browser_frame_view.h
index 0630c64..7ba19c7 100644
--- a/chrome/browser/ui/views/frame/glass_browser_frame_view.h
+++ b/chrome/browser/ui/views/frame/glass_browser_frame_view.h
@@ -168,6 +168,9 @@
   // The index of the current frame of the throbber animation.
   int throbber_frame_;
 
+  // How much extra space to reserve in non-maximized windows for a drag handle.
+  int drag_handle_padding_;
+
   static const int kThrobberIconCount = 24;
   static HICON throbber_icons_[kThrobberIconCount];
   static void InitThrobberIcons();
diff --git a/chrome/browser/ui/views/sync/inline_login_ui_browsertest.cc b/chrome/browser/ui/views/sync/inline_login_ui_browsertest.cc
index 5e6f5ee..ccc7cf6b 100644
--- a/chrome/browser/ui/views/sync/inline_login_ui_browsertest.cc
+++ b/chrome/browser/ui/views/sync/inline_login_ui_browsertest.cc
@@ -436,9 +436,6 @@
   }
 
   void OnWillCreateBrowserContextServices(content::BrowserContext* context) {
-    // Replace the signin manager and token service with fakes. Do this ahead of
-    // creating the browser so that a bunch of classes don't register as
-    // observers and end up needing to unregister when the fake is substituted.
     IdentityTestEnvironmentProfileAdaptor::
         SetIdentityTestEnvironmentFactoriesOnBrowserContext(context);
   }
diff --git a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
index b08af08..bbf75d11 100644
--- a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
+++ b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
@@ -325,7 +325,8 @@
       browser_view_->browser()->profile());
   reopen_tab_iph->NewTabOpened();
 
-  model_->delegate()->AddTabAt(GURL(), -1, true);
+  const auto group_id = model_->GetTabGroupForTab(model_->active_index());
+  model_->delegate()->AddTabAt(GURL(), -1, true, group_id);
 
 #if BUILDFLAG(ENABLE_LEGACY_DESKTOP_IN_PRODUCT_HELP)
   auto* new_tab_tracker =
diff --git a/chrome/browser/ui/views/translate/translate_bubble_view.cc b/chrome/browser/ui/views/translate/translate_bubble_view.cc
index c67c22c..0b310d5 100644
--- a/chrome/browser/ui/views/translate/translate_bubble_view.cc
+++ b/chrome/browser/ui/views/translate/translate_bubble_view.cc
@@ -9,7 +9,6 @@
 #include <string>
 #include <utility>
 #include <vector>
-
 #include "base/i18n/string_compare.h"
 #include "base/memory/singleton.h"
 #include "base/metrics/field_trial_params.h"
@@ -103,8 +102,12 @@
     // When the user reads the advanced setting panel, the bubble should not be
     // changed because they are focusing on the bubble.
     if (translate_bubble_view_->web_contents() == web_contents &&
-        translate_bubble_view_->model()->GetViewState() ==
-            TranslateBubbleModel::VIEW_STATE_ADVANCED) {
+        (translate_bubble_view_->model()->GetViewState() ==
+             TranslateBubbleModel::VIEW_STATE_ADVANCED ||
+         translate_bubble_view_->model()->GetViewState() ==
+             TranslateBubbleModel::VIEW_STATE_SOURCE_LANGUAGE ||
+         translate_bubble_view_->model()->GetViewState() ==
+             TranslateBubbleModel::VIEW_STATE_TARGET_LANGUAGE)) {
       return nullptr;
     }
     if (step != translate::TRANSLATE_STEP_TRANSLATE_ERROR) {
@@ -135,7 +138,10 @@
     view->SetHighlightedButton(highlighted_button);
   views::Widget* bubble_widget =
       views::BubbleDialogDelegateView::CreateBubble(view);
-  view->ShowForReason(reason);
+  // |allow_refocus_alert| is set to false because translate bubble does not
+  // have an additional screen reader alert instructing the user to use a
+  // hotkey combination to focus the bubble.
+  view->ShowForReason(reason, false);
   translate::ReportUiAction(translate::BUBBLE_SHOWN);
   return bubble_widget;
 }
@@ -179,6 +185,14 @@
     case TranslateBubbleModel::VIEW_STATE_ADVANCED:
       id = IDS_TRANSLATE_BUBBLE_ADVANCED_TITLE;
       break;
+    // Widget title and close button does not show for TAB ui.
+    // These two cases don't apply but need to be handled to avoid error.
+    case TranslateBubbleModel::VIEW_STATE_SOURCE_LANGUAGE:
+      id = IDS_TRANSLATE_BUBBLE_ADVANCED_TITLE;
+      break;
+    case TranslateBubbleModel::VIEW_STATE_TARGET_LANGUAGE:
+      id = IDS_TRANSLATE_BUBBLE_ADVANCED_TITLE;
+      break;
   }
 
   return l10n_util::GetStringUTF16(id);
@@ -196,10 +210,7 @@
 void TranslateBubbleView::OnMenuButtonClicked(views::Button* source,
                                               const gfx::Point& point,
                                               const ui::Event* event) {
-  gfx::Rect screen_bounds = source->GetBoundsInScreen();
-  options_menu_runner_->RunMenuAt(source->GetWidget(), nullptr, screen_bounds,
-                                  views::MenuAnchorPosition::kTopRight,
-                                  ui::MENU_SOURCE_MOUSE);
+  ShowOptionsMenuTab(source);
 }
 
 void TranslateBubbleView::Init() {
@@ -208,36 +219,32 @@
 
   should_always_translate_ = model_->ShouldAlwaysTranslate();
   // Create different view based on user selection in
-  // kUseButtonTranslateBubbleUI.
-  if (bubble_ui_model_ == language::TranslateUIBubbleModel::BUTTON ||
-      bubble_ui_model_ == language::TranslateUIBubbleModel::DEFAULT) {
-    before_translate_view_ = CreateViewBeforeTranslate();
-    translating_view_ = CreateViewTranslating();
-    after_translate_view_ = CreateViewAfterTranslate();
-    error_view_ = CreateViewError();
-    advanced_view_ = CreateViewAdvanced();
-  } else if (bubble_ui_model_ == language::TranslateUIBubbleModel::TAB) {
-    tab_translate_view_ = CreateTabView();
-    error_view_ = CreateViewError();
-    advanced_view_ = CreateViewAdvanced();
-  } else {  // Button
-    before_translate_view_ = CreateViewBeforeTranslate();
-    translating_view_ = CreateViewTranslating();
-    after_translate_view_ = CreateViewAfterTranslate();
-    error_view_ = CreateViewError();
-    advanced_view_ = CreateViewAdvanced();
-  }
-
-  // TAB UI option has the same view before/during/after translate.
   if (bubble_ui_model_ != language::TranslateUIBubbleModel::TAB) {
-    AddChildView(before_translate_view_);
-    AddChildView(translating_view_);
-    AddChildView(after_translate_view_);
+    before_translate_view_ = CreateViewBeforeTranslate();
+    translating_view_ = CreateViewTranslating();
+    after_translate_view_ = CreateViewAfterTranslate();
+    error_view_ = CreateViewError();
+    advanced_view_ = CreateViewAdvanced();
   } else {
-    AddChildView(tab_translate_view_);
+    tab_translate_view_ = CreateViewTab();
+    before_translate_view_ = tab_translate_view_;
+    translating_view_ = tab_translate_view_;
+    after_translate_view_ = tab_translate_view_;
+    advanced_view_source_ = TabUiCreateViewAdvanedSource();
+    advanced_view_target_ = TabUiCreateViewAdvanedTarget();
+    error_view_ = CreateViewError();
+  }
+  AddChildView(before_translate_view_);
+  AddChildView(translating_view_);
+  AddChildView(after_translate_view_);
+  // TAB UI has two additional advanced view.
+  if (bubble_ui_model_ == language::TranslateUIBubbleModel::TAB) {
+    AddChildView(advanced_view_source_);
+    AddChildView(advanced_view_target_);
+  } else {
+    AddChildView(advanced_view_);
   }
   AddChildView(error_view_);
-  AddChildView(advanced_view_);
 
   AddAccelerator(ui::Accelerator(ui::VKEY_RETURN, ui::EF_NONE));
 
@@ -292,6 +299,19 @@
       ShowOptionsMenu(sender);
       break;
     }
+    case BUTTON_ID_OPTIONS_MENU_TAB: {
+      ShowOptionsMenuTab(sender);
+      break;
+    }
+    case BUTTON_ID_CLOSE: {
+      GetWidget()->Close();
+      break;
+    }
+    // TODO(crbug.com/963148): implement handler to take care of RESET action.
+    case BUTTON_ID_RESET: {
+      GetWidget()->Close();
+      break;
+    }
   }
 }
 
@@ -352,6 +372,10 @@
       }
       break;
     }
+    case TranslateBubbleModel::VIEW_STATE_TARGET_LANGUAGE:
+      break;
+    case TranslateBubbleModel::VIEW_STATE_SOURCE_LANGUAGE:
+      break;
   }
   return BubbleDialogDelegateView::AcceleratorPressed(accelerator);
 }
@@ -410,6 +434,52 @@
                                   ui::MENU_SOURCE_MOUSE);
 }
 
+// Create the munu items for the dropdown options menu under TAB UI.
+void TranslateBubbleView::ShowOptionsMenuTab(views::Button* source) {
+  // Recreate the menu model as translated languages can change while the menu
+  // is not showing, which invalidates these text strings.
+  tab_options_menu_model_.reset(new ui::SimpleMenuModel(this));
+
+  tab_options_menu_model_->AddItemWithStringId(
+      OptionsMenuItem::CHANGE_TARGET_LANGUAGE,
+      IDS_TRANSLATE_BUBBLE_CHANGE_TARGET_LANGUAGE);
+
+  // Don't show "Always translate <language>" in incognito mode, because it
+  // doesn't do anything anyways.
+  if (!is_in_incognito_window_) {
+    tab_options_menu_model_->AddCheckItem(
+        OptionsMenuItem::ALWAYS_TRANSLATE_LANGUAGE,
+        l10n_util::GetStringFUTF16(
+            IDS_TRANSLATE_BUBBLE_ALWAYS_TRANSLATE_LANG,
+            model_->GetLanguageNameAt(model_->GetOriginalLanguageIndex())));
+  }
+
+  tab_options_menu_model_->AddItem(
+      OptionsMenuItem::NEVER_TRANSLATE_LANGUAGE,
+      l10n_util::GetStringFUTF16(
+          IDS_TRANSLATE_BUBBLE_NEVER_TRANSLATE_LANG,
+          model_->GetLanguageNameAt(model_->GetOriginalLanguageIndex())));
+
+  if (model_->CanBlacklistSite()) {
+    tab_options_menu_model_->AddItemWithStringId(
+        OptionsMenuItem::NEVER_TRANSLATE_SITE,
+        IDS_TRANSLATE_BUBBLE_NEVER_TRANSLATE_SITE);
+  }
+
+  tab_options_menu_model_->AddItem(
+      OptionsMenuItem::CHANGE_SOURCE_LANGUAGE,
+      l10n_util::GetStringFUTF16(
+          IDS_TRANSLATE_BUBBLE_CHANGE_SOURCE_LANGUAGE,
+          model_->GetLanguageNameAt(model_->GetOriginalLanguageIndex())));
+
+  options_menu_runner_.reset(new views::MenuRunner(
+      tab_options_menu_model_.get(), views::MenuRunner::COMBOBOX));
+  gfx::Rect screen_bounds = source->GetAnchorBoundsInScreen();
+  options_menu_runner_->RunMenuAt(source->GetWidget(), nullptr, screen_bounds,
+                                  views::MenuAnchorPosition::kTopRight,
+                                  ui::MENU_SOURCE_MOUSE);
+}
+
 bool TranslateBubbleView::IsCommandIdChecked(int command_id) const {
   DCHECK_EQ(OptionsMenuItem::ALWAYS_TRANSLATE_LANGUAGE, command_id);
   return should_always_translate_;
@@ -450,6 +520,14 @@
       translate::ReportUiAction(translate::ADVANCED_MENU_CLICKED);
       SwitchView(TranslateBubbleModel::VIEW_STATE_ADVANCED);
       break;
+    case OptionsMenuItem::CHANGE_TARGET_LANGUAGE:
+      translate::ReportUiAction(translate::ADVANCED_MENU_CLICKED);
+      SwitchView(TranslateBubbleModel::VIEW_STATE_TARGET_LANGUAGE);
+      break;
+    case OptionsMenuItem::CHANGE_SOURCE_LANGUAGE:
+      translate::ReportUiAction(translate::ADVANCED_MENU_CLICKED);
+      SwitchView(TranslateBubbleModel::VIEW_STATE_SOURCE_LANGUAGE);
+      break;
     default:
       NOTREACHED();
   }
@@ -485,6 +563,9 @@
       after_translate_view_(NULL),
       error_view_(NULL),
       advanced_view_(NULL),
+      tab_translate_view_(NULL),
+      advanced_view_source_(NULL),
+      advanced_view_target_(NULL),
       source_language_combobox_(NULL),
       target_language_combobox_(NULL),
       before_always_translate_checkbox_(NULL),
@@ -496,7 +577,7 @@
       error_type_(error_type),
       is_in_incognito_window_(
           web_contents && web_contents->GetBrowserContext()->IsOffTheRecord()),
-      bubble_ui_model_(language::GetTranslateUIBubbleModel()),
+      bubble_ui_model_(language::GetTranslateUiBubbleModel()),
       should_always_translate_(false) {
   DCHECK(anchor_view);
   translate_bubble_view_ = this;
@@ -511,24 +592,19 @@
     // view tab_translate_view is created and used throughout the translate
     // process.
     case TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE:
-      if (bubble_ui_model_ == language::TranslateUIBubbleModel::TAB) {
-        return tab_translate_view_;
-      }
       return before_translate_view_;
     case TranslateBubbleModel::VIEW_STATE_TRANSLATING:
-      if (bubble_ui_model_ == language::TranslateUIBubbleModel::TAB) {
-        return tab_translate_view_;
-      }
       return translating_view_;
     case TranslateBubbleModel::VIEW_STATE_AFTER_TRANSLATE:
-      if (bubble_ui_model_ == language::TranslateUIBubbleModel::TAB) {
-        return tab_translate_view_;
-      }
       return after_translate_view_;
     case TranslateBubbleModel::VIEW_STATE_ERROR:
       return error_view_;
     case TranslateBubbleModel::VIEW_STATE_ADVANCED:
       return advanced_view_;
+    case TranslateBubbleModel::VIEW_STATE_SOURCE_LANGUAGE:
+      return advanced_view_source_;
+    case TranslateBubbleModel::VIEW_STATE_TARGET_LANGUAGE:
+      return advanced_view_target_;
   }
   NOTREACHED();
   return NULL;
@@ -553,13 +629,23 @@
 
 void TranslateBubbleView::ConfirmAdvancedOptions() {
   model_->SetAlwaysTranslate(should_always_translate_);
-  if (model_->IsPageTranslatedInCurrentLanguages()) {
-    model_->GoBackFromAdvanced();
-    UpdateChildVisibilities();
-    SizeToContents();
+  if (bubble_ui_model_ != language::TranslateUIBubbleModel::TAB) {
+    if (model_->IsPageTranslatedInCurrentLanguages()) {
+      model_->GoBackFromAdvanced();
+      UpdateChildVisibilities();
+      SizeToContents();
+    } else {
+      model_->Translate();
+      SwitchView(TranslateBubbleModel::VIEW_STATE_TRANSLATING);
+    }
   } else {
-    model_->Translate();
-    SwitchView(TranslateBubbleModel::VIEW_STATE_TRANSLATING);
+    if (model_->IsPageTranslatedInCurrentLanguages()) {
+      SwitchView(TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE);
+      SizeToContents();
+    } else {
+      model_->Translate();
+      SwitchView(TranslateBubbleModel::VIEW_STATE_AFTER_TRANSLATE);
+    }
   }
   translate::ReportUiAction(translate::DONE_BUTTON_CLICKED);
 }
@@ -612,8 +698,12 @@
     before_always_translate_checkbox_->SetChecked(should_always_translate_);
   for (views::View* view : children())
     view->SetVisible(view == GetCurrentView());
-  if (GetWidget())
+
+  // Not required for TAB ui because the title is not shown.
+  if (bubble_ui_model_ != language::TranslateUIBubbleModel::TAB &&
+      GetWidget()) {
     GetWidget()->UpdateWindowTitle();
+  }
   // BoxLayout only considers visible children, so ensure any newly visible
   // child views are positioned correctly.
   Layout();
@@ -698,8 +788,8 @@
 }
 
 // This view is shown if "Tab" is selected for feature
-// kUseButtonTranslateBubbleUI before/on/after translate.
-views::View* TranslateBubbleView::CreateTabView() {
+// kUseButtonTranslateBubbleUi before/on/after translate.
+views::View* TranslateBubbleView::CreateViewTab() {
   base::string16 original_language_name =
       model_->GetLanguageNameAt(model_->GetOriginalLanguageIndex());
   base::string16 target_language_name =
@@ -726,28 +816,42 @@
   // Tabbed pane for language selection. Can't use unique_ptr because
   // tabs have to be added after the tabbed_pane is added to the parent,
   // when we release ownership of the unique_ptr.
+  // TODO(crbug.com/963148): Initial auto translate doesn't trigger tabbed pane
+  // to highlight the correct pane.
   views::TabbedPane* tabbed_pane = new views::TabbedPane();
 
   // Three dots options menu button
   const SkColor option_icon_color = gfx::kChromeIconGrey;
   const gfx::VectorIcon* option_icon_id = &kBrowserToolsIcon;
-  std::unique_ptr<views::MenuButton> translate_menu_button =
+  std::unique_ptr<views::MenuButton> tab_translate_options_button =
       std::make_unique<views::MenuButton>(
           base::string16(base::ASCIIToUTF16("")), this);
-  translate_menu_button->SetImage(
+
+  tab_translate_options_button->SetImage(
       views::Button::STATE_NORMAL,
       gfx::CreateVectorIcon(*option_icon_id, 16, option_icon_color));
-  translate_menu_button->SetID(BUTTON_ID_OPTIONS_MENU);
-  translate_menu_button->set_request_focus_on_press(true);
+  tab_translate_options_button->set_ink_drop_base_color(gfx::kChromeIconGrey);
+  tab_translate_options_button->SetInkDropMode(views::Button::InkDropMode::ON);
+  tab_translate_options_button->SetID(BUTTON_ID_OPTIONS_MENU_TAB);
+  tab_translate_options_button->set_request_focus_on_press(true);
 
   // Close button
   const SkColor close_icon_color = gfx::kChromeIconGrey;
   const gfx::VectorIcon* close_icon_id = &vector_icons::kCloseRoundedIcon;
-  std::unique_ptr<views::ImageButton> close_button =
-      std::make_unique<views::ImageButton>(this);
+
+  // Use CreateVectorImageButton automatically enables background ink drop
+  auto close_button = views::CreateVectorImageButton(this);
+  // Size 18 is set for |translate_menu_button| while 16 is set for
+  // |close_button| so that the ink down shadow for both buttons are the same.
+  // MenuButton's insets is smaller than ImageButton by 2. Height is
+  // unadjustable through AddColumn so setting column width will result in
+  // rectangular instead of square column shape.
   close_button->SetImage(
       views::Button::STATE_NORMAL,
-      gfx::CreateVectorIcon(*close_icon_id, 16, close_icon_color));
+      gfx::CreateVectorIcon(*close_icon_id, 18, close_icon_color));
+  close_button->set_ink_drop_base_color(gfx::kChromeIconGrey);
+  close_button->SetFocusForPlatform();
+  close_button->SetID(BUTTON_ID_CLOSE);
 
   // Initialize a column
   constexpr int kColumnSetId = 0;
@@ -776,8 +880,9 @@
   layout->StartRow(1, kColumnSetId);
   layout->AddView(language_icon.release());
   layout->AddView(tabbed_pane);
-  layout->AddView(translate_menu_button.release());
+  layout->AddView(tab_translate_options_button.release());
   layout->AddView(close_button.release());
+
   // NOTE: Panes must be added after |tabbed_pane| has been added to its parent.
   tabbed_pane->AddTab(original_language_name, CreateEmptyPane());
   tabbed_pane->AddTab(target_language_name, CreateEmptyPane());
@@ -917,7 +1022,7 @@
       l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_TRANSLATION_LANGUAGE));
 
   // Index + 1 because GetOriginalLanguageIndex() returns the actual index - 1
-  // to accomodate added label "UNKNOWN". (crbug/721600)
+  // to accommodate added label "Unknown". (crbug/721600)
   int source_default_index = model_->GetOriginalLanguageIndex() + 1;
   source_language_combobox_model_.reset(
       new SourceLanguageComboboxModel(source_default_index, model_.get()));
@@ -1030,6 +1135,182 @@
   return view;
 }
 
+views::View* TranslateBubbleView::TabUiCreateViewAdvanedSource() {
+  // Bubble title
+  // TODO(crbug.com/963148): Update label font to be the same as widget title
+  // font.
+  std::unique_ptr<views::Label> source_language_title_label =
+      std::make_unique<views::Label>(
+          l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_ADVANCED_SOURCE));
+
+  // Index + 1 because GetOriginalLanguageIndex() returns the actual index - 1
+  // to accommodate added label "Unknown". (crbug/721600)
+  // Language icon
+  int source_default_index = model_->GetOriginalLanguageIndex() + 1;
+  source_language_combobox_model_.reset(
+      new SourceLanguageComboboxModel(source_default_index, model_.get()));
+
+  // Ideally all child view elements shall be created using unique_ptr.
+  // Using normal pointer for compatibility with existing code.
+  source_language_combobox_ =
+      new views::Combobox(source_language_combobox_model_.get());
+
+  source_language_combobox_->SetID(COMBOBOX_ID_SOURCE_LANGUAGE);
+  source_language_combobox_->set_listener(this);
+  return CreateViewAdvancedTabUi(source_language_combobox_,
+                                 std::move(source_language_title_label));
+}
+
+views::View* TranslateBubbleView::TabUiCreateViewAdvanedTarget() {
+  // Bubble title
+  // TODO(crbug.com/963148): Update label font to be the same as widget title
+  // font.
+  std::unique_ptr<views::Label> target_language_title_label =
+      std::make_unique<views::Label>(
+          l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_ADVANCED_TARGET));
+
+  int target_default_index = model_->GetTargetLanguageIndex();
+  target_language_combobox_model_.reset(
+      new TargetLanguageComboboxModel(target_default_index, model_.get()));
+
+  // Ideally all view components shall be created using unique_ptr.
+  // Using normal pointer for compatibility with existing code.
+  target_language_combobox_ =
+      new views::Combobox(target_language_combobox_model_.get());
+
+  target_language_combobox_->SetID(COMBOBOX_ID_TARGET_LANGUAGE);
+  target_language_combobox_->set_listener(this);
+  return CreateViewAdvancedTabUi(target_language_combobox_,
+                                 std::move(target_language_title_label));
+}
+
+views::View* TranslateBubbleView::CreateViewAdvancedTabUi(
+    views::Combobox* combobox,
+    std::unique_ptr<views::Label> language_title_label) {
+  const int language_icon_id = IDR_TRANSLATE_BUBBLE_ICON;
+  std::unique_ptr<views::ImageView> language_icon =
+      std::make_unique<views::ImageView>();
+  gfx::ImageSkia* language_icon_image =
+      ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
+          language_icon_id);
+  language_icon->SetImage(*language_icon_image);
+
+  // Close button
+  const SkColor close_icon_color = gfx::kChromeIconGrey;
+  const gfx::VectorIcon* close_icon_id = &vector_icons::kCloseRoundedIcon;
+  // Use CreateVectorImageButton automatically enables background ink drop
+  auto close_button = views::CreateVectorImageButton(this);
+
+  // Size 18 is set for |translate_menu_button| while 16 is set for
+  // |close_button| so that the ink down shadow for both buttons are the same.
+  // MenuButton's insets is smaller than ImageButton by 2. Height is
+  // unadjustable through AddColumn so setting column width will result in
+  // rectangular instead of square column shape.
+  close_button->SetImage(
+      views::Button::STATE_NORMAL,
+      gfx::CreateVectorIcon(*close_icon_id, 18, close_icon_color));
+  close_button->set_ink_drop_base_color(gfx::kChromeIconGrey);
+  close_button->SetFocusForPlatform();
+  close_button->SetID(BUTTON_ID_CLOSE);
+
+  views::View* view = new AdvancedViewContainer();
+  views::GridLayout* layout =
+      view->SetLayoutManager(std::make_unique<views::GridLayout>(view));
+
+  enum {
+    COLUMN_SET_ID_TITLE,
+    COLUMN_SET_ID_LANGUAGES,
+    COLUMN_SET_ID_BUTTONS,
+  };
+
+  ChromeLayoutProvider* provider = ChromeLayoutProvider::Get();
+
+  views::ColumnSet* cs = layout->AddColumnSet(COLUMN_SET_ID_TITLE);
+  cs->AddColumn(views::GridLayout::TRAILING, views::GridLayout::CENTER,
+                views::GridLayout::kFixedSize, views::GridLayout::USE_PREF, 0,
+                0);
+  cs->AddPaddingColumn(
+      views::GridLayout::kFixedSize,
+      provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_HORIZONTAL) *
+          2);
+  cs->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER,
+                views::GridLayout::kFixedSize, views::GridLayout::USE_PREF, 0,
+                0);
+  cs->AddPaddingColumn(
+      views::GridLayout::kFixedSize,
+      provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_HORIZONTAL) *
+          4);
+  cs->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER,
+                views::GridLayout::kFixedSize, views::GridLayout::USE_PREF, 0,
+                0);
+  cs->AddPaddingColumn(1.0, 0);
+
+  cs = layout->AddColumnSet(COLUMN_SET_ID_LANGUAGES);
+  cs->AddColumn(views::GridLayout::TRAILING, views::GridLayout::CENTER,
+                views::GridLayout::kFixedSize, views::GridLayout::USE_PREF, 0,
+                0);
+  cs->AddPaddingColumn(
+      views::GridLayout::kFixedSize,
+      provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_HORIZONTAL));
+  cs->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER,
+                views::GridLayout::kFixedSize, views::GridLayout::USE_PREF, 0,
+                0);
+  cs->AddPaddingColumn(1.0, 0);
+
+  cs = layout->AddColumnSet(COLUMN_SET_ID_BUTTONS);
+  cs->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER,
+                views::GridLayout::kFixedSize, views::GridLayout::USE_PREF, 0,
+                0);
+  cs->AddPaddingColumn(
+      1.0, provider->GetDistanceMetric(DISTANCE_UNRELATED_CONTROL_HORIZONTAL));
+  cs->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER,
+                views::GridLayout::kFixedSize, views::GridLayout::USE_PREF, 0,
+                0);
+  cs->AddPaddingColumn(
+      views::GridLayout::kFixedSize,
+      provider->GetDistanceMetric(views::DISTANCE_RELATED_BUTTON_HORIZONTAL));
+  cs->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER,
+                views::GridLayout::kFixedSize, views::GridLayout::USE_PREF, 0,
+                0);
+
+  layout->StartRow(views::GridLayout::kFixedSize, COLUMN_SET_ID_TITLE);
+  layout->AddView(language_icon.release());
+  layout->AddView(language_title_label.release());
+  layout->AddView(close_button.release());
+
+  const int vertical_spacing =
+      provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_VERTICAL);
+  layout->AddPaddingRow(views::GridLayout::kFixedSize, vertical_spacing);
+
+  layout->StartRow(views::GridLayout::kFixedSize, COLUMN_SET_ID_LANGUAGES);
+  layout->SkipColumns(1);
+  // TODO(crbug.com/963148): Combobox doesn't take up the whole row as shown
+  // in mock.
+  layout->AddView(combobox);
+
+  layout->AddPaddingRow(views::GridLayout::kFixedSize, vertical_spacing);
+
+  layout->StartRow(views::GridLayout::kFixedSize, COLUMN_SET_ID_BUTTONS);
+  layout->SkipColumns(1);
+
+  auto advanced_done_button = views::MdTextButton::CreateSecondaryUiButton(
+      this, l10n_util::GetStringUTF16(IDS_DONE));
+  advanced_done_button->SetID(BUTTON_ID_DONE);
+  advanced_done_button->SetIsDefault(true);
+  auto advanced_reset_button = views::MdTextButton::CreateSecondaryUiButton(
+      this, l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_RESET));
+  advanced_reset_button->SetID(BUTTON_ID_RESET);
+  advanced_done_button_ = advanced_done_button.release();
+  advanced_cancel_button_ = advanced_reset_button.release();
+
+  layout->AddView(advanced_done_button_);
+  layout->AddView(advanced_cancel_button_);
+
+  UpdateAdvancedView();
+
+  return view;
+}
+
 views::Checkbox* TranslateBubbleView::GetAlwaysTranslateCheckbox() {
   if (model_->GetViewState() == TranslateBubbleModel::VIEW_STATE_ADVANCED) {
     return advanced_always_translate_checkbox_;
@@ -1044,8 +1325,13 @@
 
 void TranslateBubbleView::SwitchView(
     TranslateBubbleModel::ViewState view_state) {
-  if (model_->GetViewState() == view_state)
+  TranslateBubbleModel::ViewState current_state = model_->GetViewState();
+  if ((bubble_ui_model_ == language::TranslateUIBubbleModel::TAB &&
+       !TabUiIsAdvancedState(view_state) &&
+       !TabUiIsAdvancedState(current_state)) ||
+      current_state == view_state) {
     return;
+  }
 
   model_->SetViewState(view_state);
   if (view_state == TranslateBubbleModel::VIEW_STATE_ADVANCED)
@@ -1061,6 +1347,13 @@
   model_->ShowError(error_type);
 }
 
+bool TranslateBubbleView::TabUiIsAdvancedState(
+    TranslateBubbleModel::ViewState view_state) {
+  return !(view_state == TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE ||
+           view_state == TranslateBubbleModel::VIEW_STATE_TRANSLATING ||
+           view_state == TranslateBubbleModel::VIEW_STATE_AFTER_TRANSLATE);
+}
+
 void TranslateBubbleView::UpdateAdvancedView() {
   DCHECK(advanced_done_button_);
   advanced_done_button_->SetText(
diff --git a/chrome/browser/ui/views/translate/translate_bubble_view.h b/chrome/browser/ui/views/translate/translate_bubble_view.h
index 0eba3d744..4243cd6 100644
--- a/chrome/browser/ui/views/translate/translate_bubble_view.h
+++ b/chrome/browser/ui/views/translate/translate_bubble_view.h
@@ -25,6 +25,7 @@
 #include "ui/views/controls/button/button.h"
 #include "ui/views/controls/button/menu_button_listener.h"
 #include "ui/views/controls/combobox/combobox_listener.h"
+#include "ui/views/controls/label.h"
 #include "ui/views/controls/link_listener.h"
 #include "ui/views/controls/menu/menu_runner.h"
 #include "ui/views/controls/styled_label_listener.h"
@@ -52,7 +53,9 @@
     ALWAYS_TRANSLATE_LANGUAGE,
     NEVER_TRANSLATE_LANGUAGE,
     NEVER_TRANSLATE_SITE,
-    MORE_OPTIONS
+    MORE_OPTIONS,
+    CHANGE_TARGET_LANGUAGE,
+    CHANGE_SOURCE_LANGUAGE
   };
 
   ~TranslateBubbleView() override;
@@ -136,6 +139,9 @@
     BUTTON_ID_ALWAYS_TRANSLATE,
     BUTTON_ID_ADVANCED,
     BUTTON_ID_OPTIONS_MENU,
+    BUTTON_ID_OPTIONS_MENU_TAB,
+    BUTTON_ID_CLOSE,
+    BUTTON_ID_RESET
   };
 
   enum ComboboxID {
@@ -150,6 +156,7 @@
       ::Browser*,
       const ::base::string16&);
   FRIEND_TEST_ALL_PREFIXES(TranslateBubbleViewTest, TranslateButton);
+  FRIEND_TEST_ALL_PREFIXES(TranslateBubbleViewTest, TabUiTranslateButton);
   FRIEND_TEST_ALL_PREFIXES(TranslateBubbleViewTest, AdvancedLink);
   FRIEND_TEST_ALL_PREFIXES(TranslateBubbleViewTest, ShowOriginalButton);
   FRIEND_TEST_ALL_PREFIXES(TranslateBubbleViewTest, TryAgainButton);
@@ -158,9 +165,17 @@
   FRIEND_TEST_ALL_PREFIXES(TranslateBubbleViewTest,
                            AlwaysTranslateCheckboxAndDoneButton);
   FRIEND_TEST_ALL_PREFIXES(TranslateBubbleViewTest, DoneButton);
+  FRIEND_TEST_ALL_PREFIXES(TranslateBubbleViewTest, TabUiSourceDoneButton);
+  FRIEND_TEST_ALL_PREFIXES(TranslateBubbleViewTest, TabUiTargetDoneButton);
   FRIEND_TEST_ALL_PREFIXES(TranslateBubbleViewTest,
                            DoneButtonWithoutTranslating);
   FRIEND_TEST_ALL_PREFIXES(TranslateBubbleViewTest,
+                           TabUiSourceDoneButtonWithoutTranslating);
+  FRIEND_TEST_ALL_PREFIXES(TranslateBubbleViewTest,
+                           TabUiTargetDoneButtonWithoutTranslating);
+  FRIEND_TEST_ALL_PREFIXES(TabUiSourceTranslateBubbleViewTest,
+                           DoneButtonWithoutTranslating);
+  FRIEND_TEST_ALL_PREFIXES(TranslateBubbleViewTest,
                            CancelButtonReturningBeforeTranslate);
   FRIEND_TEST_ALL_PREFIXES(TranslateBubbleViewTest,
                            CancelButtonReturningAfterTranslate);
@@ -168,11 +183,19 @@
   FRIEND_TEST_ALL_PREFIXES(TranslateBubbleViewTest,
                            OptionsMenuNeverTranslateLanguage);
   FRIEND_TEST_ALL_PREFIXES(TranslateBubbleViewTest,
+                           TabUiOptionsMenuNeverTranslateLanguage);
+  FRIEND_TEST_ALL_PREFIXES(TranslateBubbleViewTest,
                            OptionsMenuRespectsBlacklistSite);
   FRIEND_TEST_ALL_PREFIXES(TranslateBubbleViewTest,
+                           TabUiOptionsMenuRespectsBlacklistSite);
+  FRIEND_TEST_ALL_PREFIXES(TranslateBubbleViewTest,
                            OptionsMenuNeverTranslateSite);
   FRIEND_TEST_ALL_PREFIXES(TranslateBubbleViewTest,
+                           TabUiOptionsMenuNeverTranslateSite);
+  FRIEND_TEST_ALL_PREFIXES(TranslateBubbleViewTest,
                            AlwaysTranslateLanguageMenuItem);
+  FRIEND_TEST_ALL_PREFIXES(TranslateBubbleViewTest,
+                           TabUiAlwaysTranslateLanguageMenuItem);
   FRIEND_TEST_ALL_PREFIXES(TranslateLanguageBrowserTest, TranslateAndRevert);
   FRIEND_TEST_ALL_PREFIXES(TranslateBubbleViewBrowserTest,
                            CheckNeverTranslateThisSiteBlacklist);
@@ -196,6 +219,9 @@
   // Triggers options menu.
   void ShowOptionsMenu(views::Button* source);
 
+  // Triggers options menu in TAB ui.
+  void ShowOptionsMenuTab(views::Button* source);
+
   // Handles the event when the user clicks a link.
   void HandleLinkClicked(LinkID sender_id);
 
@@ -212,7 +238,7 @@
 
   // Creates the view for TAB UI. This view is being used before/during/after
   // translate.
-  views::View* CreateTabView();
+  views::View* CreateViewTab();
 
   // AddTab function requires a view element to be shown below each tab.
   // This function creates an empty view so no extra white space below the tab.
@@ -236,6 +262,18 @@
   // Three options depending on UI selection in kUseButtonTranslateBubbleUI.
   views::View* CreateViewAdvanced();
 
+  // Creates source language label and combobox for Tab Ui advanced view
+  views::View* TabUiCreateViewAdvanedSource();
+
+  // Creates source language label and combobox for Tab Ui advanced view
+  views::View* TabUiCreateViewAdvanedTarget();
+
+  // Creates the 'advanced' view to show source/target language combobox under
+  // TAB UI. Caller takes ownership of the returned view.
+  views::View* CreateViewAdvancedTabUi(
+      views::Combobox* combobox,
+      std::unique_ptr<views::Label> language_title_label);
+
   // Get the current always translate checkbox
   views::Checkbox* GetAlwaysTranslateCheckbox();
 
@@ -253,6 +291,9 @@
   void ShowOriginal();
   void ConfirmAdvancedOptions();
 
+  // Return true if the current state is in advanced state for TAB UI.
+  bool TabUiIsAdvancedState(TranslateBubbleModel::ViewState view_state);
+
   static TranslateBubbleView* translate_bubble_view_;
 
   views::View* before_translate_view_;
@@ -261,6 +302,8 @@
   views::View* error_view_;
   views::View* advanced_view_;
   views::View* tab_translate_view_;
+  views::View* advanced_view_source_;
+  views::View* advanced_view_target_;
 
   std::unique_ptr<SourceLanguageComboboxModel> source_language_combobox_model_;
   std::unique_ptr<TargetLanguageComboboxModel> target_language_combobox_model_;
@@ -276,9 +319,12 @@
 
   // Used to trigger the options menu in tests.
   views::Button* before_translate_options_button_;
+
   std::unique_ptr<ui::SimpleMenuModel> options_menu_model_;
   std::unique_ptr<views::MenuRunner> options_menu_runner_;
 
+  std::unique_ptr<ui::SimpleMenuModel> tab_options_menu_model_;
+
   std::unique_ptr<TranslateBubbleModel> model_;
 
   translate::TranslateErrors::Type error_type_;
@@ -286,7 +332,7 @@
   // Whether the window is an incognito window.
   const bool is_in_incognito_window_;
 
-  language::TranslateUIBubbleModel bubble_ui_model_;
+  const language::TranslateUIBubbleModel bubble_ui_model_;
 
   bool should_always_translate_;
 
diff --git a/chrome/browser/ui/views/translate/translate_bubble_view_unittest.cc b/chrome/browser/ui/views/translate/translate_bubble_view_unittest.cc
index 58ed13c2..87a190cc 100644
--- a/chrome/browser/ui/views/translate/translate_bubble_view_unittest.cc
+++ b/chrome/browser/ui/views/translate/translate_bubble_view_unittest.cc
@@ -28,7 +28,6 @@
 #include "ui/views/controls/styled_label.h"
 #include "ui/views/widget/widget.h"
 
-
 namespace {
 
 class MockTranslateBubbleModel : public TranslateBubbleModel {
@@ -202,6 +201,15 @@
                                         ui::DomCode::ENTER, ui::EF_NONE));
   }
 
+  void TriggerOptionsMenuTab() {
+    views::Button* button = static_cast<views::Button*>(
+        bubble_->GetViewByID(TranslateBubbleView::BUTTON_ID_OPTIONS_MENU_TAB));
+    LOG(INFO) << button->GetID();
+    bubble_->ButtonPressed(button,
+                           ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_RETURN,
+                                        ui::DomCode::ENTER, ui::EF_NONE));
+  }
+
   ui::SimpleMenuModel* options_menu_model() {
     return bubble_->options_menu_model_.get();
   }
@@ -221,6 +229,20 @@
   EXPECT_TRUE(mock_model_->translate_called_);
 }
 
+TEST_F(TranslateBubbleViewTest, TabUiTranslateButton) {
+  scoped_feature_list_.InitAndEnableFeatureWithParameters(
+      language::kUseButtonTranslateBubbleUi,
+      {{language::kTranslateUIBubbleKey,
+        language::kTranslateUIBubbleTabValue}});
+
+  CreateAndShowBubble();
+  EXPECT_FALSE(mock_model_->translate_called_);
+
+  // Press the "Translate" button.
+  PressButton(TranslateBubbleView::BUTTON_ID_TRANSLATE);
+  EXPECT_TRUE(mock_model_->translate_called_);
+}
+
 TEST_F(TranslateBubbleViewTest, OptionsMenuNeverTranslateLanguage) {
   CreateAndShowBubble();
 
@@ -238,6 +260,28 @@
   EXPECT_TRUE(bubble_->GetWidget()->IsClosed());
 }
 
+TEST_F(TranslateBubbleViewTest, TabUiOptionsMenuNeverTranslateLanguage) {
+  scoped_feature_list_.InitAndEnableFeatureWithParameters(
+      language::kUseButtonTranslateBubbleUi,
+      {{language::kTranslateUIBubbleKey,
+        language::kTranslateUIBubbleTabValue}});
+
+  CreateAndShowBubble();
+
+  EXPECT_FALSE(bubble_->GetWidget()->IsClosed());
+  EXPECT_FALSE(mock_model_->never_translate_language_);
+  EXPECT_FALSE(denial_button_clicked());
+  TriggerOptionsMenuTab();
+
+  const int index = bubble_->tab_options_menu_model_->GetIndexOfCommandId(
+      TranslateBubbleView::NEVER_TRANSLATE_LANGUAGE);
+  bubble_->tab_options_menu_model_->ActivatedAt(index);
+
+  EXPECT_TRUE(denial_button_clicked());
+  EXPECT_TRUE(mock_model_->never_translate_language_);
+  EXPECT_TRUE(bubble_->GetWidget()->IsClosed());
+}
+
 TEST_F(TranslateBubbleViewTest, OptionsMenuNeverTranslateSite) {
   // NEVER_TRANSLATE_SITE should only show up for sites that can be blacklisted.
   mock_model_->SetCanBlacklistSite(true);
@@ -257,6 +301,31 @@
   EXPECT_TRUE(bubble_->GetWidget()->IsClosed());
 }
 
+TEST_F(TranslateBubbleViewTest, TabUiOptionsMenuNeverTranslateSite) {
+  scoped_feature_list_.InitAndEnableFeatureWithParameters(
+      language::kUseButtonTranslateBubbleUi,
+      {{language::kTranslateUIBubbleKey,
+        language::kTranslateUIBubbleTabValue}});
+
+  // NEVER_TRANSLATE_SITE should only show up for sites that can be blacklisted.
+  mock_model_->SetCanBlacklistSite(true);
+  CreateAndShowBubble();
+
+  EXPECT_FALSE(mock_model_->never_translate_site_);
+  EXPECT_FALSE(denial_button_clicked());
+  EXPECT_FALSE(bubble_->GetWidget()->IsClosed());
+
+  TriggerOptionsMenuTab();
+  const int index = bubble_->tab_options_menu_model_->GetIndexOfCommandId(
+      TranslateBubbleView::NEVER_TRANSLATE_SITE);
+  bubble_->tab_options_menu_model_->ActivatedAt(index);
+
+  EXPECT_TRUE(denial_button_clicked());
+  EXPECT_TRUE(mock_model_->never_translate_site_);
+  EXPECT_TRUE(bubble_->GetWidget()->IsClosed());
+}
+
+// This button is not used in Tab Ui.
 TEST_F(TranslateBubbleViewTest, ShowOriginalButton) {
   CreateAndShowBubble();
   bubble_->SwitchView(TranslateBubbleModel::VIEW_STATE_AFTER_TRANSLATE);
@@ -267,6 +336,7 @@
   EXPECT_TRUE(mock_model_->revert_translation_called_);
 }
 
+// This button is not used in Tab Ui.
 TEST_F(TranslateBubbleViewTest, TryAgainButton) {
   CreateAndShowBubble();
   bubble_->SwitchToErrorView(translate::TranslateErrors::NETWORK);
@@ -279,6 +349,7 @@
   EXPECT_TRUE(mock_model_->translate_called_);
 }
 
+// This checkbox is not used in Tab Ui.
 TEST_F(TranslateBubbleViewTest, AlwaysTranslateCheckboxAndCancelButton) {
   CreateAndShowBubble();
   bubble_->SwitchView(TranslateBubbleModel::VIEW_STATE_ADVANCED);
@@ -303,6 +374,7 @@
   EXPECT_EQ(0, mock_model_->set_always_translate_called_count_);
 }
 
+// This checkbox is not used in Tab Ui.
 TEST_F(TranslateBubbleViewTest, AlwaysTranslateCheckboxAndDoneButton) {
   CreateAndShowBubble();
   bubble_->SwitchView(TranslateBubbleModel::VIEW_STATE_ADVANCED);
@@ -347,6 +419,55 @@
   EXPECT_EQ(20, mock_model_->target_language_index_);
 }
 
+TEST_F(TranslateBubbleViewTest, TabUiSourceDoneButton) {
+  scoped_feature_list_.InitAndEnableFeatureWithParameters(
+      language::kUseButtonTranslateBubbleUi,
+      {{language::kTranslateUIBubbleKey,
+        language::kTranslateUIBubbleTabValue}});
+
+  CreateAndShowBubble();
+  bubble_->SwitchView(TranslateBubbleModel::VIEW_STATE_SOURCE_LANGUAGE);
+
+  // Click the "Done" button to translate. The selected languages by the user
+  // are applied.
+  EXPECT_FALSE(mock_model_->translate_called_);
+  bubble_->source_language_combobox_->SetSelectedIndex(10);
+  bubble_->HandleComboboxPerformAction(
+      TranslateBubbleView::COMBOBOX_ID_SOURCE_LANGUAGE);
+  bubble_->target_language_combobox_->SetSelectedIndex(20);
+  bubble_->HandleComboboxPerformAction(
+      TranslateBubbleView::COMBOBOX_ID_TARGET_LANGUAGE);
+  PressButton(TranslateBubbleView::BUTTON_ID_DONE);
+  EXPECT_TRUE(mock_model_->translate_called_);
+  // Expected value is (set id - 1) because user selected id is actual id + 1
+  EXPECT_EQ(9, mock_model_->original_language_index_);
+  EXPECT_EQ(20, mock_model_->target_language_index_);
+}
+
+TEST_F(TranslateBubbleViewTest, TabUiTargetDoneButton) {
+  scoped_feature_list_.InitAndEnableFeatureWithParameters(
+      language::kUseButtonTranslateBubbleUi,
+      {{language::kTranslateUIBubbleKey,
+        language::kTranslateUIBubbleTabValue}});
+
+  CreateAndShowBubble();
+  bubble_->SwitchView(TranslateBubbleModel::VIEW_STATE_TARGET_LANGUAGE);
+
+  // Click the "Done" button to translate. The selected languages by the user
+  // are applied.
+  EXPECT_FALSE(mock_model_->translate_called_);
+  bubble_->source_language_combobox_->SetSelectedIndex(10);
+  bubble_->HandleComboboxPerformAction(
+      TranslateBubbleView::COMBOBOX_ID_SOURCE_LANGUAGE);
+  bubble_->target_language_combobox_->SetSelectedIndex(20);
+  bubble_->HandleComboboxPerformAction(
+      TranslateBubbleView::COMBOBOX_ID_TARGET_LANGUAGE);
+  PressButton(TranslateBubbleView::BUTTON_ID_DONE);
+  EXPECT_TRUE(mock_model_->translate_called_);
+  EXPECT_EQ(9, mock_model_->original_language_index_);
+  EXPECT_EQ(20, mock_model_->target_language_index_);
+}
+
 TEST_F(TranslateBubbleViewTest, DoneButtonWithoutTranslating) {
   CreateAndShowBubble();
   EXPECT_EQ(TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE,
@@ -375,6 +496,72 @@
             bubble_->GetViewState());
 }
 
+TEST_F(TranslateBubbleViewTest, TabUiSourceDoneButtonWithoutTranslating) {
+  scoped_feature_list_.InitAndEnableFeatureWithParameters(
+      language::kUseButtonTranslateBubbleUi,
+      {{language::kTranslateUIBubbleKey,
+        language::kTranslateUIBubbleTabValue}});
+
+  CreateAndShowBubble();
+  EXPECT_EQ(TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE,
+            bubble_->GetViewState());
+
+  // Translate the page once.
+  mock_model_->Translate();
+  EXPECT_TRUE(mock_model_->translate_called_);
+
+  // Go back to the initial view.
+  EXPECT_EQ(TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE,
+            bubble_->GetViewState());
+  mock_model_->translate_called_ = false;
+
+  EXPECT_EQ(TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE,
+            bubble_->GetViewState());
+  bubble_->SwitchView(TranslateBubbleModel::VIEW_STATE_SOURCE_LANGUAGE);
+
+  // Click the "Done" button with the current language pair. This time,
+  // translation is not performed and the view state will be back to the
+  // previous view.
+  PressButton(TranslateBubbleView::BUTTON_ID_DONE);
+  EXPECT_FALSE(mock_model_->translate_called_);
+
+  EXPECT_EQ(TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE,
+            bubble_->GetViewState());
+}
+
+TEST_F(TranslateBubbleViewTest, TabUiTargetDoneButtonWithoutTranslating) {
+  scoped_feature_list_.InitAndEnableFeatureWithParameters(
+      language::kUseButtonTranslateBubbleUi,
+      {{language::kTranslateUIBubbleKey,
+        language::kTranslateUIBubbleTabValue}});
+
+  CreateAndShowBubble();
+  EXPECT_EQ(TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE,
+            bubble_->GetViewState());
+
+  // Translate the page once.
+  mock_model_->Translate();
+  EXPECT_TRUE(mock_model_->translate_called_);
+
+  // Go back to the initial view.
+  EXPECT_EQ(TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE,
+            bubble_->GetViewState());
+  mock_model_->translate_called_ = false;
+
+  EXPECT_EQ(TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE,
+            bubble_->GetViewState());
+  bubble_->SwitchView(TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE);
+
+  // Click the "Done" button with the current language pair. This time,
+  // translation is not performed and the view state will be back to the
+  // previous view.
+  PressButton(TranslateBubbleView::BUTTON_ID_DONE);
+  EXPECT_FALSE(mock_model_->translate_called_);
+
+  EXPECT_EQ(TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE,
+            bubble_->GetViewState());
+}
+
 TEST_F(TranslateBubbleViewTest, CancelButtonReturningBeforeTranslate) {
   CreateAndShowBubble();
   bubble_->SwitchView(TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE);
@@ -424,6 +611,25 @@
             0);
 }
 
+TEST_F(TranslateBubbleViewTest, TabUiOptionsMenuRespectsBlacklistSite) {
+  scoped_feature_list_.InitAndEnableFeatureWithParameters(
+      language::kUseButtonTranslateBubbleUi,
+      {{language::kTranslateUIBubbleKey,
+        language::kTranslateUIBubbleTabValue}});
+
+  mock_model_->SetCanBlacklistSite(false);
+  CreateAndShowBubble();
+
+  TriggerOptionsMenuTab();
+  // NEVER_TRANSLATE_SITE shouldn't show up for sites that can't be blacklisted.
+  EXPECT_EQ(-1, bubble_->tab_options_menu_model_->GetIndexOfCommandId(
+                    TranslateBubbleView::NEVER_TRANSLATE_SITE));
+  // Verify that the menu is populated so previous check makes sense.
+  EXPECT_GE(bubble_->tab_options_menu_model_->GetIndexOfCommandId(
+                TranslateBubbleView::NEVER_TRANSLATE_LANGUAGE),
+            0);
+}
+
 TEST_F(TranslateBubbleViewTest, AlwaysTranslateLanguageMenuItem) {
   CreateAndShowBubble();
 
@@ -460,3 +666,45 @@
   TriggerOptionsMenu();
   EXPECT_FALSE(bubble_->options_menu_model_->IsItemCheckedAt(index));
 }
+
+TEST_F(TranslateBubbleViewTest, TabUiAlwaysTranslateLanguageMenuItem) {
+  scoped_feature_list_.InitAndEnableFeatureWithParameters(
+      language::kUseButtonTranslateBubbleUi,
+      {{language::kTranslateUIBubbleKey,
+        language::kTranslateUIBubbleTabValue}});
+
+  CreateAndShowBubble();
+
+  TriggerOptionsMenuTab();
+  const int index = bubble_->tab_options_menu_model_->GetIndexOfCommandId(
+      TranslateBubbleView::ALWAYS_TRANSLATE_LANGUAGE);
+
+  EXPECT_FALSE(mock_model_->ShouldAlwaysTranslate());
+  EXPECT_FALSE(bubble_->tab_options_menu_model_->IsItemCheckedAt(index));
+  EXPECT_FALSE(mock_model_->translate_called_);
+  bubble_->tab_options_menu_model_->ActivatedAt(index);
+  EXPECT_TRUE(mock_model_->ShouldAlwaysTranslate());
+  EXPECT_TRUE(mock_model_->translate_called_);
+
+  // Go back to untranslated page, since the *language* should still always
+  // be translated (and this "untranslate" is temporary) the option should now
+  // be checked and it should be possible to disable it from the menu.
+  PressButton(TranslateBubbleView::BUTTON_ID_SHOW_ORIGINAL);
+  EXPECT_TRUE(mock_model_->revert_translation_called_);
+
+  TriggerOptionsMenuTab();
+  EXPECT_TRUE(mock_model_->ShouldAlwaysTranslate());
+  EXPECT_TRUE(bubble_->tab_options_menu_model_->IsItemCheckedAt(index));
+
+  // Translate should not be called when disabling always-translate. The page is
+  // not currently in a translated state and nothing needs to be reverted.
+  // translate_called_ is set back to false just to make sure it's not being
+  // called again.
+  mock_model_->translate_called_ = false;
+  bubble_->tab_options_menu_model_->ActivatedAt(index);
+  EXPECT_FALSE(mock_model_->ShouldAlwaysTranslate());
+  EXPECT_FALSE(mock_model_->translate_called_);
+
+  TriggerOptionsMenuTab();
+  EXPECT_FALSE(bubble_->tab_options_menu_model_->IsItemCheckedAt(index));
+}
\ No newline at end of file
diff --git a/chrome/browser/ui/webui/settings/people_handler.cc b/chrome/browser/ui/webui/settings/people_handler.cc
index 69625bc..c9d4d1d 100644
--- a/chrome/browser/ui/webui/settings/people_handler.cc
+++ b/chrome/browser/ui/webui/settings/people_handler.cc
@@ -386,7 +386,7 @@
         signin_metrics::SignoutDelete::IGNORE_METRIC);
   }
 
-  // If the signin manager already has an authenticated username, this is a
+  // If the identity manager already has a primary account, this is a
   // re-auth scenario, and we need to ensure that the user signs in with the
   // same email address.
   if (identity_manager->HasPrimaryAccount()) {
@@ -971,7 +971,7 @@
   std::unique_ptr<base::DictionaryValue> sync_status(new base::DictionaryValue);
   if (profile_->IsGuestSession()) {
     // Cannot display signin status when running in guest mode on chromeos
-    // because there is no SigninManager.
+    // because there is no IdentityManager.
     sync_status->SetBoolean("signinAllowed", false);
     return sync_status;
   }
diff --git a/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc b/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc
index 51db0a4a..f589b66 100644
--- a/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc
+++ b/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc
@@ -399,7 +399,7 @@
     if (identity_manager->HasPrimaryAccount()) {
       identity_manager->GetAccountsCookieMutator()->AddAccountToCookie(
           identity_manager->GetPrimaryAccountId(),
-          gaia::GaiaSource::kSigninManager, {});
+          gaia::GaiaSource::kPrimaryAccountManager, {});
     }
 
     signin_metrics::LogSigninReason(
diff --git a/chrome/browser/ui/webui/signin/login_ui_test_utils.cc b/chrome/browser/ui/webui/signin/login_ui_test_utils.cc
index 9913b9a..316a213 100644
--- a/chrome/browser/ui/webui/signin/login_ui_test_utils.cc
+++ b/chrome/browser/ui/webui/signin/login_ui_test_utils.cc
@@ -42,7 +42,7 @@
     "  return e.querySelector('input[type=password]');"
     "})()";
 
-// The SignInObserver observes the signin manager and blocks until a signin
+// The SignInObserver observes the identity manager and blocks until a signin
 // success or failure notification is fired.
 class SignInObserver : public identity::IdentityManager::Observer {
  public:
diff --git a/chrome/browser/ui/webui/signin/signin_utils_desktop.cc b/chrome/browser/ui/webui/signin/signin_utils_desktop.cc
index b116fe9..c41b92c 100644
--- a/chrome/browser/ui/webui/signin/signin_utils_desktop.cc
+++ b/chrome/browser/ui/webui/signin/signin_utils_desktop.cc
@@ -59,7 +59,7 @@
     if (can_offer == CAN_OFFER_SIGNIN_FOR_SECONDARY_ACCOUNT)
       return true;
 
-    // If the signin manager already has an authenticated name, then this is a
+    // If the identity manager already has a primary account, then this is a
     // re-auth scenario.  Make sure the email just signed in corresponds to
     // the one sign in manager expects.
     std::string current_email = identity_manager->GetPrimaryAccountInfo().email;
diff --git a/chrome/browser/ui/webui/version_ui.cc b/chrome/browser/ui/webui/version_ui.cc
index 54949a1e..694afee 100644
--- a/chrome/browser/ui/webui/version_ui.cc
+++ b/chrome/browser/ui/webui/version_ui.cc
@@ -12,6 +12,7 @@
 #include "build/build_config.h"
 #include "chrome/browser/chrome_content_browser_client.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/webui/localized_string.h"
 #include "chrome/browser/ui/webui/version_handler.h"
 #include "chrome/browser/ui/webui/version_util_win.h"
 #include "chrome/common/channel_info.h"
@@ -51,64 +52,68 @@
   WebUIDataSource* html_source =
       WebUIDataSource::Create(chrome::kChromeUIVersionHost);
 
-  // Localized and data strings.
-  html_source->AddLocalizedString(version_ui::kTitle, IDS_VERSION_UI_TITLE);
-  html_source->AddLocalizedString(version_ui::kApplicationLabel,
-                                  IDS_PRODUCT_NAME);
+  static constexpr LocalizedString kStrings[] = {
+    {version_ui::kTitle, IDS_VERSION_UI_TITLE},
+    {version_ui::kApplicationLabel, IDS_PRODUCT_NAME},
+    {version_ui::kCompany, IDS_ABOUT_VERSION_COMPANY_NAME},
+    {version_ui::kRevision, IDS_VERSION_UI_REVISION},
+    {version_ui::kUserAgentName, IDS_VERSION_UI_USER_AGENT},
+    {version_ui::kCommandLineName, IDS_VERSION_UI_COMMAND_LINE},
+    {version_ui::kVariationsName, IDS_VERSION_UI_VARIATIONS},
+    {version_ui::kVariationsCmdName, IDS_VERSION_UI_VARIATIONS_CMD},
+    {version_ui::kExecutablePathName, IDS_VERSION_UI_EXECUTABLE_PATH},
+    {version_ui::kProfilePathName, IDS_VERSION_UI_PROFILE_PATH},
+#if defined(OS_CHROMEOS)
+    {version_ui::kARC, IDS_ARC_LABEL},
+    {version_ui::kPlatform, IDS_PLATFORM_LABEL},
+    {version_ui::kCustomizationId, IDS_VERSION_UI_CUSTOMIZATION_ID},
+    {version_ui::kFirmwareVersion, IDS_VERSION_UI_FIRMWARE_VERSION},
+#else
+    {version_ui::kOSName, IDS_VERSION_UI_OS},
+#endif  // OS_CHROMEOS
+  };
+  AddLocalizedStringsBulk(html_source, kStrings, base::size(kStrings));
+
+#if defined(OS_ANDROID)
+  html_source->AddLocalizedString(version_ui::kGmsName, IDS_VERSION_UI_GMS);
+#else
+  html_source->AddLocalizedString(
+      version_ui::kVersionBitSize,
+      sizeof(void*) == 8 ? IDS_VERSION_UI_64BIT : IDS_VERSION_UI_32BIT);
+#endif  // OS_ANDROID
+
+  html_source->AddLocalizedString(version_ui::kOfficial,
+                                  version_info::IsOfficialBuild()
+                                      ? IDS_VERSION_UI_OFFICIAL
+                                      : IDS_VERSION_UI_UNOFFICIAL);
+
+  // Data strings.
   html_source->AddString(version_ui::kVersion,
                          version_info::GetVersionNumber());
   html_source->AddString(version_ui::kVersionModifier,
                          chrome::GetChannelName());
   html_source->AddString(version_ui::kJSEngine, "V8");
   html_source->AddString(version_ui::kJSVersion, V8_VERSION_STRING);
-  html_source->AddLocalizedString(version_ui::kCompany,
-                                  IDS_ABOUT_VERSION_COMPANY_NAME);
   html_source->AddString(
       version_ui::kCopyright,
       base::i18n::MessageFormatter::FormatWithNumberedArgs(
           l10n_util::GetStringUTF16(IDS_ABOUT_VERSION_COPYRIGHT),
           base::Time::Now()));
-  html_source->AddLocalizedString(version_ui::kRevision,
-                                  IDS_VERSION_UI_REVISION);
   html_source->AddString(version_ui::kCL, version_info::GetLastChange());
-  html_source->AddLocalizedString(version_ui::kOfficial,
-                                  version_info::IsOfficialBuild()
-                                      ? IDS_VERSION_UI_OFFICIAL
-                                      : IDS_VERSION_UI_UNOFFICIAL);
-  html_source->AddLocalizedString(version_ui::kUserAgentName,
-                                  IDS_VERSION_UI_USER_AGENT);
   html_source->AddString(version_ui::kUserAgent, GetUserAgent());
-  html_source->AddLocalizedString(version_ui::kCommandLineName,
-                                  IDS_VERSION_UI_COMMAND_LINE);
   // Note that the executable path and profile path are retrieved asynchronously
   // and returned in VersionHandler::OnGotFilePaths. The area is initially
   // blank.
-  html_source->AddLocalizedString(version_ui::kExecutablePathName,
-                                  IDS_VERSION_UI_EXECUTABLE_PATH);
   html_source->AddString(version_ui::kExecutablePath, std::string());
-  html_source->AddLocalizedString(version_ui::kProfilePathName,
-                                  IDS_VERSION_UI_PROFILE_PATH);
   html_source->AddString(version_ui::kProfilePath, std::string());
-  html_source->AddLocalizedString(version_ui::kVariationsName,
-                                  IDS_VERSION_UI_VARIATIONS);
-  html_source->AddLocalizedString(version_ui::kVariationsCmdName,
-                                  IDS_VERSION_UI_VARIATIONS_CMD);
-#if defined(OS_CHROMEOS)
-  html_source->AddLocalizedString(version_ui::kARC, IDS_ARC_LABEL);
-  html_source->AddLocalizedString(version_ui::kPlatform, IDS_PLATFORM_LABEL);
-  html_source->AddLocalizedString(version_ui::kCustomizationId,
-                                  IDS_VERSION_UI_CUSTOMIZATION_ID);
-  html_source->AddLocalizedString(version_ui::kFirmwareVersion,
-                                  IDS_VERSION_UI_FIRMWARE_VERSION);
-#else
-  html_source->AddLocalizedString(version_ui::kOSName, IDS_VERSION_UI_OS);
+
+#if !defined(OS_CHROMEOS)
   html_source->AddString(version_ui::kOSType, version_info::GetOSType());
-#endif  // OS_CHROMEOS
+#endif  // !OS_CHROMEOS
 
 #if defined(OS_ANDROID)
   html_source->AddString(version_ui::kOSVersion,
                          AndroidAboutAppInfo::GetOsInfo());
-  html_source->AddLocalizedString(version_ui::kGmsName, IDS_VERSION_UI_GMS);
   html_source->AddString(version_ui::kGmsVersion,
                          AndroidAboutAppInfo::GetGmsInfo());
 #else
@@ -118,10 +123,6 @@
   html_source->AddString(version_ui::kFlashVersion, std::string());
 #endif  // OS_ANDROID
 
-  html_source->AddLocalizedString(
-      version_ui::kVersionBitSize,
-      sizeof(void*) == 8 ? IDS_VERSION_UI_64BIT : IDS_VERSION_UI_32BIT);
-
 #if defined(OS_WIN)
   html_source->AddString(
       version_ui::kCommandLine,
diff --git a/chrome/common/search/BUILD.gn b/chrome/common/search/BUILD.gn
new file mode 100644
index 0000000..450c73a
--- /dev/null
+++ b/chrome/common/search/BUILD.gn
@@ -0,0 +1,24 @@
+# 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.
+
+import("//build/compiled_action.gni")
+
+executable("generate_colors_info") {
+  sources = [
+    "generate_colors_info.cc",
+    "selected_colors_info.h",
+  ]
+  deps = [
+    "//base",
+    "//skia",
+  ]
+}
+
+compiled_action("generate_chrome_colors_info") {
+  tool = ":generate_colors_info"
+  outputs = [
+    "$target_gen_dir/generated_colors_info.h",
+  ]
+  args = rebase_path(outputs, root_build_dir)
+}
diff --git a/chrome/browser/search/chrome_colors/generate_colors_info.cc b/chrome/common/search/generate_colors_info.cc
similarity index 89%
rename from chrome/browser/search/chrome_colors/generate_colors_info.cc
rename to chrome/common/search/generate_colors_info.cc
index 5d4d439..ffb8f26 100644
--- a/chrome/browser/search/chrome_colors/generate_colors_info.cc
+++ b/chrome/common/search/generate_colors_info.cc
@@ -7,7 +7,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
-#include "chrome/browser/search/chrome_colors/selected_colors_info.h"
+#include "chrome/common/search/selected_colors_info.h"
 
 // TODO(gayane): Replace with real template.
 // Template for the icon svg.
@@ -44,15 +44,16 @@
 
 // Template for the generated file content.
 // $1 - lines for updated color info.
+// $2 - number of colors.
 const char kFileContentTemplate[] =
     "// Generated from generate_colors_info.cc. Do not edit!\n"
     "\n"
-    "#ifndef CHROME_BROWSER_SEARCH_CHROME_COLORS_GENERATED_COLORS_INFO_H_\n"
-    "#define CHROME_BROWSER_SEARCH_CHROME_COLORS_GENERATED_COLORS_INFO_H_\n"
+    "#ifndef CHROME_COMMON_SEARCH_GENERATED_COLORS_INFO_H_\n"
+    "#define CHROME_COMMON_SEARCH_GENERATED_COLORS_INFO_H_\n"
     "\n"
     "#include <stdint.h>\n"
     "\n"
-    "#include \"chrome/common/search/instant_types.h\"\n"
+    "#include \"chrome/common/search/selected_colors_info.h\"\n"
     "#include \"third_party/skia/include/core/SkColor.h\"\n"
     "\n"
     "namespace chrome_colors {\n"
@@ -63,9 +64,11 @@
     "$1\n"
     "};\n"
     "\n"
+    "const size_t kNumColorsInfo = $2;"
+    "\n"
     "} // namespace chrome_colors\n"
     "\n"
-    "#endif  // CHROME_BROWSER_SEARCH_CHROME_COLORS_GENERATED_COLORS_INFO_H_\n";
+    "#endif  // CHROME_COMMON_SEARCH_GENERATED_COLORS_INFO_H_\n";
 
 // Returns hex string representation for the |color| in "#FFFFFF" format.
 std::string SkColorToHexString(SkColor color) {
@@ -106,11 +109,16 @@
 // |chrome_colors::kSelectedColorsInfo| along with generated icon data.
 void GenerateColorsInfoFile(std::string output_dir) {
   std::vector<std::string> updated_color_info;
-  for (chrome_colors::ColorInfo color_info : chrome_colors::kSelectedColorsInfo)
+  int colors_num = 0;
+  for (chrome_colors::ColorInfo color_info :
+       chrome_colors::kSelectedColorsInfo) {
     updated_color_info.push_back(GenerateColorLine(color_info));
+    colors_num++;
+  }
 
   std::vector<std::string> subst;
   subst.push_back(base::JoinString(updated_color_info, ",\n"));
+  subst.push_back(base::NumberToString(colors_num));
   std::string output =
       base::ReplaceStringPlaceholders(kFileContentTemplate, subst, NULL);
 
diff --git a/chrome/browser/search/chrome_colors/selected_colors_info.h b/chrome/common/search/selected_colors_info.h
similarity index 80%
rename from chrome/browser/search/chrome_colors/selected_colors_info.h
rename to chrome/common/search/selected_colors_info.h
index 638b900..05f4c29 100644
--- a/chrome/browser/search/chrome_colors/selected_colors_info.h
+++ b/chrome/common/search/selected_colors_info.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_SEARCH_CHROME_COLORS_SELECTED_COLORS_INFO_H_
-#define CHROME_BROWSER_SEARCH_CHROME_COLORS_SELECTED_COLORS_INFO_H_
+#ifndef CHROME_COMMON_SEARCH_SELECTED_COLORS_INFO_H_
+#define CHROME_COMMON_SEARCH_SELECTED_COLORS_INFO_H_
 
 #include <stdint.h>
 
@@ -31,4 +31,4 @@
 
 }  // namespace chrome_colors
 
-#endif  // CHROME_BROWSER_SEARCH_CHROME_COLORS_SELECTED_COLORS_INFO_H_
+#endif  // CHROME_COMMON_SEARCH_SELECTED_COLORS_INFO_H_
diff --git a/chrome/renderer/BUILD.gn b/chrome/renderer/BUILD.gn
index e5f98be2..4df09da 100644
--- a/chrome/renderer/BUILD.gn
+++ b/chrome/renderer/BUILD.gn
@@ -402,6 +402,8 @@
       "searchbox/searchbox_extension.cc",
       "searchbox/searchbox_extension.h",
     ]
+
+    deps += [ "//chrome/common/search:generate_chrome_colors_info" ]
   }
 
   if (is_android) {
diff --git a/chrome/renderer/net/net_error_helper.cc b/chrome/renderer/net/net_error_helper.cc
index a16be7c..64bcba2 100644
--- a/chrome/renderer/net/net_error_helper.cc
+++ b/chrome/renderer/net/net_error_helper.cc
@@ -41,12 +41,12 @@
 #include "content/public/renderer/render_frame.h"
 #include "content/public/renderer/render_thread.h"
 #include "content/public/renderer/render_view.h"
-#include "content/public/renderer/resource_fetcher.h"
 #include "ipc/ipc_message.h"
 #include "ipc/ipc_message_macros.h"
 #include "net/base/net_errors.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/network/public/cpp/simple_url_loader.h"
 #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
 #include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
 #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-shared.h"
@@ -111,10 +111,8 @@
 
 #if defined(OS_ANDROID)
 bool IsAutoFetchFeatureEnabled() {
-  // This feature is incompatible with OfflineContentOnNetError, so don't allow
-  // both. Disabled for touchless builds.
-  return !IsOfflineContentOnNetErrorFeatureEnabled() &&
-         base::FeatureList::IsEnabled(features::kAutoFetchOnNetErrorPage) &&
+  // Disabled for touchless builds.
+  return base::FeatureList::IsEnabled(features::kAutoFetchOnNetErrorPage) &&
          offline_pages::IsOfflinePagesEnabled();
 }
 #else   // OS_ANDROID
@@ -356,6 +354,36 @@
   return core_->ShouldSuppressErrorPage(GetFrameType(render_frame()), url);
 }
 
+std::unique_ptr<network::ResourceRequest> NetErrorHelper::CreatePostRequest(
+    const GURL& url) const {
+  auto resource_request = std::make_unique<network::ResourceRequest>();
+  resource_request->url = url;
+  resource_request->method = "POST";
+  resource_request->fetch_request_context_type =
+      static_cast<int>(blink::mojom::RequestContextType::INTERNAL);
+  resource_request->resource_type =
+      static_cast<int>(content::ResourceType::kSubResource);
+
+  blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
+  resource_request->site_for_cookies = frame->GetDocument().SiteForCookies();
+  // The security origin of the error page should exist and be opaque.
+  DCHECK(!frame->GetDocument().GetSecurityOrigin().IsNull());
+  DCHECK(frame->GetDocument().GetSecurityOrigin().IsOpaque());
+  // All requests coming from a renderer process have to use |request_initiator|
+  // that matches the |request_initiator_site_lock| set by the browser when
+  // creating URLLoaderFactory exposed to the renderer.
+  blink::WebSecurityOrigin origin = frame->GetDocument().GetSecurityOrigin();
+  resource_request->request_initiator = static_cast<url::Origin>(origin);
+  // Since the page is trying to fetch cross-origin resources (which would
+  // be protected by CORB in no-cors mode), we need to ask for CORS.  See also
+  // https://crbug.com/932542.
+  resource_request->fetch_request_mode =
+      network::mojom::FetchRequestMode::kCors;
+  resource_request->headers.SetHeader(net::HttpRequestHeaders::kOrigin,
+                                      origin.ToString().Ascii());
+  return resource_request;
+}
+
 chrome::mojom::NetworkDiagnostics*
 NetErrorHelper::GetRemoteNetworkDiagnostics() {
   if (!remote_network_diagnostics_) {
@@ -484,51 +512,44 @@
 void NetErrorHelper::FetchNavigationCorrections(
     const GURL& navigation_correction_url,
     const std::string& navigation_correction_request_body) {
-  DCHECK(!correction_fetcher_.get());
+  DCHECK(!correction_loader_.get());
 
-  correction_fetcher_ =
-      content::ResourceFetcher::Create(navigation_correction_url);
-  correction_fetcher_->SetMethod("POST");
-  correction_fetcher_->SetBody(navigation_correction_request_body);
-  correction_fetcher_->SetHeader("Content-Type", "application/json");
+  std::unique_ptr<network::ResourceRequest> resource_request =
+      CreatePostRequest(navigation_correction_url);
 
-  // Since the page is trying to fetch cross-origin resources (which would
-  // be protected by CORB in no-cors mode), we need to ask for CORS.  See also
-  // https://crbug.com/932542.
-  correction_fetcher_->SetFetchRequestMode(
-      network::mojom::FetchRequestMode::kCors);
-
-  // Prevent CORB from triggering on this request by setting an Origin header.
-  correction_fetcher_->SetHeader("Origin", "null");
-
-  correction_fetcher_->Start(
-      render_frame()->GetWebFrame(), blink::mojom::RequestContextType::INTERNAL,
-      render_frame()->GetURLLoaderFactory(), GetNetworkTrafficAnnotationTag(),
+  correction_loader_ = network::SimpleURLLoader::Create(
+      std::move(resource_request), GetNetworkTrafficAnnotationTag());
+  correction_loader_->AttachStringForUpload(navigation_correction_request_body,
+                                            "application/json");
+  correction_loader_->DownloadToString(
+      render_frame()->GetURLLoaderFactory().get(),
       base::BindOnce(&NetErrorHelper::OnNavigationCorrectionsFetched,
-                     base::Unretained(this)));
-
-  correction_fetcher_->SetTimeout(
+                     base::Unretained(this)),
+      network::SimpleURLLoader::kMaxBoundedStringDownloadSize);
+  correction_loader_->SetTimeoutDuration(
       base::TimeDelta::FromSeconds(kNavigationCorrectionFetchTimeoutSec));
 }
 
 void NetErrorHelper::CancelFetchNavigationCorrections() {
-  correction_fetcher_.reset();
+  correction_loader_.reset();
 }
 
 void NetErrorHelper::SendTrackingRequest(
     const GURL& tracking_url,
     const std::string& tracking_request_body) {
   // If there's already a pending tracking request, this will cancel it.
-  tracking_fetcher_ = content::ResourceFetcher::Create(tracking_url);
-  tracking_fetcher_->SetMethod("POST");
-  tracking_fetcher_->SetBody(tracking_request_body);
-  tracking_fetcher_->SetHeader("Content-Type", "application/json");
+  std::unique_ptr<network::ResourceRequest> resource_request =
+      CreatePostRequest(tracking_url);
 
-  tracking_fetcher_->Start(
-      render_frame()->GetWebFrame(), blink::mojom::RequestContextType::INTERNAL,
-      render_frame()->GetURLLoaderFactory(), GetNetworkTrafficAnnotationTag(),
+  tracking_loader_ = network::SimpleURLLoader::Create(
+      std::move(resource_request), GetNetworkTrafficAnnotationTag());
+  tracking_loader_->AttachStringForUpload(tracking_request_body,
+                                          "application/json");
+  tracking_loader_->DownloadToString(
+      render_frame()->GetURLLoaderFactory().get(),
       base::BindOnce(&NetErrorHelper::OnTrackingRequestComplete,
-                     base::Unretained(this)));
+                     base::Unretained(this)),
+      network::SimpleURLLoader::kMaxBoundedStringDownloadSize);
 }
 
 void NetErrorHelper::ReloadPage(bool bypass_cache) {
@@ -610,21 +631,16 @@
 }
 
 void NetErrorHelper::OnNavigationCorrectionsFetched(
-    const blink::WebURLResponse& response,
-    const std::string& data) {
-  // The fetcher may only be deleted after |data| is passed to |core_|.  Move
-  // it to a temporary to prevent any potential re-entrancy issues.
-  std::unique_ptr<content::ResourceFetcher> fetcher(
-      correction_fetcher_.release());
-  bool success = (!response.IsNull() && response.HttpStatusCode() == 200);
-  core_->OnNavigationCorrectionsFetched(success ? data : "",
+    std::unique_ptr<std::string> response_body) {
+  bool success = response_body.get() != nullptr;
+  correction_loader_.reset();
+  core_->OnNavigationCorrectionsFetched(success ? *response_body : "",
                                         base::i18n::IsRTL());
 }
 
 void NetErrorHelper::OnTrackingRequestComplete(
-    const blink::WebURLResponse& response,
-    const std::string& data) {
-  tracking_fetcher_.reset();
+    std::unique_ptr<std::string> response_body) {
+  tracking_loader_.reset();
 }
 
 void NetErrorHelper::OnNetworkDiagnosticsClientRequest(
diff --git a/chrome/renderer/net/net_error_helper.h b/chrome/renderer/net/net_error_helper.h
index e00236f..1147d2e3 100644
--- a/chrome/renderer/net/net_error_helper.h
+++ b/chrome/renderer/net/net_error_helper.h
@@ -32,19 +32,15 @@
 
 class GURL;
 
-namespace blink {
-class WebURLResponse;
-}
-
-namespace content {
-class ResourceFetcher;
-}
-
 namespace error_page {
 class Error;
 struct ErrorPageParams;
 }
 
+namespace network {
+class SimpleURLLoader;
+}
+
 // Listens for NetErrorInfo messages from the NetErrorTabHelper on the
 // browser side and updates the error page with more details (currently, just
 // DNS probe results) if/when available.
@@ -114,6 +110,10 @@
   bool ShouldSuppressErrorPage(const GURL& url);
 
  private:
+  // Returns ResourceRequest filled with |url|. It has request_initiator from
+  // the frame origin and origin header with "null" for a unique origin.
+  std::unique_ptr<network::ResourceRequest> CreatePostRequest(
+      const GURL& url) const;
   chrome::mojom::NetworkDiagnostics* GetRemoteNetworkDiagnostics();
   chrome::mojom::NetworkEasterEgg* GetRemoteNetworkEasterEgg();
 
@@ -159,11 +159,10 @@
                                      const std::string& api_key,
                                      const GURL& search_url);
 
-  void OnNavigationCorrectionsFetched(const blink::WebURLResponse& response,
-                                      const std::string& data);
+  void OnNavigationCorrectionsFetched(
+      std::unique_ptr<std::string> response_body);
 
-  void OnTrackingRequestComplete(const blink::WebURLResponse& response,
-                                 const std::string& data);
+  void OnTrackingRequestComplete(std::unique_ptr<std::string> response_body);
 
   void OnNetworkDiagnosticsClientRequest(
       chrome::mojom::NetworkDiagnosticsClientAssociatedRequest request);
@@ -181,8 +180,8 @@
                                    const std::string& api_key,
                                    const GURL& search_url) override;
 
-  std::unique_ptr<content::ResourceFetcher> correction_fetcher_;
-  std::unique_ptr<content::ResourceFetcher> tracking_fetcher_;
+  std::unique_ptr<network::SimpleURLLoader> correction_loader_;
+  std::unique_ptr<network::SimpleURLLoader> tracking_loader_;
 
   std::unique_ptr<NetErrorHelperCore> core_;
 
diff --git a/chrome/renderer/searchbox/searchbox_extension.cc b/chrome/renderer/searchbox/searchbox_extension.cc
index f660c0cb..4b07bce 100644
--- a/chrome/renderer/searchbox/searchbox_extension.cc
+++ b/chrome/renderer/searchbox/searchbox_extension.cc
@@ -17,8 +17,10 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
+#include "chrome/common/search/generated_colors_info.h"
 #include "chrome/common/search/instant_types.h"
 #include "chrome/common/search/ntp_logging_events.h"
+#include "chrome/common/search/selected_colors_info.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/renderer_resources.h"
 #include "chrome/renderer/searchbox/searchbox.h"
@@ -703,6 +705,7 @@
                                       v8::Local<v8::Value> color);
   static void RevertThemeChanges();
   static void ConfirmThemeChanges();
+  static v8::Local<v8::Value> GetColorsInfo(v8::Isolate* isolate);
 
   DISALLOW_COPY_AND_ASSIGN(NewTabPageBindings);
 };
@@ -769,7 +772,8 @@
                  &NewTabPageBindings::ApplyAutogeneratedTheme)
       .SetMethod("revertThemeChanges", &NewTabPageBindings::RevertThemeChanges)
       .SetMethod("confirmThemeChanges",
-                 &NewTabPageBindings::ConfirmThemeChanges);
+                 &NewTabPageBindings::ConfirmThemeChanges)
+      .SetMethod("getColorsInfo", &NewTabPageBindings::GetColorsInfo);
 }
 
 // static
@@ -1187,6 +1191,26 @@
     return;
   search_box->ConfirmThemeChanges();
 }
+
+v8::Local<v8::Value> NewTabPageBindings::GetColorsInfo(v8::Isolate* isolate) {
+  v8::Local<v8::Context> context = isolate->GetCurrentContext();
+  v8::Local<v8::Object> v8_colors =
+      v8::Array::New(isolate, chrome_colors::kNumColorsInfo);
+  for (chrome_colors::ColorInfo color_info :
+       chrome_colors::kGeneratedColorsInfo) {
+    v8::Local<v8::Object> v8_color_info =
+        gin::DataObjectBuilder(isolate)
+            .Set("id", color_info.id)
+            .Set("color", SkColorToArray(isolate, color_info.color))
+            .Set("label", std::string(color_info.label))
+            .Set("icon", std::string(color_info.icon_data))
+            .Build();
+    v8_colors->CreateDataProperty(context, color_info.id, v8_color_info)
+        .Check();
+  }
+  return v8_colors;
+}
+
 }  // namespace
 
 // static
diff --git a/chrome/test/data/android/portals/touch-transfer-portal.html b/chrome/test/data/android/portals/touch-transfer-portal.html
deleted file mode 100644
index bc15d7b..0000000
--- a/chrome/test/data/android/portals/touch-transfer-portal.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<!DOCTYPE html>
-<html>
-<style>
-  #scroller {
-    width: 300px;
-    height: 2000px;
-    background-color: green;
-  }
-</style>
-<body>
-  <div id="scroller"></div>
-</body>
-</html>
diff --git a/chrome/test/data/android/portals/touch-transfer.html b/chrome/test/data/android/portals/touch-transfer.html
deleted file mode 100644
index 34c7ac9..0000000
--- a/chrome/test/data/android/portals/touch-transfer.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
-  <div>This is the embedder</div>
-  <portal src="touch-transfer-portal.html"></portal>
-  <script>
-    document.addEventListener("overscroll", e => {
-      var portal = document.querySelector("portal");
-      portal.activate();
-    });
-  </script>
-</body>
-</html>
diff --git a/chrome/test/data/extensions/api_test/service_worker/filtered_events_after_restart/background.js b/chrome/test/data/extensions/api_test/service_worker/filtered_events_after_restart/background.js
deleted file mode 100644
index a9c1830..0000000
--- a/chrome/test/data/extensions/api_test/service_worker/filtered_events_after_restart/background.js
+++ /dev/null
@@ -1,7 +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.
-
-chrome.runtime.onInstalled.addListener(function() {
-  chrome.tabs.create({url: 'page.html'}, chrome.test.callbackPass());
-});
diff --git a/chrome/test/data/extensions/api_test/service_worker/filtered_events_after_restart/manifest.json b/chrome/test/data/extensions/api_test/service_worker/filtered_events_after_restart/manifest.json
deleted file mode 100644
index 8f011ad..0000000
--- a/chrome/test/data/extensions/api_test/service_worker/filtered_events_after_restart/manifest.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-  "name": "Extension service worker - persistent filtered events",
-  "version": "1.0",
-  "manifest_version": 2,
-  "description": "Extension service worker - filtered events test with webNavigation, that survives across browser restart",
-  "background": {"scripts": ["background.js"]},
-  "permissions": ["webNavigation", "tabs"]
-}
diff --git a/chrome/test/data/extensions/api_test/service_worker/filtered_events_after_restart/page.html b/chrome/test/data/extensions/api_test/service_worker/filtered_events_after_restart/page.html
deleted file mode 100644
index f6e2de85..0000000
--- a/chrome/test/data/extensions/api_test/service_worker/filtered_events_after_restart/page.html
+++ /dev/null
@@ -1 +0,0 @@
-<script src="page.js"></script>
diff --git a/chrome/test/data/extensions/api_test/service_worker/filtered_events_after_restart/page.js b/chrome/test/data/extensions/api_test/service_worker/filtered_events_after_restart/page.js
deleted file mode 100644
index 165359b..0000000
--- a/chrome/test/data/extensions/api_test/service_worker/filtered_events_after_restart/page.js
+++ /dev/null
@@ -1,22 +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.
-
-var getReadyPromise = () => new Promise(function(resolve, reject) {
-  navigator.serviceWorker.register('sw.js').then(function() {
-    return navigator.serviceWorker.ready;
-  }).then(function(registration) {
-    resolve('ready');
-  }).catch(function(err) {
-    reject(err);
-  });
-});
-
-window.runServiceWorkerAsync = function() {
-  chrome.test.log('runServiceWorkerAsync');
-  getReadyPromise().then(function(message) {
-    chrome.test.sendMessage('listener-added');
-  }).catch(function(err) {
-    chrome.test.sendMessage('FAILURE');
-  });
-};
diff --git a/chrome/test/data/extensions/api_test/service_worker/filtered_events_after_restart/a.html b/chrome/test/data/extensions/api_test/service_worker/worker_based_background/filtered_events_after_restart/a.html
similarity index 100%
rename from chrome/test/data/extensions/api_test/service_worker/filtered_events_after_restart/a.html
rename to chrome/test/data/extensions/api_test/service_worker/worker_based_background/filtered_events_after_restart/a.html
diff --git a/chrome/test/data/extensions/api_test/service_worker/worker_based_background/filtered_events_after_restart/a.js b/chrome/test/data/extensions/api_test/service_worker/worker_based_background/filtered_events_after_restart/a.js
new file mode 100644
index 0000000..0800553
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/service_worker/worker_based_background/filtered_events_after_restart/a.js
@@ -0,0 +1,7 @@
+// 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.
+
+onload = function() {
+  document.location = 'b.html';
+}
diff --git a/chrome/test/data/extensions/api_test/service_worker/filtered_events_after_restart/b.html b/chrome/test/data/extensions/api_test/service_worker/worker_based_background/filtered_events_after_restart/b.html
similarity index 100%
rename from chrome/test/data/extensions/api_test/service_worker/filtered_events_after_restart/b.html
rename to chrome/test/data/extensions/api_test/service_worker/worker_based_background/filtered_events_after_restart/b.html
diff --git a/chrome/test/data/extensions/api_test/service_worker/worker_based_background/filtered_events_after_restart/manifest.json b/chrome/test/data/extensions/api_test/service_worker/worker_based_background/filtered_events_after_restart/manifest.json
new file mode 100644
index 0000000..4b071fa
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/service_worker/worker_based_background/filtered_events_after_restart/manifest.json
@@ -0,0 +1,9 @@
+{
+  "name": "Extension service worker - persistent filtered events",
+  "version": "1.0",
+  "manifest_version": 2,
+  "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDcBHwzDvyBQ6bDppkIs9MP4ksKqCMyXQ/A52JivHZKh4YO/9vJsT3oaYhSpDCE9RPocOEQvwsHsFReW2nUEc6OLLyoCFFxIb7KkLGsmfakkut/fFdNJYh0xOTbSN8YvLWcqph09XAY2Y/f0AL7vfO1cuCqtkMt8hFrBGWxDdf9CQIDAQAB",
+  "description": "Extension service worker - filtered events test with webNavigation, that survives across browser restart",
+  "background": {"service_worker": "service_worker_background.js"},
+  "permissions": ["webNavigation"]
+}
diff --git a/chrome/test/data/extensions/api_test/service_worker/filtered_events_after_restart/sw.js b/chrome/test/data/extensions/api_test/service_worker/worker_based_background/filtered_events_after_restart/service_worker_background.js
similarity index 88%
rename from chrome/test/data/extensions/api_test/service_worker/filtered_events_after_restart/sw.js
rename to chrome/test/data/extensions/api_test/service_worker/worker_based_background/filtered_events_after_restart/service_worker_background.js
index 11a5f6a..b4813f9 100644
--- a/chrome/test/data/extensions/api_test/service_worker/filtered_events_after_restart/sw.js
+++ b/chrome/test/data/extensions/api_test/service_worker/worker_based_background/filtered_events_after_restart/service_worker_background.js
@@ -1,9 +1,10 @@
-// Copyright 2017 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.
 
 var TEST_DIR =
-      '/extensions/api_test/service_worker/filtered_events_after_restart/';
+    '/extensions/api_test/service_worker/worker_based_background/' +
+    'filtered_events_after_restart/';
 
 function getURL(port, filename) {
   return 'http://127.0.0.1:' + port + TEST_DIR + filename;
@@ -54,3 +55,5 @@
 };
 
 registerFilteredEventListeners();
+
+chrome.test.sendMessage('ready');
diff --git a/chromeos/services/device_sync/DEPS b/chromeos/services/device_sync/DEPS
index 0baeca64..822926a 100644
--- a/chromeos/services/device_sync/DEPS
+++ b/chromeos/services/device_sync/DEPS
@@ -7,8 +7,8 @@
   # see https://groups.google.com/a/chromium.org/d/msg/chromium-dev/dgFLuxqZt1o/iEqkyoQQBwAJ for help and info.
   "-components/signin/core/browser/fake_profile_oauth2_token_service.h",
   "-components/signin/core/browser/profile_oauth2_token_service.h",
-  "-components/signin/core/browser/signin_manager.h",
-  "-components/signin/core/browser/signin_manager_base.h",
+  "-components/signin/core/browser/primary_account_manager.h",
+  "-components/signin/core/browser/primary_account_policy_manager.h",
   "+components/version_info",
   "+google_apis/gaia",
   "+mojo/public/cpp",
diff --git a/chromeos/services/network_config/cros_network_config_unittest.cc b/chromeos/services/network_config/cros_network_config_unittest.cc
index 380c4a8..c1a06d0c 100644
--- a/chromeos/services/network_config/cros_network_config_unittest.cc
+++ b/chromeos/services/network_config/cros_network_config_unittest.cc
@@ -287,6 +287,9 @@
 }
 
 TEST_F(CrosNetworkConfigTest, RequestNetworkScan) {
+  // Observe device state list changes and track when the wifi scanning state
+  // gets set to true. Note: In the test the scan will complete immediately and
+  // the scanning state will get set back to false, so ignore that change.
   class ScanningObserver : public CrosNetworkConfigTestObserver {
    public:
     explicit ScanningObserver(CrosNetworkConfig* cros_network_config)
@@ -296,8 +299,8 @@
           [](bool* wifi_scanning,
              std::vector<mojom::DeviceStatePropertiesPtr> devices) {
             for (auto& device : devices) {
-              if (device->type == mojom::NetworkType::kWiFi)
-                *wifi_scanning = device->scanning;
+              if (device->type == mojom::NetworkType::kWiFi && device->scanning)
+                *wifi_scanning = true;
             }
           },
           &wifi_scanning_));
@@ -309,12 +312,9 @@
   cros_network_config()->AddObserver(observer.GenerateInterfacePtr());
   base::RunLoop().RunUntilIdle();
 
-  // Set a short delay so that the scan does not complete before the
-  // CrosNetworkConfig observer method gets fired.
-  helper().manager_test()->SetInteractiveDelay(
-      base::TimeDelta::FromMilliseconds(1));
   cros_network_config()->RequestNetworkScan(mojom::NetworkType::kWiFi);
   base::RunLoop().RunUntilIdle();
+  observer.FlushForTesting();
   EXPECT_TRUE(observer.wifi_scanning_);
 }
 
diff --git a/chromeos/tpm/tpm_token_info_getter_unittest.cc b/chromeos/tpm/tpm_token_info_getter_unittest.cc
index fe0bda26..57b6b28 100644
--- a/chromeos/tpm/tpm_token_info_getter_unittest.cc
+++ b/chromeos/tpm/tpm_token_info_getter_unittest.cc
@@ -10,12 +10,12 @@
 
 #include "base/bind.h"
 #include "base/location.h"
-#include "base/message_loop/message_loop.h"
 #include "base/optional.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/stl_util.h"
 #include "base/task_runner.h"
+#include "base/test/scoped_task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chromeos/cryptohome/cryptohome_parameters.h"
 #include "chromeos/dbus/cryptohome/cryptohome_client.h"
@@ -226,7 +226,7 @@
   std::vector<int64_t> delays_;
 
  private:
-  base::MessageLoop message_loop_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
 
   DISALLOW_COPY_AND_ASSIGN(SystemTPMTokenInfoGetterTest);
 };
@@ -252,7 +252,7 @@
   std::vector<int64_t> delays_;
 
  private:
-  base::MessageLoop message_loop_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
 
   DISALLOW_COPY_AND_ASSIGN(UserTPMTokenInfoGetterTest);
 };
diff --git a/components/autofill/core/browser/DEPS b/components/autofill/core/browser/DEPS
index fc64742..e56e6370 100644
--- a/components/autofill/core/browser/DEPS
+++ b/components/autofill/core/browser/DEPS
@@ -13,8 +13,8 @@
   # see https://groups.google.com/a/chromium.org/d/msg/chromium-dev/dgFLuxqZt1o/iEqkyoQQBwAJ for help and info.
   "-components/signin/core/browser/fake_profile_oauth2_token_service.h",
   "-components/signin/core/browser/profile_oauth2_token_service.h",
-  "-components/signin/core/browser/signin_manager.h",
-  "-components/signin/core/browser/signin_manager_base.h",
+  "-components/signin/core/browser/primary_account_manager.h",
+  "-components/signin/core/browser/primary_account_policy_manager.h",
   "+components/sync",
   "+components/variations",
   "+components/version_info",
diff --git a/components/exo/BUILD.gn b/components/exo/BUILD.gn
index e9c1ea4..52be23d 100644
--- a/components/exo/BUILD.gn
+++ b/components/exo/BUILD.gn
@@ -33,6 +33,9 @@
     "layer_tree_frame_sink_holder.h",
     "mime_utils.cc",
     "mime_utils.h",
+    "pointer.cc",
+    "pointer.h",
+    "pointer_delegate.h",
     "seat.cc",
     "seat.h",
     "seat_observer.h",
@@ -109,9 +112,6 @@
       "notification_surface.cc",
       "notification_surface.h",
       "notification_surface_manager.h",
-      "pointer.cc",
-      "pointer.h",
-      "pointer_delegate.h",
       "shell_surface.cc",
       "shell_surface.h",
       "shell_surface_base.cc",
diff --git a/components/exo/pointer.cc b/components/exo/pointer.cc
index 2c0a6c16..cb524cc 100644
--- a/components/exo/pointer.cc
+++ b/components/exo/pointer.cc
@@ -6,7 +6,6 @@
 
 #include <utility>
 
-#include "ash/public/cpp/shell_window_ids.h"
 #include "base/bind.h"
 #include "base/feature_list.h"
 #include "components/exo/input_trace.h"
@@ -16,7 +15,6 @@
 #include "components/exo/shell_surface_util.h"
 #include "components/exo/surface.h"
 #include "components/exo/wm_helper.h"
-#include "components/exo/wm_helper_chromeos.h"
 #include "components/viz/common/frame_sinks/copy_output_request.h"
 #include "components/viz/common/frame_sinks/copy_output_result.h"
 #include "ui/aura/client/capture_client.h"
@@ -32,6 +30,10 @@
 #include "ui/gfx/transform_util.h"
 #include "ui/views/widget/widget.h"
 
+#if defined(OS_CHROMEOS)
+#include "ash/public/cpp/shell_window_ids.h"
+#endif
+
 #if defined(USE_OZONE)
 #include "ui/ozone/public/cursor_factory_ozone.h"
 #endif
@@ -79,6 +81,15 @@
   return capture_info;
 }
 
+int GetContainerIdForMouseCursor() {
+#if defined(OS_CHROMEOS)
+  return ash::kShellWindowId_MouseCursorContainer;
+#else
+  NOTIMPLEMENTED();
+  return -1;
+#endif
+}
+
 }  // namespace
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -92,9 +103,8 @@
       capture_ratio_(GetCaptureDisplayInfo().GetDensityRatio()),
       cursor_capture_source_id_(base::UnguessableToken::Create()),
       cursor_capture_weak_ptr_factory_(this) {
-  WMHelperChromeOS* helper = WMHelperChromeOS::GetInstance();
+  WMHelper* helper = WMHelper::GetInstance();
   helper->AddPreTargetHandler(this);
-  helper->AddDisplayConfigurationObserver(this);
   // TODO(sky): CursorClient does not exist in mash
   // yet. https://crbug.com/631103.
   aura::client::CursorClient* cursor_client = helper->GetCursorClient();
@@ -112,8 +122,7 @@
     pinch_delegate_->OnPointerDestroying(this);
   if (relative_pointer_delegate_)
     relative_pointer_delegate_->OnPointerDestroying(this);
-  WMHelperChromeOS* helper = WMHelperChromeOS::GetInstance();
-  helper->RemoveDisplayConfigurationObserver(this);
+  WMHelper* helper = WMHelper::GetInstance();
   helper->RemovePreTargetHandler(this);
   // TODO(sky): CursorClient does not exist in mash
   // yet. https://crbug.com/631103.
@@ -478,6 +487,11 @@
 }
 
 void Pointer::OnCursorDisplayChanged(const display::Display& display) {
+  UpdatePointerSurface(root_surface());
+  auto info = GetCaptureDisplayInfo();
+  capture_scale_ = info.device_scale_factor();
+  capture_ratio_ = info.GetDensityRatio();
+
   auto* cursor_client = WMHelper::GetInstance()->GetCursorClient();
   // TODO(crbug.com/631103): CursorClient does not exist in mash yet.
   if (!cursor_client)
@@ -502,16 +516,6 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// ash::WindowTreeHostManager::Observer overrides:
-
-void Pointer::OnDisplayConfigurationChanged() {
-  UpdatePointerSurface(root_surface());
-  auto info = GetCaptureDisplayInfo();
-  capture_scale_ = info.device_scale_factor();
-  capture_ratio_ = info.GetDensityRatio();
-}
-
-////////////////////////////////////////////////////////////////////////////////
 // Pointer, private:
 
 Surface* Pointer::GetEffectiveTargetForEvent(ui::LocatedEvent* event) const {
@@ -560,7 +564,7 @@
     // snapshot. Where in the tree is not important but we might as well use
     // the cursor container.
     WMHelper::GetInstance()
-        ->GetPrimaryDisplayContainer(ash::kShellWindowId_MouseCursorContainer)
+        ->GetPrimaryDisplayContainer(GetContainerIdForMouseCursor())
         ->AddChild(host_window());
     SetRootSurface(surface);
   }
diff --git a/components/exo/pointer.h b/components/exo/pointer.h
index 124d7505..823adc5 100644
--- a/components/exo/pointer.h
+++ b/components/exo/pointer.h
@@ -7,7 +7,6 @@
 
 #include <memory>
 
-#include "ash/display/window_tree_host_manager.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/optional.h"
@@ -49,8 +48,7 @@
                 public ui::EventHandler,
                 public aura::client::CaptureClientObserver,
                 public aura::client::CursorClientObserver,
-                public aura::client::FocusChangeObserver,
-                public ash::WindowTreeHostManager::Observer {
+                public aura::client::FocusChangeObserver {
  public:
   explicit Pointer(PointerDelegate* delegate);
   ~Pointer() override;
@@ -94,9 +92,6 @@
   void OnWindowFocused(aura::Window* gained_focus,
                        aura::Window* lost_focus) override;
 
-  // Overridden from ash::WindowTreeHostManager::Observer:
-  void OnDisplayConfigurationChanged() override;
-
   // Relative motion registration.
   void RegisterRelativePointerDelegate(RelativePointerDelegate* delegate);
   void UnregisterRelativePointerDelegate(RelativePointerDelegate* delegate);
diff --git a/components/exo/wayland/BUILD.gn b/components/exo/wayland/BUILD.gn
index 86abffd..9cf66989 100644
--- a/components/exo/wayland/BUILD.gn
+++ b/components/exo/wayland/BUILD.gn
@@ -41,6 +41,8 @@
     "wayland_display_output.h",
     "wayland_input_delegate.cc",
     "wayland_input_delegate.h",
+    "wayland_pointer_delegate.cc",
+    "wayland_pointer_delegate.h",
     "wayland_touch_delegate.cc",
     "wayland_touch_delegate.h",
     "wayland_watcher.cc",
@@ -79,8 +81,6 @@
     sources += [
       "wayland_keyboard_delegate.cc",
       "wayland_keyboard_delegate.h",
-      "wayland_pointer_delegate.cc",
-      "wayland_pointer_delegate.h",
       "wayland_positioner.cc",
       "wayland_positioner.h",
       "wl_shell.cc",
diff --git a/components/exo/wayland/wl_seat.cc b/components/exo/wayland/wl_seat.cc
index 8029f43..25178180 100644
--- a/components/exo/wayland/wl_seat.cc
+++ b/components/exo/wayland/wl_seat.cc
@@ -7,15 +7,16 @@
 #include <wayland-server-core.h>
 #include <wayland-server-protocol-core.h>
 
+#include "components/exo/pointer.h"
 #include "components/exo/touch.h"
 #include "components/exo/wayland/server_util.h"
+#include "components/exo/wayland/wayland_pointer_delegate.h"
 #include "components/exo/wayland/wayland_touch_delegate.h"
+#include "ui/base/buildflags.h"
 
 #if defined(OS_CHROMEOS)
 #include "components/exo/keyboard.h"
-#include "components/exo/pointer.h"
 #include "components/exo/wayland/wayland_keyboard_delegate.h"
-#include "components/exo/wayland/wayland_pointer_delegate.h"
 #endif  // defined(OS_CHROMEOS)
 
 namespace exo {
@@ -23,7 +24,6 @@
 
 namespace {
 
-#if defined(OS_CHROMEOS)
 ////////////////////////////////////////////////////////////////////////////////
 // wl_pointer_interface:
 
@@ -45,6 +45,7 @@
 const struct wl_pointer_interface pointer_implementation = {pointer_set_cursor,
                                                             pointer_release};
 
+#if defined(OS_CHROMEOS)
 ////////////////////////////////////////////////////////////////////////////////
 // wl_keyboard_interface:
 
@@ -71,16 +72,12 @@
 // wl_seat_interface:
 
 void seat_get_pointer(wl_client* client, wl_resource* resource, uint32_t id) {
-#if defined(OS_CHROMEOS)
   wl_resource* pointer_resource = wl_resource_create(
       client, &wl_pointer_interface, wl_resource_get_version(resource), id);
 
   SetImplementation(
       pointer_resource, &pointer_implementation,
       std::make_unique<Pointer>(new WaylandPointerDelegate(pointer_resource)));
-#else
-  NOTIMPLEMENTED();
-#endif  // defined(OS_CHROMEOS)
 }
 
 void seat_get_keyboard(wl_client* client, wl_resource* resource, uint32_t id) {
@@ -135,16 +132,11 @@
 
   if (version >= WL_SEAT_NAME_SINCE_VERSION)
     wl_seat_send_name(resource, "default");
-#if defined(OS_CHROMEOS)
   uint32_t capabilities = WL_SEAT_CAPABILITY_POINTER | WL_SEAT_CAPABILITY_TOUCH;
 
-#if BUILDFLAG(USE_XKBCOMMON)
+#if defined(OS_CHROMEOS) && BUILDFLAG(USE_XKBCOMMON)
   capabilities |= WL_SEAT_CAPABILITY_KEYBOARD;
-#endif  // BUILDFLAG(USE_XKBCOMMON)
-
-#else
-  uint32_t capabilities = WL_SEAT_CAPABILITY_TOUCH;
-#endif  // defined(OS_CHROMEOS)
+#endif  // defined(OS_CHROMEOS) && BUILDFLAG(USE_XKBCOMMON)
   wl_seat_send_capabilities(resource, capabilities);
 }
 
diff --git a/components/invalidation/impl/profile_identity_provider.h b/components/invalidation/impl/profile_identity_provider.h
index 3bbfdc73..ab7a0823 100644
--- a/components/invalidation/impl/profile_identity_provider.h
+++ b/components/invalidation/impl/profile_identity_provider.h
@@ -12,8 +12,7 @@
 
 namespace invalidation {
 
-// An identity provider implementation that's backed by
-// ProfileOAuth2TokenService and SigninManager.
+// An identity provider implementation that's backed by IdentityManager
 class ProfileIdentityProvider : public IdentityProvider,
                                 public identity::IdentityManager::Observer {
  public:
diff --git a/components/language/core/common/language_experiments.cc b/components/language/core/common/language_experiments.cc
index d38d2e46..e7cec35 100644
--- a/components/language/core/common/language_experiments.cc
+++ b/components/language/core/common/language_experiments.cc
@@ -27,7 +27,7 @@
     "NotifySyncOnLanguageDetermined", base::FEATURE_DISABLED_BY_DEFAULT};
 
 // Base feature for Translate desktop UI experiment
-const base::Feature kUseButtonTranslateBubbleUI{
+const base::Feature kUseButtonTranslateBubbleUi{
     "UseButtonTranslateBubbleUI", base::FEATURE_DISABLED_BY_DEFAULT};
 
 // Params:
@@ -105,9 +105,9 @@
   return force_trigger_count >= threshold;
 }
 
-TranslateUIBubbleModel GetTranslateUIBubbleModel() {
+TranslateUIBubbleModel GetTranslateUiBubbleModel() {
   std::map<std::string, std::string> params;
-  if (base::GetFieldTrialParamsByFeature(language::kUseButtonTranslateBubbleUI,
+  if (base::GetFieldTrialParamsByFeature(language::kUseButtonTranslateBubbleUi,
                                          &params)) {
     if (params[language::kTranslateUIBubbleKey] ==
         language::kTranslateUIBubbleButtonValue) {
diff --git a/components/language/core/common/language_experiments.h b/components/language/core/common/language_experiments.h
index e7b0e98e..dd600dd 100644
--- a/components/language/core/common/language_experiments.h
+++ b/components/language/core/common/language_experiments.h
@@ -37,7 +37,7 @@
 extern const base::Feature kNotifySyncOnLanguageDetermined;
 
 // This feature uses the existing UI for translate bubble.
-extern const base::Feature kUseButtonTranslateBubbleUI;
+extern const base::Feature kUseButtonTranslateBubbleUi;
 
 // These feature params controls what translate bubble UI to display.
 extern const char kTranslateUIBubbleKey[];
@@ -82,7 +82,7 @@
 
 // Returns which translate bubble UI to use depending on selection in
 // kTranslateUIBubbleKey.
-TranslateUIBubbleModel GetTranslateUIBubbleModel();
+TranslateUIBubbleModel GetTranslateUiBubbleModel();
 }  // namespace language
 
 #endif  // COMPONENTS_LANGUAGE_CORE_COMMON_LANGUAGE_EXPERIMENTS_H_
diff --git a/components/neterror/resources/images/animated_offline_pin.svg b/components/neterror/resources/images/animated_offline_pin.svg
new file mode 100644
index 0000000..8133437
--- /dev/null
+++ b/components/neterror/resources/images/animated_offline_pin.svg
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24" width="24" height="24">
+    <clipPath id="mask">
+      <path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10 10-4.5 10-10S17.5 2 12 2zm5 16H7v-2h10v2zm-6.7-4L7 10.7l1.4-1.4 1.9 1.9 5.3-5.3L17 7.3 10.3 14z" fill="rgb(154, 160, 166)"/>
+    </clipPath>
+    <rect width="24" height="24" x="0" y="0" clip-path="url(#mask)" r="5" fill="rgb(154, 160, 166)" />
+    <rect id="blue" width="24" height="24" x="0" y="0" clip-path="url(#mask)" cx="10" cy="10" r="5" fill="rgb(26,115,232)"/>
+    <style>
+      @keyframes offlineAnimation {
+        0% {height: 0} 35% {height: 0} 60% {height: 100%} 90% {fill-opacity: 1} 100% {fill-opacity: 0}
+      }
+      #blue {
+        animation: offlineAnimation 4s infinite;
+      }
+    </style>
+</svg>
diff --git a/components/neterror/resources/neterror.css b/components/neterror/resources/neterror.css
index f52d8b1..70c9b59 100644
--- a/components/neterror/resources/neterror.css
+++ b/components/neterror/resources/neterror.css
@@ -617,16 +617,34 @@
 }
 
 #cancel-save-page-button {
+  background-image: url(images/animated_offline_pin.svg);
+  background-position: right 27px center;
+  background-repeat: no-repeat;
   border: 1px solid var(--google-gray-300);
   border-radius: 5px;
   color: var(--google-gray-700);
-  padding: 16px;
-  text-align: center;
+  margin-bottom: 26px;
+  padding-bottom: 16px;
+  padding-inline-end: 88px;
+  padding-inline-start: 16px;
+  padding-top: 16px;
+  text-align: start;
+}
+
+html[dir="rtl"] #cancel-save-page-button {
+  background-position: left 27px center;
 }
 
 #save-page-for-later-button {
   display: flex;
-  justify-content: center;
+  justify-content: start;
+}
+
+#save-page-for-later-button a:before {
+  content: url(images/download-blue.svg);
+  display: inline-block;
+  margin-inline-end: 4px;
+  vertical-align: -webkit-baseline-middle;
 }
 
 .hidden#save-page-for-later-button {
diff --git a/components/neterror/resources/neterror.html b/components/neterror/resources/neterror.html
index cad5f15..8412900 100644
--- a/components/neterror/resources/neterror.html
+++ b/components/neterror/resources/neterror.html
@@ -62,6 +62,15 @@
             </div>
           </div>
         </div>
+        <div id="save-page-for-later-button" class="hidden">
+          <a class="link-button" onclick="savePageLaterClick()"
+            jsselect="savePageLater" jscontent="savePageMsg">
+          </a>
+        </div>
+        <div id="cancel-save-page-button" class="hidden"
+          onclick="cancelSavePageClick()" jsselect="savePageLater"
+          jsvalues=".innerHTML:cancelMsg">
+        </div>
         <div id="offline-content-list" class="list-hidden" hidden>
           <div id="offline-content-list-visibility-card"
               onclick="toggleOfflineContentListVisibility(true)">
@@ -101,17 +110,6 @@
             jsselect="downloadButton"
             jscontent="msg" jsvalues=".disabledText:disabledMsg">
         </button>
-        <div id="save-page-for-later-button" class="hidden">
-          <a class="link-button" onclick="savePageLaterClick()"
-            jsselect="savePageLater"
-            jscontent="savePageMsg">
-          </a>
-        </div>
-        <div id="cancel-save-page-button" class="hidden"
-          onclick="cancelSavePageClick()"
-          jsselect="savePageLater"
-          jsvalues=".innerHTML:cancelMsg">
-        </div>
       </div>
       <button id="details-button" class="secondary-button text-button small-link"
          onclick="detailsButtonClick(); toggleHelpBox()" jscontent="details"
diff --git a/components/neterror/resources/neterror.js b/components/neterror/resources/neterror.js
index 4d2830a9c..9776a16 100644
--- a/components/neterror/resources/neterror.js
+++ b/components/neterror/resources/neterror.js
@@ -371,8 +371,7 @@
   // Show or hide control buttons.
   var controlButtonDiv = document.getElementById('control-buttons');
   controlButtonDiv.hidden = offlineContentVisible ||
-      !(reloadButtonVisible || downloadButtonVisible || attemptAutoFetch ||
-        cacheButtonVisible);
+      !(reloadButtonVisible || downloadButtonVisible || cacheButtonVisible);
 }
 
 function onDocumentLoad() {
diff --git a/components/password_manager/core/browser/sync_credentials_filter.h b/components/password_manager/core/browser/sync_credentials_filter.h
index 09bfe3b..eb8197d 100644
--- a/components/password_manager/core/browser/sync_credentials_filter.h
+++ b/components/password_manager/core/browser/sync_credentials_filter.h
@@ -32,7 +32,7 @@
 
   // Implements protection of sync credentials. Uses |client| to get the last
   // commited entry URL for a check against GAIA reauth site. Uses the factory
-  // functions repeatedly to get the sync service and signin manager to pass
+  // functions repeatedly to get the sync service and identity manager to pass
   // them to sync_util methods.
   SyncCredentialsFilter(
       const PasswordManagerClient* client,
diff --git a/components/password_manager/core/browser/sync_username_test_base.cc b/components/password_manager/core/browser/sync_username_test_base.cc
index dadb8a20..86e4ec9 100644
--- a/components/password_manager/core/browser/sync_username_test_base.cc
+++ b/components/password_manager/core/browser/sync_username_test_base.cc
@@ -15,11 +15,10 @@
 SyncUsernameTestBase::~SyncUsernameTestBase() = default;
 
 void SyncUsernameTestBase::FakeSigninAs(const std::string& email) {
-  // This method is called in a roll by some tests. Differently than
-  // SigninManager, IdentityTestEnvironment does not allow logging in
-  // without a previously log-out.
-  // So make sure tests only log in once and that the email is the same
-  // in case of FakeSigninAs calls roll.
+  // This method is called in a roll by some tests. IdentityTestEnvironment does
+  // not allow logging in without a previously log-out.
+  // So make sure tests only log in once and that the email is the same in case
+  // of FakeSigninAs calls roll.
   identity::IdentityManager* identity_manager =
       identity_test_env_.identity_manager();
   if (identity_manager->HasPrimaryAccount()) {
diff --git a/components/password_manager/core/browser/sync_username_test_base.h b/components/password_manager/core/browser/sync_username_test_base.h
index 0b1b4b1..09ac897c 100644
--- a/components/password_manager/core/browser/sync_username_test_base.h
+++ b/components/password_manager/core/browser/sync_username_test_base.h
@@ -23,7 +23,7 @@
   SyncUsernameTestBase();
   ~SyncUsernameTestBase() override;
 
-  // Instruct the signin manager to sign in with |email| or out.
+  // Instruct the identity manager to sign in with |email| or out.
   void FakeSigninAs(const std::string& email);
 
   // Produce a sample PasswordForm.
diff --git a/components/previews/content/hint_cache_store.cc b/components/previews/content/hint_cache_store.cc
index 529b1d95..4ef0a37 100644
--- a/components/previews/content/hint_cache_store.cc
+++ b/components/previews/content/hint_cache_store.cc
@@ -329,6 +329,59 @@
                      weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
 }
 
+void HintCacheStore::PurgeExpiredFetchedHints() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  if (!IsAvailable()) {
+    return;
+  }
+
+  // Load all the fetched hints to check their expiry times.
+  database_->LoadKeysAndEntriesWithFilter(
+      base::BindRepeating(&DatabasePrefixFilter,
+                          GetFetchedHintEntryKeyPrefix()),
+      base::BindOnce(&HintCacheStore::OnLoadFetchedHintsToPurgeExpired,
+                     weak_ptr_factory_.GetWeakPtr()));
+}
+
+void HintCacheStore::OnLoadFetchedHintsToPurgeExpired(
+    bool success,
+    std::unique_ptr<EntryMap> fetched_entries) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  if (!success) {
+    return;
+  }
+
+  auto keys_to_remove = std::make_unique<EntryKeySet>();
+  int64_t now_since_epoch =
+      base::Time::Now().ToDeltaSinceWindowsEpoch().InSeconds();
+
+  for (const auto& entry : *fetched_entries) {
+    if (entry.second.expiry_time_secs() <= now_since_epoch) {
+      keys_to_remove->insert(entry.first);
+    }
+  }
+
+  // TODO(mcrouse): Record the number of hints that will be expired from the
+  // store.
+
+  data_update_in_flight_ = true;
+  hint_entry_keys_.reset();
+
+  auto empty_entries = std::make_unique<EntryVector>();
+
+  database_->UpdateEntriesWithRemoveFilter(
+      std::move(empty_entries),
+      base::BindRepeating(
+          [](EntryKeySet* keys_to_remove, const std::string& key) {
+            return keys_to_remove->find(key) != keys_to_remove->end();
+          },
+          keys_to_remove.get()),
+      base::BindOnce(&HintCacheStore::OnUpdateHints,
+                     weak_ptr_factory_.GetWeakPtr(), base::DoNothing::Once()));
+}
+
 bool HintCacheStore::FindHintEntryKey(const std::string& host,
                                       EntryKey* out_hint_entry_key) const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/components/previews/content/hint_cache_store.h b/components/previews/content/hint_cache_store.h
index 94aaa9d0..07da278 100644
--- a/components/previews/content/hint_cache_store.h
+++ b/components/previews/content/hint_cache_store.h
@@ -138,15 +138,11 @@
   // Updates the fetched hints contained in the store, including the
   // metadata entry. The callback is run asynchronously after the database
   // stores the hints.
-  //
-  // TODO(mcrouse): When called, fetched hints in the store that have expired
-  // specified by |expiry_time_secs| will be purged and only the new hints and
-  // non-expired hints are retained.
   void UpdateFetchedHints(std::unique_ptr<HintUpdateData> fetched_hints_data,
                           base::OnceClosure callback);
 
   // Removes fetched hint store entries from |this|. |hint_entry_keys_| is
-  // updated after the removing fetched hint entries are removed.
+  // updated after the fetched hint entries are removed.
   void ClearFetchedHintsFromDatabase();
 
   // Finds the most specific hint entry key for the specified host. Returns
@@ -167,6 +163,11 @@
   // |this| is not available, base::Time() is returned.
   base::Time FetchedHintsUpdateTime() const;
 
+  // Removes all fetched hints that have expired from the store.
+  // |hint_entry_keys| is updated after the expired fetched hints are
+  // removed.
+  void PurgeExpiredFetchedHints();
+
  private:
   friend class HintCacheStoreTest;
   friend class HintUpdateData;
@@ -254,6 +255,12 @@
       EntryKey* out_entry_key,
       const EntryKeyPrefix& hint_entry_key_prefix) const;
 
+  // Callback that identifies any expired hints from |fetched_entries| and
+  // asynchronously removes them from the store.
+  void OnLoadFetchedHintsToPurgeExpired(
+      bool success,
+      std::unique_ptr<EntryMap> fetched_entries);
+
   // Callback that runs after the database finishes being initialized. If
   // |purge_existing_data| is true, then unconditionally purges the database;
   // otherwise, triggers loading of the metadata.
diff --git a/components/previews/content/hint_cache_store_unittest.cc b/components/previews/content/hint_cache_store_unittest.cc
index 2afb1ed..5c260000 100644
--- a/components/previews/content/hint_cache_store_unittest.cc
+++ b/components/previews/content/hint_cache_store_unittest.cc
@@ -224,6 +224,17 @@
     db()->LoadCallback(true);
   }
 
+  void PurgeExpiredFetchedHints() {
+    hint_store()->PurgeExpiredFetchedHints();
+
+    // OnFetchedHintsLoadedToMaybePurge
+    db()->LoadCallback(true);
+    // OnUpdateHints
+    db()->UpdateCallback(true);
+    // OnLoadHintEntryKeys callback
+    db()->LoadCallback(true);
+  }
+
   bool IsMetadataSchemaEntryKeyPresent() const {
     return IsKeyPresent(HintCacheStore::GetMetadataTypeEntryKey(
         HintCacheStore::MetadataType::kSchema));
@@ -1367,6 +1378,72 @@
   EXPECT_EQ(hint_entry_key, "3_domain1.org");
 }
 
+TEST_F(HintCacheStoreTest, FetchHintsPurgeExpiredFetchedHints) {
+  base::HistogramTester histogram_tester;
+  MetadataSchemaState schema_state = MetadataSchemaState::kValid;
+  size_t initial_hint_count = 10;
+  base::Time update_time = base::Time().Now();
+  SeedInitialData(schema_state, initial_hint_count);
+  CreateDatabase();
+  InitializeStore(schema_state);
+
+  base::Version version("2.0.0");
+  std::unique_ptr<HintUpdateData> update_data =
+      hint_store()->MaybeCreateUpdateDataForComponentHints(
+          base::Version(kUpdateComponentVersion));
+  ASSERT_TRUE(update_data);
+
+  optimization_guide::proto::Hint hint1;
+  hint1.set_key("domain1.org");
+  hint1.set_key_representation(optimization_guide::proto::HOST_SUFFIX);
+  update_data->MoveHintIntoUpdateData(std::move(hint1));
+  optimization_guide::proto::Hint hint2;
+  hint2.set_key("host.domain2.org");
+  hint2.set_key_representation(optimization_guide::proto::HOST_SUFFIX);
+  update_data->MoveHintIntoUpdateData(std::move(hint2));
+
+  UpdateComponentHints(std::move(update_data));
+
+  // Add fetched hints to the store that overlap with the same hosts as the
+  // initial set.
+  update_data = hint_store()->CreateUpdateDataForFetchedHints(
+      update_time, update_time + base::TimeDelta().FromDays(7));
+
+  optimization_guide::proto::Hint fetched_hint1;
+  fetched_hint1.set_key("domain2.org");
+  fetched_hint1.set_key_representation(optimization_guide::proto::HOST_SUFFIX);
+  update_data->MoveHintIntoUpdateData(std::move(fetched_hint1));
+  optimization_guide::proto::Hint fetched_hint2;
+  fetched_hint2.set_key("domain3.org");
+  fetched_hint2.set_key_representation(optimization_guide::proto::HOST_SUFFIX);
+  update_data->MoveHintIntoUpdateData(std::move(fetched_hint2));
+
+  UpdateFetchedHints(std::move(update_data));
+
+  // Add expired fetched hints to the store.
+  update_data = hint_store()->CreateUpdateDataForFetchedHints(
+      update_time, update_time - base::TimeDelta().FromDays(7));
+
+  optimization_guide::proto::Hint fetched_hint3;
+  fetched_hint1.set_key("domain4.org");
+  fetched_hint1.set_key_representation(optimization_guide::proto::HOST_SUFFIX);
+  update_data->MoveHintIntoUpdateData(std::move(fetched_hint1));
+  optimization_guide::proto::Hint fetched_hint4;
+  fetched_hint2.set_key("domain5.org");
+  fetched_hint2.set_key_representation(optimization_guide::proto::HOST_SUFFIX);
+  update_data->MoveHintIntoUpdateData(std::move(fetched_hint2));
+
+  UpdateFetchedHints(std::move(update_data));
+
+  PurgeExpiredFetchedHints();
+
+  HintCacheStore::EntryKey hint_entry_key;
+  EXPECT_FALSE(hint_store()->FindHintEntryKey("domain4.org", &hint_entry_key));
+  EXPECT_FALSE(hint_store()->FindHintEntryKey("domain5.org", &hint_entry_key));
+  EXPECT_TRUE(hint_store()->FindHintEntryKey("domain2.org", &hint_entry_key));
+  EXPECT_TRUE(hint_store()->FindHintEntryKey("domain3.org", &hint_entry_key));
+}
+
 TEST_F(HintCacheStoreTest, LoadingHintUpdatesPrefCorrectly) {
   base::HistogramTester histogram_tester;
 
diff --git a/components/previews/content/previews_optimization_guide.cc b/components/previews/content/previews_optimization_guide.cc
index 0de616a..3496445 100644
--- a/components/previews/content/previews_optimization_guide.cc
+++ b/components/previews/content/previews_optimization_guide.cc
@@ -362,6 +362,7 @@
   hints_fetch_timer_.Start(
       FROM_HERE, hint_cache_->FetchedHintsUpdateTime() - time_clock_->Now(),
       this, &PreviewsOptimizationGuide::ScheduleHintsFetch);
+  // TODO(mcrouse): Purge hints now that new fetched hints have been stored.
 }
 
 void PreviewsOptimizationGuide::UpdateHints(
diff --git a/components/search_provider_logos/DEPS b/components/search_provider_logos/DEPS
index 538cf8f..c825848 100644
--- a/components/search_provider_logos/DEPS
+++ b/components/search_provider_logos/DEPS
@@ -7,8 +7,8 @@
   # see https://groups.google.com/a/chromium.org/d/msg/chromium-dev/dgFLuxqZt1o/iEqkyoQQBwAJ for help and info.
   "!components/signin/core/browser/fake_profile_oauth2_token_service.h",
   "-components/signin/core/browser/profile_oauth2_token_service.h",
-  "-components/signin/core/browser/signin_manager.h",
-  "-components/signin/core/browser/signin_manager_base.h",
+  "-components/signin/core/browser/primary_account_manager.h",
+  "-components/signin/core/browser/primary_account_policy_manager.h",
   "+components/sync_preferences/testing_pref_service_syncable.h",
   "+net",
   "+services/identity/public/cpp",
diff --git a/components/signin/core/browser/BUILD.gn b/components/signin/core/browser/BUILD.gn
index b33e0a0..5bbd4e0 100644
--- a/components/signin/core/browser/BUILD.gn
+++ b/components/signin/core/browser/BUILD.gn
@@ -85,22 +85,22 @@
     "oauth_multilogin_helper.h",
     "oauth_multilogin_token_fetcher.cc",
     "oauth_multilogin_token_fetcher.h",
+    "primary_account_manager.cc",
+    "primary_account_manager.h",
+    "primary_account_policy_manager.cc",
+    "primary_account_policy_manager.h",
     "profile_oauth2_token_service.cc",
     "profile_oauth2_token_service.h",
     "profile_oauth2_token_service_delegate_chromeos.cc",
     "profile_oauth2_token_service_delegate_chromeos.h",
     "signin_client.cc",
     "signin_client.h",
-    "signin_manager.cc",
-    "signin_manager.h",
-    "signin_manager_base.cc",
-    "signin_manager_base.h",
     "ubertoken_fetcher_impl.cc",
     "ubertoken_fetcher_impl.h",
   ]
 
   if (is_chromeos) {
-    sources -= [ "signin_manager.cc" ]
+    sources -= [ "primary_account_policy_manager.cc" ]
   }
 
   deps = [
@@ -281,11 +281,11 @@
     "mutable_profile_oauth2_token_service_delegate_unittest.cc",
     "oauth_multilogin_helper_unittest.cc",
     "oauth_multilogin_token_fetcher_unittest.cc",
+    "primary_account_manager_unittest.cc",
     "profile_oauth2_token_service_delegate_chromeos_unittest.cc",
     "signin_error_controller_unittest.cc",
     "signin_header_helper_unittest.cc",
     "signin_investigator_unittest.cc",
-    "signin_manager_unittest.cc",
     "signin_metrics_unittest.cc",
     "signin_status_metrics_provider_unittest.cc",
     "ubertoken_fetcher_impl_unittest.cc",
@@ -317,7 +317,7 @@
   if (is_chromeos) {
     sources -= [
       "account_investigator_unittest.cc",
-      "signin_manager_unittest.cc",
+      "primary_account_manager_unittest.cc",
       "signin_status_metrics_provider_unittest.cc",
     ]
 
diff --git a/components/signin/core/browser/about_signin_internals.cc b/components/signin/core/browser/about_signin_internals.cc
index 496e6c1d..af75dc7 100644
--- a/components/signin/core/browser/about_signin_internals.cc
+++ b/components/signin/core/browser/about_signin_internals.cc
@@ -228,8 +228,6 @@
 
 // static
 void AboutSigninInternals::RegisterPrefs(PrefRegistrySimple* user_prefs) {
-  // SigninManager information for about:signin-internals.
-
   // TODO(rogerta): leaving untimed fields here for now because legacy
   // profiles still have these prefs.  In three or four version from M43
   // we can probably remove them.
diff --git a/components/signin/core/browser/account_fetcher_service.cc b/components/signin/core/browser/account_fetcher_service.cc
index 5158a250..050d117 100644
--- a/components/signin/core/browser/account_fetcher_service.cc
+++ b/components/signin/core/browser/account_fetcher_service.cc
@@ -146,9 +146,9 @@
 
 // Child account status is refreshed through invalidations which are only
 // available for the primary account. Finding the primary account requires a
-// dependency on signin_manager which we get around by only allowing a single
-// account. This is possible since we only support a single account to be a
-// child anyway.
+// dependency on PrimaryAccountManager which we get around by only allowing a
+// single account. This is possible since we only support a single account to be
+// a child anyway.
 #if defined(OS_ANDROID)
 void AccountFetcherService::UpdateChildInfo() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/components/signin/core/browser/account_reconcilor_unittest.cc b/components/signin/core/browser/account_reconcilor_unittest.cc
index a1d22a5..64509b2c 100644
--- a/components/signin/core/browser/account_reconcilor_unittest.cc
+++ b/components/signin/core/browser/account_reconcilor_unittest.cc
@@ -2209,13 +2209,13 @@
 }
 
 // This test is needed until chrome changes to use gaia obfuscated id.
-// The signin manager and token service use the gaia "email" property, which
-// preserves dots in usernames and preserves case. gaia::ParseListAccountsData()
-// however uses gaia "displayEmail" which does not preserve case, and then
-// passes the string through gaia::CanonicalizeEmail() which removes dots.  This
-// tests makes sure that an email like "Dot.S@hmail.com", as seen by the
-// token service, will be considered the same as "dots@gmail.com" as returned
-// by gaia::ParseListAccountsData().
+// The primary account manager and token service use the gaia "email" property,
+// which preserves dots in usernames and preserves case.
+// gaia::ParseListAccountsData() however uses gaia "displayEmail" which does not
+// preserve case, and then passes the string through gaia::CanonicalizeEmail()
+// which removes dots.  This tests makes sure that an email like
+// "Dot.S@hmail.com", as seen by the token service, will be considered the same
+// as "dots@gmail.com" as returned by gaia::ParseListAccountsData().
 TEST_P(AccountReconcilorMirrorEndpointParamTest, StartReconcileNoopWithDots) {
   if (identity_test_env()->identity_manager()->GetAccountIdMigrationState() !=
       identity::IdentityManager::AccountIdMigrationState::
diff --git a/components/signin/core/browser/account_tracker_service.cc b/components/signin/core/browser/account_tracker_service.cc
index bef465a4..1368511e 100644
--- a/components/signin/core/browser/account_tracker_service.cc
+++ b/components/signin/core/browser/account_tracker_service.cc
@@ -24,7 +24,6 @@
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/scoped_user_pref_update.h"
 #include "components/signin/core/browser/account_info_util.h"
-#include "components/signin/core/browser/signin_manager_base.h"
 #include "components/signin/core/browser/signin_pref_names.h"
 
 #if defined(OS_ANDROID)
diff --git a/components/signin/core/browser/identity_manager_wrapper.cc b/components/signin/core/browser/identity_manager_wrapper.cc
index fab2d43..506de5e 100644
--- a/components/signin/core/browser/identity_manager_wrapper.cc
+++ b/components/signin/core/browser/identity_manager_wrapper.cc
@@ -15,7 +15,7 @@
     std::unique_ptr<AccountTrackerService> account_tracker_service,
     std::unique_ptr<ProfileOAuth2TokenService> token_service,
     std::unique_ptr<GaiaCookieManagerService> gaia_cookie_manager_service,
-    std::unique_ptr<SigninManagerBase> signin_manager,
+    std::unique_ptr<PrimaryAccountManager> primary_account_manager,
     std::unique_ptr<AccountFetcherService> account_fetcher_service,
     std::unique_ptr<identity::PrimaryAccountMutator> primary_account_mutator,
     std::unique_ptr<identity::AccountsMutator> accounts_mutator,
@@ -24,7 +24,7 @@
     : identity::IdentityManager(std::move(account_tracker_service),
                                 std::move(token_service),
                                 std::move(gaia_cookie_manager_service),
-                                std::move(signin_manager),
+                                std::move(primary_account_manager),
                                 std::move(account_fetcher_service),
                                 std::move(primary_account_mutator),
                                 std::move(accounts_mutator),
diff --git a/components/signin/core/browser/identity_manager_wrapper.h b/components/signin/core/browser/identity_manager_wrapper.h
index b1c0324..c733c7d 100644
--- a/components/signin/core/browser/identity_manager_wrapper.h
+++ b/components/signin/core/browser/identity_manager_wrapper.h
@@ -8,12 +8,11 @@
 #include "components/keyed_service/core/keyed_service.h"
 #include "services/identity/public/cpp/identity_manager.h"
 
-class ProfileOAuth2TokenService;
-class SigninManagerBase;
-class GaiaCookieManagerService;
 class AccountFetcherService;
-class SigninManagerBase;
 class AccountsMutator;
+class GaiaCookieManagerService;
+class PrimaryAccountManager;
+class ProfileOAuth2TokenService;
 
 namespace identity {
 class PrimaryAccountMutator;
@@ -31,7 +30,7 @@
       std::unique_ptr<AccountTrackerService> account_tracker_service,
       std::unique_ptr<ProfileOAuth2TokenService> token_service,
       std::unique_ptr<GaiaCookieManagerService> gaia_cookie_manager_service,
-      std::unique_ptr<SigninManagerBase> signin_manager,
+      std::unique_ptr<PrimaryAccountManager> primary_account_manager,
       std::unique_ptr<AccountFetcherService> account_fetcher_service,
       std::unique_ptr<identity::PrimaryAccountMutator> primary_account_mutator,
       std::unique_ptr<identity::AccountsMutator> accounts_mutator,
diff --git a/components/signin/core/browser/identity_utils.h b/components/signin/core/browser/identity_utils.h
index 241066b..6427ac2 100644
--- a/components/signin/core/browser/identity_utils.h
+++ b/components/signin/core/browser/identity_utils.h
@@ -19,18 +19,17 @@
 namespace identity {
 
 // Returns true if the username is allowed based on the pattern string.
-//
-// NOTE: Can be moved to //services/identity/public/cpp once SigninManager is
-// moved to //services/identity.
 bool IsUsernameAllowedByPattern(base::StringPiece username,
                                 base::StringPiece pattern);
 
 // Returns true if the username is either allowed based on a pattern registered
 // as |pattern_pref_name| with the preferences service referenced by |prefs|,
 // or if such pattern can't be retrieved from |prefs|. This is a legacy
-// method intended to be used to migrate from SigninManager::IsAllowedUsername()
-// only while SigninManager::Initialize() can still accept a null PrefService*,
-// and can be removed once that's no longer the case (see crbug.com/908121).
+// method intended to be used to migrate from
+// PrimaryAccountPolicyManager::IsAllowedUsername() only while
+// PrimaryAccountPolicyManager::Initialize() can still accept a null
+// PrefService*, and can be removed once that's no longer the case (see
+// crbug.com/908121).
 bool LegacyIsUsernameAllowedByPatternFromPrefs(
     PrefService* prefs,
     const std::string& username,
diff --git a/components/signin/core/browser/mutable_profile_oauth2_token_service_delegate_unittest.cc b/components/signin/core/browser/mutable_profile_oauth2_token_service_delegate_unittest.cc
index 265b8572..29c92e4 100644
--- a/components/signin/core/browser/mutable_profile_oauth2_token_service_delegate_unittest.cc
+++ b/components/signin/core/browser/mutable_profile_oauth2_token_service_delegate_unittest.cc
@@ -25,9 +25,9 @@
 #include "components/signin/core/browser/account_consistency_method.h"
 #include "components/signin/core/browser/account_info.h"
 #include "components/signin/core/browser/device_id_helper.h"
+#include "components/signin/core/browser/primary_account_manager.h"
 #include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "components/signin/core/browser/signin_buildflags.h"
-#include "components/signin/core/browser/signin_manager_base.h"
 #include "components/signin/core/browser/signin_pref_names.h"
 #include "components/signin/core/browser/test_signin_client.h"
 #include "components/signin/core/browser/webdata/token_web_data.h"
@@ -105,7 +105,7 @@
     MutableProfileOAuth2TokenServiceDelegate::RegisterProfilePrefs(
         pref_service_.registry());
     AccountTrackerService::RegisterPrefs(pref_service_.registry());
-    SigninManagerBase::RegisterProfilePrefs(pref_service_.registry());
+    PrimaryAccountManager::RegisterProfilePrefs(pref_service_.registry());
     client_.reset(new TestSigninClient(&pref_service_));
     client_->GetTestURLLoaderFactory()->AddResponse(
         GaiaUrls::GetInstance()->oauth2_revoke_url().spec(), "");
diff --git a/components/signin/core/browser/oauth2_token_service_delegate_android.cc b/components/signin/core/browser/oauth2_token_service_delegate_android.cc
index 5281817b..e927be9 100644
--- a/components/signin/core/browser/oauth2_token_service_delegate_android.cc
+++ b/components/signin/core/browser/oauth2_token_service_delegate_android.cc
@@ -355,7 +355,8 @@
       account_tracker_service_->RemoveAccount(info.account_id);
   }
 
-  // No need to wait for SigninManager to finish migration if not signed in.
+  // No need to wait for PrimaryAccountManager to finish migration if not signed
+  // in.
   if (account_tracker_service_->GetMigrationState() ==
           AccountTrackerService::MIGRATION_IN_PROGRESS &&
       signed_in_account_id.empty()) {
diff --git a/components/signin/core/browser/signin_manager_base.cc b/components/signin/core/browser/primary_account_manager.cc
similarity index 89%
rename from components/signin/core/browser/signin_manager_base.cc
rename to components/signin/core/browser/primary_account_manager.cc
index cad29c2..2b4d399 100644
--- a/components/signin/core/browser/signin_manager_base.cc
+++ b/components/signin/core/browser/primary_account_manager.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 "components/signin/core/browser/signin_manager_base.h"
+#include "components/signin/core/browser/primary_account_manager.h"
 
 #include <string>
 #include <vector>
@@ -25,7 +25,7 @@
 #include "google_apis/gaia/gaia_constants.h"
 #include "google_apis/gaia/gaia_urls.h"
 
-SigninManagerBase::SigninManagerBase(
+PrimaryAccountManager::PrimaryAccountManager(
     SigninClient* client,
     ProfileOAuth2TokenService* token_service,
     AccountTrackerService* account_tracker_service,
@@ -39,14 +39,14 @@
   DCHECK(account_tracker_service_);
 }
 
-SigninManagerBase::~SigninManagerBase() {
+PrimaryAccountManager::~PrimaryAccountManager() {
   DCHECK(!observer_);
 
   token_service_->RemoveObserver(this);
 }
 
 // static
-void SigninManagerBase::RegisterProfilePrefs(PrefRegistrySimple* registry) {
+void PrimaryAccountManager::RegisterProfilePrefs(PrefRegistrySimple* registry) {
   registry->RegisterStringPref(prefs::kGoogleServicesHostedDomain,
                                std::string());
   registry->RegisterStringPref(prefs::kGoogleServicesLastAccountId,
@@ -68,12 +68,12 @@
 }
 
 // static
-void SigninManagerBase::RegisterPrefs(PrefRegistrySimple* registry) {
+void PrimaryAccountManager::RegisterPrefs(PrefRegistrySimple* registry) {
   registry->RegisterStringPref(prefs::kGoogleServicesUsernamePattern,
                                std::string());
 }
 
-void SigninManagerBase::Initialize(PrefService* local_state) {
+void PrimaryAccountManager::Initialize(PrefService* local_state) {
   // Should never call Initialize() twice.
   DCHECK(!IsInitialized());
   initialized_ = true;
@@ -162,23 +162,24 @@
   token_service_->LoadCredentials(GetAuthenticatedAccountId());
 }
 
-void SigninManagerBase::FinalizeInitBeforeLoadingRefreshTokens(
+void PrimaryAccountManager::FinalizeInitBeforeLoadingRefreshTokens(
     PrefService* local_state) {}
 
-bool SigninManagerBase::IsInitialized() const {
+bool PrimaryAccountManager::IsInitialized() const {
   return initialized_;
 }
 
-AccountInfo SigninManagerBase::GetAuthenticatedAccountInfo() const {
+AccountInfo PrimaryAccountManager::GetAuthenticatedAccountInfo() const {
   return account_tracker_service_->GetAccountInfo(GetAuthenticatedAccountId());
 }
 
-const CoreAccountId& SigninManagerBase::GetAuthenticatedAccountId() const {
+const CoreAccountId& PrimaryAccountManager::GetAuthenticatedAccountId() const {
   return authenticated_account_id_;
 }
 
-void SigninManagerBase::SetAuthenticatedAccountInfo(const std::string& gaia_id,
-                                                    const std::string& email) {
+void PrimaryAccountManager::SetAuthenticatedAccountInfo(
+    const std::string& gaia_id,
+    const std::string& email) {
   DCHECK(!gaia_id.empty());
   DCHECK(!email.empty());
 
@@ -187,7 +188,7 @@
   SetAuthenticatedAccountId(account_id);
 }
 
-void SigninManagerBase::SetAuthenticatedAccountId(
+void PrimaryAccountManager::SetAuthenticatedAccountId(
     const CoreAccountId& account_id) {
   DCHECK(!account_id.empty());
   if (!authenticated_account_id_.empty()) {
@@ -233,29 +234,29 @@
   }
 }
 
-void SigninManagerBase::ClearAuthenticatedAccountId() {
+void PrimaryAccountManager::ClearAuthenticatedAccountId() {
   authenticated_account_id_ = CoreAccountId();
   if (observer_) {
     observer_->AuthenticatedAccountCleared();
   }
 }
 
-bool SigninManagerBase::IsAuthenticated() const {
+bool PrimaryAccountManager::IsAuthenticated() const {
   return !authenticated_account_id_.empty();
 }
 
-void SigninManagerBase::SetObserver(Observer* observer) {
+void PrimaryAccountManager::SetObserver(Observer* observer) {
   DCHECK(!observer_) << "SetObserver shouldn't be called multiple times.";
   observer_ = observer;
 }
 
-void SigninManagerBase::ClearObserver() {
+void PrimaryAccountManager::ClearObserver() {
   DCHECK(observer_);
   observer_ = nullptr;
 }
 
 #if !defined(OS_CHROMEOS)
-void SigninManagerBase::SignIn(const std::string& username) {
+void PrimaryAccountManager::SignIn(const std::string& username) {
   AccountInfo info = account_tracker_service_->FindAccountInfoByEmail(username);
   DCHECK(!info.gaia.empty());
   DCHECK(!info.email.empty());
@@ -275,7 +276,7 @@
                                    signin_client()->GetInstallDate());
 }
 
-void SigninManagerBase::SignOut(
+void PrimaryAccountManager::SignOut(
     signin_metrics::ProfileSignout signout_source_metric,
     signin_metrics::SignoutDelete signout_delete_metric) {
   RemoveAccountsOption remove_option =
@@ -285,32 +286,32 @@
   StartSignOut(signout_source_metric, signout_delete_metric, remove_option);
 }
 
-void SigninManagerBase::SignOutAndRemoveAllAccounts(
+void PrimaryAccountManager::SignOutAndRemoveAllAccounts(
     signin_metrics::ProfileSignout signout_source_metric,
     signin_metrics::SignoutDelete signout_delete_metric) {
   StartSignOut(signout_source_metric, signout_delete_metric,
                RemoveAccountsOption::kRemoveAllAccounts);
 }
 
-void SigninManagerBase::SignOutAndKeepAllAccounts(
+void PrimaryAccountManager::SignOutAndKeepAllAccounts(
     signin_metrics::ProfileSignout signout_source_metric,
     signin_metrics::SignoutDelete signout_delete_metric) {
   StartSignOut(signout_source_metric, signout_delete_metric,
                RemoveAccountsOption::kKeepAllAccounts);
 }
 
-void SigninManagerBase::StartSignOut(
+void PrimaryAccountManager::StartSignOut(
     signin_metrics::ProfileSignout signout_source_metric,
     signin_metrics::SignoutDelete signout_delete_metric,
     RemoveAccountsOption remove_option) {
   signin_client()->PreSignOut(
-      base::BindOnce(&SigninManagerBase::OnSignoutDecisionReached,
+      base::BindOnce(&PrimaryAccountManager::OnSignoutDecisionReached,
                      base::Unretained(this), signout_source_metric,
                      signout_delete_metric, remove_option),
       signout_source_metric);
 }
 
-void SigninManagerBase::OnSignoutDecisionReached(
+void PrimaryAccountManager::OnSignoutDecisionReached(
     signin_metrics::ProfileSignout signout_source_metric,
     signin_metrics::SignoutDelete signout_delete_metric,
     RemoveAccountsOption remove_option,
@@ -356,13 +357,13 @@
       VLOG(0) << "Revoking all refresh tokens on server. Reason: sign out";
       token_service_->RevokeAllCredentials(
           signin_metrics::SourceForRefreshTokenOperation::
-              kSigninManager_ClearPrimaryAccount);
+              kPrimaryAccountManager_ClearAccount);
       break;
     case RemoveAccountsOption::kRemoveAuthenticatedAccountIfInError:
       if (token_service_->RefreshTokenHasError(account_id))
         token_service_->RevokeCredentials(
             account_id, signin_metrics::SourceForRefreshTokenOperation::
-                            kSigninManager_ClearPrimaryAccount);
+                            kPrimaryAccountManager_ClearAccount);
       break;
     case RemoveAccountsOption::kKeepAllAccounts:
       // Do nothing.
@@ -372,13 +373,14 @@
   FireGoogleSignedOut(account_info);
 }
 
-void SigninManagerBase::FireGoogleSignedOut(const AccountInfo& account_info) {
+void PrimaryAccountManager::FireGoogleSignedOut(
+    const AccountInfo& account_info) {
   if (observer_ != nullptr) {
     observer_->GoogleSignedOut(account_info);
   }
 }
 
-void SigninManagerBase::OnRefreshTokensLoaded() {
+void PrimaryAccountManager::OnRefreshTokensLoaded() {
   token_service_->RemoveObserver(this);
 
   if (account_tracker_service_->GetMigrationState() ==
diff --git a/components/signin/core/browser/signin_manager_base.h b/components/signin/core/browser/primary_account_manager.h
similarity index 76%
rename from components/signin/core/browser/signin_manager_base.h
rename to components/signin/core/browser/primary_account_manager.h
index 4ee0ea5..2596c7b2 100644
--- a/components/signin/core/browser/signin_manager_base.h
+++ b/components/signin/core/browser/primary_account_manager.h
@@ -2,26 +2,21 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
-// The signin manager encapsulates some functionality tracking
-// which user is signed in.
+// The PrimaryAccountManager encapsulates some functionality tracking
+// which account is the primary one.
 //
-// **NOTE** on semantics of SigninManager:
+// **NOTE** on semantics of PrimaryAccountManager:
 //
 // Once a signin is successful, the username becomes "established" and will not
 // be cleared until a SignOut operation is performed (persists across
-// restarts). Until that happens, the signin manager can still be used to
-// refresh credentials, but changing the username is not permitted.
+// restarts). Until that happens, the primary account manager can still be used
+// to refresh credentials, but changing the username is not permitted.
 //
-// On Chrome OS, because of the existence of other components that handle login
-// and signin at a higher level, all that is needed from a SigninManager is
-// caching / handling of the "authenticated username" field, and TokenService
-// initialization, so that components that depend on these two things
-// (i.e on desktop) can continue using it / don't need to change. For this
-// reason, SigninManagerBase is all that exists on Chrome OS. For desktop,
-// see signin/signin_manager.h.
+// On ChromeOS signout is not possible, so that functionality is if-def'd out on
+// that platform.
 
-#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_MANAGER_BASE_H_
-#define COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_MANAGER_BASE_H_
+#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_PRIMARY_ACCOUNT_MANAGER_H_
+#define COMPONENTS_SIGNIN_CORE_BROWSER_PRIMARY_ACCOUNT_MANAGER_H_
 
 #include <memory>
 #include <string>
@@ -45,7 +40,7 @@
 class ProfileOAuth2TokenService;
 class SigninClient;
 
-class SigninManagerBase : public OAuth2TokenService::Observer {
+class PrimaryAccountManager : public OAuth2TokenService::Observer {
  public:
   class Observer {
    public:
@@ -57,31 +52,31 @@
     virtual void GoogleSignedOut(const AccountInfo& account_info) {}
 
     // Called during the signin as soon as
-    // SigninManagerBase::authenticated_account_id_ is set.
+    // PrimaryAccountManager::authenticated_account_id_ is set.
     virtual void AuthenticatedAccountSet(const AccountInfo& account_info) {}
 
     // Called during the signout as soon as
-    // SigninManagerBase::authenticated_account_id_ is cleared.
+    // PrimaryAccountManager::authenticated_account_id_ is cleared.
     virtual void AuthenticatedAccountCleared() {}
 
    protected:
     virtual ~Observer() {}
   };
 
-// On non-ChromeOS platforms, SigninManagerBase should only be instantiated
-// via the derived SigninManager class, as the codewise assumes the
-// invariant that any SigninManagerBase object can be cast to a
-// SigninManager object when not on ChromeOS. Make the constructor private
-// and add SigninManager as a friend to support this.
-// TODO(952766): Eliminate this once SigninManager and SigninManagerBase are
-// merged.
+// On non-ChromeOS platforms, PrimaryAccountManager should only be instantiated
+// via the derived PrimaryAccountPolicyManager class, as the codewise assumes
+// the invariant that any PrimaryAccountManager object can be cast to a
+// PrimaryAccountPolicyManager object when not on ChromeOS. Make the constructor
+// private and add PrimaryAccountPolicyManager as a friend to support this.
+// TODO(952766): Eliminate this once the functionality of PrimaryAccountManager
+// and PrimaryAccountPolicyManager is merged.
 #if !defined(OS_CHROMEOS)
  private:
 #endif
-  SigninManagerBase(SigninClient* client,
-                    ProfileOAuth2TokenService* token_service,
-                    AccountTrackerService* account_tracker_service,
-                    signin::AccountConsistencyMethod account_consistency);
+  PrimaryAccountManager(SigninClient* client,
+                        ProfileOAuth2TokenService* token_service,
+                        AccountTrackerService* account_tracker_service,
+                        signin::AccountConsistencyMethod account_consistency);
 #if !defined(OS_CHROMEOS)
  public:
 #endif
@@ -98,7 +93,7 @@
   };
 #endif
 
-  ~SigninManagerBase() override;
+  ~PrimaryAccountManager() override;
 
   // Registers per-profile prefs.
   static void RegisterProfilePrefs(PrefRegistrySimple* registry);
@@ -138,7 +133,7 @@
   // Methods to set or clear the observer of signin.
   // In practice these should only be used by IdentityManager.
   // NOTE: If SetObserver is called, ClearObserver should be called before
-  // the destruction of SigninManagerBase.
+  // the destruction of PrimaryAccountManager.
   void SetObserver(Observer* observer);
   void ClearObserver();
 
@@ -146,8 +141,8 @@
   // TODO(https://crbug.com/814787): Go through this API to set the primary
   // account on ChromeOS.
 #if !defined(OS_CHROMEOS)
-  // Signs a user in. SigninManager assumes that |username| can be used to look
-  // up the corresponding account_id and gaia_id for this email.
+  // Signs a user in. PrimaryAccountPolicyManager assumes that |username| can be
+  // used to look up the corresponding account_id and gaia_id for this email.
   void SignIn(const std::string& username);
 #endif
 
@@ -187,10 +182,10 @@
   virtual void FinalizeInitBeforeLoadingRefreshTokens(PrefService* local_state);
 
  private:
-  // Added only to allow SigninManager to call the SigninManagerBase
-  // constructor while disallowing any ad-hoc subclassing of
-  // SigninManagerBase.
-  friend class SigninManager;
+  // Added only to allow PrimaryAccountPolicyManager to call the
+  // PrimaryAccountManager constructor while disallowing any ad-hoc subclassing
+  // of PrimaryAccountManager.
+  friend class PrimaryAccountPolicyManager;
 
   // Sets the authenticated user's account id.
   // If the user is already authenticated with the same account id, then this
@@ -202,9 +197,9 @@
   void SetAuthenticatedAccountId(const CoreAccountId& account_id);
 
   // Clears the authenticated user's account id.
-  // This method is not public because SigninManagerBase does not allow signing
-  // out by default. Subclasses implementing a sign-out functionality need to
-  // call this.
+  // This method is not public because PrimaryAccountManager does not allow
+  // signing out by default. Subclasses implementing a sign-out functionality
+  // need to call this.
   void ClearAuthenticatedAccountId();
 
 #if !defined(OS_CHROMEOS)
@@ -249,7 +244,7 @@
 
   signin::AccountConsistencyMethod account_consistency_;
 
-  DISALLOW_COPY_AND_ASSIGN(SigninManagerBase);
+  DISALLOW_COPY_AND_ASSIGN(PrimaryAccountManager);
 };
 
-#endif  // COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_MANAGER_BASE_H_
+#endif  // COMPONENTS_SIGNIN_CORE_BROWSER_PRIMARY_ACCOUNT_MANAGER_H_
diff --git a/components/signin/core/browser/signin_manager_unittest.cc b/components/signin/core/browser/primary_account_manager_unittest.cc
similarity index 87%
rename from components/signin/core/browser/signin_manager_unittest.cc
rename to components/signin/core/browser/primary_account_manager_unittest.cc
index c3ca8c9..286b0c2 100644
--- a/components/signin/core/browser/signin_manager_unittest.cc
+++ b/components/signin/core/browser/primary_account_manager_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 "components/signin/core/browser/signin_manager.h"
+#include "components/signin/core/browser/primary_account_policy_manager.h"
 
 #include <memory>
 #include <utility>
@@ -35,11 +35,13 @@
 
 namespace {
 
-class TestSigninManagerObserver : public SigninManagerBase::Observer {
+class TestPrimaryAccountManagerObserver
+    : public PrimaryAccountManager::Observer {
  public:
-  TestSigninManagerObserver() : num_successful_signins_(0), num_signouts_(0) {}
+  TestPrimaryAccountManagerObserver()
+      : num_successful_signins_(0), num_signouts_(0) {}
 
-  ~TestSigninManagerObserver() override {}
+  ~TestPrimaryAccountManagerObserver() override {}
 
   int num_successful_signins_;
   int num_signouts_;
@@ -56,9 +58,9 @@
 
 }  // namespace
 
-class SigninManagerTest : public testing::Test {
+class PrimaryAccountManagerTest : public testing::Test {
  public:
-  SigninManagerTest()
+  PrimaryAccountManagerTest()
       : test_signin_client_(&user_prefs_),
         token_service_(&user_prefs_,
                        std::make_unique<FakeOAuth2TokenServiceDelegate>()),
@@ -66,15 +68,15 @@
     AccountFetcherService::RegisterPrefs(user_prefs_.registry());
     AccountTrackerService::RegisterPrefs(user_prefs_.registry());
     ProfileOAuth2TokenService::RegisterProfilePrefs(user_prefs_.registry());
-    SigninManagerBase::RegisterProfilePrefs(user_prefs_.registry());
-    SigninManagerBase::RegisterPrefs(local_state_.registry());
+    PrimaryAccountManager::RegisterProfilePrefs(user_prefs_.registry());
+    PrimaryAccountManager::RegisterPrefs(local_state_.registry());
     account_tracker_.Initialize(&user_prefs_, base::FilePath());
     account_fetcher_.Initialize(
         &test_signin_client_, &token_service_, &account_tracker_,
         std::make_unique<image_fetcher::FakeImageDecoder>());
   }
 
-  ~SigninManagerTest() override {
+  ~PrimaryAccountManagerTest() override {
     if (manager_) {
       ShutDownManager();
     }
@@ -91,18 +93,19 @@
   PrefService* prefs() { return &user_prefs_; }
 
   // Seed the account tracker with information from logged in user.  Normally
-  // this is done by UI code before calling SigninManager.  Returns the string
-  // to use as the account_id.
+  // this is done by UI code before calling PrimaryAccountPolicyManager.
+  // Returns the string to use as the account_id.
   std::string AddToAccountTracker(const std::string& gaia_id,
                                   const std::string& email) {
     account_tracker_.SeedAccountInfo(gaia_id, email);
     return account_tracker_.PickAccountIdForAccount(gaia_id, email);
   }
 
-  // Create a naked signin manager if integration with PKSs is not needed.
-  void CreateSigninManager() {
+  // Create a naked primary account manager if integration with PKSs is not
+  // needed.
+  void CreatePrimaryAccountManager() {
     DCHECK(!manager_);
-    manager_ = std::make_unique<SigninManager>(
+    manager_ = std::make_unique<PrimaryAccountPolicyManager>(
         &test_signin_client_, &token_service_, &account_tracker_,
         account_consistency_);
     manager_->Initialize(&local_state_);
@@ -135,15 +138,15 @@
   ProfileOAuth2TokenService token_service_;
   AccountTrackerService account_tracker_;
   AccountFetcherService account_fetcher_;
-  std::unique_ptr<SigninManager> manager_;
-  TestSigninManagerObserver test_observer_;
+  std::unique_ptr<PrimaryAccountPolicyManager> manager_;
+  TestPrimaryAccountManagerObserver test_observer_;
   std::vector<std::string> oauth_tokens_fetched_;
   std::vector<std::string> cookies_;
   signin::AccountConsistencyMethod account_consistency_;
 };
 
-TEST_F(SigninManagerTest, SignOut) {
-  CreateSigninManager();
+TEST_F(PrimaryAccountManagerTest, SignOut) {
+  CreatePrimaryAccountManager();
   std::string main_account_id =
       AddToAccountTracker("account_id", "user@gmail.com");
   manager_->SignIn("user@gmail.com");
@@ -154,14 +157,14 @@
   EXPECT_TRUE(manager_->GetAuthenticatedAccountId().empty());
   // Should not be persisted anymore
   ShutDownManager();
-  CreateSigninManager();
+  CreatePrimaryAccountManager();
   EXPECT_FALSE(manager_->IsAuthenticated());
   EXPECT_TRUE(manager_->GetAuthenticatedAccountInfo().email.empty());
   EXPECT_TRUE(manager_->GetAuthenticatedAccountId().empty());
 }
 
-TEST_F(SigninManagerTest, SignOutRevoke) {
-  CreateSigninManager();
+TEST_F(PrimaryAccountManagerTest, SignOutRevoke) {
+  CreatePrimaryAccountManager();
   std::string main_account_id =
       AddToAccountTracker("main_id", "user@gmail.com");
   std::string other_account_id =
@@ -180,9 +183,9 @@
   EXPECT_TRUE(token_service_.GetAccounts().empty());
 }
 
-TEST_F(SigninManagerTest, SignOutDiceNoRevoke) {
+TEST_F(PrimaryAccountManagerTest, SignOutDiceNoRevoke) {
   account_consistency_ = signin::AccountConsistencyMethod::kDice;
-  CreateSigninManager();
+  CreatePrimaryAccountManager();
   std::string main_account_id =
       AddToAccountTracker("main_id", "user@gmail.com");
   std::string other_account_id =
@@ -203,9 +206,9 @@
   EXPECT_EQ(expected_tokens, token_service_.GetAccounts());
 }
 
-TEST_F(SigninManagerTest, SignOutDiceWithError) {
+TEST_F(PrimaryAccountManagerTest, SignOutDiceWithError) {
   account_consistency_ = signin::AccountConsistencyMethod::kDice;
-  CreateSigninManager();
+  CreatePrimaryAccountManager();
   std::string main_account_id =
       AddToAccountTracker("main_id", "user@gmail.com");
   std::string other_account_id =
@@ -233,8 +236,8 @@
   EXPECT_EQ(expected_tokens, token_service_.GetAccounts());
 }
 
-TEST_F(SigninManagerTest, SignOutWhileProhibited) {
-  CreateSigninManager();
+TEST_F(PrimaryAccountManagerTest, SignOutWhileProhibited) {
+  CreatePrimaryAccountManager();
   EXPECT_FALSE(manager_->IsAuthenticated());
   EXPECT_TRUE(manager_->GetAuthenticatedAccountInfo().email.empty());
   EXPECT_TRUE(manager_->GetAuthenticatedAccountId().empty());
@@ -250,10 +253,10 @@
   EXPECT_FALSE(manager_->IsAuthenticated());
 }
 
-TEST_F(SigninManagerTest, Prohibited) {
+TEST_F(PrimaryAccountManagerTest, Prohibited) {
   local_state_.SetString(prefs::kGoogleServicesUsernamePattern,
                          ".*@google.com");
-  CreateSigninManager();
+  CreatePrimaryAccountManager();
   EXPECT_TRUE(manager_->IsAllowedUsername("test@google.com"));
   EXPECT_TRUE(manager_->IsAllowedUsername("happy@google.com"));
   EXPECT_FALSE(manager_->IsAllowedUsername("test@invalid.com"));
@@ -261,11 +264,11 @@
   EXPECT_FALSE(manager_->IsAllowedUsername(std::string()));
 }
 
-TEST_F(SigninManagerTest, TestAlternateWildcard) {
+TEST_F(PrimaryAccountManagerTest, TestAlternateWildcard) {
   // Test to make sure we accept "*@google.com" as a pattern (treat it as if
   // the admin entered ".*@google.com").
   local_state_.SetString(prefs::kGoogleServicesUsernamePattern, "*@google.com");
-  CreateSigninManager();
+  CreatePrimaryAccountManager();
   EXPECT_TRUE(manager_->IsAllowedUsername("test@google.com"));
   EXPECT_TRUE(manager_->IsAllowedUsername("happy@google.com"));
   EXPECT_FALSE(manager_->IsAllowedUsername("test@invalid.com"));
@@ -273,21 +276,21 @@
   EXPECT_FALSE(manager_->IsAllowedUsername(std::string()));
 }
 
-TEST_F(SigninManagerTest, ProhibitedAtStartup) {
+TEST_F(PrimaryAccountManagerTest, ProhibitedAtStartup) {
   std::string account_id = AddToAccountTracker("gaia_id", "user@gmail.com");
   user_prefs_.SetString(prefs::kGoogleServicesAccountId, account_id);
   local_state_.SetString(prefs::kGoogleServicesUsernamePattern,
                          ".*@google.com");
-  CreateSigninManager();
+  CreatePrimaryAccountManager();
   // Currently signed in user is prohibited by policy, so should be signed out.
   EXPECT_EQ("", manager_->GetAuthenticatedAccountInfo().email);
   EXPECT_EQ("", manager_->GetAuthenticatedAccountId());
 }
 
-TEST_F(SigninManagerTest, ProhibitedAfterStartup) {
+TEST_F(PrimaryAccountManagerTest, ProhibitedAfterStartup) {
   std::string account_id = AddToAccountTracker("gaia_id", "user@gmail.com");
   user_prefs_.SetString(prefs::kGoogleServicesAccountId, account_id);
-  CreateSigninManager();
+  CreatePrimaryAccountManager();
   EXPECT_EQ("user@gmail.com", manager_->GetAuthenticatedAccountInfo().email);
   EXPECT_EQ(account_id, manager_->GetAuthenticatedAccountId());
   // Update the profile - user should be signed out.
@@ -297,8 +300,8 @@
   EXPECT_EQ("", manager_->GetAuthenticatedAccountId());
 }
 
-TEST_F(SigninManagerTest, ExternalSignIn) {
-  CreateSigninManager();
+TEST_F(PrimaryAccountManagerTest, ExternalSignIn) {
+  CreatePrimaryAccountManager();
   EXPECT_EQ("", manager_->GetAuthenticatedAccountInfo().email);
   EXPECT_EQ("", manager_->GetAuthenticatedAccountId());
   EXPECT_EQ(0, test_observer_.num_successful_signins_);
@@ -310,8 +313,9 @@
   EXPECT_EQ(account_id, manager_->GetAuthenticatedAccountId());
 }
 
-TEST_F(SigninManagerTest, ExternalSignIn_ReauthShouldNotSendNotification) {
-  CreateSigninManager();
+TEST_F(PrimaryAccountManagerTest,
+       ExternalSignIn_ReauthShouldNotSendNotification) {
+  CreatePrimaryAccountManager();
   EXPECT_EQ("", manager_->GetAuthenticatedAccountInfo().email);
   EXPECT_EQ("", manager_->GetAuthenticatedAccountId());
   EXPECT_EQ(0, test_observer_.num_successful_signins_);
@@ -328,21 +332,21 @@
   EXPECT_EQ(account_id, manager_->GetAuthenticatedAccountId());
 }
 
-TEST_F(SigninManagerTest, SigninNotAllowed) {
+TEST_F(PrimaryAccountManagerTest, SigninNotAllowed) {
   std::string user("user@google.com");
   std::string account_id = AddToAccountTracker("gaia_id", user);
   user_prefs_.SetString(prefs::kGoogleServicesAccountId, account_id);
   user_prefs_.SetBoolean(prefs::kSigninAllowed, false);
-  CreateSigninManager();
+  CreatePrimaryAccountManager();
   // Currently signing in is prohibited by policy, so should be signed out.
   EXPECT_EQ("", manager_->GetAuthenticatedAccountInfo().email);
   EXPECT_EQ("", manager_->GetAuthenticatedAccountId());
 }
 
-TEST_F(SigninManagerTest, UpgradeToNewPrefs) {
+TEST_F(PrimaryAccountManagerTest, UpgradeToNewPrefs) {
   user_prefs_.SetString(prefs::kGoogleServicesUsername, "user@gmail.com");
   user_prefs_.SetString(prefs::kGoogleServicesUserAccountId, "account_id");
-  CreateSigninManager();
+  CreatePrimaryAccountManager();
   EXPECT_EQ("user@gmail.com", manager_->GetAuthenticatedAccountInfo().email);
 
   if (account_tracker()->GetMigrationState() ==
@@ -366,13 +370,13 @@
   EXPECT_EQ("account_id", info.gaia);
 }
 
-TEST_F(SigninManagerTest, CanonicalizesPrefs) {
+TEST_F(PrimaryAccountManagerTest, CanonicalizesPrefs) {
   // This unit test is not needed after migrating to gaia id.
   if (account_tracker()->GetMigrationState() ==
       AccountTrackerService::MIGRATION_NOT_STARTED) {
     user_prefs_.SetString(prefs::kGoogleServicesUsername, "user.C@gmail.com");
 
-    CreateSigninManager();
+    CreatePrimaryAccountManager();
     EXPECT_EQ("user.C@gmail.com",
               manager_->GetAuthenticatedAccountInfo().email);
 
@@ -391,7 +395,7 @@
   }
 }
 
-TEST_F(SigninManagerTest, GaiaIdMigration) {
+TEST_F(PrimaryAccountManagerTest, GaiaIdMigration) {
   if (account_tracker()->GetMigrationState() !=
       AccountTrackerService::MIGRATION_NOT_STARTED) {
     std::string email = "user@gmail.com";
@@ -413,14 +417,14 @@
 
     client_prefs->SetString(prefs::kGoogleServicesAccountId, email);
 
-    CreateSigninManager();
+    CreatePrimaryAccountManager();
 
     EXPECT_EQ(gaia_id, manager_->GetAuthenticatedAccountId());
     EXPECT_EQ(gaia_id, user_prefs_.GetString(prefs::kGoogleServicesAccountId));
   }
 }
 
-TEST_F(SigninManagerTest, VeryOldProfileGaiaIdMigration) {
+TEST_F(PrimaryAccountManagerTest, VeryOldProfileGaiaIdMigration) {
   if (account_tracker()->GetMigrationState() !=
       AccountTrackerService::MIGRATION_NOT_STARTED) {
     std::string email = "user@gmail.com";
@@ -443,13 +447,13 @@
     client_prefs->ClearPref(prefs::kGoogleServicesAccountId);
     client_prefs->SetString(prefs::kGoogleServicesUsername, email);
 
-    CreateSigninManager();
+    CreatePrimaryAccountManager();
     EXPECT_EQ(gaia_id, manager_->GetAuthenticatedAccountId());
     EXPECT_EQ(gaia_id, user_prefs_.GetString(prefs::kGoogleServicesAccountId));
   }
 }
 
-TEST_F(SigninManagerTest, GaiaIdMigrationCrashInTheMiddle) {
+TEST_F(PrimaryAccountManagerTest, GaiaIdMigrationCrashInTheMiddle) {
   if (account_tracker()->GetMigrationState() !=
       AccountTrackerService::MIGRATION_NOT_STARTED) {
     std::string email = "user@gmail.com";
@@ -471,7 +475,7 @@
 
     client_prefs->SetString(prefs::kGoogleServicesAccountId, gaia_id);
 
-    CreateSigninManager();
+    CreatePrimaryAccountManager();
     EXPECT_EQ(gaia_id, manager_->GetAuthenticatedAccountId());
     EXPECT_EQ(gaia_id, user_prefs_.GetString(prefs::kGoogleServicesAccountId));
 
diff --git a/components/signin/core/browser/signin_manager.cc b/components/signin/core/browser/primary_account_policy_manager.cc
similarity index 71%
rename from components/signin/core/browser/signin_manager.cc
rename to components/signin/core/browser/primary_account_policy_manager.cc
index 8a62776..3bea908 100644
--- a/components/signin/core/browser/signin_manager.cc
+++ b/components/signin/core/browser/primary_account_policy_manager.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 "components/signin/core/browser/signin_manager.h"
+#include "components/signin/core/browser/primary_account_policy_manager.h"
 
 #include <string>
 #include <vector>
@@ -23,34 +23,36 @@
 #include "google_apis/gaia/google_service_auth_error.h"
 #include "third_party/icu/source/i18n/unicode/regex.h"
 
-SigninManager::SigninManager(
+PrimaryAccountPolicyManager::PrimaryAccountPolicyManager(
     SigninClient* client,
     ProfileOAuth2TokenService* token_service,
     AccountTrackerService* account_tracker_service,
     signin::AccountConsistencyMethod account_consistency)
-    : SigninManagerBase(client,
-                        token_service,
-                        account_tracker_service,
-                        account_consistency),
+    : PrimaryAccountManager(client,
+                            token_service,
+                            account_tracker_service,
+                            account_consistency),
       weak_pointer_factory_(this) {}
 
-SigninManager::~SigninManager() {
+PrimaryAccountPolicyManager::~PrimaryAccountPolicyManager() {
   local_state_pref_registrar_.RemoveAll();
 }
 
-void SigninManager::FinalizeInitBeforeLoadingRefreshTokens(
+void PrimaryAccountPolicyManager::FinalizeInitBeforeLoadingRefreshTokens(
     PrefService* local_state) {
   // local_state can be null during unit tests.
   if (local_state) {
     local_state_pref_registrar_.Init(local_state);
     local_state_pref_registrar_.Add(
         prefs::kGoogleServicesUsernamePattern,
-        base::Bind(&SigninManager::OnGoogleServicesUsernamePatternChanged,
+        base::Bind(&PrimaryAccountPolicyManager::
+                       OnGoogleServicesUsernamePatternChanged,
                    weak_pointer_factory_.GetWeakPtr()));
   }
-  signin_allowed_.Init(prefs::kSigninAllowed, signin_client()->GetPrefs(),
-                       base::Bind(&SigninManager::OnSigninAllowedPrefChanged,
-                                  base::Unretained(this)));
+  signin_allowed_.Init(
+      prefs::kSigninAllowed, signin_client()->GetPrefs(),
+      base::Bind(&PrimaryAccountPolicyManager::OnSigninAllowedPrefChanged,
+                 base::Unretained(this)));
 
   AccountInfo account_info = GetAuthenticatedAccountInfo();
   if (!account_info.account_id.empty() &&
@@ -65,11 +67,11 @@
     // Note: The token service has not yet loaded its credentials, so accounts
     // cannot be revoked here.
     //
-    // On desktop, when SigninManager is initializing, the profile was not yet
-    // marked with sign out allowed. Therefore sign out is not allowed and all
-    // calls to SignOut methods are no-op.
+    // On desktop, when PrimaryAccountManager is initializing, the profile was
+    // not yet marked with sign out allowed. Therefore sign out is not allowed
+    // and all calls to SignOut methods are no-op.
     //
-    // TODO(msarda): SignOut methods do not gurantee that sign out can actually
+    // TODO(msarda): SignOut methods do not guarantee that sign out can actually
     // be done (this depends on whether sign out is allowed). Add a check here
     // on desktop to make it clear that SignOut does not do anything.
     SignOutAndKeepAllAccounts(signin_metrics::SIGNIN_PREF_CHANGED_DURING_SIGNIN,
@@ -77,7 +79,7 @@
   }
 }
 
-void SigninManager::OnGoogleServicesUsernamePatternChanged() {
+void PrimaryAccountPolicyManager::OnGoogleServicesUsernamePatternChanged() {
   if (IsAuthenticated() &&
       !IsAllowedUsername(GetAuthenticatedAccountInfo().email)) {
     // Signed in user is invalid according to the current policy so sign
@@ -87,11 +89,11 @@
   }
 }
 
-bool SigninManager::IsSigninAllowed() const {
+bool PrimaryAccountPolicyManager::IsSigninAllowed() const {
   return signin_allowed_.GetValue();
 }
 
-void SigninManager::OnSigninAllowedPrefChanged() {
+void PrimaryAccountPolicyManager::OnSigninAllowedPrefChanged() {
   if (!IsSigninAllowed() && IsAuthenticated()) {
     VLOG(0) << "IsSigninAllowed() set to false, signing out the user";
     SignOut(signin_metrics::SIGNOUT_PREF_CHANGED,
@@ -99,7 +101,8 @@
   }
 }
 
-bool SigninManager::IsAllowedUsername(const std::string& username) const {
+bool PrimaryAccountPolicyManager::IsAllowedUsername(
+    const std::string& username) const {
   const PrefService* local_state = local_state_pref_registrar_.prefs();
   if (!local_state)
     return true;  // In a unit test with no local state - all names are allowed.
diff --git a/components/signin/core/browser/signin_manager.h b/components/signin/core/browser/primary_account_policy_manager.h
similarity index 63%
rename from components/signin/core/browser/signin_manager.h
rename to components/signin/core/browser/primary_account_policy_manager.h
index d86a3d7..2e054c5 100644
--- a/components/signin/core/browser/signin_manager.h
+++ b/components/signin/core/browser/primary_account_policy_manager.h
@@ -2,19 +2,19 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
-// The signin manager encapsulates some functionality tracking
-// which user is signed in. See SigninManagerBase for full description of
+// The signin manager encapsulates some functionality tracking which user is
+// signed in. See PrimaryAccountManager for full description of
 // responsibilities. The class defined in this file provides functionality
 // required by all platforms except Chrome OS.
 
-#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_MANAGER_H_
-#define COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_MANAGER_H_
+#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_PRIMARY_ACCOUNT_POLICY_MANAGER_H_
+#define COMPONENTS_SIGNIN_CORE_BROWSER_PRIMARY_ACCOUNT_POLICY_MANAGER_H_
 
 #include "build/build_config.h"
 
 #if defined(OS_CHROMEOS)
 
-#include "components/signin/core/browser/signin_manager_base.h"
+#include "components/signin/core/browser/primary_account_manager.h"
 
 #else
 
@@ -32,7 +32,7 @@
 #include "components/prefs/pref_member.h"
 #include "components/signin/core/browser/account_info.h"
 #include "components/signin/core/browser/account_tracker_service.h"
-#include "components/signin/core/browser/signin_manager_base.h"
+#include "components/signin/core/browser/primary_account_manager.h"
 #include "components/signin/core/browser/signin_metrics.h"
 #include "net/cookies/canonical_cookie.h"
 
@@ -43,15 +43,16 @@
 class IdentityManager;
 }  // namespace identity
 
-class SigninManager : public SigninManagerBase {
+class PrimaryAccountPolicyManager : public PrimaryAccountManager {
  public:
-  SigninManager(SigninClient* client,
-                ProfileOAuth2TokenService* token_service,
-                AccountTrackerService* account_tracker_service,
-                signin::AccountConsistencyMethod account_consistency);
-  ~SigninManager() override;
+  PrimaryAccountPolicyManager(
+      SigninClient* client,
+      ProfileOAuth2TokenService* token_service,
+      AccountTrackerService* account_tracker_service,
+      signin::AccountConsistencyMethod account_consistency);
+  ~PrimaryAccountPolicyManager() override;
 
-  // On platforms where SigninManager is responsible for dealing with
+  // On platforms where PrimaryAccountManager is responsible for dealing with
   // invalid username policy updates, we need to check this during
   // initialization and sign the user out.
   void FinalizeInitBeforeLoadingRefreshTokens(
@@ -59,8 +60,8 @@
 
  private:
   friend class identity::IdentityManager;
-  FRIEND_TEST_ALL_PREFIXES(SigninManagerTest, Prohibited);
-  FRIEND_TEST_ALL_PREFIXES(SigninManagerTest, TestAlternateWildcard);
+  FRIEND_TEST_ALL_PREFIXES(PrimaryAccountManagerTest, Prohibited);
+  FRIEND_TEST_ALL_PREFIXES(PrimaryAccountManagerTest, TestAlternateWildcard);
 
   // Returns true if a signin to Chrome is allowed (by policy or pref).
   bool IsSigninAllowed() const;
@@ -78,11 +79,11 @@
   // Helper object to listen for changes to the signin allowed preference.
   BooleanPrefMember signin_allowed_;
 
-  base::WeakPtrFactory<SigninManager> weak_pointer_factory_;
+  base::WeakPtrFactory<PrimaryAccountPolicyManager> weak_pointer_factory_;
 
-  DISALLOW_COPY_AND_ASSIGN(SigninManager);
+  DISALLOW_COPY_AND_ASSIGN(PrimaryAccountPolicyManager);
 };
 
 #endif  // !defined(OS_CHROMEOS)
 
-#endif  // COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_MANAGER_H_
+#endif  // COMPONENTS_SIGNIN_CORE_BROWSER_PRIMARY_ACCOUNT_POLICY_MANAGER_H_
diff --git a/components/signin/core/browser/profile_oauth2_token_service.cc b/components/signin/core/browser/profile_oauth2_token_service.cc
index a5c88b3..3d218a3f 100644
--- a/components/signin/core/browser/profile_oauth2_token_service.cc
+++ b/components/signin/core/browser/profile_oauth2_token_service.cc
@@ -24,10 +24,11 @@
       return "SupervisedUser::InitSync";
     case SourceForRefreshTokenOperation::kInlineLoginHandler_Signin:
       return "InlineLoginHandler::Signin";
-    case SourceForRefreshTokenOperation::kSigninManager_ClearPrimaryAccount:
-      return "SigninManager::ClearPrimaryAccount";
-    case SourceForRefreshTokenOperation::kSigninManager_LegacyPreDiceSigninFlow:
-      return "SigninManager::LegacyPreDiceSigninFlow";
+    case SourceForRefreshTokenOperation::kPrimaryAccountManager_ClearAccount:
+      return "PrimaryAccountManager::ClearAccount";
+    case SourceForRefreshTokenOperation::
+        kPrimaryAccountManager_LegacyPreDiceSigninFlow:
+      return "PrimaryAccountManager::LegacyPreDiceSigninFlow";
     case SourceForRefreshTokenOperation::kUserMenu_RemoveAccount:
       return "UserMenu::RemoveAccount";
     case SourceForRefreshTokenOperation::kUserMenu_SignOutAllAccounts:
diff --git a/components/signin/core/browser/profile_oauth2_token_service.h b/components/signin/core/browser/profile_oauth2_token_service.h
index 92fb1f81..3ab7b7e7 100644
--- a/components/signin/core/browser/profile_oauth2_token_service.h
+++ b/components/signin/core/browser/profile_oauth2_token_service.h
@@ -56,7 +56,8 @@
   // after service is used between profile restarts.
   //
   // The primary account is specified with the |primary_account_id| argument.
-  // For a regular profile, the primary account id comes from SigninManager.
+  // For a regular profile, the primary account id comes from
+  // PrimaryAccountManager.
   // For a supervised user, the id comes from SupervisedUserService.
   void LoadCredentials(const std::string& primary_account_id);
 
diff --git a/components/signin/core/browser/profile_oauth2_token_service_delegate_chromeos.cc b/components/signin/core/browser/profile_oauth2_token_service_delegate_chromeos.cc
index f7bad5a..5ff73d7 100644
--- a/components/signin/core/browser/profile_oauth2_token_service_delegate_chromeos.cc
+++ b/components/signin/core/browser/profile_oauth2_token_service_delegate_chromeos.cc
@@ -233,9 +233,9 @@
 
   // Account insertion:
   // Device Account insertion on Chrome OS happens as a 2 step process:
-  // 1. The account is inserted into SigninManager / AccountTrackerService, via
-  // IdentityManager, with a valid Gaia id and email but an invalid refresh
-  // token.
+  // 1. The account is inserted into PrimaryAccountManager /
+  // AccountTrackerService, via IdentityManager, with a valid Gaia id and email
+  // but an invalid refresh token.
   // 2. This API is called to update the aforementioned account with a valid
   // refresh token.
   // Secondary Account insertion on Chrome OS happens atomically in
diff --git a/components/signin/core/browser/signin_metrics.h b/components/signin/core/browser/signin_metrics.h
index b63c45b9..f7ad995 100644
--- a/components/signin/core/browser/signin_metrics.h
+++ b/components/signin/core/browser/signin_metrics.h
@@ -296,8 +296,8 @@
   kTokenService_LoadCredentials,
   kSupervisedUser_InitSync,
   kInlineLoginHandler_Signin,
-  kSigninManager_ClearPrimaryAccount,
-  kSigninManager_LegacyPreDiceSigninFlow,
+  kPrimaryAccountManager_ClearAccount,
+  kPrimaryAccountManager_LegacyPreDiceSigninFlow,
   kUserMenu_RemoveAccount,
   kUserMenu_SignOutAllAccounts,
   kSettings_Signout,
diff --git a/components/sync/driver/DEPS b/components/sync/driver/DEPS
index 6e0f7ed..73f02757 100644
--- a/components/sync/driver/DEPS
+++ b/components/sync/driver/DEPS
@@ -10,8 +10,8 @@
   # see https://groups.google.com/a/chromium.org/d/msg/chromium-dev/dgFLuxqZt1o/iEqkyoQQBwAJ for help and info.
   "-components/signin/core/browser/fake_profile_oauth2_token_service.h",
   "-components/signin/core/browser/profile_oauth2_token_service.h",
-  "-components/signin/core/browser/signin_manager.h",
-  "-components/signin/core/browser/signin_manager_base.h",
+  "-components/signin/core/browser/primary_account_manager.h",
+  "-components/signin/core/browser/primary_account_policy_manager.h",
   "+components/sync/base",
   "+components/sync/engine",
   "+components/sync/engine_impl",
diff --git a/components/sync/protocol/user_consent_specifics.proto b/components/sync/protocol/user_consent_specifics.proto
index 4f93f8d..0091bccf 100644
--- a/components/sync/protocol/user_consent_specifics.proto
+++ b/components/sync/protocol/user_consent_specifics.proto
@@ -74,7 +74,7 @@
   // redundant.
   //
   // For semantics and usage of the |account_id| in the signin codebase,
-  // see SigninManagerBase::GetAuthenticatedAccountId()
+  // see PrimaryAccountManager::GetAuthenticatedAccountId()
   // or AccountInfo::account_id.
   optional string account_id = 6;
 
diff --git a/components/sync/protocol/user_event_specifics.proto b/components/sync/protocol/user_event_specifics.proto
index 0035a89..7f77388 100644
--- a/components/sync/protocol/user_event_specifics.proto
+++ b/components/sync/protocol/user_event_specifics.proto
@@ -145,7 +145,7 @@
     // redundant.
     //
     // For semantics and usage of the |account_id| in the signin codebase,
-    // see SigninManagerBase::GetAuthenticatedAccountId()
+    // see PrimaryAccountManager::GetAuthenticatedAccountId()
     // or AccountInfo::account_id.
     optional string account_id = 6;
 
diff --git a/components/translate/core/browser/translate_infobar_delegate.cc b/components/translate/core/browser/translate_infobar_delegate.cc
index a22411d..5d230b2 100644
--- a/components/translate/core/browser/translate_infobar_delegate.cc
+++ b/components/translate/core/browser/translate_infobar_delegate.cc
@@ -157,7 +157,6 @@
 }
 
 void TranslateInfoBarDelegate::Translate() {
-  DCHECK_NE(original_language_code(), target_language_code());
   ui_delegate_.Translate();
 }
 
diff --git a/components/translate/core/browser/translate_manager.cc b/components/translate/core/browser/translate_manager.cc
index 42731ab..46fa3d2 100644
--- a/components/translate/core/browser/translate_manager.cc
+++ b/components/translate/core/browser/translate_manager.cc
@@ -275,10 +275,19 @@
         metrics::TranslateEventProto::USER_CONTEXT_MENU_TRANSLATE);
   }
 
-  // Trigger the "translating now" UI.
-  translate_client_->ShowTranslateUI(
-      translate::TRANSLATE_STEP_TRANSLATING, source_lang, target_lang,
-      TranslateErrors::NONE, triggered_from_menu);
+  if (source_lang == target_lang) {
+    // Trigger the "translate error" UI.
+    translate_client_->ShowTranslateUI(
+        translate::TRANSLATE_STEP_TRANSLATE_ERROR, source_lang, target_lang,
+        TranslateErrors::IDENTICAL_LANGUAGES, triggered_from_menu);
+    NotifyTranslateError(TranslateErrors::IDENTICAL_LANGUAGES);
+    return;
+  } else {
+    // Trigger the "translating now" UI.
+    translate_client_->ShowTranslateUI(
+        translate::TRANSLATE_STEP_TRANSLATING, source_lang, target_lang,
+        TranslateErrors::NONE, triggered_from_menu);
+  }
 
   TranslateScript* script = TranslateDownloadManager::GetInstance()->script();
   DCHECK(script != nullptr);
diff --git a/components/upload_list/text_log_upload_list.cc b/components/upload_list/text_log_upload_list.cc
index ee3245a..e18b8f5 100644
--- a/components/upload_list/text_log_upload_list.cc
+++ b/components/upload_list/text_log_upload_list.cc
@@ -34,11 +34,6 @@
 
 TextLogUploadList::~TextLogUploadList() = default;
 
-base::TaskTraits TextLogUploadList::LoadingTaskTraits() {
-  return {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
-          base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN};
-}
-
 std::vector<UploadList::UploadInfo> TextLogUploadList::LoadUploadList() {
   std::vector<UploadInfo> uploads;
 
diff --git a/components/upload_list/text_log_upload_list.h b/components/upload_list/text_log_upload_list.h
index d5ae02ae..98ac183 100644
--- a/components/upload_list/text_log_upload_list.h
+++ b/components/upload_list/text_log_upload_list.h
@@ -30,7 +30,6 @@
   ~TextLogUploadList() override;
 
   // UploadList:
-  base::TaskTraits LoadingTaskTraits() override;
   std::vector<UploadList::UploadInfo> LoadUploadList() override;
   void ClearUploadList(const base::Time& begin, const base::Time& end) override;
 
diff --git a/components/upload_list/upload_list.cc b/components/upload_list/upload_list.cc
index 75f7f050..18e49bc 100644
--- a/components/upload_list/upload_list.cc
+++ b/components/upload_list/upload_list.cc
@@ -10,6 +10,17 @@
 
 #include "base/bind.h"
 #include "base/task/post_task.h"
+#include "base/task/task_traits.h"
+
+namespace {
+
+// USER_VISIBLE because loading uploads blocks chrome://crashes,
+// chrome://webrtc-logs and the feedback UI. See https://crbug.com/972526.
+constexpr base::TaskTraits kLoadingTaskTraits = {
+    base::MayBlock(), base::TaskPriority::USER_BLOCKING,
+    base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN};
+
+}  // namespace
 
 UploadList::UploadInfo::UploadInfo(const std::string& upload_id,
                                    const base::Time& upload_time,
@@ -53,7 +64,7 @@
   DCHECK(sequence_checker_.CalledOnValidSequence());
   load_callback_ = std::move(callback);
   base::PostTaskWithTraitsAndReplyWithResult(
-      FROM_HERE, LoadingTaskTraits(),
+      FROM_HERE, kLoadingTaskTraits,
       base::Bind(&UploadList::LoadUploadList, this),
       base::Bind(&UploadList::OnLoadComplete, this));
 }
@@ -64,7 +75,7 @@
   DCHECK(sequence_checker_.CalledOnValidSequence());
   clear_callback_ = std::move(callback);
   base::PostTaskWithTraitsAndReply(
-      FROM_HERE, LoadingTaskTraits(),
+      FROM_HERE, kLoadingTaskTraits,
       base::BindOnce(&UploadList::ClearUploadList, this, begin, end),
       base::BindOnce(&UploadList::OnClearComplete, this));
 }
@@ -76,7 +87,7 @@
 void UploadList::RequestSingleUploadAsync(const std::string& local_id) {
   DCHECK(sequence_checker_.CalledOnValidSequence());
   base::PostTaskWithTraits(
-      FROM_HERE, LoadingTaskTraits(),
+      FROM_HERE, kLoadingTaskTraits,
       base::BindOnce(&UploadList::RequestSingleUpload, this, local_id));
 }
 
diff --git a/components/upload_list/upload_list.h b/components/upload_list/upload_list.h
index e7cff3fd..7a1a7ea 100644
--- a/components/upload_list/upload_list.h
+++ b/components/upload_list/upload_list.h
@@ -14,7 +14,6 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/sequence_checker.h"
-#include "base/task/task_traits.h"
 #include "base/time/time.h"
 
 // An UploadList is an abstraction over a list of client-side data files that
@@ -91,10 +90,6 @@
  protected:
   virtual ~UploadList();
 
-  // Returns the TaskTraits that should be used for LoadUploadList() and
-  // RequestSingleUpload().
-  virtual base::TaskTraits LoadingTaskTraits() = 0;
-
   // Reads the upload log and stores the entries in |uploads|.
   virtual std::vector<UploadInfo> LoadUploadList() = 0;
 
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
index 5588fba..53c44317 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
+++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
@@ -556,6 +556,9 @@
   if (!MakeCurrent(true /* need_fbo0 */))
     return;
 
+  auto* channel_manager = gpu_service_->gpu_channel_manager();
+  channel_manager->ScheduleGrContextCleanup();
+
   PullTextureUpdates(std::move(sync_tokens));
 
   {
diff --git a/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc b/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc
index c9e23d0..e29ca1e 100644
--- a/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc
+++ b/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc
@@ -54,6 +54,12 @@
   std::unique_ptr<base::DictionaryValue> BuildAccessibilityTreeWithNode(
       AtspiAccessible* node);
 
+  void AddValueProperties(AtkObject* atk_object, base::DictionaryValue* dict);
+  void AddTableProperties(AtkObject* atk_object, base::DictionaryValue* dict);
+  void AddTableCellProperties(const ui::AXPlatformNodeAuraLinux* node,
+                              AtkObject* atk_object,
+                              base::DictionaryValue* dict);
+
   void RecursiveBuildAccessibilityTree(AtspiAccessible* node,
                                        base::DictionaryValue* dict);
   virtual void AddProperties(AtspiAccessible* node,
@@ -318,6 +324,157 @@
     "footnote",  // ATK_ROLE_FOOTNOTE = 122.
 };
 
+void AccessibilityTreeFormatterAuraLinux::AddValueProperties(
+    AtkObject* atk_object,
+    base::DictionaryValue* dict) {
+  if (!ATK_IS_VALUE(atk_object))
+    return;
+
+  auto value_properties = std::make_unique<base::ListValue>();
+  AtkValue* value = ATK_VALUE(atk_object);
+  GValue current = G_VALUE_INIT;
+  g_value_init(&current, G_TYPE_FLOAT);
+  atk_value_get_current_value(value, &current);
+  value_properties->AppendString(
+      base::StringPrintf("current=%f", g_value_get_float(&current)));
+
+  GValue minimum = G_VALUE_INIT;
+  g_value_init(&minimum, G_TYPE_FLOAT);
+  atk_value_get_minimum_value(value, &minimum);
+  value_properties->AppendString(
+      base::StringPrintf("minimum=%f", g_value_get_float(&minimum)));
+
+  GValue maximum = G_VALUE_INIT;
+  g_value_init(&maximum, G_TYPE_FLOAT);
+  atk_value_get_maximum_value(value, &maximum);
+  value_properties->AppendString(
+      base::StringPrintf("maximum=%f", g_value_get_float(&maximum)));
+  dict->Set("value", std::move(value_properties));
+}
+
+void AccessibilityTreeFormatterAuraLinux::AddTableProperties(
+    AtkObject* atk_object,
+    base::DictionaryValue* dict) {
+  if (!ATK_IS_TABLE(atk_object))
+    return;
+
+  // Column details.
+  AtkTable* table = ATK_TABLE(atk_object);
+  int n_cols = atk_table_get_n_columns(table);
+  auto table_properties = std::make_unique<base::ListValue>();
+  table_properties->AppendString(base::StringPrintf("cols=%i", n_cols));
+
+  std::vector<std::string> col_headers;
+  for (int i = 0; i < n_cols; i++) {
+    std::string header = atk_table_get_column_description(table, i);
+    if (!header.empty())
+      col_headers.push_back(base::StringPrintf("'%s'", header.c_str()));
+  }
+
+  if (!col_headers.size())
+    col_headers.push_back("NONE");
+
+  table_properties->AppendString(base::StringPrintf(
+      "headers=(%s);", base::JoinString(col_headers, ", ").c_str()));
+
+  // Row details.
+  int n_rows = atk_table_get_n_rows(table);
+  table_properties->AppendString(base::StringPrintf("rows=%i", n_rows));
+
+  std::vector<std::string> row_headers;
+  for (int i = 0; i < n_rows; i++) {
+    std::string header = atk_table_get_row_description(table, i);
+    if (!header.empty())
+      row_headers.push_back(base::StringPrintf("'%s'", header.c_str()));
+  }
+
+  if (!row_headers.size())
+    row_headers.push_back("NONE");
+
+  table_properties->AppendString(base::StringPrintf(
+      "headers=(%s);", base::JoinString(row_headers, ", ").c_str()));
+
+  // Caption details.
+  AtkObject* caption = atk_table_get_caption(table);
+  table_properties->AppendString(
+      base::StringPrintf("caption=%s;", caption ? "true" : "false"));
+
+  // Summarize information about the cells from the table's perspective here.
+  std::vector<std::string> span_info;
+  for (int r = 0; r < n_rows; r++) {
+    for (int c = 0; c < n_cols; c++) {
+      int row_span = atk_table_get_row_extent_at(table, r, c);
+      int col_span = atk_table_get_column_extent_at(table, r, c);
+      if (row_span != 1 || col_span != 1) {
+        span_info.push_back(base::StringPrintf("cell at %i,%i: %ix%i", r, c,
+                                               row_span, col_span));
+      }
+    }
+  }
+  if (!span_info.size())
+    span_info.push_back("all: 1x1");
+
+  table_properties->AppendString(base::StringPrintf(
+      "spans=(%s)", base::JoinString(span_info, ", ").c_str()));
+  dict->Set("table", std::move(table_properties));
+}
+
+void AccessibilityTreeFormatterAuraLinux::AddTableCellProperties(
+    const ui::AXPlatformNodeAuraLinux* node,
+    AtkObject* atk_object,
+    base::DictionaryValue* dict) {
+  AtkRole role = atk_object_get_role(atk_object);
+  if (role != ATK_ROLE_TABLE_CELL && role != ATK_ROLE_COLUMN_HEADER &&
+      role != ATK_ROLE_ROW_HEADER) {
+    return;
+  }
+
+  int row = 0, col = 0, row_span = 0, col_span = 0;
+  int n_row_headers = 0, n_column_headers = 0;
+
+  // Properties obtained via AtkTableCell, if possible. If we do not have at
+  // least ATK 2.12, use the same logic in our AtkTableCell implementation so
+  // that tests can still be run.
+  auto cell_interface = ui::AtkTableCellInterface::Get();
+  if (cell_interface.has_value()) {
+    AtkTableCell* cell = G_TYPE_CHECK_INSTANCE_CAST(
+        (atk_object), cell_interface->GetType(), AtkTableCell);
+
+    cell_interface->GetRowColumnSpan(cell, &row, &col, &row_span, &col_span);
+
+    GPtrArray* column_headers = cell_interface->GetColumnHeaderCells(cell);
+    n_column_headers = column_headers->len;
+    g_ptr_array_unref(column_headers);
+
+    GPtrArray* row_headers = cell_interface->GetRowHeaderCells(cell);
+    n_row_headers = row_headers->len;
+    g_ptr_array_unref(row_headers);
+  } else {
+    row = node->GetTableRow();
+    col = node->GetTableColumn();
+    row_span = node->GetTableRowSpan();
+    col_span = node->GetTableColumnSpan();
+    if (role == ATK_ROLE_TABLE_CELL) {
+      auto* delegate = node->GetTable()->GetDelegate();
+      n_column_headers = delegate->GetColHeaderNodeIds(col).size();
+      n_row_headers = delegate->GetRowHeaderNodeIds(row).size();
+    }
+  }
+
+  std::vector<std::string> cell_info;
+  cell_info.push_back(base::StringPrintf("row=%i", row));
+  cell_info.push_back(base::StringPrintf("col=%i", col));
+  cell_info.push_back(base::StringPrintf("row_span=%i", row_span));
+  cell_info.push_back(base::StringPrintf("col_span=%i", col_span));
+  cell_info.push_back(base::StringPrintf("n_row_headers=%i", n_row_headers));
+  cell_info.push_back(base::StringPrintf("n_col_headers=%i", n_column_headers));
+
+  auto cell_properties = std::make_unique<base::ListValue>();
+  cell_properties->AppendString(
+      base::StringPrintf("(%s)", base::JoinString(cell_info, ", ").c_str()));
+  dict->Set("cell", std::move(cell_properties));
+}
+
 void AccessibilityTreeFormatterAuraLinux::AddProperties(
     const BrowserAccessibility& node,
     base::DictionaryValue* dict) {
@@ -371,132 +528,9 @@
   atk_attribute_set_free(attributes);
 
   // Properties obtained via AtkValue.
-  auto value_properties = std::make_unique<base::ListValue>();
-  if (ATK_IS_VALUE(atk_object)) {
-    AtkValue* value = ATK_VALUE(atk_object);
-    GValue current = G_VALUE_INIT;
-    g_value_init(&current, G_TYPE_FLOAT);
-    atk_value_get_current_value(value, &current);
-    value_properties->AppendString(
-        base::StringPrintf("current=%f", g_value_get_float(&current)));
-
-    GValue minimum = G_VALUE_INIT;
-    g_value_init(&minimum, G_TYPE_FLOAT);
-    atk_value_get_minimum_value(value, &minimum);
-    value_properties->AppendString(
-        base::StringPrintf("minimum=%f", g_value_get_float(&minimum)));
-
-    GValue maximum = G_VALUE_INIT;
-    g_value_init(&maximum, G_TYPE_FLOAT);
-    atk_value_get_maximum_value(value, &maximum);
-    value_properties->AppendString(
-        base::StringPrintf("maximum=%f", g_value_get_float(&maximum)));
-  }
-  dict->Set("value", std::move(value_properties));
-
-  // Properties obtained via AtkTable.
-  auto table_properties = std::make_unique<base::ListValue>();
-  if (ATK_IS_TABLE(atk_object)) {
-    AtkTable* table = ATK_TABLE(atk_object);
-
-    // Column details.
-    int n_cols = atk_table_get_n_columns(table);
-    table_properties->AppendString(base::StringPrintf("cols=%i", n_cols));
-
-    std::vector<std::string> col_headers;
-    for (int i = 0; i < n_cols; i++) {
-      std::string header = atk_table_get_column_description(table, i);
-      if (!header.empty())
-        col_headers.push_back(base::StringPrintf("'%s'", header.c_str()));
-    }
-
-    if (!col_headers.size())
-      col_headers.push_back("NONE");
-
-    table_properties->AppendString(base::StringPrintf(
-        "headers=(%s);", base::JoinString(col_headers, ", ").c_str()));
-
-    // Row details.
-    int n_rows = atk_table_get_n_rows(table);
-    table_properties->AppendString(base::StringPrintf("rows=%i", n_rows));
-
-    std::vector<std::string> row_headers;
-    for (int i = 0; i < n_rows; i++) {
-      std::string header = atk_table_get_row_description(table, i);
-      if (!header.empty())
-        row_headers.push_back(base::StringPrintf("'%s'", header.c_str()));
-    }
-
-    if (!row_headers.size())
-      row_headers.push_back("NONE");
-
-    table_properties->AppendString(base::StringPrintf(
-        "headers=(%s);", base::JoinString(row_headers, ", ").c_str()));
-
-    // Caption details.
-    AtkObject* caption = atk_table_get_caption(table);
-    table_properties->AppendString(
-        base::StringPrintf("caption=%s;", caption ? "true" : "false"));
-
-    // Summarize information about the cells from the table's perspective here.
-    std::vector<std::string> span_info;
-    for (int r = 0; r < n_rows; r++) {
-      for (int c = 0; c < n_cols; c++) {
-        int row_span = atk_table_get_row_extent_at(table, r, c);
-        int col_span = atk_table_get_column_extent_at(table, r, c);
-        if (row_span != 1 || col_span != 1) {
-          span_info.push_back(base::StringPrintf("cell at %i,%i: %ix%i", r, c,
-                                                 row_span, col_span));
-        }
-      }
-    }
-    if (!span_info.size())
-      span_info.push_back("all: 1x1");
-
-    table_properties->AppendString(base::StringPrintf(
-        "spans=(%s)", base::JoinString(span_info, ", ").c_str()));
-  }
-
-  dict->Set("table", std::move(table_properties));
-
-  // Properties obtained via AtkTableCell, if possible. If we do not have at
-  // least ATK 2.12, use the same logic in our AtkTableCell implementation so
-  // that tests can still be run.
-  auto cell_properties = std::make_unique<base::ListValue>();
-  if (role == ATK_ROLE_TABLE_CELL || role == ATK_ROLE_COLUMN_HEADER ||
-      role == ATK_ROLE_ROW_HEADER) {
-    int row, col, row_span, col_span;
-    int n_row_headers = 0, n_column_headers = 0;
-    auto cell_interface = ui::AtkTableCellInterface::Get();
-    if (cell_interface.has_value()) {
-      AtkTableCell* cell = G_TYPE_CHECK_INSTANCE_CAST(
-          (atk_object), cell_interface->GetType(), AtkTableCell);
-      GPtrArray* column_headers = cell_interface->GetColumnHeaderCells(cell);
-      GPtrArray* row_headers = cell_interface->GetRowHeaderCells(cell);
-      n_column_headers = column_headers->len;
-      n_row_headers = row_headers->len;
-      g_ptr_array_unref(column_headers);
-      g_ptr_array_unref(row_headers);
-      cell_interface->GetRowColumnSpan(cell, &row, &col, &row_span, &col_span);
-    } else {
-      row = ax_platform_node->GetTableRow();
-      col = ax_platform_node->GetTableColumn();
-      row_span = ax_platform_node->GetTableRowSpan();
-      col_span = ax_platform_node->GetTableColumnSpan();
-      if (role == ATK_ROLE_TABLE_CELL) {
-        auto* delegate = ax_platform_node->GetTable()->GetDelegate();
-        n_column_headers = delegate->GetColHeaderNodeIds(col).size();
-        n_row_headers = delegate->GetRowHeaderNodeIds(row).size();
-      }
-    }
-    cell_properties->AppendString(
-        base::StringPrintf("(row=%i, col=%i, row_span=%i, col_span=%i", row,
-                           col, row_span, col_span));
-    cell_properties->AppendString(
-        base::StringPrintf("n_row_headers=%i, n_col_headers=%i)", n_row_headers,
-                           n_column_headers));
-  }
-  dict->Set("cell", std::move(cell_properties));
+  AddValueProperties(atk_object, dict);
+  AddTableProperties(atk_object, dict);
+  AddTableCellProperties(ax_platform_node, atk_object, dict);
 }
 
 void AccessibilityTreeFormatterAuraLinux::AddProperties(
diff --git a/content/browser/cache_storage/cache_storage_context_impl.cc b/content/browser/cache_storage/cache_storage_context_impl.cc
index cc8bfd1..8bad367 100644
--- a/content/browser/cache_storage/cache_storage_context_impl.cc
+++ b/content/browser/cache_storage/cache_storage_context_impl.cc
@@ -11,6 +11,7 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "content/browser/blob_storage/chrome_blob_storage_context.h"
 #include "content/browser/cache_storage/cache_storage_dispatcher_host.h"
+#include "content/browser/cache_storage/cache_storage_quota_client.h"
 #include "content/browser/cache_storage/legacy/legacy_cache_storage_manager.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_task_traits.h"
@@ -50,8 +51,20 @@
 
   task_runner_->PostTask(
       FROM_HERE,
-      base::BindOnce(&CacheStorageContextImpl::CreateCacheStorageManager, this,
-                     user_data_directory, std::move(cache_task_runner),
+      base::BindOnce(
+          &CacheStorageContextImpl::CreateCacheStorageManagerOnTaskRunner, this,
+          user_data_directory, std::move(cache_task_runner),
+          quota_manager_proxy));
+
+  // If our target sequence is the IO thread, then the manager is guaranteed to
+  // be created before this task fires to create the quota clients.  If we are
+  // running with a different target sequence then the quota client code will
+  // get a cross-sequence wrapper that is guaranteed to initialize its internal
+  // SequenceBound<> object after the real manager is created.
+  base::PostTaskWithTraits(
+      FROM_HERE, {BrowserThread::IO},
+      base::BindOnce(&CacheStorageContextImpl::CreateQuotaClientsOnIOThread,
+                     base::WrapRefCounted(this),
                      std::move(quota_manager_proxy)));
 }
 
@@ -147,7 +160,7 @@
   observers_->RemoveObserver(observer);
 }
 
-void CacheStorageContextImpl::CreateCacheStorageManager(
+void CacheStorageContextImpl::CreateCacheStorageManagerOnTaskRunner(
     const base::FilePath& user_data_directory,
     scoped_refptr<base::SequencedTaskRunner> cache_task_runner,
     scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy) {
@@ -156,7 +169,7 @@
   DCHECK(!cache_manager_);
   cache_manager_ = LegacyCacheStorageManager::Create(
       user_data_directory, std::move(cache_task_runner), task_runner_,
-      std::move(quota_manager_proxy), observers_);
+      quota_manager_proxy, observers_);
 }
 
 void CacheStorageContextImpl::ShutdownOnTaskRunner() {
@@ -213,4 +226,15 @@
   }
 }
 
+void CacheStorageContextImpl::CreateQuotaClientsOnIOThread(
+    scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  if (!quota_manager_proxy.get())
+    return;
+  quota_manager_proxy->RegisterClient(new CacheStorageQuotaClient(
+      cache_manager(), CacheStorageOwner::kCacheAPI));
+  quota_manager_proxy->RegisterClient(new CacheStorageQuotaClient(
+      cache_manager(), CacheStorageOwner::kBackgroundFetch));
+}
+
 }  // namespace content
diff --git a/content/browser/cache_storage/cache_storage_context_impl.h b/content/browser/cache_storage/cache_storage_context_impl.h
index d9f1e70..d663c51 100644
--- a/content/browser/cache_storage/cache_storage_context_impl.h
+++ b/content/browser/cache_storage/cache_storage_context_impl.h
@@ -39,8 +39,8 @@
 
 // One instance of this exists per StoragePartition, and services multiple
 // child processes/origins. Most logic is delegated to the owned
-// CacheStorageManager instance, which is only accessed on the IO
-// thread.
+// CacheStorageManager instance, which is only accessed on the target
+// sequence.
 class CONTENT_EXPORT CacheStorageContextImpl : public CacheStorageContext {
  public:
   explicit CacheStorageContextImpl(BrowserContext* browser_context);
@@ -91,7 +91,7 @@
   ~CacheStorageContextImpl() override;
 
  private:
-  void CreateCacheStorageManager(
+  void CreateCacheStorageManagerOnTaskRunner(
       const base::FilePath& user_data_directory,
       scoped_refptr<base::SequencedTaskRunner> cache_task_runner,
       scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy);
@@ -101,6 +101,9 @@
   void SetBlobParametersForCacheOnTaskRunner(
       ChromeBlobStorageContext* blob_storage_context);
 
+  void CreateQuotaClientsOnIOThread(
+      scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy);
+
   // Initialized at construction.
   const scoped_refptr<base::SequencedTaskRunner> task_runner_;
   const scoped_refptr<ObserverList> observers_;
@@ -111,7 +114,7 @@
   // Initialized in Init().
   scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy_;
 
-  // Only accessed on the IO thread.
+  // Only accessed on the target sequence.
   scoped_refptr<CacheStorageManager> cache_manager_;
 
   // Initialized from the UI thread and bound to |task_runner_|.
diff --git a/content/browser/cache_storage/cache_storage_manager_unittest.cc b/content/browser/cache_storage/cache_storage_manager_unittest.cc
index 427e4b9..1b8871a 100644
--- a/content/browser/cache_storage/cache_storage_manager_unittest.cc
+++ b/content/browser/cache_storage/cache_storage_manager_unittest.cc
@@ -2260,8 +2260,8 @@
 
   void SetUp() override {
     CacheStorageManagerTest::SetUp();
-    quota_client_.reset(new CacheStorageQuotaClient(
-        cache_manager_->AsWeakPtr(), CacheStorageOwner::kCacheAPI));
+    quota_client_ = std::make_unique<CacheStorageQuotaClient>(
+        cache_manager_, CacheStorageOwner::kCacheAPI);
   }
 
   void QuotaUsageCallback(base::RunLoop* run_loop, int64_t usage) {
@@ -2432,8 +2432,8 @@
   quota_manager_proxy_->SimulateQuotaManagerDestroyed();
   cache_manager_ =
       LegacyCacheStorageManager::CreateForTesting(cache_manager_.get());
-  quota_client_.reset(new CacheStorageQuotaClient(
-      cache_manager_->AsWeakPtr(), CacheStorageOwner::kCacheAPI));
+  quota_client_ = std::make_unique<CacheStorageQuotaClient>(
+      cache_manager_, CacheStorageOwner::kCacheAPI);
 
   EXPECT_TRUE(QuotaDeleteOriginData(origin1_));
   EXPECT_EQ(0, QuotaGetOriginUsage(origin1_));
diff --git a/content/browser/cache_storage/cache_storage_quota_client.cc b/content/browser/cache_storage/cache_storage_quota_client.cc
index 1c9e74ab..009bbff 100644
--- a/content/browser/cache_storage/cache_storage_quota_client.cc
+++ b/content/browser/cache_storage/cache_storage_quota_client.cc
@@ -12,9 +12,9 @@
 namespace content {
 
 CacheStorageQuotaClient::CacheStorageQuotaClient(
-    base::WeakPtr<CacheStorageManager> cache_manager,
+    scoped_refptr<CacheStorageManager> cache_manager,
     CacheStorageOwner owner)
-    : cache_manager_(cache_manager), owner_(owner) {}
+    : cache_manager_(std::move(cache_manager)), owner_(owner) {}
 
 CacheStorageQuotaClient::~CacheStorageQuotaClient() {}
 
@@ -32,8 +32,7 @@
                                              GetUsageCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  if (!cache_manager_ || !DoesSupport(type) ||
-      !CacheStorageManager::IsValidQuotaOrigin(origin)) {
+  if (!DoesSupport(type) || !CacheStorageManager::IsValidQuotaOrigin(origin)) {
     std::move(callback).Run(0);
     return;
   }
@@ -45,7 +44,7 @@
                                                 GetOriginsCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  if (!cache_manager_ || !DoesSupport(type)) {
+  if (!DoesSupport(type)) {
     std::move(callback).Run(std::set<url::Origin>());
     return;
   }
@@ -58,7 +57,7 @@
                                                 GetOriginsCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  if (!cache_manager_ || !DoesSupport(type)) {
+  if (!DoesSupport(type)) {
     std::move(callback).Run(std::set<url::Origin>());
     return;
   }
@@ -71,11 +70,6 @@
                                                DeletionCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  if (!cache_manager_) {
-    std::move(callback).Run(blink::mojom::QuotaStatusCode::kErrorAbort);
-    return;
-  }
-
   if (!DoesSupport(type) || !CacheStorageManager::IsValidQuotaOrigin(origin)) {
     std::move(callback).Run(blink::mojom::QuotaStatusCode::kOk);
     return;
diff --git a/content/browser/cache_storage/cache_storage_quota_client.h b/content/browser/cache_storage/cache_storage_quota_client.h
index d3c1620..6569550 100644
--- a/content/browser/cache_storage/cache_storage_quota_client.h
+++ b/content/browser/cache_storage/cache_storage_quota_client.h
@@ -18,11 +18,11 @@
 enum class CacheStorageOwner;
 
 // CacheStorageQuotaClient is owned by the QuotaManager. There is one per
-// CacheStorageManager, and therefore one per
-// ServiceWorkerContextCore.
+// CacheStorageManager/CacheStorageOwner tuple.  Created and accessed on
+// the IO thread.
 class CONTENT_EXPORT CacheStorageQuotaClient : public storage::QuotaClient {
  public:
-  CacheStorageQuotaClient(base::WeakPtr<CacheStorageManager> cache_manager,
+  CacheStorageQuotaClient(scoped_refptr<CacheStorageManager> cache_manager,
                           CacheStorageOwner owner);
   ~CacheStorageQuotaClient() override;
 
@@ -45,7 +45,7 @@
   static ID GetIDFromOwner(CacheStorageOwner owner);
 
  private:
-  base::WeakPtr<CacheStorageManager> cache_manager_;
+  scoped_refptr<CacheStorageManager> cache_manager_;
   CacheStorageOwner owner_;
 
   DISALLOW_COPY_AND_ASSIGN(CacheStorageQuotaClient);
diff --git a/content/browser/cache_storage/legacy/legacy_cache_storage_manager.cc b/content/browser/cache_storage/legacy/legacy_cache_storage_manager.cc
index 84874592..eecdcf9 100644
--- a/content/browser/cache_storage/legacy/legacy_cache_storage_manager.cc
+++ b/content/browser/cache_storage/legacy/legacy_cache_storage_manager.cc
@@ -276,7 +276,7 @@
       base::BindOnce(&ListOriginsAndLastModifiedOnTaskRunner, usages_ptr,
                      root_path_, owner),
       base::BindOnce(&LegacyCacheStorageManager::GetAllOriginsUsageGetSizes,
-                     weak_ptr_factory_.GetWeakPtr(), std::move(usages),
+                     base::WrapRefCounted(this), std::move(usages),
                      std::move(callback)));
 }
 
@@ -389,7 +389,7 @@
   cache_storage_map_.erase({origin, owner});
   cache_storage->GetSizeThenCloseAllCaches(
       base::BindOnce(&LegacyCacheStorageManager::DeleteOriginDidClose,
-                     weak_ptr_factory_.GetWeakPtr(), origin, owner,
+                     base::WrapRefCounted(this), origin, owner,
                      std::move(callback), base::WrapUnique(cache_storage)));
 }
 
@@ -441,15 +441,7 @@
       cache_task_runner_(std::move(cache_task_runner)),
       scheduler_task_runner_(std::move(scheduler_task_runner)),
       quota_manager_proxy_(std::move(quota_manager_proxy)),
-      observers_(std::move(observers)),
-      weak_ptr_factory_(this) {
-  if (quota_manager_proxy_.get()) {
-    quota_manager_proxy_->RegisterClient(new CacheStorageQuotaClient(
-        weak_ptr_factory_.GetWeakPtr(), CacheStorageOwner::kCacheAPI));
-    quota_manager_proxy_->RegisterClient(new CacheStorageQuotaClient(
-        weak_ptr_factory_.GetWeakPtr(), CacheStorageOwner::kBackgroundFetch));
-  }
-}
+      observers_(std::move(observers)) {}
 
 // static
 base::FilePath LegacyCacheStorageManager::ConstructOriginPath(
diff --git a/content/browser/cache_storage/legacy/legacy_cache_storage_manager.h b/content/browser/cache_storage/legacy/legacy_cache_storage_manager.h
index 35ddcba3..6160131 100644
--- a/content/browser/cache_storage/legacy/legacy_cache_storage_manager.h
+++ b/content/browser/cache_storage/legacy/legacy_cache_storage_manager.h
@@ -88,10 +88,6 @@
   void NotifyCacheContentChanged(const url::Origin& origin,
                                  const std::string& name);
 
-  base::WeakPtr<CacheStorageManager> AsWeakPtr() {
-    return weak_ptr_factory_.GetWeakPtr();
-  }
-
   base::FilePath root_path() const { return root_path_; }
 
   // This method is called when the last CacheStorageHandle for a particular
@@ -161,7 +157,9 @@
 
   std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_;
 
-  base::WeakPtrFactory<LegacyCacheStorageManager> weak_ptr_factory_;
+  // Do not add a WeakPtrFactory since this class is destroyed via a
+  // cross-thread delete helper.
+
   DISALLOW_COPY_AND_ASSIGN(LegacyCacheStorageManager);
 };
 
diff --git a/content/browser/devtools/protocol/system_info_handler.cc b/content/browser/devtools/protocol/system_info_handler.cc
index 66730f3..b6030a1 100644
--- a/content/browser/devtools/protocol/system_info_handler.cc
+++ b/content/browser/devtools/protocol/system_info_handler.cc
@@ -106,6 +106,10 @@
     in_aux_attributes_ = false;
   }
 
+  void BeginANGLEFeature() override {}
+
+  void EndANGLEFeature() override {}
+
  private:
   protocol::DictionaryValue* dictionary_;
   bool in_aux_attributes_;
diff --git a/content/browser/gpu/gpu_internals_ui.cc b/content/browser/gpu/gpu_internals_ui.cc
index 9c9d6af..b049c96 100644
--- a/content/browser/gpu/gpu_internals_ui.cc
+++ b/content/browser/gpu/gpu_internals_ui.cc
@@ -501,6 +501,23 @@
   }
   return info;
 }
+
+std::unique_ptr<base::ListValue> GetANGLEFeatures() {
+  gpu::GPUInfo gpu_info = GpuDataManagerImpl::GetInstance()->GetGPUInfo();
+  auto angle_features_list = std::make_unique<base::ListValue>();
+  for (const auto& feature : gpu_info.angle_features) {
+    auto angle_feature = std::make_unique<base::DictionaryValue>();
+    angle_feature->SetString("name", feature.name);
+    angle_feature->SetString("category", feature.category);
+    angle_feature->SetString("description", feature.description);
+    angle_feature->SetString("bug", feature.bug);
+    angle_feature->SetString("status", feature.status);
+    angle_features_list->Append(std::move(angle_feature));
+  }
+
+  return angle_features_list;
+}
+
 // This class receives javascript messages from the renderer.
 // Note that the WebUI infrastructure runs on the UI thread, therefore all of
 // this class's methods are expected to run on the UI thread.
@@ -671,6 +688,7 @@
   for (const auto& workaround : GetDriverBugWorkarounds())
     workarounds->AppendString(workaround);
   feature_status->Set("workarounds", std::move(workarounds));
+  feature_status->Set("ANGLEFeatures", GetANGLEFeatures());
   gpu_info_val->Set("featureStatus", std::move(feature_status));
   if (!GpuDataManagerImpl::GetInstance()->IsGpuProcessUsingHardwareGpu()) {
     auto feature_status_for_hardware_gpu =
diff --git a/content/browser/renderer_host/code_cache_host_impl.cc b/content/browser/renderer_host/code_cache_host_impl.cc
index e2a51508..51056a83 100644
--- a/content/browser/renderer_host/code_cache_host_impl.cc
+++ b/content/browser/renderer_host/code_cache_host_impl.cc
@@ -24,7 +24,6 @@
 #include "content/public/common/content_features.h"
 #include "content/public/common/url_constants.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
-#include "net/base/features.h"
 #include "net/base/io_buffer.h"
 #include "third_party/blink/public/common/cache_storage/cache_storage_utils.h"
 #include "url/gurl.h"
@@ -135,30 +134,16 @@
 
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  if (!base::FeatureList::IsEnabled(net::features::kIsolatedCodeCache)) {
-    // Only store Javascript (not WebAssembly) code in the single-keyed cache.
-    if (cache_type == blink::mojom::CodeCacheType::kJavascript) {
-      base::PostTaskWithTraits(
-          FROM_HERE, {BrowserThread::UI},
-          base::BindOnce(&CodeCacheHostImpl::DidGenerateCacheableMetadataOnUI,
-                         render_process_id_, url, expected_response_time,
-                         std::move(data)));
-    } else {
-      mojo::ReportBadMessage("Single-keyed code cache is Javascript only.");
-      return;
-    }
-  } else {
-    GeneratedCodeCache* code_cache = GetCodeCache(cache_type);
-    if (!code_cache)
-      return;
+  GeneratedCodeCache* code_cache = GetCodeCache(cache_type);
+  if (!code_cache)
+    return;
 
-    base::Optional<GURL> origin_lock =
-        GetSecondaryKeyForCodeCache(url, render_process_id_);
-    if (!origin_lock)
-      return;
+  base::Optional<GURL> origin_lock =
+      GetSecondaryKeyForCodeCache(url, render_process_id_);
+  if (!origin_lock)
+    return;
 
-    code_cache->WriteData(url, *origin_lock, expected_response_time, data);
-  }
+  code_cache->WriteData(url, *origin_lock, expected_response_time, data);
 }
 
 void CodeCacheHostImpl::FetchCachedCode(blink::mojom::CodeCacheType cache_type,
@@ -268,25 +253,4 @@
       url, expected_response_time, trace_id, buf, buf_len);
 }
 
-// static
-void CodeCacheHostImpl::DidGenerateCacheableMetadataOnUI(
-    int render_process_id,
-    const GURL& url,
-    base::Time expected_response_time,
-    mojo_base::BigBuffer data) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  RenderProcessHost* host = RenderProcessHost::FromID(render_process_id);
-  if (!host)
-    return;
-
-  // Use the same priority for the metadata write as for script
-  // resources (see defaultPriorityForResourceType() in WebKit's
-  // CachedResource.cpp). Note that WebURLRequest::PriorityMedium
-  // corresponds to net::LOW (see ConvertWebKitPriorityToNetPriority()
-  // in weburlloader_impl.cc).
-  const net::RequestPriority kPriority = net::LOW;
-  host->GetStoragePartition()->GetNetworkContext()->WriteCacheMetadata(
-      url, kPriority, expected_response_time, std::move(data));
-}
-
 }  // namespace content
diff --git a/content/browser/renderer_host/code_cache_host_impl.h b/content/browser/renderer_host/code_cache_host_impl.h
index f80f7ed..74370c1bd 100644
--- a/content/browser/renderer_host/code_cache_host_impl.h
+++ b/content/browser/renderer_host/code_cache_host_impl.h
@@ -83,11 +83,6 @@
                                   int buf_len,
                                   CacheStorageCacheHandle cache_handle,
                                   blink::mojom::CacheStorageError error);
-  static void DidGenerateCacheableMetadataOnUI(
-      int render_process_id,
-      const GURL& url,
-      base::Time expected_response_time,
-      mojo_base::BigBuffer data);
 
   // Our render process host ID, used to bind to the correct render process.
   const int render_process_id_;
diff --git a/content/browser/renderer_host/legacy_render_widget_host_win.cc b/content/browser/renderer_host/legacy_render_widget_host_win.cc
index b781869..1a6f5be 100644
--- a/content/browser/renderer_host/legacy_render_widget_host_win.cc
+++ b/content/browser/renderer_host/legacy_render_widget_host_win.cc
@@ -178,9 +178,13 @@
   if (!features::IsUsingWMPointerForTouch())
     RegisterTouchWindow(hwnd(), TWF_WANTPALM);
 
-  HRESULT hr = ::CreateStdAccessibleObject(hwnd(), OBJID_WINDOW,
-                                           IID_PPV_ARGS(&window_accessible_));
-  DCHECK(SUCCEEDED(hr));
+  HRESULT hr;
+  if (!::switches::IsExperimentalAccessibilityPlatformUIAEnabled()) {
+    hr = ::CreateStdAccessibleObject(hwnd(), OBJID_WINDOW,
+                                     IID_PPV_ARGS(&window_accessible_));
+  } else {
+    hr = S_OK;
+  }
 
   ui::AXMode mode =
       BrowserAccessibilityStateImpl::GetInstance()->GetAccessibilityMode();
diff --git a/content/browser/resources/gpu/info_view.html b/content/browser/resources/gpu/info_view.html
index 1d44f6c..5cbdf82a 100644
--- a/content/browser/resources/gpu/info_view.html
+++ b/content/browser/resources/gpu/info_view.html
@@ -25,6 +25,12 @@
     </ul>
   </div>
 
+  <div class='angle-features-div'>
+    <h3>ANGLE Features</h3>
+    <ul class="angle-features-list">
+    </ul>
+  </div>
+
   <div>
     <h3>Version Information</h3>
     <div id="client-info"></div>
diff --git a/content/browser/resources/gpu/info_view.js b/content/browser/resources/gpu/info_view.js
index 3bd13fa..16bcee8 100644
--- a/content/browser/resources/gpu/info_view.js
+++ b/content/browser/resources/gpu/info_view.js
@@ -97,6 +97,8 @@
       const problemsList = this.querySelector('.problems-list');
       const workaroundsDiv = this.querySelector('.workarounds-div');
       const workaroundsList = this.querySelector('.workarounds-list');
+      const ANGLEFeaturesDiv = this.querySelector('.angle-features-div');
+      const ANGLEFeaturesList = this.querySelector('.angle-features-list');
 
       const basicInfoForHardwareGpuDiv =
           this.querySelector('.basic-info-for-hardware-gpu-div');
@@ -121,11 +123,13 @@
         if (gpuInfo.featureStatus) {
           this.appendFeatureInfo_(
               gpuInfo.featureStatus, featureStatusList, problemsDiv,
-              problemsList, workaroundsDiv, workaroundsList);
+              problemsList, workaroundsDiv, workaroundsList, ANGLEFeaturesDiv,
+              ANGLEFeaturesList);
         } else {
           featureStatusList.textContent = '';
           problemsList.hidden = true;
           workaroundsList.hidden = true;
+          ANGLEFeaturesList.hidden = true;
         }
 
         if (gpuInfo.featureStatusForHardwareGpu) {
@@ -210,7 +214,7 @@
 
     appendFeatureInfo_: function(
         featureInfo, featureStatusList, problemsDiv, problemsList,
-        workaroundsDiv, workaroundsList) {
+        workaroundsDiv, workaroundsList, ANGLEFeaturesDiv, ANGLEFeaturesList) {
       // Feature map
       const featureLabelMap = {
         '2d_canvas': 'Canvas',
@@ -317,6 +321,18 @@
       } else {
         workaroundsDiv.hidden = true;
       }
+
+      if (featureInfo.ANGLEFeatures.length) {
+        ANGLEFeaturesDiv.hidden = false;
+        ANGLEFeaturesList.textContent = '';
+        for (i = 0; i < featureInfo.ANGLEFeatures.length; i++) {
+          const ANGLEFeature = featureInfo.ANGLEFeatures[i];
+          const ANGLEFeatureEl = this.createANGLEFeatureEl_(ANGLEFeature);
+          ANGLEFeaturesList.appendChild(ANGLEFeatureEl);
+        }
+      } else {
+        ANGLEFeaturesDiv.hidden = true;
+      }
     },
 
     createProblemEl_: function(problem) {
@@ -387,6 +403,74 @@
       return problemEl;
     },
 
+    createANGLEFeatureEl_: function(ANGLEFeature) {
+      const ANGLEFeatureEl = document.createElement('li');
+
+      // Name comes first, bolded
+      const name = document.createElement('b');
+      name.textContent = ANGLEFeature.name;
+      ANGLEFeatureEl.appendChild(name);
+
+      // If there's a category, it follows the name in parentheses
+      if (ANGLEFeature.category) {
+        const separator = document.createElement('span');
+        separator.textContent = ' ';
+        ANGLEFeatureEl.appendChild(separator);
+
+        const category = document.createElement('span');
+        category.textContent = '(' + ANGLEFeature.category + ')';
+        ANGLEFeatureEl.appendChild(category);
+      }
+
+      // If there's a bug link, try to parse the crbug/anglebug number
+      if (ANGLEFeature.bug) {
+        const separator = document.createElement('span');
+        separator.textContent = ' ';
+        ANGLEFeatureEl.appendChild(separator);
+
+        const bug = document.createElement('a');
+        if (ANGLEFeature.bug.includes('crbug.com/')) {
+          bug.textContent = ANGLEFeature.bug.match(/\d+/);
+        } else if (ANGLEFeature.bug.includes('anglebug.com/')) {
+          bug.textContent = 'anglebug:' + ANGLEFeature.bug.match(/\d+/);
+        } else {
+          bug.textContent = ANGLEFeature.bug;
+        }
+        bug.href = ANGLEFeature.bug;
+        ANGLEFeatureEl.appendChild(bug);
+      }
+
+      // Follow with a colon, and the status (colored)
+      const separator = document.createElement('span');
+      separator.textContent = ': ';
+      ANGLEFeatureEl.appendChild(separator);
+
+      const status = document.createElement('span');
+      if (ANGLEFeature.status == 'enabled') {
+        status.textContent = 'Enabled';
+        status.classList.add('feature-green');
+      } else {
+        status.textContent = 'Disabled';
+        status.classList.add('feature-red');
+      }
+      ANGLEFeatureEl.appendChild(status);
+
+      // if there's a description, put on new line, italicized
+      if (ANGLEFeature.description) {
+        const brNode = document.createElement('br');
+        ANGLEFeatureEl.appendChild(brNode);
+
+        const iNode = document.createElement('i');
+        ANGLEFeatureEl.appendChild(iNode);
+
+        const description = document.createElement('span');
+        description.textContent = ANGLEFeature.description;
+        iNode.appendChild(description);
+      }
+
+      return ANGLEFeatureEl;
+    },
+
     setText_: function(outputElementId, text) {
       const peg = $(outputElementId);
       peg.textContent = text;
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc
index 68ef3633..a640fbb6 100644
--- a/content/browser/storage_partition_impl.cc
+++ b/content/browser/storage_partition_impl.cc
@@ -60,7 +60,6 @@
 #include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
 #include "mojo/public/cpp/bindings/callback_helpers.h"
-#include "net/base/features.h"
 #include "net/base/net_errors.h"
 #include "net/cookies/canonical_cookie.h"
 #include "net/url_request/url_request_context.h"
@@ -818,30 +817,28 @@
       base::MakeRefCounted<NativeFileSystemManagerImpl>(
           partition->filesystem_context_, blob_context);
 
-  if (base::FeatureList::IsEnabled(net::features::kIsolatedCodeCache)) {
-    GeneratedCodeCacheSettings settings =
-        GetContentClient()->browser()->GetGeneratedCodeCacheSettings(context);
+  GeneratedCodeCacheSettings settings =
+      GetContentClient()->browser()->GetGeneratedCodeCacheSettings(context);
 
-    // For Incognito mode, we should not persist anything on the disk so
-    // we do not create a code cache. Caching the generated code in memory
-    // is not useful, since V8 already maintains one copy in memory.
-    if (!in_memory && settings.enabled()) {
-      partition->generated_code_cache_context_ =
-          base::MakeRefCounted<GeneratedCodeCacheContext>();
+  // For Incognito mode, we should not persist anything on the disk so
+  // we do not create a code cache. Caching the generated code in memory
+  // is not useful, since V8 already maintains one copy in memory.
+  if (!in_memory && settings.enabled()) {
+    partition->generated_code_cache_context_ =
+        base::MakeRefCounted<GeneratedCodeCacheContext>();
 
-      base::FilePath code_cache_path;
-      if (partition_domain.empty()) {
-        code_cache_path = settings.path().AppendASCII("Code Cache");
-      } else {
-        // For site isolated partitions use the config directory.
-        code_cache_path = settings.path()
-                              .Append(relative_partition_path)
-                              .AppendASCII("Code Cache");
-      }
-      DCHECK_GE(settings.size_in_bytes(), 0);
-      partition->GetGeneratedCodeCacheContext()->Initialize(
-          code_cache_path, settings.size_in_bytes());
+    base::FilePath code_cache_path;
+    if (partition_domain.empty()) {
+      code_cache_path = settings.path().AppendASCII("Code Cache");
+    } else {
+      // For site isolated partitions use the config directory.
+      code_cache_path = settings.path()
+                            .Append(relative_partition_path)
+                            .AppendASCII("Code Cache");
     }
+    DCHECK_GE(settings.size_in_bytes(), 0);
+    partition->GetGeneratedCodeCacheContext()->Initialize(
+        code_cache_path, settings.size_in_bytes());
   }
 
   return partition;
diff --git a/content/browser/storage_partition_impl_unittest.cc b/content/browser/storage_partition_impl_unittest.cc
index 39a7d99..1124cb8 100644
--- a/content/browser/storage_partition_impl_unittest.cc
+++ b/content/browser/storage_partition_impl_unittest.cc
@@ -31,7 +31,6 @@
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "content/public/test/test_utils.h"
 #include "content/test/fake_leveldb_database.h"
-#include "net/base/features.h"
 #include "net/base/test_completion_callback.h"
 #include "net/cookies/canonical_cookie.h"
 #include "net/cookies/cookie_store.h"
@@ -1312,10 +1311,6 @@
 }
 
 TEST_F(StoragePartitionImplTest, ClearCodeCache) {
-  base::test::ScopedFeatureList feature_list;
-  feature_list.InitAndEnableFeature(net::features::kIsolatedCodeCache);
-  ASSERT_TRUE(base::FeatureList::IsEnabled(net::features::kIsolatedCodeCache));
-
   StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
       BrowserContext::GetDefaultStoragePartition(browser_context()));
   // Ensure code cache is initialized.
@@ -1347,10 +1342,6 @@
 }
 
 TEST_F(StoragePartitionImplTest, ClearCodeCacheSpecificURL) {
-  base::test::ScopedFeatureList feature_list;
-  feature_list.InitAndEnableFeature(net::features::kIsolatedCodeCache);
-  ASSERT_TRUE(base::FeatureList::IsEnabled(net::features::kIsolatedCodeCache));
-
   StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
       BrowserContext::GetDefaultStoragePartition(browser_context()));
   // Ensure code cache is initialized.
@@ -1388,10 +1379,6 @@
 }
 
 TEST_F(StoragePartitionImplTest, ClearCodeCacheDateRange) {
-  base::test::ScopedFeatureList feature_list;
-  feature_list.InitAndEnableFeature(net::features::kIsolatedCodeCache);
-  ASSERT_TRUE(base::FeatureList::IsEnabled(net::features::kIsolatedCodeCache));
-
   StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
       BrowserContext::GetDefaultStoragePartition(browser_context()));
   // Ensure code cache is initialized.
@@ -1441,11 +1428,7 @@
 
 TEST_F(StoragePartitionImplTest, ClearWasmCodeCache) {
   base::test::ScopedFeatureList feature_list;
-  feature_list.InitWithFeatures(
-      std::vector<base::Feature>(
-          {net::features::kIsolatedCodeCache, blink::features::kWasmCodeCache}),
-      std::vector<base::Feature>());
-  ASSERT_TRUE(base::FeatureList::IsEnabled(net::features::kIsolatedCodeCache));
+  feature_list.InitAndEnableFeature(blink::features::kWasmCodeCache);
   ASSERT_TRUE(base::FeatureList::IsEnabled(blink::features::kWasmCodeCache));
 
   StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
@@ -1479,32 +1462,7 @@
   base::RunLoop().RunUntilIdle();
 }
 
-TEST_F(StoragePartitionImplTest, ClearCodeCacheNoIsolatedCodeCache) {
-  base::test::ScopedFeatureList feature_list;
-  feature_list.InitAndDisableFeature(net::features::kIsolatedCodeCache);
-  ASSERT_FALSE(base::FeatureList::IsEnabled(net::features::kIsolatedCodeCache));
-
-  StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
-      BrowserContext::GetDefaultStoragePartition(browser_context()));
-  base::RunLoop().RunUntilIdle();
-  // We should not create GeneratedCodeCacheContext when IsolatedCodeCache
-  // is disabled.
-  EXPECT_EQ(nullptr, partition->GetGeneratedCodeCacheContext());
-
-  base::RunLoop run_loop;
-  // This shouldn't crash.
-  base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE,
-      base::BindOnce(&ClearCodeCache, partition, base::Time(), base::Time(),
-                     base::RepeatingCallback<bool(const GURL&)>(), &run_loop));
-  run_loop.Run();
-}
-
 TEST_F(StoragePartitionImplTest, ClearCodeCacheIncognito) {
-  base::test::ScopedFeatureList feature_list;
-  feature_list.InitAndEnableFeature(net::features::kIsolatedCodeCache);
-  ASSERT_TRUE(base::FeatureList::IsEnabled(net::features::kIsolatedCodeCache));
-
   browser_context()->set_is_off_the_record(true);
 
   StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
diff --git a/content/browser/web_package/prefetched_signed_exchange_cache.cc b/content/browser/web_package/prefetched_signed_exchange_cache.cc
index 3bbd7b7a..9f21c19 100644
--- a/content/browser/web_package/prefetched_signed_exchange_cache.cc
+++ b/content/browser/web_package/prefetched_signed_exchange_cache.cc
@@ -14,6 +14,7 @@
 #include "content/public/common/content_features.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
+#include "net/http/http_cache.h"
 #include "net/http/http_util.h"
 #include "net/url_request/redirect_util.h"
 #include "services/network/public/cpp/constants.h"
@@ -445,6 +446,48 @@
   DISALLOW_COPY_AND_ASSIGN(PrefetchedNavigationLoaderInterceptor);
 };
 
+bool CanStoreEntry(const PrefetchedSignedExchangeCache::Entry& entry) {
+  const net::HttpResponseHeaders* outer_headers =
+      entry.outer_response()->headers.get();
+  // We don't store responses with a "cache-control: no-store" header.
+  if (outer_headers->HasHeaderValue("cache-control", "no-store"))
+    return false;
+
+  // Generally we don't store responses with a "vary" header. We only allows
+  // "accept-encoding" vary header. This is because content decoding is handled
+  // by the network layer and PrefetchedSignedExchangeCache stores decoded
+  // response bodies, so we can safely ignore varying on the "Accept-Encoding"
+  // header.
+  std::string value;
+  size_t iter = 0;
+  while (outer_headers->EnumerateHeader(&iter, "vary", &value)) {
+    if (!base::EqualsCaseInsensitiveASCII(value, "accept-encoding"))
+      return false;
+  }
+  return true;
+}
+
+bool CanUseEntry(const PrefetchedSignedExchangeCache::Entry& entry) {
+  const std::unique_ptr<const network::ResourceResponseHead>& outer_response =
+      entry.outer_response();
+  // Use the prefetched entry within kPrefetchReuseMins minutes without
+  // validation.
+  if (outer_response->headers->GetCurrentAge(outer_response->request_time,
+                                             outer_response->response_time,
+                                             base::Time::Now()) <
+      base::TimeDelta::FromMinutes(net::HttpCache::kPrefetchReuseMins)) {
+    return true;
+  }
+  // We use the prefetched entry when we don't need the validation.
+  if (outer_response->headers->RequiresValidation(
+          outer_response->request_time, outer_response->response_time,
+          base::Time::Now()) != net::VALIDATION_NONE) {
+    // TODO(crbug.com/935267): Consider discarding this entry.
+    return false;
+  }
+  return true;
+}
+
 }  // namespace
 
 PrefetchedSignedExchangeCache::Entry::Entry() = default;
@@ -526,6 +569,9 @@
   DCHECK(cached_exchange->inner_response());
   DCHECK(cached_exchange->completion_status());
   DCHECK(cached_exchange->blob_data_handle());
+
+  if (!CanStoreEntry(*cached_exchange))
+    return;
   const GURL outer_url = cached_exchange->outer_url();
   exchanges_[outer_url] = std::move(cached_exchange);
 }
@@ -536,9 +582,12 @@
   const auto it = exchanges_.find(outer_url);
   if (it == exchanges_.end())
     return nullptr;
+  const std::unique_ptr<const Entry>& exchange = it->second;
+  if (!CanUseEntry(*exchange.get()))
+    return nullptr;
   return std::make_unique<PrefetchedNavigationLoaderInterceptor>(
-      it->second->Clone(),
-      GetInfoListForNavigation(outer_url, it->second->inner_url()));
+      exchange->Clone(),
+      GetInfoListForNavigation(outer_url, exchange->inner_url()));
 }
 
 const PrefetchedSignedExchangeCache::EntryMap&
@@ -572,6 +621,8 @@
       // same origin.
       continue;
     }
+    if (!CanUseEntry(*exchange.get()))
+      continue;
     network::mojom::URLLoaderFactoryPtrInfo loader_factory_info;
     new SubresourceSignedExchangeURLLoaderFactory(
         mojo::MakeRequest(&loader_factory_info), exchange->Clone(),
diff --git a/content/browser/web_package/signed_exchange_subresource_prefetch_browsertest.cc b/content/browser/web_package/signed_exchange_subresource_prefetch_browsertest.cc
index 53bfb949..bb41b87 100644
--- a/content/browser/web_package/signed_exchange_subresource_prefetch_browsertest.cc
+++ b/content/browser/web_package/signed_exchange_subresource_prefetch_browsertest.cc
@@ -7,6 +7,7 @@
 
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
+#include "base/no_destructor.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/stl_util.h"
@@ -15,9 +16,11 @@
 #include "base/task_runner.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
+#include "base/test/scoped_mock_clock_override.h"
 #include "base/test/test_timeouts.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "base/time/time_override.h"
 #include "content/browser/blob_storage/chrome_blob_storage_context.h"
 #include "content/browser/frame_host/render_frame_host_impl.h"
 #include "content/browser/loader/prefetch_browsertest_base.h"
@@ -35,6 +38,7 @@
 #include "content/shell/browser/shell.h"
 #include "net/base/features.h"
 #include "net/dns/mock_host_resolver.h"
+#include "net/http/http_cache.h"
 #include "services/network/cross_origin_read_blocking.h"
 #include "services/network/public/cpp/features.h"
 #include "storage/browser/blob/blob_storage_context.h"
@@ -115,6 +119,56 @@
                             url.spec().c_str(), as);
 }
 
+// This class supplies a mock time which flies faster than the actual time
+// using ScopedTimeClockOverrides. This is used to check the cache expiration
+// logic.
+class MockClock {
+ public:
+  // Returns a MockClock which will not be deleted. If the test use this class,
+  // this method should be called once while single-threaded to initialize
+  // ScopedTimeClockOverrides to avoid threading issues.
+  static MockClock& Get() {
+    static base::NoDestructor<MockClock> mock_clock;
+    return *mock_clock;
+  }
+
+  void Advance(base::TimeDelta delta) {
+    DCHECK_GE(delta, base::TimeDelta());
+    base::AutoLock lock(lock_);
+    offset_ += delta;
+  }
+
+ private:
+  friend base::NoDestructor<MockClock>;
+
+  static base::Time MockedNow() {
+    return base::subtle::TimeNowIgnoringOverride() + mock_clock_->GetOffset();
+  }
+
+  MockClock() {
+    mock_clock_ = this;
+    time_override_ = std::make_unique<base::subtle::ScopedTimeClockOverrides>(
+        &MockClock::MockedNow, nullptr, nullptr);
+  }
+
+  ~MockClock() {}
+
+  base::TimeDelta GetOffset() {
+    base::AutoLock lock(lock_);
+    return offset_;
+  }
+
+  static MockClock* mock_clock_;
+
+  std::unique_ptr<base::subtle::ScopedTimeClockOverrides> time_override_;
+  base::Lock lock_;
+  base::TimeDelta offset_ GUARDED_BY(lock_);
+
+  DISALLOW_COPY_AND_ASSIGN(MockClock);
+};
+
+MockClock* MockClock::mock_clock_ = nullptr;
+
 }  // namespace
 
 class SignedExchangePrefetchBrowserTest
@@ -123,7 +177,11 @@
                      bool /* sxg_subresource_prefetch_enabled */>>,
       public PrefetchBrowserTestBase {
  public:
-  SignedExchangePrefetchBrowserTest() = default;
+  SignedExchangePrefetchBrowserTest() {
+    // Call MockClock::Get() here to initialize ScopedMockClockOverride which
+    // should be created while single-threaded.
+    MockClock::Get();
+  }
   ~SignedExchangePrefetchBrowserTest() = default;
 
   void SetUp() override {
@@ -137,6 +195,9 @@
     enable_features.push_back(features::kSignedHTTPExchange);
     if (network_service_enabled) {
       enable_features.push_back(network::features::kNetworkService);
+      // Need to run the network service in process for testing cache expirity
+      // (PrefetchMainResourceSXG_ExceedPrefetchReuseMins) using MockClock.
+      enable_features.push_back(features::kNetworkServiceInProcess);
     } else {
       disabled_features.push_back(network::features::kNetworkService);
     }
@@ -183,9 +244,15 @@
     const net::SHA256HashValue header_integrity = {{0x01}};
     const std::string content =
         "<head><title>Prefetch Target (SXG)</title></head>";
+    auto sxg_request_counter =
+        RequestCounter::CreateAndMonitor(embedded_test_server(), sxg_path);
+
     LoadPrefetchMainResourceSXGTestPage(
         prefetch_page_hostname, prefetch_page_path, sxg_hostname, sxg_path,
-        inner_url_hostname, inner_url_path, header_integrity, content);
+        inner_url_hostname, inner_url_path, header_integrity, content,
+        {} /* sxg_outer_headers */);
+
+    EXPECT_EQ(1, sxg_request_counter->GetRequestCount());
 
     const GURL sxg_url = embedded_test_server()->GetURL(sxg_hostname, sxg_path);
     const GURL inner_url =
@@ -206,6 +273,8 @@
     // the target URL. The target content should still be read correctly.
     // The content is loaded from PrefetchedSignedExchangeCache.
     NavigateToURLAndWaitTitle(sxg_url, "Prefetch Target (SXG)");
+
+    EXPECT_EQ(1, sxg_request_counter->GetRequestCount());
   }
 
   void LoadPrefetchMainResourceSXGTestPage(
@@ -216,7 +285,9 @@
       const std::string& inner_url_hostname,
       const std::string& inner_url_path,
       const net::SHA256HashValue& header_integrity,
-      const std::string& content) {
+      const std::string& content,
+      const std::vector<std::pair<std::string, std::string>>&
+          sxg_outer_headers) {
     auto sxg_request_counter =
         RequestCounter::CreateAndMonitor(embedded_test_server(), sxg_path);
     RegisterRequestHandler(embedded_test_server());
@@ -232,7 +303,8 @@
                      ResponseEntry(base::StringPrintf(
                          "<body><link rel='prefetch' href='%s'></body>",
                          sxg_url.spec().c_str())));
-    RegisterResponse(sxg_path, CreateSignedExchangeResponseEntry(content));
+    RegisterResponse(sxg_path, CreateSignedExchangeResponseEntry(
+                                   content, sxg_outer_headers));
 
     MockSignedExchangeHandlerFactory factory({MockSignedExchangeHandlerParams(
         sxg_url, SignedExchangeLoadResult::kSuccess, net::OK, inner_url,
@@ -261,6 +333,7 @@
     limits.max_file_size = kTestBlobStorageMaxFileSizeBytes;
     context->context()->set_limits_for_testing(limits);
   }
+
   base::test::ScopedFeatureList feature_list_;
 
   DISALLOW_COPY_AND_ASSIGN(SignedExchangePrefetchBrowserTest);
@@ -311,13 +384,188 @@
       "example.com" /* sxg_hostname */, "/target.sxg" /* sxg_path */,
       "example.com" /* inner_url_hostname */,
       "/target.html" /* inner_url_path */,
-      net::SHA256HashValue({{0x01}}) /* header_integrity */, content);
+      net::SHA256HashValue({{0x01}}) /* header_integrity */, content,
+      {} /* sxg_outer_headers */);
   const auto cached_exchanges = GetCachedExchanges(shell());
   // The content of prefetched SXG is larger than the Blob storage limit.
   // So the SXG should not be stored to the cache.
   EXPECT_EQ(0u, cached_exchanges.size());
 }
 
+IN_PROC_BROWSER_TEST_P(SignedExchangePrefetchBrowserTest,
+                       PrefetchMainResourceSXG_CacheControlNoStore) {
+  const std::string content =
+      "<head><title>Prefetch Target (SXG)</title></head>";
+
+  LoadPrefetchMainResourceSXGTestPage(
+      "example.com" /* prefetch_page_hostname */,
+      "/prefetch.html" /* prefetch_page_path */,
+      "example.com" /* sxg_hostname */, "/target.sxg" /* sxg_path */,
+      "example.com" /* inner_url_hostname */,
+      "/target.html" /* inner_url_path */,
+      net::SHA256HashValue({{0x01}}) /* header_integrity */, content,
+      {{"cache-control", "no-store"}} /* sxg_outer_headers */);
+  const auto cached_exchanges = GetCachedExchanges(shell());
+  // The signed exchange which response header has "cache-control: no-store"
+  // header should not be stored to the cache.
+  EXPECT_EQ(0u, cached_exchanges.size());
+}
+
+IN_PROC_BROWSER_TEST_P(SignedExchangePrefetchBrowserTest,
+                       PrefetchMainResourceSXG_VaryAsteriskHeader) {
+  const std::string content =
+      "<head><title>Prefetch Target (SXG)</title></head>";
+
+  LoadPrefetchMainResourceSXGTestPage(
+      "example.com" /* prefetch_page_hostname */,
+      "/prefetch.html" /* prefetch_page_path */,
+      "example.com" /* sxg_hostname */, "/target.sxg" /* sxg_path */,
+      "example.com" /* inner_url_hostname */,
+      "/target.html" /* inner_url_path */,
+      net::SHA256HashValue({{0x01}}) /* header_integrity */, content,
+      {{"vary", "*"}} /* sxg_outer_headers */);
+  const auto cached_exchanges = GetCachedExchanges(shell());
+  // The signed exchange which response header has "vary: *" header should not
+  // be stored to the cache.
+  EXPECT_EQ(0u, cached_exchanges.size());
+}
+
+IN_PROC_BROWSER_TEST_P(SignedExchangePrefetchBrowserTest,
+                       PrefetchMainResourceSXG_VaryAcceptEncodingHeader) {
+  const std::string content =
+      "<head><title>Prefetch Target (SXG)</title></head>";
+
+  LoadPrefetchMainResourceSXGTestPage(
+      "example.com" /* prefetch_page_hostname */,
+      "/prefetch.html" /* prefetch_page_path */,
+      "example.com" /* sxg_hostname */, "/target.sxg" /* sxg_path */,
+      "example.com" /* inner_url_hostname */,
+      "/target.html" /* inner_url_path */,
+      net::SHA256HashValue({{0x01}}) /* header_integrity */, content,
+      {{"vary", "accept-encoding"}} /* sxg_outer_headers */);
+  // The signed exchange which response header has "vary: accept-encoding"
+  // header should be stored to the cache.
+  const auto cached_exchanges = GetCachedExchanges(shell());
+  EXPECT_EQ(1u, cached_exchanges.size());
+}
+
+IN_PROC_BROWSER_TEST_P(SignedExchangePrefetchBrowserTest,
+                       PrefetchMainResourceSXG_ExceedPrefetchReuseMins) {
+  const char* hostname = "example.com";
+  const char* sxg_path = "/target.sxg";
+  const char* inner_url_path = "/target.html";
+  const std::string content =
+      "<head><title>Prefetch Target (SXG)</title></head>";
+  auto sxg_request_counter =
+      RequestCounter::CreateAndMonitor(embedded_test_server(), sxg_path);
+
+  LoadPrefetchMainResourceSXGTestPage(
+      hostname, "/prefetch.html" /* prefetch_page_path */, hostname, sxg_path,
+      hostname, inner_url_path,
+      net::SHA256HashValue({{0x01}}) /* header_integrity */, content,
+      {} /* sxg_outer_headers */);
+  EXPECT_EQ(1, sxg_request_counter->GetRequestCount());
+
+  const GURL sxg_url = embedded_test_server()->GetURL(hostname, sxg_path);
+  const GURL inner_url =
+      embedded_test_server()->GetURL(hostname, inner_url_path);
+
+  EXPECT_EQ(1u, GetCachedExchanges(shell()).size());
+
+  MockClock::Get().Advance(base::TimeDelta::FromSeconds(
+      net::HttpCache::kPrefetchReuseMins * 60 + 1));
+
+  // Need to setup MockSignedExchangeHandlerFactory because the SXG is loaded
+  // from the server again.
+  MockSignedExchangeHandlerFactory factory({MockSignedExchangeHandlerParams(
+      sxg_url, SignedExchangeLoadResult::kSuccess, net::OK, inner_url,
+      "text/html", {} /* sxg_inner_headers */,
+      net::SHA256HashValue({{0x01}}) /* header_integrity */)});
+  ScopedSignedExchangeHandlerFactory scoped_factory(&factory);
+
+  NavigateToURLAndWaitTitle(sxg_url, "Prefetch Target (SXG)");
+
+  // SXG must be fetched again.
+  EXPECT_EQ(2, sxg_request_counter->GetRequestCount());
+}
+
+IN_PROC_BROWSER_TEST_P(SignedExchangePrefetchBrowserTest,
+                       PrefetchMainResourceSXG_CacheControlPublic) {
+  const char* hostname = "example.com";
+  const char* sxg_path = "/target.sxg";
+  const char* inner_url_path = "/target.html";
+  const std::string content =
+      "<head><title>Prefetch Target (SXG)</title></head>";
+  auto sxg_request_counter =
+      RequestCounter::CreateAndMonitor(embedded_test_server(), sxg_path);
+
+  LoadPrefetchMainResourceSXGTestPage(
+      hostname, "/prefetch.html" /* prefetch_page_path */, hostname, sxg_path,
+      hostname, inner_url_path,
+      net::SHA256HashValue({{0x01}}) /* header_integrity */, content,
+      {{"cache-control",
+        base::StringPrintf("public, max-age=%d",
+                           net::HttpCache::kPrefetchReuseMins * 3 *
+                               60)}} /* sxg_outer_headers */);
+  EXPECT_EQ(1, sxg_request_counter->GetRequestCount());
+
+  const GURL sxg_url = embedded_test_server()->GetURL(hostname, sxg_path);
+  const GURL inner_url =
+      embedded_test_server()->GetURL(hostname, inner_url_path);
+
+  EXPECT_EQ(1u, GetCachedExchanges(shell()).size());
+
+  MockClock::Get().Advance(base::TimeDelta::FromSeconds(
+      net::HttpCache::kPrefetchReuseMins * 2 * 60));
+  NavigateToURLAndWaitTitle(sxg_url, "Prefetch Target (SXG)");
+
+  // SXG must Not be fetched again.
+  EXPECT_EQ(1, sxg_request_counter->GetRequestCount());
+}
+
+IN_PROC_BROWSER_TEST_P(SignedExchangePrefetchBrowserTest,
+                       PrefetchMainResourceSXG_CacheControlPublicExpire) {
+  const char* hostname = "example.com";
+  const char* sxg_path = "/target.sxg";
+  const char* inner_url_path = "/target.html";
+  const std::string content =
+      "<head><title>Prefetch Target (SXG)</title></head>";
+  auto sxg_request_counter =
+      RequestCounter::CreateAndMonitor(embedded_test_server(), sxg_path);
+
+  LoadPrefetchMainResourceSXGTestPage(
+      hostname, "/prefetch.html" /* prefetch_page_path */, hostname, sxg_path,
+      hostname, inner_url_path,
+      net::SHA256HashValue({{0x01}}) /* header_integrity */, content,
+      {{"cache-control",
+        base::StringPrintf("public, max-age=%d",
+                           net::HttpCache::kPrefetchReuseMins * 3 *
+                               60)}} /* sxg_outer_headers */);
+  EXPECT_EQ(1, sxg_request_counter->GetRequestCount());
+
+  const GURL sxg_url = embedded_test_server()->GetURL(hostname, sxg_path);
+  const GURL inner_url =
+      embedded_test_server()->GetURL(hostname, inner_url_path);
+
+  EXPECT_EQ(1u, GetCachedExchanges(shell()).size());
+
+  MockClock::Get().Advance(base::TimeDelta::FromSeconds(
+      net::HttpCache::kPrefetchReuseMins * 3 * 60 + 1));
+
+  // Need to setup MockSignedExchangeHandlerFactory because the SXG is loaded
+  // from the server again.
+  MockSignedExchangeHandlerFactory factory({MockSignedExchangeHandlerParams(
+      sxg_url, SignedExchangeLoadResult::kSuccess, net::OK, inner_url,
+      "text/html", {} /* sxg_inner_headers */,
+      net::SHA256HashValue({{0x01}}) /* header_integrity */)});
+  ScopedSignedExchangeHandlerFactory scoped_factory(&factory);
+
+  NavigateToURLAndWaitTitle(sxg_url, "Prefetch Target (SXG)");
+
+  // SXG must be fetched again, because the cache has been expired.
+  EXPECT_EQ(2, sxg_request_counter->GetRequestCount());
+}
+
 // This test is almost same as SignedExchangeSubresourcePrefetchBrowserTest's
 // MainResourceSXGAndScriptSXG_SameOrigin. The only difference is that this test
 // is executed without SignedExchangeSubresourcePrefetch but with
@@ -458,7 +706,11 @@
     : public testing::WithParamInterface<bool /* network_service_enabled */>,
       public PrefetchBrowserTestBase {
  public:
-  SignedExchangeSubresourcePrefetchBrowserTest() = default;
+  SignedExchangeSubresourcePrefetchBrowserTest() {
+    // Call MockClock::Get() here to initialize ScopedMockClockOverride which
+    // should be created while single-threaded.
+    MockClock::Get();
+  }
   ~SignedExchangeSubresourcePrefetchBrowserTest() = default;
 
   void SetUp() override {
@@ -470,6 +722,9 @@
     enable_features.push_back(features::kSignedExchangeSubresourcePrefetch);
     if (network_service_enabled) {
       enable_features.push_back(network::features::kNetworkService);
+      // Need to run the network service in process for testing cache expirity
+      // (PrefetchMainResourceSXG_ExceedPrefetchReuseMins) using MockClock.
+      enable_features.push_back(features::kNetworkServiceInProcess);
     } else {
       disabled_features.push_back(network::features::kNetworkService);
     }
@@ -500,7 +755,11 @@
       const std::string& inner_url_hostname,
       const std::string& page_inner_url_path,
       const std::string& script_inner_url_path,
+      const std::vector<std::pair<std::string, std::string>>&
+          script_sxg_outer_headers,
+      int64_t elapsed_time_after_prefetch,
       const std::string& expected_title,
+      bool script_sxg_should_be_stored,
       int expected_script_fetch_count) {
     // When |expected_script_fetch_count| is -1, we don't check the script fetch
     // count.
@@ -549,9 +808,14 @@
                      CreateSignedExchangeResponseEntry(
                          "<head><title>Prefetch Target (SXG)</title>"
                          "<script src=\"./script.js\"></script></head>",
-                         {{"link", outer_link_header}}));
-    RegisterResponse(script_sxg_path, CreateSignedExchangeResponseEntry(
-                                          "document.title=\"done\";"));
+                         {{"link", outer_link_header},
+                          {"cache-control",
+                           base::StringPrintf(
+                               "public, max-age=%d",
+                               net::HttpCache::kPrefetchReuseMins * 3 * 60)}}));
+    RegisterResponse(script_sxg_path,
+                     CreateSignedExchangeResponseEntry(
+                         "document.title=\"done\";", script_sxg_outer_headers));
     MockSignedExchangeHandlerFactory factory(
         {MockSignedExchangeHandlerParams(
              sxg_page_url, SignedExchangeLoadResult::kSuccess, net::OK,
@@ -576,7 +840,7 @@
     EXPECT_EQ(2, GetPrefetchURLLoaderCallCount());
 
     const auto cached_exchanges = GetCachedExchanges(shell());
-    EXPECT_EQ(2u, cached_exchanges.size());
+    EXPECT_EQ(script_sxg_should_be_stored ? 2u : 1u, cached_exchanges.size());
 
     const auto target_it = cached_exchanges.find(sxg_page_url);
     ASSERT_TRUE(target_it != cached_exchanges.end());
@@ -584,11 +848,17 @@
     EXPECT_EQ(inner_url_page_url, target_it->second->inner_url());
     EXPECT_EQ(page_header_integrity, *target_it->second->header_integrity());
 
-    const auto script_it = cached_exchanges.find(sxg_script_url);
-    ASSERT_TRUE(script_it != cached_exchanges.end());
-    EXPECT_EQ(sxg_script_url, script_it->second->outer_url());
-    EXPECT_EQ(inner_url_script_url, script_it->second->inner_url());
-    EXPECT_EQ(script_header_integrity, *script_it->second->header_integrity());
+    if (script_sxg_should_be_stored) {
+      const auto script_it = cached_exchanges.find(sxg_script_url);
+      ASSERT_TRUE(script_it != cached_exchanges.end());
+      EXPECT_EQ(sxg_script_url, script_it->second->outer_url());
+      EXPECT_EQ(inner_url_script_url, script_it->second->inner_url());
+      EXPECT_EQ(script_header_integrity,
+                *script_it->second->header_integrity());
+    }
+
+    MockClock::Get().Advance(
+        base::TimeDelta::FromSeconds(elapsed_time_after_prefetch));
 
     // Subsequent navigation to the target URL wouldn't hit the network for
     // the target URL. The target content should still be read correctly.
@@ -733,7 +1003,9 @@
       "/script.sxg" /* script_sxg_path */,
       "example.com" /* inner_url_hostname */,
       "/target.html" /* page_inner_url_path */,
-      "/script.js" /* script_inner_url_path */, "done" /* expected_title */,
+      "/script.js" /* script_inner_url_path */,
+      {} /* script_sxg_outer_headers */, 0 /* elapsed_time_after_prefetch */,
+      "done" /* expected_title */, true /* script_sxg_should_be_stored */,
       0 /* expected_script_fetch_count */);
 }
 
@@ -749,7 +1021,9 @@
       "/script.js" /* script_sxg_path */,
       "example.com" /* inner_url_hostname */,
       "/target.html" /* page_inner_url_path */,
-      "/script.js" /* script_inner_url_path */, "done" /* expected_title */,
+      "/script.js" /* script_inner_url_path */,
+      {} /* script_sxg_outer_headers */, 0 /* elapsed_time_after_prefetch */,
+      "done" /* expected_title */, true /* script_sxg_should_be_stored */,
       // Note that we don't check the script fetch count in this test.
       -1 /* expected_script_fetch_count  */);
 }
@@ -769,7 +1043,9 @@
       "/script.sxg" /* script_sxg_path */,
       "publisher.example.com" /* inner_url_hostname */,
       "/target.html" /* page_inner_url_path */,
-      "/script.js" /* script_inner_url_path */, "done" /* expected_title */,
+      "/script.js" /* script_inner_url_path */,
+      {} /* script_sxg_outer_headers */, 0 /* elapsed_time_after_prefetch */,
+      "done" /* expected_title */, true /* script_sxg_should_be_stored */,
       0 /* expected_script_fetch_count */);
 }
 
@@ -787,7 +1063,123 @@
       "publisher.example.com" /* inner_url_hostname */,
       "/target.html" /* page_inner_url_path */,
       "/script.js" /* script_inner_url_path */,
-      "from server" /* expected_title */, 1 /* expected_script_fetch_count */);
+      {} /* script_sxg_outer_headers */, 0 /* elapsed_time_after_prefetch */,
+      "from server" /* expected_title */,
+      true /* script_sxg_should_be_stored */,
+      1 /* expected_script_fetch_count */);
+}
+
+IN_PROC_BROWSER_TEST_P(SignedExchangeSubresourcePrefetchBrowserTest,
+                       MainResourceSXGAndScriptSXG_CacheControlNoStore) {
+  RunPrefetchMainResourceSXGAndScriptSXGTest(
+      "example.com" /* prefetch_page_hostname */,
+      "/prefetch.html" /* prefetch_page_path */,
+      "example.com" /* page_sxg_hostname */, "/target.sxg" /* page_sxg_path */,
+      "example.com" /* script_sxg_hostname */,
+      "/script.sxg" /* script_sxg_path */,
+      "example.com" /* inner_url_hostname */,
+      "/target.html" /* page_inner_url_path */,
+      "/script.js" /* script_inner_url_path */,
+      {{"cache-control", "no-store"}} /* script_sxg_outer_headers */,
+      0 /* elapsed_time_after_prefetch */, "from server" /* expected_title */,
+      false /* script_sxg_should_be_stored */,
+      1 /* expected_script_fetch_count */);
+}
+
+IN_PROC_BROWSER_TEST_P(SignedExchangeSubresourcePrefetchBrowserTest,
+                       MainResourceSXGAndScriptSXG_VaryAsteriskHeader) {
+  RunPrefetchMainResourceSXGAndScriptSXGTest(
+      "example.com" /* prefetch_page_hostname */,
+      "/prefetch.html" /* prefetch_page_path */,
+      "example.com" /* page_sxg_hostname */, "/target.sxg" /* page_sxg_path */,
+      "example.com" /* script_sxg_hostname */,
+      "/script.sxg" /* script_sxg_path */,
+      "example.com" /* inner_url_hostname */,
+      "/target.html" /* page_inner_url_path */,
+      "/script.js" /* script_inner_url_path */,
+      {{"vary", "*"}} /* script_sxg_outer_headers */,
+      0 /* elapsed_time_after_prefetch */, "from server" /* expected_title */,
+      false /* script_sxg_should_be_stored */,
+      1 /* expected_script_fetch_count */);
+}
+
+IN_PROC_BROWSER_TEST_P(SignedExchangeSubresourcePrefetchBrowserTest,
+                       MainResourceSXGAndScriptSXG_VaryAcceptEncodingHeader) {
+  RunPrefetchMainResourceSXGAndScriptSXGTest(
+      "example.com" /* prefetch_page_hostname */,
+      "/prefetch.html" /* prefetch_page_path */,
+      "example.com" /* page_sxg_hostname */, "/target.sxg" /* page_sxg_path */,
+      "example.com" /* script_sxg_hostname */,
+      "/script.sxg" /* script_sxg_path */,
+      "example.com" /* inner_url_hostname */,
+      "/target.html" /* page_inner_url_path */,
+      "/script.js" /* script_inner_url_path */,
+      {{"vary", "accept-encoding"}} /* script_sxg_outer_headers */,
+      0 /* elapsed_time_after_prefetch */, "done" /* expected_title */,
+      true /* script_sxg_should_be_stored */,
+      0 /* expected_script_fetch_count */);
+}
+
+IN_PROC_BROWSER_TEST_P(SignedExchangeSubresourcePrefetchBrowserTest,
+                       MainResourceSXGAndScriptSXG_ExceedPrefetchReuseMins) {
+  RunPrefetchMainResourceSXGAndScriptSXGTest(
+      "example.com" /* prefetch_page_hostname */,
+      "/prefetch.html" /* prefetch_page_path */,
+      "example.com" /* page_sxg_hostname */, "/target.sxg" /* page_sxg_path */,
+      "example.com" /* script_sxg_hostname */,
+      "/script.sxg" /* script_sxg_path */,
+      "example.com" /* inner_url_hostname */,
+      "/target.html" /* page_inner_url_path */,
+      "/script.js" /* script_inner_url_path */,
+      {} /* script_sxg_outer_headers */,
+      net::HttpCache::kPrefetchReuseMins * 60 + 1
+      /* elapsed_time_after_prefetch */,
+      "from server" /* expected_title */,
+      true /* script_sxg_should_be_stored */,
+      1 /* expected_script_fetch_count */);
+}
+
+IN_PROC_BROWSER_TEST_P(SignedExchangeSubresourcePrefetchBrowserTest,
+                       MainResourceSXGAndScriptSXG_CacheControlPublic) {
+  RunPrefetchMainResourceSXGAndScriptSXGTest(
+      "example.com" /* prefetch_page_hostname */,
+      "/prefetch.html" /* prefetch_page_path */,
+      "example.com" /* page_sxg_hostname */, "/target.sxg" /* page_sxg_path */,
+      "example.com" /* script_sxg_hostname */,
+      "/script.sxg" /* script_sxg_path */,
+      "example.com" /* inner_url_hostname */,
+      "/target.html" /* page_inner_url_path */,
+      "/script.js" /* script_inner_url_path */,
+      {{"cache-control",
+        base::StringPrintf("public, max-age=%d",
+                           net::HttpCache::kPrefetchReuseMins * 3 *
+                               60)}} /* script_sxg_outer_headers */,
+      net::HttpCache::kPrefetchReuseMins * 2 * 60
+      /* elapsed_time_after_prefetch */,
+      "done" /* expected_title */, true /* script_sxg_should_be_stored */,
+      0 /* expected_script_fetch_count */);
+}
+
+IN_PROC_BROWSER_TEST_P(SignedExchangeSubresourcePrefetchBrowserTest,
+                       MainResourceSXGAndScriptSXG_CacheControlPublicExpire) {
+  RunPrefetchMainResourceSXGAndScriptSXGTest(
+      "example.com" /* prefetch_page_hostname */,
+      "/prefetch.html" /* prefetch_page_path */,
+      "example.com" /* page_sxg_hostname */, "/target.sxg" /* page_sxg_path */,
+      "example.com" /* script_sxg_hostname */,
+      "/script.sxg" /* script_sxg_path */,
+      "example.com" /* inner_url_hostname */,
+      "/target.html" /* page_inner_url_path */,
+      "/script.js" /* script_inner_url_path */,
+      {{"cache-control",
+        base::StringPrintf("public, max-age=%d",
+                           net::HttpCache::kPrefetchReuseMins * 3 *
+                               60)}} /* script_sxg_outer_headers */,
+      net::HttpCache::kPrefetchReuseMins * 3 * 60 + 1
+      /* elapsed_time_after_prefetch */,
+      "from server" /* expected_title */,
+      true /* script_sxg_should_be_stored */,
+      1 /* expected_script_fetch_count */);
 }
 
 IN_PROC_BROWSER_TEST_P(SignedExchangeSubresourcePrefetchBrowserTest,
diff --git a/content/browser/worker_host/dedicated_worker_host.cc b/content/browser/worker_host/dedicated_worker_host.cc
index 933766f3..620e412 100644
--- a/content/browser/worker_host/dedicated_worker_host.cc
+++ b/content/browser/worker_host/dedicated_worker_host.cc
@@ -67,6 +67,7 @@
   void StartScriptLoad(
       const GURL& script_url,
       const url::Origin& request_initiator_origin,
+      network::mojom::FetchCredentialsMode credentials_mode,
       blink::mojom::BlobURLTokenPtr blob_url_token,
       blink::mojom::DedicatedWorkerHostFactoryClientPtr client) {
     DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -99,7 +100,7 @@
         storage_partition_impl->GetAppCacheService(), process_id_);
 
     WorkerScriptFetchInitiator::Start(
-        process_id_, script_url, request_initiator_origin,
+        process_id_, script_url, request_initiator_origin, credentials_mode,
         ResourceType::kWorker,
         storage_partition_impl->GetServiceWorkerContext(),
         appcache_handle_->core(), std::move(blob_url_loader_factory), nullptr,
@@ -324,6 +325,7 @@
   void CreateWorkerHostAndStartScriptLoad(
       const GURL& script_url,
       const url::Origin& request_initiator_origin,
+      network::mojom::FetchCredentialsMode credentials_mode,
       blink::mojom::BlobURLTokenPtr blob_url_token,
       blink::mojom::DedicatedWorkerHostFactoryClientPtr client) override {
     DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -347,7 +349,8 @@
             mojo::MakeRequest(&interface_provider)));
     client->OnWorkerHostCreated(std::move(interface_provider));
     host_raw->StartScriptLoad(script_url, request_initiator_origin,
-                              std::move(blob_url_token), std::move(client));
+                              credentials_mode, std::move(blob_url_token),
+                              std::move(client));
   }
 
  private:
diff --git a/content/browser/worker_host/shared_worker_service_impl.cc b/content/browser/worker_host/shared_worker_service_impl.cc
index 6282f24..d4b9829 100644
--- a/content/browser/worker_host/shared_worker_service_impl.cc
+++ b/content/browser/worker_host/shared_worker_service_impl.cc
@@ -210,12 +210,21 @@
     weak_host->SetAppCacheHandle(std::move(appcache_handle));
   }
 
+  // Fetch classic shared worker script with "same-origin" credentials mode.
+  // https://html.spec.whatwg.org/C/#fetch-a-classic-worker-script
+  //
+  // TODO(nhiroki): The document's renderer should provide credentials mode
+  // specified by WorkerOptions for module script.
+  // (https://crbug.com/824646, https://crbug.com/907749)
+  const auto credentials_mode =
+      network::mojom::FetchCredentialsMode::kSameOrigin;
+
   WorkerScriptFetchInitiator::Start(
       process_id, weak_host->instance()->url(),
-      weak_host->instance()->constructor_origin(), ResourceType::kSharedWorker,
-      service_worker_context_, appcache_handle_core,
-      std::move(blob_url_loader_factory), url_loader_factory_override_,
-      storage_partition_,
+      weak_host->instance()->constructor_origin(), credentials_mode,
+      ResourceType::kSharedWorker, service_worker_context_,
+      appcache_handle_core, std::move(blob_url_loader_factory),
+      url_loader_factory_override_, storage_partition_,
       base::BindOnce(&SharedWorkerServiceImpl::DidCreateScriptLoader,
                      weak_factory_.GetWeakPtr(), std::move(instance), weak_host,
                      std::move(client), process_id, frame_id, message_port));
diff --git a/content/browser/worker_host/worker_script_fetch_initiator.cc b/content/browser/worker_host/worker_script_fetch_initiator.cc
index e4093c0..3e13bdc7 100644
--- a/content/browser/worker_host/worker_script_fetch_initiator.cc
+++ b/content/browser/worker_host/worker_script_fetch_initiator.cc
@@ -36,6 +36,7 @@
 #include "content/public/common/content_switches.h"
 #include "content/public/common/origin_util.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
+#include "net/base/load_flags.h"
 #include "services/network/loader_util.h"
 #include "services/network/public/cpp/features.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
@@ -50,6 +51,7 @@
     int process_id,
     const GURL& script_url,
     const url::Origin& request_initiator,
+    network::mojom::FetchCredentialsMode credentials_mode,
     ResourceType resource_type,
     scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
     AppCacheNavigationHandleCore* appcache_handle_core,
@@ -98,6 +100,20 @@
     resource_request->request_initiator = request_initiator;
     resource_request->resource_type = static_cast<int>(resource_type);
 
+    // When the credentials mode is "omit", clear |allow_credentials| and set
+    // load flags to disable sending credentials according to the comments in
+    // CorsURLLoaderFactory::IsSane().
+    // TODO(https://crbug.com/799935): Unify |LOAD_DO_NOT_*| into
+    // |allow_credentials|.
+    resource_request->fetch_credentials_mode = credentials_mode;
+    if (credentials_mode == network::mojom::FetchCredentialsMode::kOmit) {
+      resource_request->allow_credentials = false;
+      const auto load_flags_pattern = net::LOAD_DO_NOT_SAVE_COOKIES |
+                                      net::LOAD_DO_NOT_SEND_COOKIES |
+                                      net::LOAD_DO_NOT_SEND_AUTH_DATA;
+      resource_request->load_flags |= load_flags_pattern;
+    }
+
     switch (resource_type) {
       case ResourceType::kWorker:
         resource_request->fetch_request_context_type =
diff --git a/content/browser/worker_host/worker_script_fetch_initiator.h b/content/browser/worker_host/worker_script_fetch_initiator.h
index 1c8b7c03..1240f6e 100644
--- a/content/browser/worker_host/worker_script_fetch_initiator.h
+++ b/content/browser/worker_host/worker_script_fetch_initiator.h
@@ -14,6 +14,7 @@
 #include "content/public/common/resource_type.h"
 #include "content/public/common/url_loader_throttle.h"
 #include "services/network/public/cpp/resource_response.h"
+#include "services/network/public/mojom/fetch_api.mojom.h"
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
 #include "third_party/blink/public/mojom/service_worker/controller_service_worker.mojom.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom.h"
@@ -59,6 +60,7 @@
       int process_id,
       const GURL& script_url,
       const url::Origin& request_initiator,
+      network::mojom::FetchCredentialsMode credentials_mode,
       ResourceType resource_type,
       scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
       AppCacheNavigationHandleCore* appcache_handle_core,
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc
index b44db133..32d91d8 100644
--- a/content/child/runtime_features.cc
+++ b/content/child/runtime_features.cc
@@ -18,7 +18,6 @@
 #include "content/public/common/content_switches.h"
 #include "gpu/config/gpu_switches.h"
 #include "media/base/media_switches.h"
-#include "net/base/features.h"
 #include "services/device/public/cpp/device_features.h"
 #include "services/network/public/cpp/features.h"
 #include "third_party/blink/public/common/features.h"
@@ -413,8 +412,6 @@
   WebRuntimeFeatures::EnableCacheInlineScriptCode(
       base::FeatureList::IsEnabled(features::kCacheInlineScriptCode));
 
-  WebRuntimeFeatures::EnableIsolatedCodeCache(
-      base::FeatureList::IsEnabled(net::features::kIsolatedCodeCache));
   WebRuntimeFeatures::EnableWasmCodeCache(
       base::FeatureList::IsEnabled(blink::features::kWasmCodeCache));
 
diff --git a/content/public/renderer/BUILD.gn b/content/public/renderer/BUILD.gn
index 1f3e181..e7c9ea2 100644
--- a/content/public/renderer/BUILD.gn
+++ b/content/public/renderer/BUILD.gn
@@ -61,7 +61,6 @@
     "renderer_ppapi_host.h",
     "request_peer.h",
     "resource_dispatcher_delegate.h",
-    "resource_fetcher.h",
     "seccomp_sandbox_status_android.h",
     "url_loader_throttle_provider.h",
     "v8_value_converter.h",
diff --git a/content/public/renderer/resource_fetcher.h b/content/public/renderer/resource_fetcher.h
deleted file mode 100644
index ffd1eb8e..0000000
--- a/content/public/renderer/resource_fetcher.h
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2013 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_RENDERER_RESOURCE_FETCHER_H_
-#define CONTENT_PUBLIC_RENDERER_RESOURCE_FETCHER_H_
-
-#include <memory>
-#include <string>
-
-#include "base/callback.h"
-#include "content/common/content_export.h"
-#include "third_party/blink/public/platform/web_url_request.h"
-
-class GURL;
-
-namespace base {
-class TimeDelta;
-}
-
-namespace blink {
-class WebLocalFrame;
-class WebURLResponse;
-}
-
-namespace net {
-struct NetworkTrafficAnnotationTag;
-}
-
-namespace network {
-class SharedURLLoaderFactory;
-}
-
-namespace content {
-
-// Interface to download resources asynchronously.  Specified callback will be
-// called asynchronously after the URL has been fetched, successfully or not.
-// If there is a failure, response and data will both be empty.  |response| and
-// |data| are both valid until the ResourceFetcher instance is destroyed.  If
-// the instance is destroyed before the operation is finished, the request is
-// canceled, and the callback will not be called.
-class CONTENT_EXPORT ResourceFetcher {
- public:
-  using StartCallback =
-      base::OnceCallback<void(const blink::WebURLResponse& response,
-                              const std::string& data)>;
-
-  static constexpr size_t kDefaultMaximumDownloadSize = 1024 * 1024;
-
-  virtual ~ResourceFetcher() {}
-
-  // Creates a ResourceFetcher for the specified resource.
-  static std::unique_ptr<ResourceFetcher> Create(const GURL& url);
-
-  // Set the corresponding parameters of the request.  Must be called before
-  // Start.  By default, requests are GETs with no body and respect the default
-  // cache policy.
-  virtual void SetMethod(const std::string& method) = 0;
-  virtual void SetBody(const std::string& body) = 0;
-  virtual void SetHeader(const std::string& header,
-                         const std::string& value) = 0;
-  virtual void SetFetchRequestMode(
-      network::mojom::FetchRequestMode fetch_request_mode) = 0;
-
-  // Starts the request using the specified frame.  Calls |callback| when
-  // done.
-  virtual void Start(
-      blink::WebLocalFrame* frame,
-      blink::mojom::RequestContextType request_context,
-      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
-      const net::NetworkTrafficAnnotationTag& annotation_tag,
-      StartCallback callback,
-      size_t maximum_download_size = kDefaultMaximumDownloadSize) = 0;
-
-  // Sets how long to wait for the server to reply.  By default, there is no
-  // timeout.  Must be called after a request is started at most once.
-  virtual void SetTimeout(const base::TimeDelta& timeout) = 0;
-};
-
-}  // namespace content
-
-#endif  // CONTENT_PUBLIC_RENDERER_RESOURCE_FETCHER_H_
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn
index b1848dc..c9744c9 100644
--- a/content/renderer/BUILD.gn
+++ b/content/renderer/BUILD.gn
@@ -78,8 +78,6 @@
     "fetchers/associated_resource_fetcher_impl.h",
     "fetchers/multi_resolution_image_resource_fetcher.cc",
     "fetchers/multi_resolution_image_resource_fetcher.h",
-    "fetchers/resource_fetcher_impl.cc",
-    "fetchers/resource_fetcher_impl.h",
     "frame_blame_context.cc",
     "frame_blame_context.h",
     "frame_owner_properties.cc",
@@ -228,8 +226,6 @@
     "media/stream/media_stream_dispatcher_eventhandler.h",
     "media/stream/media_stream_renderer_factory_impl.cc",
     "media/stream/media_stream_renderer_factory_impl.h",
-    "media/stream/media_stream_video_renderer_sink.cc",
-    "media/stream/media_stream_video_renderer_sink.h",
     "media/stream/processed_local_audio_source.cc",
     "media/stream/processed_local_audio_source.h",
     "media/stream/remote_media_stream_track_adapter.cc",
diff --git a/content/renderer/fetchers/resource_fetcher_browsertest.cc b/content/renderer/fetchers/resource_fetcher_browsertest.cc
deleted file mode 100644
index 6bf4679..0000000
--- a/content/renderer/fetchers/resource_fetcher_browsertest.cc
+++ /dev/null
@@ -1,409 +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 "content/public/renderer/resource_fetcher.h"
-
-#include <stdint.h>
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/command_line.h"
-#include "base/time/time.h"
-#include "base/timer/timer.h"
-#include "build/build_config.h"
-#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/common/url_constants.h"
-#include "content/public/renderer/render_frame.h"
-#include "content/public/renderer/render_view.h"
-#include "content/public/test/content_browser_test.h"
-#include "content/public/test/content_browser_test_utils.h"
-#include "content/public/test/test_utils.h"
-#include "content/shell/browser/shell.h"
-#include "net/test/embedded_test_server/embedded_test_server.h"
-#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
-#include "services/network/public/cpp/shared_url_loader_factory.h"
-#include "third_party/blink/public/platform/web_url_response.h"
-#include "third_party/blink/public/web/web_local_frame.h"
-#include "third_party/blink/public/web/web_view.h"
-
-using blink::WebURLRequest;
-using blink::WebURLResponse;
-
-namespace content {
-
-static const int kMaxWaitTimeMs = 5000;
-
-class FetcherDelegate {
- public:
-  FetcherDelegate() : completed_(false), timed_out_(false) {
-    // Start a repeating timer waiting for the download to complete.  The
-    // callback has to be a static function, so we hold on to our instance.
-    FetcherDelegate::instance_ = this;
-    StartTimer();
-  }
-
-  virtual ~FetcherDelegate() {}
-
-  ResourceFetcher::StartCallback NewCallback() {
-    return base::BindOnce(&FetcherDelegate::OnURLFetchComplete,
-                          base::Unretained(this));
-  }
-
-  virtual void OnURLFetchComplete(const WebURLResponse& response,
-                                  const std::string& data) {
-    response_ = response;
-    data_ = data;
-    completed_ = true;
-    timer_.Stop();
-    if (!timed_out_)
-      std::move(quit_task_).Run();
-  }
-
-  bool completed() const { return completed_; }
-  bool timed_out() const { return timed_out_; }
-
-  std::string data() const { return data_; }
-  const WebURLResponse& response() const { return response_; }
-
-  // Wait for the request to complete or timeout.
-  void WaitForResponse() {
-    scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner;
-    quit_task_ = runner->QuitClosure();
-    runner->Run();
-  }
-
-  void StartTimer() {
-    timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(kMaxWaitTimeMs),
-                 this, &FetcherDelegate::TimerFired);
-  }
-
-  void TimerFired() {
-    ASSERT_FALSE(completed_);
-
-    timed_out_ = true;
-    if (!completed_)
-      std::move(quit_task_).Run();
-    FAIL() << "fetch timed out";
-  }
-
-  static FetcherDelegate* instance_;
-
- private:
-  base::OneShotTimer timer_;
-  bool completed_;
-  bool timed_out_;
-  WebURLResponse response_;
-  std::string data_;
-  base::OnceClosure quit_task_;
-};
-
-FetcherDelegate* FetcherDelegate::instance_ = nullptr;
-
-class EvilFetcherDelegate : public FetcherDelegate {
- public:
-  ~EvilFetcherDelegate() override {}
-
-  void SetFetcher(ResourceFetcher* fetcher) { fetcher_.reset(fetcher); }
-
-  void OnURLFetchComplete(const WebURLResponse& response,
-                          const std::string& data) override {
-    FetcherDelegate::OnURLFetchComplete(response, data);
-
-    // Destroy the ResourceFetcher here.  We are testing that upon returning
-    // to the ResourceFetcher that it does not crash.  This must be done after
-    // calling FetcherDelegate::OnURLFetchComplete, since deleting the fetcher
-    // invalidates |response| and |data|.
-    fetcher_.reset();
-  }
-
- private:
-  std::unique_ptr<ResourceFetcher> fetcher_;
-};
-
-class ResourceFetcherTests : public ContentBrowserTest {
- public:
-  ResourceFetcherTests() : render_view_routing_id_(MSG_ROUTING_NONE) {}
-
-  void SetUpCommandLine(base::CommandLine* command_line) override {
-    command_line->AppendSwitch(switches::kSingleProcess);
-#if defined(OS_WIN)
-    // Don't want to try to create a GPU process.
-    command_line->AppendSwitch(switches::kDisableGpu);
-#endif
-  }
-
-  void SetUpOnMainThread() override {
-    render_view_routing_id_ =
-        shell()->web_contents()->GetRenderViewHost()->GetRoutingID();
-  }
-
-  RenderView* GetRenderView() {
-    return RenderView::FromRoutingID(render_view_routing_id_);
-  }
-
-  void ResourceFetcherDownloadOnRenderer(const GURL& url) {
-    blink::WebLocalFrame* frame =
-        GetRenderView()->GetWebView()->MainFrame()->ToWebLocalFrame();
-
-    std::unique_ptr<FetcherDelegate> delegate(new FetcherDelegate);
-    std::unique_ptr<ResourceFetcher> fetcher(ResourceFetcher::Create(url));
-    fetcher->Start(frame, blink::mojom::RequestContextType::INTERNAL,
-                   RenderFrame::FromWebFrame(frame)->GetURLLoaderFactory(),
-                   TRAFFIC_ANNOTATION_FOR_TESTS, delegate->NewCallback());
-
-    delegate->WaitForResponse();
-
-    ASSERT_TRUE(delegate->completed());
-    EXPECT_EQ(200, delegate->response().HttpStatusCode());
-    std::string text = delegate->data();
-    EXPECT_TRUE(text.find("Basic html test.") != std::string::npos);
-  }
-
-  void ResourceFetcherRedirectOnRenderer(const GURL& url,
-                                         const GURL& final_url) {
-    blink::WebLocalFrame* frame =
-        GetRenderView()->GetWebView()->MainFrame()->ToWebLocalFrame();
-
-    std::unique_ptr<FetcherDelegate> delegate(new FetcherDelegate);
-    std::unique_ptr<ResourceFetcher> fetcher(ResourceFetcher::Create(url));
-    fetcher->Start(frame, blink::mojom::RequestContextType::INTERNAL,
-                   RenderFrame::FromWebFrame(frame)->GetURLLoaderFactory(),
-                   TRAFFIC_ANNOTATION_FOR_TESTS, delegate->NewCallback());
-
-    delegate->WaitForResponse();
-
-    ASSERT_TRUE(delegate->completed());
-    EXPECT_EQ(200, delegate->response().HttpStatusCode());
-    EXPECT_EQ(final_url.spec(),
-              delegate->response().CurrentRequestUrl().GetString().Utf8());
-    std::string text = delegate->data();
-    EXPECT_TRUE(text.find("Basic html test.") != std::string::npos);
-  }
-
-  void ResourceFetcher404OnRenderer(const GURL& url) {
-    blink::WebLocalFrame* frame =
-        GetRenderView()->GetWebView()->MainFrame()->ToWebLocalFrame();
-
-    std::unique_ptr<FetcherDelegate> delegate(new FetcherDelegate);
-    std::unique_ptr<ResourceFetcher> fetcher(ResourceFetcher::Create(url));
-    fetcher->Start(frame, blink::mojom::RequestContextType::INTERNAL,
-                   RenderFrame::FromWebFrame(frame)->GetURLLoaderFactory(),
-                   TRAFFIC_ANNOTATION_FOR_TESTS, delegate->NewCallback());
-
-    delegate->WaitForResponse();
-
-    ASSERT_TRUE(delegate->completed());
-    EXPECT_EQ(404, delegate->response().HttpStatusCode());
-  }
-
-  void ResourceFetcherDidFailOnRenderer() {
-    blink::WebLocalFrame* frame =
-        GetRenderView()->GetWebView()->MainFrame()->ToWebLocalFrame();
-
-    // Try to fetch a page on a site that doesn't exist.
-    GURL url("http://localhost:1339/doesnotexist");
-    std::unique_ptr<FetcherDelegate> delegate(new FetcherDelegate);
-    std::unique_ptr<ResourceFetcher> fetcher(ResourceFetcher::Create(url));
-    fetcher->Start(frame, blink::mojom::RequestContextType::INTERNAL,
-                   RenderFrame::FromWebFrame(frame)->GetURLLoaderFactory(),
-                   TRAFFIC_ANNOTATION_FOR_TESTS, delegate->NewCallback());
-
-    delegate->WaitForResponse();
-
-    // When we fail, we still call the Delegate callback but we pass in empty
-    // values.
-    EXPECT_TRUE(delegate->completed());
-    EXPECT_TRUE(delegate->response().IsNull());
-    EXPECT_EQ(std::string(), delegate->data());
-    EXPECT_FALSE(delegate->timed_out());
-  }
-
-  void ResourceFetcherTimeoutOnRenderer(const GURL& url) {
-    blink::WebLocalFrame* frame =
-        GetRenderView()->GetWebView()->MainFrame()->ToWebLocalFrame();
-
-    std::unique_ptr<FetcherDelegate> delegate(new FetcherDelegate);
-    std::unique_ptr<ResourceFetcher> fetcher(ResourceFetcher::Create(url));
-    fetcher->Start(frame, blink::mojom::RequestContextType::INTERNAL,
-                   RenderFrame::FromWebFrame(frame)->GetURLLoaderFactory(),
-                   TRAFFIC_ANNOTATION_FOR_TESTS, delegate->NewCallback());
-    fetcher->SetTimeout(base::TimeDelta());
-
-    delegate->WaitForResponse();
-
-    // When we timeout, we still call the Delegate callback but we pass in empty
-    // values.
-    EXPECT_TRUE(delegate->completed());
-    EXPECT_TRUE(delegate->response().IsNull());
-    EXPECT_EQ(std::string(), delegate->data());
-    EXPECT_FALSE(delegate->timed_out());
-  }
-
-  void ResourceFetcherDeletedInCallbackOnRenderer(const GURL& url) {
-    blink::WebLocalFrame* frame =
-        GetRenderView()->GetWebView()->MainFrame()->ToWebLocalFrame();
-
-    std::unique_ptr<EvilFetcherDelegate> delegate(new EvilFetcherDelegate);
-    std::unique_ptr<ResourceFetcher> fetcher(ResourceFetcher::Create(url));
-    fetcher->Start(frame, blink::mojom::RequestContextType::INTERNAL,
-                   RenderFrame::FromWebFrame(frame)->GetURLLoaderFactory(),
-                   TRAFFIC_ANNOTATION_FOR_TESTS, delegate->NewCallback());
-    fetcher->SetTimeout(base::TimeDelta());
-    delegate->SetFetcher(fetcher.release());
-
-    delegate->WaitForResponse();
-    EXPECT_FALSE(delegate->timed_out());
-  }
-
-  void ResourceFetcherPost(const GURL& url) {
-    const char* kBody = "Really nifty POST body!";
-
-    blink::WebLocalFrame* frame =
-        GetRenderView()->GetWebView()->MainFrame()->ToWebLocalFrame();
-
-    std::unique_ptr<FetcherDelegate> delegate(new FetcherDelegate);
-    std::unique_ptr<ResourceFetcher> fetcher(ResourceFetcher::Create(url));
-    fetcher->SetMethod("POST");
-    fetcher->SetBody(kBody);
-    fetcher->Start(frame, blink::mojom::RequestContextType::INTERNAL,
-                   RenderFrame::FromWebFrame(frame)->GetURLLoaderFactory(),
-                   TRAFFIC_ANNOTATION_FOR_TESTS, delegate->NewCallback());
-
-    delegate->WaitForResponse();
-    ASSERT_TRUE(delegate->completed());
-    EXPECT_EQ(200, delegate->response().HttpStatusCode());
-    EXPECT_EQ(kBody, delegate->data());
-  }
-
-  void ResourceFetcherSetHeader(const GURL& url) {
-    const char* kHeader = "Rather boring header.";
-
-    blink::WebLocalFrame* frame =
-        GetRenderView()->GetWebView()->MainFrame()->ToWebLocalFrame();
-
-    std::unique_ptr<FetcherDelegate> delegate(new FetcherDelegate);
-    std::unique_ptr<ResourceFetcher> fetcher(ResourceFetcher::Create(url));
-    fetcher->SetHeader("header", kHeader);
-    fetcher->Start(frame, blink::mojom::RequestContextType::INTERNAL,
-                   RenderFrame::FromWebFrame(frame)->GetURLLoaderFactory(),
-                   TRAFFIC_ANNOTATION_FOR_TESTS, delegate->NewCallback());
-
-    delegate->WaitForResponse();
-    ASSERT_TRUE(delegate->completed());
-    EXPECT_EQ(200, delegate->response().HttpStatusCode());
-    EXPECT_EQ(kHeader, delegate->data());
-  }
-
-  int32_t render_view_routing_id_;
-};
-
-// Test a fetch from the test server.
-// If this flakes, use http://crbug.com/51622.
-IN_PROC_BROWSER_TEST_F(ResourceFetcherTests, ResourceFetcherDownload) {
-  // Need to spin up the renderer to same-site URL.
-  ASSERT_TRUE(embedded_test_server()->Start());
-  NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
-
-  GURL url(embedded_test_server()->GetURL("/simple_page.html"));
-
-  PostTaskToInProcessRendererAndWait(
-      base::BindOnce(&ResourceFetcherTests::ResourceFetcherDownloadOnRenderer,
-                     base::Unretained(this), url));
-}
-
-// Test if ResourceFetcher can handle server redirects correctly.
-IN_PROC_BROWSER_TEST_F(ResourceFetcherTests, ResourceFetcherRedirect) {
-  // Need to spin up the renderer to same-site URL.
-  ASSERT_TRUE(embedded_test_server()->Start());
-  NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
-
-  GURL final_url(embedded_test_server()->GetURL("/simple_page.html"));
-  GURL url(
-      embedded_test_server()->GetURL("/server-redirect?" + final_url.spec()));
-
-  PostTaskToInProcessRendererAndWait(
-      base::BindOnce(&ResourceFetcherTests::ResourceFetcherRedirectOnRenderer,
-                     base::Unretained(this), url, final_url));
-}
-
-IN_PROC_BROWSER_TEST_F(ResourceFetcherTests, ResourceFetcher404) {
-  // Need to spin up the renderer to same-site URL.
-  ASSERT_TRUE(embedded_test_server()->Start());
-  NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
-
-  // Test 404 response.
-  GURL url = embedded_test_server()->GetURL("/thisfiledoesntexist.html");
-
-  PostTaskToInProcessRendererAndWait(
-      base::BindOnce(&ResourceFetcherTests::ResourceFetcher404OnRenderer,
-                     base::Unretained(this), url));
-}
-
-// If this flakes, use http://crbug.com/51622.
-IN_PROC_BROWSER_TEST_F(ResourceFetcherTests, ResourceFetcherDidFail) {
-  // Need to spin up the renderer.
-  NavigateToURL(shell(), GURL(url::kAboutBlankURL));
-
-  PostTaskToInProcessRendererAndWait(
-      base::BindOnce(&ResourceFetcherTests::ResourceFetcherDidFailOnRenderer,
-                     base::Unretained(this)));
-}
-
-IN_PROC_BROWSER_TEST_F(ResourceFetcherTests, ResourceFetcherTimeout) {
-  // Need to spin up the renderer to same-site URL.
-  ASSERT_TRUE(embedded_test_server()->Start());
-  NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
-
-  // Grab a page that takes at least 1 sec to respond, but set the fetcher to
-  // timeout in 0 sec.
-  GURL url(embedded_test_server()->GetURL("/slow?1"));
-
-  PostTaskToInProcessRendererAndWait(
-      base::BindOnce(&ResourceFetcherTests::ResourceFetcherTimeoutOnRenderer,
-                     base::Unretained(this), url));
-}
-
-IN_PROC_BROWSER_TEST_F(ResourceFetcherTests, ResourceFetcherDeletedInCallback) {
-  // Need to spin up the renderer to same-site URL.
-  ASSERT_TRUE(embedded_test_server()->Start());
-  NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
-
-  // Grab a page that takes at least 1 sec to respond, but set the fetcher to
-  // timeout in 0 sec.
-  GURL url(embedded_test_server()->GetURL("/slow?1"));
-
-  PostTaskToInProcessRendererAndWait(base::BindOnce(
-      &ResourceFetcherTests::ResourceFetcherDeletedInCallbackOnRenderer,
-      base::Unretained(this), url));
-}
-
-// Test that ResourceFetchers can handle POSTs.
-IN_PROC_BROWSER_TEST_F(ResourceFetcherTests, ResourceFetcherPost) {
-  // Need to spin up the renderer to same-site URL.
-  ASSERT_TRUE(embedded_test_server()->Start());
-  NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
-
-  // Grab a page that echos the POST body.
-  GURL url(embedded_test_server()->GetURL("/echo"));
-
-  PostTaskToInProcessRendererAndWait(base::BindOnce(
-      &ResourceFetcherTests::ResourceFetcherPost, base::Unretained(this), url));
-}
-
-// Test that ResourceFetchers can set headers.
-IN_PROC_BROWSER_TEST_F(ResourceFetcherTests, ResourceFetcherSetHeader) {
-  // Need to spin up the renderer to same-site URL.
-  ASSERT_TRUE(embedded_test_server()->Start());
-  NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
-
-  // Grab a page that echos the POST body.
-  GURL url(embedded_test_server()->GetURL("/echoheader?header"));
-
-  PostTaskToInProcessRendererAndWait(
-      base::BindOnce(&ResourceFetcherTests::ResourceFetcherSetHeader,
-                     base::Unretained(this), url));
-}
-
-}  // namespace content
diff --git a/content/renderer/fetchers/resource_fetcher_impl.cc b/content/renderer/fetchers/resource_fetcher_impl.cc
deleted file mode 100644
index 96faed0..0000000
--- a/content/renderer/fetchers/resource_fetcher_impl.cc
+++ /dev/null
@@ -1,356 +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 "content/renderer/fetchers/resource_fetcher_impl.h"
-
-#include <stdint.h>
-
-#include <memory>
-#include <string>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/single_thread_task_runner.h"
-#include "content/public/common/referrer.h"
-#include "content/public/renderer/render_frame.h"
-#include "content/renderer/loader/resource_dispatcher.h"
-#include "content/renderer/loader/web_url_request_util.h"
-#include "mojo/public/cpp/bindings/binding.h"
-#include "net/base/net_errors.h"
-#include "net/http/http_request_headers.h"
-#include "net/url_request/url_request_context.h"
-#include "services/network/public/cpp/resource_request_body.h"
-#include "services/network/public/cpp/shared_url_loader_factory.h"
-#include "services/network/public/mojom/url_loader_factory.mojom.h"
-#include "third_party/blink/public/platform/web_security_origin.h"
-#include "third_party/blink/public/platform/web_string.h"
-#include "third_party/blink/public/platform/web_url.h"
-#include "third_party/blink/public/platform/web_url_response.h"
-#include "third_party/blink/public/web/web_document.h"
-#include "third_party/blink/public/web/web_local_frame.h"
-
-namespace {
-
-constexpr int32_t kRoutingId = 0;
-
-}  // namespace
-
-namespace content {
-
-// static
-std::unique_ptr<ResourceFetcher> ResourceFetcher::Create(const GURL& url) {
-  // Can not use std::make_unique<> because the constructor is private.
-  return std::unique_ptr<ResourceFetcher>(new ResourceFetcherImpl(url));
-}
-
-// TODO(toyoshim): Internal implementation might be replaced with
-// SimpleURLLoader, and content::ResourceFetcher could be a thin-wrapper
-// class to use SimpleURLLoader with blink-friendly types.
-class ResourceFetcherImpl::ClientImpl : public network::mojom::URLLoaderClient {
- public:
-  ClientImpl(ResourceFetcherImpl* parent,
-             StartCallback callback,
-             size_t maximum_download_size,
-             scoped_refptr<base::SingleThreadTaskRunner> task_runner)
-      : parent_(parent),
-        client_binding_(this),
-        data_pipe_watcher_(FROM_HERE,
-                           mojo::SimpleWatcher::ArmingPolicy::MANUAL,
-                           std::move(task_runner)),
-        status_(Status::kNotStarted),
-        completed_(false),
-        maximum_download_size_(maximum_download_size),
-        callback_(std::move(callback)) {}
-
-  ~ClientImpl() override {
-    callback_.Reset();
-    Cancel();
-  }
-
-  void Start(const network::ResourceRequest& request,
-             scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
-             const net::NetworkTrafficAnnotationTag& annotation_tag,
-             scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
-    status_ = Status::kStarted;
-    response_.SetCurrentRequestUrl(request.url);
-
-    network::mojom::URLLoaderClientPtr client;
-    client_binding_.Bind(mojo::MakeRequest(&client), std::move(task_runner));
-
-    url_loader_factory->CreateLoaderAndStart(
-        mojo::MakeRequest(&loader_), kRoutingId,
-        ResourceDispatcher::MakeRequestID(), network::mojom::kURLLoadOptionNone,
-        request, std::move(client),
-        net::MutableNetworkTrafficAnnotationTag(annotation_tag));
-  }
-
-  void Cancel() {
-    ClearReceivedDataToFail();
-    completed_ = true;
-    Close();
-  }
-
-  bool IsActive() const {
-    return status_ == Status::kStarted || status_ == Status::kFetching ||
-           status_ == Status::kClosed;
-  }
-
- private:
-  enum class Status {
-    kNotStarted,  // Initial state.
-    kStarted,     // Start() is called, but data pipe is not ready yet.
-    kFetching,    // Fetching via data pipe.
-    kClosed,      // Data pipe is already closed, but may not be completed yet.
-    kCompleted,   // Final state.
-  };
-
-  void MayComplete() {
-    DCHECK(IsActive()) << "status: " << static_cast<int>(status_);
-    DCHECK_NE(Status::kCompleted, status_);
-
-    if (status_ == Status::kFetching || !completed_)
-      return;
-
-    status_ = Status::kCompleted;
-    loader_.reset();
-
-    parent_->OnLoadComplete();
-
-    if (callback_.is_null())
-      return;
-
-    std::move(callback_).Run(response_, data_);
-  }
-
-  void ClearReceivedDataToFail() {
-    response_ = blink::WebURLResponse();
-    data_.clear();
-  }
-
-  void ReadDataPipe() {
-    DCHECK_EQ(Status::kFetching, status_);
-
-    for (;;) {
-      const void* data;
-      uint32_t size;
-      MojoResult result =
-          data_pipe_->BeginReadData(&data, &size, MOJO_READ_DATA_FLAG_NONE);
-      if (result == MOJO_RESULT_SHOULD_WAIT) {
-        data_pipe_watcher_.ArmOrNotify();
-        return;
-      }
-
-      if (result == MOJO_RESULT_FAILED_PRECONDITION) {
-        // Complete to read the data pipe successfully.
-        Close();
-        return;
-      }
-      DCHECK_EQ(MOJO_RESULT_OK, result);  // Only program errors can fire.
-
-      if (data_.size() + size > maximum_download_size_) {
-        data_pipe_->EndReadData(size);
-        Cancel();
-        return;
-      }
-
-      data_.append(static_cast<const char*>(data), size);
-
-      result = data_pipe_->EndReadData(size);
-      DCHECK_EQ(MOJO_RESULT_OK, result);  // Only program errors can fire.
-    }
-  }
-
-  void Close() {
-    if (status_ == Status::kFetching) {
-      data_pipe_watcher_.Cancel();
-      data_pipe_.reset();
-    }
-    status_ = Status::kClosed;
-    MayComplete();
-  }
-
-  void OnDataPipeSignaled(MojoResult result,
-                          const mojo::HandleSignalsState& state) {
-    ReadDataPipe();
-  }
-
-  // network::mojom::URLLoaderClient overrides:
-  void OnReceiveResponse(
-      const network::ResourceResponseHead& response_head) override {
-    DCHECK_EQ(Status::kStarted, status_);
-    // Existing callers need URL and HTTP status code. URL is already set in
-    // Start().
-    if (response_head.headers)
-      response_.SetHttpStatusCode(response_head.headers->response_code());
-  }
-  void OnReceiveRedirect(
-      const net::RedirectInfo& redirect_info,
-      const network::ResourceResponseHead& response_head) override {
-    DCHECK_EQ(Status::kStarted, status_);
-    loader_->FollowRedirect({}, {}, base::nullopt);
-    response_.SetCurrentRequestUrl(redirect_info.new_url);
-  }
-  void OnUploadProgress(int64_t current_position,
-                        int64_t total_size,
-                        OnUploadProgressCallback ack_callback) override {}
-  void OnReceiveCachedMetadata(mojo_base::BigBuffer data) override {}
-  void OnTransferSizeUpdated(int32_t transfer_size_diff) override {}
-  void OnStartLoadingResponseBody(
-      mojo::ScopedDataPipeConsumerHandle body) override {
-    DCHECK_EQ(Status::kStarted, status_);
-    status_ = Status::kFetching;
-
-    data_pipe_ = std::move(body);
-    data_pipe_watcher_.Watch(
-        data_pipe_.get(),
-        MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
-        MOJO_WATCH_CONDITION_SATISFIED,
-        base::BindRepeating(
-            &ResourceFetcherImpl::ClientImpl::OnDataPipeSignaled,
-            base::Unretained(this)));
-    ReadDataPipe();
-  }
-  void OnComplete(const network::URLLoaderCompletionStatus& status) override {
-    // When Cancel() sets |complete_|, OnComplete() may be called.
-    if (completed_)
-      return;
-
-    DCHECK(IsActive()) << "status: " << static_cast<int>(status_);
-    if (status.error_code != net::OK) {
-      ClearReceivedDataToFail();
-      Close();
-    }
-    completed_ = true;
-    MayComplete();
-  }
-
- private:
-  ResourceFetcherImpl* parent_;
-  network::mojom::URLLoaderPtr loader_;
-  mojo::Binding<network::mojom::URLLoaderClient> client_binding_;
-  mojo::ScopedDataPipeConsumerHandle data_pipe_;
-  mojo::SimpleWatcher data_pipe_watcher_;
-
-  Status status_;
-
-  // A flag to represent if OnComplete() is already called. |data_pipe_| can be
-  // ready even after OnComplete() is called.
-  bool completed_;
-
-  // Maximum download size to be stored in |data_|.
-  const size_t maximum_download_size_;
-
-  // Received data to be passed to the |callback_|.
-  std::string data_;
-
-  // Response to be passed to the |callback_|.
-  blink::WebURLResponse response_;
-
-  // Callback when we're done.
-  StartCallback callback_;
-
-  DISALLOW_COPY_AND_ASSIGN(ClientImpl);
-};
-
-ResourceFetcherImpl::ResourceFetcherImpl(const GURL& url) {
-  DCHECK(url.is_valid());
-  request_.url = url;
-}
-
-ResourceFetcherImpl::~ResourceFetcherImpl() {
-  client_.reset();
-}
-
-void ResourceFetcherImpl::SetMethod(const std::string& method) {
-  DCHECK(!client_);
-  request_.method = method;
-}
-
-void ResourceFetcherImpl::SetBody(const std::string& body) {
-  DCHECK(!client_);
-  request_.request_body =
-      network::ResourceRequestBody::CreateFromBytes(body.data(), body.size());
-}
-
-void ResourceFetcherImpl::SetHeader(const std::string& header,
-                                    const std::string& value) {
-  DCHECK(!client_);
-  if (base::LowerCaseEqualsASCII(header, net::HttpRequestHeaders::kReferer)) {
-    request_.referrer = GURL(value);
-    DCHECK(request_.referrer.is_valid());
-    request_.referrer_policy = Referrer::GetDefaultReferrerPolicy();
-  } else {
-    request_.headers.SetHeader(header, value);
-  }
-}
-
-void ResourceFetcherImpl::SetFetchRequestMode(
-    network::mojom::FetchRequestMode fetch_request_mode) {
-  request_.fetch_request_mode = fetch_request_mode;
-}
-
-void ResourceFetcherImpl::Start(
-    blink::WebLocalFrame* frame,
-    blink::mojom::RequestContextType request_context,
-    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
-    const net::NetworkTrafficAnnotationTag& annotation_tag,
-    StartCallback callback,
-    size_t maximum_download_size) {
-  DCHECK(!client_);
-  DCHECK(frame);
-  DCHECK(url_loader_factory);
-  DCHECK(!frame->GetDocument().IsNull());
-  if (request_.method.empty())
-    request_.method = net::HttpRequestHeaders::kGetMethod;
-  if (request_.request_body) {
-    DCHECK(!base::LowerCaseEqualsASCII(request_.method,
-                                       net::HttpRequestHeaders::kGetMethod))
-        << "GETs can't have bodies.";
-  }
-
-  request_.fetch_request_context_type = static_cast<int>(request_context);
-  request_.site_for_cookies = frame->GetDocument().SiteForCookies();
-  if (!frame->GetDocument().GetSecurityOrigin().IsNull()) {
-    request_.request_initiator =
-        static_cast<url::Origin>(frame->GetDocument().GetSecurityOrigin());
-    SetHeader(net::HttpRequestHeaders::kOrigin,
-              blink::WebSecurityOrigin::CreateUnique().ToString().Ascii());
-  }
-  request_.resource_type =
-      static_cast<int>(RequestContextToResourceType(request_context));
-
-  client_ = std::make_unique<ClientImpl>(
-      this, std::move(callback), maximum_download_size,
-      frame->GetTaskRunner(blink::TaskType::kNetworking));
-  // TODO(kinuko, toyoshim): This task runner should be given by the consumer
-  // of this class.
-  client_->Start(request_, std::move(url_loader_factory), annotation_tag,
-                 frame->GetTaskRunner(blink::TaskType::kNetworking));
-
-  // No need to hold on to the request; reset it now.
-  request_ = network::ResourceRequest();
-}
-
-void ResourceFetcherImpl::SetTimeout(const base::TimeDelta& timeout) {
-  DCHECK(client_);
-  DCHECK(client_->IsActive());
-  DCHECK(!timeout_timer_.IsRunning());
-
-  timeout_timer_.Start(FROM_HERE, timeout, this,
-                       &ResourceFetcherImpl::OnTimeout);
-}
-
-void ResourceFetcherImpl::OnLoadComplete() {
-  timeout_timer_.Stop();
-}
-
-void ResourceFetcherImpl::OnTimeout() {
-  DCHECK(client_);
-  DCHECK(client_->IsActive());
-  client_->Cancel();
-}
-
-}  // namespace content
diff --git a/content/renderer/fetchers/resource_fetcher_impl.h b/content/renderer/fetchers/resource_fetcher_impl.h
deleted file mode 100644
index 6a3b3a6..0000000
--- a/content/renderer/fetchers/resource_fetcher_impl.h
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright (c) 2011 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_RENDERER_FETCHERS_RESOURCE_FETCHER_IMPL_H_
-#define CONTENT_RENDERER_FETCHERS_RESOURCE_FETCHER_IMPL_H_
-
-#include <memory>
-#include <string>
-
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/time/time.h"
-#include "base/timer/timer.h"
-#include "content/public/renderer/resource_fetcher.h"
-#include "net/http/http_request_headers.h"
-#include "services/network/public/cpp/resource_request.h"
-#include "third_party/blink/public/platform/web_url_request.h"
-
-class GURL;
-
-namespace blink {
-class WebLocalFrame;
-}
-
-namespace content {
-
-class ResourceFetcherImpl : public ResourceFetcher {
- public:
-  // ResourceFetcher implementation:
-  void SetMethod(const std::string& method) override;
-  void SetBody(const std::string& body) override;
-  void SetHeader(const std::string& header, const std::string& value) override;
-  void SetFetchRequestMode(
-      network::mojom::FetchRequestMode fetch_request_mode) override;
-  void Start(blink::WebLocalFrame* frame,
-             blink::mojom::RequestContextType request_context,
-             scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
-             const net::NetworkTrafficAnnotationTag& annotation_tag,
-             StartCallback callback,
-             size_t maximum_download_size) override;
-  void SetTimeout(const base::TimeDelta& timeout) override;
-
- private:
-  friend class ResourceFetcher;
-
-  class ClientImpl;
-
-  explicit ResourceFetcherImpl(const GURL& url);
-
-  ~ResourceFetcherImpl() override;
-
-  void OnLoadComplete();
-  void OnTimeout();
-
-  std::unique_ptr<ClientImpl> client_;
-
-  // Request to send.
-  network::ResourceRequest request_;
-
-  // Limit how long to wait for the server.
-  base::OneShotTimer timeout_timer_;
-
-  DISALLOW_COPY_AND_ASSIGN(ResourceFetcherImpl);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_RENDERER_FETCHERS_RESOURCE_FETCHER_IMPL_H_
diff --git a/content/renderer/loader/web_worker_fetch_context_impl.cc b/content/renderer/loader/web_worker_fetch_context_impl.cc
index 1c845f8..861df1d 100644
--- a/content/renderer/loader/web_worker_fetch_context_impl.cc
+++ b/content/renderer/loader/web_worker_fetch_context_impl.cc
@@ -191,11 +191,11 @@
           ChildThreadImpl::current()->thread_safe_sender(),
           ChildThreadImpl::current()->GetConnector()->Clone()));
   if (provider_context) {
-    worker_fetch_context->set_is_controlled_by_service_worker(
-        provider_context->IsControlledByServiceWorker());
+    worker_fetch_context->set_controller_service_worker_mode(
+        provider_context->GetControllerServiceWorkerMode());
     worker_fetch_context->set_client_id(provider_context->client_id());
   } else {
-    worker_fetch_context->set_is_controlled_by_service_worker(
+    worker_fetch_context->set_controller_service_worker_mode(
         blink::mojom::ControllerServiceWorkerMode::kNoController);
   }
   return worker_fetch_context;
@@ -272,8 +272,8 @@
           std::move(service_worker_worker_client_registry_ptr_info),
           std::move(host_ptr_info), loader_factory_->Clone(),
           fallback_factory_->Clone(), std::move(task_runner));
-  new_context->is_controlled_by_service_worker_ =
-      is_controlled_by_service_worker_;
+  new_context->controller_service_worker_mode_ =
+      controller_service_worker_mode_;
 
   return new_context;
 }
@@ -310,8 +310,8 @@
           std::move(service_worker_worker_client_registry_ptr_info),
           std::move(container_host_ptr_info), std::move(loader_factory_info),
           std::move(fallback_factory_info), std::move(task_runner));
-  new_context->is_controlled_by_service_worker_ =
-      service_worker_provider_context->IsControlledByServiceWorker();
+  new_context->controller_service_worker_mode_ =
+      service_worker_provider_context->GetControllerServiceWorkerMode();
 
   return new_context;
 }
@@ -418,8 +418,8 @@
 }
 
 blink::mojom::ControllerServiceWorkerMode
-WebWorkerFetchContextImpl::IsControlledByServiceWorker() const {
-  return is_controlled_by_service_worker_;
+WebWorkerFetchContextImpl::GetControllerServiceWorkerMode() const {
+  return controller_service_worker_mode_;
 }
 
 void WebWorkerFetchContextImpl::SetIsOnSubframe(bool is_on_sub_frame) {
@@ -480,9 +480,9 @@
       ancestor_frame_id_, std::move(task_runner));
 }
 
-void WebWorkerFetchContextImpl::set_is_controlled_by_service_worker(
+void WebWorkerFetchContextImpl::set_controller_service_worker_mode(
     blink::mojom::ControllerServiceWorkerMode mode) {
-  is_controlled_by_service_worker_ = mode;
+  controller_service_worker_mode_ = mode;
 }
 
 void WebWorkerFetchContextImpl::set_ancestor_frame_id(int id) {
@@ -530,7 +530,7 @@
 
 void WebWorkerFetchContextImpl::OnControllerChanged(
     blink::mojom::ControllerServiceWorkerMode mode) {
-  set_is_controlled_by_service_worker(mode);
+  set_controller_service_worker_mode(mode);
   ResetServiceWorkerURLLoaderFactory();
 }
 
@@ -573,7 +573,7 @@
 void WebWorkerFetchContextImpl::ResetServiceWorkerURLLoaderFactory() {
   if (!web_loader_factory_)
     return;
-  if (IsControlledByServiceWorker() !=
+  if (GetControllerServiceWorkerMode() !=
       blink::mojom::ControllerServiceWorkerMode::kControlled) {
     web_loader_factory_->SetServiceWorkerURLLoaderFactory(nullptr);
     return;
diff --git a/content/renderer/loader/web_worker_fetch_context_impl.h b/content/renderer/loader/web_worker_fetch_context_impl.h
index 7972502..a502db03 100644
--- a/content/renderer/loader/web_worker_fetch_context_impl.h
+++ b/content/renderer/loader/web_worker_fetch_context_impl.h
@@ -100,7 +100,7 @@
       mojo::ScopedMessagePipeHandle url_loader_factory_handle) override;
   std::unique_ptr<blink::CodeCacheLoader> CreateCodeCacheLoader() override;
   void WillSendRequest(blink::WebURLRequest&) override;
-  blink::mojom::ControllerServiceWorkerMode IsControlledByServiceWorker()
+  blink::mojom::ControllerServiceWorkerMode GetControllerServiceWorkerMode()
       const override;
   void SetIsOnSubframe(bool) override;
   bool IsOnSubframe() const override;
@@ -126,7 +126,7 @@
   // it's copied from the ancestor frame (directly for non-nested workers, or
   // indirectly via its parent worker for nested workers). For shared workers,
   // it's copied from the shadow page.
-  void set_is_controlled_by_service_worker(
+  void set_controller_service_worker_mode(
       blink::mojom::ControllerServiceWorkerMode mode);
   void set_ancestor_frame_id(int id);
   void set_frame_request_blocker(
@@ -221,7 +221,7 @@
   // Consumed on the worker thread to create |fallback_factory_|.
   std::unique_ptr<network::SharedURLLoaderFactoryInfo> fallback_factory_info_;
 
-  blink::mojom::ControllerServiceWorkerMode is_controlled_by_service_worker_ =
+  blink::mojom::ControllerServiceWorkerMode controller_service_worker_mode_ =
       blink::mojom::ControllerServiceWorkerMode::kNoController;
 
   // Initialized on the worker thread when InitializeOnWorkerThread() is called.
diff --git a/content/renderer/media/stream/media_stream_audio_processor.cc b/content/renderer/media/stream/media_stream_audio_processor.cc
index 7e76f7aa..4f99d26b 100644
--- a/content/renderer/media/stream/media_stream_audio_processor.cc
+++ b/content/renderer/media/stream/media_stream_audio_processor.cc
@@ -48,7 +48,6 @@
 namespace {
 
 using webrtc::AudioProcessing;
-using NoiseSuppression = webrtc::AudioProcessing::Config::NoiseSuppression;
 
 constexpr int kAudioProcessingNumberOfChannels = 1;
 constexpr int kBuffersPerSecond = 100;  // 10 ms per buffer.
@@ -609,16 +608,11 @@
     playout_data_source_->AddPlayoutSink(this);
   }
 
-  // TODO(saza): When Chrome uses AGC2, handle all JSON config via the
-  // webrtc::AudioProcessing::Config, crbug.com/895814.
-  base::Optional<double> pre_amplifier_fixed_gain_factor,
-      gain_control_compression_gain_db;
-  blink::GetExtraGainConfig(audio_processing_platform_config_json,
-                            &pre_amplifier_fixed_gain_factor,
-                            &gain_control_compression_gain_db);
-
   webrtc::AudioProcessing::Config apm_config = audio_processing_->GetConfig();
-  apm_config.high_pass_filter.enabled = properties.goog_highpass_filter;
+  base::Optional<double> gain_control_compression_gain_db;
+  blink::PopulateApmConfig(&apm_config, properties,
+                           audio_processing_platform_config_json,
+                           &gain_control_compression_gain_db);
 
   if (properties.goog_auto_gain_control ||
       properties.goog_experimental_auto_gain_control) {
@@ -642,19 +636,13 @@
         use_peaks_not_rms, saturation_margin, gain_control_compression_gain_db);
   }
 
-  blink::ConfigPreAmplifier(&apm_config, pre_amplifier_fixed_gain_factor);
   if (goog_typing_detection) {
     // TODO(xians): Remove this |typing_detector_| after the typing suppression
     // is enabled by default.
     typing_detector_.reset(new webrtc::TypingDetection());
     blink::EnableTypingDetection(&apm_config, typing_detector_.get());
   }
-  if (properties.goog_noise_suppression) {
-    blink::EnableNoiseSuppression(&apm_config, NoiseSuppression::kHigh);
-  }
-  if (properties.EchoCancellationIsWebRtcProvided()) {
-    blink::EnableEchoCancellation(&apm_config);
-  }
+
   audio_processing_->ApplyConfig(apm_config);
 
   RecordProcessingState(AUDIO_PROCESSING_ENABLED);
diff --git a/content/renderer/media/stream/media_stream_audio_processor_unittest.cc b/content/renderer/media/stream/media_stream_audio_processor_unittest.cc
index 7765a57..764a7ea 100644
--- a/content/renderer/media/stream/media_stream_audio_processor_unittest.cc
+++ b/content/renderer/media/stream/media_stream_audio_processor_unittest.cc
@@ -420,28 +420,4 @@
   audio_processor->Stop();
 }
 
-TEST_F(MediaStreamAudioProcessorTest, GetExtraGainConfigNullOpt) {
-  base::Optional<std::string> audio_processing_platform_config_json;
-  base::Optional<double> pre_amplifier_fixed_gain_factor,
-      gain_control_compression_gain_db;
-  blink::GetExtraGainConfig(audio_processing_platform_config_json,
-                            &pre_amplifier_fixed_gain_factor,
-                            &gain_control_compression_gain_db);
-  EXPECT_FALSE(pre_amplifier_fixed_gain_factor);
-  EXPECT_FALSE(gain_control_compression_gain_db);
-}
-
-TEST_F(MediaStreamAudioProcessorTest, GetExtraGainConfig) {
-  base::Optional<std::string> audio_processing_platform_config_json =
-      "{\"gain_control_compression_gain_db\": 10}";
-  base::Optional<double> pre_amplifier_fixed_gain_factor,
-      gain_control_compression_gain_db;
-  blink::GetExtraGainConfig(audio_processing_platform_config_json,
-                            &pre_amplifier_fixed_gain_factor,
-                            &gain_control_compression_gain_db);
-  EXPECT_FALSE(pre_amplifier_fixed_gain_factor);
-  EXPECT_TRUE(gain_control_compression_gain_db);
-  EXPECT_EQ(gain_control_compression_gain_db.value(), 10);
-}
-
 }  // namespace content
diff --git a/content/renderer/media/stream/media_stream_renderer_factory_impl.cc b/content/renderer/media/stream/media_stream_renderer_factory_impl.cc
index befbb2f..cc8833f 100644
--- a/content/renderer/media/stream/media_stream_renderer_factory_impl.cc
+++ b/content/renderer/media/stream/media_stream_renderer_factory_impl.cc
@@ -7,7 +7,6 @@
 #include <utility>
 
 #include "base/strings/utf_string_conversions.h"
-#include "content/renderer/media/stream/media_stream_video_renderer_sink.h"
 #include "content/renderer/media/stream/track_audio_renderer.h"
 #include "content/renderer/media/webrtc/peer_connection_dependency_factory.h"
 #include "content/renderer/media/webrtc/peer_connection_remote_audio_source.h"
@@ -16,6 +15,7 @@
 #include "content/renderer/render_thread_impl.h"
 #include "third_party/blink/public/platform/modules/mediastream/media_stream_audio_track.h"
 #include "third_party/blink/public/platform/web_media_stream.h"
+#include "third_party/blink/public/web/modules/mediastream/media_stream_video_renderer_sink.h"
 #include "third_party/blink/public/web/modules/mediastream/media_stream_video_track.h"
 #include "third_party/webrtc/api/media_stream_interface.h"
 
@@ -68,9 +68,9 @@
     return nullptr;
   }
 
-  return new MediaStreamVideoRendererSink(video_tracks[0], repaint_cb,
-                                          std::move(io_task_runner),
-                                          std::move(main_render_task_runner));
+  return new blink::MediaStreamVideoRendererSink(
+      video_tracks[0], repaint_cb, std::move(io_task_runner),
+      std::move(main_render_task_runner));
 }
 
 scoped_refptr<blink::WebMediaStreamAudioRenderer>
diff --git a/content/renderer/media/stream/media_stream_video_source_unittest.cc b/content/renderer/media/stream/media_stream_video_source_unittest.cc
index d618bff..2f7b6c2 100644
--- a/content/renderer/media/stream/media_stream_video_source_unittest.cc
+++ b/content/renderer/media/stream/media_stream_video_source_unittest.cc
@@ -15,13 +15,13 @@
 #include "content/child/child_process.h"
 #include "content/renderer/media/stream/mock_constraint_factory.h"
 #include "content/renderer/media/stream/mock_media_stream_video_sink.h"
-#include "content/renderer/media/stream/mock_media_stream_video_source.h"
 #include "media/base/limits.h"
 #include "media/base/video_frame.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/mojom/mediastream/media_stream.mojom-shared.h"
 #include "third_party/blink/public/web/modules/mediastream/media_stream_video_source.h"
 #include "third_party/blink/public/web/modules/mediastream/media_stream_video_track.h"
+#include "third_party/blink/public/web/modules/mediastream/mock_media_stream_video_source.h"
 #include "third_party/blink/public/web/modules/mediastream/video_track_adapter_settings.h"
 #include "third_party/blink/public/web/web_heap.h"
 
@@ -41,7 +41,7 @@
         number_of_failed_constraints_applied_(0),
         result_(blink::mojom::MediaStreamRequestResult::OK),
         result_name_(""),
-        mock_source_(new MockMediaStreamVideoSource(
+        mock_source_(new blink::MockMediaStreamVideoSource(
             media::VideoCaptureFormat(gfx::Size(1280, 720),
                                       1000.0,
                                       media::PIXEL_FORMAT_I420),
@@ -128,7 +128,7 @@
   blink::mojom::MediaStreamRequestResult error_type() const { return result_; }
   blink::WebString error_name() const { return result_name_; }
 
-  MockMediaStreamVideoSource* mock_source() { return mock_source_; }
+  blink::MockMediaStreamVideoSource* mock_source() { return mock_source_; }
 
   const blink::WebMediaStreamSource& web_source() { return web_source_; }
 
@@ -264,7 +264,7 @@
   blink::WebString result_name_;
   blink::WebMediaStreamSource web_source_;
   // |mock_source_| is owned by |web_source_|.
-  MockMediaStreamVideoSource* mock_source_;
+  blink::MockMediaStreamVideoSource* mock_source_;
 };
 
 TEST_F(MediaStreamVideoSourceTest, AddTrackAndStartSource) {
diff --git a/content/renderer/media/stream/media_stream_video_track_unittest.cc b/content/renderer/media/stream/media_stream_video_track_unittest.cc
index e2a58cba..dfa498e2 100644
--- a/content/renderer/media/stream/media_stream_video_track_unittest.cc
+++ b/content/renderer/media/stream/media_stream_video_track_unittest.cc
@@ -15,10 +15,10 @@
 #include "base/threading/thread_checker_impl.h"
 #include "content/child/child_process.h"
 #include "content/renderer/media/stream/mock_media_stream_video_sink.h"
-#include "content/renderer/media/stream/mock_media_stream_video_source.h"
 #include "media/base/video_frame.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/web/modules/mediastream/media_stream_video_track.h"
+#include "third_party/blink/public/web/modules/mediastream/mock_media_stream_video_source.h"
 #include "third_party/blink/public/web/modules/mediastream/video_track_adapter_settings.h"
 #include "third_party/blink/public/web/web_heap.h"
 
@@ -72,7 +72,7 @@
  protected:
   void InitializeSource() {
     blink_source_.Reset();
-    mock_source_ = new MockMediaStreamVideoSource(
+    mock_source_ = new blink::MockMediaStreamVideoSource(
         media::VideoCaptureFormat(
             gfx::Size(kMockSourceWidth, kMockSourceHeight), 30.0,
             media::PIXEL_FORMAT_I420),
@@ -118,7 +118,7 @@
 
   void UpdateVideoSourceToRespondToRequestRefreshFrame() {
     blink_source_.Reset();
-    mock_source_ = new MockMediaStreamVideoSource(
+    mock_source_ = new blink::MockMediaStreamVideoSource(
         media::VideoCaptureFormat(
             gfx::Size(kMockSourceWidth, kMockSourceHeight), 30.0,
             media::PIXEL_FORMAT_I420),
@@ -130,7 +130,7 @@
     blink_source_.SetPlatformSource(base::WrapUnique(mock_source_));
   }
 
-  MockMediaStreamVideoSource* mock_source() { return mock_source_; }
+  blink::MockMediaStreamVideoSource* mock_source() { return mock_source_; }
   const blink::WebMediaStreamSource& blink_source() const {
     return blink_source_;
   }
@@ -142,7 +142,7 @@
   const ChildProcess child_process_;
   blink::WebMediaStreamSource blink_source_;
   // |mock_source_| is owned by |webkit_source_|.
-  MockMediaStreamVideoSource* mock_source_;
+  blink::MockMediaStreamVideoSource* mock_source_;
   bool source_started_;
 };
 
diff --git a/content/renderer/media/stream/user_media_client_impl_unittest.cc b/content/renderer/media/stream/user_media_client_impl_unittest.cc
index 5c34abe5..044e668a 100644
--- a/content/renderer/media/stream/user_media_client_impl_unittest.cc
+++ b/content/renderer/media/stream/user_media_client_impl_unittest.cc
@@ -19,7 +19,6 @@
 #include "content/renderer/media/stream/media_stream_constraints_util_video_content.h"
 #include "content/renderer/media/stream/media_stream_device_observer.h"
 #include "content/renderer/media/stream/mock_constraint_factory.h"
-#include "content/renderer/media/stream/mock_media_stream_video_source.h"
 #include "content/renderer/media/stream/mock_mojo_media_stream_dispatcher_host.h"
 #include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h"
 #include "media/audio/audio_device_description.h"
@@ -39,6 +38,7 @@
 #include "third_party/blink/public/platform/web_vector.h"
 #include "third_party/blink/public/web/modules/mediastream/media_stream_constraints_util.h"
 #include "third_party/blink/public/web/modules/mediastream/media_stream_video_track.h"
+#include "third_party/blink/public/web/modules/mediastream/mock_media_stream_video_source.h"
 #include "third_party/blink/public/web/web_heap.h"
 
 using testing::_;
@@ -154,12 +154,13 @@
   }
 };
 
-class MockMediaStreamVideoCapturerSource : public MockMediaStreamVideoSource {
+class MockMediaStreamVideoCapturerSource
+    : public blink::MockMediaStreamVideoSource {
  public:
   MockMediaStreamVideoCapturerSource(const blink::MediaStreamDevice& device,
                                      const SourceStoppedCallback& stop_callback,
                                      PeerConnectionDependencyFactory* factory)
-      : MockMediaStreamVideoSource() {
+      : blink::MockMediaStreamVideoSource() {
     SetDevice(device);
     SetStopCallback(stop_callback);
   }
diff --git a/content/renderer/media/webrtc/media_stream_video_webrtc_sink_unittest.cc b/content/renderer/media/webrtc/media_stream_video_webrtc_sink_unittest.cc
index e523d75..5d320439 100644
--- a/content/renderer/media/webrtc/media_stream_video_webrtc_sink_unittest.cc
+++ b/content/renderer/media/webrtc/media_stream_video_webrtc_sink_unittest.cc
@@ -7,10 +7,10 @@
 #include "base/test/scoped_task_environment.h"
 #include "content/child/child_process.h"
 #include "content/renderer/media/stream/mock_constraint_factory.h"
-#include "content/renderer/media/stream/mock_media_stream_registry.h"
 #include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
+#include "third_party/blink/public/web/modules/mediastream/mock_media_stream_registry.h"
 #include "third_party/blink/public/web/modules/mediastream/video_track_adapter_settings.h"
 
 namespace content {
@@ -49,7 +49,7 @@
   MockPeerConnectionDependencyFactory dependency_factory_;
 
  private:
-  MockMediaStreamRegistry registry_;
+  blink::MockMediaStreamRegistry registry_;
   // A ChildProcess is needed to fool the Tracks and Sources into believing they
   // are on the right threads. A ScopedTaskEnvironment must be instantiated
   // before ChildProcess to prevent it from leaking a ThreadPool.
diff --git a/content/renderer/media/webrtc/rtc_peer_connection_handler_unittest.cc b/content/renderer/media/webrtc/rtc_peer_connection_handler_unittest.cc
index 899f900..5165cd3 100644
--- a/content/renderer/media/webrtc/rtc_peer_connection_handler_unittest.cc
+++ b/content/renderer/media/webrtc/rtc_peer_connection_handler_unittest.cc
@@ -26,7 +26,6 @@
 #include "content/child/child_process.h"
 #include "content/renderer/media/audio/mock_audio_device_factory.h"
 #include "content/renderer/media/stream/mock_constraint_factory.h"
-#include "content/renderer/media/stream/mock_media_stream_video_source.h"
 #include "content/renderer/media/stream/processed_local_audio_source.h"
 #include "content/renderer/media/webrtc/mock_data_channel_impl.h"
 #include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h"
@@ -56,6 +55,7 @@
 #include "third_party/blink/public/platform/web_rtc_void_request.h"
 #include "third_party/blink/public/platform/web_url.h"
 #include "third_party/blink/public/web/modules/mediastream/media_stream_video_track.h"
+#include "third_party/blink/public/web/modules/mediastream/mock_media_stream_video_source.h"
 #include "third_party/blink/public/web/web_heap.h"
 #include "third_party/webrtc/api/peer_connection_interface.h"
 #include "third_party/webrtc/api/rtp_receiver_interface.h"
@@ -328,8 +328,8 @@
                             blink::WebMediaStreamSource::kTypeVideo,
                             blink::WebString::FromUTF8("video_track"),
                             false /* remote */);
-    MockMediaStreamVideoSource* native_video_source =
-        new MockMediaStreamVideoSource();
+    blink::MockMediaStreamVideoSource* native_video_source =
+        new blink::MockMediaStreamVideoSource();
     video_source.SetPlatformSource(base::WrapUnique(native_video_source));
 
     blink::WebVector<blink::WebMediaStreamTrack> audio_tracks(
diff --git a/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_unittest.cc b/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_unittest.cc
index f5fdf11..24bdea16 100644
--- a/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_unittest.cc
+++ b/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_unittest.cc
@@ -14,7 +14,6 @@
 #include "base/test/scoped_task_environment.h"
 #include "content/child/child_process.h"
 #include "content/renderer/media/stream/mock_media_stream_video_sink.h"
-#include "content/renderer/media/stream/mock_media_stream_video_source.h"
 #include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/platform/modules/mediastream/media_stream_audio_source.h"
@@ -23,6 +22,7 @@
 #include "third_party/blink/public/platform/web_media_stream_track.h"
 #include "third_party/blink/public/platform/web_string.h"
 #include "third_party/blink/public/web/modules/mediastream/media_stream_video_track.h"
+#include "third_party/blink/public/web/modules/mediastream/mock_media_stream_video_source.h"
 #include "third_party/blink/public/web/web_heap.h"
 
 namespace content {
@@ -68,7 +68,8 @@
                           blink::WebMediaStreamSource::kTypeVideo,
                           blink::WebString::FromUTF8("local_video_track"),
                           false);
-    MockMediaStreamVideoSource* video_source = new MockMediaStreamVideoSource();
+    blink::MockMediaStreamVideoSource* video_source =
+        new blink::MockMediaStreamVideoSource();
     // Takes ownership of |video_source|.
     web_source.SetPlatformSource(base::WrapUnique(video_source));
 
diff --git a/content/renderer/media_recorder/media_recorder_handler_unittest.cc b/content/renderer/media_recorder/media_recorder_handler_unittest.cc
index c5e244b4..ee44ed5 100644
--- a/content/renderer/media_recorder/media_recorder_handler_unittest.cc
+++ b/content/renderer/media_recorder/media_recorder_handler_unittest.cc
@@ -12,7 +12,6 @@
 #include "base/test/scoped_task_environment.h"
 #include "base/time/time.h"
 #include "content/child/child_process.h"
-#include "content/renderer/media/stream/mock_media_stream_registry.h"
 #include "content/renderer/media_recorder/media_recorder_handler.h"
 #include "media/audio/simple_sources.h"
 #include "media/base/audio_bus.h"
@@ -22,6 +21,7 @@
 #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
 #include "third_party/blink/public/platform/web_media_recorder_handler_client.h"
 #include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/public/web/modules/mediastream/mock_media_stream_registry.h"
 #include "third_party/blink/public/web/web_heap.h"
 
 using ::testing::_;
@@ -141,7 +141,7 @@
   // and Sources in |registry_| into believing they are on the right threads.
   const base::test::ScopedTaskEnvironment scoped_task_environment_;
   const ChildProcess child_process_;
-  MockMediaStreamRegistry registry_;
+  blink::MockMediaStreamRegistry registry_;
 
   // The Class under test. Needs to be scoped_ptr to force its destruction.
   std::unique_ptr<MediaRecorderHandler> media_recorder_handler_;
diff --git a/content/renderer/media_recorder/video_track_recorder_unittest.cc b/content/renderer/media_recorder/video_track_recorder_unittest.cc
index 72c83fc..540a622 100644
--- a/content/renderer/media_recorder/video_track_recorder_unittest.cc
+++ b/content/renderer/media_recorder/video_track_recorder_unittest.cc
@@ -19,7 +19,6 @@
 #include "base/test/scoped_task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "content/child/child_process.h"
-#include "content/renderer/media/stream/mock_media_stream_video_source.h"
 #include "media/base/video_codecs.h"
 #include "media/base/video_frame.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -27,6 +26,7 @@
 #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
 #include "third_party/blink/public/platform/web_string.h"
 #include "third_party/blink/public/web/modules/mediastream/media_stream_video_track.h"
+#include "third_party/blink/public/web/modules/mediastream/mock_media_stream_video_source.h"
 #include "third_party/blink/public/web/web_heap.h"
 
 using media::VideoFrame;
@@ -68,7 +68,7 @@
   VideoTrackRecorderTest()
       : scoped_task_environment_(
             base::test::ScopedTaskEnvironment::MainThreadType::UI),
-        mock_source_(new MockMediaStreamVideoSource()) {
+        mock_source_(new blink::MockMediaStreamVideoSource()) {
     const blink::WebString webkit_track_id(
         blink::WebString::FromASCII("dummy"));
     blink_source_.Initialize(webkit_track_id,
@@ -154,7 +154,7 @@
 
   // All members are non-const due to the series of initialize() calls needed.
   // |mock_source_| is owned by |blink_source_|, |track_| by |blink_track_|.
-  MockMediaStreamVideoSource* mock_source_;
+  blink::MockMediaStreamVideoSource* mock_source_;
   blink::WebMediaStreamSource blink_source_;
   blink::MediaStreamVideoTrack* track_;
   blink::WebMediaStreamTrack blink_track_;
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc
index 8bdf34b..72eb182 100644
--- a/content/renderer/renderer_blink_platform_impl.cc
+++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -69,7 +69,6 @@
 #include "mojo/public/cpp/bindings/strong_associated_binding.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "mojo/public/cpp/system/platform_handle.h"
-#include "net/base/features.h"
 #include "ppapi/buildflags/buildflags.h"
 #include "services/network/public/cpp/features.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
@@ -380,17 +379,12 @@
     base::Time response_time,
     const uint8_t* data,
     size_t size) {
-  // Only cache WebAssembly if we have isolated code caches.
-  // TODO(bbudge) Remove this check when isolated code caches are on by default.
-  if (cache_type == blink::mojom::CodeCacheType::kJavascript ||
-      base::FeatureList::IsEnabled(net::features::kIsolatedCodeCache)) {
-    // Let the browser know we generated cacheable metadata for this resource.
-    // The browser may cache it and return it on subsequent responses to speed
-    // the processing of this resource.
-    GetCodeCacheHost().DidGenerateCacheableMetadata(
-        cache_type, url, response_time,
-        mojo_base::BigBuffer(base::make_span(data, size)));
-  }
+  // Let the browser know we generated cacheable metadata for this resource.
+  // The browser may cache it and return it on subsequent responses to speed
+  // the processing of this resource.
+  GetCodeCacheHost().DidGenerateCacheableMetadata(
+      cache_type, url, response_time,
+      mojo_base::BigBuffer(base::make_span(data, size)));
 }
 
 void RendererBlinkPlatformImpl::FetchCachedCode(
diff --git a/content/renderer/service_worker/service_worker_fetch_context_impl.cc b/content/renderer/service_worker/service_worker_fetch_context_impl.cc
index 880bec6..edafeef 100644
--- a/content/renderer/service_worker/service_worker_fetch_context_impl.cc
+++ b/content/renderer/service_worker/service_worker_fetch_context_impl.cc
@@ -114,7 +114,7 @@
 }
 
 blink::mojom::ControllerServiceWorkerMode
-ServiceWorkerFetchContextImpl::IsControlledByServiceWorker() const {
+ServiceWorkerFetchContextImpl::GetControllerServiceWorkerMode() const {
   return blink::mojom::ControllerServiceWorkerMode::kNoController;
 }
 
diff --git a/content/renderer/service_worker/service_worker_fetch_context_impl.h b/content/renderer/service_worker/service_worker_fetch_context_impl.h
index f1734529..504388f 100644
--- a/content/renderer/service_worker/service_worker_fetch_context_impl.h
+++ b/content/renderer/service_worker/service_worker_fetch_context_impl.h
@@ -49,7 +49,7 @@
       mojo::ScopedMessagePipeHandle url_loader_factory_handle) override;
   blink::WebURLLoaderFactory* GetScriptLoaderFactory() override;
   void WillSendRequest(blink::WebURLRequest&) override;
-  blink::mojom::ControllerServiceWorkerMode IsControlledByServiceWorker()
+  blink::mojom::ControllerServiceWorkerMode GetControllerServiceWorkerMode()
       const override;
   blink::WebURL SiteForCookies() const override;
   base::Optional<blink::WebSecurityOrigin> TopFrameOrigin() const override;
diff --git a/content/renderer/service_worker/service_worker_network_provider_for_frame.cc b/content/renderer/service_worker/service_worker_network_provider_for_frame.cc
index caaf9b2a..f30e2b7 100644
--- a/content/renderer/service_worker/service_worker_network_provider_for_frame.cc
+++ b/content/renderer/service_worker/service_worker_network_provider_for_frame.cc
@@ -138,10 +138,10 @@
 }
 
 blink::mojom::ControllerServiceWorkerMode
-ServiceWorkerNetworkProviderForFrame::IsControlledByServiceWorker() {
+ServiceWorkerNetworkProviderForFrame::GetControllerServiceWorkerMode() {
   if (!context())
     return blink::mojom::ControllerServiceWorkerMode::kNoController;
-  return context()->IsControlledByServiceWorker();
+  return context()->GetControllerServiceWorkerMode();
 }
 
 int64_t ServiceWorkerNetworkProviderForFrame::ControllerServiceWorkerID() {
diff --git a/content/renderer/service_worker/service_worker_network_provider_for_frame.h b/content/renderer/service_worker/service_worker_network_provider_for_frame.h
index c3cba01..b41beb34 100644
--- a/content/renderer/service_worker/service_worker_network_provider_for_frame.h
+++ b/content/renderer/service_worker/service_worker_network_provider_for_frame.h
@@ -48,7 +48,7 @@
       const blink::WebURLRequest& request,
       std::unique_ptr<blink::scheduler::WebResourceLoadingTaskRunnerHandle>
           task_runner_handle) override;
-  blink::mojom::ControllerServiceWorkerMode IsControlledByServiceWorker()
+  blink::mojom::ControllerServiceWorkerMode GetControllerServiceWorkerMode()
       override;
   int64_t ControllerServiceWorkerID() override;
   void DispatchNetworkQuiet() override;
diff --git a/content/renderer/service_worker/service_worker_network_provider_for_service_worker.cc b/content/renderer/service_worker/service_worker_network_provider_for_service_worker.cc
index d3b4dfc..cef498cb 100644
--- a/content/renderer/service_worker/service_worker_network_provider_for_service_worker.cc
+++ b/content/renderer/service_worker/service_worker_network_provider_for_service_worker.cc
@@ -77,7 +77,7 @@
 }
 
 blink::mojom::ControllerServiceWorkerMode
-ServiceWorkerNetworkProviderForServiceWorker::IsControlledByServiceWorker() {
+ServiceWorkerNetworkProviderForServiceWorker::GetControllerServiceWorkerMode() {
   return blink::mojom::ControllerServiceWorkerMode::kNoController;
 }
 
diff --git a/content/renderer/service_worker/service_worker_network_provider_for_service_worker.h b/content/renderer/service_worker/service_worker_network_provider_for_service_worker.h
index ed156c3c..f130ebd 100644
--- a/content/renderer/service_worker/service_worker_network_provider_for_service_worker.h
+++ b/content/renderer/service_worker/service_worker_network_provider_for_service_worker.h
@@ -31,7 +31,7 @@
       const blink::WebURLRequest& request,
       std::unique_ptr<blink::scheduler::WebResourceLoadingTaskRunnerHandle>
           task_runner_handle) override;
-  blink::mojom::ControllerServiceWorkerMode IsControlledByServiceWorker()
+  blink::mojom::ControllerServiceWorkerMode GetControllerServiceWorkerMode()
       override;
   int64_t ControllerServiceWorkerID() override;
   void DispatchNetworkQuiet() override;
diff --git a/content/renderer/service_worker/service_worker_provider_context.cc b/content/renderer/service_worker/service_worker_provider_context.cc
index b5d38750..fb70248 100644
--- a/content/renderer/service_worker/service_worker_provider_context.cc
+++ b/content/renderer/service_worker/service_worker_provider_context.cc
@@ -93,7 +93,7 @@
 }
 
 blink::mojom::ControllerServiceWorkerMode
-ServiceWorkerProviderContext::IsControlledByServiceWorker() const {
+ServiceWorkerProviderContext::GetControllerServiceWorkerMode() const {
   DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence());
   DCHECK(state_for_client_);
   return state_for_client_->controller_mode;
diff --git a/content/renderer/service_worker/service_worker_provider_context.h b/content/renderer/service_worker/service_worker_provider_context.h
index a0d0803..e00bd7b 100644
--- a/content/renderer/service_worker/service_worker_provider_context.h
+++ b/content/renderer/service_worker/service_worker_provider_context.h
@@ -90,7 +90,8 @@
   // (ServiceWorkerContainer#controller).
   int64_t GetControllerVersionId() const;
 
-  blink::mojom::ControllerServiceWorkerMode IsControlledByServiceWorker() const;
+  blink::mojom::ControllerServiceWorkerMode GetControllerServiceWorkerMode()
+      const;
 
   // Takes the controller service worker object info set by SetController() if
   // any, otherwise returns nullptr.
diff --git a/content/renderer/worker/dedicated_worker_host_factory_client.cc b/content/renderer/worker/dedicated_worker_host_factory_client.cc
index 34c57115..bb269a8 100644
--- a/content/renderer/worker/dedicated_worker_host_factory_client.cc
+++ b/content/renderer/worker/dedicated_worker_host_factory_client.cc
@@ -42,13 +42,14 @@
 void DedicatedWorkerHostFactoryClient::CreateWorkerHost(
     const blink::WebURL& script_url,
     const blink::WebSecurityOrigin& script_origin,
+    network::mojom::FetchCredentialsMode credentials_mode,
     mojo::ScopedMessagePipeHandle blob_url_token) {
   DCHECK(blink::features::IsPlzDedicatedWorkerEnabled());
   blink::mojom::DedicatedWorkerHostFactoryClientPtr client_ptr;
   binding_.Bind(mojo::MakeRequest(&client_ptr));
 
   factory_->CreateWorkerHostAndStartScriptLoad(
-      script_url, script_origin,
+      script_url, script_origin, credentials_mode,
       blink::mojom::BlobURLTokenPtr(blink::mojom::BlobURLTokenPtrInfo(
           std::move(blob_url_token), blink::mojom::BlobURLToken::Version_)),
       std::move(client_ptr));
diff --git a/content/renderer/worker/dedicated_worker_host_factory_client.h b/content/renderer/worker/dedicated_worker_host_factory_client.h
index b41135f7..5b3e537 100644
--- a/content/renderer/worker/dedicated_worker_host_factory_client.h
+++ b/content/renderer/worker/dedicated_worker_host_factory_client.h
@@ -44,6 +44,7 @@
       const blink::WebSecurityOrigin& script_origin) override;
   void CreateWorkerHost(const blink::WebURL& script_url,
                         const blink::WebSecurityOrigin& script_origin,
+                        network::mojom::FetchCredentialsMode credentials_mode,
                         mojo::ScopedMessagePipeHandle blob_url_token) override;
   scoped_refptr<blink::WebWorkerFetchContext> CloneWorkerFetchContext(
       blink::WebWorkerFetchContext* web_worker_fetch_context,
diff --git a/content/renderer/worker/service_worker_network_provider_for_worker.cc b/content/renderer/worker/service_worker_network_provider_for_worker.cc
index c96e50a..5353878 100644
--- a/content/renderer/worker/service_worker_network_provider_for_worker.cc
+++ b/content/renderer/worker/service_worker_network_provider_for_worker.cc
@@ -95,10 +95,10 @@
 }
 
 blink::mojom::ControllerServiceWorkerMode
-ServiceWorkerNetworkProviderForWorker::IsControlledByServiceWorker() {
+ServiceWorkerNetworkProviderForWorker::GetControllerServiceWorkerMode() {
   if (!context())
     return blink::mojom::ControllerServiceWorkerMode::kNoController;
-  return context()->IsControlledByServiceWorker();
+  return context()->GetControllerServiceWorkerMode();
 }
 
 int64_t ServiceWorkerNetworkProviderForWorker::ControllerServiceWorkerID() {
diff --git a/content/renderer/worker/service_worker_network_provider_for_worker.h b/content/renderer/worker/service_worker_network_provider_for_worker.h
index b9f75ad..5a908da 100644
--- a/content/renderer/worker/service_worker_network_provider_for_worker.h
+++ b/content/renderer/worker/service_worker_network_provider_for_worker.h
@@ -55,7 +55,7 @@
       const blink::WebURLRequest& request,
       std::unique_ptr<blink::scheduler::WebResourceLoadingTaskRunnerHandle>
           task_runner_handle) override;
-  blink::mojom::ControllerServiceWorkerMode IsControlledByServiceWorker()
+  blink::mojom::ControllerServiceWorkerMode GetControllerServiceWorkerMode()
       override;
   int64_t ControllerServiceWorkerID() override;
   void DispatchNetworkQuiet() override;
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index a29bcad3..4b11f76 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -1325,7 +1325,6 @@
     sources += [
       "../renderer/browser_render_view_browsertest.cc",
       "../renderer/dom_serializer_browsertest.cc",
-      "../renderer/fetchers/resource_fetcher_browsertest.cc",
       "../renderer/render_thread_impl_discardable_memory_browsertest.cc",
       "../renderer/savable_resources_browsertest.cc",
     ]
@@ -1844,17 +1843,12 @@
     "../renderer/media/stream/media_stream_constraints_util_video_content_unittest.cc",
     "../renderer/media/stream/media_stream_constraints_util_video_device_unittest.cc",
     "../renderer/media/stream/media_stream_device_observer_unittest.cc",
-    "../renderer/media/stream/media_stream_video_renderer_sink_unittest.cc",
     "../renderer/media/stream/media_stream_video_source_unittest.cc",
     "../renderer/media/stream/media_stream_video_track_unittest.cc",
     "../renderer/media/stream/mock_constraint_factory.cc",
     "../renderer/media/stream/mock_constraint_factory.h",
-    "../renderer/media/stream/mock_media_stream_registry.cc",
-    "../renderer/media/stream/mock_media_stream_registry.h",
     "../renderer/media/stream/mock_media_stream_video_sink.cc",
     "../renderer/media/stream/mock_media_stream_video_sink.h",
-    "../renderer/media/stream/mock_media_stream_video_source.cc",
-    "../renderer/media/stream/mock_media_stream_video_source.h",
     "../renderer/media/stream/processed_local_audio_source_unittest.cc",
     "../renderer/media/stream/user_media_client_impl_unittest.cc",
     "../renderer/media/stream/webmediaplayer_ms_unittest.cc",
diff --git a/content/test/data/accessibility/aria/aria-cell-expected-auralinux.txt b/content/test/data/accessibility/aria/aria-cell-expected-auralinux.txt
index 88b140d4..7f1e4d00d 100644
--- a/content/test/data/accessibility/aria/aria-cell-expected-auralinux.txt
+++ b/content/test/data/accessibility/aria/aria-cell-expected-auralinux.txt
@@ -1,12 +1,12 @@
 [document web]
 ++[table] cols=2 headers=('Browser', 'Rendering Engine'); rows=2 headers=(NONE); caption=false; spans=(all: 1x1)
 ++++[table row] selectable
-++++++[column header] name='Browser' selectable (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[column header] name='Browser' selectable (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Browser'
-++++++[column header] name='Rendering Engine' selectable (row=0, col=1, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[column header] name='Rendering Engine' selectable (row=0, col=1, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Rendering Engine'
 ++++[table row] selectable
-++++++[table cell] name='Chrome' selectable (row=1, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='Chrome' selectable (row=1, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='Chrome'
-++++++[table cell] name='Blink' selectable (row=1, col=1, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='Blink' selectable (row=1, col=1, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='Blink'
diff --git a/content/test/data/accessibility/aria/aria-col-attr-expected-auralinux.txt b/content/test/data/accessibility/aria/aria-col-attr-expected-auralinux.txt
index ef09828..43091386 100644
--- a/content/test/data/accessibility/aria/aria-col-attr-expected-auralinux.txt
+++ b/content/test/data/accessibility/aria/aria-col-attr-expected-auralinux.txt
@@ -1,18 +1,18 @@
 [document web]
 ++[table] colcount:5 cols=4 headers=('cell 2', 'cell 4', 'cell 5'); rows=2 headers=(NONE); caption=false; spans=(cell at 0,3: 0x0)
 ++++[table row] selectable
-++++++[column header] name='cell 2' selectable colindex:2 colspan:2 (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[column header] name='cell 2' selectable colindex:2 colspan:2 (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='cell 2'
-++++++[column header] name='cell 4' selectable colindex:4 (row=0, col=1, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[column header] name='cell 4' selectable colindex:4 (row=0, col=1, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='cell 4'
-++++++[column header] name='cell 5' selectable colindex:5 (row=0, col=2, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[column header] name='cell 5' selectable colindex:5 (row=0, col=2, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='cell 5'
 ++++[table row] selectable
-++++++[table cell] name='cell 2' selectable colindex:2 (row=1, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='cell 2' selectable colindex:2 (row=1, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='cell 2'
-++++++[table cell] name='cell 3' selectable colindex:3 (row=1, col=1, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='cell 3' selectable colindex:3 (row=1, col=1, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='cell 3'
-++++++[table cell] name='cell 4' selectable colindex:4 (row=1, col=2, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='cell 4' selectable colindex:4 (row=1, col=2, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='cell 4'
-++++++[table cell] name='cell 5' selectable colindex:5 (row=1, col=3, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[table cell] name='cell 5' selectable colindex:5 (row=1, col=3, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='cell 5'
diff --git a/content/test/data/accessibility/aria/aria-columnheader-expected-auralinux.txt b/content/test/data/accessibility/aria/aria-columnheader-expected-auralinux.txt
index 2724dbc..78dabd1 100644
--- a/content/test/data/accessibility/aria/aria-columnheader-expected-auralinux.txt
+++ b/content/test/data/accessibility/aria/aria-columnheader-expected-auralinux.txt
@@ -1,17 +1,17 @@
 [document web]
 ++[table] cols=2 headers=('Browser', 'Rendering Engine'); rows=3 headers=(NONE); caption=false; spans=(all: 1x1)
 ++++[table row] selectable
-++++++[column header] name='Browser' selectable (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[column header] name='Browser' selectable (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Browser'
-++++++[column header] name='Rendering Engine' selectable (row=0, col=1, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[column header] name='Rendering Engine' selectable (row=0, col=1, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Rendering Engine'
 ++++[table row] selectable
-++++++[table cell] name='Chrome' selectable (row=1, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='Chrome' selectable (row=1, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='Chrome'
-++++++[table cell] name='Blink' selectable (row=1, col=1, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='Blink' selectable (row=1, col=1, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='Blink'
 ++++[table row] selectable
-++++++[table cell] name='Safari' selectable (row=2, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='Safari' selectable (row=2, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='Safari'
-++++++[table cell] name='WebKit' selectable (row=2, col=1, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='WebKit' selectable (row=2, col=1, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='WebKit'
diff --git a/content/test/data/accessibility/aria/aria-grid-expected-auralinux.txt b/content/test/data/accessibility/aria/aria-grid-expected-auralinux.txt
index ba72a89..57b3c43 100644
--- a/content/test/data/accessibility/aria/aria-grid-expected-auralinux.txt
+++ b/content/test/data/accessibility/aria/aria-grid-expected-auralinux.txt
@@ -1,12 +1,12 @@
 [document web]
 ++[table] xml-roles:grid cols=2 headers=('Browser', 'Rendering Engine'); rows=2 headers=(NONE); caption=false; spans=(all: 1x1)
 ++++[table row] selectable xml-roles:row
-++++++[column header] name='Browser' selectable colindex:1 rowindex:1 xml-roles:columnheader (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[column header] name='Browser' selectable colindex:1 rowindex:1 xml-roles:columnheader (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Browser'
-++++++[column header] name='Rendering Engine' selectable colindex:2 rowindex:1 xml-roles:columnheader (row=0, col=1, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[column header] name='Rendering Engine' selectable colindex:2 rowindex:1 xml-roles:columnheader (row=0, col=1, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Rendering Engine'
 ++++[table row] selectable xml-roles:row
-++++++[table cell] name='Chrome' selectable colindex:1 rowindex:2 xml-roles:gridcell (row=1, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='Chrome' selectable colindex:1 rowindex:2 xml-roles:gridcell (row=1, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='Chrome'
-++++++[table cell] name='Blink' selectable colindex:2 rowindex:2 xml-roles:gridcell (row=1, col=1, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='Blink' selectable colindex:2 rowindex:2 xml-roles:gridcell (row=1, col=1, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='Blink'
diff --git a/content/test/data/accessibility/aria/aria-gridcell-expected-auralinux.txt b/content/test/data/accessibility/aria/aria-gridcell-expected-auralinux.txt
index df09bb2..48b74fd 100644
--- a/content/test/data/accessibility/aria/aria-gridcell-expected-auralinux.txt
+++ b/content/test/data/accessibility/aria/aria-gridcell-expected-auralinux.txt
@@ -1,12 +1,12 @@
 [document web]
 ++[table] multiselectable xml-roles:grid cols=2 headers=('Browser', 'Rendering Engine'); rows=2 headers=(NONE); caption=false; spans=(all: 1x1)
 ++++[table row] selectable xml-roles:row
-++++++[column header] name='Browser' selectable colindex:1 rowindex:1 xml-roles:columnheader (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[column header] name='Browser' selectable colindex:1 rowindex:1 xml-roles:columnheader (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Browser'
-++++++[column header] name='Rendering Engine' selectable colindex:2 rowindex:1 xml-roles:columnheader (row=0, col=1, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[column header] name='Rendering Engine' selectable colindex:2 rowindex:1 xml-roles:columnheader (row=0, col=1, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Rendering Engine'
 ++++[table row] selectable xml-roles:row
-++++++[table cell] name='Chrome' selectable colindex:1 rowindex:2 xml-roles:gridcell (row=1, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='Chrome' selectable colindex:1 rowindex:2 xml-roles:gridcell (row=1, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='Chrome'
-++++++[table cell] name='Blink' selectable colindex:2 rowindex:2 xml-roles:gridcell (row=1, col=1, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='Blink' selectable colindex:2 rowindex:2 xml-roles:gridcell (row=1, col=1, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='Blink'
diff --git a/content/test/data/accessibility/aria/aria-illegal-val-expected-auralinux.txt b/content/test/data/accessibility/aria/aria-illegal-val-expected-auralinux.txt
index 780db7e..6c5f965 100644
--- a/content/test/data/accessibility/aria/aria-illegal-val-expected-auralinux.txt
+++ b/content/test/data/accessibility/aria/aria-illegal-val-expected-auralinux.txt
@@ -21,4 +21,4 @@
 ++[entry] name='Required illegal' required selectable-text
 ++[tree] multiselectable
 ++++[tree item] name='Selected illegal' selectable selected
-++[column header] name='Sort illegal' selectable sort:other (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++[column header] name='Sort illegal' selectable sort:other (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
diff --git a/content/test/data/accessibility/aria/aria-level-expected-auralinux.txt b/content/test/data/accessibility/aria/aria-level-expected-auralinux.txt
index 413a33c..4d69dfd 100644
--- a/content/test/data/accessibility/aria/aria-level-expected-auralinux.txt
+++ b/content/test/data/accessibility/aria/aria-level-expected-auralinux.txt
@@ -23,8 +23,8 @@
 ++++++[text] name='Tree item at level 3'
 ++[tree table]
 ++++[table row] selectable level:1
-++++++[table cell] name='Cell at level 1' selectable (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[table cell] name='Cell at level 1' selectable (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Cell at level 1'
 ++++[table row] selectable level:2
-++++++[table cell] name='Cell at level 2' selectable (row=1, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[table cell] name='Cell at level 2' selectable (row=1, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Cell at level 2'
diff --git a/content/test/data/accessibility/aria/aria-row-attr-expected-auralinux.txt b/content/test/data/accessibility/aria/aria-row-attr-expected-auralinux.txt
index 6ad5b7b..8208642b 100644
--- a/content/test/data/accessibility/aria/aria-row-attr-expected-auralinux.txt
+++ b/content/test/data/accessibility/aria/aria-row-attr-expected-auralinux.txt
@@ -1,14 +1,14 @@
 [document web]
 ++[table] rowcount:5 cols=3 headers=('cell 2', 'cell 3', 'cell 4'); rows=2 headers=(NONE); caption=false; spans=(cell at 1,2: 0x0)
 ++++[table row] selectable
-++++++[column header] name='cell 2' selectable rowindex:3 (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[column header] name='cell 2' selectable rowindex:3 (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='cell 2'
-++++++[column header] name='cell 3' selectable rowindex:3 (row=0, col=1, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[column header] name='cell 3' selectable rowindex:3 (row=0, col=1, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='cell 3'
-++++++[column header] name='cell 4' selectable rowindex:3 rowspan:2 (row=0, col=2, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[column header] name='cell 4' selectable rowindex:3 rowspan:2 (row=0, col=2, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='cell 4'
 ++++[table row] selectable rowindex:4
-++++++[table cell] name='cell 2' selectable rowindex:4 (row=1, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='cell 2' selectable rowindex:4 (row=1, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='cell 2'
-++++++[table cell] name='cell 3' selectable rowindex:4 (row=1, col=1, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='cell 3' selectable rowindex:4 (row=1, col=1, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='cell 3'
diff --git a/content/test/data/accessibility/aria/aria-row-expected-auralinux.txt b/content/test/data/accessibility/aria/aria-row-expected-auralinux.txt
index 2724dbc..78dabd1 100644
--- a/content/test/data/accessibility/aria/aria-row-expected-auralinux.txt
+++ b/content/test/data/accessibility/aria/aria-row-expected-auralinux.txt
@@ -1,17 +1,17 @@
 [document web]
 ++[table] cols=2 headers=('Browser', 'Rendering Engine'); rows=3 headers=(NONE); caption=false; spans=(all: 1x1)
 ++++[table row] selectable
-++++++[column header] name='Browser' selectable (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[column header] name='Browser' selectable (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Browser'
-++++++[column header] name='Rendering Engine' selectable (row=0, col=1, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[column header] name='Rendering Engine' selectable (row=0, col=1, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Rendering Engine'
 ++++[table row] selectable
-++++++[table cell] name='Chrome' selectable (row=1, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='Chrome' selectable (row=1, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='Chrome'
-++++++[table cell] name='Blink' selectable (row=1, col=1, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='Blink' selectable (row=1, col=1, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='Blink'
 ++++[table row] selectable
-++++++[table cell] name='Safari' selectable (row=2, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='Safari' selectable (row=2, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='Safari'
-++++++[table cell] name='WebKit' selectable (row=2, col=1, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='WebKit' selectable (row=2, col=1, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='WebKit'
diff --git a/content/test/data/accessibility/aria/aria-rowheader-expected-auralinux.txt b/content/test/data/accessibility/aria/aria-rowheader-expected-auralinux.txt
index 209ead19..8334afd 100644
--- a/content/test/data/accessibility/aria/aria-rowheader-expected-auralinux.txt
+++ b/content/test/data/accessibility/aria/aria-rowheader-expected-auralinux.txt
@@ -1,16 +1,16 @@
 [document web]
 ++[table] xml-roles:grid cols=3 headers=(NONE); rows=2 headers=('Browser', 'Rendering Engine'); caption=false; spans=(all: 1x1)
 ++++[table row] selectable xml-roles:row
-++++++[row header] name='Browser' selectable xml-roles:rowheader (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[row header] name='Browser' selectable xml-roles:rowheader (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Browser'
-++++++[table cell] name='Chrome' selectable xml-roles:gridcell (row=0, col=1, row_span=1, col_span=1 n_row_headers=1, n_col_headers=0)
+++++++[table cell] name='Chrome' selectable xml-roles:gridcell (row=0, col=1, row_span=1, col_span=1, n_row_headers=1, n_col_headers=0)
 ++++++++[text] name='Chrome'
-++++++[table cell] name='Safari' selectable xml-roles:gridcell (row=0, col=2, row_span=1, col_span=1 n_row_headers=1, n_col_headers=0)
+++++++[table cell] name='Safari' selectable xml-roles:gridcell (row=0, col=2, row_span=1, col_span=1, n_row_headers=1, n_col_headers=0)
 ++++++++[text] name='Safari'
 ++++[table row] selectable xml-roles:row
-++++++[row header] name='Rendering Engine' selectable xml-roles:rowheader (row=1, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[row header] name='Rendering Engine' selectable xml-roles:rowheader (row=1, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Rendering Engine'
-++++++[table cell] name='Blink' selectable xml-roles:gridcell (row=1, col=1, row_span=1, col_span=1 n_row_headers=1, n_col_headers=0)
+++++++[table cell] name='Blink' selectable xml-roles:gridcell (row=1, col=1, row_span=1, col_span=1, n_row_headers=1, n_col_headers=0)
 ++++++++[text] name='Blink'
-++++++[table cell] name='WebKit' selectable xml-roles:gridcell (row=1, col=2, row_span=1, col_span=1 n_row_headers=1, n_col_headers=0)
+++++++[table cell] name='WebKit' selectable xml-roles:gridcell (row=1, col=2, row_span=1, col_span=1, n_row_headers=1, n_col_headers=0)
 ++++++++[text] name='WebKit'
diff --git a/content/test/data/accessibility/aria/aria-rowtext-expected-auralinux.txt b/content/test/data/accessibility/aria/aria-rowtext-expected-auralinux.txt
index 4bfd3c2..952d1e1 100644
--- a/content/test/data/accessibility/aria/aria-rowtext-expected-auralinux.txt
+++ b/content/test/data/accessibility/aria/aria-rowtext-expected-auralinux.txt
@@ -1,12 +1,12 @@
 [document web]
 ++[table] cols=2 headers=(NONE); rows=2 headers=(NONE); caption=false; spans=(all: 1x1)
 ++++[table row] selectable
-++++++[table cell] name='cell A3' selectable colindex:1 coltext:A rowindex:3 rowtext:3 (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[table cell] name='cell A3' selectable colindex:1 coltext:A rowindex:3 rowtext:3 (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='cell A3'
-++++++[table cell] name='cell B3' selectable colindex:2 coltext:B rowindex:3 rowtext:3 (row=0, col=1, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[table cell] name='cell B3' selectable colindex:2 coltext:B rowindex:3 rowtext:3 (row=0, col=1, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='cell B3'
 ++++[table row] selectable
-++++++[table cell] name='cell A4' selectable colindex:1 coltext:A rowindex:4 rowtext:4 (row=1, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[table cell] name='cell A4' selectable colindex:1 coltext:A rowindex:4 rowtext:4 (row=1, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='cell A4'
-++++++[table cell] name='cell B4' selectable colindex:2 coltext:B rowindex:4 rowtext:4 (row=1, col=1, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[table cell] name='cell B4' selectable colindex:2 coltext:B rowindex:4 rowtext:4 (row=1, col=1, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='cell B4'
diff --git a/content/test/data/accessibility/aria/aria-sort-aria-grid-expected-auralinux.txt b/content/test/data/accessibility/aria/aria-sort-aria-grid-expected-auralinux.txt
index 95cb00d..3dfa23d 100644
--- a/content/test/data/accessibility/aria/aria-sort-aria-grid-expected-auralinux.txt
+++ b/content/test/data/accessibility/aria/aria-sort-aria-grid-expected-auralinux.txt
@@ -1,91 +1,91 @@
 [document web]
 ++[table] cols=1 headers=('Alphabet'); rows=3 headers=(NONE); caption=false; spans=(all: 1x1)
 ++++[table row] selectable
-++++++[column header] name='Alphabet' selectable (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[column header] name='Alphabet' selectable (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Alphabet'
 ++++[table row] selectable
-++++++[table cell] name='A' selectable (row=1, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='A' selectable (row=1, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='A'
 ++++[table row] selectable
-++++++[table cell] name='B' selectable (row=2, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='B' selectable (row=2, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='B'
 ++[table] cols=1 headers=('Alphabet'); rows=3 headers=(NONE); caption=false; spans=(all: 1x1)
 ++++[table row] selectable
-++++++[column header] name='Alphabet' selectable (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[column header] name='Alphabet' selectable (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Alphabet'
 ++++[table row] selectable
-++++++[table cell] name='A' selectable (row=1, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='A' selectable (row=1, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='A'
 ++++[table row] selectable
-++++++[table cell] name='B' selectable (row=2, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='B' selectable (row=2, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='B'
 ++[table] cols=1 headers=('Alphabet'); rows=3 headers=(NONE); caption=false; spans=(all: 1x1)
 ++++[table row] selectable
-++++++[column header] name='Alphabet' selectable sort:ascending (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[column header] name='Alphabet' selectable sort:ascending (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Alphabet'
 ++++[table row] selectable
-++++++[table cell] name='A' selectable (row=1, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='A' selectable (row=1, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='A'
 ++++[table row] selectable
-++++++[table cell] name='B' selectable (row=2, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='B' selectable (row=2, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='B'
 ++[table] cols=1 headers=('Alphabet'); rows=3 headers=(NONE); caption=false; spans=(all: 1x1)
 ++++[table row] selectable
-++++++[column header] name='Alphabet' selectable sort:descending (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[column header] name='Alphabet' selectable sort:descending (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Alphabet'
 ++++[table row] selectable
-++++++[table cell] name='B' selectable (row=1, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='B' selectable (row=1, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='B'
 ++++[table row] selectable
-++++++[table cell] name='A' selectable (row=2, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='A' selectable (row=2, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='A'
 ++[table] cols=1 headers=('Alphabet'); rows=3 headers=(NONE); caption=false; spans=(all: 1x1)
 ++++[table row] selectable
-++++++[column header] name='Alphabet' selectable sort:other (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[column header] name='Alphabet' selectable sort:other (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Alphabet'
 ++++[table row] selectable
-++++++[table cell] name='A' selectable (row=1, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='A' selectable (row=1, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='A'
 ++++[table row] selectable
-++++++[table cell] name='A' selectable (row=2, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='A' selectable (row=2, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='A'
 ++[table] cols=3 headers=(NONE); rows=1 headers=('Alphabet'); caption=false; spans=(all: 1x1)
 ++++[table row] selectable
-++++++[row header] name='Alphabet' selectable (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[row header] name='Alphabet' selectable (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Alphabet'
-++++++[table cell] name='A' selectable (row=0, col=1, row_span=1, col_span=1 n_row_headers=1, n_col_headers=0)
+++++++[table cell] name='A' selectable (row=0, col=1, row_span=1, col_span=1, n_row_headers=1, n_col_headers=0)
 ++++++++[text] name='A'
-++++++[table cell] name='B' selectable (row=0, col=2, row_span=1, col_span=1 n_row_headers=1, n_col_headers=0)
+++++++[table cell] name='B' selectable (row=0, col=2, row_span=1, col_span=1, n_row_headers=1, n_col_headers=0)
 ++++++++[text] name='B'
 ++[table] cols=3 headers=(NONE); rows=1 headers=('Alphabet'); caption=false; spans=(all: 1x1)
 ++++[table row] selectable
-++++++[row header] name='Alphabet' selectable (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[row header] name='Alphabet' selectable (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Alphabet'
-++++++[table cell] name='A' selectable (row=0, col=1, row_span=1, col_span=1 n_row_headers=1, n_col_headers=0)
+++++++[table cell] name='A' selectable (row=0, col=1, row_span=1, col_span=1, n_row_headers=1, n_col_headers=0)
 ++++++++[text] name='A'
-++++++[table cell] name='B' selectable (row=0, col=2, row_span=1, col_span=1 n_row_headers=1, n_col_headers=0)
+++++++[table cell] name='B' selectable (row=0, col=2, row_span=1, col_span=1, n_row_headers=1, n_col_headers=0)
 ++++++++[text] name='B'
 ++[table] cols=3 headers=(NONE); rows=1 headers=('Alphabet'); caption=false; spans=(all: 1x1)
 ++++[table row] selectable
-++++++[row header] name='Alphabet' selectable sort:ascending (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[row header] name='Alphabet' selectable sort:ascending (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Alphabet'
-++++++[table cell] name='A' selectable (row=0, col=1, row_span=1, col_span=1 n_row_headers=1, n_col_headers=0)
+++++++[table cell] name='A' selectable (row=0, col=1, row_span=1, col_span=1, n_row_headers=1, n_col_headers=0)
 ++++++++[text] name='A'
-++++++[table cell] name='B' selectable (row=0, col=2, row_span=1, col_span=1 n_row_headers=1, n_col_headers=0)
+++++++[table cell] name='B' selectable (row=0, col=2, row_span=1, col_span=1, n_row_headers=1, n_col_headers=0)
 ++++++++[text] name='B'
 ++[table] cols=3 headers=(NONE); rows=1 headers=('Alphabet'); caption=false; spans=(all: 1x1)
 ++++[table row] selectable
-++++++[row header] name='Alphabet' selectable sort:descending (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[row header] name='Alphabet' selectable sort:descending (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Alphabet'
-++++++[table cell] name='B' selectable (row=0, col=1, row_span=1, col_span=1 n_row_headers=1, n_col_headers=0)
+++++++[table cell] name='B' selectable (row=0, col=1, row_span=1, col_span=1, n_row_headers=1, n_col_headers=0)
 ++++++++[text] name='B'
-++++++[table cell] name='A' selectable (row=0, col=2, row_span=1, col_span=1 n_row_headers=1, n_col_headers=0)
+++++++[table cell] name='A' selectable (row=0, col=2, row_span=1, col_span=1, n_row_headers=1, n_col_headers=0)
 ++++++++[text] name='A'
 ++[table] cols=3 headers=(NONE); rows=1 headers=('Alphabet'); caption=false; spans=(all: 1x1)
 ++++[table row] selectable
-++++++[row header] name='Alphabet' selectable sort:other (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[row header] name='Alphabet' selectable sort:other (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Alphabet'
-++++++[table cell] name='A' selectable (row=0, col=1, row_span=1, col_span=1 n_row_headers=1, n_col_headers=0)
+++++++[table cell] name='A' selectable (row=0, col=1, row_span=1, col_span=1, n_row_headers=1, n_col_headers=0)
 ++++++++[text] name='A'
-++++++[table cell] name='A' selectable (row=0, col=2, row_span=1, col_span=1 n_row_headers=1, n_col_headers=0)
+++++++[table cell] name='A' selectable (row=0, col=2, row_span=1, col_span=1, n_row_headers=1, n_col_headers=0)
 ++++++++[text] name='A'
diff --git a/content/test/data/accessibility/aria/aria-sort-html-table-expected-auralinux.txt b/content/test/data/accessibility/aria/aria-sort-html-table-expected-auralinux.txt
index 9d0cdfc6..3b2497a7 100644
--- a/content/test/data/accessibility/aria/aria-sort-html-table-expected-auralinux.txt
+++ b/content/test/data/accessibility/aria/aria-sort-html-table-expected-auralinux.txt
@@ -1,103 +1,103 @@
 [document web]
 ++[table] name='Data table' cols=1 headers=('Alphabet'); rows=3 headers=(NONE); caption=false; spans=(all: 1x1)
 ++++[table row]
-++++++[column header] name='Alphabet' (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[column header] name='Alphabet' (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Alphabet'
 ++++[table row]
-++++++[table cell] name='A' (row=1, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='A' (row=1, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='A'
 ++++[table row]
-++++++[table cell] name='B' (row=2, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='B' (row=2, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='B'
 ++[table] name='Data table' cols=1 headers=('Alphabet'); rows=3 headers=(NONE); caption=false; spans=(all: 1x1)
 ++++[table row]
-++++++[column header] name='Alphabet' (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[column header] name='Alphabet' (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Alphabet'
 ++++[table row]
-++++++[table cell] name='A' (row=1, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='A' (row=1, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='A'
 ++++[table row]
-++++++[table cell] name='B' (row=2, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='B' (row=2, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='B'
 ++[table] name='Data table' cols=1 headers=('Alphabet'); rows=3 headers=(NONE); caption=false; spans=(all: 1x1)
 ++++[table row]
-++++++[column header] name='Alphabet' sort:ascending (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[column header] name='Alphabet' sort:ascending (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Alphabet'
 ++++[table row]
-++++++[table cell] name='A' (row=1, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='A' (row=1, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='A'
 ++++[table row]
-++++++[table cell] name='B' (row=2, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='B' (row=2, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='B'
 ++[table] name='Data table' cols=1 headers=('Alphabet'); rows=3 headers=(NONE); caption=false; spans=(all: 1x1)
 ++++[table row]
-++++++[column header] name='Alphabet' sort:descending (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[column header] name='Alphabet' sort:descending (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Alphabet'
 ++++[table row]
-++++++[table cell] name='B' (row=1, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='B' (row=1, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='B'
 ++++[table row]
-++++++[table cell] name='A' (row=2, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='A' (row=2, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='A'
 ++[table] name='Data table' cols=1 headers=('Alphabet'); rows=3 headers=(NONE); caption=false; spans=(all: 1x1)
 ++++[table row]
-++++++[column header] name='Alphabet' sort:other (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[column header] name='Alphabet' sort:other (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Alphabet'
 ++++[table row]
-++++++[table cell] name='A' (row=1, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='A' (row=1, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='A'
 ++++[table row]
-++++++[table cell] name='A' (row=2, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='A' (row=2, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='A'
 ++[table] name='Data table' cols=3 headers=(NONE); rows=1 headers=('Alphabet'); caption=false; spans=(all: 1x1)
 ++++[table row]
-++++++[row header] name='Alphabet' (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[row header] name='Alphabet' (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Alphabet'
-++++++[table cell] name='A' (row=0, col=1, row_span=1, col_span=1 n_row_headers=1, n_col_headers=0)
+++++++[table cell] name='A' (row=0, col=1, row_span=1, col_span=1, n_row_headers=1, n_col_headers=0)
 ++++++++[text] name='A'
-++++++[table cell] name='B' (row=0, col=2, row_span=1, col_span=1 n_row_headers=1, n_col_headers=0)
+++++++[table cell] name='B' (row=0, col=2, row_span=1, col_span=1, n_row_headers=1, n_col_headers=0)
 ++++++++[text] name='B'
 ++[table] name='Data table' cols=3 headers=(NONE); rows=1 headers=('Alphabet'); caption=false; spans=(all: 1x1)
 ++++[table row]
-++++++[row header] name='Alphabet' (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[row header] name='Alphabet' (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Alphabet'
-++++++[table cell] name='A' (row=0, col=1, row_span=1, col_span=1 n_row_headers=1, n_col_headers=0)
+++++++[table cell] name='A' (row=0, col=1, row_span=1, col_span=1, n_row_headers=1, n_col_headers=0)
 ++++++++[text] name='A'
-++++++[table cell] name='B' (row=0, col=2, row_span=1, col_span=1 n_row_headers=1, n_col_headers=0)
+++++++[table cell] name='B' (row=0, col=2, row_span=1, col_span=1, n_row_headers=1, n_col_headers=0)
 ++++++++[text] name='B'
 ++[table] name='Data table' cols=3 headers=(NONE); rows=1 headers=('Alphabet'); caption=false; spans=(all: 1x1)
 ++++[table row]
-++++++[row header] name='Alphabet' sort:ascending (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[row header] name='Alphabet' sort:ascending (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Alphabet'
-++++++[table cell] name='A' (row=0, col=1, row_span=1, col_span=1 n_row_headers=1, n_col_headers=0)
+++++++[table cell] name='A' (row=0, col=1, row_span=1, col_span=1, n_row_headers=1, n_col_headers=0)
 ++++++++[text] name='A'
-++++++[table cell] name='B' (row=0, col=2, row_span=1, col_span=1 n_row_headers=1, n_col_headers=0)
+++++++[table cell] name='B' (row=0, col=2, row_span=1, col_span=1, n_row_headers=1, n_col_headers=0)
 ++++++++[text] name='B'
 ++[table] name='Data table' cols=3 headers=(NONE); rows=1 headers=('Alphabet'); caption=false; spans=(all: 1x1)
 ++++[table row]
-++++++[row header] name='Alphabet' sort:descending (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[row header] name='Alphabet' sort:descending (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Alphabet'
-++++++[table cell] name='B' (row=0, col=1, row_span=1, col_span=1 n_row_headers=1, n_col_headers=0)
+++++++[table cell] name='B' (row=0, col=1, row_span=1, col_span=1, n_row_headers=1, n_col_headers=0)
 ++++++++[text] name='B'
-++++++[table cell] name='A' (row=0, col=2, row_span=1, col_span=1 n_row_headers=1, n_col_headers=0)
+++++++[table cell] name='A' (row=0, col=2, row_span=1, col_span=1, n_row_headers=1, n_col_headers=0)
 ++++++++[text] name='A'
 ++[table] name='Data table' cols=3 headers=(NONE); rows=1 headers=('Alphabet'); caption=false; spans=(all: 1x1)
 ++++[table row]
-++++++[row header] name='Alphabet' sort:other (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[row header] name='Alphabet' sort:other (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Alphabet'
-++++++[table cell] name='A' (row=0, col=1, row_span=1, col_span=1 n_row_headers=1, n_col_headers=0)
+++++++[table cell] name='A' (row=0, col=1, row_span=1, col_span=1, n_row_headers=1, n_col_headers=0)
 ++++++++[text] name='A'
-++++++[table cell] name='A' (row=0, col=2, row_span=1, col_span=1 n_row_headers=1, n_col_headers=0)
+++++++[table cell] name='A' (row=0, col=2, row_span=1, col_span=1, n_row_headers=1, n_col_headers=0)
 ++++++++[text] name='A'
 ++[table] name='Data table' cols=1 headers=('Alphabet'); rows=3 headers=(NONE); caption=false; spans=(all: 1x1)
 ++++[table row]
-++++++[column header] name='Alphabet' (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[column header] name='Alphabet' (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Alphabet'
 ++++[table row]
-++++++[table cell] name='A' (row=1, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='A' (row=1, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='A'
 ++++[table row]
-++++++[table cell] name='B' (row=2, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='B' (row=2, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='B'
 ++[section]
 ++++[text] name='Alphabet'
diff --git a/content/test/data/accessibility/aria/aria-table-expected-auralinux.txt b/content/test/data/accessibility/aria/aria-table-expected-auralinux.txt
index 88b140d4..7f1e4d00d 100644
--- a/content/test/data/accessibility/aria/aria-table-expected-auralinux.txt
+++ b/content/test/data/accessibility/aria/aria-table-expected-auralinux.txt
@@ -1,12 +1,12 @@
 [document web]
 ++[table] cols=2 headers=('Browser', 'Rendering Engine'); rows=2 headers=(NONE); caption=false; spans=(all: 1x1)
 ++++[table row] selectable
-++++++[column header] name='Browser' selectable (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[column header] name='Browser' selectable (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Browser'
-++++++[column header] name='Rendering Engine' selectable (row=0, col=1, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[column header] name='Rendering Engine' selectable (row=0, col=1, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Rendering Engine'
 ++++[table row] selectable
-++++++[table cell] name='Chrome' selectable (row=1, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='Chrome' selectable (row=1, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='Chrome'
-++++++[table cell] name='Blink' selectable (row=1, col=1, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='Blink' selectable (row=1, col=1, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='Blink'
diff --git a/content/test/data/accessibility/aria/aria-treegrid-expected-auralinux.txt b/content/test/data/accessibility/aria/aria-treegrid-expected-auralinux.txt
index a50d2db..e9437cc 100644
--- a/content/test/data/accessibility/aria/aria-treegrid-expected-auralinux.txt
+++ b/content/test/data/accessibility/aria/aria-treegrid-expected-auralinux.txt
@@ -1,12 +1,12 @@
 [document web]
 ++[tree table] xml-roles:treegrid
 ++++[table row] selectable level:1 xml-roles:row
-++++++[table cell] name='Cell at level 1' selectable xml-roles:gridcell (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[table cell] name='Cell at level 1' selectable xml-roles:gridcell (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Cell at level 1'
 ++++[table row] selectable level:2 xml-roles:row
-++++++[table cell] name='Cell at level 2' selectable xml-roles:gridcell (row=1, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[table cell] name='Cell at level 2' selectable xml-roles:gridcell (row=1, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Cell at level 2'
 ++[tree table] xml-roles:treegrid
 ++++[table row] selectable level:1 xml-roles:row
-++++++[table cell] name='Cell at level 1' selectable xml-roles:gridcell (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[table cell] name='Cell at level 1' selectable xml-roles:gridcell (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Cell at level 1'
diff --git a/content/test/data/accessibility/html/caption-expected-auralinux.txt b/content/test/data/accessibility/html/caption-expected-auralinux.txt
index b8531c2..2e805b63 100644
--- a/content/test/data/accessibility/html/caption-expected-auralinux.txt
+++ b/content/test/data/accessibility/html/caption-expected-auralinux.txt
@@ -3,17 +3,17 @@
 ++++[caption] label-for
 ++++++[text] name='Browser and Engine'
 ++++[table row]
-++++++[column header] name='Browser' (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[column header] name='Browser' (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Browser'
-++++++[column header] name='Engine' (row=0, col=1, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[column header] name='Engine' (row=0, col=1, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Engine'
 ++++[table row]
-++++++[table cell] name='Chrome' (row=1, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='Chrome' (row=1, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='Chrome'
-++++++[table cell] name='Blink' (row=1, col=1, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='Blink' (row=1, col=1, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='Blink'
 ++++[table row]
-++++++[table cell] name='Safari' (row=2, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='Safari' (row=2, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='Safari'
-++++++[table cell] name='WebKit' (row=2, col=1, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='WebKit' (row=2, col=1, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='WebKit'
diff --git a/content/test/data/accessibility/html/col-expected-auralinux.txt b/content/test/data/accessibility/html/col-expected-auralinux.txt
index 6863cda8..cfa81eb 100644
--- a/content/test/data/accessibility/html/col-expected-auralinux.txt
+++ b/content/test/data/accessibility/html/col-expected-auralinux.txt
@@ -1,12 +1,12 @@
 [document web]
 ++[table] cols=2 headers=('Browser', 'Rendering Engine'); rows=2 headers=(NONE); caption=false; spans=(all: 1x1)
 ++++[table row]
-++++++[column header] name='Browser' (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[column header] name='Browser' (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Browser'
-++++++[column header] name='Rendering Engine' (row=0, col=1, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[column header] name='Rendering Engine' (row=0, col=1, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Rendering Engine'
 ++++[table row]
-++++++[table cell] name='Chrome' (row=1, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='Chrome' (row=1, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='Chrome'
-++++++[table cell] name='Blink' (row=1, col=1, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='Blink' (row=1, col=1, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='Blink'
diff --git a/content/test/data/accessibility/html/colgroup-expected-auralinux.txt b/content/test/data/accessibility/html/colgroup-expected-auralinux.txt
index 93d4721..173f62b1 100644
--- a/content/test/data/accessibility/html/colgroup-expected-auralinux.txt
+++ b/content/test/data/accessibility/html/colgroup-expected-auralinux.txt
@@ -1,12 +1,12 @@
 [document web]
 ++[table] cols=2 headers=('Single', 'Pair'); rows=2 headers=(NONE); caption=false; spans=(all: 1x1)
 ++++[table row]
-++++++[column header] name='Single' (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[column header] name='Single' (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Single'
-++++++[column header] name='Pair' (row=0, col=1, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[column header] name='Pair' (row=0, col=1, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Pair'
 ++++[table row]
-++++++[table cell] name='A' (row=1, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='A' (row=1, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='A'
-++++++[table cell] name='AA' (row=1, col=1, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='AA' (row=1, col=1, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='AA'
diff --git a/content/test/data/accessibility/html/contenteditable-descendants-expected-auralinux.txt b/content/test/data/accessibility/html/contenteditable-descendants-expected-auralinux.txt
index fb2efbe..40c01f6e 100644
--- a/content/test/data/accessibility/html/contenteditable-descendants-expected-auralinux.txt
+++ b/content/test/data/accessibility/html/contenteditable-descendants-expected-auralinux.txt
@@ -11,7 +11,7 @@
 ++++++[text] name='.' editable
 ++++[table] editable cols=1 headers=(NONE); rows=1 headers=(NONE); caption=false; spans=(all: 1x1)
 ++++++[table row] editable
-++++++++[table cell] name='Always expose editable tables as tables.' editable (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++++[table cell] name='Always expose editable tables as tables.' editable (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++++[text] name='Always expose editable tables as tables.' editable
 ++++[list] editable
 ++++++[list item] editable
diff --git a/content/test/data/accessibility/html/contenteditable-descendants-with-selection-expected-auralinux.txt b/content/test/data/accessibility/html/contenteditable-descendants-with-selection-expected-auralinux.txt
index 2fa7f7a..c7d2535 100644
--- a/content/test/data/accessibility/html/contenteditable-descendants-with-selection-expected-auralinux.txt
+++ b/content/test/data/accessibility/html/contenteditable-descendants-with-selection-expected-auralinux.txt
@@ -11,7 +11,7 @@
 ++++++[text] name='.' editable
 ++++[table] editable cols=1 headers=(NONE); rows=1 headers=(NONE); caption=false; spans=(all: 1x1)
 ++++++[table row] editable
-++++++++[table cell] name='Always expose editable tables as tables.' editable (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++++[table cell] name='Always expose editable tables as tables.' editable (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++++[text] name='Always expose editable tables as tables.' editable
 ++++[list] editable
 ++++++[list item] editable
diff --git a/content/test/data/accessibility/html/table-focusable-sections-expected-auralinux.txt b/content/test/data/accessibility/html/table-focusable-sections-expected-auralinux.txt
index f776f1df..92491f7 100644
--- a/content/test/data/accessibility/html/table-focusable-sections-expected-auralinux.txt
+++ b/content/test/data/accessibility/html/table-focusable-sections-expected-auralinux.txt
@@ -2,24 +2,24 @@
 ++[table] cols=2 headers=('Sum', 'Subtraction'); rows=4 headers=(NONE); caption=false; spans=(all: 1x1)
 ++++[panel]
 ++++++[table row]
-++++++++[column header] name='Sum' (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++++[column header] name='Sum' (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++++[text] name='Sum'
-++++++++[column header] name='Subtraction' (row=0, col=1, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++++[column header] name='Subtraction' (row=0, col=1, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++++[text] name='Subtraction'
 ++++[panel]
 ++++++[table row]
-++++++++[table cell] name='10' (row=1, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++++[table cell] name='10' (row=1, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++++[text] name='10'
-++++++++[table cell] name='7' (row=1, col=1, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++++[table cell] name='7' (row=1, col=1, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++++[text] name='7'
 ++++++[table row]
-++++++++[table cell] name='2' (row=2, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++++[table cell] name='2' (row=2, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++++[text] name='2'
-++++++++[table cell] name='4' (row=2, col=1, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++++[table cell] name='4' (row=2, col=1, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++++[text] name='4'
 ++++[panel]
 ++++++[table row]
-++++++++[table cell] name='12' (row=3, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++++[table cell] name='12' (row=3, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++++[text] name='12'
-++++++++[table cell] name='3' (row=3, col=1, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++++[table cell] name='3' (row=3, col=1, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++++[text] name='3'
diff --git a/content/test/data/accessibility/html/table-simple-expected-auralinux.txt b/content/test/data/accessibility/html/table-simple-expected-auralinux.txt
index 6f2a7de..b086df3 100644
--- a/content/test/data/accessibility/html/table-simple-expected-auralinux.txt
+++ b/content/test/data/accessibility/html/table-simple-expected-auralinux.txt
@@ -1,17 +1,17 @@
 [document web] name='Table example'
 ++[table] cols=2 headers=('Pair', 'Single'); rows=3 headers=(NONE); caption=false; spans=(all: 1x1)
 ++++[table row]
-++++++[column header] name='Pair' (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[column header] name='Pair' (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Pair'
-++++++[column header] name='Single' (row=0, col=1, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[column header] name='Single' (row=0, col=1, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Single'
 ++++[table row]
-++++++[table cell] name='AB' (row=1, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='AB' (row=1, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='AB'
-++++++[table cell] name='B' (row=1, col=1, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='B' (row=1, col=1, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='B'
 ++++[table row]
-++++++[table cell] name='CD' (row=2, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='CD' (row=2, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='CD'
-++++++[table cell] name='D' (row=2, col=1, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='D' (row=2, col=1, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='D'
diff --git a/content/test/data/accessibility/html/table-spans-expected-auralinux.txt b/content/test/data/accessibility/html/table-spans-expected-auralinux.txt
index 3380342..4161be06 100644
--- a/content/test/data/accessibility/html/table-spans-expected-auralinux.txt
+++ b/content/test/data/accessibility/html/table-spans-expected-auralinux.txt
@@ -1,21 +1,21 @@
 [document web] name='Table example with rowspan and colspan'
 ++[table] cols=2 headers=(NONE); rows=2 headers=(NONE); caption=false; spans=(cell at 0,0: 2x1, cell at 1,0: 2x1)
 ++++[table row]
-++++++[table cell] name='AD' (row=0, col=0, row_span=2, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[table cell] name='AD' (row=0, col=0, row_span=2, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='AD'
-++++++[table cell] name='BC' (row=0, col=1, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[table cell] name='BC' (row=0, col=1, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='BC'
 ++++[table row]
-++++++[table cell] name='EF' (row=1, col=1, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[table cell] name='EF' (row=1, col=1, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='EF'
 ++[table] cols=3 headers=(NONE); rows=2 headers=(NONE); caption=false; spans=(cell at 0,0: 2x1, cell at 0,1: 1x2, cell at 0,2: 1x2, cell at 1,0: 2x1)
 ++++[table row]
-++++++[table cell] name='AD' (row=0, col=0, row_span=2, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[table cell] name='AD' (row=0, col=0, row_span=2, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='AD'
-++++++[table cell] name='BC' (row=0, col=1, row_span=1, col_span=2 n_row_headers=0, n_col_headers=0)
+++++++[table cell] name='BC' (row=0, col=1, row_span=1, col_span=2, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='BC'
 ++++[table row]
-++++++[table cell] name='EF' (row=1, col=1, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[table cell] name='EF' (row=1, col=1, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='EF'
-++++++[table cell] name='GH' (row=1, col=2, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[table cell] name='GH' (row=1, col=2, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='GH'
diff --git a/content/test/data/accessibility/html/table-th-colheader-expected-auralinux.txt b/content/test/data/accessibility/html/table-th-colheader-expected-auralinux.txt
index 15a3f20..53fa61da 100644
--- a/content/test/data/accessibility/html/table-th-colheader-expected-auralinux.txt
+++ b/content/test/data/accessibility/html/table-th-colheader-expected-auralinux.txt
@@ -1,12 +1,12 @@
 [document web]
 ++[table] cols=2 headers=('Firstname', 'Lastname'); rows=2 headers=(NONE); caption=false; spans=(all: 1x1)
 ++++[table row]
-++++++[column header] name='Firstname' table-cell-index:0 (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[column header] name='Firstname' table-cell-index:0 (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Firstname'
-++++++[column header] name='Lastname' table-cell-index:1 (row=0, col=1, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[column header] name='Lastname' table-cell-index:1 (row=0, col=1, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Lastname'
 ++++[table row]
-++++++[table cell] name='Jill' table-cell-index:2 (row=1, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='Jill' table-cell-index:2 (row=1, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='Jill'
-++++++[table cell] name='Smith' table-cell-index:3 (row=1, col=1, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='Smith' table-cell-index:3 (row=1, col=1, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='Smith'
diff --git a/content/test/data/accessibility/html/table-th-rowheader-expected-auralinux.txt b/content/test/data/accessibility/html/table-th-rowheader-expected-auralinux.txt
index ed81a2c..64554698 100644
--- a/content/test/data/accessibility/html/table-th-rowheader-expected-auralinux.txt
+++ b/content/test/data/accessibility/html/table-th-rowheader-expected-auralinux.txt
@@ -1,12 +1,12 @@
 [document web] name='Table example - th rowheader'
 ++[table] cols=2 headers=(NONE); rows=2 headers=('Firstname', 'Lastname'); caption=false; spans=(all: 1x1)
 ++++[table row]
-++++++[row header] name='Firstname' (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[row header] name='Firstname' (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Firstname'
-++++++[table cell] name='Jill' (row=0, col=1, row_span=1, col_span=1 n_row_headers=1, n_col_headers=0)
+++++++[table cell] name='Jill' (row=0, col=1, row_span=1, col_span=1, n_row_headers=1, n_col_headers=0)
 ++++++++[text] name='Jill'
 ++++[table row]
-++++++[row header] name='Lastname' (row=1, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[row header] name='Lastname' (row=1, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Lastname'
-++++++[table cell] name='Smith' (row=1, col=1, row_span=1, col_span=1 n_row_headers=1, n_col_headers=0)
+++++++[table cell] name='Smith' (row=1, col=1, row_span=1, col_span=1, n_row_headers=1, n_col_headers=0)
 ++++++++[text] name='Smith'
diff --git a/content/test/data/accessibility/html/table-thead-tbody-tfoot-expected-auralinux.txt b/content/test/data/accessibility/html/table-thead-tbody-tfoot-expected-auralinux.txt
index f71c4455..49d96556 100644
--- a/content/test/data/accessibility/html/table-thead-tbody-tfoot-expected-auralinux.txt
+++ b/content/test/data/accessibility/html/table-thead-tbody-tfoot-expected-auralinux.txt
@@ -1,22 +1,22 @@
 [document web] name='Table example - thead, tbody, tfoot'
 ++[table] cols=2 headers=('Sum', 'Subtraction'); rows=4 headers=(NONE); caption=false; spans=(all: 1x1)
 ++++[table row]
-++++++[column header] name='Sum' (row=0, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[column header] name='Sum' (row=0, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Sum'
-++++++[column header] name='Subtraction' (row=0, col=1, row_span=1, col_span=1 n_row_headers=0, n_col_headers=0)
+++++++[column header] name='Subtraction' (row=0, col=1, row_span=1, col_span=1, n_row_headers=0, n_col_headers=0)
 ++++++++[text] name='Subtraction'
 ++++[table row]
-++++++[table cell] name='10' (row=1, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='10' (row=1, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='10'
-++++++[table cell] name='7' (row=1, col=1, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='7' (row=1, col=1, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='7'
 ++++[table row]
-++++++[table cell] name='2' (row=2, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='2' (row=2, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='2'
-++++++[table cell] name='4' (row=2, col=1, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='4' (row=2, col=1, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='4'
 ++++[table row]
-++++++[table cell] name='12' (row=3, col=0, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='12' (row=3, col=0, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='12'
-++++++[table cell] name='3' (row=3, col=1, row_span=1, col_span=1 n_row_headers=0, n_col_headers=1)
+++++++[table cell] name='3' (row=3, col=1, row_span=1, col_span=1, n_row_headers=0, n_col_headers=1)
 ++++++++[text] name='3'
diff --git a/dbus/bus_unittest.cc b/dbus/bus_unittest.cc
index 738c64cc..559bfd7 100644
--- a/dbus/bus_unittest.cc
+++ b/dbus/bus_unittest.cc
@@ -9,8 +9,8 @@
 #include "base/files/file_descriptor_watcher_posix.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
 #include "base/threading/thread.h"
 #include "dbus/exported_object.h"
 #include "dbus/object_path.h"
@@ -129,8 +129,7 @@
 }
 
 TEST(BusTest, RemoveObjectProxy) {
-  // Setup the current thread's MessageLoop.
-  base::MessageLoop message_loop;
+  base::test::ScopedTaskEnvironment scoped_task_environment;
 
   // Start the D-Bus thread.
   base::Thread::Options thread_options;
diff --git a/dbus/end_to_end_async_unittest.cc b/dbus/end_to_end_async_unittest.cc
index 2df62ed1..f90c443 100644
--- a/dbus/end_to_end_async_unittest.cc
+++ b/dbus/end_to_end_async_unittest.cc
@@ -11,10 +11,10 @@
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/stl_util.h"
+#include "base/test/scoped_task_environment.h"
 #include "base/test/test_timeouts.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_restrictions.h"
@@ -255,7 +255,7 @@
     run_loop_->Run();
   }
 
-  base::MessageLoop message_loop_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
   std::unique_ptr<base::RunLoop> run_loop_;
   std::vector<std::string> response_strings_;
   std::vector<std::string> error_names_;
@@ -442,7 +442,7 @@
 
   // We shouldn't receive any responses. Wait for a while just to make sure.
   run_loop_.reset(new base::RunLoop);
-  message_loop_.task_runner()->PostDelayedTask(
+  scoped_task_environment_.GetMainThreadTaskRunner()->PostDelayedTask(
       FROM_HERE, run_loop_->QuitClosure(), TestTimeouts::tiny_timeout());
   run_loop_->Run();
   EXPECT_TRUE(response_strings_.empty());
@@ -542,9 +542,9 @@
   // Call the method with an empty callback.
   const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
   object_proxy_->CallMethod(&method_call, timeout_ms, base::DoNothing());
-  // Post a delayed task to quit the message loop.
+  // Post a delayed task to quit the RunLoop.
   run_loop_.reset(new base::RunLoop);
-  message_loop_.task_runner()->PostDelayedTask(
+  scoped_task_environment_.GetMainThreadTaskRunner()->PostDelayedTask(
       FROM_HERE, run_loop_->QuitClosure(), TestTimeouts::tiny_timeout());
   run_loop_->Run();
   // We cannot tell if the empty callback is called, but at least we can
diff --git a/dbus/mock_unittest.cc b/dbus/mock_unittest.cc
index 938d2cf..548bf970 100644
--- a/dbus/mock_unittest.cc
+++ b/dbus/mock_unittest.cc
@@ -7,9 +7,9 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
+#include "base/test/scoped_task_environment.h"
 #include "dbus/message.h"
 #include "dbus/mock_bus.h"
 #include "dbus/mock_exported_object.h"
@@ -83,7 +83,7 @@
 
  protected:
   std::string response_string_;
-  base::MessageLoop message_loop_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
   std::unique_ptr<base::RunLoop> run_loop_;
   scoped_refptr<MockBus> mock_bus_;
   scoped_refptr<MockObjectProxy> mock_proxy_;
@@ -115,15 +115,15 @@
     return nullptr;
   }
 
-  // Creates a response and runs the given response callback in the
-  // message loop with the response. Used to implement for |mock_proxy_|.
+  // Creates a response and posts the given response callback with the
+  // response. Used to implement for |mock_proxy_|.
   void HandleMockProxyResponseWithMessageLoop(
       MethodCall* method_call,
       int timeout_ms,
       ObjectProxy::ResponseCallback* response_callback) {
     std::unique_ptr<Response> response =
         CreateMockProxyResponse(method_call, timeout_ms);
-    message_loop_.task_runner()->PostTask(
+    scoped_task_environment_.GetMainThreadTaskRunner()->PostTask(
         FROM_HERE,
         base::BindOnce(&MockTest::RunResponseCallback, base::Unretained(this),
                        std::move(*response_callback), std::move(response)));
diff --git a/dbus/object_manager_unittest.cc b/dbus/object_manager_unittest.cc
index 3f90734..5654fa0 100644
--- a/dbus/object_manager_unittest.cc
+++ b/dbus/object_manager_unittest.cc
@@ -11,9 +11,9 @@
 #include <vector>
 
 #include "base/bind.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
+#include "base/test/scoped_task_environment.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_restrictions.h"
 #include "dbus/bus.h"
@@ -205,7 +205,7 @@
     WaitForMethodCallback();
   }
 
-  base::MessageLoop message_loop_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
   std::unique_ptr<base::RunLoop> run_loop_;
   std::unique_ptr<base::Thread> dbus_thread_;
   scoped_refptr<Bus> bus_;
@@ -405,7 +405,7 @@
   // after setting up the match rule for PropertiesChanged. We should process
   // the PropertiesChanged event right after that. If we don't receive it within
   // 2 seconds, then fail the test.
-  message_loop_.task_runner()->PostDelayedTask(
+  scoped_task_environment_.GetMainThreadTaskRunner()->PostDelayedTask(
       FROM_HERE,
       base::BindOnce(&ObjectManagerTest::PropertiesChangedTestTimeout,
                      base::Unretained(this)),
diff --git a/dbus/property_unittest.cc b/dbus/property_unittest.cc
index 4846328..f3d4e8f 100644
--- a/dbus/property_unittest.cc
+++ b/dbus/property_unittest.cc
@@ -13,10 +13,10 @@
 
 #include "base/bind.h"
 #include "base/logging.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/test/scoped_task_environment.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_restrictions.h"
 #include "dbus/bus.h"
@@ -158,7 +158,7 @@
     }
   }
 
-  base::MessageLoop message_loop_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
   std::unique_ptr<base::RunLoop> run_loop_;
   std::unique_ptr<base::Thread> dbus_thread_;
   scoped_refptr<Bus> bus_;
diff --git a/dbus/signal_sender_verification_unittest.cc b/dbus/signal_sender_verification_unittest.cc
index 8c6ca57..92fe63a 100644
--- a/dbus/signal_sender_verification_unittest.cc
+++ b/dbus/signal_sender_verification_unittest.cc
@@ -5,11 +5,11 @@
 #include <memory>
 
 #include "base/bind.h"
-#include "base/message_loop/message_loop.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/histogram_samples.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
+#include "base/test/scoped_task_environment.h"
 #include "base/test/test_timeouts.h"
 #include "base/threading/platform_thread.h"
 #include "base/threading/thread_restrictions.h"
@@ -114,8 +114,8 @@
 
   void OnOwnership(bool expected, bool success) {
     ASSERT_EQ(expected, success);
-    // PostTask to quit the MessageLoop as this is called from D-Bus thread.
-    message_loop_.task_runner()->PostTask(
+    // PostTask to quit the RunLoop as this is called from D-Bus thread.
+    scoped_task_environment_.GetMainThreadTaskRunner()->PostTask(
         FROM_HERE,
         base::BindOnce(&SignalSenderVerificationTest::OnOwnershipInternal,
                        base::Unretained(this)));
@@ -166,7 +166,7 @@
     base::ThreadRestrictions::SetIOAllowed(false);
   }
 
-  base::MessageLoop message_loop_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
   std::unique_ptr<base::RunLoop> run_loop_;
   std::unique_ptr<base::Thread> dbus_thread_;
   scoped_refptr<Bus> bus_;
diff --git a/device/gamepad/public/cpp/gamepad_mojom_traits_unittest.cc b/device/gamepad/public/cpp/gamepad_mojom_traits_unittest.cc
index 366b3967..07e6947 100644
--- a/device/gamepad/public/cpp/gamepad_mojom_traits_unittest.cc
+++ b/device/gamepad/public/cpp/gamepad_mojom_traits_unittest.cc
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 #include "device/gamepad/public/cpp/gamepad_mojom_traits.h"
-#include "base/message_loop/message_loop.h"
+#include "base/test/scoped_task_environment.h"
 #include "device/gamepad/public/cpp/gamepad.h"
 #include "device/gamepad/public/mojom/gamepad.mojom.h"
 #include "mojo/public/cpp/test_support/test_utils.h"
@@ -163,7 +163,7 @@
   GamepadStructTraitsTest() {}
 
  private:
-  base::MessageLoop message_loop_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
 
   DISALLOW_COPY_AND_ASSIGN(GamepadStructTraitsTest);
 };
diff --git a/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc b/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc
index e1d7cdb..046fa2a 100644
--- a/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc
+++ b/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc
@@ -260,6 +260,9 @@
     // Set-Cookie if it existed.
     auto saved_headers = current_response_.headers;
     current_response_ = head;
+    // If this redirect is from an HSTS upgrade, OnHeadersReceived will not be
+    // called before OnReceiveRedirect, so make sure the saved headers exist
+    // before setting them.
     if (saved_headers)
       current_response_.headers = saved_headers;
     ContinueToBeforeRedirect(redirect_info, net::OK);
diff --git a/fuchsia/http/http_service_unittest.cc b/fuchsia/http/http_service_unittest.cc
index fcea6be4..ba15a54 100644
--- a/fuchsia/http/http_service_unittest.cc
+++ b/fuchsia/http/http_service_unittest.cc
@@ -369,7 +369,9 @@
 }
 
 // Ensure the service can handle multiple concurrent requests.
-TEST_F(HttpServiceTest, MultipleRequests) {
+// TODO(crbug.com/972212): re-enable test when reason of the flakiness is
+// resolved.
+TEST_F(HttpServiceTest, DISABLED_MultipleRequests) {
   oldhttp::URLLoaderPtr url_loaders[100];
   for (int i = 0; i < 100; i++) {
     http_service()->CreateURLLoader(url_loaders[i].NewRequest());
diff --git a/google_apis/gaia/gaia_auth_fetcher.cc b/google_apis/gaia/gaia_auth_fetcher.cc
index 19fea63..4cf029a 100644
--- a/google_apis/gaia/gaia_auth_fetcher.cc
+++ b/google_apis/gaia/gaia_auth_fetcher.cc
@@ -125,7 +125,9 @@
     case gaia::GaiaSource::kOAuth2LoginVerifier:
       source_string = "ChromiumOAuth2LoginVerifier";
       break;
-    case gaia::GaiaSource::kSigninManager:
+    case gaia::GaiaSource::kPrimaryAccountManager:
+      // Even though this string refers to an old name from the Chromium POV, it
+      // should not be changed as it is passed server-side.
       source_string = "ChromiumSigninManager";
       break;
   }
diff --git a/google_apis/gaia/gaia_auth_fetcher.h b/google_apis/gaia/gaia_auth_fetcher.h
index a0c555f..0039f9a 100644
--- a/google_apis/gaia/gaia_auth_fetcher.h
+++ b/google_apis/gaia/gaia_auth_fetcher.h
@@ -49,7 +49,7 @@
   kAccountReconcilorDice,
   kAccountReconcilorMirror,
   kOAuth2LoginVerifier,
-  kSigninManager
+  kPrimaryAccountManager
 };
 
 }  // namespace gaia
diff --git a/gpu/command_buffer/service/shared_image_backing_factory_iosurface.mm b/gpu/command_buffer/service/shared_image_backing_factory_iosurface.mm
index 2f6cee1..78babfa 100644
--- a/gpu/command_buffer/service/shared_image_backing_factory_iosurface.mm
+++ b/gpu/command_buffer/service/shared_image_backing_factory_iosurface.mm
@@ -462,7 +462,7 @@
         DCHECK(mtl_texture_);
       }
       GrMtlTextureInfo info;
-      info.fTexture = mtl_texture_.get();
+      info.fTexture.retain(mtl_texture_.get());
       gr_backend_texture = GrBackendTexture(size().width(), size().height(),
                                             GrMipMapped::kNo, info);
     }
diff --git a/gpu/config/gpu_info.cc b/gpu/config/gpu_info.cc
index 7b9fddb..4fd34df 100644
--- a/gpu/config/gpu_info.cc
+++ b/gpu/config/gpu_info.cc
@@ -106,6 +106,17 @@
 }
 #endif
 
+void EnumerateANGLEFeature(const gpu::ANGLEFeature& feature,
+                           gpu::GPUInfo::Enumerator* enumerator) {
+  enumerator->BeginANGLEFeature();
+  enumerator->AddString("name", feature.name);
+  enumerator->AddString("category", feature.category);
+  enumerator->AddString("description", feature.description);
+  enumerator->AddString("bug", feature.bug);
+  enumerator->AddString("status", feature.status);
+  enumerator->EndANGLEFeature();
+}
+
 }  // namespace
 
 namespace gpu {
@@ -150,6 +161,13 @@
 ImageDecodeAcceleratorSupportedProfile& ImageDecodeAcceleratorSupportedProfile::
 operator=(ImageDecodeAcceleratorSupportedProfile&& other) = default;
 
+ANGLEFeature::ANGLEFeature() = default;
+ANGLEFeature::ANGLEFeature(const ANGLEFeature& other) = default;
+ANGLEFeature::ANGLEFeature(ANGLEFeature&& other) = default;
+ANGLEFeature::~ANGLEFeature() = default;
+ANGLEFeature& ANGLEFeature::operator=(const ANGLEFeature& other) = default;
+ANGLEFeature& ANGLEFeature::operator=(ANGLEFeature&& other) = default;
+
 GPUInfo::GPUDevice::GPUDevice()
     : vendor_id(0),
       device_id(0),
@@ -257,6 +275,8 @@
 #endif
 
     bool oop_rasterization_supported;
+
+    ANGLEFeatures angle_features;
   };
 
   // If this assert fails then most likely something below needs to be updated.
@@ -326,6 +346,8 @@
   enumerator->AddInt64("rgbaVisual", rgba_visual);
 #endif
   enumerator->AddBool("oopRasterizationSupported", oop_rasterization_supported);
+  for (const auto& angle_feature : angle_features)
+    EnumerateANGLEFeature(angle_feature, enumerator);
   enumerator->EndAuxAttributes();
 }
 
diff --git a/gpu/config/gpu_info.h b/gpu/config/gpu_info.h
index 0e35bc60..46f3975 100644
--- a/gpu/config/gpu_info.h
+++ b/gpu/config/gpu_info.h
@@ -177,6 +177,32 @@
 };
 #endif
 
+// Specification of a feature that can be enabled/disable in ANGLE
+struct GPU_EXPORT ANGLEFeature {
+  ANGLEFeature();
+  ANGLEFeature(const ANGLEFeature& other);
+  ANGLEFeature(ANGLEFeature&& other);
+  ~ANGLEFeature();
+  ANGLEFeature& operator=(const ANGLEFeature& other);
+  ANGLEFeature& operator=(ANGLEFeature&& other);
+
+  // Name of the feature in camel_case.
+  std::string name;
+
+  // Name of the category that the feature belongs to.
+  std::string category;
+
+  // One sentence description of the feature, why it's available.
+  std::string description;
+
+  // Full link to cr/angle bug if applicable.
+  std::string bug;
+
+  // Status, can be "enabled" or "disabled".
+  std::string status;
+};
+using ANGLEFeatures = std::vector<ANGLEFeature>;
+
 struct GPU_EXPORT GPUInfo {
   struct GPU_EXPORT GPUDevice {
     GPUDevice();
@@ -339,6 +365,10 @@
 
   bool oop_rasterization_supported;
 
+  // List of the currently available ANGLE features. May be empty if not
+  // applicable.
+  ANGLEFeatures angle_features;
+
   // Note: when adding new members, please remember to update EnumerateFields
   // in gpu_info.cc.
 
@@ -386,6 +416,9 @@
     virtual void BeginDx12VulkanVersionInfo() = 0;
     virtual void EndDx12VulkanVersionInfo() = 0;
 
+    virtual void BeginANGLEFeature() = 0;
+    virtual void EndANGLEFeature() = 0;
+
    protected:
     virtual ~Enumerator() = default;
   };
diff --git a/gpu/config/gpu_info_collector.cc b/gpu/config/gpu_info_collector.cc
index ad0e520f..735ff74 100644
--- a/gpu/config/gpu_info_collector.cc
+++ b/gpu/config/gpu_info_collector.cc
@@ -28,21 +28,29 @@
 #include "ui/gl/gl_context.h"
 #include "ui/gl/gl_implementation.h"
 #include "ui/gl/gl_surface.h"
+#include "ui/gl/gl_surface_egl.h"
 #include "ui/gl/gl_switches.h"
 #include "ui/gl/gl_version_info.h"
 #include "ui/gl/init/create_gr_gl_interface.h"
 #include "ui/gl/init/gl_factory.h"
 
-#if defined(OS_ANDROID)
-#include "ui/gl/gl_surface_egl.h"
-#endif  // OS_ANDROID
-
 #if defined(USE_X11)
 #include "ui/gl/gl_visual_picker_glx.h"
 #endif
 
 namespace {
 
+// From ANGLE's egl/eglext.h.
+#ifndef EGL_ANGLE_feature_control
+#define EGL_ANGLE_feature_control 1
+#define EGL_FEATURE_NAME_ANGLE 0x3460
+#define EGL_FEATURE_CATEGORY_ANGLE 0x3461
+#define EGL_FEATURE_DESCRIPTION_ANGLE 0x3462
+#define EGL_FEATURE_BUG_ANGLE 0x3463
+#define EGL_FEATURE_STATUS_ANGLE 0x3464
+#define EGL_FEATURE_COUNT_ANGLE 0x3465
+#endif /* EGL_ANGLE_feature_control */
+
 scoped_refptr<gl::GLSurface> InitializeGLSurface() {
   scoped_refptr<gl::GLSurface> surface(
       gl::init::CreateOffscreenGLSurface(gfx::Size()));
@@ -80,6 +88,16 @@
   return std::string();
 }
 
+std::string QueryEGLStringi(EGLDisplay display,
+                            unsigned int name,
+                            unsigned int index) {
+  const char* egl_string =
+      reinterpret_cast<const char*>(eglQueryStringiANGLE(display, name, index));
+  if (egl_string)
+    return std::string(egl_string);
+  return std::string();
+}
+
 // Return a version string in the format of "major.minor".
 std::string GetVersionFromString(const std::string& version_string) {
   size_t begin = version_string.find_first_of("0123456789");
@@ -263,6 +281,28 @@
   gpu_info->pixel_shader_version = glsl_version;
   gpu_info->vertex_shader_version = glsl_version;
 
+  // Populate the list of ANGLE features by querying the functions exposed by
+  // EGL_ANGLE_feature_control if it's available.
+  if (gl::GLSurfaceEGL::IsANGLEFeatureControlSupported()) {
+    EGLDisplay display = gl::GLSurfaceEGL::GetHardwareDisplay();
+    EGLAttrib feature_count = 0;
+    eglQueryDisplayAttribANGLE(display, EGL_FEATURE_COUNT_ANGLE,
+                               &feature_count);
+    gpu_info->angle_features.resize(static_cast<size_t>(feature_count));
+    for (size_t i = 0; i < gpu_info->angle_features.size(); i++) {
+      gpu_info->angle_features[i].name =
+          QueryEGLStringi(display, EGL_FEATURE_NAME_ANGLE, i);
+      gpu_info->angle_features[i].category =
+          QueryEGLStringi(display, EGL_FEATURE_CATEGORY_ANGLE, i);
+      gpu_info->angle_features[i].description =
+          QueryEGLStringi(display, EGL_FEATURE_DESCRIPTION_ANGLE, i);
+      gpu_info->angle_features[i].bug =
+          QueryEGLStringi(display, EGL_FEATURE_BUG_ANGLE, i);
+      gpu_info->angle_features[i].status =
+          QueryEGLStringi(display, EGL_FEATURE_STATUS_ANGLE, i);
+    }
+  }
+
   IdentifyActiveGPU(gpu_info);
   return true;
 }
diff --git a/gpu/ipc/common/gpu_info.mojom b/gpu/ipc/common/gpu_info.mojom
index 9705ef1..a11e5844 100644
--- a/gpu/ipc/common/gpu_info.mojom
+++ b/gpu/ipc/common/gpu_info.mojom
@@ -116,6 +116,15 @@
   uint32 vulkan_version;
 };
 
+// gpu::ANGLEFeature
+struct ANGLEFeature {
+  string name;
+  string category;
+  string description;
+  string bug;
+  string status;
+};
+
 // Corresponds to |gpu::GPUInfo| in gpu/config/gpu_info.h
 struct GpuInfo {
   mojo_base.mojom.TimeDelta initialization_time;
@@ -167,4 +176,6 @@
   uint64 system_visual;
   uint64 rgba_visual;
   bool oop_rasterization_supported;
+
+  array<ANGLEFeature> angle_features;
 };
diff --git a/gpu/ipc/common/gpu_info.typemap b/gpu/ipc/common/gpu_info.typemap
index 4ff5fe2..227c76c 100644
--- a/gpu/ipc/common/gpu_info.typemap
+++ b/gpu/ipc/common/gpu_info.typemap
@@ -22,4 +22,5 @@
   "gpu.mojom.VideoDecodeAcceleratorCapabilities=gpu::VideoDecodeAcceleratorCapabilities",
   "gpu.mojom.VideoEncodeAcceleratorSupportedProfile=gpu::VideoEncodeAcceleratorSupportedProfile",
   "gpu.mojom.ImageDecodeAcceleratorSupportedProfile=gpu::ImageDecodeAcceleratorSupportedProfile",
+  "gpu.mojom.ANGLEFeature=gpu::ANGLEFeature",
 ]
diff --git a/gpu/ipc/common/gpu_info_struct_traits.cc b/gpu/ipc/common/gpu_info_struct_traits.cc
index 28d5662..687a69a 100644
--- a/gpu/ipc/common/gpu_info_struct_traits.cc
+++ b/gpu/ipc/common/gpu_info_struct_traits.cc
@@ -350,6 +350,15 @@
 }
 #endif
 
+// static
+bool StructTraits<gpu::mojom::ANGLEFeatureDataView, gpu::ANGLEFeature>::Read(
+    gpu::mojom::ANGLEFeatureDataView data,
+    gpu::ANGLEFeature* out) {
+  return data.ReadName(&out->name) && data.ReadCategory(&out->category) &&
+         data.ReadDescription(&out->description) && data.ReadBug(&out->bug) &&
+         data.ReadStatus(&out->status);
+}
+
 bool StructTraits<gpu::mojom::GpuInfoDataView, gpu::GPUInfo>::Read(
     gpu::mojom::GpuInfoDataView data,
     gpu::GPUInfo* out) {
@@ -403,7 +412,8 @@
          data.ReadVideoEncodeAcceleratorSupportedProfiles(
              &out->video_encode_accelerator_supported_profiles) &&
          data.ReadImageDecodeAcceleratorSupportedProfiles(
-             &out->image_decode_accelerator_supported_profiles);
+             &out->image_decode_accelerator_supported_profiles) &&
+         data.ReadAngleFeatures(&out->angle_features);
 }
 
 }  // namespace mojo
diff --git a/gpu/ipc/common/gpu_info_struct_traits.h b/gpu/ipc/common/gpu_info_struct_traits.h
index 9877fa47..93b0a635 100644
--- a/gpu/ipc/common/gpu_info_struct_traits.h
+++ b/gpu/ipc/common/gpu_info_struct_traits.h
@@ -220,6 +220,32 @@
 #endif
 
 template <>
+struct StructTraits<gpu::mojom::ANGLEFeatureDataView, gpu::ANGLEFeature> {
+  static bool Read(gpu::mojom::ANGLEFeatureDataView data,
+                   gpu::ANGLEFeature* out);
+
+  static const std::string& name(const gpu::ANGLEFeature& input) {
+    return input.name;
+  }
+
+  static const std::string& category(const gpu::ANGLEFeature& input) {
+    return input.category;
+  }
+
+  static const std::string& description(const gpu::ANGLEFeature& input) {
+    return input.description;
+  }
+
+  static const std::string& bug(const gpu::ANGLEFeature& input) {
+    return input.bug;
+  }
+
+  static const std::string& status(const gpu::ANGLEFeature& input) {
+    return input.status;
+  }
+};
+
+template <>
 struct StructTraits<gpu::mojom::GpuInfoDataView, gpu::GPUInfo> {
   static bool Read(gpu::mojom::GpuInfoDataView data, gpu::GPUInfo* out);
 
@@ -380,6 +406,11 @@
   static bool oop_rasterization_supported(const gpu::GPUInfo& input) {
     return input.oop_rasterization_supported;
   }
+
+  static std::vector<gpu::ANGLEFeature> angle_features(
+      const gpu::GPUInfo& input) {
+    return input.angle_features;
+  }
 };
 
 }  // namespace mojo
diff --git a/ios/BUILD.gn b/ios/BUILD.gn
index 323b491..20da26e6 100644
--- a/ios/BUILD.gn
+++ b/ios/BUILD.gn
@@ -54,6 +54,7 @@
       "//ios/chrome/test:all_tests",
       "//ios/chrome/test/earl_grey:all_tests",
       "//ios/chrome/test/earl_grey2:all_tests",
+      "//ios/chrome/test/wpt:all_tests",
       "//ios/components:all_tests",
       "//ios/net:all_tests",
       "//ios/showcase:all_tests",
diff --git a/ios/build/bots/chromium.fyi/ios13-beta-simulator.json b/ios/build/bots/chromium.fyi/ios13-beta-simulator.json
index d3c176d1..5262131e 100644
--- a/ios/build/bots/chromium.fyi/ios13-beta-simulator.json
+++ b/ios/build/bots/chromium.fyi/ios13-beta-simulator.json
@@ -1,9 +1,9 @@
 {
   "comments": [
     "Run tests on iOS13beta track on 64-bit iOS 13 simulators.",
-    "Note: Xcode 11 will requires OSX 10.14."
+    "Note: Xcode 11 requires OSX 10.14.3 and up"
   ],
-  "xcode build version": "10b61",
+  "xcode build version": "10e1001",
   "gn_args": [
     "goma_dir=\"$(goma_dir)\"",
     "is_component_build=false",
@@ -14,5 +14,315 @@
     "use_goma=true"
   ],
   "tests": [
+    {
+      "xcode parallelization": true,
+      "include": "eg2_tests.json",
+      "device type": "iPhone X",
+      "os": "13.0",
+      "xcode build version": "11m336w",
+      "pool":"Chrome",
+      "host os": "Mac-10.14.4",
+      "optional_dimensions": {
+          "60": [{
+            "host os": "Mac-10.14.5"
+          }],
+          "120": [{
+            "host os": "Mac-10.14.3"
+          }]
+      }
+    },
+    {
+      "xcode parallelization": true,
+      "include": "eg2_tests.json",
+      "device type": "iPad 6th Gen",
+      "os": "13.0",
+      "xcode build version": "11m336w",
+      "pool":"Chrome",
+      "host os": "Mac-10.14.4",
+      "optional_dimensions": {
+          "60": [{
+            "host os": "Mac-10.14.5"
+          }],
+          "120": [{
+            "host os": "Mac-10.14.3"
+          }]
+      }
+    },
+    {
+      "xcode parallelization": true,
+      "include": "eg2_tests.json",
+      "device type": "iPhone X",
+      "os": "12.2",
+      "xcode build version": "10e1001",
+      "pool":"Chrome",
+      "host os": "Mac-10.14.4",
+      "optional_dimensions": {
+          "60": [{
+            "host os": "Mac-10.14.5"
+          }],
+          "120": [{
+            "host os": "Mac-10.14.3"
+          }]
+      }
+    },
+    {
+      "xcode parallelization": true,
+      "include": "eg2_tests.json",
+      "device type": "iPad 6th Gen",
+      "os": "12.2",
+      "xcode build version": "10e1001",
+      "pool":"Chrome",
+      "host os": "Mac-10.14.4",
+      "optional_dimensions": {
+          "60": [{
+            "host os": "Mac-10.14.5"
+          }],
+          "120": [{
+            "host os": "Mac-10.14.3"
+          }]
+      }
+    },
+    {
+      "xcode parallelization": true,
+      "include": "eg2_tests.json",
+      "device type": "iPhone X",
+      "os": "11.4",
+      "xcode build version": "10e1001",
+      "pool":"Chrome",
+      "host os": "Mac-10.14.4",
+      "optional_dimensions": {
+          "60": [{
+            "host os": "Mac-10.14.5"
+          }],
+          "120": [{
+            "host os": "Mac-10.14.3"
+          }]
+      }
+    },
+    {
+      "xcode parallelization": true,
+      "include": "eg2_tests.json",
+      "device type": "iPad 6th Gen",
+      "os": "11.4",
+      "xcode build version": "10e1001",
+      "pool":"Chrome",
+      "host os": "Mac-10.14.4",
+      "optional_dimensions": {
+          "60": [{
+            "host os": "Mac-10.14.5"
+          }],
+          "120": [{
+            "host os": "Mac-10.14.3"
+          }]
+      }
+    },
+    {
+      "include": "common_tests.json",
+      "device type": "iPhone X",
+      "os": "13.3",
+      "xcode build version": "11m336w",
+      "host os": "Mac-10.14.4",
+      "pool":"Chrome",
+      "optional_dimensions": {
+          "60": [{
+            "host os": "Mac-10.14.5"
+          }],
+          "120": [{
+            "host os": "Mac-10.14.3"
+          }]
+      }
+    },
+    {
+      "include": "eg_cq_tests.json",
+      "device type": "iPhone X",
+      "os": "13.0",
+      "xcode build version": "11m336w",
+      "host os": "Mac-10.14.4",
+      "pool":"Chrome",
+      "optional_dimensions": {
+          "60": [{
+            "host os": "Mac-10.14.5"
+          }],
+          "120": [{
+            "host os": "Mac-10.14.3"
+          }]
+      }
+    },
+    {
+      "include": "eg_cq_tests.json",
+      "device type": "iPhone 6 Plus",
+      "os": "13.0",
+      "xcode build version": "11m336w",
+      "host os": "Mac-10.14.4",
+      "pool":"Chrome",
+      "optional_dimensions": {
+          "60": [{
+            "host os": "Mac-10.14.5"
+          }],
+          "120": [{
+            "host os": "Mac-10.14.3"
+          }]
+      }
+    },
+    {
+      "include": "eg_cq_tests.json",
+      "device type": "iPhone 5s",
+      "os": "13.0",
+      "xcode build version": "11m336w",
+      "host os": "Mac-10.14.4",
+      "pool":"Chrome",
+      "optional_dimensions": {
+          "60": [{
+            "host os": "Mac-10.14.5"
+          }],
+          "120": [{
+            "host os": "Mac-10.14.3"
+          }]
+      }
+    },
+    {
+      "include": "eg_cq_tests.json",
+      "device type": "iPad Pro (12.9-inch)",
+      "os": "13.0",
+      "xcode build version": "11m336w",
+      "host os": "Mac-10.14.4",
+      "pool":"Chrome",
+      "optional_dimensions": {
+          "60": [{
+            "host os": "Mac-10.14.5"
+          }],
+          "120": [{
+            "host os": "Mac-10.14.3"
+          }]
+      }
+    },
+    {
+      "include": "eg_tests.json",
+      "device type": "iPhone X",
+      "os": "13.0",
+      "xcode build version": "11m336w",
+      "host os": "Mac-10.14.4",
+      "pool":"Chrome",
+      "optional_dimensions": {
+          "60": [{
+            "host os": "Mac-10.14.5"
+          }],
+          "120": [{
+            "host os": "Mac-10.14.3"
+          }]
+      }
+    },
+    {
+      "include": "eg_tests.json",
+      "device type": "iPhone 6 Plus",
+      "os": "13.0",
+      "xcode build version": "11m336w",
+      "host os": "Mac-10.14.4",
+      "pool":"Chrome",
+      "optional_dimensions": {
+          "60": [{
+            "host os": "Mac-10.14.5"
+          }],
+          "120": [{
+            "host os": "Mac-10.14.3"
+          }]
+      }
+    },
+    {
+      "include": "eg_tests.json",
+      "device type": "iPad Air",
+      "os": "13.0",
+      "xcode build version": "11m336w",
+      "host os": "Mac-10.14.4",
+      "pool":"Chrome",
+      "optional_dimensions": {
+          "60": [{
+            "host os": "Mac-10.14.5"
+          }],
+          "120": [{
+            "host os": "Mac-10.14.3"
+          }]
+      }
+    },
+    {
+      "include": "eg_tests.json",
+      "device type": "iPhone 5s",
+      "os": "13.0",
+      "xcode build version": "11m336w",
+      "host os": "Mac-10.14.4",
+      "pool":"Chrome",
+      "optional_dimensions": {
+          "60": [{
+            "host os": "Mac-10.14.5"
+          }],
+          "120": [{
+            "host os": "Mac-10.14.3"
+          }]
+      }
+    },
+    {
+      "include": "screen_size_dependent_tests.json",
+      "device type": "iPhone 6s Plus",
+      "os": "13.0",
+      "xcode build version": "11m336w",
+      "host os": "Mac-10.14.4",
+      "pool":"Chrome",
+      "optional_dimensions": {
+          "60": [{
+            "host os": "Mac-10.14.5"
+          }],
+          "120": [{
+            "host os": "Mac-10.14.3"
+          }]
+      }
+    },
+    {
+      "include": "screen_size_dependent_tests.json",
+      "device type": "iPhone X",
+      "os": "13.0",
+      "xcode build version": "11m336w",
+      "host os": "Mac-10.14.4",
+      "pool":"Chrome",
+      "optional_dimensions": {
+          "60": [{
+            "host os": "Mac-10.14.5"
+          }],
+          "120": [{
+            "host os": "Mac-10.14.3"
+          }]
+      }
+    },
+    {
+      "include": "screen_size_dependent_tests.json",
+      "device type": "iPhone 5s",
+      "os": "13.0",
+      "xcode build version": "11m336w",
+      "host os": "Mac-10.14.4",
+      "pool":"Chrome",
+      "optional_dimensions": {
+          "60": [{
+            "host os": "Mac-10.14.5"
+          }],
+          "120": [{
+            "host os": "Mac-10.14.3"
+          }]
+      }
+    },
+    {
+      "include": "screen_size_dependent_tests.json",
+      "device type": "iPad Air 2",
+      "os": "13.0",
+      "xcode build version": "11m336w",
+      "host os": "Mac-10.14.4",
+      "pool":"Chrome",
+      "optional_dimensions": {
+          "60": [{
+            "host os": "Mac-10.14.5"
+          }],
+          "120": [{
+            "host os": "Mac-10.14.3"
+          }]
+      }
+    }
   ]
 }
diff --git a/ios/build/bots/chromium.fyi/ios13-sdk-simulator.json b/ios/build/bots/chromium.fyi/ios13-sdk-simulator.json
index 19951f2..656613c7 100644
--- a/ios/build/bots/chromium.fyi/ios13-sdk-simulator.json
+++ b/ios/build/bots/chromium.fyi/ios13-sdk-simulator.json
@@ -24,10 +24,30 @@
       "device type": "iPhone X",
       "os": "13.0",
       "pool":"Chrome",
-      "host os": "Mac-10.14.3",
+      "host os": "Mac-10.14.4",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.14.4"
+            "host os": "Mac-10.14.5"
+          }],
+          "120": [{
+            "host os": "Mac-10.14.3"
+          }]
+      },
+      "priority": 30
+    },
+    {
+      "xcode parallelization": true,
+      "include": "eg2_tests.json",
+      "device type": "iPad 6th Gen",
+      "os": "13.0",
+      "pool":"Chrome",
+      "host os": "Mac-10.14.4",
+      "optional_dimensions": {
+          "60": [{
+            "host os": "Mac-10.14.5"
+          }],
+          "120": [{
+            "host os": "Mac-10.14.3"
           }]
       },
       "priority": 30
diff --git a/ios/build/bots/chromium.mac/ios13-beta-simulator.json b/ios/build/bots/chromium.mac/ios13-beta-simulator.json
index d8c3d43..c170fd2 100644
--- a/ios/build/bots/chromium.mac/ios13-beta-simulator.json
+++ b/ios/build/bots/chromium.mac/ios13-beta-simulator.json
@@ -1,11 +1,11 @@
 {
   "comments": [
     "Run tests on iOS13beta track on 64-bit iOS 13 simulators.",
-    "Note: Xcode 11 will requires OSX 10.14.",
+    "Note: Xcode 11 requires OSX 10.14.3 and up",
     "Note: This file exists only to support the trybot.",
     "It should be kept in sync with the CI configuration in ../chromium.fyi/."
   ],
-  "xcode build version": "10b61",
+  "xcode build version": "10e1001",
   "gn_args": [
     "goma_dir=\"$(goma_dir)\"",
     "is_component_build=false",
@@ -16,5 +16,315 @@
     "use_goma=true"
   ],
   "tests": [
+    {
+      "xcode parallelization": true,
+      "include": "eg2_tests.json",
+      "device type": "iPhone X",
+      "os": "13.0",
+      "xcode build version": "11m336w",
+      "pool":"Chrome",
+      "host os": "Mac-10.14.4",
+      "optional_dimensions": {
+          "60": [{
+            "host os": "Mac-10.14.5"
+          }],
+          "120": [{
+            "host os": "Mac-10.14.3"
+          }]
+      }
+    },
+    {
+      "xcode parallelization": true,
+      "include": "eg2_tests.json",
+      "device type": "iPad 6th Gen",
+      "os": "13.0",
+      "xcode build version": "11m336w",
+      "pool":"Chrome",
+      "host os": "Mac-10.14.4",
+      "optional_dimensions": {
+          "60": [{
+            "host os": "Mac-10.14.5"
+          }],
+          "120": [{
+            "host os": "Mac-10.14.3"
+          }]
+      }
+    },
+    {
+      "xcode parallelization": true,
+      "include": "eg2_tests.json",
+      "device type": "iPhone X",
+      "os": "12.2",
+      "xcode build version": "10e1001",
+      "pool":"Chrome",
+      "host os": "Mac-10.14.4",
+      "optional_dimensions": {
+          "60": [{
+            "host os": "Mac-10.14.5"
+          }],
+          "120": [{
+            "host os": "Mac-10.14.3"
+          }]
+      }
+    },
+    {
+      "xcode parallelization": true,
+      "include": "eg2_tests.json",
+      "device type": "iPad 6th Gen",
+      "os": "12.2",
+      "xcode build version": "10e1001",
+      "pool":"Chrome",
+      "host os": "Mac-10.14.4",
+      "optional_dimensions": {
+          "60": [{
+            "host os": "Mac-10.14.5"
+          }],
+          "120": [{
+            "host os": "Mac-10.14.3"
+          }]
+      }
+    },
+    {
+      "xcode parallelization": true,
+      "include": "eg2_tests.json",
+      "device type": "iPhone X",
+      "os": "11.4",
+      "xcode build version": "10e1001",
+      "pool":"Chrome",
+      "host os": "Mac-10.14.4",
+      "optional_dimensions": {
+          "60": [{
+            "host os": "Mac-10.14.5"
+          }],
+          "120": [{
+            "host os": "Mac-10.14.3"
+          }]
+      }
+    },
+    {
+      "xcode parallelization": true,
+      "include": "eg2_tests.json",
+      "device type": "iPad 6th Gen",
+      "os": "11.4",
+      "xcode build version": "10e1001",
+      "pool":"Chrome",
+      "host os": "Mac-10.14.4",
+      "optional_dimensions": {
+          "60": [{
+            "host os": "Mac-10.14.5"
+          }],
+          "120": [{
+            "host os": "Mac-10.14.3"
+          }]
+      }
+    },
+    {
+      "include": "common_tests.json",
+      "device type": "iPhone X",
+      "os": "13.3",
+      "xcode build version": "11m336w",
+      "host os": "Mac-10.14.4",
+      "pool":"Chrome",
+      "optional_dimensions": {
+          "60": [{
+            "host os": "Mac-10.14.5"
+          }],
+          "120": [{
+            "host os": "Mac-10.14.3"
+          }]
+      }
+    },
+    {
+      "include": "eg_cq_tests.json",
+      "device type": "iPhone X",
+      "os": "13.0",
+      "xcode build version": "11m336w",
+      "host os": "Mac-10.14.4",
+      "pool":"Chrome",
+      "optional_dimensions": {
+          "60": [{
+            "host os": "Mac-10.14.5"
+          }],
+          "120": [{
+            "host os": "Mac-10.14.3"
+          }]
+      }
+    },
+    {
+      "include": "eg_cq_tests.json",
+      "device type": "iPhone 6 Plus",
+      "os": "13.0",
+      "xcode build version": "11m336w",
+      "host os": "Mac-10.14.4",
+      "pool":"Chrome",
+      "optional_dimensions": {
+          "60": [{
+            "host os": "Mac-10.14.5"
+          }],
+          "120": [{
+            "host os": "Mac-10.14.3"
+          }]
+      }
+    },
+    {
+      "include": "eg_cq_tests.json",
+      "device type": "iPhone 5s",
+      "os": "13.0",
+      "xcode build version": "11m336w",
+      "host os": "Mac-10.14.4",
+      "pool":"Chrome",
+      "optional_dimensions": {
+          "60": [{
+            "host os": "Mac-10.14.5"
+          }],
+          "120": [{
+            "host os": "Mac-10.14.3"
+          }]
+      }
+    },
+    {
+      "include": "eg_cq_tests.json",
+      "device type": "iPad Pro (12.9-inch)",
+      "os": "13.0",
+      "xcode build version": "11m336w",
+      "host os": "Mac-10.14.4",
+      "pool":"Chrome",
+      "optional_dimensions": {
+          "60": [{
+            "host os": "Mac-10.14.5"
+          }],
+          "120": [{
+            "host os": "Mac-10.14.3"
+          }]
+      }
+    },
+    {
+      "include": "eg_tests.json",
+      "device type": "iPhone X",
+      "os": "13.0",
+      "xcode build version": "11m336w",
+      "host os": "Mac-10.14.4",
+      "pool":"Chrome",
+      "optional_dimensions": {
+          "60": [{
+            "host os": "Mac-10.14.5"
+          }],
+          "120": [{
+            "host os": "Mac-10.14.3"
+          }]
+      }
+    },
+    {
+      "include": "eg_tests.json",
+      "device type": "iPhone 6 Plus",
+      "os": "13.0",
+      "xcode build version": "11m336w",
+      "host os": "Mac-10.14.4",
+      "pool":"Chrome",
+      "optional_dimensions": {
+          "60": [{
+            "host os": "Mac-10.14.5"
+          }],
+          "120": [{
+            "host os": "Mac-10.14.3"
+          }]
+      }
+    },
+    {
+      "include": "eg_tests.json",
+      "device type": "iPad Air",
+      "os": "13.0",
+      "xcode build version": "11m336w",
+      "host os": "Mac-10.14.4",
+      "pool":"Chrome",
+      "optional_dimensions": {
+          "60": [{
+            "host os": "Mac-10.14.5"
+          }],
+          "120": [{
+            "host os": "Mac-10.14.3"
+          }]
+      }
+    },
+    {
+      "include": "eg_tests.json",
+      "device type": "iPhone 5s",
+      "os": "13.0",
+      "xcode build version": "11m336w",
+      "host os": "Mac-10.14.4",
+      "pool":"Chrome",
+      "optional_dimensions": {
+          "60": [{
+            "host os": "Mac-10.14.5"
+          }],
+          "120": [{
+            "host os": "Mac-10.14.3"
+          }]
+      }
+    },
+    {
+      "include": "screen_size_dependent_tests.json",
+      "device type": "iPhone 6s Plus",
+      "os": "13.0",
+      "xcode build version": "11m336w",
+      "host os": "Mac-10.14.4",
+      "pool":"Chrome",
+      "optional_dimensions": {
+          "60": [{
+            "host os": "Mac-10.14.5"
+          }],
+          "120": [{
+            "host os": "Mac-10.14.3"
+          }]
+      }
+    },
+    {
+      "include": "screen_size_dependent_tests.json",
+      "device type": "iPhone X",
+      "os": "13.0",
+      "xcode build version": "11m336w",
+      "host os": "Mac-10.14.4",
+      "pool":"Chrome",
+      "optional_dimensions": {
+          "60": [{
+            "host os": "Mac-10.14.5"
+          }],
+          "120": [{
+            "host os": "Mac-10.14.3"
+          }]
+      }
+    },
+    {
+      "include": "screen_size_dependent_tests.json",
+      "device type": "iPhone 5s",
+      "os": "13.0",
+      "xcode build version": "11m336w",
+      "host os": "Mac-10.14.4",
+      "pool":"Chrome",
+      "optional_dimensions": {
+          "60": [{
+            "host os": "Mac-10.14.5"
+          }],
+          "120": [{
+            "host os": "Mac-10.14.3"
+          }]
+      }
+    },
+    {
+      "include": "screen_size_dependent_tests.json",
+      "device type": "iPad Air 2",
+      "os": "13.0",
+      "xcode build version": "11m336w",
+      "host os": "Mac-10.14.4",
+      "pool":"Chrome",
+      "optional_dimensions": {
+          "60": [{
+            "host os": "Mac-10.14.5"
+          }],
+          "120": [{
+            "host os": "Mac-10.14.3"
+          }]
+      }
+    }
   ]
 }
diff --git a/ios/build/bots/chromium.mac/ios13-sdk-simulator.json b/ios/build/bots/chromium.mac/ios13-sdk-simulator.json
index 19951f2..6636e95 100644
--- a/ios/build/bots/chromium.mac/ios13-sdk-simulator.json
+++ b/ios/build/bots/chromium.mac/ios13-sdk-simulator.json
@@ -1,6 +1,9 @@
 {
   "comments": [
-    "Runs tests on 64-bit iOS 11.4 and 12.1 and 13.0 tests"
+    "Runs tests on 64-bit iOS 11.4 and 12.1 and 13.0 tests.",
+    "Note: Xcode 11 requires OSX 10.14.3 and up",
+    "Note: This file exists only to support the trybot.",
+    "It should be kept in sync with the CI configuration in ../chromium.fyi/."
   ],
   "xcode build version": "11m336w",
   "gn_args": [
@@ -24,10 +27,30 @@
       "device type": "iPhone X",
       "os": "13.0",
       "pool":"Chrome",
-      "host os": "Mac-10.14.3",
+      "host os": "Mac-10.14.4",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.14.4"
+            "host os": "Mac-10.14.5"
+          }],
+          "120": [{
+            "host os": "Mac-10.14.3"
+          }]
+      },
+      "priority": 30
+    },
+    {
+      "xcode parallelization": true,
+      "include": "eg2_tests.json",
+      "device type": "iPad 6th Gen",
+      "os": "13.0",
+      "pool":"Chrome",
+      "host os": "Mac-10.14.4",
+      "optional_dimensions": {
+          "60": [{
+            "host os": "Mac-10.14.5"
+          }],
+          "120": [{
+            "host os": "Mac-10.14.3"
           }]
       },
       "priority": 30
diff --git a/ios/build/bots/tests/eg2_tests.json b/ios/build/bots/tests/eg2_tests.json
index af254bb..df6730b 100644
--- a/ios/build/bots/tests/eg2_tests.json
+++ b/ios/build/bots/tests/eg2_tests.json
@@ -8,6 +8,14 @@
             "host": "ios_chrome_eg2tests"
         },
         {
+            "app": "ios_chrome_ui_eg2tests_module",
+            "host": "ios_chrome_eg2tests"
+        },
+        {
+            "app": "ios_chrome_web_eg2tests_module",
+            "host": "ios_chrome_eg2tests"
+        },
+        {
             "app": "ios_web_shell_eg2tests_module",
             "host": "ios_web_shell_eg2tests"
         }
diff --git a/ios/chrome/browser/DEPS b/ios/chrome/browser/DEPS
index 993b86e..d4e1ffd9d1 100644
--- a/ios/chrome/browser/DEPS
+++ b/ios/chrome/browser/DEPS
@@ -76,8 +76,8 @@
   # Use identity_manager.h instead of the below files;
   # see https://groups.google.com/a/chromium.org/d/msg/chromium-dev/dgFLuxqZt1o/iEqkyoQQBwAJ for help and info.
   "!components/signin/core/browser/fake_profile_oauth2_token_service.h",
-  "!components/signin/core/browser/signin_manager.h",
-  "!components/signin/core/browser/signin_manager_base.h",
+  "!components/signin/core/browser/primary_account_manager.h",
+  "!components/signin/core/browser/primary_account_policy_manager.h",
   "+components/signin/ios/browser",
   "+components/ssl_errors",
   "+components/suggestions",
diff --git a/ios/chrome/browser/browser_state/chrome_browser_state_manager_impl.cc b/ios/chrome/browser/browser_state/chrome_browser_state_manager_impl.cc
index 915a6f1..b5d64b0 100644
--- a/ios/chrome/browser/browser_state/chrome_browser_state_manager_impl.cc
+++ b/ios/chrome/browser/browser_state/chrome_browser_state_manager_impl.cc
@@ -229,7 +229,7 @@
   size_t browser_state_index =
       cache->GetIndexOfBrowserStateWithPath(browser_state->GetStatePath());
   if (browser_state_index != std::string::npos) {
-    // The BrowserStateInfoCache's info must match the Signin Manager.
+    // The BrowserStateInfoCache's info must match the IdentityManager.
     cache->SetAuthInfoOfBrowserStateAtIndex(browser_state_index,
                                             account_info.gaia, username);
     return;
diff --git a/ios/chrome/browser/signin/authentication_service.mm b/ios/chrome/browser/signin/authentication_service.mm
index b2837d9..7f7cd78d 100644
--- a/ios/chrome/browser/signin/authentication_service.mm
+++ b/ios/chrome/browser/signin/authentication_service.mm
@@ -327,14 +327,14 @@
       identity_manager_->LegacySeedAccountInfo(info);
   std::string old_authenticated_account_id =
       identity_manager_->GetPrimaryAccountId();
-  // |SigninManager::SetAuthenticatedAccountId| simply ignores the call if
-  // there is already a signed in user. Check that there is no signed in account
-  // or that the new signed in account matches the old one to avoid a mismatch
-  // between the old and the new authenticated accounts.
+  // |PrimaryAccountManager::SetAuthenticatedAccountId| simply ignores the call
+  // if there is already a signed in user. Check that there is no signed in
+  // account or that the new signed in account matches the old one to avoid a
+  // mismatch between the old and the new authenticated accounts.
   if (!old_authenticated_account_id.empty())
     CHECK_EQ(new_authenticated_account_id, old_authenticated_account_id);
 
-  // Update the SigninManager with the new logged in identity.
+  // Update the PrimaryAccountManager with the new logged in identity.
   auto* account_mutator = identity_manager_->GetPrimaryAccountMutator();
   DCHECK(account_mutator);
   account_mutator->SetPrimaryAccount(new_authenticated_account_id);
diff --git a/ios/chrome/browser/signin/identity_manager_factory.cc b/ios/chrome/browser/signin/identity_manager_factory.cc
index 96b31f6..8d824b91 100644
--- a/ios/chrome/browser/signin/identity_manager_factory.cc
+++ b/ios/chrome/browser/signin/identity_manager_factory.cc
@@ -14,8 +14,8 @@
 #include "components/signin/core/browser/account_consistency_method.h"
 #include "components/signin/core/browser/gaia_cookie_manager_service.h"
 #include "components/signin/core/browser/identity_manager_wrapper.h"
+#include "components/signin/core/browser/primary_account_policy_manager.h"
 #include "components/signin/core/browser/profile_oauth2_token_service.h"
-#include "components/signin/core/browser/signin_manager.h"
 #include "components/signin/ios/browser/profile_oauth2_token_service_ios_delegate.h"
 #include "ios/chrome/browser/application_context.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
@@ -60,14 +60,15 @@
   return account_fetcher_service;
 }
 
-std::unique_ptr<SigninManagerBase> BuildSigninManager(
+std::unique_ptr<PrimaryAccountManager> BuildPrimaryAccountManager(
     ios::ChromeBrowserState* chrome_browser_state,
     AccountTrackerService* account_tracker_service,
     ProfileOAuth2TokenService* token_service) {
-  std::unique_ptr<SigninManager> service = std::make_unique<SigninManager>(
-      SigninClientFactory::GetForBrowserState(chrome_browser_state),
-      token_service, account_tracker_service,
-      signin::AccountConsistencyMethod::kMirror);
+  std::unique_ptr<PrimaryAccountPolicyManager> service =
+      std::make_unique<PrimaryAccountPolicyManager>(
+          SigninClientFactory::GetForBrowserState(chrome_browser_state),
+          token_service, account_tracker_service,
+          signin::AccountConsistencyMethod::kMirror);
   service->Initialize(GetApplicationContext()->GetLocalState());
   return service;
 }
@@ -139,12 +140,13 @@
       token_service.get(),
       SigninClientFactory::GetForBrowserState(browser_state));
 
-  std::unique_ptr<SigninManagerBase> signin_manager = BuildSigninManager(
-      browser_state, account_tracker_service.get(), token_service.get());
+  std::unique_ptr<PrimaryAccountManager> primary_account_manager =
+      BuildPrimaryAccountManager(browser_state, account_tracker_service.get(),
+                                 token_service.get());
 
   auto primary_account_mutator =
       std::make_unique<identity::PrimaryAccountMutatorImpl>(
-          account_tracker_service.get(), signin_manager.get(),
+          account_tracker_service.get(), primary_account_manager.get(),
           browser_state->GetPrefs());
 
   auto accounts_cookie_mutator =
@@ -162,8 +164,9 @@
 
   auto identity_manager = std::make_unique<IdentityManagerWrapper>(
       std::move(account_tracker_service), std::move(token_service),
-      std::move(gaia_cookie_manager_service), std::move(signin_manager),
-      std::move(account_fetcher_service), std::move(primary_account_mutator),
+      std::move(gaia_cookie_manager_service),
+      std::move(primary_account_manager), std::move(account_fetcher_service),
+      std::move(primary_account_mutator),
       /*accounts_mutator=*/nullptr, std::move(accounts_cookie_mutator),
       std::move(diagnostics_provider));
 
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/card_view_controller_egtest.mm b/ios/chrome/browser/ui/autofill/manual_fill/card_view_controller_egtest.mm
index edc8e8a7..16a6dfc 100644
--- a/ios/chrome/browser/ui/autofill/manual_fill/card_view_controller_egtest.mm
+++ b/ios/chrome/browser/ui/autofill/manual_fill/card_view_controller_egtest.mm
@@ -24,7 +24,6 @@
 #import "ios/chrome/test/app/chrome_test_util.h"
 #import "ios/chrome/test/earl_grey/chrome_actions.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
-#import "ios/chrome/test/earl_grey/chrome_error_util.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #import "ios/web/public/test/earl_grey/web_view_matchers.h"
@@ -135,9 +134,8 @@
   [super setUp];
   GREYAssertTrue(self.testServer->Start(), @"Test server failed to start.");
   const GURL URL = self.testServer->GetURL(kFormHTMLFile);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:URL]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:"hello!"]);
+  [ChromeEarlGrey loadURL:URL];
+  [ChromeEarlGrey waitForWebStateContainingText:"hello!"];
 
   _personalDataManager =
       autofill::PersonalDataManagerFactory::GetForBrowserState(
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/fallback_coordinator_egtest.mm b/ios/chrome/browser/ui/autofill/manual_fill/fallback_coordinator_egtest.mm
index 680cabc..ff9b8392b 100644
--- a/ios/chrome/browser/ui/autofill/manual_fill/fallback_coordinator_egtest.mm
+++ b/ios/chrome/browser/ui/autofill/manual_fill/fallback_coordinator_egtest.mm
@@ -26,7 +26,6 @@
 #import "ios/chrome/test/earl_grey/chrome_actions.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
-#import "ios/chrome/test/earl_grey/chrome_error_util.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #import "ios/web/public/test/earl_grey/web_view_matchers.h"
@@ -339,9 +338,8 @@
   _personalDataManager->SetSyncingForTest(true);
   GREYAssertTrue(self.testServer->Start(), @"Test server failed to start.");
   const GURL URL = self.testServer->GetURL(kFormHTMLFile);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:URL]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:"Profile form"]);
+  [ChromeEarlGrey loadURL:URL];
+  [ChromeEarlGrey waitForWebStateContainingText:"Profile form"];
 }
 
 - (void)tearDown {
@@ -606,12 +604,11 @@
       assertWithMatcher:grey_sufficientlyVisible()];
 
   // Open a tab in incognito.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey openNewIncognitoTab]);
+  [ChromeEarlGrey openNewIncognitoTab];
   const GURL URL = self.testServer->GetURL(kFormHTMLFile);
   NSString* omniboxText = base::SysUTF8ToNSString(URL.spec() + "\n");
   [ChromeEarlGreyUI focusOmniboxAndType:omniboxText];
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:"Profile form"]);
+  [ChromeEarlGrey waitForWebStateContainingText:"Profile form"];
 
   // Bring up the keyboard by tapping the city, which is the element before the
   // picker.
@@ -644,10 +641,9 @@
       assertWithMatcher:grey_sufficientlyVisible()];
 
   // Open a tab in incognito.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey openNewIncognitoTab]);
+  [ChromeEarlGrey openNewIncognitoTab];
   [ChromeEarlGreyUI focusOmniboxAndType:omniboxText];
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:webViewText]);
+  [ChromeEarlGrey waitForWebStateContainingText:webViewText];
 
   [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()]
       performAction:chrome_test_util::TapWebElement(kFormElementCity)];
@@ -659,10 +655,9 @@
       assertWithMatcher:grey_sufficientlyVisible()];
 
   [ChromeEarlGrey closeCurrentTab];
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey openNewTab]);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:URL]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:webViewText]);
+  [ChromeEarlGrey openNewTab];
+  [ChromeEarlGrey loadURL:URL];
+  [ChromeEarlGrey waitForWebStateContainingText:webViewText];
 
   // Bring up the keyboard by tapping the city, which is the element before the
   // picker.
@@ -676,10 +671,9 @@
       assertWithMatcher:grey_sufficientlyVisible()];
 
   // Open a tab in incognito.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey openNewIncognitoTab]);
+  [ChromeEarlGrey openNewIncognitoTab];
   [ChromeEarlGreyUI focusOmniboxAndType:omniboxText];
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:webViewText]);
+  [ChromeEarlGrey waitForWebStateContainingText:webViewText];
 
   // Bring up the keyboard by tapping the city, which is the element before the
   // picker.
@@ -687,10 +681,9 @@
       performAction:chrome_test_util::TapWebElement(kFormElementCity)];
 
   // Open a  regular tab.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey openNewTab]);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:URL]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:webViewText]);
+  [ChromeEarlGrey openNewTab];
+  [ChromeEarlGrey loadURL:URL];
+  [ChromeEarlGrey waitForWebStateContainingText:webViewText];
 
   // Bring up the keyboard by tapping the city, which is the element before the
   // picker.
@@ -719,12 +712,11 @@
       assertWithMatcher:grey_sufficientlyVisible()];
 
   // Open a tab in incognito.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey openNewIncognitoTab]);
+  [ChromeEarlGrey openNewIncognitoTab];
   const GURL URL = self.testServer->GetURL(kFormHTMLFile);
   NSString* omniboxText = base::SysUTF8ToNSString(URL.spec() + "\n");
   [ChromeEarlGreyUI focusOmniboxAndType:omniboxText];
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:"Profile form"]);
+  [ChromeEarlGrey waitForWebStateContainingText:"Profile form"];
 
   // Bring up the keyboard by tapping the city, which is the element before the
   // picker.
@@ -732,10 +724,9 @@
       performAction:chrome_test_util::TapWebElement(kFormElementCity)];
 
   // Open a  regular tab.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey openNewTab]);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:URL]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:"Profile form"]);
+  [ChromeEarlGrey openNewTab];
+  [ChromeEarlGrey loadURL:URL];
+  [ChromeEarlGrey waitForWebStateContainingText:"Profile form"];
 
   // Bring up the keyboard by tapping the city, which is the element before the
   // picker.
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/fallback_view_controller_egtest.mm b/ios/chrome/browser/ui/autofill/manual_fill/fallback_view_controller_egtest.mm
index 81e1e08..f51329d 100644
--- a/ios/chrome/browser/ui/autofill/manual_fill/fallback_view_controller_egtest.mm
+++ b/ios/chrome/browser/ui/autofill/manual_fill/fallback_view_controller_egtest.mm
@@ -18,7 +18,6 @@
 #import "ios/chrome/test/earl_grey/chrome_actions.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
-#import "ios/chrome/test/earl_grey/chrome_error_util.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #import "ios/web/public/test/earl_grey/web_view_matchers.h"
@@ -81,9 +80,8 @@
 
   GREYAssertTrue(self.testServer->Start(), @"Test server failed to start.");
   const GURL URL = self.testServer->GetURL(kFormHTMLFile);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:URL]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:"Hello"]);
+  [ChromeEarlGrey loadURL:URL];
+  [ChromeEarlGrey waitForWebStateContainingText:"Hello"];
 }
 
 - (void)tearDown {
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/keyboard_observer_egtest.mm b/ios/chrome/browser/ui/autofill/manual_fill/keyboard_observer_egtest.mm
index 13f49852..c23ac132 100644
--- a/ios/chrome/browser/ui/autofill/manual_fill/keyboard_observer_egtest.mm
+++ b/ios/chrome/browser/ui/autofill/manual_fill/keyboard_observer_egtest.mm
@@ -10,7 +10,6 @@
 #import "ios/chrome/browser/ui/util/keyboard_observer_helper.h"
 #import "ios/chrome/test/app/chrome_test_util.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
-#import "ios/chrome/test/earl_grey/chrome_error_util.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #import "ios/web/public/test/earl_grey/web_view_actions.h"
@@ -93,9 +92,8 @@
   web::test::SetUpFileBasedHttpServer();
   GURL URL = web::test::HttpServer::MakeUrl(
       "http://ios/testing/data/http_server_files/multi_field_form.html");
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:URL]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:"hello!"]);
+  [ChromeEarlGrey loadURL:URL];
+  [ChromeEarlGrey waitForWebStateContainingText:"hello!"];
 
   // Opening the keyboard from a webview blocks EarlGrey's synchronization.
   [[GREYConfiguration sharedInstance]
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/password_view_controller_egtest.mm b/ios/chrome/browser/ui/autofill/manual_fill/password_view_controller_egtest.mm
index 3890fddf..1bafb9a 100644
--- a/ios/chrome/browser/ui/autofill/manual_fill/password_view_controller_egtest.mm
+++ b/ios/chrome/browser/ui/autofill/manual_fill/password_view_controller_egtest.mm
@@ -25,7 +25,6 @@
 #import "ios/chrome/test/app/chrome_test_util.h"
 #import "ios/chrome/test/earl_grey/chrome_actions.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
-#import "ios/chrome/test/earl_grey/chrome_error_util.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #import "ios/web/public/test/earl_grey/web_view_matchers.h"
@@ -239,9 +238,8 @@
   [super setUp];
   GREYAssertTrue(self.testServer->Start(), @"Test server failed to start.");
   const GURL URL = self.testServer->GetURL(kFormHTMLFile);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:URL]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:"hello!"]);
+  [ChromeEarlGrey loadURL:URL];
+  [ChromeEarlGrey waitForWebStateContainingText:"hello!"];
   SaveExamplePasswordForm();
 }
 
@@ -573,9 +571,8 @@
   }
 
   const GURL URL = self.testServer->GetURL(kIFrameHTMLFile);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:URL]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:"iFrame"]);
+  [ChromeEarlGrey loadURL:URL];
+  [ChromeEarlGrey waitForWebStateContainingText:"iFrame"];
   SaveLocalPasswordForm(URL);
 
   // Bring up the keyboard.
diff --git a/ios/chrome/browser/ui/autofill/save_card_infobar_egtest.mm b/ios/chrome/browser/ui/autofill/save_card_infobar_egtest.mm
index 7fe56ca..8a7c063 100644
--- a/ios/chrome/browser/ui/autofill/save_card_infobar_egtest.mm
+++ b/ios/chrome/browser/ui/autofill/save_card_infobar_egtest.mm
@@ -23,7 +23,6 @@
 #import "ios/chrome/browser/ui/autofill/save_card_infobar_controller.h"
 #import "ios/chrome/test/app/chrome_test_util.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
-#import "ios/chrome/test/earl_grey/chrome_error_util.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #include "ios/web/public/js_messaging/web_frame_util.h"
@@ -237,20 +236,17 @@
 #pragma mark - Page interaction helper methods
 
 - (void)fillAndSubmitFormWithCardDetailsOnly {
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey tapWebStateElementWithID:@"fill_card_only"]);
+  [ChromeEarlGrey tapWebStateElementWithID:@"fill_card_only"];
   [self submitForm];
 }
 
 - (void)fillAndSubmitForm {
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey tapWebStateElementWithID:@"fill_form"]);
+  [ChromeEarlGrey tapWebStateElementWithID:@"fill_form"];
   [self submitForm];
 }
 
 - (void)submitForm {
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey tapWebStateElementWithID:@"submit"]);
+  [ChromeEarlGrey tapWebStateElementWithID:@"submit"];
 }
 
 #pragma mark - Helper methods
@@ -289,8 +285,8 @@
 // fallback local save infobar becomes visible if the request unexpectedly fails
 // but the form data is complete.
 - (void)offerLocalSave_FullData_RequestFails {
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey
-      loadURL:web::test::HttpServer::MakeUrl(kCreditCardUploadForm)]);
+  [ChromeEarlGrey
+      loadURL:web::test::HttpServer::MakeUrl(kCreditCardUploadForm)];
 
   // Set up the Google Payments server response.
   test_url_loader_factory_.AddResponse(kURLGetUploadDetailsRequest,
@@ -319,8 +315,8 @@
 // fallback local save infobar becomes visible if the request is declined but
 // the form data is complete.
 - (void)offerLocalSave_FullData_PaymentsDeclines {
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey
-      loadURL:web::test::HttpServer::MakeUrl(kCreditCardUploadForm)]);
+  [ChromeEarlGrey
+      loadURL:web::test::HttpServer::MakeUrl(kCreditCardUploadForm)];
 
   // Set up the Google Payments server response.
   test_url_loader_factory_.AddResponse(kURLGetUploadDetailsRequest,
@@ -348,8 +344,8 @@
 // date, should query Google Payments; but the fallback local save infobar
 // should not appear if the request is declined and the form data is incomplete.
 - (void)testNotOfferLocalSave_PartialData_PaymentsDeclines {
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey
-      loadURL:web::test::HttpServer::MakeUrl(kCreditCardUploadForm)]);
+  [ChromeEarlGrey
+      loadURL:web::test::HttpServer::MakeUrl(kCreditCardUploadForm)];
 
   // Set up the Google Payments server response.
   test_url_loader_factory_.AddResponse(kURLGetUploadDetailsRequest,
@@ -371,8 +367,8 @@
 // Ensures that submitting the form should query Google Payments; and the
 // upstreaming infobar should appear if the request is accepted.
 - (void)offerUpstream_FullData_PaymentsAccepts {
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey
-      loadURL:web::test::HttpServer::MakeUrl(kCreditCardUploadForm)]);
+  [ChromeEarlGrey
+      loadURL:web::test::HttpServer::MakeUrl(kCreditCardUploadForm)];
 
   // Set up the Google Payments server response.
   test_url_loader_factory_.AddResponse(kURLGetUploadDetailsRequest,
@@ -399,8 +395,8 @@
 // date, should query Google Payments and the upstreaming infobar should appear
 // if the request is accepted.
 - (void)offerUpstream_PartialData_PaymentsAccepts {
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey
-      loadURL:web::test::HttpServer::MakeUrl(kCreditCardUploadForm)]);
+  [ChromeEarlGrey
+      loadURL:web::test::HttpServer::MakeUrl(kCreditCardUploadForm)];
 
   // Set up the Google Payments server response.
   test_url_loader_factory_.AddResponse(kURLGetUploadDetailsRequest,
@@ -432,8 +428,8 @@
 
   base::HistogramTester histogram_tester;
 
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey
-      loadURL:web::test::HttpServer::MakeUrl(kCreditCardUploadForm)]);
+  [ChromeEarlGrey
+      loadURL:web::test::HttpServer::MakeUrl(kCreditCardUploadForm)];
 
   // Set up the Google Payments server response.
   test_url_loader_factory_.AddResponse(kURLGetUploadDetailsRequest,
@@ -479,8 +475,8 @@
 
   base::HistogramTester histogram_tester;
 
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey
-      loadURL:web::test::HttpServer::MakeUrl(kCreditCardUploadForm)]);
+  [ChromeEarlGrey
+      loadURL:web::test::HttpServer::MakeUrl(kCreditCardUploadForm)];
 
   // Set up the Google Payments server response.
   test_url_loader_factory_.AddResponse(kURLGetUploadDetailsRequest,
@@ -532,8 +528,8 @@
 // Ensures that the infobar goes away and no credit card is saved to Chrome if
 // the user declines local save.
 - (void)userData_LocalSave_UserDeclines {
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey
-      loadURL:web::test::HttpServer::MakeUrl(kCreditCardUploadForm)]);
+  [ChromeEarlGrey
+      loadURL:web::test::HttpServer::MakeUrl(kCreditCardUploadForm)];
 
   // Set up the Google Payments server response.
   test_url_loader_factory_.AddResponse(kURLGetUploadDetailsRequest,
@@ -572,8 +568,8 @@
 // Ensures that the infobar goes away and the credit card is saved to Chrome if
 // the user accepts local save.
 - (void)testUserData_LocalSave_UserAccepts {
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey
-      loadURL:web::test::HttpServer::MakeUrl(kCreditCardUploadForm)]);
+  [ChromeEarlGrey
+      loadURL:web::test::HttpServer::MakeUrl(kCreditCardUploadForm)];
 
   // Ensure there are no saved credit cards.
   GREYAssertEqual(0U, personal_data_manager_->GetCreditCards().size(),
@@ -616,8 +612,8 @@
 // TODO(crbug.com/925670): remove SetMaxStrikesOnFormFillCard() and incur
 // the maximum number of strikes by showing and declining save infobar instead.
 - (void)testNotOfferLocalSave_MaxStrikesReached {
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey
-      loadURL:web::test::HttpServer::MakeUrl(kCreditCardUploadForm)]);
+  [ChromeEarlGrey
+      loadURL:web::test::HttpServer::MakeUrl(kCreditCardUploadForm)];
 
   // Set up the Google Payments server response.
   test_url_loader_factory_.AddResponse(kURLGetUploadDetailsRequest,
diff --git a/ios/chrome/browser/ui/autofill/save_profile_egtest.mm b/ios/chrome/browser/ui/autofill/save_profile_egtest.mm
index 66d0290..e1053ba 100644
--- a/ios/chrome/browser/ui/autofill/save_profile_egtest.mm
+++ b/ios/chrome/browser/ui/autofill/save_profile_egtest.mm
@@ -12,7 +12,6 @@
 #include "ios/chrome/browser/autofill/personal_data_manager_factory.h"
 #import "ios/chrome/test/app/chrome_test_util.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
-#import "ios/chrome/test/earl_grey/chrome_error_util.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #import "ios/web/public/test/http_server/http_server.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -57,18 +56,15 @@
 #pragma mark - Page interaction helper methods
 
 - (void)fillAndSubmitForm {
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey tapWebStateElementWithID:@"fill_profile_president"]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey tapWebStateElementWithID:@"submit_profile"]);
+  [ChromeEarlGrey tapWebStateElementWithID:@"fill_profile_president"];
+  [ChromeEarlGrey tapWebStateElementWithID:@"submit_profile"];
 }
 
 #pragma mark - Tests
 
 // Ensures that the profile is saved to Chrome after submitting the form.
 - (void)testUserData_LocalSave {
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey loadURL:web::test::HttpServer::MakeUrl(kProfileForm)]);
+  [ChromeEarlGrey loadURL:web::test::HttpServer::MakeUrl(kProfileForm)];
 
   // Ensure there are no saved profiles.
   GREYAssertEqual(0U, personal_data_manager_->GetProfiles().size(),
diff --git a/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm b/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm
index a27d9f3..39f7cb31 100644
--- a/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm
+++ b/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm
@@ -36,7 +36,6 @@
 #import "ios/chrome/test/earl_grey/accessibility_util.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
-#import "ios/chrome/test/earl_grey/chrome_error_util.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #import "ios/public/provider/chrome/browser/signin/fake_chrome_identity.h"
@@ -171,14 +170,14 @@
 - (void)setUp {
   [super setUp];
 
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForBookmarksToFinishLoading]);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey clearBookmarks]);
+  [ChromeEarlGrey waitForBookmarksToFinishLoading];
+  [ChromeEarlGrey clearBookmarks];
 }
 
 // Tear down called once per test.
 - (void)tearDown {
   [super tearDown];
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey clearBookmarks]);
+  [ChromeEarlGrey clearBookmarks];
   // Clear position cache so that Bookmarks starts at the root folder in next
   // test.
   ios::ChromeBrowserState* browser_state =
@@ -197,7 +196,7 @@
   std::string expectedURLContent = bookmarkedURL.GetContent();
   NSString* bookmarkTitle = @"my bookmark";
 
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:bookmarkedURL]);
+  [ChromeEarlGrey loadURL:bookmarkedURL];
   [[EarlGrey selectElementWithMatcher:OmniboxText(expectedURLContent)]
       assertWithMatcher:grey_notNil()];
 
@@ -270,9 +269,9 @@
       "http://ios/testing/data/http_server_files/pony.html");
   const GURL secondURL = web::test::HttpServer::MakeUrl(
       "http://ios/testing/data/http_server_files/destination.html");
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:firstURL]);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey openNewTab]);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:secondURL]);
+  [ChromeEarlGrey loadURL:firstURL];
+  [ChromeEarlGrey openNewTab];
+  [ChromeEarlGrey loadURL:secondURL];
 
   [BookmarksTestCase bookmarkCurrentTabWithTitle:@"my bookmark"];
   [BookmarksTestCase assertBookmarksWithTitle:@"my bookmark" expectedCount:1];
@@ -914,7 +913,7 @@
 // Tests that chrome://bookmarks is disabled.
 - (void)testBookmarksURLDisabled {
   const std::string kChromeBookmarksURL = "chrome://bookmarks";
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:GURL(kChromeBookmarksURL)]);
+  [ChromeEarlGrey loadURL:GURL(kChromeBookmarksURL)];
 
   // Verify chrome://bookmarks appears in the omnibox.
   [[EarlGrey selectElementWithMatcher:OmniboxText(kChromeBookmarksURL)]
@@ -922,8 +921,7 @@
 
   // Verify that the resulting page is an error page.
   std::string errorMessage = net::ErrorToShortString(net::ERR_INVALID_URL);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:errorMessage]);
+  [ChromeEarlGrey waitForWebStateContainingText:errorMessage];
 }
 
 #pragma mark - Helpers
@@ -1719,14 +1717,14 @@
 - (void)setUp {
   [super setUp];
 
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForBookmarksToFinishLoading]);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey clearBookmarks]);
+  [ChromeEarlGrey waitForBookmarksToFinishLoading];
+  [ChromeEarlGrey clearBookmarks];
 }
 
 // Tear down called once per test.
 - (void)tearDown {
   [super tearDown];
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey clearBookmarks]);
+  [ChromeEarlGrey clearBookmarks];
   // Clear position cache so that Bookmarks starts at the root folder in next
   // test.
   ios::ChromeBrowserState* browser_state =
@@ -2111,7 +2109,7 @@
                          IDS_IOS_BOOKMARK_CONTEXT_MENU_OPEN];
 
   // Verify there are 3 normal tabs.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForMainTabCount:3]);
+  [ChromeEarlGrey waitForMainTabCount:3];
   GREYAssertTrue([ChromeEarlGrey incognitoTabCount] == 0,
                  @"Incognito tab count should be 0");
 
@@ -2119,7 +2117,7 @@
   [BookmarksTestCase verifyOrderOfTabsWithCurrentTabIndex:0];
 
   // Switch to Incognito mode by adding a new incognito tab.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey openNewIncognitoTab]);
+  [ChromeEarlGrey openNewIncognitoTab];
 
   [BookmarksTestCase openBookmarks];
 
@@ -2128,12 +2126,12 @@
                          IDS_IOS_BOOKMARK_CONTEXT_MENU_OPEN];
 
   // Verify there are 6 normal tabs and no new incognito tabs.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForMainTabCount:6]);
+  [ChromeEarlGrey waitForMainTabCount:6];
   GREYAssertTrue([ChromeEarlGrey incognitoTabCount] == 1,
                  @"Incognito tab count should be 1");
 
   // Close the incognito tab to go back to normal mode.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey closeAllIncognitoTabs]);
+  [ChromeEarlGrey closeAllIncognitoTabs];
 
   // The following verifies the selected bookmarks are open in the same order as
   // in folder.
@@ -2154,7 +2152,7 @@
                          IDS_IOS_BOOKMARK_CONTEXT_MENU_OPEN_INCOGNITO];
 
   // Verify there are 3 incognito tabs and no new normal tab.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForIncognitoTabCount:3]);
+  [ChromeEarlGrey waitForIncognitoTabCount:3];
   GREYAssertTrue([ChromeEarlGrey mainTabCount] == 1,
                  @"Main tab count should be 1");
 
@@ -2175,7 +2173,7 @@
   // there will be 2 new tabs only.
 
   // Verify there are 5 incognito tabs and no new normal tab.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForIncognitoTabCount:5]);
+  [ChromeEarlGrey waitForIncognitoTabCount:5];
   GREYAssertTrue([ChromeEarlGrey mainTabCount] == 1,
                  @"Main tab count should be 1");
 
@@ -2208,7 +2206,7 @@
       performAction:grey_tap()];
 
   // Verify there is 1 new normal tab created and no new incognito tab created.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForMainTabCount:2]);
+  [ChromeEarlGrey waitForMainTabCount:2];
   GREYAssertTrue([ChromeEarlGrey incognitoTabCount] == 0,
                  @"Incognito tab count should be 0");
 
@@ -2228,7 +2226,7 @@
       performAction:grey_tap()];
 
   // Verify there is 1 incognito tab created and no new normal tab created.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForIncognitoTabCount:1]);
+  [ChromeEarlGrey waitForIncognitoTabCount:1];
   GREYAssertTrue([ChromeEarlGrey mainTabCount] == 2,
                  @"Main tab count should be 2");
 
@@ -2272,7 +2270,7 @@
       performAction:grey_tap()];
 
   // Verify a new incognito tab is created.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForIncognitoTabCount:2]);
+  [ChromeEarlGrey waitForIncognitoTabCount:2];
   GREYAssertTrue([ChromeEarlGrey mainTabCount] == 2,
                  @"Main tab count should be 2");
 
@@ -2296,7 +2294,7 @@
       performAction:grey_tap()];
 
   // Verify a new normal tab is created and no incognito tab is created.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForMainTabCount:3]);
+  [ChromeEarlGrey waitForMainTabCount:3];
   GREYAssertTrue([ChromeEarlGrey incognitoTabCount] == 2,
                  @"Incognito tab count should be 2");
 
@@ -2710,14 +2708,14 @@
 - (void)setUp {
   [super setUp];
 
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForBookmarksToFinishLoading]);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey clearBookmarks]);
+  [ChromeEarlGrey waitForBookmarksToFinishLoading];
+  [ChromeEarlGrey clearBookmarks];
 }
 
 // Tear down called once per test.
 - (void)tearDown {
   [super tearDown];
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey clearBookmarks]);
+  [ChromeEarlGrey clearBookmarks];
   // Clear position cache so that Bookmarks starts at the root folder in next
   // test.
   ios::ChromeBrowserState* browser_state =
@@ -2943,14 +2941,14 @@
 - (void)setUp {
   [super setUp];
 
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForBookmarksToFinishLoading]);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey clearBookmarks]);
+  [ChromeEarlGrey waitForBookmarksToFinishLoading];
+  [ChromeEarlGrey clearBookmarks];
 }
 
 // Tear down called once per test.
 - (void)tearDown {
   [super tearDown];
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey clearBookmarks]);
+  [ChromeEarlGrey clearBookmarks];
 
   // Clear position cache so that Bookmarks starts at the root folder in next
   // test.
@@ -3118,14 +3116,14 @@
 - (void)setUp {
   [super setUp];
 
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForBookmarksToFinishLoading]);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey clearBookmarks]);
+  [ChromeEarlGrey waitForBookmarksToFinishLoading];
+  [ChromeEarlGrey clearBookmarks];
 }
 
 // Tear down called once per test.
 - (void)tearDown {
   [super tearDown];
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey clearBookmarks]);
+  [ChromeEarlGrey clearBookmarks];
   // Clear position cache so that Bookmarks starts at the root folder in next
   // test.
   ios::ChromeBrowserState* browser_state =
@@ -3878,7 +3876,7 @@
                                 expectedCount:0];
   // Open the page.
   std::string expectedURLContent = bookmarkedURL.GetContent();
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:bookmarkedURL]);
+  [ChromeEarlGrey loadURL:bookmarkedURL];
   [[EarlGrey selectElementWithMatcher:OmniboxText(expectedURLContent)]
       assertWithMatcher:grey_notNil()];
 
@@ -4003,7 +4001,7 @@
       "http://ios/testing/data/http_server_files/pony.html");
   std::string expectedURLContent = bookmarkedURL.GetContent();
 
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:bookmarkedURL]);
+  [ChromeEarlGrey loadURL:bookmarkedURL];
   [[EarlGrey selectElementWithMatcher:OmniboxText(expectedURLContent)]
       assertWithMatcher:grey_notNil()];
 
@@ -4057,14 +4055,14 @@
 - (void)setUp {
   [super setUp];
 
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForBookmarksToFinishLoading]);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey clearBookmarks]);
+  [ChromeEarlGrey waitForBookmarksToFinishLoading];
+  [ChromeEarlGrey clearBookmarks];
 }
 
 // Tear down called once per test.
 - (void)tearDown {
   [super tearDown];
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey clearBookmarks]);
+  [ChromeEarlGrey clearBookmarks];
   // Clear position cache so that Bookmarks starts at the root folder in next
   // test.
   ios::ChromeBrowserState* browser_state =
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller_egtest.mm b/ios/chrome/browser/ui/browser_view/browser_view_controller_egtest.mm
index 2a2a718d..37e84dd1 100644
--- a/ios/chrome/browser/ui/browser_view/browser_view_controller_egtest.mm
+++ b/ios/chrome/browser/ui/browser_view/browser_view_controller_egtest.mm
@@ -19,7 +19,6 @@
 #import "ios/chrome/test/app/tab_test_util.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
-#import "ios/chrome/test/earl_grey/chrome_error_util.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #include "ios/web/public/test/http_server/html_response_provider.h"
@@ -56,11 +55,10 @@
   web::test::SetUpSimpleHttpServer(responses);
 
   // Just load the first URL.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:startURL]);
+  [ChromeEarlGrey loadURL:startURL];
 
   // Waits for the page to load and check it is the expected content.
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:responses[startURL]]);
+  [ChromeEarlGrey waitForWebStateContainingText:responses[startURL]];
 
   // In the omnibox, the URL should be present, without the http:// prefix.
   [[EarlGrey selectElementWithMatcher:chrome_test_util::Omnibox()]
@@ -83,8 +81,7 @@
                   @"Did not navigate to the destination url.");
 
   // Verifies that the destination page is shown.
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:responses[destinationURL]]);
+  [ChromeEarlGrey waitForWebStateContainingText:responses[destinationURL]];
 }
 
 // Tests the fix for the regression reported in https://crbug.com/801165.  The
@@ -100,13 +97,12 @@
   web::test::SetUpSimpleHttpServer(responses);
 
   // Load the test page.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:testURL]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:"File Picker Test"]);
+  [ChromeEarlGrey loadURL:testURL];
+  [ChromeEarlGrey waitForWebStateContainingText:"File Picker Test"];
 
   // Invoke the file picker and tap on the "Cancel" button to dismiss the file
   // picker.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey tapWebStateElementWithID:@"file"]);
+  [ChromeEarlGrey tapWebStateElementWithID:@"file"];
   [[EarlGrey selectElementWithMatcher:chrome_test_util::CancelButton()]
       performAction:grey_tap()];
   [[GREYUIThreadExecutor sharedInstance] drainUntilIdle];
@@ -130,13 +126,13 @@
   int mainTabCount = 1;
   if (base::FeatureList::IsEnabled(kBlockNewTabPagePendingLoad))
     mainTabCount = 2;
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForMainTabCount:mainTabCount]);
+  [ChromeEarlGrey waitForMainTabCount:mainTabCount];
 }
 
 // Tests that BVC properly handles open URL. When BVC is showing a non-NTP
 // tab, the URL should be opened in a new tab, adding to the tab count.
 - (void)testOpenURLFromTab {
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:GURL("https://invalid")]);
+  [ChromeEarlGrey loadURL:GURL("https://invalid")];
   id<UIApplicationDelegate> appDelegate =
       [[UIApplication sharedApplication] delegate];
   [appDelegate application:[UIApplication sharedApplication]
@@ -145,14 +141,14 @@
   [[EarlGrey selectElementWithMatcher:chrome_test_util::OmniboxText(
                                           "https://anything")]
       assertWithMatcher:grey_notNil()];
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForMainTabCount:2]);
+  [ChromeEarlGrey waitForMainTabCount:2];
 }
 
 // Tests that BVC properly handles open URL. When tab switcher is showing,
 // the URL should be opened in a new tab, and BVC should be shown.
 - (void)testOpenURLFromTabSwitcher {
   [ChromeEarlGrey closeCurrentTab];
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForMainTabCount:0]);
+  [ChromeEarlGrey waitForMainTabCount:0];
   id<UIApplicationDelegate> appDelegate =
       [[UIApplication sharedApplication] delegate];
   [appDelegate application:[UIApplication sharedApplication]
@@ -161,7 +157,7 @@
   [[EarlGrey selectElementWithMatcher:chrome_test_util::OmniboxText(
                                           "https://anything")]
       assertWithMatcher:grey_notNil()];
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForMainTabCount:1]);
+  [ChromeEarlGrey waitForMainTabCount:1];
 }
 
 #pragma mark - WebState visibility
@@ -177,16 +173,14 @@
   web::test::SetUpSimpleHttpServer(responses);
 
   // Load the test page.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:testURL]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:testPageContents]);
+  [ChromeEarlGrey loadURL:testURL];
+  [ChromeEarlGrey waitForWebStateContainingText:testPageContents];
   web::WebState* firstWebState = chrome_test_util::GetCurrentTab().webState;
 
   // And do the same in a second tab.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey openNewTab]);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:testURL]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:testPageContents]);
+  [ChromeEarlGrey openNewTab];
+  [ChromeEarlGrey loadURL:testURL];
+  [ChromeEarlGrey waitForWebStateContainingText:testPageContents];
   web::WebState* secondWebState = chrome_test_util::GetCurrentTab().webState;
 
   // Check visibility before and after switching tabs.
diff --git a/ios/chrome/browser/ui/dialogs/javascript_dialog_egtest.mm b/ios/chrome/browser/ui/dialogs/javascript_dialog_egtest.mm
index 6c45942..1390a2c 100644
--- a/ios/chrome/browser/ui/dialogs/javascript_dialog_egtest.mm
+++ b/ios/chrome/browser/ui/dialogs/javascript_dialog_egtest.mm
@@ -20,7 +20,6 @@
 #import "ios/chrome/test/earl_grey/chrome_actions.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
-#import "ios/chrome/test/earl_grey/chrome_error_util.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #include "ios/testing/earl_grey/disabled_test_macros.h"
@@ -389,15 +388,13 @@
 #pragma mark - Utility
 
 - (void)loadBlankTestPage {
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:self.emptyPageURL]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:std::string()]);
+  [ChromeEarlGrey loadURL:self.emptyPageURL];
+  [ChromeEarlGrey waitForWebStateContainingText:std::string()];
 }
 
 - (void)loadPageWithLink {
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:self.linkPageURL]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kLinkPageLinkText]);
+  [ChromeEarlGrey loadURL:self.linkPageURL];
+  [ChromeEarlGrey waitForWebStateContainingText:kLinkPageLinkText];
 }
 
 #pragma mark - Tests
@@ -411,8 +408,7 @@
   [[EarlGrey selectElementWithMatcher:OKButton()] performAction:grey_tap()];
 
   // Wait for the html body to be reset to the correct value.
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kAlertResultBody]);
+  [ChromeEarlGrey waitForWebStateContainingText:kAlertResultBody];
 }
 
 // Tests that a confirmation dialog is shown, and that the completion block is
@@ -425,8 +421,7 @@
   [[EarlGrey selectElementWithMatcher:OKButton()] performAction:grey_tap()];
 
   // Wait for the html body to be reset to the correct value.
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kConfirmationResultBodyOK]);
+  [ChromeEarlGrey waitForWebStateContainingText:kConfirmationResultBodyOK];
 }
 
 // Tests that a confirmation dialog is shown, and that the completion block is
@@ -440,8 +435,8 @@
   TapCancel();
 
   // Wait for the html body to be reset to the correct value.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey
-      waitForWebStateContainingText:kConfirmationResultBodyCancelled]);
+  [ChromeEarlGrey
+      waitForWebStateContainingText:kConfirmationResultBodyCancelled];
 }
 
 // Tests that a prompt dialog is shown, and that the completion block is called
@@ -463,8 +458,7 @@
   [[EarlGrey selectElementWithMatcher:OKButton()] performAction:grey_tap()];
 
   // Wait for the html body to be reset to the input text.
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kPromptTestUserInput]);
+  [ChromeEarlGrey waitForWebStateContainingText:kPromptTestUserInput];
 }
 
 // Tests that a prompt dialog is shown, and that the completion block is called
@@ -487,8 +481,7 @@
   TapCancel();
 
   // Wait for the html body to be reset to the cancel text.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey
-      waitForWebStateContainingText:kPromptResultBodyCancelled]);
+  [ChromeEarlGrey waitForWebStateContainingText:kPromptResultBodyCancelled];
 }
 
 // Tests that JavaScript alerts that are shown in a loop can be suppressed.
@@ -515,8 +508,7 @@
   TapSuppressDialogsButton();
 
   // Wait for the html body to be reset to the loop finished text.
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kAlertLoopFinishedText]);
+  [ChromeEarlGrey waitForWebStateContainingText:kAlertLoopFinishedText];
 }
 
 // Tests to ensure crbug.com/658260 does not regress.
@@ -553,8 +545,7 @@
   [[EarlGrey selectElementWithMatcher:OKButton()] performAction:grey_tap()];
 
   // Wait for the html body to be reset to the correct value.
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kAlertResultBody]);
+  [ChromeEarlGrey waitForWebStateContainingText:kAlertResultBody];
 }
 
 // Tests that an alert is presented after displaying the share menu.
@@ -580,8 +571,7 @@
   [[EarlGrey selectElementWithMatcher:OKButton()] performAction:grey_tap()];
 
   // Wait for the html body to be reset to the correct value.
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kAlertResultBody]);
+  [ChromeEarlGrey waitForWebStateContainingText:kAlertResultBody];
 }
 
 // Tests that an alert is presented after a new tab animation is finished.
diff --git a/ios/chrome/browser/ui/download/ar_quick_look_egtest.mm b/ios/chrome/browser/ui/download/ar_quick_look_egtest.mm
index f1961c2..16efc9f 100644
--- a/ios/chrome/browser/ui/download/ar_quick_look_egtest.mm
+++ b/ios/chrome/browser/ui/download/ar_quick_look_egtest.mm
@@ -17,7 +17,6 @@
 #include "ios/chrome/browser/ui/util/ui_util.h"
 #import "ios/chrome/test/app/chrome_test_util.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
-#import "ios/chrome/test/earl_grey/chrome_error_util.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #include "net/http/http_status_code.h"
 #include "net/test/embedded_test_server/http_request.h"
@@ -89,11 +88,9 @@
          "below 12 because QLPreviewController is not available.");
   }
 
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey loadURL:self.testServer->GetURL("/")]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:"Good"]);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey tapWebStateElementWithID:@"good"]);
+  [ChromeEarlGrey loadURL:self.testServer->GetURL("/")];
+  [ChromeEarlGrey waitForWebStateContainingText:"Good"];
+  [ChromeEarlGrey tapWebStateElementWithID:@"good"];
 
   // QLPreviewController UI is rendered out of host process so EarlGrey matcher
   // can not find QLPreviewController UI. Instead this test relies on view
@@ -116,12 +113,9 @@
          "below 12 because QLPreviewController is not available.");
   }
 
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey loadURL:self.testServer->GetURL("/")]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:"Unauthorized"]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey tapWebStateElementWithID:@"unauthorized"]);
+  [ChromeEarlGrey loadURL:self.testServer->GetURL("/")];
+  [ChromeEarlGrey waitForWebStateContainingText:"Unauthorized"];
+  [ChromeEarlGrey tapWebStateElementWithID:@"unauthorized"];
 
   // QLPreviewController UI is rendered out of host process so EarlGrey matcher
   // can not find QLPreviewController UI. Instead this test relies on view
@@ -144,12 +138,9 @@
          "below 12 because QLPreviewController is not available.");
   }
 
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey loadURL:self.testServer->GetURL("/")]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:"Forbidden"]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey tapWebStateElementWithID:@"forbidden"]);
+  [ChromeEarlGrey loadURL:self.testServer->GetURL("/")];
+  [ChromeEarlGrey waitForWebStateContainingText:"Forbidden"];
+  [ChromeEarlGrey tapWebStateElementWithID:@"forbidden"];
 
   // QLPreviewController UI is rendered out of host process so EarlGrey matcher
   // can not find QLPreviewController UI. Instead this test relies on view
@@ -172,12 +163,9 @@
          "below 12 because QLPreviewController is not available.");
   }
 
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey loadURL:self.testServer->GetURL("/")]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:"Changing Mime Type"]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey tapWebStateElementWithID:@"changing-mime-type"]);
+  [ChromeEarlGrey loadURL:self.testServer->GetURL("/")];
+  [ChromeEarlGrey waitForWebStateContainingText:"Changing Mime Type"];
+  [ChromeEarlGrey tapWebStateElementWithID:@"changing-mime-type"];
 
   // QLPreviewController UI is rendered out of host process so EarlGrey matcher
   // can not find QLPreviewController UI. Instead this test relies on view
diff --git a/ios/chrome/browser/ui/download/download_manager_egtest.mm b/ios/chrome/browser/ui/download/download_manager_egtest.mm
index 797183d..a71aab73a 100644
--- a/ios/chrome/browser/ui/download/download_manager_egtest.mm
+++ b/ios/chrome/browser/ui/download/download_manager_egtest.mm
@@ -13,7 +13,6 @@
 #import "ios/chrome/test/earl_grey/chrome_actions.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
-#import "ios/chrome/test/earl_grey/chrome_error_util.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #import "ios/chrome/test/scoped_eg_synchronization_disabler.h"
@@ -107,12 +106,9 @@
 // presented. EarlGrey does not allow testing "Open in..." dialog, because it
 // is run in a separate process.
 - (void)testSucessfullDownload {
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey loadURL:self.testServer->GetURL("/")]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:"Download"]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey tapWebStateElementWithID:@"download"]);
+  [ChromeEarlGrey loadURL:self.testServer->GetURL("/")];
+  [ChromeEarlGrey waitForWebStateContainingText:"Download"];
+  [ChromeEarlGrey tapWebStateElementWithID:@"download"];
 
   GREYAssert(WaitForDownloadButton(), @"Download button did not show up");
   [[EarlGrey selectElementWithMatcher:DownloadButton()]
@@ -125,13 +121,10 @@
 // presented. EarlGrey does not allow testing "Open in..." dialog, because it
 // is run in a separate process. Performs download in Incognito.
 - (void)testSucessfullDownloadInIncognito {
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey openNewIncognitoTab]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey loadURL:self.testServer->GetURL("/")]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:"Download"]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey tapWebStateElementWithID:@"download"]);
+  [ChromeEarlGrey openNewIncognitoTab];
+  [ChromeEarlGrey loadURL:self.testServer->GetURL("/")];
+  [ChromeEarlGrey waitForWebStateContainingText:"Download"];
+  [ChromeEarlGrey tapWebStateElementWithID:@"download"];
 
   GREYAssert(WaitForDownloadButton(), @"Download button did not show up");
   [[EarlGrey selectElementWithMatcher:DownloadButton()]
@@ -142,12 +135,9 @@
 
 // Tests cancelling download UI.
 - (void)testCancellingDownload {
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey loadURL:self.testServer->GetURL("/")]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:"Download"]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey tapWebStateElementWithID:@"download"]);
+  [ChromeEarlGrey loadURL:self.testServer->GetURL("/")];
+  [ChromeEarlGrey waitForWebStateContainingText:"Download"];
+  [ChromeEarlGrey tapWebStateElementWithID:@"download"];
 
   GREYAssert(WaitForDownloadButton(), @"Download button did not show up");
   [[EarlGrey selectElementWithMatcher:DownloadButton()]
@@ -166,12 +156,9 @@
 // separate tabs and loads the URL there. Then closes the tab and waits for
 // the download completion.
 - (void)testDownloadWhileBrowsing {
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey loadURL:self.testServer->GetURL("/")]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:"Download"]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey tapWebStateElementWithID:@"download"]);
+  [ChromeEarlGrey loadURL:self.testServer->GetURL("/")];
+  [ChromeEarlGrey waitForWebStateContainingText:"Download"];
+  [ChromeEarlGrey tapWebStateElementWithID:@"download"];
 
   GREYAssert(WaitForDownloadButton(), @"Download button did not show up");
   [[EarlGrey selectElementWithMatcher:DownloadButton()]
@@ -182,24 +169,21 @@
     // does not wait until the download progress bar becomes idle (which will
     // not happen until the download is complete).
     ScopedSynchronizationDisabler disabler;
-    CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey openNewTab]);
+    [ChromeEarlGrey openNewTab];
   }
 
   // Load a URL in a separate Tab and close that tab.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:GURL(kChromeUITermsURL)]);
+  [ChromeEarlGrey loadURL:GURL(kChromeUITermsURL)];
   const char kTermsText[] = "Google Chrome Terms of Service";
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kTermsText]);
+  [ChromeEarlGrey waitForWebStateContainingText:kTermsText];
   [ChromeEarlGrey closeCurrentTab];
   GREYAssert(WaitForOpenInButton(), @"Open in... button did not show up");
 }
 
 // Tests "Open in New Tab" on download link.
 - (void)testDownloadInNewTab {
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey loadURL:self.testServer->GetURL("/")]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:"Download"]);
+  [ChromeEarlGrey loadURL:self.testServer->GetURL("/")];
+  [ChromeEarlGrey waitForWebStateContainingText:"Download"];
 
   // Open context menu for download link.
   [[EarlGrey selectElementWithMatcher:WebViewInWebState(GetCurrentWebState())]
@@ -214,7 +198,7 @@
       performAction:grey_tap()];
 
   // Wait until the new tab is open and switch to that tab.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForMainTabCount:2]);
+  [ChromeEarlGrey waitForMainTabCount:2];
   [ChromeEarlGrey selectTabAtIndex:1U];
   GREYAssert(WaitForDownloadButton(), @"Download button did not show up");
 
@@ -226,12 +210,9 @@
 
 // Tests accessibility on Download Manager UI when download is not started.
 - (void)testAccessibilityOnNotStartedDownloadToolbar {
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey loadURL:self.testServer->GetURL("/")]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:"Download"]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey tapWebStateElementWithID:@"download"]);
+  [ChromeEarlGrey loadURL:self.testServer->GetURL("/")];
+  [ChromeEarlGrey waitForWebStateContainingText:"Download"];
+  [ChromeEarlGrey tapWebStateElementWithID:@"download"];
 
   GREYAssert(WaitForDownloadButton(), @"Download button did not show up");
   [[EarlGrey selectElementWithMatcher:DownloadButton()]
@@ -242,12 +223,9 @@
 
 // Tests accessibility on Download Manager UI when download is complete.
 - (void)testAccessibilityOnCompletedDownloadToolbar {
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey loadURL:self.testServer->GetURL("/")]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:"Download"]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey tapWebStateElementWithID:@"download"]);
+  [ChromeEarlGrey loadURL:self.testServer->GetURL("/")];
+  [ChromeEarlGrey waitForWebStateContainingText:"Download"];
+  [ChromeEarlGrey tapWebStateElementWithID:@"download"];
 
   GREYAssert(WaitForDownloadButton(), @"Download button did not show up");
   [[EarlGrey selectElementWithMatcher:DownloadButton()]
diff --git a/ios/chrome/browser/ui/download/pass_kit_egtest.mm b/ios/chrome/browser/ui/download/pass_kit_egtest.mm
index fc0333f..04c0543 100644
--- a/ios/chrome/browser/ui/download/pass_kit_egtest.mm
+++ b/ios/chrome/browser/ui/download/pass_kit_egtest.mm
@@ -17,7 +17,6 @@
 #include "ios/chrome/grit/ios_strings.h"
 #import "ios/chrome/test/app/chrome_test_util.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
-#import "ios/chrome/test/earl_grey/chrome_error_util.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #include "net/test/embedded_test_server/http_request.h"
 #include "net/test/embedded_test_server/http_response.h"
@@ -79,11 +78,9 @@
 // Tests that Chrome presents PassKit error infobar if pkpass file cannot be
 // parsed.
 - (void)testPassKitParsingError {
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey loadURL:self.testServer->GetURL("/")]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:"Bad"]);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey tapWebStateElementWithID:@"bad"]);
+  [ChromeEarlGrey loadURL:self.testServer->GetURL("/")];
+  [ChromeEarlGrey waitForWebStateContainingText:"Bad"];
+  [ChromeEarlGrey tapWebStateElementWithID:@"bad"];
 
   bool infobarShown = WaitUntilConditionOrTimeout(kWaitForDownloadTimeout, ^{
     NSError* error = nil;
@@ -102,11 +99,9 @@
     EARL_GREY_TEST_SKIPPED(@"Wallet app is not supported on iPads.");
   }
 
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey loadURL:self.testServer->GetURL("/")]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:"Good"]);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey tapWebStateElementWithID:@"good"]);
+  [ChromeEarlGrey loadURL:self.testServer->GetURL("/")];
+  [ChromeEarlGrey waitForWebStateContainingText:"Good"];
+  [ChromeEarlGrey tapWebStateElementWithID:@"good"];
 
   // PKAddPassesViewController UI is rendered out of host process so EarlGrey
   // matcher can not find PassKit Dialog UI. Instead this test relies on view
diff --git a/ios/chrome/browser/ui/find_bar/find_in_page_egtest.mm b/ios/chrome/browser/ui/find_bar/find_in_page_egtest.mm
index e6e6f7b..0a1f493 100644
--- a/ios/chrome/browser/ui/find_bar/find_in_page_egtest.mm
+++ b/ios/chrome/browser/ui/find_bar/find_in_page_egtest.mm
@@ -15,7 +15,6 @@
 #import "ios/chrome/test/earl_grey/accessibility_util.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
-#import "ios/chrome/test/earl_grey/chrome_error_util.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #import "ios/web/public/test/http_server/http_server.h"
@@ -222,11 +221,10 @@
 
 - (void)navigateToTestPage {
   // Navigate to a page with some text.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:self.testURL]);
+  [ChromeEarlGrey loadURL:self.testURL];
 
   // Verify web page finished loading.
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kFindInPageResponse]);
+  [ChromeEarlGrey waitForWebStateContainingText:kFindInPageResponse];
 }
 
 @end
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_egtest.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_egtest.mm
index 5a5d665..28dc5a0d 100644
--- a/ios/chrome/browser/ui/fullscreen/fullscreen_egtest.mm
+++ b/ios/chrome/browser/ui/fullscreen/fullscreen_egtest.mm
@@ -17,7 +17,6 @@
 #import "ios/chrome/test/app/chrome_test_util.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
-#import "ios/chrome/test/earl_grey/chrome_error_util.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #import "ios/web/common/features.h"
@@ -90,7 +89,7 @@
   web::test::SetUpFileBasedHttpServer();
   GURL URL = web::test::HttpServer::MakeUrl(
       "http://ios/testing/data/http_server_files/two_pages.pdf");
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:URL]);
+  [ChromeEarlGrey loadURL:URL];
 
   [ChromeEarlGreyUI waitForToolbarVisible:YES];
 
@@ -118,7 +117,7 @@
   web::test::SetUpFileBasedHttpServer();
   GURL URL = web::test::HttpServer::MakeUrl(
       "http://ios/testing/data/http_server_files/single_page_wide.pdf");
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:URL]);
+  [ChromeEarlGrey loadURL:URL];
 
   // TODO(crbug.com/852393): Investigate why synchronization isn't working.  Is
   // an animation going on forever?
@@ -163,7 +162,7 @@
   web::test::SetUpFileBasedHttpServer();
   GURL URL = web::test::HttpServer::MakeUrl(
       "http://ios/testing/data/http_server_files/two_pages.pdf");
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:URL]);
+  [ChromeEarlGrey loadURL:URL];
 
   // Test that the toolbar is hidden after a user swipes up.
   HideToolbarUsingUI();
@@ -185,9 +184,8 @@
 // header being shown even if was not previously shown.
 - (void)testChromeToChromeURLKeepsHeaderOnScreen {
   const GURL kChromeAboutURL("chrome://chrome-urls");
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:kChromeAboutURL]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:"chrome://version"]);
+  [ChromeEarlGrey loadURL:kChromeAboutURL];
+  [ChromeEarlGrey waitForWebStateContainingText:"chrome://version"];
 
   // Hide the toolbar. The page is not long enough to dismiss the toolbar using
   // the UI so we have to zoom in.
@@ -227,8 +225,7 @@
 
   // Test that the toolbar is visible when moving from one chrome:// link to
   // another chrome:// link.
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey tapWebStateElementWithID:@"version"]);
+  [ChromeEarlGrey tapWebStateElementWithID:@"version"];
   [ChromeEarlGreyUI waitForToolbarVisible:YES];
 }
 
@@ -241,7 +238,7 @@
       base::StringPrintf("<p style='height:%dem'>a</p><p>b</p>", kPageHeightEM);
   web::test::SetUpSimpleHttpServer(responses);
 
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:URL]);
+  [ChromeEarlGrey loadURL:URL];
   [ChromeEarlGreyUI waitForToolbarVisible:YES];
   // Simulate a user scroll down.
   HideToolbarUsingUI();
@@ -267,14 +264,13 @@
       kPageHeightEM);
   web::test::SetUpSimpleHttpServer(responses);
 
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:URL]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:"Tall page"]);
+  [ChromeEarlGrey loadURL:URL];
+  [ChromeEarlGrey waitForWebStateContainingText:"Tall page"];
 
   // Hide the toolbar.
   HideToolbarUsingUI();
   [ChromeEarlGreyUI waitForToolbarVisible:NO];
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey tapWebStateElementWithID:@"link"]);
+  [ChromeEarlGrey tapWebStateElementWithID:@"link"];
   // Main test is here: Make sure the header is still visible!
   [ChromeEarlGreyUI waitForToolbarVisible:YES];
 }
@@ -304,25 +300,22 @@
       kPageHeightEM, javaScript.c_str());
 
   web::test::SetUpSimpleHttpServer(responses);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey setContentSettings:CONTENT_SETTING_ALLOW]);
+  [ChromeEarlGrey setContentSettings:CONTENT_SETTING_ALLOW];
 
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:URL]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:"link1"]);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForMainTabCount:1]);
+  [ChromeEarlGrey loadURL:URL];
+  [ChromeEarlGrey waitForWebStateContainingText:"link1"];
+  [ChromeEarlGrey waitForMainTabCount:1];
 
   // Hide the toolbar.
   HideToolbarUsingUI();
   [ChromeEarlGreyUI waitForToolbarVisible:NO];
 
   // Open new window.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey tapWebStateElementWithID:@"link1"]);
+  [ChromeEarlGrey tapWebStateElementWithID:@"link1"];
 
   // Check that a new Tab was created.
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:"link2"]);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForMainTabCount:2]);
+  [ChromeEarlGrey waitForWebStateContainingText:"link2"];
+  [ChromeEarlGrey waitForMainTabCount:2];
 
   AssertURLIs(destinationURL);
 
@@ -344,11 +337,10 @@
                @"Failed to receive WKErrorDomain error");
   }
 
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:"link1"]);
+  [ChromeEarlGrey waitForWebStateContainingText:"link1"];
 
   // Make sure the toolbar is on the screen.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForMainTabCount:1]);
+  [ChromeEarlGrey waitForMainTabCount:1];
   [ChromeEarlGreyUI waitForToolbarVisible:YES];
 }
 
@@ -374,18 +366,16 @@
                               "id='link2'>link2</a>";
   web::test::SetUpSimpleHttpServer(responses);
 
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:originURL]);
+  [ChromeEarlGrey loadURL:originURL];
 
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:"link1"]);
+  [ChromeEarlGrey waitForWebStateContainingText:"link1"];
   // Dismiss the toolbar.
   HideToolbarUsingUI();
   [ChromeEarlGreyUI waitForToolbarVisible:NO];
 
   // Navigate to the other page.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey tapWebStateElementWithID:@"link1"]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:"link2"]);
+  [ChromeEarlGrey tapWebStateElementWithID:@"link1"];
+  [ChromeEarlGrey waitForWebStateContainingText:"link2"];
 
   // Make sure toolbar is shown since a new load has started.
   [ChromeEarlGreyUI waitForToolbarVisible:YES];
@@ -395,7 +385,7 @@
   [ChromeEarlGreyUI waitForToolbarVisible:NO];
 
   // Go back.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey tapWebStateElementWithID:@"link2"]);
+  [ChromeEarlGrey tapWebStateElementWithID:@"link2"];
 
   // Make sure the toolbar has loaded now that a new page has loaded.
   [ChromeEarlGreyUI waitForToolbarVisible:YES];
@@ -415,16 +405,15 @@
   responses[URL] = manyLines;
   web::test::SetUpSimpleHttpServer(responses);
 
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:URL]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:"link"]);
+  [ChromeEarlGrey loadURL:URL];
+  [ChromeEarlGrey waitForWebStateContainingText:"link"];
 
   // Dismiss the toolbar.
   HideToolbarUsingUI();
   [ChromeEarlGreyUI waitForToolbarVisible:NO];
 
   // Go back to NTP, which is a native view.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey tapWebStateElementWithID:@"link"]);
+  [ChromeEarlGrey tapWebStateElementWithID:@"link"];
 
   // Make sure the toolbar is visible now that a new page has loaded.
   [ChromeEarlGreyUI waitForToolbarVisible:YES];
@@ -446,11 +435,11 @@
       new ErrorPageResponseProvider(responses));
   web::test::SetUpHttpServer(std::move(provider));
 
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:URL]);
+  [ChromeEarlGrey loadURL:URL];
   HideToolbarUsingUI();
   [ChromeEarlGreyUI waitForToolbarVisible:NO];
 
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey tapWebStateElementWithID:@"link"]);
+  [ChromeEarlGrey tapWebStateElementWithID:@"link"];
   AssertURLIs(ErrorPageResponseProvider::GetDnsFailureUrl());
   [ChromeEarlGreyUI waitForToolbarVisible:YES];
 }
diff --git a/ios/chrome/browser/ui/history/history_ui_egtest.mm b/ios/chrome/browser/ui/history/history_ui_egtest.mm
index 4bc88bd8..92e597b0 100644
--- a/ios/chrome/browser/ui/history/history_ui_egtest.mm
+++ b/ios/chrome/browser/ui/history/history_ui_egtest.mm
@@ -30,7 +30,6 @@
 #import "ios/chrome/test/earl_grey/accessibility_util.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
-#import "ios/chrome/test/earl_grey/chrome_error_util.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #import "ios/public/provider/chrome/browser/signin/chrome_identity.h"
@@ -197,19 +196,17 @@
   // Tap a history entry and assert that navigation to that entry's URL occurs.
   [[EarlGrey selectElementWithMatcher:HistoryEntry(_URL1, kTitle1)]
       performAction:grey_tap()];
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kResponse1]);
+  [ChromeEarlGrey waitForWebStateContainingText:kResponse1];
 }
 
 // Tests that history is not changed after performing back navigation.
 - (void)testHistoryUpdateAfterBackNavigation {
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:_URL1]);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:_URL2]);
+  [ChromeEarlGrey loadURL:_URL1];
+  [ChromeEarlGrey loadURL:_URL2];
 
   [[EarlGrey selectElementWithMatcher:chrome_test_util::BackButton()]
       performAction:grey_tap()];
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kResponse1]);
+  [ChromeEarlGrey waitForWebStateContainingText:kResponse1];
 
   [self openHistoryPanel];
 
@@ -356,7 +353,7 @@
   [[EarlGrey selectElementWithMatcher:chrome_test_util::OmniboxText(
                                           _URL1.GetContent())]
       assertWithMatcher:grey_notNil()];
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForMainTabCount:2]);
+  [ChromeEarlGrey waitForMainTabCount:2];
 }
 
 // Tests display and selection of 'Open in New Incognito Tab' in a context menu
@@ -376,8 +373,8 @@
   [[EarlGrey selectElementWithMatcher:chrome_test_util::OmniboxText(
                                           _URL1.GetContent())]
       assertWithMatcher:grey_notNil()];
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForMainTabCount:1]);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForIncognitoTabCount:1]);
+  [ChromeEarlGrey waitForMainTabCount:1];
+  [ChromeEarlGrey waitForIncognitoTabCount:1];
 }
 
 // Tests display and selection of 'Copy URL' in a context menu on a history
@@ -422,17 +419,14 @@
 #pragma mark Helper Methods
 
 - (void)loadTestURLs {
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:_URL1]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kResponse1]);
+  [ChromeEarlGrey loadURL:_URL1];
+  [ChromeEarlGrey waitForWebStateContainingText:kResponse1];
 
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:_URL2]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kResponse2]);
+  [ChromeEarlGrey loadURL:_URL2];
+  [ChromeEarlGrey waitForWebStateContainingText:kResponse2];
 
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:_URL3]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kResponse3]);
+  [ChromeEarlGrey loadURL:_URL3];
+  [ChromeEarlGrey waitForWebStateContainingText:kResponse3];
 }
 
 - (void)openHistoryPanel {
diff --git a/ios/chrome/browser/ui/infobars/infobar_egtest.mm b/ios/chrome/browser/ui/infobars/infobar_egtest.mm
index 6c7a5b6..6fa4dede 100644
--- a/ios/chrome/browser/ui/infobars/infobar_egtest.mm
+++ b/ios/chrome/browser/ui/infobars/infobar_egtest.mm
@@ -15,7 +15,6 @@
 #import "ios/chrome/browser/ui/infobars/test_infobar_delegate.h"
 #import "ios/chrome/test/app/chrome_test_util.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
-#import "ios/chrome/test/earl_grey/chrome_error_util.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #import "ios/web/public/test/http_server/http_server.h"
@@ -96,8 +95,8 @@
   // Open a new tab and navigate to the test page.
   const GURL testURL = web::test::HttpServer::MakeUrl(
       "http://ios/testing/data/http_server_files/pony.html");
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:testURL]);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForMainTabCount:1]);
+  [ChromeEarlGrey loadURL:testURL];
+  [ChromeEarlGrey waitForMainTabCount:1];
 
   // Infobar Message
   NSString* infoBarMessage = @"TestInfoBar";
@@ -111,7 +110,7 @@
 
   // Navigate to a different page.  Verify that the infobar is dismissed and no
   // longer visible on screen.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:GURL(url::kAboutBlankURL)]);
+  [ChromeEarlGrey loadURL:GURL(url::kAboutBlankURL)];
   VerifyTestInfoBarVisibleForCurrentTab(false, infoBarMessage);
   VerifyNumberOfInfobarsInManager(0);
 }
@@ -126,16 +125,16 @@
   web::test::SetUpFileBasedHttpServer();
 
   // Create the first tab and navigate to the test page.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:destinationURL]);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForMainTabCount:1]);
+  [ChromeEarlGrey loadURL:destinationURL];
+  [ChromeEarlGrey waitForMainTabCount:1];
 
   // Infobar Message
   NSString* infoBarMessage = @"TestInfoBar";
 
   // Create the second tab, navigate to the test page, and add the test infobar.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey openNewTab]);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:ponyURL]);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForMainTabCount:2]);
+  [ChromeEarlGrey openNewTab];
+  [ChromeEarlGrey loadURL:ponyURL];
+  [ChromeEarlGrey waitForMainTabCount:2];
   VerifyTestInfoBarVisibleForCurrentTab(false, infoBarMessage);
   VerifyNumberOfInfobarsInManager(0);
   GREYAssert(AddTestInfoBarToCurrentTabWithMessage(infoBarMessage),
@@ -150,12 +149,12 @@
 
   // Navigate to a different URL in the first tab, to verify that this
   // navigation does not hide the infobar in the second tab.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:ponyURL]);
+  [ChromeEarlGrey loadURL:ponyURL];
 
   // Close the first tab.  Verify that there is only one tab remaining and its
   // infobar is visible.
   [ChromeEarlGrey closeCurrentTab];
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForMainTabCount:1]);
+  [ChromeEarlGrey waitForMainTabCount:1];
   VerifyTestInfoBarVisibleForCurrentTab(true, infoBarMessage);
   VerifyNumberOfInfobarsInManager(1);
 }
@@ -167,8 +166,8 @@
   // Open a new tab and navigate to the test page.
   const GURL testURL = web::test::HttpServer::MakeUrl(
       "http://ios/testing/data/http_server_files/pony.html");
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:testURL]);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForMainTabCount:1]);
+  [ChromeEarlGrey loadURL:testURL];
+  [ChromeEarlGrey waitForMainTabCount:1];
 
   // Infobar Message
   NSString* infoBarMessage = @"TestInfoBar";
@@ -196,8 +195,8 @@
   // Open a new tab and navigate to the test page.
   const GURL testURL = web::test::HttpServer::MakeUrl(
       "http://ios/testing/data/http_server_files/pony.html");
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:testURL]);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForMainTabCount:1]);
+  [ChromeEarlGrey loadURL:testURL];
+  [ChromeEarlGrey waitForMainTabCount:1];
 
   // First Infobar Message
   NSString* firstInfoBarMessage = @"TestFirstInfoBar";
@@ -229,8 +228,8 @@
   // Open a new tab and navigate to the test page.
   const GURL testURL = web::test::HttpServer::MakeUrl(
       "http://ios/testing/data/http_server_files/pony.html");
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:testURL]);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForMainTabCount:1]);
+  [ChromeEarlGrey loadURL:testURL];
+  [ChromeEarlGrey waitForMainTabCount:1];
 
   // Infobar Message
   NSString* firstInfoBarMessage =
@@ -263,8 +262,8 @@
   // Open a new tab and navigate to the test page.
   const GURL testURL = web::test::HttpServer::MakeUrl(
       "http://ios/testing/data/http_server_files/pony.html");
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:testURL]);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForMainTabCount:1]);
+  [ChromeEarlGrey loadURL:testURL];
+  [ChromeEarlGrey waitForMainTabCount:1];
 
   // First Infobar Message
   NSString* firstInfoBarMessage =
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_egtest.mm b/ios/chrome/browser/ui/ntp/new_tab_page_egtest.mm
index b2bb8bc..c9fbbb0d 100644
--- a/ios/chrome/browser/ui/ntp/new_tab_page_egtest.mm
+++ b/ios/chrome/browser/ui/ntp/new_tab_page_egtest.mm
@@ -17,7 +17,6 @@
 #import "ios/chrome/test/app/chrome_test_util.h"
 #import "ios/chrome/test/earl_grey/accessibility_util.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
-#import "ios/chrome/test/earl_grey/chrome_error_util.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -61,10 +60,10 @@
 
 // Tests that all items are accessible on the incognito page.
 - (void)testAccessibilityOnIncognitoTab {
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey openNewIncognitoTab]);
+  [ChromeEarlGrey openNewIncognitoTab];
   WaitForHistoryToDisappear();
   chrome_test_util::VerifyAccessibilityForCurrentScreen();
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey closeAllIncognitoTabs]);
+  [ChromeEarlGrey closeAllIncognitoTabs];
 }
 
 @end
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_egtest.mm b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_egtest.mm
index 35d3b93a9..b14b35bf 100644
--- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_egtest.mm
+++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_egtest.mm
@@ -12,7 +12,6 @@
 #import "ios/chrome/browser/ui/tab_grid/tab_grid_egtest_util.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
-#import "ios/chrome/test/earl_grey/chrome_error_util.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #include "net/test/embedded_test_server/http_request.h"
@@ -111,16 +110,13 @@
 - (void)testSwitchToOpenTab {
   // Open the first page.
   GURL firstPageURL = self.testServer->GetURL(kPage1URL);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:firstPageURL]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kPage1]);
+  [ChromeEarlGrey loadURL:firstPageURL];
+  [ChromeEarlGrey waitForWebStateContainingText:kPage1];
 
   // Open the second page in another tab.
   [ChromeEarlGreyUI openNewTab];
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey loadURL:self.testServer->GetURL(kPage2URL)]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kPage2]);
+  [ChromeEarlGrey loadURL:self.testServer->GetURL(kPage2URL)];
+  [ChromeEarlGrey waitForWebStateContainingText:kPage2];
 
   // Type the URL of the first page in the omnibox to trigger it as suggestion.
   [ChromeEarlGreyUI focusOmniboxAndType:base::SysUTF8ToNSString(kPage1URL)];
@@ -128,8 +124,7 @@
   // Switch to the first tab.
   [[EarlGrey selectElementWithMatcher:SwitchTabElementForUrl(firstPageURL)]
       performAction:grey_tap()];
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kPage1]);
+  [ChromeEarlGrey waitForWebStateContainingText:kPage1];
 
   // Check that both tabs are opened (and that we switched tab and not just
   // navigated.
@@ -148,16 +143,13 @@
   GURL URL2 = self.testServer->GetURL(kPage2URL);
 
   // Open the first page.
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey loadURL:self.testServer->GetURL(kPage1URL)]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kPage1]);
+  [ChromeEarlGrey loadURL:self.testServer->GetURL(kPage1URL)];
+  [ChromeEarlGrey waitForWebStateContainingText:kPage1];
 
   // Open the second page in another tab.
   [ChromeEarlGreyUI openNewTab];
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:URL2]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kPage2]);
+  [ChromeEarlGrey loadURL:URL2];
+  [ChromeEarlGrey waitForWebStateContainingText:kPage2];
 
   // Type the URL of the first page in the omnibox to trigger it as suggestion.
   [ChromeEarlGreyUI focusOmniboxAndType:base::SysUTF8ToNSString(kPage2URL)];
@@ -178,33 +170,27 @@
   GURL URL3 = self.testServer->GetURL(kPage3URL);
 
   // Add all the pages to the history.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:URL1]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kPage1]);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:URL2]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kPage2]);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:URL3]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kPage3]);
+  [ChromeEarlGrey loadURL:URL1];
+  [ChromeEarlGrey waitForWebStateContainingText:kPage1];
+  [ChromeEarlGrey loadURL:URL2];
+  [ChromeEarlGrey waitForWebStateContainingText:kPage2];
+  [ChromeEarlGrey loadURL:URL3];
+  [ChromeEarlGrey waitForWebStateContainingText:kPage3];
   [[self class] closeAllTabs];
 
   // Load page 1 in non-incognito and page 2 in incognito.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey openNewTab]);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:URL1]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kPage1]);
+  [ChromeEarlGrey openNewTab];
+  [ChromeEarlGrey loadURL:URL1];
+  [ChromeEarlGrey waitForWebStateContainingText:kPage1];
 
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey openNewIncognitoTab]);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:URL2]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kPage2]);
+  [ChromeEarlGrey openNewIncognitoTab];
+  [ChromeEarlGrey loadURL:URL2];
+  [ChromeEarlGrey waitForWebStateContainingText:kPage2];
 
   // Open page 3 in non-incognito.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey openNewTab]);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:URL3]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kPage3]);
+  [ChromeEarlGrey openNewTab];
+  [ChromeEarlGrey loadURL:URL3];
+  [ChromeEarlGrey waitForWebStateContainingText:kPage3];
 
   [ChromeEarlGreyUI focusOmniboxAndType:base::SysUTF8ToNSString(URL3.host())];
 
@@ -223,10 +209,9 @@
       assertWithMatcher:grey_nil()];
 
   // Open page 3 in incognito.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey openNewIncognitoTab]);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:URL3]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kPage3]);
+  [ChromeEarlGrey openNewIncognitoTab];
+  [ChromeEarlGrey loadURL:URL3];
+  [ChromeEarlGrey waitForWebStateContainingText:kPage3];
 
   [ChromeEarlGreyUI focusOmniboxAndType:base::SysUTF8ToNSString(URL3.host())];
 
@@ -248,47 +233,42 @@
 - (void)testCloseNTPWhenSwitching {
   // Open the first page.
   GURL URL1 = self.testServer->GetURL(kPage1URL);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:URL1]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kPage1]);
+  [ChromeEarlGrey loadURL:URL1];
+  [ChromeEarlGrey waitForWebStateContainingText:kPage1];
 
   // Open a new tab and switch to the first tab.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey openNewTab]);
+  [ChromeEarlGrey openNewTab];
   [[EarlGrey selectElementWithMatcher:chrome_test_util::FakeOmnibox()]
       performAction:grey_typeText(base::SysUTF8ToNSString(URL1.host()))];
   [[EarlGrey selectElementWithMatcher:SwitchTabElementForUrl(URL1)]
       performAction:grey_tap()];
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kPage1]);
+  [ChromeEarlGrey waitForWebStateContainingText:kPage1];
 
   // Check that the other tab is closed.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForMainTabCount:1]);
+  [ChromeEarlGrey waitForMainTabCount:1];
 }
 
 - (void)testDontCloseNTPWhenSwitchingWithForwardHistory {
   // Open the first page.
   GURL URL1 = self.testServer->GetURL(kPage1URL);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:URL1]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kPage1]);
+  [ChromeEarlGrey loadURL:URL1];
+  [ChromeEarlGrey waitForWebStateContainingText:kPage1];
 
   // Open a new tab, navigate to a page and go back to have forward history.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey openNewTab]);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:URL1]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kPage1]);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey goBack]);
+  [ChromeEarlGrey openNewTab];
+  [ChromeEarlGrey loadURL:URL1];
+  [ChromeEarlGrey waitForWebStateContainingText:kPage1];
+  [ChromeEarlGrey goBack];
 
   // Navigate to the other tab.
   [[EarlGrey selectElementWithMatcher:chrome_test_util::FakeOmnibox()]
       performAction:grey_typeText(base::SysUTF8ToNSString(URL1.host()))];
   [[EarlGrey selectElementWithMatcher:SwitchTabElementForUrl(URL1)]
       performAction:grey_tap()];
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kPage1]);
+  [ChromeEarlGrey waitForWebStateContainingText:kPage1];
 
   // Check that the other tab is not closed.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForMainTabCount:2]);
+  [ChromeEarlGrey waitForMainTabCount:2];
 }
 
 // Tests that switching to closed tab opens the tab in foreground, except if it
@@ -297,16 +277,13 @@
   GURL URL1 = self.testServer->GetURL(kPage1URL);
 
   // Open the first page.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:URL1]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kPage1]);
+  [ChromeEarlGrey loadURL:URL1];
+  [ChromeEarlGrey waitForWebStateContainingText:kPage1];
 
   // Open a new tab and load another URL.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey openNewTab]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey loadURL:self.testServer->GetURL(kPage2URL)]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kPage2]);
+  [ChromeEarlGrey openNewTab];
+  [ChromeEarlGrey loadURL:self.testServer->GetURL(kPage2URL)];
+  [ChromeEarlGrey waitForWebStateContainingText:kPage2];
 
   // Start typing url of the first page.
   [ChromeEarlGreyUI focusOmniboxAndType:base::SysUTF8ToNSString(kPage1URL)];
@@ -317,16 +294,15 @@
 
   // Close the first page.
   [ChromeEarlGrey closeTabAtIndex:0];
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForMainTabCount:1]);
+  [ChromeEarlGrey waitForMainTabCount:1];
 
   // Try to switch to the first tab.
   [[EarlGrey selectElementWithMatcher:SwitchTabElementForUrl(URL1)]
       performAction:grey_tap()];
 
   // Check that the URL has been opened in a new foreground tab.
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kPage1]);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForMainTabCount:2]);
+  [ChromeEarlGrey waitForWebStateContainingText:kPage1];
+  [ChromeEarlGrey waitForMainTabCount:2];
 }
 
 // Tests that having multiple suggestions with corresponding opened tabs display
@@ -334,19 +310,17 @@
 - (void)testMultiplePageOpened {
   // Open the first page.
   GURL URL1 = self.testServer->GetURL(kPage1URL);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:URL1]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kPage1]);
+  [ChromeEarlGrey loadURL:URL1];
+  [ChromeEarlGrey waitForWebStateContainingText:kPage1];
 
   // Open the second page in a new tab.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey openNewTab]);
+  [ChromeEarlGrey openNewTab];
   GURL URL2 = self.testServer->GetURL(kPage2URL);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:URL2]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kPage2]);
+  [ChromeEarlGrey loadURL:URL2];
+  [ChromeEarlGrey waitForWebStateContainingText:kPage2];
 
   // Start typing url of the two opened pages in a new tab.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey openNewTab]);
+  [ChromeEarlGrey openNewTab];
   [[EarlGrey selectElementWithMatcher:chrome_test_util::FakeOmnibox()]
       performAction:grey_typeText(@"page")];
 
diff --git a/ios/chrome/browser/ui/omnibox/popup/shortcuts/shortcuts_egtest.mm b/ios/chrome/browser/ui/omnibox/popup/shortcuts/shortcuts_egtest.mm
index 1daf176..3f94bcf 100644
--- a/ios/chrome/browser/ui/omnibox/popup/shortcuts/shortcuts_egtest.mm
+++ b/ios/chrome/browser/ui/omnibox/popup/shortcuts/shortcuts_egtest.mm
@@ -15,7 +15,6 @@
 #import "ios/chrome/test/app/chrome_test_util.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
-#import "ios/chrome/test/earl_grey/chrome_error_util.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #include "net/test/embedded_test_server/http_request.h"
@@ -122,8 +121,7 @@
   [ChromeEarlGreyUI focusOmnibox];
   [[EarlGrey selectElementWithMatcher:[self mostVisitedTileMatcher]]
       performAction:grey_tap()];
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kTilePageLoadedString]);
+  [ChromeEarlGrey waitForWebStateContainingText:kTilePageLoadedString];
 }
 
 - (void)testBookmarksShortcut {
@@ -239,15 +237,14 @@
 // Tests that on the NTP the shortcuts don't show up.
 - (void)testNTPShortcutsDontShowUp {
   [[self class] closeAllTabs];
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey openNewTab]);
+  [ChromeEarlGrey openNewTab];
 
   // Tap the fake omnibox.
   [[EarlGrey selectElementWithMatcher:chrome_test_util::FakeOmnibox()]
       performAction:grey_tap()];
   // Wait for the real omnibox to be visible.
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForSufficientlyVisibleElementWithMatcher:
-                          chrome_test_util::Omnibox()]);
+  [ChromeEarlGrey
+      waitForSufficientlyVisibleElementWithMatcher:chrome_test_util::Omnibox()];
 
   // The shortcuts should not show up here.
   // The shortcuts are similar to the NTP tiles, so in this test it's necessary
@@ -262,23 +259,21 @@
 
 - (void)navigateToAPage {
   const GURL pageURL = self.testServer->GetURL(kPageURL);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:pageURL]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kPageLoadedString]);
+  [ChromeEarlGrey loadURL:pageURL];
+  [ChromeEarlGrey waitForWebStateContainingText:kPageLoadedString];
 }
 
 - (void)prepareMostVisitedTiles {
   const GURL pageURL = self.testServer->GetURL(kTilePageURL);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:pageURL]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kTilePageLoadedString]);
+  [ChromeEarlGrey loadURL:pageURL];
+  [ChromeEarlGrey waitForWebStateContainingText:kTilePageLoadedString];
 
   // After loading URL, need to do another action before opening a new tab
   // with the icon present.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey goBack]);
+  [ChromeEarlGrey goBack];
 
   [[self class] closeAllTabs];
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey openNewTab]);
+  [ChromeEarlGrey openNewTab];
 }
 
 - (id<GREYMatcher>)mostVisitedTileMatcher {
diff --git a/ios/chrome/browser/ui/page_info/page_info_egtest.mm b/ios/chrome/browser/ui/page_info/page_info_egtest.mm
index 8dbd79e..c26071a 100644
--- a/ios/chrome/browser/ui/page_info/page_info_egtest.mm
+++ b/ios/chrome/browser/ui/page_info/page_info_egtest.mm
@@ -11,7 +11,6 @@
 #include "ios/chrome/browser/ui/util/ui_util.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
-#import "ios/chrome/test/earl_grey/chrome_error_util.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
@@ -36,7 +35,7 @@
                              errorOrNil:nil];
   }
 
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:GURL("https://invalid")]);
+  [ChromeEarlGrey loadURL:GURL("https://invalid")];
   [ChromeEarlGreyUI openToolsMenu];
   [[[EarlGrey
       selectElementWithMatcher:grey_allOf(grey_accessibilityID(
diff --git a/ios/chrome/browser/ui/print/print_controller_egtest.mm b/ios/chrome/browser/ui/print/print_controller_egtest.mm
index 3708471..22d2649 100644
--- a/ios/chrome/browser/ui/print/print_controller_egtest.mm
+++ b/ios/chrome/browser/ui/print/print_controller_egtest.mm
@@ -12,7 +12,6 @@
 #import "ios/chrome/test/app/chrome_test_util.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
-#import "ios/chrome/test/earl_grey/chrome_error_util.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #include "ios/testing/earl_grey/disabled_test_macros.h"
@@ -57,9 +56,8 @@
   responses[url] = response;
   web::test::SetUpSimpleHttpServer(responses);
 
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:url]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:response]);
+  [ChromeEarlGrey loadURL:url];
+  [ChromeEarlGrey waitForWebStateContainingText:response];
 
   [self printCurrentPage];
 }
@@ -71,7 +69,7 @@
 
   web::test::SetUpFileBasedHttpServer();
   GURL url = web::test::HttpServer::MakeUrl(kPDFURL);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:url waitForCompletion:NO]);
+  [ChromeEarlGrey loadURL:url waitForCompletion:NO];
 
   [self printCurrentPage];
 }
diff --git a/ios/chrome/browser/ui/sad_tab/sad_tab_view_egtest.mm b/ios/chrome/browser/ui/sad_tab/sad_tab_view_egtest.mm
index c5c4a82..03c2b02 100644
--- a/ios/chrome/browser/ui/sad_tab/sad_tab_view_egtest.mm
+++ b/ios/chrome/browser/ui/sad_tab/sad_tab_view_egtest.mm
@@ -10,7 +10,6 @@
 #import "ios/chrome/test/app/chrome_test_util.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
-#import "ios/chrome/test/earl_grey/chrome_error_util.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #import "ios/web/public/test/http_server/http_server.h"
@@ -92,9 +91,8 @@
 
   // Prepare a helper block to test Sad Tab navigating from and to normal pages.
   void (^loadAndCheckSimpleURL)() = ^void() {
-    CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:simple_URL]);
-    CHROME_EG_ASSERT_NO_ERROR(
-        [ChromeEarlGrey waitForWebStateContainingText:"You've arrived"]);
+    [ChromeEarlGrey loadURL:simple_URL];
+    [ChromeEarlGrey waitForWebStateContainingText:"You've arrived"];
     [[EarlGrey selectElementWithMatcher:reloadSadTabTitleText()]
         assertWithMatcher:grey_nil()];
     [[EarlGrey selectElementWithMatcher:feedbackSadTabTitleContainsText()]
@@ -105,8 +103,7 @@
 
   // Navigate to the chrome://crash URL which should show the Sad Tab.
   const GURL crash_URL = GURL("chrome://crash");
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:crash_URL
-                                  waitForCompletion:NO]);
+  [ChromeEarlGrey loadURL:crash_URL waitForCompletion:NO];
   [[EarlGrey selectElementWithMatcher:reloadSadTabTitleText()]
       assertWithMatcher:grey_notNil()];
 
@@ -117,8 +114,7 @@
   // A second visit to the crashing URL should show a feedback message.
   // It should also show help messages including an invitation to use
   // Incognito Mode.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:crash_URL
-                                  waitForCompletion:NO]);
+  [ChromeEarlGrey loadURL:crash_URL waitForCompletion:NO];
   [[EarlGrey selectElementWithMatcher:feedbackSadTabTitleContainsText()]
       assertWithMatcher:grey_notNil()];
   [[EarlGrey selectElementWithMatcher:incognitoHelpContainsText()]
@@ -135,17 +131,15 @@
       grey_accessibilityID(kToolsMenuNewIncognitoTabId);
   [[EarlGrey selectElementWithMatcher:newIncognitoTabButtonMatcher]
       performAction:grey_tap()];
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForIncognitoTabCount:1]);
+  [ChromeEarlGrey waitForIncognitoTabCount:1];
   loadAndCheckSimpleURL();
 
   // Test an initial crash, and then a second crash in Incognito mode, as above.
   // Incognito mode should not be suggested if already in Incognito mode.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:crash_URL
-                                  waitForCompletion:NO]);
+  [ChromeEarlGrey loadURL:crash_URL waitForCompletion:NO];
   [[EarlGrey selectElementWithMatcher:reloadSadTabTitleText()]
       assertWithMatcher:grey_notNil()];
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:crash_URL
-                                  waitForCompletion:NO]);
+  [ChromeEarlGrey loadURL:crash_URL waitForCompletion:NO];
   [[EarlGrey selectElementWithMatcher:feedbackSadTabTitleContainsText()]
       assertWithMatcher:grey_notNil()];
   [[EarlGrey selectElementWithMatcher:incognitoHelpContainsText()]
diff --git a/ios/chrome/browser/ui/side_swipe/side_swipe_egtest.mm b/ios/chrome/browser/ui/side_swipe/side_swipe_egtest.mm
index 53d720d..51067b9 100644
--- a/ios/chrome/browser/ui/side_swipe/side_swipe_egtest.mm
+++ b/ios/chrome/browser/ui/side_swipe/side_swipe_egtest.mm
@@ -10,7 +10,6 @@
 #import "ios/chrome/browser/ui/util/uikit_ui_util.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
-#import "ios/chrome/test/earl_grey/chrome_error_util.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #include "ios/testing/earl_grey/disabled_test_macros.h"
@@ -53,27 +52,22 @@
   GREYAssertTrue(self.testServer->Start(), @"Test server failed to start.");
 
   // Load the first page.
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey loadURL:self.testServer->GetURL("/echo")]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:"Echo"]);
+  [ChromeEarlGrey loadURL:self.testServer->GetURL("/echo")];
+  [ChromeEarlGrey waitForWebStateContainingText:"Echo"];
 
   // Open a new Tab to have a tab to switch to.
   [ChromeEarlGreyUI openNewTab];
 
   // Load the second page in the new tab.
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey loadURL:self.testServer->GetURL("/defaultresponse")]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:"Default response"]);
+  [ChromeEarlGrey loadURL:self.testServer->GetURL("/defaultresponse")];
+  [ChromeEarlGrey waitForWebStateContainingText:"Default response"];
 
   // Side swipe on the toolbar.
   [[EarlGrey selectElementWithMatcher:grey_kindOfClass(klass)]
       performAction:grey_swipeSlowInDirection(kGREYDirectionRight)];
 
   // Check that we swiped back to our web page.
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:"Echo"]);
+  [ChromeEarlGrey waitForWebStateContainingText:"Echo"];
 }
 
 @end
diff --git a/ios/chrome/browser/ui/toolbar/adaptive_toolbar_egtest.mm b/ios/chrome/browser/ui/toolbar/adaptive_toolbar_egtest.mm
index f801fce..b698ac4 100644
--- a/ios/chrome/browser/ui/toolbar/adaptive_toolbar_egtest.mm
+++ b/ios/chrome/browser/ui/toolbar/adaptive_toolbar_egtest.mm
@@ -23,7 +23,6 @@
 #import "ios/chrome/test/app/chrome_test_util.h"
 #import "ios/chrome/test/earl_grey/chrome_actions.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
-#import "ios/chrome/test/earl_grey/chrome_error_util.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #include "ios/testing/earl_grey/disabled_test_macros.h"
@@ -406,8 +405,8 @@
   }
 
   // Setup the bookmarks.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForBookmarksToFinishLoading]);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey clearBookmarks]);
+  [ChromeEarlGrey waitForBookmarksToFinishLoading];
+  [ChromeEarlGrey clearBookmarks];
 
   // Setup the server.
   self.testServer->RegisterRequestHandler(
@@ -415,8 +414,7 @@
   GREYAssertTrue(self.testServer->Start(), @"Test server failed to start.");
 
   // Navigate to a page and check the bookmark button is not spotlighted.
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey loadURL:self.testServer->GetURL(kPageURL)]);
+  [ChromeEarlGrey loadURL:self.testServer->GetURL(kPageURL)];
   [[EarlGrey selectElementWithMatcher:BookmarkButton()]
       assertWithMatcher:grey_allOf(grey_kindOfClass([UIControl class]),
                                    grey_not(Spotlighted()), nil)];
@@ -428,20 +426,18 @@
       assertWithMatcher:Spotlighted()];
 
   // Navigate to a different page and check the button is not selected.
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey loadURL:self.testServer->GetURL(kPageURL2)]);
+  [ChromeEarlGrey loadURL:self.testServer->GetURL(kPageURL2)];
   [[EarlGrey selectElementWithMatcher:BookmarkButton()]
       assertWithMatcher:grey_allOf(grey_kindOfClass([UIControl class]),
                                    grey_not(Spotlighted()), nil)];
 
   // Navigate back to the bookmarked page and check the button.
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey loadURL:self.testServer->GetURL(kPageURL)]);
+  [ChromeEarlGrey loadURL:self.testServer->GetURL(kPageURL)];
   [[EarlGrey selectElementWithMatcher:BookmarkButton()]
       assertWithMatcher:Spotlighted()];
 
   // Clean the bookmarks
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey clearBookmarks]);
+  [ChromeEarlGrey clearBookmarks];
 }
 
 // Tests that tapping a button cancels the focus on the omnibox.
@@ -451,7 +447,7 @@
   }
 
   // Navigate to a page to enable the back button.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:GURL("chrome://version")]);
+  [ChromeEarlGrey loadURL:GURL("chrome://version")];
 
   FocusOmnibox();
 
@@ -466,7 +462,7 @@
 // different orientation than the default one.
 - (void)testFocusOmniboxFromOtherOrientation {
   // Load a page to have the toolbar visible (hidden on NTP).
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:GURL("chrome://version")]);
+  [ChromeEarlGrey loadURL:GURL("chrome://version")];
 
   // Get the original trait collection.
   UIViewController* topViewController =
@@ -504,7 +500,7 @@
 // the default orientation.
 - (void)testFocusOmniboxFromPortrait {
   // Load a page to have the toolbar visible (hidden on NTP).
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:GURL("chrome://version")]);
+  [ChromeEarlGrey loadURL:GURL("chrome://version")];
 
   FocusOmnibox();
 
@@ -556,8 +552,7 @@
   GREYAssertTrue(self.testServer->Start(), @"Test server failed to start.");
 
   // Navigate to a page.
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey loadURL:self.testServer->GetURL(kPageURL)]);
+  [ChromeEarlGrey loadURL:self.testServer->GetURL(kPageURL)];
 
   GREYAssert(AddInfobar(), @"Failed to add infobar.");
 
@@ -636,10 +631,8 @@
   GREYAssertTrue(self.testServer->Start(), @"Test server failed to start.");
 
   // Loads two url and check the navigation buttons status.
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey loadURL:self.testServer->GetURL(kPageURL)]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey loadURL:self.testServer->GetURL(kPageURL2)]);
+  [ChromeEarlGrey loadURL:self.testServer->GetURL(kPageURL)];
+  [ChromeEarlGrey loadURL:self.testServer->GetURL(kPageURL2)];
   [[EarlGrey selectElementWithMatcher:chrome_test_util::BackButton()]
       assertWithMatcher:grey_interactable()];
   [[EarlGrey selectElementWithMatcher:chrome_test_util::ForwardButton()]
@@ -717,7 +710,7 @@
   const GURL pageURL = self.testServer->GetURL(kPageURL);
 
   // Navigate to another page and check that the share button is enabled.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:pageURL]);
+  [ChromeEarlGrey loadURL:pageURL];
   [[EarlGrey selectElementWithMatcher:ShareButton()]
       assertWithMatcher:grey_interactable()];
 
@@ -750,7 +743,7 @@
   [[GREYUIThreadExecutor sharedInstance] drainUntilIdleWithTimeout:2];
 
   [[self class] closeAllTabs];
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey openNewTab]);
+  [ChromeEarlGrey openNewTab];
 
   // Check that the bottom toolbar is visible.
   [[EarlGrey selectElementWithMatcher:SearchButton()]
@@ -760,7 +753,7 @@
 // Verifies the existence and state of toolbar UI elements.
 - (void)testToolbarUI {
   // Load a page to have the toolbar visible (hidden on NTP).
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:GURL("chrome://version")]);
+  [ChromeEarlGrey loadURL:GURL("chrome://version")];
 
   // Get the original trait collection.
   UIViewController* topViewController =
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_egtest.mm b/ios/chrome/browser/ui/toolbar/toolbar_egtest.mm
index 1112383c..12af228 100644
--- a/ios/chrome/browser/ui/toolbar/toolbar_egtest.mm
+++ b/ios/chrome/browser/ui/toolbar/toolbar_egtest.mm
@@ -13,7 +13,6 @@
 #include "ios/chrome/grit/ios_strings.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
-#import "ios/chrome/test/earl_grey/chrome_error_util.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #import "ios/testing/earl_grey/earl_grey_test.h"
@@ -43,16 +42,15 @@
   web::test::SetUpFileBasedHttpServer();
   const GURL URL = web::test::HttpServer::MakeUrl(
       "http://ios/testing/data/http_server_files/destination.html");
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:URL]);
+  [ChromeEarlGrey loadURL:URL];
   [[EarlGrey selectElementWithMatcher:OmniboxText(URL.GetContent())]
       assertWithMatcher:grey_notNil()];
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:"You've arrived"]);
+  [ChromeEarlGrey waitForWebStateContainingText:"You've arrived"];
 }
 
 // Verifies opening a new tab from the tools menu.
 - (void)testNewTabFromMenu {
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForMainTabCount:1]);
+  [ChromeEarlGrey waitForMainTabCount:1];
 
   // Open tab via the UI.
   [ChromeEarlGreyUI openToolsMenu];
@@ -61,12 +59,12 @@
   [[EarlGrey selectElementWithMatcher:newTabButtonMatcher]
       performAction:grey_tap()];
 
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForMainTabCount:2]);
+  [ChromeEarlGrey waitForMainTabCount:2];
 }
 
 // Verifies opening a new incognito tab from the tools menu.
 - (void)testNewIncognitoTabFromMenu {
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForIncognitoTabCount:0]);
+  [ChromeEarlGrey waitForIncognitoTabCount:0];
 
   // Open incognito tab.
   [ChromeEarlGreyUI openToolsMenu];
@@ -75,7 +73,7 @@
   [[EarlGrey selectElementWithMatcher:newIncognitoTabButtonMatcher]
       performAction:grey_tap()];
 
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForIncognitoTabCount:1]);
+  [ChromeEarlGrey waitForIncognitoTabCount:1];
 }
 
 // Tests whether input mode in an omnibox can be canceled via "Cancel" button
@@ -88,7 +86,7 @@
 
   const GURL URL = web::test::HttpServer::MakeUrl("http://origin");
 
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:URL]);
+  [ChromeEarlGrey loadURL:URL];
 
   [[EarlGrey selectElementWithMatcher:chrome_test_util::DefocusedLocationView()]
       performAction:grey_tap()];
@@ -121,7 +119,7 @@
 
   const GURL URL = web::test::HttpServer::MakeUrl("http://origin");
 
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:URL]);
+  [ChromeEarlGrey loadURL:URL];
 
   [[EarlGrey selectElementWithMatcher:chrome_test_util::Omnibox()]
       assertWithMatcher:chrome_test_util::OmniboxText(URL.GetContent())];
@@ -150,7 +148,7 @@
 
   const GURL URL = web::test::HttpServer::MakeUrl("http://origin");
 
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:URL]);
+  [ChromeEarlGrey loadURL:URL];
 
   [[EarlGrey selectElementWithMatcher:chrome_test_util::Omnibox()]
       assertWithMatcher:chrome_test_util::OmniboxText(URL.GetContent())];
@@ -176,8 +174,8 @@
   // (Subsequent steps in this test require the omnibox to be tappable, but in
   // some configurations the NTP only has a fakebox and does not display the
   // omnibox.)
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:GURL("about:blank")]);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:GURL("chrome://version")]);
+  [ChromeEarlGrey loadURL:GURL("about:blank")];
+  [ChromeEarlGrey loadURL:GURL("chrome://version")];
 
   // First test: check that the keyboard is opened when tapping the omnibox,
   // and that it is dismissed when the "Back" button is tapped.
@@ -224,7 +222,7 @@
   const GURL URL = web::test::HttpServer::MakeUrl("http://veryLongURLTestPage");
   const GURL secondURL = web::test::HttpServer::MakeUrl("http://pastePage");
 
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:URL]);
+  [ChromeEarlGrey loadURL:URL];
 
   [[EarlGrey selectElementWithMatcher:chrome_test_util::Omnibox()]
       assertWithMatcher:chrome_test_util::OmniboxText(URL.GetContent())];
@@ -257,7 +255,7 @@
         performAction:grey_tap()];
   }
 
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:secondURL]);
+  [ChromeEarlGrey loadURL:secondURL];
   [[EarlGrey selectElementWithMatcher:chrome_test_util::Omnibox()]
       performAction:grey_longPress()];
 
@@ -281,7 +279,7 @@
 
   const GURL URL = web::test::HttpServer::MakeUrl("http://origin");
 
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:URL]);
+  [ChromeEarlGrey loadURL:URL];
   [[EarlGrey selectElementWithMatcher:chrome_test_util::DefocusedLocationView()]
       performAction:grey_tap()];
 
@@ -310,7 +308,7 @@
   GURL URL = web::test::HttpServer::MakeUrl("http://foo");
   responses[URL] = "bar";
   web::test::SetUpSimpleHttpServer(responses);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:GURL(URL)]);
+  [ChromeEarlGrey loadURL:GURL(URL)];
 
   [ChromeEarlGreyUI focusOmniboxAndType:@"javascript:alert('Hello');\n"];
 
@@ -326,7 +324,7 @@
   if (IsIPadIdiom()) {
     EARL_GREY_TEST_DISABLED(@"Disabled for iPad due to a typing bug.");
   }
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:GURL("chrome://version")]);
+  [ChromeEarlGrey loadURL:GURL("chrome://version")];
   [ChromeEarlGreyUI focusOmniboxAndType:@"javascript:alert('Hello');\n"];
 
   [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(@"Hello")]
@@ -427,9 +425,8 @@
   // Select the omnibox to get the keyboard up.
   [[EarlGrey selectElementWithMatcher:chrome_test_util::NewTabPageOmnibox()]
       performAction:grey_tap()];
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForSufficientlyVisibleElementWithMatcher:
-                          chrome_test_util::Omnibox()]);
+  [ChromeEarlGrey
+      waitForSufficientlyVisibleElementWithMatcher:chrome_test_util::Omnibox()];
 
   // Tap the "/" keyboard accessory button.
   id<GREYMatcher> slashButtonMatcher = grey_allOf(
diff --git a/ios/chrome/browser/ui/webui/inspect/inspect_ui_egtest.mm b/ios/chrome/browser/ui/webui/inspect/inspect_ui_egtest.mm
index b864398..8c238965 100644
--- a/ios/chrome/browser/ui/webui/inspect/inspect_ui_egtest.mm
+++ b/ios/chrome/browser/ui/webui/inspect/inspect_ui_egtest.mm
@@ -11,7 +11,6 @@
 #import "ios/chrome/test/app/chrome_test_util.h"
 #import "ios/chrome/test/earl_grey/chrome_actions.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
-#import "ios/chrome/test/earl_grey/chrome_error_util.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #include "ios/web/public/test/element_selector.h"
@@ -110,299 +109,227 @@
 
 // Tests that chrome://inspect allows the user to enable and disable logging.
 - (void)testStartStopLogging {
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:GURL(kChromeUIInspectURL)]);
+  [ChromeEarlGrey loadURL:GURL(kChromeUIInspectURL)];
 
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingElement:StartLoggingButton()]);
+  [ChromeEarlGrey waitForWebStateContainingElement:StartLoggingButton()];
 
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey tapWebStateElementWithID:kStartLoggingButtonId]);
+  [ChromeEarlGrey tapWebStateElementWithID:kStartLoggingButtonId];
 
   ElementSelector* stopLoggingButton = [ElementSelector
       selectorWithElementID:base::SysNSStringToUTF8(kStopLoggingButtonId)];
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingElement:stopLoggingButton]);
+  [ChromeEarlGrey waitForWebStateContainingElement:stopLoggingButton];
 
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey tapWebStateElementWithID:kStopLoggingButtonId]);
+  [ChromeEarlGrey tapWebStateElementWithID:kStopLoggingButtonId];
 
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingElement:StartLoggingButton()]);
+  [ChromeEarlGrey waitForWebStateContainingElement:StartLoggingButton()];
 }
 
 // Tests that log messages from a page's main frame are displayed.
 - (void)testMainFrameLogging {
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:GURL(kChromeUIInspectURL)]);
+  [ChromeEarlGrey loadURL:GURL(kChromeUIInspectURL)];
 
   // Start logging.
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingElement:StartLoggingButton()]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey tapWebStateElementWithID:kStartLoggingButtonId]);
+  [ChromeEarlGrey waitForWebStateContainingElement:StartLoggingButton()];
+  [ChromeEarlGrey tapWebStateElementWithID:kStartLoggingButtonId];
 
   // Open console test page.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey openNewTab]);
+  [ChromeEarlGrey openNewTab];
   const GURL consoleTestsURL = self.testServer->GetURL(kConsolePage);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:consoleTestsURL]);
+  [ChromeEarlGrey loadURL:consoleTestsURL];
   std::string debugButtonID = base::SysNSStringToUTF8(kDebugMessageButtonId);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey
-      waitForWebStateContainingElement:
-          [ElementSelector selectorWithElementID:debugButtonID]]);
+  [ChromeEarlGrey waitForWebStateContainingElement:
+                      [ElementSelector selectorWithElementID:debugButtonID]];
 
   // Log messages.
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey tapWebStateElementWithID:kDebugMessageButtonId]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey tapWebStateElementWithID:kErrorMessageButtonId]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey tapWebStateElementWithID:kInfoMessageButtonId]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey tapWebStateElementWithID:kLogMessageButtonId]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey tapWebStateElementWithID:kWarningMessageButtonId]);
+  [ChromeEarlGrey tapWebStateElementWithID:kDebugMessageButtonId];
+  [ChromeEarlGrey tapWebStateElementWithID:kErrorMessageButtonId];
+  [ChromeEarlGrey tapWebStateElementWithID:kInfoMessageButtonId];
+  [ChromeEarlGrey tapWebStateElementWithID:kLogMessageButtonId];
+  [ChromeEarlGrey tapWebStateElementWithID:kWarningMessageButtonId];
 
   [ChromeEarlGrey selectTabAtIndex:0];
   // Validate messages and labels are displayed.
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kDebugMessageLabel]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kDebugMessageText]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kErrorMessageLabel]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kErrorMessageText]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kInfoMessageLabel]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kInfoMessageText]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kLogMessageLabel]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kLogMessageText]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kWarningMessageLabel]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kWarningMessageText]);
+  [ChromeEarlGrey waitForWebStateContainingText:kDebugMessageLabel];
+  [ChromeEarlGrey waitForWebStateContainingText:kDebugMessageText];
+  [ChromeEarlGrey waitForWebStateContainingText:kErrorMessageLabel];
+  [ChromeEarlGrey waitForWebStateContainingText:kErrorMessageText];
+  [ChromeEarlGrey waitForWebStateContainingText:kInfoMessageLabel];
+  [ChromeEarlGrey waitForWebStateContainingText:kInfoMessageText];
+  [ChromeEarlGrey waitForWebStateContainingText:kLogMessageLabel];
+  [ChromeEarlGrey waitForWebStateContainingText:kLogMessageText];
+  [ChromeEarlGrey waitForWebStateContainingText:kWarningMessageLabel];
+  [ChromeEarlGrey waitForWebStateContainingText:kWarningMessageText];
 }
 
 // Tests that log messages from an iframe are displayed.
 - (void)testIframeLogging {
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:GURL(kChromeUIInspectURL)]);
+  [ChromeEarlGrey loadURL:GURL(kChromeUIInspectURL)];
 
   // Start logging.
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingElement:StartLoggingButton()]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey tapWebStateElementWithID:kStartLoggingButtonId]);
+  [ChromeEarlGrey waitForWebStateContainingElement:StartLoggingButton()];
+  [ChromeEarlGrey tapWebStateElementWithID:kStartLoggingButtonId];
 
   // Open console test page.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey openNewTab]);
+  [ChromeEarlGrey openNewTab];
   const GURL consoleTestsURL = self.testServer->GetURL(kConsolePage);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:consoleTestsURL]);
+  [ChromeEarlGrey loadURL:consoleTestsURL];
 
   std::string debugButtonID = base::SysNSStringToUTF8(kDebugMessageButtonId);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey
-      waitForWebStateContainingElement:
-          [ElementSelector selectorWithElementID:debugButtonID]]);
+  [ChromeEarlGrey waitForWebStateContainingElement:
+                      [ElementSelector selectorWithElementID:debugButtonID]];
 
   // Log messages.
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey tapWebStateElementInIFrameWithID:debugButtonID]);
+  [ChromeEarlGrey tapWebStateElementInIFrameWithID:debugButtonID];
 
   std::string errorButtonID = base::SysNSStringToUTF8(kErrorMessageButtonId);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey tapWebStateElementInIFrameWithID:errorButtonID]);
+  [ChromeEarlGrey tapWebStateElementInIFrameWithID:errorButtonID];
 
   std::string infoButtonID = base::SysNSStringToUTF8(kInfoMessageButtonId);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey tapWebStateElementInIFrameWithID:infoButtonID]);
+  [ChromeEarlGrey tapWebStateElementInIFrameWithID:infoButtonID];
 
   std::string logButtonID = base::SysNSStringToUTF8(kLogMessageButtonId);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey tapWebStateElementInIFrameWithID:logButtonID]);
+  [ChromeEarlGrey tapWebStateElementInIFrameWithID:logButtonID];
 
   std::string warnButtonID = base::SysNSStringToUTF8(kWarningMessageButtonId);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey tapWebStateElementInIFrameWithID:warnButtonID]);
+  [ChromeEarlGrey tapWebStateElementInIFrameWithID:warnButtonID];
 
   [ChromeEarlGrey selectTabAtIndex:0];
   // Validate messages and labels are displayed.
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kDebugMessageLabel]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kIFrameDebugMessageText]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kErrorMessageLabel]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kIFrameErrorMessageText]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kInfoMessageLabel]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kIFrameInfoMessageText]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kLogMessageLabel]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kIFrameLogMessageText]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kWarningMessageLabel]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kIFrameWarningMessageText]);
+  [ChromeEarlGrey waitForWebStateContainingText:kDebugMessageLabel];
+  [ChromeEarlGrey waitForWebStateContainingText:kIFrameDebugMessageText];
+  [ChromeEarlGrey waitForWebStateContainingText:kErrorMessageLabel];
+  [ChromeEarlGrey waitForWebStateContainingText:kIFrameErrorMessageText];
+  [ChromeEarlGrey waitForWebStateContainingText:kInfoMessageLabel];
+  [ChromeEarlGrey waitForWebStateContainingText:kIFrameInfoMessageText];
+  [ChromeEarlGrey waitForWebStateContainingText:kLogMessageLabel];
+  [ChromeEarlGrey waitForWebStateContainingText:kIFrameLogMessageText];
+  [ChromeEarlGrey waitForWebStateContainingText:kWarningMessageLabel];
+  [ChromeEarlGrey waitForWebStateContainingText:kIFrameWarningMessageText];
 }
 
 // Tests that log messages are correctly displayed from multiple tabs.
 - (void)testLoggingFromMultipleTabs {
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:GURL(kChromeUIInspectURL)]);
+  [ChromeEarlGrey loadURL:GURL(kChromeUIInspectURL)];
 
   // Start logging.
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingElement:StartLoggingButton()]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey tapWebStateElementWithID:kStartLoggingButtonId]);
+  [ChromeEarlGrey waitForWebStateContainingElement:StartLoggingButton()];
+  [ChromeEarlGrey tapWebStateElementWithID:kStartLoggingButtonId];
 
   // Open console test page.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey openNewTab]);
+  [ChromeEarlGrey openNewTab];
   const GURL consoleTestsURL = self.testServer->GetURL(kConsolePage);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:consoleTestsURL]);
+  [ChromeEarlGrey loadURL:consoleTestsURL];
   std::string logButtonID = base::SysNSStringToUTF8(kLogMessageButtonId);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey
+  [ChromeEarlGrey
       waitForWebStateContainingElement:[ElementSelector
-                                           selectorWithElementID:logButtonID]]);
+                                           selectorWithElementID:logButtonID]];
 
   // Log a message and verify it is displayed.
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey tapWebStateElementWithID:kDebugMessageButtonId]);
+  [ChromeEarlGrey tapWebStateElementWithID:kDebugMessageButtonId];
   [ChromeEarlGrey selectTabAtIndex:0];
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kDebugMessageLabel]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kDebugMessageText]);
+  [ChromeEarlGrey waitForWebStateContainingText:kDebugMessageLabel];
+  [ChromeEarlGrey waitForWebStateContainingText:kDebugMessageText];
 
   // Open console test page again.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey openNewTab]);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:consoleTestsURL]);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey
+  [ChromeEarlGrey openNewTab];
+  [ChromeEarlGrey loadURL:consoleTestsURL];
+  [ChromeEarlGrey
       waitForWebStateContainingElement:[ElementSelector
-                                           selectorWithElementID:logButtonID]]);
+                                           selectorWithElementID:logButtonID]];
 
   // Log another message and verify it is displayed.
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey tapWebStateElementWithID:kLogMessageButtonId]);
+  [ChromeEarlGrey tapWebStateElementWithID:kLogMessageButtonId];
   [ChromeEarlGrey selectTabAtIndex:0];
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kLogMessageLabel]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kLogMessageText]);
+  [ChromeEarlGrey waitForWebStateContainingText:kLogMessageLabel];
+  [ChromeEarlGrey waitForWebStateContainingText:kLogMessageText];
 
   // Ensure the log from the first tab still exists.
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kDebugMessageLabel]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kDebugMessageText]);
+  [ChromeEarlGrey waitForWebStateContainingText:kDebugMessageLabel];
+  [ChromeEarlGrey waitForWebStateContainingText:kDebugMessageText];
 }
 
 // Tests that messages are cleared after stopping logging.
 - (void)testMessagesClearedOnStopLogging {
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:GURL(kChromeUIInspectURL)]);
+  [ChromeEarlGrey loadURL:GURL(kChromeUIInspectURL)];
 
   // Start logging.
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingElement:StartLoggingButton()]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey tapWebStateElementWithID:kStartLoggingButtonId]);
+  [ChromeEarlGrey waitForWebStateContainingElement:StartLoggingButton()];
+  [ChromeEarlGrey tapWebStateElementWithID:kStartLoggingButtonId];
 
   // Open console test page.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey openNewTab]);
+  [ChromeEarlGrey openNewTab];
   const GURL consoleTestsURL = self.testServer->GetURL(kConsolePage);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:consoleTestsURL]);
+  [ChromeEarlGrey loadURL:consoleTestsURL];
   std::string logButtonID = base::SysNSStringToUTF8(kLogMessageButtonId);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey
+  [ChromeEarlGrey
       waitForWebStateContainingElement:[ElementSelector
-                                           selectorWithElementID:logButtonID]]);
+                                           selectorWithElementID:logButtonID]];
 
   // Log a message and verify it is displayed.
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey tapWebStateElementWithID:kDebugMessageButtonId]);
+  [ChromeEarlGrey tapWebStateElementWithID:kDebugMessageButtonId];
   [ChromeEarlGrey selectTabAtIndex:0];
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kDebugMessageLabel]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kDebugMessageText]);
+  [ChromeEarlGrey waitForWebStateContainingText:kDebugMessageLabel];
+  [ChromeEarlGrey waitForWebStateContainingText:kDebugMessageText];
 
   // Stop logging.
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey tapWebStateElementWithID:kStopLoggingButtonId]);
+  [ChromeEarlGrey tapWebStateElementWithID:kStopLoggingButtonId];
   // Ensure message was cleared.
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateNotContainingText:kDebugMessageLabel]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateNotContainingText:kDebugMessageText]);
+  [ChromeEarlGrey waitForWebStateNotContainingText:kDebugMessageLabel];
+  [ChromeEarlGrey waitForWebStateNotContainingText:kDebugMessageText];
 }
 
 // Tests that messages are cleared after a page reload.
 - (void)testMessagesClearedOnReload {
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:GURL(kChromeUIInspectURL)]);
+  [ChromeEarlGrey loadURL:GURL(kChromeUIInspectURL)];
 
   // Start logging.
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingElement:StartLoggingButton()]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey tapWebStateElementWithID:kStartLoggingButtonId]);
+  [ChromeEarlGrey waitForWebStateContainingElement:StartLoggingButton()];
+  [ChromeEarlGrey tapWebStateElementWithID:kStartLoggingButtonId];
 
   // Open console test page.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey openNewTab]);
+  [ChromeEarlGrey openNewTab];
   const GURL consoleTestsURL = self.testServer->GetURL(kConsolePage);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:consoleTestsURL]);
+  [ChromeEarlGrey loadURL:consoleTestsURL];
   std::string logButtonID = base::SysNSStringToUTF8(kLogMessageButtonId);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey
+  [ChromeEarlGrey
       waitForWebStateContainingElement:[ElementSelector
-                                           selectorWithElementID:logButtonID]]);
+                                           selectorWithElementID:logButtonID]];
 
   // Log a message and verify it is displayed.
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey tapWebStateElementWithID:kDebugMessageButtonId]);
+  [ChromeEarlGrey tapWebStateElementWithID:kDebugMessageButtonId];
   [ChromeEarlGrey selectTabAtIndex:0];
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kDebugMessageLabel]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kDebugMessageText]);
+  [ChromeEarlGrey waitForWebStateContainingText:kDebugMessageLabel];
+  [ChromeEarlGrey waitForWebStateContainingText:kDebugMessageText];
 
   // Reload page.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey reload]);
+  [ChromeEarlGrey reload];
   // Ensure message was cleared.
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateNotContainingText:kDebugMessageLabel]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateNotContainingText:kDebugMessageText]);
+  [ChromeEarlGrey waitForWebStateNotContainingText:kDebugMessageLabel];
+  [ChromeEarlGrey waitForWebStateNotContainingText:kDebugMessageText];
 }
 
 // Tests that messages are cleared for a tab which is closed.
 - (void)testMessagesClearedOnTabClosure {
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:GURL(kChromeUIInspectURL)]);
+  [ChromeEarlGrey loadURL:GURL(kChromeUIInspectURL)];
 
   // Start logging.
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingElement:StartLoggingButton()]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey tapWebStateElementWithID:kStartLoggingButtonId]);
+  [ChromeEarlGrey waitForWebStateContainingElement:StartLoggingButton()];
+  [ChromeEarlGrey tapWebStateElementWithID:kStartLoggingButtonId];
 
   // Open console test page.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey openNewTab]);
+  [ChromeEarlGrey openNewTab];
   const GURL consoleTestsURL = self.testServer->GetURL(kConsolePage);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:consoleTestsURL]);
+  [ChromeEarlGrey loadURL:consoleTestsURL];
   std::string debugButtonID = base::SysNSStringToUTF8(kDebugMessageButtonId);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey
-      waitForWebStateContainingElement:
-          [ElementSelector selectorWithElementID:debugButtonID]]);
+  [ChromeEarlGrey waitForWebStateContainingElement:
+                      [ElementSelector selectorWithElementID:debugButtonID]];
 
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey tapWebStateElementWithID:kDebugMessageButtonId]);
+  [ChromeEarlGrey tapWebStateElementWithID:kDebugMessageButtonId];
   [ChromeEarlGrey closeCurrentTab];
 
   // Validate message and label are not displayed.
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateNotContainingText:kDebugMessageLabel]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateNotContainingText:kDebugMessageText]);
+  [ChromeEarlGrey waitForWebStateNotContainingText:kDebugMessageLabel];
+  [ChromeEarlGrey waitForWebStateNotContainingText:kDebugMessageText];
 }
 
 @end
diff --git a/ios/chrome/browser/ui/webui/web_ui_egtest.mm b/ios/chrome/browser/ui/webui/web_ui_egtest.mm
index e4c5525..e7af7e6 100644
--- a/ios/chrome/browser/ui/webui/web_ui_egtest.mm
+++ b/ios/chrome/browser/ui/webui/web_ui_egtest.mm
@@ -15,7 +15,6 @@
 #import "ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
-#import "ios/chrome/test/earl_grey/chrome_error_util.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #import "ios/web/public/web_client.h"
@@ -35,7 +34,7 @@
 // Loads WebUI page with given |host|.
 void LoadWebUIUrl(const std::string& host) {
   GURL web_ui_url(url::SchemeHostPort(kChromeUIScheme, host, 0).Serialize());
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:web_ui_url]);
+  [ChromeEarlGrey loadURL:web_ui_url];
 }
 
 // Adds wait for omnibox text matcher so that omnibox text can be updated.
@@ -84,14 +83,12 @@
 
   // Verify that app version is present on the page.
   const std::string version = version_info::GetVersionNumber();
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:version]);
+  [ChromeEarlGrey waitForWebStateContainingText:version];
 
   // Verify that mobile User Agent string is present on the page.
   const std::string userAgent =
       web::GetWebClient()->GetUserAgent(web::UserAgentType::MOBILE);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:userAgent]);
+  [ChromeEarlGrey waitForWebStateContainingText:userAgent];
 }
 
 // Tests that clicking on a chrome://terms link from chrome://chrome-urls
@@ -100,16 +97,15 @@
   LoadWebUIUrl(kChromeUIChromeURLsHost);
 
   // Tap on chrome://terms link on the page.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey
+  [ChromeEarlGrey
       tapWebStateElementWithID:[NSString
-                                   stringWithUTF8String:kChromeUITermsHost]]);
+                                   stringWithUTF8String:kChromeUITermsHost]];
 
   // Verify that the resulting page is chrome://terms.
   [[EarlGrey selectElementWithMatcher:WaitForOmniboxText("chrome://terms")]
       assertWithMatcher:grey_notNil()];
   const std::string kTermsText = "Google Chrome Terms of Service";
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kTermsText]);
+  [ChromeEarlGrey waitForWebStateContainingText:kTermsText];
 }
 
 // Tests that back navigation functions properly after navigation via anchor
@@ -118,15 +114,14 @@
   LoadWebUIUrl(kChromeUIChromeURLsHost);
 
   // Tap on chrome://version link on the page.
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey
+  [ChromeEarlGrey
       tapWebStateElementWithID:[NSString
-                                   stringWithUTF8String:kChromeUIVersionHost]]);
+                                   stringWithUTF8String:kChromeUIVersionHost]];
 
   // Verify that the resulting page is chrome://version.
   [[EarlGrey selectElementWithMatcher:WaitForOmniboxText("chrome://version")]
       assertWithMatcher:grey_notNil()];
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:"The Chromium Authors"]);
+  [ChromeEarlGrey waitForWebStateContainingText:"The Chromium Authors"];
 
   // Tap the back button in the toolbar and verify that the resulting page is
   // the previously visited page chrome://chrome-urls.
@@ -134,8 +129,7 @@
   [[EarlGrey
       selectElementWithMatcher:WaitForOmniboxText("chrome://chrome-urls")]
       assertWithMatcher:grey_notNil()];
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:"List of Chrome URLs"]);
+  [ChromeEarlGrey waitForWebStateContainingText:"List of Chrome URLs"];
 }
 
 // Tests that back and forward navigation between chrome URLs functions
@@ -163,8 +157,8 @@
   // Tap the back button in the toolbar then reload, and verify that the
   // resulting page corresponds to the first URL.
   [[EarlGrey selectElementWithMatcher:BackButton()] performAction:grey_tap()];
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey waitForPageToFinishLoading]);
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey reload]);
+  [ChromeEarlGrey waitForPageToFinishLoading];
+  [ChromeEarlGrey reload];
   [[EarlGrey selectElementWithMatcher:WaitForOmniboxText("chrome://version")]
       assertWithMatcher:grey_notNil()];
 
@@ -197,14 +191,13 @@
 - (void)testChromeURLInvalid {
   // Navigate to the native error page chrome://invalidchromeurl.
   const std::string kChromeInvalidURL = "chrome://invalidchromeurl";
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:GURL(kChromeInvalidURL)]);
+  [ChromeEarlGrey loadURL:GURL(kChromeInvalidURL)];
 
   // Verify that the resulting page is an error page.
   [[EarlGrey selectElementWithMatcher:WaitForOmniboxText(kChromeInvalidURL)]
       assertWithMatcher:grey_notNil()];
   std::string errorMessage = net::ErrorToShortString(net::ERR_INVALID_URL);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:errorMessage]);
+  [ChromeEarlGrey waitForWebStateContainingText:errorMessage];
 }
 
 // Tests that repeated back/forward navigation from web URL is allowed.
@@ -220,29 +213,24 @@
   LoadWebUIUrl(kChromeUIVersionHost);
   [[EarlGrey selectElementWithMatcher:WaitForOmniboxText(kChromeVersionURL)]
       assertWithMatcher:grey_notNil()];
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kChromeVersionWebText]);
+  [ChromeEarlGrey waitForWebStateContainingText:kChromeVersionWebText];
 
   GURL webURL = self.testServer->GetURL("/pony.html");
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey loadURL:webURL]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kWebPageText]);
+  [ChromeEarlGrey loadURL:webURL];
+  [ChromeEarlGrey waitForWebStateContainingText:kWebPageText];
 
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey goBack]);
+  [ChromeEarlGrey goBack];
   [[EarlGrey selectElementWithMatcher:WaitForOmniboxText(kChromeVersionURL)]
       assertWithMatcher:grey_notNil()];
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kChromeVersionWebText]);
+  [ChromeEarlGrey waitForWebStateContainingText:kChromeVersionWebText];
 
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey goForward]);
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kWebPageText]);
+  [ChromeEarlGrey goForward];
+  [ChromeEarlGrey waitForWebStateContainingText:kWebPageText];
 
-  CHROME_EG_ASSERT_NO_ERROR([ChromeEarlGrey goBack]);
+  [ChromeEarlGrey goBack];
   [[EarlGrey selectElementWithMatcher:WaitForOmniboxText(kChromeVersionURL)]
       assertWithMatcher:grey_notNil()];
-  CHROME_EG_ASSERT_NO_ERROR(
-      [ChromeEarlGrey waitForWebStateContainingText:kChromeVersionWebText]);
+  [ChromeEarlGrey waitForWebStateContainingText:kChromeVersionWebText];
 }
 
 @end
diff --git a/ios/chrome/test/DEPS b/ios/chrome/test/DEPS
index fca057ff..764eb24 100644
--- a/ios/chrome/test/DEPS
+++ b/ios/chrome/test/DEPS
@@ -16,8 +16,8 @@
   # see https://groups.google.com/a/chromium.org/d/msg/chromium-dev/dgFLuxqZt1o/iEqkyoQQBwAJ for help and info.
   "-components/signin/core/browser/fake_profile_oauth2_token_service.h",
   "-components/signin/core/browser/profile_oauth2_token_service.h",
-  "-components/signin/core/browser/signin_manager.h",
-  "-components/signin/core/browser/signin_manager_base.h",
+  "-components/signin/core/browser/primary_account_manager.h",
+  "-components/signin/core/browser/primary_account_policy_manager.h",
   "+components/sync",
   "+components/sync_device_info",
   "+components/unified_consent",
diff --git a/ios/chrome/test/wpt/BUILD.gn b/ios/chrome/test/wpt/BUILD.gn
new file mode 100644
index 0000000..5bf8186
--- /dev/null
+++ b/ios/chrome/test/wpt/BUILD.gn
@@ -0,0 +1,84 @@
+# 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.
+
+import("//build/config/ios/ios_sdk.gni")
+import("//build/config/ios/rules.gni")
+import("//ios/chrome/test/earl_grey2/chrome_ios_eg2_test.gni")
+
+group("all_tests") {
+  testonly = true
+  deps = [
+    ":ios_cwt_chromedriver_tests",
+    ":ios_cwt_chromedriver_tests_module",
+  ]
+}
+
+chrome_ios_eg2_test_app_host("ios_cwt_chromedriver_tests") {
+  deps = [
+    ":eg_app_support+eg2",
+  ]
+}
+
+chrome_ios_eg2_test("ios_cwt_chromedriver_tests_module") {
+  xcode_test_application_name = "ios_cwt_chromedriver_tests"
+
+  deps = [
+    ":cwt_chromedriver_tests",
+  ]
+}
+
+source_set("shared_helper_headers") {
+  testonly = true
+  sources = [
+    "cwt_webdriver_app_interface.h",
+  ]
+}
+
+source_set("eg_app_support+eg2") {
+  defines = [ "CHROME_EARL_GREY_2" ]
+  testonly = true
+  configs += [ "//build/config/compiler:enable_arc" ]
+
+  sources = [
+    "cwt_webdriver_app_interface.mm",
+  ]
+
+  deps = [
+    "//base",
+    "//base/test:test_support",
+    "//ios/chrome/test/app:test_support",
+    "//ios/testing:nserror_support",
+    "//ios/testing/earl_grey:eg_app_support+eg2",
+    "//ios/third_party/earl_grey2:app_framework+link",
+  ]
+
+  public_deps = [
+    ":shared_helper_headers",
+  ]
+}
+
+source_set("cwt_chromedriver_tests") {
+  defines = [ "CHROME_EARL_GREY_2" ]
+  testonly = true
+  configs += [
+    "//build/config/compiler:enable_arc",
+    "//build/config/ios:xctest_config",
+  ]
+
+  sources = [
+    "cwt_chrome_driver.mm",
+    "cwt_request_handler.h",
+    "cwt_request_handler.mm",
+  ]
+
+  deps = [
+    ":shared_helper_headers",
+    "//components/version_info:version_info",
+    "//ios/testing/earl_grey:eg_test_support+eg2",
+    "//ios/third_party/earl_grey2:test_lib",
+    "//net:test_support",
+  ]
+
+  libs = [ "UIKit.framework" ]
+}
diff --git a/ios/chrome/test/wpt/cwt_chrome_driver.mm b/ios/chrome/test/wpt/cwt_chrome_driver.mm
new file mode 100644
index 0000000..1604a6f
--- /dev/null
+++ b/ios/chrome/test/wpt/cwt_chrome_driver.mm
@@ -0,0 +1,79 @@
+// 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.
+
+#import <TestLib/EarlGreyImpl/EarlGrey.h>
+#import <UIKit/UIKit.h>
+#import <XCTest/XCTest.h>
+
+#include "base/logging.h"
+#include "base/strings/sys_string_conversions.h"
+#import "ios/chrome/test/wpt/cwt_request_handler.h"
+#import "ios/testing/earl_grey/base_earl_grey_test_case.h"
+#include "net/base/port_util.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "url/url_constants.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace {
+
+// The port that CWTChromeDriver's HTTP server listens on.
+const int kDefaultPort = 8123;
+
+}
+
+// Dummy test case that hosts CWTChromeDriver. CWTChromeDriver implements a
+// minimal subset of the WebDriver protocol needed to run most Web Platform
+// Tests. CWTChromeDriverTestCase launches a test server that listens for
+// WebDriver commands, and then uses EarlGrey2's eDistantObject protocol to pass
+// on corresponding messages to the app process. Each CWTChromeDriver launches a
+// single instance of Chrome, but mulitple instances of CWTChromeDriver can be
+// run in parallel in order to use multiple instances of Chrome.
+@interface CWTChromeDriverTestCase : BaseEarlGreyTestCase
+@end
+
+@implementation CWTChromeDriverTestCase
+
+// Dummy test that keeps the test app alive.
+- (void)testRunCWTChromeDriver {
+  int port = kDefaultPort;
+
+  NSArray* arguments = NSProcessInfo.processInfo.arguments;
+  NSUInteger index = [arguments indexOfObject:@"--port"];
+  if (index != NSNotFound && arguments.count > index + 1) {
+    NSString* portString = [arguments objectAtIndex:index + 1];
+    if (net::IsPortAllowedForScheme(portString.intValue, url::kHttpScheme))
+      port = portString.intValue;
+    else
+      LOG(ERROR) << base::SysNSStringToUTF8(portString)
+                 << " is not a valid port for http";
+  }
+
+  XCTestExpectation* dummyExpectation =
+      [self expectationWithDescription:@"dummy expectation"];
+  CWTRequestHandler requestHandler(^{
+    [dummyExpectation fulfill];
+  });
+
+  net::EmbeddedTestServer server;
+  server.RegisterRequestHandler(base::BindRepeating(
+      &CWTRequestHandler::HandleRequest, base::Unretained(&requestHandler)));
+  bool started = server.Start(port);
+  if (!started)
+    XCTFail("Unable to start web server");
+  LOG(INFO) << "CWTChromeDriver listening on port " << server.port();
+
+  // The dummy expectation will only be fulfilled once all the tests using this
+  // instance of CWTChromeDriver have run, so wait with a long timeout.
+  const NSTimeInterval kTimeoutInSeconds = 1000000;
+  [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil];
+
+  bool stopped = server.ShutdownAndWaitUntilComplete();
+  if (!stopped)
+    XCTFail("Unable to stop web server");
+}
+
+@end
diff --git a/ios/chrome/test/wpt/cwt_request_handler.h b/ios/chrome/test/wpt/cwt_request_handler.h
new file mode 100644
index 0000000..992813c
--- /dev/null
+++ b/ios/chrome/test/wpt/cwt_request_handler.h
@@ -0,0 +1,79 @@
+// 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 IOS_CHROME_TEST_WPT_CWT_REQUEST_HANDLER_H_
+#define IOS_CHROME_TEST_WPT_CWT_REQUEST_HANDLER_H_
+
+#import <Foundation/Foundation.h>
+#include <string>
+
+#include "base/ios/block_types.h"
+#include "base/macros.h"
+#include "base/optional.h"
+#include "base/values.h"
+#include "net/test/embedded_test_server/http_request.h"
+#include "net/test/embedded_test_server/http_response.h"
+
+// Implements a subset of the WebDriver protocol, for running Web Platform
+// Tests. This not intended to be a general-purpose WebDriver implementation.
+// Each CWTRequestHandler supports only a single session. Additional
+// requests to create a session while one is already active will return an
+// error response.
+//
+// See https://w3c.github.io/webdriver/ for the complete WebDriver protocol
+// specification. In addition to only implementing a subset of this protocol,
+// CWTRequestHandler only performs minimal error-checking for the sake
+// of making clients easier to debug, and otherwise assumes that the client
+// is submitting well-formed requests, and that all requests are coming from
+// a single client.
+//
+// For example, to create a session, load a URL, and then close the session, the
+// following sequence of requests can be used:
+// 1) POST /session
+// 2) POST /url (with a content body that is a JSON dictionary whose 'url'
+//    property's value is the URL to navigate to)
+// 3) DELETE /session/{session id}
+class CWTRequestHandler {
+ public:
+  // |session_completion_handler| is a block to be called when a session is
+  // closed.
+  CWTRequestHandler(ProceduralBlock sesssion_completion_handler);
+
+  // Creates responses for HTTP requests according to the WebDriver protocol.
+  std::unique_ptr<net::test_server::HttpResponse> HandleRequest(
+      const net::test_server::HttpRequest& request);
+
+ private:
+  // Creates a new session, if no session has already been created. Otherwise,
+  // return an error.
+  base::Value InitializeSession();
+
+  // Terminates the current session.
+  base::Value CloseSession();
+
+  // Navigates the current tab to the given URL, and wait for the page load to
+  // complete.
+  base::Value NavigateToUrl(const base::Value* url);
+
+  // Processes the given command, HTTP method, and request content. Returns the
+  // result of processing the command, or nullopt_t if the command is unknown.
+  base::Optional<base::Value> ProcessCommand(
+      const std::string& command,
+      net::test_server::HttpMethod http_method,
+      const std::string& request_content);
+
+  // Block that gets called when a session is terminated.
+  ProceduralBlock session_completion_handler_;
+
+  // A randomly-generated identifier created by InitializeSession().
+  std::string session_id_;
+
+  // Timeouts used when performing browser operations.
+  NSTimeInterval script_timeout_;
+  NSTimeInterval page_load_timeout_;
+
+  DISALLOW_COPY_AND_ASSIGN(CWTRequestHandler);
+};
+
+#endif  // IOS_CHROME_TEST_WPT_CWT_REQUEST_HANDLER_H_
diff --git a/ios/chrome/test/wpt/cwt_request_handler.mm b/ios/chrome/test/wpt/cwt_request_handler.mm
new file mode 100644
index 0000000..d5a6309
--- /dev/null
+++ b/ios/chrome/test/wpt/cwt_request_handler.mm
@@ -0,0 +1,218 @@
+// 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.
+
+#import "ios/chrome/test/wpt/cwt_request_handler.h"
+
+#include "base/guid.h"
+#include "base/json/json_reader.h"
+#include "base/json/json_writer.h"
+#include "base/strings/sys_string_conversions.h"
+#include "components/version_info/version_info.h"
+#import "ios/chrome/test/wpt/cwt_webdriver_app_interface.h"
+#import "ios/testing/earl_grey/earl_grey_test.h"
+#include "net/http/http_status_code.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+GREY_STUB_CLASS_IN_APP_BACKGROUND_QUEUE(CWTWebDriverAppInterface)
+
+using net::test_server::HttpRequest;
+using net::test_server::HttpResponse;
+
+namespace {
+
+const NSTimeInterval kDefaultScriptTimeout = 30;
+const NSTimeInterval kDefaultPageLoadTimeout = 300;
+
+// WebDriver commands.
+const char kWebDriverSessionCommand[] = "session";
+const char kWebDriverNavigationCommand[] = "url";
+
+// WebDriver error codes.
+const char kWebDriverInvalidArgumentError[] = "invalid argument";
+const char kWebDriverInvalidSessionError[] = "invalid session id";
+const char kWebDriverSessionCreationError[] = "session not created";
+const char kWebDriverTimeoutError[] = "timeout";
+const char kWebDriverUnknownCommandError[] = "unknown command";
+
+// WebDriver error messages. The content of each message is implementation-
+// defined, not prescribed the by the spec.
+const char kWebDriverMissingRequestMessage[] = "Missing request body";
+const char kWebDriverMissingURLMessage[] = "No url argument";
+const char kWebDriverNoActiveSessionMessage[] = "No currently active session";
+const char kWebDriverPageLoadTimeoutMessage[] = "Page load timed out";
+const char kWebDriverSessionAlreadyExistsMessage[] = "A session already exists";
+const char kWebDriverUnknownCommandMessage[] = "No such command";
+
+// WebDriver request field names. These are fields that are contained within
+// the body of a POST request.
+const char kWebDriverURLRequestField[] = "url";
+
+// WebDriver response field name. This is the top-level field in the JSON object
+// contained in a response.
+const char kWebDriverValueResponseField[] = "value";
+
+// WebDriver value field names. These fields are contained within the 'value'
+// field in a WebDriver reponse. Each response value has zero or more of these
+// fields.
+const char kWebDriverCapabilitiesValueField[] = "capabilities";
+const char kWebDriverErrorCodeValueField[] = "error";
+const char kWebDriverErrorMessageValueField[] = "message";
+const char kWebDriverSessionIdValueField[] = "sessionId";
+
+// Field names for the "capabilities" struct that's included in the response
+// when creating a session.
+const char kCapabilitiesBrowserNameField[] = "browserName";
+const char kCapabilitiesBrowserVersionField[] = "browserVersion";
+const char kCapabilitiesPlatformNameField[] = "platformName";
+const char kCapabilitiesPageLoadStrategyField[] = "pageLoadStrategy";
+const char kCapabilitiesProxyField[] = "proxy";
+const char kCapabilitiesScriptTimeoutField[] = "timeouts.script";
+const char kCapabilitiesPageLoadTimeoutField[] = "timeouts.pageLoad";
+const char kCapabilitiesImplicitTimeoutField[] = "timeouts.implicit";
+const char kCapabilitiesCanResizeWindowsField[] = "setWindowRect";
+
+// Field values for the "capabilities" struct that's included in the response
+// when creating a session.
+const char kCapabilitiesBrowserName[] = "chrome_ios";
+const char kCapabilitiesPlatformName[] = "iOS";
+const char kCapabilitiesPageLoadStrategy[] = "normal";
+
+base::Value CreateErrorValue(const std::string& error,
+                             const std::string& message) {
+  base::Value error_value(base::Value::Type::DICTIONARY);
+  error_value.SetStringKey(kWebDriverErrorCodeValueField, error);
+  error_value.SetStringKey(kWebDriverErrorMessageValueField, message);
+  return error_value;
+}
+
+bool IsErrorValue(const base::Value& value) {
+  return value.is_dict() && value.FindKey(kWebDriverErrorCodeValueField);
+}
+
+}  // namespace
+
+CWTRequestHandler::CWTRequestHandler(ProceduralBlock session_completion_handler)
+    : session_completion_handler_(session_completion_handler),
+      script_timeout_(kDefaultScriptTimeout),
+      page_load_timeout_(kDefaultPageLoadTimeout) {}
+
+base::Optional<base::Value> CWTRequestHandler::ProcessCommand(
+    const std::string& command,
+    net::test_server::HttpMethod http_method,
+    const std::string& request_content) {
+  if (http_method == net::test_server::METHOD_POST) {
+    base::Optional<base::Value> content =
+        base::JSONReader::Read(request_content);
+    if (!content || !content->is_dict()) {
+      return CreateErrorValue(kWebDriverInvalidArgumentError,
+                              kWebDriverMissingRequestMessage);
+    }
+
+    if (command == kWebDriverSessionCommand)
+      return InitializeSession();
+
+    if (session_id_.empty()) {
+      return CreateErrorValue(kWebDriverInvalidSessionError,
+                              kWebDriverNoActiveSessionMessage);
+    }
+
+    if (command == kWebDriverNavigationCommand)
+      return NavigateToUrl(content->FindKey(kWebDriverURLRequestField));
+
+    return base::nullopt;
+  }
+
+  if (http_method == net::test_server::METHOD_DELETE) {
+    if (!session_id_.empty() && command == session_id_)
+      return CloseSession();
+
+    return base::nullopt;
+  }
+
+  return base::nullopt;
+}
+
+std::unique_ptr<net::test_server::HttpResponse>
+CWTRequestHandler::HandleRequest(const net::test_server::HttpRequest& request) {
+  std::string command = request.GetURL().ExtractFileName();
+  base::Optional<base::Value> result =
+      ProcessCommand(command, request.method, request.content);
+
+  auto response = std::make_unique<net::test_server::BasicHttpResponse>();
+  response->set_content_type("application/json; charset=utf-8");
+  response->AddCustomHeader("Cache-Control", "no-cache");
+  if (!result) {
+    response->set_code(net::HTTP_NOT_FOUND);
+    result = CreateErrorValue(kWebDriverUnknownCommandError,
+                              kWebDriverUnknownCommandMessage);
+  } else if (IsErrorValue(*result)) {
+    response->set_code(net::HTTP_INTERNAL_SERVER_ERROR);
+  } else {
+    response->set_code(net::HTTP_OK);
+  }
+
+  base::Value response_content(base::Value::Type::DICTIONARY);
+  response_content.SetKey(kWebDriverValueResponseField, std::move(*result));
+  std::string response_content_string;
+  base::JSONWriter::Write(response_content, &response_content_string);
+  response->set_content(response_content_string);
+
+  return std::move(response);
+}
+
+base::Value CWTRequestHandler::InitializeSession() {
+  if (!session_id_.empty()) {
+    return CreateErrorValue(kWebDriverSessionCreationError,
+                            kWebDriverSessionAlreadyExistsMessage);
+  }
+  base::Value result(base::Value::Type::DICTIONARY);
+  session_id_ = base::GenerateGUID();
+  result.SetStringKey(kWebDriverSessionIdValueField, session_id_);
+
+  base::Value capabilities(base::Value::Type::DICTIONARY);
+  capabilities.SetStringKey(kCapabilitiesBrowserNameField,
+                            kCapabilitiesBrowserName);
+  capabilities.SetStringKey(kCapabilitiesBrowserVersionField,
+                            version_info::GetVersionNumber());
+  capabilities.SetStringKey(kCapabilitiesPlatformNameField,
+                            kCapabilitiesPlatformName);
+  capabilities.SetStringKey(kCapabilitiesPageLoadStrategyField,
+                            kCapabilitiesPageLoadStrategy);
+  capabilities.SetKey(kCapabilitiesProxyField,
+                      base::Value(base::Value::Type::DICTIONARY));
+  capabilities.SetIntPath(kCapabilitiesScriptTimeoutField,
+                          script_timeout_ * 1000);
+  capabilities.SetIntPath(kCapabilitiesPageLoadTimeoutField,
+                          page_load_timeout_ * 1000);
+  capabilities.SetIntPath(kCapabilitiesImplicitTimeoutField, 0);
+  capabilities.SetKey(kCapabilitiesCanResizeWindowsField, base::Value(false));
+
+  result.SetKey(kWebDriverCapabilitiesValueField, std::move(capabilities));
+  return result;
+}
+
+base::Value CWTRequestHandler::CloseSession() {
+  session_id_.clear();
+  session_completion_handler_();
+  return base::Value(base::Value::Type::NONE);
+}
+
+base::Value CWTRequestHandler::NavigateToUrl(const base::Value* url) {
+  if (!url || !url->is_string()) {
+    return CreateErrorValue(kWebDriverInvalidArgumentError,
+                            kWebDriverMissingURLMessage);
+  }
+
+  NSError* error = [CWTWebDriverAppInterface
+               loadURL:base::SysUTF8ToNSString(url->GetString())
+      timeoutInSeconds:page_load_timeout_];
+  if (!error)
+    return base::Value(base::Value::Type::NONE);
+
+  return CreateErrorValue(kWebDriverTimeoutError,
+                          kWebDriverPageLoadTimeoutMessage);
+}
diff --git a/ios/chrome/test/wpt/cwt_webdriver_app_interface.h b/ios/chrome/test/wpt/cwt_webdriver_app_interface.h
new file mode 100644
index 0000000..54fe3f90
--- /dev/null
+++ b/ios/chrome/test/wpt/cwt_webdriver_app_interface.h
@@ -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.
+
+#ifndef IOS_CHROME_TEST_WPT_CWT_WEBDRIVER_APP_INTERFACE_H_
+#define IOS_CHROME_TEST_WPT_CWT_WEBDRIVER_APP_INTERFACE_H_
+
+#import <Foundation/Foundation.h>
+
+// Methods used by CWTRequestHandler to perform browser-level actions such as
+// opening and closing tabs, navigating to a URL, and injecting JavaScript.
+// These methods run on a background thread in the app process in order to
+// avoid deadlock while waiting for actions to complete on the main thread.
+@interface CWTWebDriverAppInterface : NSObject
+
+// Loads the given URL in the current tab. Returns true if the load completes
+// within |timeout| seconds, and false otherwise.
++ (NSError*)loadURL:(NSString*)URL timeoutInSeconds:(NSTimeInterval)timeout;
+
+@end
+
+#endif  // IOS_CHROME_TEST_WPT_CWT_WEBDRIVER_APP_INTERFACE_H_
diff --git a/ios/chrome/test/wpt/cwt_webdriver_app_interface.mm b/ios/chrome/test/wpt/cwt_webdriver_app_interface.mm
new file mode 100644
index 0000000..2164d097
--- /dev/null
+++ b/ios/chrome/test/wpt/cwt_webdriver_app_interface.mm
@@ -0,0 +1,41 @@
+// 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.
+
+#import "ios/chrome/test/wpt/cwt_webdriver_app_interface.h"
+
+#include "base/strings/sys_string_conversions.h"
+#import "base/test/ios/wait_util.h"
+#import "ios/chrome/test/app/chrome_test_util.h"
+#import "ios/chrome/test/app/navigation_test_util.h"
+#import "ios/testing/earl_grey/earl_grey_app.h"
+#import "ios/testing/nserror_util.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+using base::test::ios::WaitUntilConditionOrTimeout;
+
+@implementation CWTWebDriverAppInterface
+
++ (NSError*)loadURL:(NSString*)URL timeoutInSeconds:(NSTimeInterval)timeout {
+  grey_dispatch_sync_on_main_thread(^{
+    chrome_test_util::LoadUrl(GURL(base::SysNSStringToUTF8(URL)));
+  });
+
+  bool success = WaitUntilConditionOrTimeout(timeout, ^bool {
+    __block BOOL isLoading = NO;
+    grey_dispatch_sync_on_main_thread(^{
+      isLoading = chrome_test_util::GetCurrentWebState()->IsLoading();
+    });
+    return !isLoading;
+  });
+
+  if (success)
+    return nil;
+
+  return testing::NSErrorWithLocalizedDescription(@"Page load timed out");
+}
+
+@end
diff --git a/ios/net/cookies/cookie_store_ios_persistent_unittest.mm b/ios/net/cookies/cookie_store_ios_persistent_unittest.mm
index ad12e14ac..3b0a543 100644
--- a/ios/net/cookies/cookie_store_ios_persistent_unittest.mm
+++ b/ios/net/cookies/cookie_store_ios_persistent_unittest.mm
@@ -11,8 +11,8 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
 #import "ios/net/cookies/cookie_store_ios_test_util.h"
 #include "net/cookies/canonical_cookie_test_helpers.h"
 #include "net/cookies/cookie_store_change_unittest.h"
@@ -53,7 +53,7 @@
   static const int enforces_prefixes = true;
   static const bool enforce_strict_secure = false;
 
-  base::MessageLoop loop_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
 };
 
 INSTANTIATE_TYPED_TEST_SUITE_P(PersistentCookieStoreIOS,
@@ -110,7 +110,7 @@
   const GURL kTestCookieURL;
 
  protected:
-  base::MessageLoop loop_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
   ScopedTestingCookieStoreIOSClient scoped_cookie_store_ios_client_;
   scoped_refptr<net::TestPersistentCookieStore> backend_;
   std::unique_ptr<net::CookieStoreIOS> store_;
diff --git a/ios/net/cookies/cookie_store_ios_unittest.mm b/ios/net/cookies/cookie_store_ios_unittest.mm
index bd9cfc42..cc3c2bd8 100644
--- a/ios/net/cookies/cookie_store_ios_unittest.mm
+++ b/ios/net/cookies/cookie_store_ios_unittest.mm
@@ -11,10 +11,10 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/test/bind_test_util.h"
+#include "base/test/scoped_task_environment.h"
 #include "ios/net/cookies/cookie_store_ios_client.h"
 #import "ios/net/cookies/cookie_store_ios_test_util.h"
 #import "ios/net/cookies/ns_http_system_cookie_store.h"
@@ -68,7 +68,7 @@
   static const bool has_exact_change_ordering = false;
   static const int creation_time_granularity_in_ms = 1000;
 
-  base::MessageLoop loop_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
 };
 
 INSTANTIATE_TYPED_TEST_SUITE_P(CookieStoreIOS,
@@ -195,7 +195,7 @@
   const GURL kTestCookieURLFoo;
   const GURL kTestCookieURLBarBar;
 
-  base::MessageLoop loop_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
   ScopedTestingCookieStoreIOSClient scoped_cookie_store_ios_client_;
   scoped_refptr<TestPersistentCookieStore> backend_;
   // |system_store_| will point to the NSHTTPSystemCookieStore object owned by
diff --git a/ios/net/cookies/ns_http_system_cookie_store_unittest.mm b/ios/net/cookies/ns_http_system_cookie_store_unittest.mm
index 3015a0f5..5297239 100644
--- a/ios/net/cookies/ns_http_system_cookie_store_unittest.mm
+++ b/ios/net/cookies/ns_http_system_cookie_store_unittest.mm
@@ -8,7 +8,7 @@
 
 #include <memory>
 
-#include "base/message_loop/message_loop.h"
+#include "base/test/scoped_task_environment.h"
 #include "ios/net/cookies/system_cookie_store_unittest_template.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
@@ -55,7 +55,7 @@
   SystemCookieStore* GetCookieStore() { return store_.get(); }
 
  private:
-  base::MessageLoop loop;
+  base::test::ScopedTaskEnvironment scoped_task_environment;
   ScopedTestingCookieStoreIOSClient scoped_cookie_store_ios_client_;
   NSHTTPCookieStorage* shared_store_;
   std::unique_ptr<net::NSHTTPSystemCookieStore> store_;
diff --git a/ios/net/protocol_handler_util_unittest.mm b/ios/net/protocol_handler_util_unittest.mm
index 8851be6..fa2d5df 100644
--- a/ios/net/protocol_handler_util_unittest.mm
+++ b/ios/net/protocol_handler_util_unittest.mm
@@ -8,9 +8,9 @@
 #include <utility>
 
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/sys_string_conversions.h"
+#include "base/test/scoped_task_environment.h"
 #include "net/base/elements_upload_data_stream.h"
 #import "net/base/mac/url_conversions.h"
 #include "net/base/upload_bytes_element_reader.h"
@@ -154,7 +154,7 @@
   void OnReadCompleted(URLRequest* request, int bytes_read) override {}
 
  protected:
-  base::MessageLoop loop_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
   URLRequestJobFactoryImpl job_factory_;
   std::unique_ptr<URLRequestContext> request_context_;
 };
diff --git a/ios/web_view/internal/DEPS b/ios/web_view/internal/DEPS
index 3a64c6e..8c4977435f 100644
--- a/ios/web_view/internal/DEPS
+++ b/ios/web_view/internal/DEPS
@@ -24,7 +24,7 @@
   # Use identity_manager.h instead of the below files;
   # see https://groups.google.com/a/chromium.org/d/msg/chromium-dev/dgFLuxqZt1o/iEqkyoQQBwAJ for help and info.
   "!components/signin/core/browser/fake_profile_oauth2_token_service.h",
-  "!components/signin/core/browser/signin_manager_base.h",
+  "!components/signin/core/browser/primary_account_manager.h",
   "+components/signin/ios",
   "+components/ssl_errors",
   "+components/strings/grit",
diff --git a/ios/web_view/internal/signin/web_view_identity_manager_factory.mm b/ios/web_view/internal/signin/web_view_identity_manager_factory.mm
index 965252a..f0bc6774 100644
--- a/ios/web_view/internal/signin/web_view_identity_manager_factory.mm
+++ b/ios/web_view/internal/signin/web_view_identity_manager_factory.mm
@@ -14,8 +14,8 @@
 #include "components/signin/core/browser/account_consistency_method.h"
 #include "components/signin/core/browser/gaia_cookie_manager_service.h"
 #include "components/signin/core/browser/identity_manager_wrapper.h"
+#include "components/signin/core/browser/primary_account_policy_manager.h"
 #include "components/signin/core/browser/profile_oauth2_token_service.h"
-#include "components/signin/core/browser/signin_manager.h"
 #include "components/signin/core/browser/signin_pref_names.h"
 #include "components/signin/ios/browser/profile_oauth2_token_service_ios_delegate.h"
 #include "ios/web_view/internal/app/application_context.h"
@@ -71,7 +71,7 @@
   return account_fetcher_service;
 }
 
-std::unique_ptr<SigninManagerBase> BuildSigninManager(
+std::unique_ptr<PrimaryAccountManager> BuildPrimaryAccountManager(
     WebViewBrowserState* browser_state,
     AccountTrackerService* account_tracker_service,
     ProfileOAuth2TokenService* token_service) {
@@ -82,10 +82,11 @@
   pref_service->ClearPref(prefs::kGoogleServicesUsername);
   pref_service->ClearPref(prefs::kGoogleServicesUserAccountId);
 
-  std::unique_ptr<SigninManager> service = std::make_unique<SigninManager>(
-      WebViewSigninClientFactory::GetForBrowserState(browser_state),
-      token_service, account_tracker_service,
-      signin::AccountConsistencyMethod::kDisabled);
+  std::unique_ptr<PrimaryAccountPolicyManager> service =
+      std::make_unique<PrimaryAccountPolicyManager>(
+          WebViewSigninClientFactory::GetForBrowserState(browser_state),
+          token_service, account_tracker_service,
+          signin::AccountConsistencyMethod::kDisabled);
   service->Initialize(ApplicationContext::GetInstance()->GetLocalState());
   return service;
 }
@@ -141,12 +142,13 @@
       token_service.get(),
       WebViewSigninClientFactory::GetForBrowserState(browser_state));
 
-  std::unique_ptr<SigninManagerBase> signin_manager = BuildSigninManager(
-      browser_state, account_tracker_service.get(), token_service.get());
+  std::unique_ptr<PrimaryAccountManager> primary_account_manager =
+      BuildPrimaryAccountManager(browser_state, account_tracker_service.get(),
+                                 token_service.get());
 
   auto primary_account_mutator =
       std::make_unique<identity::PrimaryAccountMutatorImpl>(
-          account_tracker_service.get(), signin_manager.get(),
+          account_tracker_service.get(), primary_account_manager.get(),
           browser_state->GetPrefs());
 
   auto accounts_cookie_mutator =
@@ -164,8 +166,9 @@
 
   return std::make_unique<IdentityManagerWrapper>(
       std::move(account_tracker_service), std::move(token_service),
-      std::move(gaia_cookie_manager_service), std::move(signin_manager),
-      std::move(account_fetcher_service), std::move(primary_account_mutator),
+      std::move(gaia_cookie_manager_service),
+      std::move(primary_account_manager), std::move(account_fetcher_service),
+      std::move(primary_account_mutator),
       /*accounts_mutator=*/nullptr, std::move(accounts_cookie_mutator),
       std::move(diagnostics_provider));
 }
diff --git a/media/audio/audio_features.cc b/media/audio/audio_features.cc
index e5fdc299..a36d1fc 100644
--- a/media/audio/audio_features.cc
+++ b/media/audio/audio_features.cc
@@ -28,4 +28,8 @@
                                           base::FEATURE_DISABLED_BY_DEFAULT};
 #endif
 
+#if defined(OS_WIN)
+const base::Feature kAllowIAudioClient3{"AllowIAudioClient3",
+                                        base::FEATURE_ENABLED_BY_DEFAULT};
+#endif
 }  // namespace features
diff --git a/media/audio/audio_features.h b/media/audio/audio_features.h
index 70e228d..b219d86 100644
--- a/media/audio/audio_features.h
+++ b/media/audio/audio_features.h
@@ -23,6 +23,10 @@
 MEDIA_EXPORT extern const base::Feature kForceEnableSystemAec;
 #endif
 
+#if defined(OS_WIN)
+MEDIA_EXPORT extern const base::Feature kAllowIAudioClient3;
+#endif
+
 }  // namespace features
 
 #endif  // MEDIA_AUDIO_AUDIO_FEATURES_H_
diff --git a/media/audio/win/core_audio_util_win.cc b/media/audio/win/core_audio_util_win.cc
index addae7d..04ab5e3 100644
--- a/media/audio/win/core_audio_util_win.cc
+++ b/media/audio/win/core_audio_util_win.cc
@@ -24,6 +24,7 @@
 #include "base/win/scoped_variant.h"
 #include "base/win/windows_version.h"
 #include "media/audio/audio_device_description.h"
+#include "media/audio/audio_features.h"
 #include "media/base/media_switches.h"
 
 using Microsoft::WRL::ComPtr;
@@ -313,7 +314,8 @@
 }
 
 bool IAudioClient3IsSupported() {
-  return CoreAudioUtil::GetIAudioClientVersion() >= 3;
+  return base::FeatureList::IsEnabled(features::kAllowIAudioClient3) &&
+         CoreAudioUtil::GetIAudioClientVersion() >= 3;
 }
 
 std::string GetDeviceID(IMMDevice* device) {
diff --git a/mojo/public/tools/bindings/chromium_bindings_configuration.gni b/mojo/public/tools/bindings/chromium_bindings_configuration.gni
index c135fed..451cc99 100644
--- a/mojo/public/tools/bindings/chromium_bindings_configuration.gni
+++ b/mojo/public/tools/bindings/chromium_bindings_configuration.gni
@@ -3,7 +3,6 @@
 # found in the LICENSE file.
 
 _typemap_imports = [
-  "//ash/public/interfaces/typemaps.gni",
   "//chrome/chrome_cleaner/interfaces/typemaps/typemaps.gni",
   "//chrome/common/importer/typemaps.gni",
   "//chrome/common/media_router/mojo/typemaps.gni",
diff --git a/net/base/features.cc b/net/base/features.cc
index 502fdeac..2061f27 100644
--- a/net/base/features.cc
+++ b/net/base/features.cc
@@ -7,8 +7,6 @@
 namespace net {
 namespace features {
 
-// Toggles the `Accept-Language` HTTP request header, which
-// https://github.com/WICG/lang-client-hint proposes that we deprecate.
 const base::Feature kAcceptLanguageHeader{"AcceptLanguageHeader",
                                           base::FEATURE_ENABLED_BY_DEFAULT};
 
@@ -17,18 +15,6 @@
 const base::FeatureParam<int> kMaxRefererHeaderLength = {
     &kCapRefererHeaderLength, "MaxRefererHeaderLength", 4096};
 
-// Uses a site isolated code cache that is keyed on the resource url and the
-// origin lock of the renderer that is requesting the resource. The requests
-// to site-isolated code cache are handled by the content/GeneratedCodeCache
-// When this flag is enabled, the metadata field of the HttpCache is unused.
-const base::Feature kIsolatedCodeCache = {"IsolatedCodeCache",
-                                          base::FEATURE_ENABLED_BY_DEFAULT};
-
-// Enables the additional TLS 1.3 server-random-based downgrade protection
-// described in https://tools.ietf.org/html/rfc8446#section-4.1.3
-//
-// This is a MUST-level requirement of TLS 1.3, but has compatibility issues
-// with some buggy non-compliant TLS-terminating proxies.
 const base::Feature kEnforceTLS13Downgrade{"EnforceTLS13Downgrade",
                                            base::FEATURE_ENABLED_BY_DEFAULT};
 
diff --git a/net/base/features.h b/net/base/features.h
index 00856023..d2e39d71 100644
--- a/net/base/features.h
+++ b/net/base/features.h
@@ -21,12 +21,6 @@
 NET_EXPORT extern const base::Feature kCapRefererHeaderLength;
 NET_EXPORT extern const base::FeatureParam<int> kMaxRefererHeaderLength;
 
-// Uses a site isolated code cache that is keyed on the resource url and the
-// origin lock of the renderer that is requesting the resource. The requests
-// to site-isolated code cache are handled by the content/GeneratedCodeCache
-// When this flag is enabled, the metadata field of the HttpCache is unused.
-NET_EXPORT extern const base::Feature kIsolatedCodeCache;
-
 // Enables the additional TLS 1.3 server-random-based downgrade protection
 // described in https://tools.ietf.org/html/rfc8446#section-4.1.3
 //
diff --git a/net/http/http_cache.cc b/net/http/http_cache.cc
index d7997e50..acd5cf8 100644
--- a/net/http/http_cache.cc
+++ b/net/http/http_cache.cc
@@ -232,94 +232,6 @@
 
 //-----------------------------------------------------------------------------
 
-// This class encapsulates a transaction whose only purpose is to write metadata
-// to a given entry.
-class HttpCache::MetadataWriter {
- public:
-  explicit MetadataWriter(HttpCache::Transaction* transaction)
-      : verified_(false), buf_len_(0), transaction_(transaction) {}
-
-  ~MetadataWriter() = default;
-
-  // Implements the bulk of HttpCache::WriteMetadata.
-  void Write(const GURL& url,
-             base::Time expected_response_time,
-             IOBuffer* buf,
-             int buf_len);
-
- private:
-  void VerifyResponse(int result);
-  void SelfDestroy();
-  void OnIOComplete(int result);
-
-  bool verified_;
-  scoped_refptr<IOBuffer> buf_;
-  int buf_len_;
-  base::Time expected_response_time_;
-  HttpRequestInfo request_info_;
-
-  // |transaction_| to come after |request_info_| so that |request_info_| is not
-  // destroyed earlier.
-  std::unique_ptr<HttpCache::Transaction> transaction_;
-  DISALLOW_COPY_AND_ASSIGN(MetadataWriter);
-};
-
-void HttpCache::MetadataWriter::Write(const GURL& url,
-                                      base::Time expected_response_time,
-                                      IOBuffer* buf,
-                                      int buf_len) {
-  DCHECK_GT(buf_len, 0);
-  DCHECK(buf);
-  DCHECK(buf->data());
-  request_info_.url = url;
-  request_info_.method = "GET";
-
-  // todo (crbug.com/690099): Incorrect usage of LOAD_ONLY_FROM_CACHE.
-  request_info_.load_flags =
-      LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION | LOAD_SKIP_VARY_CHECK;
-
-  expected_response_time_ = expected_response_time;
-  buf_ = buf;
-  buf_len_ = buf_len;
-  verified_ = false;
-
-  int rv = transaction_->Start(
-      &request_info_,
-      base::Bind(&MetadataWriter::OnIOComplete, base::Unretained(this)),
-      NetLogWithSource());
-  if (rv != ERR_IO_PENDING)
-    VerifyResponse(rv);
-}
-
-void HttpCache::MetadataWriter::VerifyResponse(int result) {
-  verified_ = true;
-  if (result != OK)
-    return SelfDestroy();
-
-  const HttpResponseInfo* response_info = transaction_->GetResponseInfo();
-  DCHECK(response_info->was_cached);
-  if (response_info->response_time != expected_response_time_)
-    return SelfDestroy();
-
-  result = transaction_->WriteMetadata(
-      buf_.get(),
-      buf_len_,
-      base::Bind(&MetadataWriter::OnIOComplete, base::Unretained(this)));
-  if (result != ERR_IO_PENDING)
-    SelfDestroy();
-}
-
-void HttpCache::MetadataWriter::SelfDestroy() {
-  delete this;
-}
-
-void HttpCache::MetadataWriter::OnIOComplete(int result) {
-  if (!verified_)
-    return VerifyResponse(result);
-  SelfDestroy();
-}
-
-//-----------------------------------------------------------------------------
 HttpCache::HttpCache(HttpNetworkSession* session,
                      std::unique_ptr<BackendFactory> backend_factory,
                      bool is_main_cache)
@@ -425,28 +337,6 @@
   return response_info->InitFromPickle(pickle, response_truncated);
 }
 
-void HttpCache::WriteMetadata(const GURL& url,
-                              RequestPriority priority,
-                              base::Time expected_response_time,
-                              IOBuffer* buf,
-                              int buf_len) {
-  if (!buf_len)
-    return;
-
-  // Do lazy initialization of disk cache if needed.
-  if (!disk_cache_.get()) {
-    // We don't care about the result.
-    CreateBackend(nullptr, CompletionOnceCallback());
-  }
-
-  HttpCache::Transaction* transaction =
-      new HttpCache::Transaction(priority, this);
-  MetadataWriter* writer = new MetadataWriter(transaction);
-
-  // The writer will self destruct when done.
-  writer->Write(url, expected_response_time, buf, buf_len);
-}
-
 void HttpCache::CloseAllConnections() {
   HttpNetworkSession* session = GetSession();
   if (session)
diff --git a/net/http/http_cache.h b/net/http/http_cache.h
index 03707d1..832a5dcc 100644
--- a/net/http/http_cache.h
+++ b/net/http/http_cache.h
@@ -56,7 +56,6 @@
 
 class HttpNetworkSession;
 class HttpResponseInfo;
-class IOBuffer;
 class NetLog;
 struct HttpRequestInfo;
 
@@ -203,17 +202,6 @@
                                 HttpResponseInfo* response_info,
                                 bool* response_truncated);
 
-  // Writes |buf_len| bytes of metadata stored in |buf| to the cache entry
-  // referenced by |url|, as long as the entry's |expected_response_time| has
-  // not changed. This method returns without blocking, and the operation will
-  // be performed asynchronously without any completion notification.
-  // Takes ownership of |buf|.
-  virtual void WriteMetadata(const GURL& url,
-                             RequestPriority priority,
-                             base::Time expected_response_time,
-                             IOBuffer* buf,
-                             int buf_len);
-
   // Get/Set the cache's mode.
   void set_mode(Mode value) { mode_ = value; }
   Mode mode() { return mode_; }
@@ -300,13 +288,17 @@
   enum {
     kResponseInfoIndex = 0,
     kResponseContentIndex,
+    // Only currently used in DoTruncateCachedMetadata().
+    // TODO(mmenke): Remove this in and DoTruncateCachedMetadata() in M79, after
+    // most metadata entries in the cache have been removed. Without
+    // DoTruncateCachedMetadata(), the metadata will be removed when a cache
+    // entry is destroyed, but some conditionalized updates will keep it around.
     kMetadataIndex,
 
     // Must remain at the end of the enum.
     kNumCacheEntryDataIndices
   };
 
-  class MetadataWriter;
   class QuicServerInfoFactoryAdaptor;
   class Transaction;
   class WorkItem;
diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc
index 8c5633a..ced4e70 100644
--- a/net/http/http_cache_transaction.cc
+++ b/net/http/http_cache_transaction.cc
@@ -223,23 +223,6 @@
   return mode_;
 }
 
-int HttpCache::Transaction::WriteMetadata(IOBuffer* buf,
-                                          int buf_len,
-                                          CompletionOnceCallback callback) {
-  DCHECK(buf);
-  DCHECK_GT(buf_len, 0);
-  DCHECK(!callback.is_null());
-  if (!cache_.get() || !entry_)
-    return ERR_UNEXPECTED;
-
-  // We don't need to track this operation for anything.
-  // It could be possible to check if there is something already written and
-  // avoid writing again (it should be the same, right?), but let's allow the
-  // caller to "update" the contents with something new.
-  return entry_->disk_entry->WriteData(kMetadataIndex, 0, buf, buf_len,
-                                       std::move(callback), true);
-}
-
 LoadState HttpCache::Transaction::GetWriterLoadState() const {
   const HttpTransaction* transaction = network_transaction();
   if (transaction)
@@ -977,13 +960,6 @@
         DCHECK_EQ(OK, rv);
         rv = DoPartialHeadersReceived();
         break;
-      case STATE_CACHE_READ_METADATA:
-        DCHECK_EQ(OK, rv);
-        rv = DoCacheReadMetadata();
-        break;
-      case STATE_CACHE_READ_METADATA_COMPLETE:
-        rv = DoCacheReadMetadataComplete(rv);
-        break;
       case STATE_HEADERS_PHASE_CANNOT_PROCEED:
         rv = DoHeadersPhaseCannotProceed(rv);
         break;
@@ -2078,17 +2054,7 @@
 int HttpCache::Transaction::DoPartialHeadersReceived() {
   new_response_ = nullptr;
 
-  if (!partial_) {
-    if (entry_ && entry_->disk_entry->GetDataSize(kMetadataIndex) &&
-        !base::FeatureList::IsEnabled(net::features::kIsolatedCodeCache)) {
-      TransitionToState(STATE_CACHE_READ_METADATA);
-    } else {
-      TransitionToState(STATE_FINISH_HEADERS);
-    }
-    return OK;
-  }
-
-  if (mode_ != NONE && !reading_) {
+  if (partial_ && mode_ != NONE && !reading_) {
     // We are about to return the headers for a byte-range request to the user,
     // so let's fix them.
     partial_->FixResponseHeaders(response_.headers.get(), true);
@@ -2175,34 +2141,6 @@
   return rv;
 }
 
-int HttpCache::Transaction::DoCacheReadMetadata() {
-  TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheReadMetadata");
-  DCHECK(entry_);
-  DCHECK(!response_.metadata.get());
-  DCHECK(!base::FeatureList::IsEnabled(net::features::kIsolatedCodeCache));
-  TransitionToState(STATE_CACHE_READ_METADATA_COMPLETE);
-
-  response_.metadata = base::MakeRefCounted<IOBufferWithSize>(
-      entry_->disk_entry->GetDataSize(kMetadataIndex));
-
-  net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_READ_INFO);
-  return entry_->disk_entry->ReadData(kMetadataIndex, 0,
-                                      response_.metadata.get(),
-                                      response_.metadata->size(),
-                                      io_callback_);
-}
-
-int HttpCache::Transaction::DoCacheReadMetadataComplete(int result) {
-  TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheReadMetadataComplete");
-  net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_READ_INFO,
-                                    result);
-  if (result != response_.metadata->size())
-    return OnCacheReadError(result, false);
-
-  TransitionToState(STATE_FINISH_HEADERS);
-  return OK;
-}
-
 int HttpCache::Transaction::DoNetworkReadCacheWrite() {
   TRACE_EVENT0("io", "HttpCacheTransaction::DoNetworkReadCacheWrite");
   DCHECK(InWriters());
@@ -2526,12 +2464,7 @@
   if (method_ == "HEAD")
     FixHeadersForHead();
 
-  if (entry_->disk_entry->GetDataSize(kMetadataIndex) &&
-      !base::FeatureList::IsEnabled(net::features::kIsolatedCodeCache)) {
-    TransitionToState(STATE_CACHE_READ_METADATA);
-  } else {
-    TransitionToState(STATE_FINISH_HEADERS);
-  }
+  TransitionToState(STATE_FINISH_HEADERS);
   return OK;
 }
 
@@ -3104,12 +3037,7 @@
   if (method_ == "HEAD")
     FixHeadersForHead();
 
-  if (entry_->disk_entry->GetDataSize(kMetadataIndex) &&
-      !base::FeatureList::IsEnabled(net::features::kIsolatedCodeCache)) {
-    TransitionToState(STATE_CACHE_READ_METADATA);
-  } else {
-    TransitionToState(STATE_FINISH_HEADERS);
-  }
+  TransitionToState(STATE_FINISH_HEADERS);
   return OK;
 }
 
diff --git a/net/http/http_cache_transaction.h b/net/http/http_cache_transaction.h
index e4cc343f..640f851 100644
--- a/net/http/http_cache_transaction.h
+++ b/net/http/http_cache_transaction.h
@@ -86,25 +86,6 @@
 
   const std::string& key() const { return cache_key_; }
 
-  // Writes |buf_len| bytes of meta-data from the provided buffer |buf|. to the
-  // HTTP cache entry that backs this transaction (if any).
-  // Returns the number of bytes actually written, or a net error code. If the
-  // operation cannot complete immediately, returns ERR_IO_PENDING, grabs a
-  // reference to the buffer (until completion), and notifies the caller using
-  // the provided |callback| when the operation finishes.
-  //
-  // The first time this method is called for a given transaction, previous
-  // meta-data will be overwritten with the provided data, and subsequent
-  // invocations will keep appending to the cached entry.
-  //
-  // In order to guarantee that the metadata is set to the correct entry, the
-  // response (or response info) must be evaluated by the caller, for instance
-  // to make sure that the response_time is as expected, before calling this
-  // method.
-  int WriteMetadata(IOBuffer* buf,
-                    int buf_len,
-                    CompletionOnceCallback callback);
-
   HttpCache::ActiveEntry* entry() { return entry_; }
 
   // Returns the LoadState of the writer transaction of a given ActiveEntry. In
@@ -278,8 +259,6 @@
     STATE_TRUNCATE_CACHED_METADATA,
     STATE_TRUNCATE_CACHED_METADATA_COMPLETE,
     STATE_PARTIAL_HEADERS_RECEIVED,
-    STATE_CACHE_READ_METADATA,
-    STATE_CACHE_READ_METADATA_COMPLETE,
     STATE_HEADERS_PHASE_CANNOT_PROCEED,
     STATE_FINISH_HEADERS,
     STATE_FINISH_HEADERS_COMPLETE,
@@ -360,8 +339,6 @@
   int DoTruncateCachedMetadata();
   int DoTruncateCachedMetadataComplete(int result);
   int DoPartialHeadersReceived();
-  int DoCacheReadMetadata();
-  int DoCacheReadMetadataComplete(int result);
   int DoHeadersPhaseCannotProceed(int result);
   int DoFinishHeaders(int result);
   int DoFinishHeadersComplete(int result);
diff --git a/net/http/http_cache_unittest.cc b/net/http/http_cache_unittest.cc
index a64269c..107d6c6 100644
--- a/net/http/http_cache_unittest.cc
+++ b/net/http/http_cache_unittest.cc
@@ -9732,169 +9732,6 @@
   histograms.ExpectTotalCount("HttpCache.TopFrameOriginPresent", 3);
 }
 
-// Tests that we can write metadata to an entry.
-TEST_F(HttpCacheTest, WriteMetadata_OK) {
-  base::test::ScopedFeatureList feature_list;
-  feature_list.InitAndDisableFeature(net::features::kIsolatedCodeCache);
-  ASSERT_FALSE(base::FeatureList::IsEnabled(net::features::kIsolatedCodeCache));
-  MockHttpCache cache;
-
-  // Write to the cache
-  HttpResponseInfo response;
-  RunTransactionTestWithResponseInfo(cache.http_cache(), kSimpleGET_Transaction,
-                                     &response);
-  EXPECT_TRUE(response.metadata.get() == nullptr);
-
-  // Trivial call.
-  cache.http_cache()->WriteMetadata(GURL("foo"), DEFAULT_PRIORITY, Time::Now(),
-                                    nullptr, 0);
-
-  // Write meta data to the same entry.
-  scoped_refptr<IOBufferWithSize> buf =
-      base::MakeRefCounted<IOBufferWithSize>(50);
-  memset(buf->data(), 0, buf->size());
-  base::strlcpy(buf->data(), "Hi there", buf->size());
-  cache.http_cache()->WriteMetadata(GURL(kSimpleGET_Transaction.url),
-                                    DEFAULT_PRIORITY, response.response_time,
-                                    buf.get(), buf->size());
-
-  // Release the buffer before the operation takes place.
-  buf = nullptr;
-
-  // Makes sure we finish pending operations.
-  base::RunLoop().RunUntilIdle();
-
-  RunTransactionTestWithResponseInfo(cache.http_cache(), kSimpleGET_Transaction,
-                                     &response);
-  ASSERT_TRUE(response.metadata.get() != nullptr);
-  EXPECT_EQ(50, response.metadata->size());
-  EXPECT_EQ(0, strcmp(response.metadata->data(), "Hi there"));
-
-  EXPECT_EQ(1, cache.network_layer()->transaction_count());
-  EXPECT_EQ(2, cache.disk_cache()->open_count());
-  EXPECT_EQ(1, cache.disk_cache()->create_count());
-}
-
-// Tests that we don't read metadata when IsolatedCodeCache is enabled.
-TEST_F(HttpCacheTest, ReadMetadata_IsolatedCache) {
-  base::test::ScopedFeatureList feature_list;
-  feature_list.InitAndEnableFeature(net::features::kIsolatedCodeCache);
-  ASSERT_TRUE(base::FeatureList::IsEnabled(net::features::kIsolatedCodeCache));
-  MockHttpCache cache;
-
-  // Write to the cache
-  HttpResponseInfo response;
-  RunTransactionTestWithResponseInfo(cache.http_cache(), kSimpleGET_Transaction,
-                                     &response);
-  EXPECT_TRUE(response.metadata.get() == nullptr);
-
-  // Trivial call.
-  cache.http_cache()->WriteMetadata(GURL("foo"), DEFAULT_PRIORITY, Time::Now(),
-                                    nullptr, 0);
-
-  // Write meta data to the same entry.
-  scoped_refptr<IOBufferWithSize> buf =
-      base::MakeRefCounted<IOBufferWithSize>(50);
-  memset(buf->data(), 0, buf->size());
-  base::strlcpy(buf->data(), "Hi there", buf->size());
-  cache.http_cache()->WriteMetadata(GURL(kSimpleGET_Transaction.url),
-                                    DEFAULT_PRIORITY, response.response_time,
-                                    buf.get(), buf->size());
-
-  // Release the buffer before the operation takes place.
-  buf = nullptr;
-
-  // Makes sure we finish pending operations.
-  base::RunLoop().RunUntilIdle();
-
-  RunTransactionTestWithResponseInfo(cache.http_cache(), kSimpleGET_Transaction,
-                                     &response);
-  ASSERT_TRUE(response.metadata.get() == nullptr);
-
-  EXPECT_EQ(1, cache.network_layer()->transaction_count());
-  EXPECT_EQ(2, cache.disk_cache()->open_count());
-  EXPECT_EQ(1, cache.disk_cache()->create_count());
-}
-
-// Tests that we only write metadata to an entry if the time stamp matches.
-TEST_F(HttpCacheTest, WriteMetadata_Fail) {
-  base::test::ScopedFeatureList feature_list;
-  feature_list.InitAndDisableFeature(net::features::kIsolatedCodeCache);
-  ASSERT_FALSE(base::FeatureList::IsEnabled(net::features::kIsolatedCodeCache));
-  MockHttpCache cache;
-
-  // Write to the cache
-  HttpResponseInfo response;
-  RunTransactionTestWithResponseInfo(cache.http_cache(), kSimpleGET_Transaction,
-                                     &response);
-  EXPECT_TRUE(response.metadata.get() == nullptr);
-
-  // Attempt to write meta data to the same entry.
-  scoped_refptr<IOBufferWithSize> buf =
-      base::MakeRefCounted<IOBufferWithSize>(50);
-  memset(buf->data(), 0, buf->size());
-  base::strlcpy(buf->data(), "Hi there", buf->size());
-  base::Time expected_time = response.response_time -
-                             base::TimeDelta::FromMilliseconds(20);
-  cache.http_cache()->WriteMetadata(GURL(kSimpleGET_Transaction.url),
-                                    DEFAULT_PRIORITY, expected_time, buf.get(),
-                                    buf->size());
-
-  // Makes sure we finish pending operations.
-  base::RunLoop().RunUntilIdle();
-
-  RunTransactionTestWithResponseInfo(cache.http_cache(), kSimpleGET_Transaction,
-                                     &response);
-  EXPECT_TRUE(response.metadata.get() == nullptr);
-
-  EXPECT_EQ(1, cache.network_layer()->transaction_count());
-  EXPECT_EQ(2, cache.disk_cache()->open_count());
-  EXPECT_EQ(1, cache.disk_cache()->create_count());
-}
-
-// Tests that we ignore VARY checks when writing metadata since the request
-// headers for the WriteMetadata transaction are made up.
-TEST_F(HttpCacheTest, WriteMetadata_IgnoreVary) {
-  base::test::ScopedFeatureList feature_list;
-  feature_list.InitAndDisableFeature(net::features::kIsolatedCodeCache);
-  ASSERT_FALSE(base::FeatureList::IsEnabled(net::features::kIsolatedCodeCache));
-  MockHttpCache cache;
-
-  // Write to the cache
-  HttpResponseInfo response;
-  ScopedMockTransaction transaction(kSimpleGET_Transaction);
-  transaction.request_headers = "accept-encoding: gzip\r\n";
-  transaction.response_headers =
-      "Vary: accept-encoding\n"
-      "Cache-Control: max-age=10000\n";
-
-  RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
-                                     &response);
-  EXPECT_FALSE(response.metadata);
-
-  // Attempt to write meta data to the same entry.
-  scoped_refptr<IOBufferWithSize> buf =
-      base::MakeRefCounted<IOBufferWithSize>(50);
-  memset(buf->data(), 0, buf->size());
-  base::strlcpy(buf->data(), "Hi there", buf->size());
-  cache.http_cache()->WriteMetadata(GURL(transaction.url), DEFAULT_PRIORITY,
-                                    response.response_time, buf.get(),
-                                    buf->size());
-
-  // Makes sure we finish pending operations.
-  base::RunLoop().RunUntilIdle();
-
-  RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
-                                     &response);
-  ASSERT_TRUE(response.metadata);
-  EXPECT_EQ(50, response.metadata->size());
-  EXPECT_EQ(0, strcmp(response.metadata->data(), "Hi there"));
-
-  EXPECT_EQ(1, cache.network_layer()->transaction_count());
-  EXPECT_EQ(2, cache.disk_cache()->open_count());
-  EXPECT_EQ(1, cache.disk_cache()->create_count());
-}
-
 TEST_F(HttpCacheTest, SkipVaryCheck) {
   MockHttpCache cache;
 
@@ -9986,72 +9823,6 @@
   RunTransactionTest(cache.http_cache(), transaction);
 }
 
-// Tests that we can read metadata after validating the entry and with READ mode
-// transactions.
-TEST_F(HttpCacheTest, ReadMetadata) {
-  base::test::ScopedFeatureList feature_list;
-  feature_list.InitAndDisableFeature(net::features::kIsolatedCodeCache);
-  ASSERT_FALSE(base::FeatureList::IsEnabled(net::features::kIsolatedCodeCache));
-  MockHttpCache cache;
-
-  // Write to the cache
-  HttpResponseInfo response;
-  RunTransactionTestWithResponseInfo(cache.http_cache(),
-                                     kTypicalGET_Transaction, &response);
-  EXPECT_TRUE(response.metadata.get() == nullptr);
-
-  // Write meta data to the same entry.
-  scoped_refptr<IOBufferWithSize> buf =
-      base::MakeRefCounted<IOBufferWithSize>(50);
-  memset(buf->data(), 0, buf->size());
-  base::strlcpy(buf->data(), "Hi there", buf->size());
-  cache.http_cache()->WriteMetadata(GURL(kTypicalGET_Transaction.url),
-                                    DEFAULT_PRIORITY, response.response_time,
-                                    buf.get(), buf->size());
-
-  // Makes sure we finish pending operations.
-  base::RunLoop().RunUntilIdle();
-
-  // Start with a READ mode transaction.
-  MockTransaction trans1(kTypicalGET_Transaction);
-  trans1.load_flags = LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
-
-  RunTransactionTestWithResponseInfo(cache.http_cache(), trans1, &response);
-  ASSERT_TRUE(response.metadata.get() != nullptr);
-  EXPECT_EQ(50, response.metadata->size());
-  EXPECT_EQ(0, strcmp(response.metadata->data(), "Hi there"));
-
-  EXPECT_EQ(1, cache.network_layer()->transaction_count());
-  EXPECT_EQ(2, cache.disk_cache()->open_count());
-  EXPECT_EQ(1, cache.disk_cache()->create_count());
-  base::RunLoop().RunUntilIdle();
-
-  // Now make sure that the entry is re-validated with the server.
-  trans1.load_flags = LOAD_VALIDATE_CACHE;
-  trans1.status = "HTTP/1.1 304 Not Modified";
-  AddMockTransaction(&trans1);
-
-  response.metadata = nullptr;
-  RunTransactionTestWithResponseInfo(cache.http_cache(), trans1, &response);
-  EXPECT_TRUE(response.metadata.get() != nullptr);
-
-  EXPECT_EQ(2, cache.network_layer()->transaction_count());
-  EXPECT_EQ(3, cache.disk_cache()->open_count());
-  EXPECT_EQ(1, cache.disk_cache()->create_count());
-  base::RunLoop().RunUntilIdle();
-  RemoveMockTransaction(&trans1);
-
-  // Now return 200 when validating the entry so the metadata will be lost.
-  MockTransaction trans2(kTypicalGET_Transaction);
-  trans2.load_flags = LOAD_VALIDATE_CACHE;
-  RunTransactionTestWithResponseInfo(cache.http_cache(), trans2, &response);
-  EXPECT_TRUE(response.metadata.get() == nullptr);
-
-  EXPECT_EQ(3, cache.network_layer()->transaction_count());
-  EXPECT_EQ(4, cache.disk_cache()->open_count());
-  EXPECT_EQ(1, cache.disk_cache()->create_count());
-}
-
 // Tests that we don't mark entries as truncated when a filter detects the end
 // of the stream.
 TEST_F(HttpCacheTest, FilterCompletion) {
diff --git a/services/identity/DEPS b/services/identity/DEPS
index da77e88..3345ad6 100644
--- a/services/identity/DEPS
+++ b/services/identity/DEPS
@@ -7,8 +7,8 @@
   "+components/signin/core/browser/fake_profile_oauth2_token_service.h",
   "+components/signin/core/browser/profile_oauth2_token_service.h",
   "+components/signin/core/browser/set_accounts_in_cookie_result.h",
-  "+components/signin/core/browser/signin_manager_base.h",
-  "+components/signin/core/browser/signin_manager.h",
+  "+components/signin/core/browser/primary_account_manager.h",
+  "+components/signin/core/browser/primary_account_policy_manager.h",
   "+components/signin/core/browser/test_signin_client.h",
   "+components/signin/public",
   "+components/sync_preferences/testing_pref_service_syncable.h",
diff --git a/services/identity/README.md b/services/identity/README.md
index 0b8dc83..f5ece0f4 100644
--- a/services/identity/README.md
+++ b/services/identity/README.md
@@ -24,9 +24,9 @@
 
 There is no way to obtain the information of the primary account synchronously,
 i.e., there is no literal equivalent to
-SigninManagerBase::GetAuthenticatedAccountInfo(). Instead, you should call the
+PrimaryAccountManager::GetAuthenticatedAccountInfo(). Instead, you should call the
 asynchronous method IdentityManager::GetPrimaryAccountInfo(). To date, all use
-cases of SigninManagerBase::GetAuthenticatedAccountInfo() that we have seen have
+cases of PrimaryAccountManager::GetAuthenticatedAccountInfo() that we have seen have
 been part of a larger asynchronous flow (e.g., obtaining an access token in
 response to an invocation of the chrome.identity extension API). In these use
 cases, you can simply fold the asynchronous obtaining of the authenticated
@@ -57,7 +57,7 @@
 
 ## Being Notified on Signin of the Primary Account
 
-If you were previously listening to SigninManagerBase::GoogleSigninSucceeded()
+If you were previously listening to PrimaryAccountManager::GoogleSigninSucceeded()
 or OAuth2TokenService::OnRefreshTokenIsAvailable() to determine when the primary
 account is available, you should call
 IdentityManager::GetPrimaryAccountWhenAvailable(). This method will fire when
@@ -102,9 +102,9 @@
 
 There are plans to build a unified Observer interface that will supersede the
 various current Observer interfaces (AccountTracker, OAuth2TokenService,
-SigninManager, AccountTrackerService). However, this functionality has not yet
-been built. Contact blundell@chromium.org with your use case, which can help
-drive the bringup of this interface.
+PrimaryAccountManager, AccountTrackerService). However, this functionality has
+not yet been built. Contact blundell@chromium.org with your use case, which can
+help drive the bringup of this interface.
 
 ## Other Needs
 
diff --git a/services/identity/identity_service.h b/services/identity/identity_service.h
index 15fd781..ee407ca6 100644
--- a/services/identity/identity_service.h
+++ b/services/identity/identity_service.h
@@ -5,7 +5,7 @@
 #ifndef SERVICES_IDENTITY_IDENTITY_SERVICE_H_
 #define SERVICES_IDENTITY_IDENTITY_SERVICE_H_
 
-#include "components/signin/core/browser/signin_manager_base.h"
+#include "components/signin/core/browser/primary_account_manager.h"
 #include "mojo/public/cpp/bindings/strong_binding_set.h"
 #include "services/identity/public/cpp/identity_manager.h"
 #include "services/identity/public/mojom/identity_accessor.mojom.h"
diff --git a/services/identity/public/cpp/README.md b/services/identity/public/cpp/README.md
index a0dc8c1..c08d24e 100644
--- a/services/identity/public/cpp/README.md
+++ b/services/identity/public/cpp/README.md
@@ -2,8 +2,8 @@
 identity. It is backed by //components/signin.
 
 Documentation on the mapping between usage of legacy signin
-classes (notably SigninManager(Base) and ProfileOAuth2TokenService) and usage of
-IdentityManager is available here:
+classes (notably PrimaryAccountManager and ProfileOAuth2TokenService) and usage
+of IdentityManager is available here:
 
 https://docs.google.com/document/d/14f3qqkDM9IE4Ff_l6wuXvCMeHfSC9TxKezXTCyeaPUY/edit#
 
@@ -11,8 +11,8 @@
 signin and //google_apis/gaia:
 
 - "Primary account" in IdentityManager refers to what is called the
-  "authenticated account" in SigninManager, i.e., the account that has been
-  blessed for sync by the user.
+  "authenticated account" in PrimaryAccountManager, i.e., the account that has
+  been blessed for sync by the user.
 - PrimaryAccountTokenFetcher is the primary client-side interface for obtaining
   access tokens for the primary account. In particular, it can take care of 
   waiting until the primary account is available.
@@ -23,7 +23,7 @@
   use in cases where neither the production code nor the unittest is interacting
   with Profile (e.g., //components-level unittests).
 - identity_test_utils.h provides lower-level test facilities for interacting
-  explicitly with IdentityManager and its dependencies (SigninManager,
+  explicitly with IdentityManager and its dependencies (PrimaryAccountManager,
   ProfileOAuth2TokenService). These facilities are the way to interact with
   IdentityManager in unittest contexts where the production code and/or the
   unittest are interacting with Profile (in particular, where the
diff --git a/services/identity/public/cpp/accounts_mutator_impl.cc b/services/identity/public/cpp/accounts_mutator_impl.cc
index 5ed1dcf..deaf63a 100644
--- a/services/identity/public/cpp/accounts_mutator_impl.cc
+++ b/services/identity/public/cpp/accounts_mutator_impl.cc
@@ -11,22 +11,22 @@
 #include "components/signin/core/browser/account_info.h"
 #include "components/signin/core/browser/account_tracker_service.h"
 #include "components/signin/core/browser/device_id_helper.h"
+#include "components/signin/core/browser/primary_account_manager.h"
 #include "components/signin/core/browser/profile_oauth2_token_service.h"
-#include "components/signin/core/browser/signin_manager_base.h"
 
 namespace identity {
 
 AccountsMutatorImpl::AccountsMutatorImpl(
     ProfileOAuth2TokenService* token_service,
     AccountTrackerService* account_tracker_service,
-    SigninManagerBase* signin_manager,
+    PrimaryAccountManager* primary_account_manager,
     PrefService* pref_service)
     : token_service_(token_service),
       account_tracker_service_(account_tracker_service),
-      signin_manager_(signin_manager) {
+      primary_account_manager_(primary_account_manager) {
   DCHECK(token_service_);
   DCHECK(account_tracker_service_);
-  DCHECK(signin_manager_);
+  DCHECK(primary_account_manager_);
 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
   pref_service_ = pref_service;
   DCHECK(pref_service_);
@@ -78,9 +78,9 @@
 
 void AccountsMutatorImpl::InvalidateRefreshTokenForPrimaryAccount(
     signin_metrics::SourceForRefreshTokenOperation source) {
-  DCHECK(signin_manager_->IsAuthenticated());
+  DCHECK(primary_account_manager_->IsAuthenticated());
   AccountInfo primary_account_info =
-      signin_manager_->GetAuthenticatedAccountInfo();
+      primary_account_manager_->GetAuthenticatedAccountInfo();
   AddOrUpdateAccount(primary_account_info.gaia, primary_account_info.email,
                      OAuth2TokenServiceDelegate::kInvalidRefreshToken,
                      primary_account_info.is_under_advanced_protection, source);
diff --git a/services/identity/public/cpp/accounts_mutator_impl.h b/services/identity/public/cpp/accounts_mutator_impl.h
index 4ba626fc..c5bdfd3 100644
--- a/services/identity/public/cpp/accounts_mutator_impl.h
+++ b/services/identity/public/cpp/accounts_mutator_impl.h
@@ -15,8 +15,8 @@
 
 class AccountTrackerService;
 class PrefService;
+class PrimaryAccountManager;
 class ProfileOAuth2TokenService;
-class SigninManagerBase;
 
 namespace identity {
 
@@ -25,7 +25,7 @@
  public:
   explicit AccountsMutatorImpl(ProfileOAuth2TokenService* token_service,
                                AccountTrackerService* account_tracker_service,
-                               SigninManagerBase* signin_manager,
+                               PrimaryAccountManager* primary_account_manager,
                                PrefService* pref_service);
   ~AccountsMutatorImpl() override;
 
@@ -59,7 +59,7 @@
  private:
   ProfileOAuth2TokenService* token_service_;
   AccountTrackerService* account_tracker_service_;
-  SigninManagerBase* signin_manager_;
+  PrimaryAccountManager* primary_account_manager_;
 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
   PrefService* pref_service_;
 #endif
diff --git a/services/identity/public/cpp/identity_manager.cc b/services/identity/public/cpp/identity_manager.cc
index 1015ccc..62c1b43 100644
--- a/services/identity/public/cpp/identity_manager.cc
+++ b/services/identity/public/cpp/identity_manager.cc
@@ -44,7 +44,7 @@
     std::unique_ptr<AccountTrackerService> account_tracker_service,
     std::unique_ptr<ProfileOAuth2TokenService> token_service,
     std::unique_ptr<GaiaCookieManagerService> gaia_cookie_manager_service,
-    std::unique_ptr<SigninManagerBase> signin_manager,
+    std::unique_ptr<PrimaryAccountManager> primary_account_manager,
     std::unique_ptr<AccountFetcherService> account_fetcher_service,
     std::unique_ptr<PrimaryAccountMutator> primary_account_mutator,
     std::unique_ptr<AccountsMutator> accounts_mutator,
@@ -53,7 +53,7 @@
     : account_tracker_service_(std::move(account_tracker_service)),
       token_service_(std::move(token_service)),
       gaia_cookie_manager_service_(std::move(gaia_cookie_manager_service)),
-      signin_manager_(std::move(signin_manager)),
+      primary_account_manager_(std::move(primary_account_manager)),
       account_fetcher_service_(std::move(account_fetcher_service)),
       primary_account_mutator_(std::move(primary_account_mutator)),
       accounts_mutator_(std::move(accounts_mutator)),
@@ -62,7 +62,7 @@
   DCHECK(account_fetcher_service_);
   DCHECK(accounts_cookie_mutator_);
   DCHECK(diagnostics_provider_);
-  signin_manager_->SetObserver(this);
+  primary_account_manager_->SetObserver(this);
   token_service_->AddDiagnosticsObserver(this);
   token_service_->AddObserver(this);
   account_tracker_service_->AddObserver(this);
@@ -76,10 +76,11 @@
       base::BindRepeating(&IdentityManager::OnGaiaCookieDeletedByUserAction,
                           base::Unretained(this)));
 
-  // Seed the primary account with any state that |signin_manager_| loaded from
-  // prefs.
-  if (signin_manager_->IsAuthenticated()) {
-    CoreAccountInfo account = signin_manager_->GetAuthenticatedAccountInfo();
+  // Seed the primary account with any state that |primary_account_manager_|
+  // loaded from prefs.
+  if (primary_account_manager_->IsAuthenticated()) {
+    CoreAccountInfo account =
+        primary_account_manager_->GetAuthenticatedAccountInfo();
     DCHECK(!account.account_id.empty());
     primary_account_ = std::move(account);
   }
@@ -91,7 +92,7 @@
   token_service_->Shutdown();
   account_tracker_service_->Shutdown();
 
-  signin_manager_->ClearObserver();
+  primary_account_manager_->ClearObserver();
   token_service_->RemoveObserver(this);
   token_service_->RemoveDiagnosticsObserver(this);
   account_tracker_service_->RemoveObserver(this);
@@ -99,16 +100,18 @@
 
 // TODO(862619) change return type to base::Optional<CoreAccountInfo>
 CoreAccountInfo IdentityManager::GetPrimaryAccountInfo() const {
-  DCHECK_EQ(primary_account_.has_value(), signin_manager_->IsAuthenticated());
+  DCHECK_EQ(primary_account_.has_value(),
+            primary_account_manager_->IsAuthenticated());
   auto result = primary_account_.value_or(CoreAccountInfo());
-  DCHECK_EQ(result.account_id, signin_manager_->GetAuthenticatedAccountId());
+  DCHECK_EQ(result.account_id,
+            primary_account_manager_->GetAuthenticatedAccountId());
 #if DCHECK_IS_ON()
-  CoreAccountInfo signin_manager_account =
-      signin_manager_->GetAuthenticatedAccountInfo();
-  if (!signin_manager_account.account_id.empty()) {
-    DCHECK_EQ(signin_manager_account, result)
-        << "If signin_manager_'s account is set (account has a refresh token), "
-           "primary_account_ must have the same value.";
+  CoreAccountInfo primary_account_manager_account =
+      primary_account_manager_->GetAuthenticatedAccountInfo();
+  if (!primary_account_manager_account.account_id.empty()) {
+    DCHECK_EQ(primary_account_manager_account, result)
+        << "If primary_account_manager_'s account is set (account has a "
+           "refresh token), primary_account_ must have the same value.";
   }
 #endif
   return result;
@@ -119,7 +122,8 @@
 }
 
 bool IdentityManager::HasPrimaryAccount() const {
-  DCHECK_EQ(primary_account_.has_value(), signin_manager_->IsAuthenticated());
+  DCHECK_EQ(primary_account_.has_value(),
+            primary_account_manager_->IsAuthenticated());
   return primary_account_.has_value();
 }
 
@@ -312,13 +316,13 @@
 
 // static
 void IdentityManager::RegisterLocalStatePrefs(PrefRegistrySimple* registry) {
-  SigninManagerBase::RegisterPrefs(registry);
+  PrimaryAccountManager::RegisterPrefs(registry);
 }
 
 // static
 void IdentityManager::RegisterProfilePrefs(PrefRegistrySimple* registry) {
   ProfileOAuth2TokenService::RegisterProfilePrefs(registry);
-  SigninManagerBase::RegisterProfilePrefs(registry);
+  PrimaryAccountManager::RegisterProfilePrefs(registry);
   AccountFetcherService::RegisterPrefs(registry);
   AccountTrackerService::RegisterPrefs(registry);
 }
@@ -326,8 +330,8 @@
 CoreAccountId IdentityManager::PickAccountIdForAccount(
     const std::string& gaia,
     const std::string& email) const {
-  // TODO(triploblastic@): Remove explicit conversion once signin_manager
-  // has been fixed to use CoreAccountId.
+  // TODO(triploblastic@): Remove explicit conversion once
+  // primary_account_manager has been fixed to use CoreAccountId.
   return CoreAccountId(
       account_tracker_service_->PickAccountIdForAccount(gaia, email));
 }
@@ -370,7 +374,7 @@
 void IdentityManager::LegacySetPrimaryAccount(
     const std::string& gaia_id,
     const std::string& email_address) {
-  signin_manager_->SetAuthenticatedAccountInfo(gaia_id, email_address);
+  primary_account_manager_->SetAuthenticatedAccountInfo(gaia_id, email_address);
 
   // TODO(https://crbug.com/944012): Unify the firing of this observer
   // notification between ChromeOS and other platforms.
@@ -437,8 +441,8 @@
   diagnostics_observer_list_.RemoveObserver(observer);
 }
 
-SigninManagerBase* IdentityManager::GetSigninManager() {
-  return signin_manager_.get();
+PrimaryAccountManager* IdentityManager::GetPrimaryAccountManager() {
+  return primary_account_manager_.get();
 }
 
 ProfileOAuth2TokenService* IdentityManager::GetTokenService() {
@@ -508,11 +512,11 @@
   }
 }
 void IdentityManager::AuthenticatedAccountSet(const AccountInfo& account_info) {
-  DCHECK(signin_manager_->IsAuthenticated());
+  DCHECK(primary_account_manager_->IsAuthenticated());
   primary_account_ = account_info;
 }
 void IdentityManager::AuthenticatedAccountCleared() {
-  DCHECK(!signin_manager_->IsAuthenticated());
+  DCHECK(!primary_account_manager_->IsAuthenticated());
   primary_account_.reset();
 }
 
diff --git a/services/identity/public/cpp/identity_manager.h b/services/identity/public/cpp/identity_manager.h
index 97c05973..a5803ad25 100644
--- a/services/identity/public/cpp/identity_manager.h
+++ b/services/identity/public/cpp/identity_manager.h
@@ -13,8 +13,8 @@
 #include "components/signin/core/browser/account_fetcher_service.h"
 #include "components/signin/core/browser/account_info.h"
 #include "components/signin/core/browser/account_tracker_service.h"
+#include "components/signin/core/browser/primary_account_manager.h"
 #include "components/signin/core/browser/profile_oauth2_token_service.h"
-#include "components/signin/core/browser/signin_manager_base.h"
 #include "components/signin/core/browser/signin_metrics.h"
 #include "components/signin/core/browser/ubertoken_fetcher.h"
 #include "services/identity/public/cpp/access_token_fetcher.h"
@@ -50,7 +50,7 @@
 
 // Gives access to information about the user's Google identities. See
 // ./README.md for detailed documentation.
-class IdentityManager : public SigninManagerBase::Observer,
+class IdentityManager : public PrimaryAccountManager::Observer,
                         public OAuth2TokenService::DiagnosticsObserver,
                         public OAuth2TokenService::Observer,
                         public AccountTrackerService::Observer {
@@ -190,7 +190,7 @@
       std::unique_ptr<AccountTrackerService> account_tracker_service,
       std::unique_ptr<ProfileOAuth2TokenService> token_service,
       std::unique_ptr<GaiaCookieManagerService> gaia_cookie_manager_service,
-      std::unique_ptr<SigninManagerBase> signin_manager,
+      std::unique_ptr<PrimaryAccountManager> primary_account_manager,
       std::unique_ptr<AccountFetcherService> account_fetcher_service,
       std::unique_ptr<PrimaryAccountMutator> primary_account_mutator,
       std::unique_ptr<AccountsMutator> accounts_mutator,
@@ -563,7 +563,7 @@
                            ForceRefreshOfExtendedAccountInfo);
 
   // Private getters used for testing only (i.e. see identity_test_utils.h).
-  SigninManagerBase* GetSigninManager();
+  PrimaryAccountManager* GetPrimaryAccountManager();
   ProfileOAuth2TokenService* GetTokenService();
   AccountTrackerService* GetAccountTrackerService();
   AccountFetcherService* GetAccountFetcherService();
@@ -582,7 +582,7 @@
   void FireOnPrimaryAccountSetNotification(
       const CoreAccountInfo& primary_account_info);
 
-  // SigninManagerBase::Observer:
+  // PrimaryAccountManager::Observer:
   void GoogleSigninSucceeded(const AccountInfo& account_info) override;
   void GoogleSignedOut(const AccountInfo& account_info) override;
   void AuthenticatedAccountSet(const AccountInfo& account_info) override;
@@ -629,7 +629,7 @@
   std::unique_ptr<AccountTrackerService> account_tracker_service_;
   std::unique_ptr<ProfileOAuth2TokenService> token_service_;
   std::unique_ptr<GaiaCookieManagerService> gaia_cookie_manager_service_;
-  std::unique_ptr<SigninManagerBase> signin_manager_;
+  std::unique_ptr<PrimaryAccountManager> primary_account_manager_;
   std::unique_ptr<AccountFetcherService> account_fetcher_service_;
 
   // PrimaryAccountMutator instance. May be null if mutation of the primary
diff --git a/services/identity/public/cpp/identity_manager_unittest.cc b/services/identity/public/cpp/identity_manager_unittest.cc
index e8f2803..3f562c8c 100644
--- a/services/identity/public/cpp/identity_manager_unittest.cc
+++ b/services/identity/public/cpp/identity_manager_unittest.cc
@@ -22,8 +22,8 @@
 #include "components/signin/core/browser/fake_profile_oauth2_token_service.h"
 #include "components/signin/core/browser/gaia_cookie_manager_service.h"
 #include "components/signin/core/browser/list_accounts_test_utils.h"
+#include "components/signin/core/browser/primary_account_policy_manager.h"
 #include "components/signin/core/browser/set_accounts_in_cookie_result.h"
-#include "components/signin/core/browser/signin_manager.h"
 #include "components/signin/core/browser/signin_switches.h"
 #include "components/signin/core/browser/test_signin_client.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
@@ -218,8 +218,9 @@
     IdentityManager::RegisterProfilePrefs(pref_service_.registry());
     IdentityManager::RegisterLocalStatePrefs(pref_service_.registry());
 
-    RecreateIdentityManager(signin::AccountConsistencyMethod::kDisabled,
-                            SigninManagerSetup::kWithAuthenticatedAccout);
+    RecreateIdentityManager(
+        signin::AccountConsistencyMethod::kDisabled,
+        PrimaryAccountManagerSetup::kWithAuthenticatedAccout);
   }
 
   ~IdentityManagerTest() override {
@@ -252,7 +253,7 @@
   }
 
   // See RecreateIdentityManager.
-  enum class SigninManagerSetup {
+  enum class PrimaryAccountManagerSetup {
     kWithAuthenticatedAccout,
     kNoAuthenticatedAccount
   };
@@ -260,18 +261,19 @@
   // Used by some tests that need to re-instantiate IdentityManager after
   // performing some other setup.
   void RecreateIdentityManager() {
-    RecreateIdentityManager(signin::AccountConsistencyMethod::kDisabled,
-                            SigninManagerSetup::kNoAuthenticatedAccount);
+    RecreateIdentityManager(
+        signin::AccountConsistencyMethod::kDisabled,
+        PrimaryAccountManagerSetup::kNoAuthenticatedAccount);
   }
 
   // Recreates IdentityManager with given |account_consistency| and optionally
-  // seeds with an authenticated account depending on |singin_manager_setup|.
-  // This process destroys any existing IdentityManager and its dependencies,
-  // then remakes them. Dependencies that outlive SigninManager (e.g.
-  // SigninClient) will be reused.
+  // seeds with an authenticated account depending on
+  // |primary_account_manager_setup|. This process destroys any existing
+  // IdentityManager and its dependencies, then remakes them. Dependencies that
+  // outlive PrimaryAccountManager (e.g. SigninClient) will be reused.
   void RecreateIdentityManager(
       signin::AccountConsistencyMethod account_consistency,
-      SigninManagerSetup signin_manager_setup) {
+      PrimaryAccountManagerSetup primary_account_manager_setup) {
     // Remove observers first, otherwise IdentityManager destruction might
     // trigger a DCHECK because there are still living observers.
     identity_manager_observer_.reset();
@@ -295,26 +297,29 @@
 
 #if defined(OS_CHROMEOS)
     DCHECK_EQ(account_consistency, signin::AccountConsistencyMethod::kDisabled)
-        << "AccountConsistency is not used by SigninManagerBase";
-    auto signin_manager = std::make_unique<SigninManagerBase>(
+        << "AccountConsistency is not used by PrimaryAccountManager";
+    auto primary_account_manager = std::make_unique<PrimaryAccountManager>(
         &signin_client_, token_service.get(), account_tracker_service.get(),
         account_consistency);
 #else
-    auto signin_manager = std::make_unique<SigninManager>(
-        &signin_client_, token_service.get(), account_tracker_service.get(),
-        account_consistency);
+    auto primary_account_manager =
+        std::make_unique<PrimaryAccountPolicyManager>(
+            &signin_client_, token_service.get(), account_tracker_service.get(),
+            account_consistency);
 #endif
 
-    // Passing this switch ensures that the new SigninManager starts with a
-    // clean slate. Otherwise SigninManagerBase::Initialize will use the account
-    // id stored in prefs::kGoogleServicesAccountId.
+    // Passing this switch ensures that the new PrimaryAccountManager starts
+    // with a clean slate. Otherwise PrimaryAccountManager::Initialize will use
+    // the account id stored in prefs::kGoogleServicesAccountId.
     base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
     cmd_line->AppendSwitch(switches::kClearTokenService);
 
-    signin_manager->Initialize(&pref_service_);
+    primary_account_manager->Initialize(&pref_service_);
 
-    if (signin_manager_setup == SigninManagerSetup::kWithAuthenticatedAccout) {
-      signin_manager->SetAuthenticatedAccountInfo(kTestGaiaId, kTestEmail);
+    if (primary_account_manager_setup ==
+        PrimaryAccountManagerSetup::kWithAuthenticatedAccout) {
+      primary_account_manager->SetAuthenticatedAccountInfo(kTestGaiaId,
+                                                           kTestEmail);
     }
 
     auto accounts_cookie_mutator = std::make_unique<AccountsCookieMutatorImpl>(
@@ -325,9 +330,10 @@
 
     identity_manager_.reset(new IdentityManager(
         std::move(account_tracker_service), std::move(token_service),
-        std::move(gaia_cookie_manager_service), std::move(signin_manager),
-        std::move(account_fetcher_service), nullptr, nullptr,
-        std::move(accounts_cookie_mutator), std::move(diagnostics_provider)));
+        std::move(gaia_cookie_manager_service),
+        std::move(primary_account_manager), std::move(account_fetcher_service),
+        nullptr, nullptr, std::move(accounts_cookie_mutator),
+        std::move(diagnostics_provider)));
     identity_manager_observer_.reset(
         new TestIdentityManagerObserver(identity_manager_.get()));
     identity_manager_diagnostics_observer_.reset(
@@ -382,7 +388,8 @@
   DISALLOW_COPY_AND_ASSIGN(IdentityManagerTest);
 };
 
-// Test that IdentityManager starts off with the information in SigninManager.
+// Test that IdentityManager starts off with the information in
+// PrimaryAccountManager.
 TEST_F(IdentityManagerTest, PrimaryAccountInfoAtStartup) {
   CoreAccountInfo primary_account_info =
       identity_manager()->GetPrimaryAccountInfo();
@@ -993,7 +1000,7 @@
   std::set<std::string> scopes{"scope"};
   std::string access_token = "access_token";
 
-  identity_manager()->GetSigninManager()->SetAuthenticatedAccountInfo(
+  identity_manager()->GetPrimaryAccountManager()->SetAuthenticatedAccountInfo(
       kTestGaiaId, kTestEmail);
   token_service()->UpdateCredentials(primary_account_id(), "refresh_token");
 
@@ -1032,7 +1039,7 @@
   identity_manager_diagnostics_observer()
       ->set_on_access_token_requested_callback(run_loop.QuitClosure());
 
-  identity_manager()->GetSigninManager()->SetAuthenticatedAccountInfo(
+  identity_manager()->GetPrimaryAccountManager()->SetAuthenticatedAccountInfo(
       kTestGaiaId, kTestEmail);
   token_service()->UpdateCredentials(primary_account_id(), "refresh_token");
 
@@ -1119,7 +1126,7 @@
   identity_manager_diagnostics_observer()
       ->set_on_access_token_requested_callback(run_loop.QuitClosure());
 
-  identity_manager()->GetSigninManager()->SetAuthenticatedAccountInfo(
+  identity_manager()->GetPrimaryAccountManager()->SetAuthenticatedAccountInfo(
       kTestGaiaId, kTestEmail);
   token_service()->UpdateCredentials(primary_account_id(), "refresh_token");
 
@@ -1172,7 +1179,7 @@
   identity_manager_diagnostics_observer()
       ->set_on_access_token_request_completed_callback(run_loop.QuitClosure());
 
-  identity_manager()->GetSigninManager()->SetAuthenticatedAccountInfo(
+  identity_manager()->GetPrimaryAccountManager()->SetAuthenticatedAccountInfo(
       kTestGaiaId, kTestEmail);
   token_service()->UpdateCredentials(primary_account_id(), "refresh_token");
   token_service()->set_auto_post_fetch_response_on_message_loop(true);
@@ -1468,7 +1475,7 @@
   identity_manager_observer()->SetOnRefreshTokensLoadedCallback(
       run_loop.QuitClosure());
 
-  // Credentials are already loaded in SigninManager::Initialize()
+  // Credentials are already loaded in PrimaryAccountManager::Initialize()
   // which runs even before the IdentityManager is created. That's why
   // we fake the credentials loaded state and force another load in
   // order to be able to capture the TokensLoaded event.
@@ -1904,7 +1911,7 @@
 
 TEST_F(IdentityManagerTest,
        BatchChangeObserversAreNotifiedOnCredentialsUpdate) {
-  identity_manager()->GetSigninManager()->SetAuthenticatedAccountInfo(
+  identity_manager()->GetPrimaryAccountManager()->SetAuthenticatedAccountInfo(
       kTestGaiaId, kTestEmail);
   token_service()->UpdateCredentials(primary_account_id(), "refresh_token");
 
@@ -1997,7 +2004,7 @@
   identity_manager_observer()->SetOnRefreshTokensLoadedCallback(
       run_loop.QuitClosure());
 
-  // Credentials are already loaded in SigninManager::Initialize()
+  // Credentials are already loaded in PrimaryAccountManager::Initialize()
   // which runs even before the IdentityManager is created. That's why
   // we fake the credentials loaded state and force another load in
   // order to test AreRefreshTokensLoaded.
diff --git a/services/identity/public/cpp/identity_test_environment.cc b/services/identity/public/cpp/identity_test_environment.cc
index eefe2c88..3921f581 100644
--- a/services/identity/public/cpp/identity_test_environment.cc
+++ b/services/identity/public/cpp/identity_test_environment.cc
@@ -13,7 +13,7 @@
 #include "components/signin/core/browser/fake_profile_oauth2_token_service.h"
 #include "components/signin/core/browser/gaia_cookie_manager_service.h"
 #include "components/signin/core/browser/identity_manager_wrapper.h"
-#include "components/signin/core/browser/signin_manager.h"
+#include "components/signin/core/browser/primary_account_policy_manager.h"
 #include "components/signin/core/browser/test_signin_client.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
 #include "google_apis/gaia/oauth2_access_token_consumer.h"
@@ -198,17 +198,17 @@
       signin_client, token_service.get(), account_tracker_service.get(),
       std::make_unique<image_fetcher::FakeImageDecoder>());
 
-  std::unique_ptr<SigninManagerBase> signin_manager =
+  std::unique_ptr<PrimaryAccountManager> primary_account_manager =
 #if defined(OS_CHROMEOS)
-      std::make_unique<SigninManagerBase>(signin_client, token_service.get(),
-                                          account_tracker_service.get(),
-                                          account_consistency);
+      std::make_unique<PrimaryAccountManager>(
+          signin_client, token_service.get(), account_tracker_service.get(),
+          account_consistency);
 #else
-      std::make_unique<SigninManager>(signin_client, token_service.get(),
-                                      account_tracker_service.get(),
-                                      account_consistency);
+      std::make_unique<PrimaryAccountPolicyManager>(
+          signin_client, token_service.get(), account_tracker_service.get(),
+          account_consistency);
 #endif
-  signin_manager->Initialize(pref_service);
+  primary_account_manager->Initialize(pref_service);
 
   std::unique_ptr<GaiaCookieManagerService> gaia_cookie_manager_service =
       std::make_unique<GaiaCookieManagerService>(token_service.get(),
@@ -219,13 +219,14 @@
 
 #if !defined(OS_CHROMEOS)
   primary_account_mutator = std::make_unique<PrimaryAccountMutatorImpl>(
-      account_tracker_service.get(), signin_manager.get(), pref_service);
+      account_tracker_service.get(), primary_account_manager.get(),
+      pref_service);
 #endif
 
 #if !defined(OS_ANDROID) && !defined(OS_IOS)
   accounts_mutator = std::make_unique<AccountsMutatorImpl>(
-      token_service.get(), account_tracker_service.get(), signin_manager.get(),
-      pref_service);
+      token_service.get(), account_tracker_service.get(),
+      primary_account_manager.get(), pref_service);
 #endif
 
   auto diagnostics_provider = std::make_unique<DiagnosticsProviderImpl>(
@@ -236,10 +237,10 @@
 
   return std::make_unique<IdentityManagerWrapper>(
       std::move(account_tracker_service), std::move(token_service),
-      std::move(gaia_cookie_manager_service), std::move(signin_manager),
-      std::move(account_fetcher_service), std::move(primary_account_mutator),
-      std::move(accounts_mutator), std::move(accounts_cookie_mutator),
-      std::move(diagnostics_provider));
+      std::move(gaia_cookie_manager_service),
+      std::move(primary_account_manager), std::move(account_fetcher_service),
+      std::move(primary_account_mutator), std::move(accounts_mutator),
+      std::move(accounts_cookie_mutator), std::move(diagnostics_provider));
 }
 
 IdentityTestEnvironment::~IdentityTestEnvironment() {
diff --git a/services/identity/public/cpp/identity_test_environment.h b/services/identity/public/cpp/identity_test_environment.h
index 2f726f39..c1dbeb0 100644
--- a/services/identity/public/cpp/identity_test_environment.h
+++ b/services/identity/public/cpp/identity_test_environment.h
@@ -91,8 +91,8 @@
 
   // Sets the primary account for the given email address, generating a GAIA ID
   // that corresponds uniquely to that email address. On non-ChromeOS, results
-  // in the firing of the IdentityManager and SigninManager callbacks for signin
-  // success. Blocks until the primary account is set. Returns the
+  // in the firing of the IdentityManager and PrimaryAccountManager callbacks
+  // for signin success. Blocks until the primary account is set. Returns the
   // CoreAccountInfo of the newly-set account.
   CoreAccountInfo SetPrimaryAccount(const std::string& email);
 
@@ -115,15 +115,15 @@
   // Makes the primary account available for the given email address, generating
   // a GAIA ID and refresh token that correspond uniquely to that email address.
   // On non-ChromeOS platforms, this will also result in the firing of the
-  // IdentityManager and SigninManager callbacks for signin success. On all
-  // platforms, this method blocks until the primary account is available.
+  // IdentityManager and PrimaryAccountManager callbacks for signin success. On
+  // all platforms, this method blocks until the primary account is available.
   // Returns the AccountInfo of the newly-available account.
   AccountInfo MakePrimaryAccountAvailable(const std::string& email);
 
   // Clears the primary account if present, with |policy| used to determine
   // whether to keep or remove all accounts. On non-ChromeOS, results in the
-  // firing of the IdentityManager and SigninManager callbacks for signout.
-  // Blocks until the primary account is cleared.
+  // firing of the IdentityManager and PrimaryAccountManager callbacks for
+  // signout. Blocks until the primary account is cleared.
   void ClearPrimaryAccount(
       ClearPrimaryAccountPolicy policy = ClearPrimaryAccountPolicy::DEFAULT);
 
diff --git a/services/identity/public/cpp/identity_test_utils.cc b/services/identity/public/cpp/identity_test_utils.cc
index 5e94362..b5b2840 100644
--- a/services/identity/public/cpp/identity_test_utils.cc
+++ b/services/identity/public/cpp/identity_test_utils.cc
@@ -77,8 +77,9 @@
 CoreAccountInfo SetPrimaryAccount(IdentityManager* identity_manager,
                                   const std::string& email) {
   DCHECK(!identity_manager->HasPrimaryAccount());
-  SigninManagerBase* signin_manager = identity_manager->GetSigninManager();
-  DCHECK(!signin_manager->IsAuthenticated());
+  PrimaryAccountManager* primary_account_manager =
+      identity_manager->GetPrimaryAccountManager();
+  DCHECK(!primary_account_manager->IsAuthenticated());
 
   AccountTrackerService* account_tracker_service =
       identity_manager->GetAccountTrackerService();
@@ -101,10 +102,10 @@
   // test-only API.
   identity_manager->LegacySetPrimaryAccount(gaia_id, email);
 #else
-  signin_manager->SignIn(email);
+  primary_account_manager->SignIn(email);
 #endif
 
-  DCHECK(signin_manager->IsAuthenticated());
+  DCHECK(primary_account_manager->IsAuthenticated());
   DCHECK(identity_manager->HasPrimaryAccount());
   return identity_manager->GetPrimaryAccountInfo();
 }
@@ -161,7 +162,8 @@
   TestIdentityManagerObserver signout_observer(identity_manager);
   signout_observer.SetOnPrimaryAccountClearedCallback(run_loop.QuitClosure());
 
-  SigninManagerBase* signin_manager = identity_manager->GetSigninManager();
+  PrimaryAccountManager* primary_account_manager =
+      identity_manager->GetPrimaryAccountManager();
   signin_metrics::ProfileSignout signout_source_metric =
       signin_metrics::SIGNOUT_TEST;
   signin_metrics::SignoutDelete signout_delete_metric =
@@ -169,15 +171,16 @@
 
   switch (policy) {
     case ClearPrimaryAccountPolicy::DEFAULT:
-      signin_manager->SignOut(signout_source_metric, signout_delete_metric);
+      primary_account_manager->SignOut(signout_source_metric,
+                                       signout_delete_metric);
       break;
     case ClearPrimaryAccountPolicy::KEEP_ALL_ACCOUNTS:
-      signin_manager->SignOutAndKeepAllAccounts(signout_source_metric,
-                                                signout_delete_metric);
+      primary_account_manager->SignOutAndKeepAllAccounts(signout_source_metric,
+                                                         signout_delete_metric);
       break;
     case ClearPrimaryAccountPolicy::REMOVE_ALL_ACCOUNTS:
-      signin_manager->SignOutAndRemoveAllAccounts(signout_source_metric,
-                                                  signout_delete_metric);
+      primary_account_manager->SignOutAndRemoveAllAccounts(
+          signout_source_metric, signout_delete_metric);
       break;
   }
 
diff --git a/services/identity/public/cpp/identity_test_utils.h b/services/identity/public/cpp/identity_test_utils.h
index ef47d569..891b94f9 100644
--- a/services/identity/public/cpp/identity_test_utils.h
+++ b/services/identity/public/cpp/identity_test_utils.h
@@ -47,8 +47,8 @@
 // Sets the primary account (which must not already be set) to the given email
 // address, generating a GAIA ID that corresponds uniquely to that email
 // address. On non-ChromeOS, results in the firing of the IdentityManager and
-// SigninManager callbacks for signin success. Blocks until the primary account
-// is set. Returns the CoreAccountInfo of the newly-set account.
+// PrimaryAccountManager callbacks for signin success. Blocks until the primary
+// account is set. Returns the CoreAccountInfo of the newly-set account.
 // NOTE: See disclaimer at top of file re: direct usage.
 CoreAccountInfo SetPrimaryAccount(IdentityManager* identity_manager,
                                   const std::string& email);
@@ -74,8 +74,8 @@
 // Makes the primary account (which must not already be set) available for the
 // given email address, generating a GAIA ID and refresh token that correspond
 // uniquely to that email address. On non-ChromeOS, results in the firing of the
-// IdentityManager and SigninManager callbacks for signin success. Blocks until
-// the primary account is available. Returns the AccountInfo of the
+// IdentityManager and PrimaryAccountManager callbacks for signin success.
+// Blocks until the primary account is available. Returns the AccountInfo of the
 // newly-available account.
 // NOTE: See disclaimer at top of file re: direct usage.
 AccountInfo MakePrimaryAccountAvailable(IdentityManager* identity_manager,
@@ -83,8 +83,8 @@
 
 // Clears the primary account if present, with |policy| used to determine
 // whether to keep or remove all accounts. On non-ChromeOS, results in the
-// firing of the IdentityManager and SigninManager callbacks for signout. Blocks
-// until the primary account is cleared.
+// firing of the IdentityManager and PrimaryAccountManager callbacks for
+// signout. Blocks until the primary account is cleared.
 // NOTE: See disclaimer at top of file re: direct usage.
 void ClearPrimaryAccount(
     IdentityManager* identity_manager,
diff --git a/services/identity/public/cpp/primary_account_mutator_impl.cc b/services/identity/public/cpp/primary_account_mutator_impl.cc
index 2c7075c..e0ff567 100644
--- a/services/identity/public/cpp/primary_account_mutator_impl.cc
+++ b/services/identity/public/cpp/primary_account_mutator_impl.cc
@@ -8,20 +8,20 @@
 
 #include "components/prefs/pref_service.h"
 #include "components/signin/core/browser/account_tracker_service.h"
-#include "components/signin/core/browser/signin_manager_base.h"
+#include "components/signin/core/browser/primary_account_manager.h"
 #include "components/signin/core/browser/signin_pref_names.h"
 
 namespace identity {
 
 PrimaryAccountMutatorImpl::PrimaryAccountMutatorImpl(
     AccountTrackerService* account_tracker,
-    SigninManagerBase* signin_manager,
+    PrimaryAccountManager* primary_account_manager,
     PrefService* pref_service)
     : account_tracker_(account_tracker),
-      signin_manager_(signin_manager),
+      primary_account_manager_(primary_account_manager),
       pref_service_(pref_service) {
   DCHECK(account_tracker_);
-  DCHECK(signin_manager_);
+  DCHECK(primary_account_manager_);
   DCHECK(pref_service_);
 }
 
@@ -32,7 +32,7 @@
   if (!pref_service_->GetBoolean(prefs::kSigninAllowed))
     return false;
 
-  if (signin_manager_->IsAuthenticated())
+  if (primary_account_manager_->IsAuthenticated())
     return false;
 
   AccountInfo account_info = account_tracker_->GetAccountInfo(account_id);
@@ -41,7 +41,7 @@
 
   // TODO(crbug.com/889899): should check that the account email is allowed.
 
-  signin_manager_->SignIn(account_info.email);
+  primary_account_manager_->SignIn(account_info.email);
   return true;
 }
 
@@ -49,19 +49,20 @@
     ClearAccountsAction action,
     signin_metrics::ProfileSignout source_metric,
     signin_metrics::SignoutDelete delete_metric) {
-  if (!signin_manager_->IsAuthenticated())
+  if (!primary_account_manager_->IsAuthenticated())
     return false;
 
   switch (action) {
     case PrimaryAccountMutator::ClearAccountsAction::kDefault:
-      signin_manager_->SignOut(source_metric, delete_metric);
+      primary_account_manager_->SignOut(source_metric, delete_metric);
       break;
     case PrimaryAccountMutator::ClearAccountsAction::kKeepAll:
-      signin_manager_->SignOutAndKeepAllAccounts(source_metric, delete_metric);
+      primary_account_manager_->SignOutAndKeepAllAccounts(source_metric,
+                                                          delete_metric);
       break;
     case PrimaryAccountMutator::ClearAccountsAction::kRemoveAll:
-      signin_manager_->SignOutAndRemoveAllAccounts(source_metric,
-                                                   delete_metric);
+      primary_account_manager_->SignOutAndRemoveAllAccounts(source_metric,
+                                                            delete_metric);
       break;
   }
 
diff --git a/services/identity/public/cpp/primary_account_mutator_impl.h b/services/identity/public/cpp/primary_account_mutator_impl.h
index 7a4e2c6..99f6398 100644
--- a/services/identity/public/cpp/primary_account_mutator_impl.h
+++ b/services/identity/public/cpp/primary_account_mutator_impl.h
@@ -9,16 +9,16 @@
 
 class AccountTrackerService;
 class PrefService;
-class SigninManagerBase;
+class PrimaryAccountManager;
 
 namespace identity {
 
 // Concrete implementation of PrimaryAccountMutator that is based on the
-// SigninManager API. It is supported on all platform except Chrome OS.
+// PrimaryAccountManager API. It is supported on all platform except Chrome OS.
 class PrimaryAccountMutatorImpl : public PrimaryAccountMutator {
  public:
   PrimaryAccountMutatorImpl(AccountTrackerService* account_tracker,
-                            SigninManagerBase* signin_manager,
+                            PrimaryAccountManager* primary_account_manager,
                             PrefService* pref_service);
   ~PrimaryAccountMutatorImpl() override;
 
@@ -33,7 +33,7 @@
   // Pointers to the services used by the PrimaryAccountMutatorImpl. They
   // *must* outlive this instance.
   AccountTrackerService* account_tracker_ = nullptr;
-  SigninManagerBase* signin_manager_ = nullptr;
+  PrimaryAccountManager* primary_account_manager_ = nullptr;
   PrefService* pref_service_ = nullptr;
 };
 
diff --git a/services/identity/public/cpp/primary_account_mutator_unittest.cc b/services/identity/public/cpp/primary_account_mutator_unittest.cc
index 7ee1a1a..8781dd0 100644
--- a/services/identity/public/cpp/primary_account_mutator_unittest.cc
+++ b/services/identity/public/cpp/primary_account_mutator_unittest.cc
@@ -405,9 +405,9 @@
       signin_metrics::SIGNOUT_TEST,
       signin_metrics::SignoutDelete::IGNORE_METRIC));
 
-  // The underlying SigninManager in IdentityTestEnvironment will be created
-  // with signin::AccountConsistencyMethod::kDisabled, which should result in
-  // ClearPrimaryAccount() removing all the tokens.
+  // The underlying PrimaryAccountManager in IdentityTestEnvironment will be
+  // created with signin::AccountConsistencyMethod::kDisabled, which should
+  // result in ClearPrimaryAccount() removing all the tokens.
   EXPECT_FALSE(identity_manager->HasPrimaryAccount());
   EXPECT_FALSE(identity_manager->HasAccountWithRefreshToken(
       primary_account_info.account_id));
diff --git a/services/network/network_context.cc b/services/network/network_context.cc
index 2eb42bf8..28ca367 100644
--- a/services/network/network_context.cc
+++ b/services/network/network_context.cc
@@ -26,6 +26,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/task/post_task.h"
 #include "base/task/task_traits.h"
+#include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
 #include "components/cookie_config/cookie_store_util.h"
 #include "components/domain_reliability/monitor.h"
@@ -1386,21 +1387,6 @@
     cache->OnExternalCacheHit(url, http_method, top_frame_origin);
 }
 
-void NetworkContext::WriteCacheMetadata(const GURL& url,
-                                        net::RequestPriority priority,
-                                        base::Time expected_response_time,
-                                        mojo_base::BigBuffer data) {
-  net::HttpCache* cache =
-      url_request_context_->http_transaction_factory()->GetCache();
-  if (!cache)
-    return;
-
-  auto buf = base::MakeRefCounted<net::IOBuffer>(data.size());
-  memcpy(buf->data(), data.data(), data.size());
-  cache->WriteMetadata(url, priority, expected_response_time, buf.get(),
-                       data.size());
-}
-
 void NetworkContext::SetCorsOriginAccessListsForOrigin(
     const url::Origin& source_origin,
     std::vector<mojom::CorsOriginPatternPtr> allow_patterns,
@@ -1712,7 +1698,7 @@
   scoped_refptr<SessionCleanupCookieStore> session_cleanup_cookie_store;
   if (params_->cookie_path) {
     scoped_refptr<base::SequencedTaskRunner> client_task_runner =
-        base::MessageLoopCurrent::Get()->task_runner();
+        base::ThreadTaskRunnerHandle::Get();
     scoped_refptr<base::SequencedTaskRunner> background_task_runner =
         base::CreateSequencedTaskRunnerWithTraits(
             {base::MayBlock(), net::GetCookieStoreBackgroundSequencePriority(),
diff --git a/services/network/network_context.h b/services/network/network_context.h
index 0f9e0fe..700ddb2 100644
--- a/services/network/network_context.h
+++ b/services/network/network_context.h
@@ -199,10 +199,6 @@
       const GURL& url,
       const std::string& http_method,
       const base::Optional<url::Origin>& top_frame_origin) override;
-  void WriteCacheMetadata(const GURL& url,
-                          net::RequestPriority priority,
-                          base::Time expected_response_time,
-                          mojo_base::BigBuffer data) override;
   void ClearHostCache(mojom::ClearDataFilterPtr filter,
                       ClearHostCacheCallback callback) override;
   void ClearHttpAuthCache(base::Time start_time,
diff --git a/services/network/public/cpp/simple_url_loader.cc b/services/network/public/cpp/simple_url_loader.cc
index 068b861..7a54f5f 100644
--- a/services/network/public/cpp/simple_url_loader.cc
+++ b/services/network/public/cpp/simple_url_loader.cc
@@ -1163,9 +1163,9 @@
          *resource_request_->request_body->elements()) {
       // Files should be attached with AttachFileForUpload, so that (Once
       // supported) they can be opened in the current process.
-      //
-      // TODO(mmenke): Add a similar method for bytes, to allow streaming of
-      // large byte buffers to the network process when uploading.
+
+      // Bytes should be attached with AttachStringForUpload to allow
+      // streaming of large byte buffers to the network process when uploading.
       DCHECK(element.type() != mojom::DataElementType::kFile &&
              element.type() != mojom::DataElementType::kBytes);
     }
diff --git a/services/network/public/mojom/network_context.mojom b/services/network/public/mojom/network_context.mojom
index 69885a8b..18ccc3dd 100644
--- a/services/network/public/mojom/network_context.mojom
+++ b/services/network/public/mojom/network_context.mojom
@@ -611,13 +611,6 @@
   NotifyExternalCacheHit(url.mojom.Url url, string http_method,
                          url.mojom.Origin? top_frame_origin);
 
-  // Caches |data| associated with |url| and |expected_response_time| in the
-  // HttpCache related to this NetworkContext.
-  WriteCacheMetadata(url.mojom.Url url,
-                     RequestPriority priority,
-                     mojo_base.mojom.Time expected_response_time,
-                     mojo_base.mojom.BigBuffer data);
-
   // Clears the host cache. This will affect all NetworkContexts that share the
   // same HostResolved as the NetworkContext this is called on.
   //
diff --git a/services/network/test/test_network_context.h b/services/network/test/test_network_context.h
index cde07db..98b59d4f 100644
--- a/services/network/test/test_network_context.h
+++ b/services/network/test/test_network_context.h
@@ -153,10 +153,6 @@
       const GURL& url,
       const std::string& http_method,
       const base::Optional<url::Origin>& top_frame_origin) override {}
-  void WriteCacheMetadata(const GURL& url,
-                          net::RequestPriority priority,
-                          base::Time expected_response_time,
-                          mojo_base::BigBuffer data) override {}
   void VerifyCertForSignedExchange(
       const scoped_refptr<net::X509Certificate>& certificate,
       const GURL& url,
diff --git a/services/service_manager/sandbox/mac/gpu_v2.sb b/services/service_manager/sandbox/mac/gpu_v2.sb
index aeca837..18253476 100644
--- a/services/service_manager/sandbox/mac/gpu_v2.sb
+++ b/services/service_manager/sandbox/mac/gpu_v2.sb
@@ -9,8 +9,11 @@
 
 (allow-cvms-blobs)
 
+(allow ipc-posix-shm)
+
 ; Allow communication between the GPU process and the UI server.
 (allow mach-lookup
+  (global-name "com.apple.cfprefsd.agent")
   (global-name "com.apple.cfprefsd.daemon")
   (global-name "com.apple.CoreServices.coreservicesd")
   (global-name "com.apple.coreservices.launchservicesd")
diff --git a/skia/public/interfaces/test/struct_traits_unittest.cc b/skia/public/interfaces/test/struct_traits_unittest.cc
index 194886e..0ec1d48 100644
--- a/skia/public/interfaces/test/struct_traits_unittest.cc
+++ b/skia/public/interfaces/test/struct_traits_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 "base/message_loop/message_loop.h"
+#include "base/test/scoped_task_environment.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "skia/public/interfaces/test/traits_test_service.mojom.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -46,7 +46,7 @@
     std::move(callback).Run(t);
   }
 
-  base::MessageLoop loop_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
   mojo::BindingSet<TraitsTestService> traits_test_bindings_;
 
   DISALLOW_COPY_AND_ASSIGN(StructTraitsTest);
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl
index 619b094..34d3749b 100644
--- a/testing/buildbot/gn_isolate_map.pyl
+++ b/testing/buildbot/gn_isolate_map.pyl
@@ -1300,6 +1300,16 @@
     "label": "//ios/chrome/test/earl_grey2:ios_chrome_smoke_eg2tests_module",
     "type": "raw",
   },
+  "ios_chrome_ui_eg2tests_module": {
+    "args": [],
+    "label": "//ios/chrome/test/earl_grey2:ios_chrome_ui_eg2tests_module",
+    "type": "raw",
+  },
+"ios_chrome_web_eg2tests_module": {
+    "args": [],
+    "label": "//ios/chrome/test/earl_grey2:ios_chrome_web_eg2tests_module",
+    "type": "raw",
+  },
   "ios_web_shell_eg2tests_module": {
     "args": [],
     "label": "//ios/web/shell/test:ios_web_shell_eg2tests_module",
diff --git a/testing/buildbot/manage.py b/testing/buildbot/manage.py
index 8f32988..6d0b3a45 100755
--- a/testing/buildbot/manage.py
+++ b/testing/buildbot/manage.py
@@ -100,6 +100,8 @@
   'ios_chrome_unittests',
   'ios_chrome_web_egtests',
   'ios_chrome_smoke_eg2tests_module',
+  'ios_chrome_ui_eg2tests_module',
+  'ios_chrome_web_eg2tests_module',
   'ios_web_shell_eg2tests_module',
   'ios_components_unittests',
   'ios_net_unittests',
diff --git a/third_party/blink/public/BUILD.gn b/third_party/blink/public/BUILD.gn
index 57c25c1..62d3bea4 100644
--- a/third_party/blink/public/BUILD.gn
+++ b/third_party/blink/public/BUILD.gn
@@ -33,6 +33,7 @@
   public_deps = [
     ":test_headers",
     "//third_party/blink/renderer/modules/exported:test_support",
+    "//third_party/blink/renderer/modules/mediastream:test_support",
     "//third_party/blink/renderer/platform:test_support",
   ]
 }
@@ -102,6 +103,12 @@
     "platform/scheduler/test/renderer_scheduler_test_support.h",
     "platform/scheduler/test/web_fake_thread_scheduler.h",
     "platform/scheduler/test/web_mock_thread_scheduler.h",
+
+    # TODO(crbug.com/704136): Remove the group of mock_media_*.h
+    # files below when content/renderer/media/stream Onion souping
+    # is done.
+    "web/modules/mediastream/mock_media_stream_registry.h",
+    "web/modules/mediastream/mock_media_stream_video_source.h",
   ]
   deps = [
     ":blink_headers",
@@ -364,6 +371,7 @@
     "web/modules/mediastream/media_stream_constraints_util_sets.h",
     "web/modules/mediastream/media_stream_constraints_util_video_device.h",
     "web/modules/mediastream/media_stream_video_capturer_source.h",
+    "web/modules/mediastream/media_stream_video_renderer_sink.h",
     "web/modules/mediastream/media_stream_video_sink.h",
     "web/modules/mediastream/media_stream_video_source.h",
     "web/modules/mediastream/media_stream_video_track.h",
diff --git a/third_party/blink/public/mojom/worker/dedicated_worker_host_factory.mojom b/third_party/blink/public/mojom/worker/dedicated_worker_host_factory.mojom
index 6a0e68b..baa807ae 100644
--- a/third_party/blink/public/mojom/worker/dedicated_worker_host_factory.mojom
+++ b/third_party/blink/public/mojom/worker/dedicated_worker_host_factory.mojom
@@ -4,6 +4,7 @@
 
 module blink.mojom;
 
+import "services/network/public/mojom/fetch_api.mojom";
 import "services/service_manager/public/mojom/interface_provider.mojom";
 import "third_party/blink/public/mojom/blob/blob_url_store.mojom";
 import "third_party/blink/public/mojom/loader/url_loader_factory_bundle.mojom";
@@ -82,6 +83,7 @@
   CreateWorkerHostAndStartScriptLoad(
       url.mojom.Url script_url,
       url.mojom.Origin origin,
+      network.mojom.FetchCredentialsMode credentials_mode,
       blink.mojom.BlobURLToken? blob_url_token,
       DedicatedWorkerHostFactoryClient client);
 };
diff --git a/third_party/blink/public/platform/modules/mediastream/media_stream_audio_processor_options.h b/third_party/blink/public/platform/modules/mediastream/media_stream_audio_processor_options.h
index 5bd8311..102b277 100644
--- a/third_party/blink/public/platform/modules/mediastream/media_stream_audio_processor_options.h
+++ b/third_party/blink/public/platform/modules/mediastream/media_stream_audio_processor_options.h
@@ -90,15 +90,6 @@
   bool goog_experimental_auto_gain_control = true;
 };
 
-// Enables the echo cancellation.
-BLINK_PLATFORM_EXPORT void EnableEchoCancellation(
-    AudioProcessing::Config* apm_config);
-
-// Enables the noise suppression with the given level.
-BLINK_PLATFORM_EXPORT void EnableNoiseSuppression(
-    AudioProcessing::Config* apm_config,
-    AudioProcessing::Config::NoiseSuppression::Level ns_level);
-
 // Enables the typing detection with the given detector.
 BLINK_PLATFORM_EXPORT void EnableTypingDetection(
     AudioProcessing::Config* apm_config,
@@ -119,12 +110,6 @@
 BLINK_PLATFORM_EXPORT void StopEchoCancellationDump(
     AudioProcessing* audio_processing);
 
-// Loads fixed gains for pre-amplifier and gain control from config JSON string.
-BLINK_PLATFORM_EXPORT void GetExtraGainConfig(
-    const base::Optional<std::string>& audio_processing_platform_config_json,
-    base::Optional<double>* pre_amplifier_fixed_gain_factor,
-    base::Optional<double>* gain_control_compression_gain_db);
-
 // Enables automatic gain control with flags and optional configures.
 BLINK_PLATFORM_EXPORT void ConfigAutomaticGainControl(
     AudioProcessing::Config* apm_config,
@@ -135,10 +120,11 @@
     base::Optional<int> hybrid_agc_saturation_margin,
     base::Optional<double> compression_gain_db);
 
-// Enables pre-amplifier with given gain factor if the optional |factor| is set.
-BLINK_PLATFORM_EXPORT void ConfigPreAmplifier(
+BLINK_PLATFORM_EXPORT void PopulateApmConfig(
     AudioProcessing::Config* apm_config,
-    base::Optional<double> fixed_gain_factor);
+    const AudioProcessingProperties& properties,
+    const base::Optional<std::string>& audio_processing_platform_config_json,
+    base::Optional<double>* gain_control_compression_gain_db);
 
 }  // namespace blink
 
diff --git a/third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h b/third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h
index 4a78b88..f63aaf0 100644
--- a/third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h
+++ b/third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h
@@ -70,7 +70,7 @@
 
   // For service worker clients.
   virtual blink::mojom::ControllerServiceWorkerMode
-  IsControlledByServiceWorker() = 0;
+  GetControllerServiceWorkerMode() = 0;
 
   // For service worker clients. Returns an identifier of the controller service
   // worker associated with the loading context.
diff --git a/third_party/blink/public/platform/web_dedicated_worker_host_factory_client.h b/third_party/blink/public/platform/web_dedicated_worker_host_factory_client.h
index b9b9cc8..6baa3ebe 100644
--- a/third_party/blink/public/platform/web_dedicated_worker_host_factory_client.h
+++ b/third_party/blink/public/platform/web_dedicated_worker_host_factory_client.h
@@ -7,6 +7,7 @@
 
 #include "base/memory/ref_counted.h"
 #include "mojo/public/cpp/system/message_pipe.h"
+#include "services/network/public/mojom/fetch_api.mojom-shared.h"
 
 namespace base {
 class SingleThreadTaskRunner;
@@ -34,6 +35,7 @@
   virtual void CreateWorkerHost(
       const blink::WebURL& script_url,
       const blink::WebSecurityOrigin& script_origin,
+      network::mojom::FetchCredentialsMode credentials_mode,
       mojo::ScopedMessagePipeHandle blob_url_token) = 0;
 
   // Clones the given WebWorkerFetchContext for nested workers.
diff --git a/third_party/blink/public/platform/web_runtime_features.h b/third_party/blink/public/platform/web_runtime_features.h
index f1d73e93..a9a04be 100644
--- a/third_party/blink/public/platform/web_runtime_features.h
+++ b/third_party/blink/public/platform/web_runtime_features.h
@@ -90,7 +90,6 @@
   BLINK_PLATFORM_EXPORT static void EnableBlockingFocusWithoutUserActivation(
       bool);
   BLINK_PLATFORM_EXPORT static void EnableCacheInlineScriptCode(bool);
-  BLINK_PLATFORM_EXPORT static void EnableIsolatedCodeCache(bool);
   BLINK_PLATFORM_EXPORT static void EnableWasmCodeCache(bool);
   BLINK_PLATFORM_EXPORT static void EnableCanvas2dImageChromium(bool);
   BLINK_PLATFORM_EXPORT static void EnableCSSHexAlphaColor(bool);
diff --git a/third_party/blink/public/platform/web_worker_fetch_context.h b/third_party/blink/public/platform/web_worker_fetch_context.h
index f67d193..7d647804 100644
--- a/third_party/blink/public/platform/web_worker_fetch_context.h
+++ b/third_party/blink/public/platform/web_worker_fetch_context.h
@@ -90,9 +90,10 @@
   // worker)
   virtual void WillSendRequest(WebURLRequest&) = 0;
 
-  // Whether the fetch context is controlled by a service worker.
+  // Returns whether a controller service worker exists and if it has fetch
+  // handler.
   virtual blink::mojom::ControllerServiceWorkerMode
-  IsControlledByServiceWorker() const = 0;
+  GetControllerServiceWorkerMode() const = 0;
 
   // This flag is used to block all mixed content in subframes.
   virtual void SetIsOnSubframe(bool) {}
diff --git a/third_party/blink/public/web/modules/mediastream/DEPS b/third_party/blink/public/web/modules/mediastream/DEPS
index 53880d2..9ef7b3b 100644
--- a/third_party/blink/public/web/modules/mediastream/DEPS
+++ b/third_party/blink/public/web/modules/mediastream/DEPS
@@ -14,3 +14,9 @@
     "+media/capture",
     "+ui/gfx/geometry/size.h"
 ]
+
+specific_include_rules = {
+    "mock_media_stream_video_source.h" : [
+        "+testing/gmock/include/gmock/gmock.h",
+    ],
+}
diff --git a/content/renderer/media/stream/media_stream_video_renderer_sink.h b/third_party/blink/public/web/modules/mediastream/media_stream_video_renderer_sink.h
similarity index 87%
rename from content/renderer/media/stream/media_stream_video_renderer_sink.h
rename to third_party/blink/public/web/modules/mediastream/media_stream_video_renderer_sink.h
index f417cff..715fea8 100644
--- a/content/renderer/media/stream/media_stream_video_renderer_sink.h
+++ b/third_party/blink/public/web/modules/mediastream/media_stream_video_renderer_sink.h
@@ -2,16 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CONTENT_RENDERER_MEDIA_STREAM_MEDIA_STREAM_VIDEO_RENDERER_SINK_H_
-#define CONTENT_RENDERER_MEDIA_STREAM_MEDIA_STREAM_VIDEO_RENDERER_SINK_H_
+#ifndef THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_MEDIASTREAM_MEDIA_STREAM_VIDEO_RENDERER_SINK_H_
+#define THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_MEDIASTREAM_MEDIA_STREAM_VIDEO_RENDERER_SINK_H_
 
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/threading/thread_checker.h"
-#include "content/common/content_export.h"
 #include "third_party/blink/public/common/media/video_capture.h"
 #include "third_party/blink/public/platform/modules/mediastream/web_media_stream_video_renderer.h"
+#include "third_party/blink/public/platform/web_common.h"
 #include "third_party/blink/public/platform/web_media_stream_track.h"
 #include "third_party/blink/public/web/modules/mediastream/media_stream_video_sink.h"
 #include "ui/gfx/geometry/size.h"
@@ -20,7 +20,7 @@
 class SingleThreadTaskRunner;
 }  // namespace base
 
-namespace content {
+namespace blink {
 
 // MediaStreamVideoRendererSink is a blink::WebMediaStreamVideoRenderer designed
 // for rendering Video MediaStreamTracks [1], MediaStreamVideoRendererSink
@@ -34,7 +34,7 @@
 // TODO(wuchengli): Add unit test. See the link below for reference.
 // https://src.chromium.org/viewvc/chrome/trunk/src/content/renderer/media/rtc_
 // video_decoder_unittest.cc?revision=180591&view=markup
-class CONTENT_EXPORT MediaStreamVideoRendererSink
+class BLINK_EXPORT MediaStreamVideoRendererSink
     : public blink::WebMediaStreamVideoRenderer,
       public blink::MediaStreamVideoSink {
  public:
@@ -87,6 +87,6 @@
   DISALLOW_COPY_AND_ASSIGN(MediaStreamVideoRendererSink);
 };
 
-}  // namespace content
+}  // namespace blink
 
-#endif  // CONTENT_RENDERER_MEDIA_STREAM_MEDIA_STREAM_VIDEO_RENDERER_SINK_H_
+#endif  // THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_MEDIASTREAM_MEDIA_STREAM_VIDEO_RENDERER_SINK_H_
diff --git a/content/renderer/media/stream/mock_media_stream_registry.h b/third_party/blink/public/web/modules/mediastream/mock_media_stream_registry.h
similarity index 67%
rename from content/renderer/media/stream/mock_media_stream_registry.h
rename to third_party/blink/public/web/modules/mediastream/mock_media_stream_registry.h
index 7b5ee2e7..bbe30d0 100644
--- a/content/renderer/media/stream/mock_media_stream_registry.h
+++ b/third_party/blink/public/web/modules/mediastream/mock_media_stream_registry.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CONTENT_RENDERER_MEDIA_STREAM_MOCK_MEDIA_STREAM_REGISTRY_H_
-#define CONTENT_RENDERER_MEDIA_STREAM_MOCK_MEDIA_STREAM_REGISTRY_H_
+#ifndef THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_MEDIASTREAM_MOCK_MEDIA_STREAM_REGISTRY_H_
+#define THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_MEDIASTREAM_MOCK_MEDIA_STREAM_REGISTRY_H_
 
 #include <string>
 
@@ -11,10 +11,8 @@
 #include "third_party/blink/public/platform/web_media_stream.h"
 
 namespace blink {
-class VideoTrackAdapterSettings;
-}
 
-namespace content {
+class VideoTrackAdapterSettings;
 
 // This class encapsulates creation of a Blink MediaStream having inside the
 // necessary Blink and Chromium, track and source. The Chrome Video source is
@@ -25,21 +23,21 @@
 
   void Init();
   void AddVideoTrack(const std::string& track_id,
-                     const blink::VideoTrackAdapterSettings& adapter_settings,
+                     const VideoTrackAdapterSettings& adapter_settings,
                      const base::Optional<bool>& noise_reduction,
                      bool is_screen_cast,
                      double min_frame_rate);
   void AddVideoTrack(const std::string& track_id);
   void AddAudioTrack(const std::string& track_id);
 
-  const blink::WebMediaStream test_stream() const { return test_stream_; }
+  const WebMediaStream test_stream() const { return test_stream_; }
 
   void reset() { test_stream_.Reset(); }
 
  private:
-  blink::WebMediaStream test_stream_;
+  WebMediaStream test_stream_;
 };
 
-}  // namespace content
+}  // namespace blink
 
-#endif  // CONTENT_RENDERER_MEDIA_STREAM_MOCK_MEDIA_STREAM_REGISTRY_H_
+#endif  // THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_MEDIASTREAM_MOCK_MEDIA_STREAM_REGISTRY_H_
diff --git a/content/renderer/media/stream/mock_media_stream_video_source.h b/third_party/blink/public/web/modules/mediastream/mock_media_stream_video_source.h
similarity index 90%
rename from content/renderer/media/stream/mock_media_stream_video_source.h
rename to third_party/blink/public/web/modules/mediastream/mock_media_stream_video_source.h
index 99bb3f6..0c469bc 100644
--- a/content/renderer/media/stream/mock_media_stream_video_source.h
+++ b/third_party/blink/public/web/modules/mediastream/mock_media_stream_video_source.h
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CONTENT_RENDERER_MEDIA_STREAM_MOCK_MEDIA_STREAM_VIDEO_SOURCE_H_
-#define CONTENT_RENDERER_MEDIA_STREAM_MOCK_MEDIA_STREAM_VIDEO_SOURCE_H_
+#ifndef THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_MEDIASTREAM_MOCK_MEDIA_STREAM_VIDEO_SOURCE_H_
+#define THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_MEDIASTREAM_MOCK_MEDIA_STREAM_VIDEO_SOURCE_H_
 
 #include "third_party/blink/public/web/modules/mediastream/media_stream_video_source.h"
 
 #include "base/macros.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
-namespace content {
+namespace blink {
 
 class MockMediaStreamVideoSource : public blink::MediaStreamVideoSource {
  public:
@@ -89,6 +89,6 @@
   DISALLOW_COPY_AND_ASSIGN(MockMediaStreamVideoSource);
 };
 
-}  // namespace content
+}  // namespace blink
 
-#endif  // CONTENT_RENDERER_MEDIA_STREAM_MOCK_MEDIA_STREAM_VIDEO_SOURCE_H_
+#endif  // THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_MEDIASTREAM_MOCK_MEDIA_STREAM_VIDEO_SOURCE_H_
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.cc b/third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.cc
index ea967fa..0f2accb 100644
--- a/third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.cc
+++ b/third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.cc
@@ -8,11 +8,27 @@
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
+#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
 
 namespace blink {
 
-V8TestingScope::V8TestingScope()
-    : holder_(std::make_unique<DummyPageHolder>()),
+namespace {
+
+std::unique_ptr<DummyPageHolder> CreateDummyPageHolder(const KURL& url) {
+  std::unique_ptr<DummyPageHolder> holder = std::make_unique<DummyPageHolder>();
+  if (url.IsValid()) {
+    holder->GetFrame().Loader().CommitNavigation(
+        WebNavigationParams::CreateWithHTMLBuffer(SharedBuffer::Create(), url),
+        nullptr /* extra_data */);
+    blink::test::RunPendingTasks();
+  }
+  return holder;
+}
+
+}  // namespace
+
+V8TestingScope::V8TestingScope(const KURL& url)
+    : holder_(CreateDummyPageHolder(url)),
       handle_scope_(GetIsolate()),
       context_(GetScriptState()->GetContext()),
       context_scope_(GetContext()),
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h b/third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h
index 0349072..5084a90 100644
--- a/third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h
+++ b/third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h
@@ -7,6 +7,7 @@
 
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/bindings/script_state.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
 #include "third_party/blink/renderer/platform/wtf/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/forward.h"
 #include "v8/include/v8.h"
@@ -17,13 +18,14 @@
 class DummyPageHolder;
 class ExecutionContext;
 class LocalFrame;
+class KURL;
 class Page;
 
 class V8TestingScope {
   STACK_ALLOCATED();
 
  public:
-  V8TestingScope();
+  explicit V8TestingScope(const KURL& url = KURL());
   ScriptState* GetScriptState() const;
   ExecutionContext* GetExecutionContext() const;
   v8::Isolate* GetIsolate() const;
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn
index dc2ce36..1e187be 100644
--- a/third_party/blink/renderer/core/BUILD.gn
+++ b/third_party/blink/renderer/core/BUILD.gn
@@ -2114,7 +2114,6 @@
     "streams/readable_stream_test.cc",
     "streams/stream_promise_resolver_test.cc",
     "streams/test_underlying_source.h",
-    "streams/transferable_streams_test.cc",
     "streams/transform_stream_test.cc",
     "streams/writable_stream_test.cc",
     "style/border_value_test.cc",
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_context.cc b/third_party/blink/renderer/core/display_lock/display_lock_context.cc
index a372a88..ac7356b 100644
--- a/third_party/blink/renderer/core/display_lock/display_lock_context.cc
+++ b/third_party/blink/renderer/core/display_lock/display_lock_context.cc
@@ -92,10 +92,7 @@
     : ContextLifecycleObserver(context),
       element_(element),
       document_(&element_->GetDocument()),
-      state_(this) {
-  if (document_->View())
-    document_->View()->RegisterForLifecycleNotifications(this);
-}
+      state_(this) {}
 
 DisplayLockContext::~DisplayLockContext() {
   DCHECK_EQ(state_, kUnlocked);
@@ -125,9 +122,6 @@
   FinishAcquireResolver(kDetach);
   CancelTimeoutTask();
   state_ = kUnlocked;
-
-  if (document_ && document_->View())
-    document_->View()->UnregisterFromLifecycleNotifications(this);
 }
 
 void DisplayLockContext::ContextDestroyed(ExecutionContext*) {
@@ -376,6 +370,7 @@
       break;
     case kDetach:
       (*resolver)->Detach();
+      break;
   }
   *resolver = nullptr;
   if (!HasResolver() && ConnectedToView())
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc
index 056cd637..0e6aa51 100644
--- a/third_party/blink/renderer/core/dom/document.cc
+++ b/third_party/blink/renderer/core/dom/document.cc
@@ -6454,7 +6454,7 @@
     // No source for a security context.
     // This can occur via document.implementation.createDocument().
     cookie_url_ = KURL(g_empty_string);
-    SetSecurityOrigin(SecurityOrigin::CreateUniqueOpaque());
+    SetSecurityOrigin(initializer.GetDocumentOrigin());
     InitContentSecurityPolicy();
     ApplyFeaturePolicy({});
     return;
diff --git a/third_party/blink/renderer/core/frame/bar_prop.idl b/third_party/blink/renderer/core/frame/bar_prop.idl
index 6bd3b1c..9f6d18e 100644
--- a/third_party/blink/renderer/core/frame/bar_prop.idl
+++ b/third_party/blink/renderer/core/frame/bar_prop.idl
@@ -28,6 +28,8 @@
 
 // https://html.spec.whatwg.org/C/#barprop
 
-interface BarProp {
+[
+    Exposed=Window
+] interface BarProp {
     readonly attribute boolean visible;
 };
diff --git a/third_party/blink/renderer/core/frame/csp/content_security_policy_test.cc b/third_party/blink/renderer/core/frame/csp/content_security_policy_test.cc
index 976e248b..87578b2 100644
--- a/third_party/blink/renderer/core/frame/csp/content_security_policy_test.cc
+++ b/third_party/blink/renderer/core/frame/csp/content_security_policy_test.cc
@@ -69,9 +69,10 @@
                           kContentSecurityPolicyHeaderSourceHTTP);
     EXPECT_EQ(test.expected_policy, csp->GetInsecureRequestPolicy());
 
-    auto* document = MakeGarbageCollected<Document>();
-    document->SetSecurityOrigin(secure_origin);
-    document->SetURL(secure_url);
+    DocumentInit init = DocumentInit::Create()
+                            .WithOriginToCommit(secure_origin)
+                            .WithURL(secure_url);
+    auto* document = MakeGarbageCollected<Document>(init);
     csp->BindToDelegate(document->GetContentSecurityPolicyDelegate());
     EXPECT_EQ(test.expected_policy, document->GetInsecureRequestPolicy());
     bool expect_upgrade = test.expected_policy & kUpgradeInsecureRequests;
@@ -720,8 +721,8 @@
   WTF::OrdinalNumber context_line;
 
   // We need document for HTMLScriptElement tests.
-  auto* document = MakeGarbageCollected<Document>();
-  document->SetSecurityOrigin(secure_origin);
+  DocumentInit init = DocumentInit::Create().WithOriginToCommit(secure_origin);
+  auto* document = MakeGarbageCollected<Document>(init);
 
   for (const auto& test : cases) {
     SCOPED_TRACE(testing::Message() << "Policy: `" << test.policy
diff --git a/third_party/blink/renderer/core/frame/csp/source_list_directive_test.cc b/third_party/blink/renderer/core/frame/csp/source_list_directive_test.cc
index 1db6529e..7f7b237 100644
--- a/third_party/blink/renderer/core/frame/csp/source_list_directive_test.cc
+++ b/third_party/blink/renderer/core/frame/csp/source_list_directive_test.cc
@@ -36,8 +36,9 @@
     KURL secure_url("https://example.test/image.png");
     scoped_refptr<SecurityOrigin> secure_origin(
         SecurityOrigin::Create(secure_url));
-    document = MakeGarbageCollected<Document>();
-    document->SetSecurityOrigin(secure_origin);
+    DocumentInit init =
+        DocumentInit::Create().WithOriginToCommit(secure_origin);
+    document = MakeGarbageCollected<Document>(init);
     csp->BindToDelegate(document->GetContentSecurityPolicyDelegate());
   }
 
@@ -45,8 +46,9 @@
     KURL secure_url(origin);
     scoped_refptr<SecurityOrigin> secure_origin(
         SecurityOrigin::Create(secure_url));
-    auto* document = MakeGarbageCollected<Document>();
-    document->SetSecurityOrigin(secure_origin);
+    DocumentInit init =
+        DocumentInit::Create().WithOriginToCommit(secure_origin);
+    auto* document = MakeGarbageCollected<Document>(init);
     auto* csp = MakeGarbageCollected<ContentSecurityPolicy>();
     csp->BindToDelegate(document->GetContentSecurityPolicyDelegate());
     return csp;
diff --git a/third_party/blink/renderer/core/frame/history.idl b/third_party/blink/renderer/core/frame/history.idl
index 182cfa0..87f3691 100644
--- a/third_party/blink/renderer/core/frame/history.idl
+++ b/third_party/blink/renderer/core/frame/history.idl
@@ -27,7 +27,9 @@
 
 enum ScrollRestoration {"auto", "manual"};
 
-interface History {
+[
+    Exposed=Window
+] interface History {
     [MeasureAs=HistoryLength, RaisesException] readonly attribute unsigned long length;
     [Measure, RaisesException] attribute ScrollRestoration scrollRestoration;
     // TODO(foolip): The SerializedScriptValue type should be any.
diff --git a/third_party/blink/renderer/core/frame/navigator.idl b/third_party/blink/renderer/core/frame/navigator.idl
index a309bef4..f13febb 100644
--- a/third_party/blink/renderer/core/frame/navigator.idl
+++ b/third_party/blink/renderer/core/frame/navigator.idl
@@ -19,7 +19,9 @@
 
 // https://html.spec.whatwg.org/C/#the-navigator-object
 
-interface Navigator {
+[
+    Exposed=Window
+] interface Navigator {
     // objects implementing this interface also implement the interfaces given below
 
     // TODO(foolip): vendorSub should be on NavigatorID.
diff --git a/third_party/blink/renderer/core/frame/navigator_device_memory.idl b/third_party/blink/renderer/core/frame/navigator_device_memory.idl
index 7a8e26b..7629518 100644
--- a/third_party/blink/renderer/core/frame/navigator_device_memory.idl
+++ b/third_party/blink/renderer/core/frame/navigator_device_memory.idl
@@ -7,6 +7,6 @@
 [
     Exposed=(Window, Worker)
 ] interface mixin NavigatorDeviceMemory {
-    [HighEntropy,MeasureAs=NavigatorDeviceMemory,RuntimeEnabled=NavigatorDeviceMemory,SecureContext]
+    [HighEntropy,MeasureAs=NavigatorDeviceMemory,SecureContext]
     readonly attribute float deviceMemory;
 };
diff --git a/third_party/blink/renderer/core/frame/user_activation.idl b/third_party/blink/renderer/core/frame/user_activation.idl
index f6a9ea0..fc1e315 100644
--- a/third_party/blink/renderer/core/frame/user_activation.idl
+++ b/third_party/blink/renderer/core/frame/user_activation.idl
@@ -3,8 +3,10 @@
 // found in the LICENSE file.
 
 // https://github.com/dtapuska/useractivation
-[RuntimeEnabled=UserActivationAPI]
-interface UserActivation {
+[
+    RuntimeEnabled=UserActivationAPI,
+    Exposed=(Window,Worker,AudioWorklet)
+] interface UserActivation {
   [Measure] readonly attribute boolean hasBeenActive;
   [Measure] readonly attribute boolean isActive;
 };
diff --git a/third_party/blink/renderer/core/html/forms/html_button_element.idl b/third_party/blink/renderer/core/html/forms/html_button_element.idl
index e872816f7..9f41e83a 100644
--- a/third_party/blink/renderer/core/html/forms/html_button_element.idl
+++ b/third_party/blink/renderer/core/html/forms/html_button_element.idl
@@ -19,8 +19,10 @@
  */
 
 // https://html.spec.whatwg.org/C/#the-button-element
-[HTMLConstructor]
-interface HTMLButtonElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLButtonElement : HTMLElement {
     [CEReactions, Reflect] attribute boolean autofocus;
     [CEReactions, Reflect] attribute boolean disabled;
     [ImplementedAs=formOwner] readonly attribute HTMLFormElement? form;
diff --git a/third_party/blink/renderer/core/html/forms/html_data_list_element.idl b/third_party/blink/renderer/core/html/forms/html_data_list_element.idl
index 84358a8a..29c7714 100644
--- a/third_party/blink/renderer/core/html/forms/html_data_list_element.idl
+++ b/third_party/blink/renderer/core/html/forms/html_data_list_element.idl
@@ -29,7 +29,9 @@
  */
 
 // https://html.spec.whatwg.org/C/#the-datalist-element
-[HTMLConstructor]
-interface HTMLDataListElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLDataListElement : HTMLElement {
     readonly attribute HTMLCollection options;
 };
diff --git a/third_party/blink/renderer/core/html/forms/html_field_set_element.idl b/third_party/blink/renderer/core/html/forms/html_field_set_element.idl
index 66adce58..f9b20c2c 100644
--- a/third_party/blink/renderer/core/html/forms/html_field_set_element.idl
+++ b/third_party/blink/renderer/core/html/forms/html_field_set_element.idl
@@ -18,8 +18,10 @@
  */
 
 // https://html.spec.whatwg.org/C/#the-fieldset-element
-[HTMLConstructor]
-interface HTMLFieldSetElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLFieldSetElement : HTMLElement {
     [CEReactions, Reflect] attribute boolean disabled;
     [ImplementedAs=formOwner] readonly attribute HTMLFormElement? form;
     [CEReactions, Reflect] attribute DOMString name;
diff --git a/third_party/blink/renderer/core/html/forms/html_form_controls_collection.idl b/third_party/blink/renderer/core/html/forms/html_form_controls_collection.idl
index 8a084be..6842382 100644
--- a/third_party/blink/renderer/core/html/forms/html_form_controls_collection.idl
+++ b/third_party/blink/renderer/core/html/forms/html_form_controls_collection.idl
@@ -21,6 +21,7 @@
 
 // https://html.spec.whatwg.org/C/#the-htmlformcontrolscollection-interface
 
+[Exposed=Window]
 interface HTMLFormControlsCollection : HTMLCollection {
     // inherits length and item()
     [ImplementedAs=namedGetter] getter (RadioNodeList or Element)? namedItem(DOMString name); // shadows inherited namedItem()
diff --git a/third_party/blink/renderer/core/html/forms/html_form_element.idl b/third_party/blink/renderer/core/html/forms/html_form_element.idl
index 91d58da..9d7b6360 100644
--- a/third_party/blink/renderer/core/html/forms/html_form_element.idl
+++ b/third_party/blink/renderer/core/html/forms/html_form_element.idl
@@ -21,6 +21,7 @@
 // https://html.spec.whatwg.org/C/#the-form-element
 
 [
+    Exposed=Window,
     HTMLConstructor,
     OverrideBuiltins
 ] interface HTMLFormElement : HTMLElement {
diff --git a/third_party/blink/renderer/core/html/forms/html_label_element.idl b/third_party/blink/renderer/core/html/forms/html_label_element.idl
index 39f1eba..24d8fca 100644
--- a/third_party/blink/renderer/core/html/forms/html_label_element.idl
+++ b/third_party/blink/renderer/core/html/forms/html_label_element.idl
@@ -19,8 +19,10 @@
  */
 
 // https://html.spec.whatwg.org/C/#the-label-element
-[HTMLConstructor]
-interface HTMLLabelElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLLabelElement : HTMLElement {
     readonly attribute HTMLFormElement? form;
     [CEReactions, Reflect=for] attribute DOMString htmlFor;
     readonly attribute HTMLElement? control;
diff --git a/third_party/blink/renderer/core/html/forms/html_legend_element.idl b/third_party/blink/renderer/core/html/forms/html_legend_element.idl
index b20b50e..6b0a63b 100644
--- a/third_party/blink/renderer/core/html/forms/html_legend_element.idl
+++ b/third_party/blink/renderer/core/html/forms/html_legend_element.idl
@@ -19,8 +19,10 @@
  */
 
 // https://html.spec.whatwg.org/C/#the-legend-element
-[HTMLConstructor]
-interface HTMLLegendElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLLegendElement : HTMLElement {
     readonly attribute HTMLFormElement? form;
 
     // obsolete members
diff --git a/third_party/blink/renderer/core/html/forms/html_opt_group_element.idl b/third_party/blink/renderer/core/html/forms/html_opt_group_element.idl
index 60ede69..a4c96c36 100644
--- a/third_party/blink/renderer/core/html/forms/html_opt_group_element.idl
+++ b/third_party/blink/renderer/core/html/forms/html_opt_group_element.idl
@@ -18,8 +18,10 @@
  */
 
 // https://html.spec.whatwg.org/C/#the-optgroup-element
-[HTMLConstructor]
-interface HTMLOptGroupElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLOptGroupElement : HTMLElement {
     [CEReactions, Reflect] attribute boolean disabled;
     [CEReactions, Reflect] attribute DOMString label;
 };
diff --git a/third_party/blink/renderer/core/html/forms/html_option_element.idl b/third_party/blink/renderer/core/html/forms/html_option_element.idl
index 638e3af..fd2eb01 100644
--- a/third_party/blink/renderer/core/html/forms/html_option_element.idl
+++ b/third_party/blink/renderer/core/html/forms/html_option_element.idl
@@ -21,6 +21,7 @@
 // https://html.spec.whatwg.org/C/#the-option-element
 
 [
+    Exposed=Window,
     HTMLConstructor,
     NamedConstructor=Option(optional DOMString data = null,
                             optional DOMString value = null,
diff --git a/third_party/blink/renderer/core/html/forms/html_options_collection.idl b/third_party/blink/renderer/core/html/forms/html_options_collection.idl
index a78ff41..7fecb92f 100644
--- a/third_party/blink/renderer/core/html/forms/html_options_collection.idl
+++ b/third_party/blink/renderer/core/html/forms/html_options_collection.idl
@@ -21,6 +21,7 @@
 
 // https://html.spec.whatwg.org/C/#the-htmloptionscollection-interface
 
+[Exposed=Window]
 interface HTMLOptionsCollection : HTMLCollection {
     // Inherits item() and namedItem()
     [CEReactions, RaisesException=Setter] attribute unsigned long length; // shadows inherited length
diff --git a/third_party/blink/renderer/core/html/forms/html_output_element.idl b/third_party/blink/renderer/core/html/forms/html_output_element.idl
index 50a38fb..369394a6c 100644
--- a/third_party/blink/renderer/core/html/forms/html_output_element.idl
+++ b/third_party/blink/renderer/core/html/forms/html_output_element.idl
@@ -24,8 +24,10 @@
  */
 
 // https://html.spec.whatwg.org/C/#the-output-element
-[HTMLConstructor]
-interface HTMLOutputElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLOutputElement : HTMLElement {
     [PutForwards=value] readonly attribute DOMTokenList htmlFor;
     [ImplementedAs=formOwner] readonly attribute HTMLFormElement? form;
     [CEReactions, Reflect] attribute DOMString name;
diff --git a/third_party/blink/renderer/core/html/forms/html_select_element.idl b/third_party/blink/renderer/core/html/forms/html_select_element.idl
index 4e43cd41..feaf76f 100644
--- a/third_party/blink/renderer/core/html/forms/html_select_element.idl
+++ b/third_party/blink/renderer/core/html/forms/html_select_element.idl
@@ -20,8 +20,10 @@
  */
 
 // https://html.spec.whatwg.org/C/#the-select-element
-[HTMLConstructor]
-interface HTMLSelectElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLSelectElement : HTMLElement {
     [CEReactions, ImplementedAs=IDLExposedAutofillValue] attribute DOMString autocomplete;
     [CEReactions, Reflect] attribute boolean autofocus;
     [CEReactions, Reflect] attribute boolean disabled;
diff --git a/third_party/blink/renderer/core/html/forms/html_text_area_element.idl b/third_party/blink/renderer/core/html/forms/html_text_area_element.idl
index c06bd0d9..4e1376f 100644
--- a/third_party/blink/renderer/core/html/forms/html_text_area_element.idl
+++ b/third_party/blink/renderer/core/html/forms/html_text_area_element.idl
@@ -20,8 +20,10 @@
  */
 
 // https://html.spec.whatwg.org/C/#the-textarea-element
-[HTMLConstructor]
-interface HTMLTextAreaElement : HTMLElement {
+[
+    Exposed=Window,
+    HTMLConstructor
+] interface HTMLTextAreaElement : HTMLElement {
     [CEReactions, ImplementedAs=IDLExposedAutofillValue] attribute DOMString autocomplete;
     [CEReactions, Reflect] attribute boolean autofocus;
     [CEReactions] attribute unsigned long cols;
diff --git a/third_party/blink/renderer/core/html/forms/password_input_type_test.cc b/third_party/blink/renderer/core/html/forms/password_input_type_test.cc
index 202bb99f..f9bb4466 100644
--- a/third_party/blink/renderer/core/html/forms/password_input_type_test.cc
+++ b/third_party/blink/renderer/core/html/forms/password_input_type_test.cc
@@ -69,10 +69,12 @@
 // in a secure context.
 TEST(PasswordInputTypeTest, DidEditFieldEventNotSentFromSecureContext) {
   auto page_holder = std::make_unique<DummyPageHolder>(IntSize(2000, 2000));
+  page_holder->GetFrame().Loader().CommitNavigation(
+      WebNavigationParams::CreateWithHTMLBuffer(SharedBuffer::Create(),
+                                                KURL("https://example.test")),
+      nullptr /* extra_data */);
+  blink::test::RunPendingTasks();
   MockInsecureInputService mock_service(page_holder->GetFrame());
-  page_holder->GetDocument().SetURL(KURL("https://example.test"));
-  page_holder->GetDocument().SetSecurityOrigin(
-      SecurityOrigin::Create(KURL("https://example.test")));
   page_holder->GetDocument().SetSecureContextStateForTesting(
       SecureContextState::kSecure);
   page_holder->GetDocument().body()->SetInnerHTMLFromString(
diff --git a/third_party/blink/renderer/core/html/forms/validity_state.idl b/third_party/blink/renderer/core/html/forms/validity_state.idl
index 5c5d868..b5c52047 100644
--- a/third_party/blink/renderer/core/html/forms/validity_state.idl
+++ b/third_party/blink/renderer/core/html/forms/validity_state.idl
@@ -22,6 +22,7 @@
 
 // https://html.spec.whatwg.org/C/#validitystate
 
+[Exposed=Window]
 interface ValidityState {
     readonly attribute boolean valueMissing;
     readonly attribute boolean typeMismatch;
diff --git a/third_party/blink/renderer/core/html/html_frame_element_test.cc b/third_party/blink/renderer/core/html/html_frame_element_test.cc
index 61c9520..d6cafca 100644
--- a/third_party/blink/renderer/core/html/html_frame_element_test.cc
+++ b/third_party/blink/renderer/core/html/html_frame_element_test.cc
@@ -16,10 +16,12 @@
 // Frame elements do not have any container-policy related attributes, but the
 // fullscreen feature should be unconditionally disabled.
 TEST_F(HTMLFrameElementTest, DefaultContainerPolicy) {
-  auto* document = MakeGarbageCollected<Document>();
   const KURL document_url("http://example.com");
-  document->SetURL(document_url);
-  document->UpdateSecurityOrigin(SecurityOrigin::Create(document_url));
+  DocumentInit init =
+      DocumentInit::Create()
+          .WithInitiatorOrigin(SecurityOrigin::Create(document_url))
+          .WithURL(document_url);
+  auto* document = MakeGarbageCollected<Document>(init);
 
   auto* frame_element = MakeGarbageCollected<HTMLFrameElement>(*document);
 
diff --git a/third_party/blink/renderer/core/html/html_iframe_element_test.cc b/third_party/blink/renderer/core/html/html_iframe_element_test.cc
index bfe5e63..16932628a 100644
--- a/third_party/blink/renderer/core/html/html_iframe_element_test.cc
+++ b/third_party/blink/renderer/core/html/html_iframe_element_test.cc
@@ -22,11 +22,12 @@
   }
 
   void SetUp() final {
-    document_ = MakeGarbageCollected<Document>();
     const KURL document_url("http://example.com");
-    document_->SetURL(document_url);
-    document_->UpdateSecurityOrigin(SecurityOrigin::Create(document_url));
-
+    DocumentInit init =
+        DocumentInit::Create()
+            .WithOriginToCommit(SecurityOrigin::Create(document_url))
+            .WithURL(document_url);
+    document_ = MakeGarbageCollected<Document>(init);
     frame_element_ = MakeGarbageCollected<HTMLIFrameElement>(*document_);
   }
 
diff --git a/third_party/blink/renderer/core/html/parser/html_preload_scanner_test.cc b/third_party/blink/renderer/core/html/parser/html_preload_scanner_test.cc
index 81c536a..fbcf1a2 100644
--- a/third_party/blink/renderer/core/html/parser/html_preload_scanner_test.cc
+++ b/third_party/blink/renderer/core/html/parser/html_preload_scanner_test.cc
@@ -245,8 +245,7 @@
     KURL document_url = KURL("http://whatever.test/");
     if (use_secure_document_url)
       document_url = KURL("https://whatever.test/");
-    GetDocument().SetURL(document_url);
-    GetDocument().SetSecurityOrigin(SecurityOrigin::Create(document_url));
+    NavigateTo(document_url);
     GetDocument().GetSettings()->SetViewportEnabled(viewport_state ==
                                                     kViewportEnabled);
     GetDocument().GetSettings()->SetViewportMetaEnabled(viewport_state ==
diff --git a/third_party/blink/renderer/core/layout/layout_theme_default.cc b/third_party/blink/renderer/core/layout/layout_theme_default.cc
index c29363d6..9fcf1da 100644
--- a/third_party/blink/renderer/core/layout/layout_theme_default.cc
+++ b/third_party/blink/renderer/core/layout/layout_theme_default.cc
@@ -73,8 +73,8 @@
 }
 
 Color LayoutThemeDefault::SystemColor(CSSValueID css_value_id) const {
-  static const Color kDefaultButtonGrayColor(0xffdddddd);
-  static const Color kDefaultMenuColor(0xfff7f7f7);
+  constexpr Color kDefaultButtonGrayColor(0xffdddddd);
+  constexpr Color kDefaultMenuColor(0xfff7f7f7);
 
   if (css_value_id == CSSValueID::kButtonface) {
     if (UseMockTheme())
@@ -249,7 +249,7 @@
 }
 
 Color LayoutThemeDefault::PlatformFocusRingColor() const {
-  static Color focus_ring_color(229, 151, 0, 255);
+  constexpr Color focus_ring_color(0xFFE59700);
   return focus_ring_color;
 }
 
@@ -386,8 +386,8 @@
 //
 // The following values come from the defaults of GTK+.
 //
-static const int kProgressAnimationFrames = 10;
-static constexpr TimeDelta kProgressAnimationInterval =
+constexpr int kProgressAnimationFrames = 10;
+constexpr TimeDelta kProgressAnimationInterval =
     TimeDelta::FromMilliseconds(125);
 
 TimeDelta LayoutThemeDefault::AnimationRepeatIntervalForProgressBar() const {
diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc
index 487f317..1667a8d 100644
--- a/third_party/blink/renderer/core/loader/document_loader.cc
+++ b/third_party/blink/renderer/core/loader/document_loader.cc
@@ -1401,7 +1401,7 @@
   // DidObserveLoadingBehavior() must be called after DispatchDidCommitLoad() is
   // called for the metrics tracking logic to handle it properly.
   if (service_worker_network_provider_ &&
-      service_worker_network_provider_->IsControlledByServiceWorker() ==
+      service_worker_network_provider_->GetControllerServiceWorkerMode() ==
           blink::mojom::ControllerServiceWorkerMode::kControlled) {
     GetLocalFrameClient().DidObserveLoadingBehavior(
         kWebLoadingBehaviorServiceWorkerControlled);
diff --git a/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties.cc b/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties.cc
index 0f2d78f5..89c5589 100644
--- a/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties.cc
+++ b/third_party/blink/renderer/core/loader/frame_resource_fetcher_properties.cc
@@ -43,7 +43,7 @@
           .GetServiceWorkerNetworkProvider();
   if (!service_worker_network_provider)
     return blink::mojom::ControllerServiceWorkerMode::kNoController;
-  return service_worker_network_provider->IsControlledByServiceWorker();
+  return service_worker_network_provider->GetControllerServiceWorkerMode();
 }
 
 int64_t FrameResourceFetcherProperties::ServiceWorkerId() const {
diff --git a/third_party/blink/renderer/core/loader/mixed_content_checker_test.cc b/third_party/blink/renderer/core/loader/mixed_content_checker_test.cc
index 0760d12..ca4ec7f0 100644
--- a/third_party/blink/renderer/core/loader/mixed_content_checker_test.cc
+++ b/third_party/blink/renderer/core/loader/mixed_content_checker_test.cc
@@ -16,6 +16,7 @@
 #include "third_party/blink/renderer/core/loader/empty_clients.h"
 #include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
+#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
 #include "third_party/blink/renderer/platform/weborigin/kurl.h"
 #include "third_party/blink/renderer/platform/weborigin/security_origin.h"
 
@@ -71,8 +72,11 @@
 
 TEST(MixedContentCheckerTest, ContextTypeForInspector) {
   auto dummy_page_holder = std::make_unique<DummyPageHolder>(IntSize(1, 1));
-  dummy_page_holder->GetFrame().GetDocument()->SetSecurityOrigin(
-      SecurityOrigin::CreateFromString("http://example.test"));
+  dummy_page_holder->GetFrame().Loader().CommitNavigation(
+      WebNavigationParams::CreateWithHTMLBuffer(SharedBuffer::Create(),
+                                                KURL("http://example.test")),
+      nullptr /* extra_data */);
+  blink::test::RunPendingTasks();
 
   ResourceRequest not_mixed_content("https://example.test/foo.jpg");
   not_mixed_content.SetRequestContext(mojom::RequestContextType::SCRIPT);
@@ -80,8 +84,12 @@
             MixedContentChecker::ContextTypeForInspector(
                 &dummy_page_holder->GetFrame(), not_mixed_content));
 
-  dummy_page_holder->GetFrame().GetDocument()->SetSecurityOrigin(
-      SecurityOrigin::CreateFromString("https://example.test"));
+  dummy_page_holder->GetFrame().Loader().CommitNavigation(
+      WebNavigationParams::CreateWithHTMLBuffer(SharedBuffer::Create(),
+                                                KURL("https://example.test")),
+      nullptr /* extra_data */);
+  blink::test::RunPendingTasks();
+
   EXPECT_EQ(WebMixedContentContextType::kNotMixedContent,
             MixedContentChecker::ContextTypeForInspector(
                 &dummy_page_holder->GetFrame(), not_mixed_content));
@@ -143,21 +151,22 @@
 }
 
 TEST(MixedContentCheckerTest, DetectMixedForm) {
+  KURL main_resource_url(NullURL(), "https://example.test/");
   MixedContentCheckerMockLocalFrameClient* client =
       MakeGarbageCollected<MixedContentCheckerMockLocalFrameClient>();
   auto dummy_page_holder =
       std::make_unique<DummyPageHolder>(IntSize(1, 1), nullptr, client);
-
-  KURL main_resource_url(NullURL(), "https://example.test/");
+  dummy_page_holder->GetFrame().Loader().CommitNavigation(
+      WebNavigationParams::CreateWithHTMLBuffer(SharedBuffer::Create(),
+                                                main_resource_url),
+      nullptr /* extra_data */);
+  blink::test::RunPendingTasks();
 
   KURL http_form_action_url(NullURL(), "http://example-action.test/");
   KURL https_form_action_url(NullURL(), "https://example-action.test/");
   KURL javascript_form_action_url(NullURL(), "javascript:void(0);");
   KURL mailto_form_action_url(NullURL(), "mailto:action@example-action.test");
 
-  dummy_page_holder->GetFrame().GetDocument()->SetSecurityOrigin(
-      SecurityOrigin::Create(main_resource_url));
-
   // mailto and http are non-secure form targets.
   EXPECT_CALL(*client, DidContainInsecureFormAction()).Times(2);
 
@@ -176,20 +185,22 @@
 }
 
 TEST(MixedContentCheckerTest, DetectMixedFavicon) {
+  KURL main_resource_url("https://example.test/");
   MixedContentCheckerMockLocalFrameClient* client =
       MakeGarbageCollected<MixedContentCheckerMockLocalFrameClient>();
   auto dummy_page_holder =
       std::make_unique<DummyPageHolder>(IntSize(1, 1), nullptr, client);
+  dummy_page_holder->GetFrame().Loader().CommitNavigation(
+      WebNavigationParams::CreateWithHTMLBuffer(SharedBuffer::Create(),
+                                                main_resource_url),
+      nullptr /* extra_data */);
+  blink::test::RunPendingTasks();
   dummy_page_holder->GetFrame().GetSettings()->SetAllowRunningOfInsecureContent(
       false);
 
-  KURL main_resource_url("https://example.test/");
   KURL http_favicon_url("http://example.test/favicon.png");
   KURL https_favicon_url("https://example.test/favicon.png");
 
-  dummy_page_holder->GetFrame().GetDocument()->SetSecurityOrigin(
-      SecurityOrigin::Create(main_resource_url));
-
   // Test that a mixed content favicon is correctly blocked.
   EXPECT_TRUE(MixedContentChecker::ShouldBlockFetch(
       &dummy_page_holder->GetFrame(), mojom::RequestContextType::FAVICON,
diff --git a/third_party/blink/renderer/core/loader/threadable_loader_test.cc b/third_party/blink/renderer/core/loader/threadable_loader_test.cc
index 7f1a010..6136d879 100644
--- a/third_party/blink/renderer/core/loader/threadable_loader_test.cc
+++ b/third_party/blink/renderer/core/loader/threadable_loader_test.cc
@@ -160,9 +160,11 @@
  public:
   ThreadableLoaderTestHelper()
       : dummy_page_holder_(std::make_unique<DummyPageHolder>(IntSize(1, 1))) {
-    GetDocument().SetURL(KURL("http://fake.url/"));
-    GetDocument().SetSecurityOrigin(
-        SecurityOrigin::Create(KURL("http://fake.url/")));
+    KURL url("http://fake.url/");
+    dummy_page_holder_->GetFrame().Loader().CommitNavigation(
+        WebNavigationParams::CreateWithHTMLBuffer(SharedBuffer::Create(), url),
+        nullptr /* extra_data */);
+    blink::test::RunPendingTasks();
   }
 
   void CreateLoader(ThreadableLoaderClient* client) {
diff --git a/third_party/blink/renderer/core/loader/worker_resource_fetcher_properties.cc b/third_party/blink/renderer/core/loader/worker_resource_fetcher_properties.cc
index f413fcb..ebdcbdf 100644
--- a/third_party/blink/renderer/core/loader/worker_resource_fetcher_properties.cc
+++ b/third_party/blink/renderer/core/loader/worker_resource_fetcher_properties.cc
@@ -28,7 +28,7 @@
 
 mojom::ControllerServiceWorkerMode
 WorkerResourceFetcherProperties::GetControllerServiceWorkerMode() const {
-  return web_context_->IsControlledByServiceWorker();
+  return web_context_->GetControllerServiceWorkerMode();
 }
 
 bool WorkerResourceFetcherProperties::IsPaused() const {
diff --git a/third_party/blink/renderer/core/page/spatial_navigation.cc b/third_party/blink/renderer/core/page/spatial_navigation.cc
index e215896a..75878ac7 100644
--- a/third_party/blink/renderer/core/page/spatial_navigation.cc
+++ b/third_party/blink/renderer/core/page/spatial_navigation.cc
@@ -289,7 +289,9 @@
   // CanScrollInDirection(). Regular arrow-key scrolling (without
   // --enable-spatial-navigation) already uses smooth scrolling by default.
   ScrollableArea* scroller = ScrollableAreaFor(container);
-  DCHECK(scroller);
+  if (!scroller)
+    return false;
+
   scroller->ScrollBy(ScrollOffset(dx, dy), kUserScroll);
   return true;
 }
diff --git a/third_party/blink/renderer/core/script/module_map_test.cc b/third_party/blink/renderer/core/script/module_map_test.cc
index da2f4ab..6197ae8 100644
--- a/third_party/blink/renderer/core/script/module_map_test.cc
+++ b/third_party/blink/renderer/core/script/module_map_test.cc
@@ -198,8 +198,7 @@
 
 void ModuleMapTest::SetUp() {
   PageTestBase::SetUp(IntSize(500, 500));
-  GetDocument().SetURL(KURL("https://example.com"));
-  GetDocument().SetSecurityOrigin(SecurityOrigin::Create(GetDocument().Url()));
+  NavigateTo(KURL("https://example.com"));
   modulator_ = MakeGarbageCollected<ModuleMapTestModulator>(
       ToScriptStateForMainWorld(&GetFrame()));
   map_ = MakeGarbageCollected<ModuleMap>(modulator_);
diff --git a/third_party/blink/renderer/core/streams/BUILD.gn b/third_party/blink/renderer/core/streams/BUILD.gn
index d8c60b6..24a5a05 100644
--- a/third_party/blink/renderer/core/streams/BUILD.gn
+++ b/third_party/blink/renderer/core/streams/BUILD.gn
@@ -30,8 +30,6 @@
     "stream_algorithms.h",
     "stream_promise_resolver.cc",
     "stream_promise_resolver.h",
-    "transferable_streams.cc",
-    "transferable_streams.h",
     "transform_stream.cc",
     "transform_stream.h",
     "transform_stream_default_controller.cc",
diff --git a/third_party/blink/renderer/core/streams/README.md b/third_party/blink/renderer/core/streams/README.md
index 1b845c20..6856924 100644
--- a/third_party/blink/renderer/core/streams/README.md
+++ b/third_party/blink/renderer/core/streams/README.md
@@ -26,8 +26,6 @@
     writable_stream_default_writer.idl
     writable_stream_native.cc
     writable_stream_native.h
-    transferable_streams.cc
-    transferable_streams.h
     transform_stream_default_controller.cc
     transform_stream_default_controller.h
     transform_stream_native.cc
diff --git a/third_party/blink/renderer/core/streams/readable_stream.cc b/third_party/blink/renderer/core/streams/readable_stream.cc
index e1088481..8b787d6 100644
--- a/third_party/blink/renderer/core/streams/readable_stream.cc
+++ b/third_party/blink/renderer/core/streams/readable_stream.cc
@@ -60,9 +60,11 @@
 ReadableStream* ReadableStream::Deserialize(ScriptState* script_state,
                                             MessagePort* port,
                                             ExceptionState& exception_state) {
+  // TODO(ricea): Implementation serialization for the native implementation.
   if (RuntimeEnabledFeatures::StreamsNativeEnabled()) {
-    return ReadableStreamNative::Deserialize(script_state, port,
-                                             exception_state);
+    exception_state.ThrowTypeError(
+        "serialization disabled because StreamsNative feature is enabled");
+    return nullptr;
   }
 
   return ReadableStreamWrapper::Deserialize(script_state, port,
diff --git a/third_party/blink/renderer/core/streams/readable_stream_native.cc b/third_party/blink/renderer/core/streams/readable_stream_native.cc
index 1828317..d957c75 100644
--- a/third_party/blink/renderer/core/streams/readable_stream_native.cc
+++ b/third_party/blink/renderer/core/streams/readable_stream_native.cc
@@ -15,7 +15,6 @@
 #include "third_party/blink/renderer/core/streams/readable_stream_reader.h"
 #include "third_party/blink/renderer/core/streams/stream_algorithms.h"
 #include "third_party/blink/renderer/core/streams/stream_promise_resolver.h"
-#include "third_party/blink/renderer/core/streams/transferable_streams.h"
 #include "third_party/blink/renderer/core/streams/underlying_source_base.h"
 #include "third_party/blink/renderer/core/streams/writable_stream_default_controller.h"
 #include "third_party/blink/renderer/core/streams/writable_stream_default_writer.h"
@@ -31,6 +30,13 @@
 
 namespace blink {
 
+struct ReadableStreamNative::PipeOptions {
+  PipeOptions() = default;
+  bool prevent_close = false;
+  bool prevent_abort = false;
+  bool prevent_cancel = false;
+};
+
 // PipeToEngine implements PipeTo(). All standard steps in this class come from
 // https://streams.spec.whatwg.org/#readable-stream-pipe-to
 //
@@ -1388,43 +1394,7 @@
 void ReadableStreamNative::Serialize(ScriptState* script_state,
                                      MessagePort* port,
                                      ExceptionState& exception_state) {
-  if (IsLocked(this)) {
-    exception_state.ThrowTypeError("Cannot transfer a locked stream");
-    return;
-  }
-
-  auto* writable =
-      CreateCrossRealmTransformWritable(script_state, port, exception_state);
-  if (exception_state.HadException()) {
-    return;
-  }
-
-  auto promise = PipeTo(script_state, this, writable, PipeOptions());
-  promise.MarkAsHandled();
-}
-
-ReadableStreamNative* ReadableStreamNative::Deserialize(
-    ScriptState* script_state,
-    MessagePort* port,
-    ExceptionState& exception_state) {
-  // We need to execute JavaScript to call "Then" on v8::Promises. We will not
-  // run author code.
-  v8::Isolate::AllowJavascriptExecutionScope allow_js(
-      script_state->GetIsolate());
-  auto* readable =
-      CreateCrossRealmTransformReadable(script_state, port, exception_state);
-  if (exception_state.HadException()) {
-    return nullptr;
-  }
-  return readable;
-}
-
-ScriptPromise ReadableStreamNative::PipeTo(ScriptState* script_state,
-                                           ReadableStreamNative* readable,
-                                           WritableStreamNative* destination,
-                                           PipeOptions pipe_options) {
-  auto* engine = MakeGarbageCollected<PipeToEngine>(script_state, pipe_options);
-  return engine->Start(readable, destination);
+  // TODO(ricea): Implement this.
 }
 
 v8::Local<v8::Value> ReadableStreamNative::GetStoredError(
@@ -1439,6 +1409,14 @@
   ReadableStream::Trace(visitor);
 }
 
+ScriptPromise ReadableStreamNative::PipeTo(ScriptState* script_state,
+                                           ReadableStreamNative* readable,
+                                           WritableStreamNative* destination,
+                                           PipeOptions pipe_options) {
+  auto* engine = MakeGarbageCollected<PipeToEngine>(script_state, pipe_options);
+  return engine->Start(readable, destination);
+}
+
 //
 // Abstract Operations Used By Controllers
 //
diff --git a/third_party/blink/renderer/core/streams/readable_stream_native.h b/third_party/blink/renderer/core/streams/readable_stream_native.h
index 9cd1fea..b2af17d4 100644
--- a/third_party/blink/renderer/core/streams/readable_stream_native.h
+++ b/third_party/blink/renderer/core/streams/readable_stream_native.h
@@ -30,13 +30,6 @@
 // See https://streams.spec.whatwg.org/#rs-model for background.
 class ReadableStreamNative : public ReadableStream {
  public:
-  struct PipeOptions {
-    PipeOptions() = default;
-    bool prevent_close = false;
-    bool prevent_abort = false;
-    bool prevent_cancel = false;
-  };
-
   enum State : uint8_t { kReadable, kClosed, kErrored };
 
   // Implements ReadableStream::Create() when this implementation is enabled.
@@ -153,10 +146,6 @@
 
   void Serialize(ScriptState*, MessagePort* port, ExceptionState&) override;
 
-  static ReadableStreamNative* Deserialize(ScriptState*,
-                                           MessagePort* port,
-                                           ExceptionState&);
-
   bool IsBroken() const override { return false; }
 
   //
@@ -173,12 +162,6 @@
     return stream->reader_;
   }
 
-  // https://streams.spec.whatwg.org/#readable-stream-pipe-to
-  static ScriptPromise PipeTo(ScriptState*,
-                              ReadableStreamNative*,
-                              WritableStreamNative*,
-                              PipeOptions);
-
   //
   // Functions exported for use by TransformStream. Not part of the standard.
   //
@@ -207,6 +190,7 @@
   friend class ReadableStreamDefaultController;
   friend class ReadableStreamReader;
 
+  struct PipeOptions;
   class PipeToEngine;
   class ReadHandleImpl;
   class TeeEngine;
@@ -220,6 +204,12 @@
                                                     bool for_author_code,
                                                     ExceptionState&);
 
+  // https://streams.spec.whatwg.org/#readable-stream-pipe-to
+  static ScriptPromise PipeTo(ScriptState*,
+                              ReadableStreamNative*,
+                              WritableStreamNative*,
+                              PipeOptions);
+
   // https://streams.spec.whatwg.org/#readable-stream-add-read-request
   static StreamPromiseResolver* AddReadRequest(ScriptState*,
                                                ReadableStreamNative*);
diff --git a/third_party/blink/renderer/core/streams/readable_stream_reader.h b/third_party/blink/renderer/core/streams/readable_stream_reader.h
index 6099dca..3d5f8d3 100644
--- a/third_party/blink/renderer/core/streams/readable_stream_reader.h
+++ b/third_party/blink/renderer/core/streams/readable_stream_reader.h
@@ -6,7 +6,6 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_READABLE_STREAM_READER_H_
 
 #include "third_party/blink/renderer/bindings/core/v8/script_value.h"
-#include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
 #include "v8/include/v8.h"
 
@@ -26,7 +25,7 @@
 // with the standard, ReadableStreamDefaultReader is implemented by the
 // ReadableStreamReader class.
 // TODO(ricea): Refactor this when implementing ReadableStreamBYOBReader.
-class CORE_EXPORT ReadableStreamReader : public ScriptWrappable {
+class ReadableStreamReader : public ScriptWrappable {
   DEFINE_WRAPPERTYPEINFO();
 
  public:
diff --git a/third_party/blink/renderer/core/streams/readable_stream_test.cc b/third_party/blink/renderer/core/streams/readable_stream_test.cc
index 2217f82..656da9d 100644
--- a/third_party/blink/renderer/core/streams/readable_stream_test.cc
+++ b/third_party/blink/renderer/core/streams/readable_stream_test.cc
@@ -410,6 +410,11 @@
 }
 
 TEST_P(ReadableStreamTest, Serialize) {
+  if (GetParam()) {
+    // Serialize() is not yet supported in the C++ implementation.
+    return;
+  }
+
   ScopedTransferableStreamsForTest enabled(true);
 
   V8TestingScope scope;
diff --git a/third_party/blink/renderer/core/streams/transferable_streams.cc b/third_party/blink/renderer/core/streams/transferable_streams.cc
deleted file mode 100644
index ee7e1d25..0000000
--- a/third_party/blink/renderer/core/streams/transferable_streams.cc
+++ /dev/null
@@ -1,875 +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.
-
-// Functions for transferable streams. See design doc
-// https://docs.google.com/document/d/1_KuZzg5c3pncLJPFa8SuVm23AP4tft6mzPCL5at3I9M/edit
-
-#include "third_party/blink/renderer/core/streams/transferable_streams.h"
-
-#include "base/stl_util.h"
-#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_dom_exception.h"
-#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/core/dom/events/native_event_listener.h"
-#include "third_party/blink/renderer/core/events/message_event.h"
-#include "third_party/blink/renderer/core/messaging/message_port.h"
-#include "third_party/blink/renderer/core/messaging/post_message_options.h"
-#include "third_party/blink/renderer/core/streams/miscellaneous_operations.h"
-#include "third_party/blink/renderer/core/streams/promise_handler.h"
-#include "third_party/blink/renderer/core/streams/readable_stream_default_controller.h"
-#include "third_party/blink/renderer/core/streams/readable_stream_native.h"
-#include "third_party/blink/renderer/core/streams/stream_algorithms.h"
-#include "third_party/blink/renderer/core/streams/stream_promise_resolver.h"
-#include "third_party/blink/renderer/core/streams/writable_stream_default_controller.h"
-#include "third_party/blink/renderer/core/streams/writable_stream_native.h"
-#include "third_party/blink/renderer/platform/bindings/exception_state.h"
-#include "third_party/blink/renderer/platform/bindings/script_state.h"
-#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
-#include "third_party/blink/renderer/platform/heap/heap.h"
-#include "third_party/blink/renderer/platform/heap/visitor.h"
-#include "third_party/blink/renderer/platform/wtf/assertions.h"
-#include "v8/include/v8.h"
-
-// See the design doc at
-// https://docs.google.com/document/d/1_KuZzg5c3pncLJPFa8SuVm23AP4tft6mzPCL5at3I9M/edit
-// for explanation of how transferable streams are constructed from the "cross
-// realm identity transform" implemented in this file.
-
-// The peer (the other end of the MessagePort) is untrusted as it may be
-// compromised. This means we have to be very careful in unpacking the messages
-// from the peer. LOG(WARNING) is used for cases where a message from the peer
-// appears to be invalid. If this appears during ordinary testing it indicates a
-// bug.
-//
-// The -vmodule=transferable_streams=3 command-line argument can be used for
-// debugging of the protocol.
-
-namespace blink {
-
-namespace {
-
-// These are the types of messages that are sent between peers.
-enum class MessageType { kPull, kCancel, kChunk, kClose, kAbort, kError };
-
-// These are the different ways an error reason can be encoded.
-enum class ErrorType { kTypeError, kJson, kDomException, kUndefined };
-
-bool IsATypeError(ScriptState* script_state, v8::Local<v8::Object> object) {
-  // There isn't a 100% reliable way to identify a TypeError.
-  return object->IsNativeError() &&
-         object->GetConstructorName()
-             ->Equals(script_state->GetContext(),
-                      V8AtomicString(script_state->GetIsolate(), "TypeError"))
-             .ToChecked();
-}
-
-bool IsADOMException(v8::Isolate* isolate, v8::Local<v8::Object> object) {
-  return V8DOMException::HasInstance(object, isolate);
-}
-
-// Creates a JavaScript object with a null prototype structured like {key1:
-// value2, key2: value2}. This is used to create objects to be serialized by
-// postMessage.
-v8::Local<v8::Object> CreateKeyValueObject(v8::Isolate* isolate,
-                                           const char* key1,
-                                           v8::Local<v8::Value> value1,
-                                           const char* key2,
-                                           v8::Local<v8::Value> value2) {
-  v8::Local<v8::Name> names[] = {V8AtomicString(isolate, key1),
-                                 V8AtomicString(isolate, key2)};
-  v8::Local<v8::Value> values[] = {value1, value2};
-  static_assert(base::size(names) == base::size(values),
-                "names and values arrays must be the same size");
-  return v8::Object::New(isolate, v8::Null(isolate), names, values,
-                         base::size(names));
-}
-
-// Unpacks an object created by CreateKeyValueObject(). |value1| and |value2|
-// are out parameters. Returns false on failure.
-bool UnpackKeyValueObject(ScriptState* script_state,
-                          v8::Local<v8::Object> object,
-                          const char* key1,
-                          v8::Local<v8::Value>* value1,
-                          const char* key2,
-                          v8::Local<v8::Value>* value2) {
-  auto* isolate = script_state->GetIsolate();
-  v8::TryCatch try_catch(isolate);
-  auto context = script_state->GetContext();
-  if (!object->Get(context, V8AtomicString(isolate, key1)).ToLocal(value1)) {
-    DLOG(WARNING) << "Error reading key: '" << key1 << "'";
-    return false;
-  }
-  if (!object->Get(context, V8AtomicString(isolate, key2)).ToLocal(value2)) {
-    DLOG(WARNING) << "Error reading key: '" << key2 << "'";
-    return false;
-  }
-  return true;
-}
-
-// Send a message with type |type| and contents |value| over |port|. The type
-// will be packed as a number with key "t", and the value will be packed with
-// key "v".
-void PackAndPostMessage(ScriptState* script_state,
-                        MessagePort* port,
-                        MessageType type,
-                        v8::Local<v8::Value> value,
-                        ExceptionState& exception_state) {
-  DVLOG(3) << "PackAndPostMessage sending message type "
-           << static_cast<int>(type);
-  auto* isolate = script_state->GetIsolate();
-  v8::Local<v8::Object> packed = CreateKeyValueObject(
-      isolate, "t", v8::Number::New(isolate, static_cast<int>(type)), "v",
-      value);
-  port->postMessage(script_state, ScriptValue(script_state, packed),
-                    PostMessageOptions::Create(), exception_state);
-}
-
-// Packs an error into an {e: number, s: string} object for transmission by
-// postMessage. Serializing the resulting object should never fail.
-v8::Local<v8::Object> PackErrorType(v8::Isolate* isolate,
-                                    ErrorType type,
-                                    v8::Local<v8::String> string) {
-  auto error_as_number = v8::Number::New(isolate, static_cast<int>(type));
-  return CreateKeyValueObject(isolate, "e", error_as_number, "s", string);
-}
-
-// Overload for the common case where |string| is a compile-time constant.
-v8::Local<v8::Object> PackErrorType(v8::Isolate* isolate,
-                                    ErrorType type,
-                                    const char* string) {
-  return PackErrorType(isolate, type, V8String(isolate, string));
-}
-
-// We'd like to able to transfer TypeError exceptions, but we can't, so we hack
-// around it. PackReason() is guaranteed to succeed and the object produced is
-// guaranteed to be serializable by postMessage(), however data may be lost. It
-// is not very efficient, and has fairly arbitrary semantics.
-// TODO(ricea): Replace once Errors are serializable.
-v8::Local<v8::Value> PackReason(ScriptState* script_state,
-                                v8::Local<v8::Value> reason) {
-  auto* isolate = script_state->GetIsolate();
-  auto context = script_state->GetContext();
-  if (reason->IsString() || reason->IsNumber() || reason->IsBoolean()) {
-    v8::TryCatch try_catch(isolate);
-    v8::Local<v8::String> stringified;
-    if (!v8::JSON::Stringify(context, reason).ToLocal(&stringified)) {
-      return PackErrorType(isolate, ErrorType::kTypeError,
-                           "Cannot transfer message");
-    }
-
-    return PackErrorType(isolate, ErrorType::kJson, stringified);
-  }
-
-  if (reason->IsFunction() || reason->IsSymbol() ||
-      !(reason->IsObject() || reason->IsNull())) {
-    // Squash to undefined
-    return PackErrorType(isolate, ErrorType::kUndefined, "");
-  }
-
-  if (IsATypeError(script_state, reason.As<v8::Object>())) {
-    v8::TryCatch try_catch(isolate);
-    // "message" on TypeError is a normal property, meaning that if it
-    // is set, it is set on the object itself. We can take advantage of
-    // this to avoid executing user JavaScript in the case when the
-    // TypeError was generated internally.
-    v8::Local<v8::Value> descriptor;
-    if (!reason.As<v8::Object>()
-             ->GetOwnPropertyDescriptor(context,
-                                        V8AtomicString(isolate, "message"))
-             .ToLocal(&descriptor)) {
-      return PackErrorType(isolate, ErrorType::kTypeError,
-                           "Cannot transfer message");
-    }
-    if (descriptor->IsUndefined()) {
-      return PackErrorType(isolate, ErrorType::kTypeError, "");
-    }
-    v8::Local<v8::Value> message;
-    CHECK(descriptor->IsObject());
-    if (!descriptor.As<v8::Object>()
-             ->Get(context, V8AtomicString(isolate, "value"))
-             .ToLocal(&message)) {
-      message = V8String(isolate, "Cannot transfer message");
-    } else if (!message->IsString()) {
-      message = V8String(isolate, "");
-    }
-    return PackErrorType(isolate, ErrorType::kTypeError,
-                         message.As<v8::String>());
-  }
-
-  if (IsADOMException(isolate, reason.As<v8::Object>())) {
-    DOMException* dom_exception =
-        V8DOMException::ToImpl(reason.As<v8::Object>());
-    String message = dom_exception->message();
-    String name = dom_exception->name();
-    v8::Local<v8::Value> packed = CreateKeyValueObject(
-        isolate, "m", V8String(isolate, message), "n", V8String(isolate, name));
-    // It should be impossible for this to fail, except for out-of-memory.
-    v8::Local<v8::String> packed_string =
-        v8::JSON::Stringify(context, packed).ToLocalChecked();
-    return PackErrorType(isolate, ErrorType::kDomException, packed_string);
-  }
-
-  v8::TryCatch try_catch(isolate);
-  v8::Local<v8::Value> json;
-  if (!v8::JSON::Stringify(context, reason).ToLocal(&json)) {
-    return PackErrorType(isolate, ErrorType::kTypeError,
-                         "Cannot transfer message");
-  }
-
-  return PackErrorType(isolate, ErrorType::kJson, json.As<v8::String>());
-}
-
-// Converts an object created by PackReason() back into a clone of the original
-// object, minus any data that was discarded by PackReason().
-bool UnpackReason(ScriptState* script_state,
-                  v8::Local<v8::Value> packed_reason,
-                  v8::Local<v8::Value>* reason) {
-  // We need to be robust against malformed input because it could come from a
-  // compromised renderer.
-  if (!packed_reason->IsObject()) {
-    DLOG(WARNING) << "packed_reason is not an object";
-    return false;
-  }
-
-  v8::Local<v8::Value> encoder_value;
-  v8::Local<v8::Value> string_value;
-  if (!UnpackKeyValueObject(script_state, packed_reason.As<v8::Object>(), "e",
-                            &encoder_value, "s", &string_value)) {
-    return false;
-  }
-
-  if (!encoder_value->IsNumber()) {
-    DLOG(WARNING) << "encoder_value is not a number";
-    return false;
-  }
-
-  int encoder = encoder_value.As<v8::Number>()->Value();
-  if (!string_value->IsString()) {
-    DLOG(WARNING) << "string_value is not a string";
-    return false;
-  }
-
-  v8::Local<v8::String> string = string_value.As<v8::String>();
-  auto* isolate = script_state->GetIsolate();
-  auto context = script_state->GetContext();
-  switch (static_cast<ErrorType>(encoder)) {
-    case ErrorType::kJson: {
-      v8::TryCatch try_catch(isolate);
-      if (!v8::JSON::Parse(context, string).ToLocal(reason)) {
-        DLOG(WARNING) << "JSON Parse failed. Content: " << ToCoreString(string);
-        return false;
-      }
-      return true;
-    }
-
-    case ErrorType::kTypeError:
-      *reason = v8::Exception::TypeError(string);
-      return true;
-
-    case ErrorType::kDomException: {
-      v8::TryCatch try_catch(isolate);
-      v8::Local<v8::Value> packed_exception;
-      if (!v8::JSON::Parse(context, string).ToLocal(&packed_exception)) {
-        DLOG(WARNING) << "Packed DOMException JSON parse failed";
-        return false;
-      }
-
-      if (!packed_exception->IsObject()) {
-        DLOG(WARNING) << "Packed DOMException is not an object";
-        return false;
-      }
-
-      v8::Local<v8::Value> message;
-      v8::Local<v8::Value> name;
-      if (!UnpackKeyValueObject(script_state, packed_exception.As<v8::Object>(),
-                                "m", &message, "n", &name)) {
-        DLOG(WARNING) << "Failed unpacking packed DOMException";
-        return false;
-      }
-
-      if (!message->IsString()) {
-        DLOG(WARNING) << "DOMException message is not a string";
-        return false;
-      }
-
-      if (!name->IsString()) {
-        DLOG(WARNING) << "DOMException name is not a string";
-        return false;
-      }
-
-      auto ToBlink = [](v8::Local<v8::Value> value) {
-        return ToBlinkString<String>(value.As<v8::String>(), kDoNotExternalize);
-      };
-      *reason = ToV8(DOMException::Create(ToBlink(message), ToBlink(name)),
-                     script_state);
-      return true;
-    }
-
-    case ErrorType::kUndefined:
-      *reason = v8::Undefined(isolate);
-      return true;
-
-    default:
-      DLOG(WARNING) << "Invalid ErrorType: " << encoder;
-      return false;
-  }
-}
-
-// Base class for CrossRealmTransformWritable and CrossRealmTransformReadable.
-// Contains common methods that are used when handling MessagePort events.
-class CrossRealmTransformStream
-    : public GarbageCollected<CrossRealmTransformStream> {
- public:
-  // Neither of the subclasses require finalization, so no destructor.
-
-  virtual ScriptState* GetScriptState() const = 0;
-  virtual MessagePort* GetMessagePort() const = 0;
-
-  // HandleMessage() is called by CrossRealmTransformMessageListener to handle
-  // an incoming message from the MessagePort.
-  virtual void HandleMessage(MessageType type, v8::Local<v8::Value> value) = 0;
-
-  // HandleError() is called by CrossRealmTransformErrorListener when an error
-  // event is fired on the message port. It should error the stream.
-  virtual void HandleError(v8::Local<v8::Value> error) = 0;
-
-  virtual void Trace(Visitor*) {}
-};
-
-// Handles MessageEvents from the MessagePort.
-class CrossRealmTransformMessageListener final : public NativeEventListener {
- public:
-  explicit CrossRealmTransformMessageListener(CrossRealmTransformStream* target)
-      : target_(target) {}
-
-  void Invoke(ExecutionContext*, Event* event) override {
-    // TODO(ricea): Find a way to guarantee this cast is safe.
-    MessageEvent* message = static_cast<MessageEvent*>(event);
-    ScriptState* script_state = target_->GetScriptState();
-    // The deserializer code called by message->data() looks up the ScriptState
-    // from the current context, so we need to make sure it is set.
-    ScriptState::Scope scope(script_state);
-    v8::Local<v8::Value> data = message->data(script_state).V8Value();
-    if (!data->IsObject()) {
-      DLOG(WARNING) << "Invalid message from peer ignored (not object)";
-      return;
-    }
-
-    v8::Local<v8::Value> type;
-    v8::Local<v8::Value> value;
-    if (!UnpackKeyValueObject(script_state, data.As<v8::Object>(), "t", &type,
-                              "v", &value)) {
-      DLOG(WARNING) << "Invalid message from peer ignored";
-      return;
-    }
-
-    if (!type->IsNumber()) {
-      DLOG(WARNING) << "Invalid message from peer ignored (type is not number)";
-      return;
-    }
-
-    int type_value = type.As<v8::Number>()->Value();
-    DVLOG(3) << "MessageListener saw message type " << type_value;
-    target_->HandleMessage(static_cast<MessageType>(type_value), value);
-  }
-
-  void Trace(Visitor* visitor) override {
-    visitor->Trace(target_);
-    NativeEventListener::Trace(visitor);
-  }
-
- private:
-  const Member<CrossRealmTransformStream> target_;
-};
-
-// Handles "error" events from the MessagePort.
-class CrossRealmTransformErrorListener final : public NativeEventListener {
- public:
-  explicit CrossRealmTransformErrorListener(CrossRealmTransformStream* target)
-      : target_(target) {}
-
-  void Invoke(ExecutionContext*, Event*) override {
-    ScriptState* script_state = target_->GetScriptState();
-    const auto* error =
-        DOMException::Create("chunk could not be cloned", "DataCloneError");
-    auto* message_port = target_->GetMessagePort();
-    v8::Local<v8::Value> error_value = ToV8(error, script_state);
-    ExceptionState exception_state(script_state->GetIsolate(),
-                                   ExceptionState::kUnknownContext, "", "");
-
-    PackAndPostMessage(script_state, message_port, MessageType::kError,
-                       PackReason(script_state, error_value), exception_state);
-    if (exception_state.HadException()) {
-      DLOG(WARNING) << "Ignoring postMessage failure in error listener";
-      exception_state.ClearException();
-    }
-
-    message_port->close();
-    target_->HandleError(error_value);
-  }
-
-  void Trace(Visitor* visitor) override {
-    visitor->Trace(target_);
-    NativeEventListener::Trace(visitor);
-  }
-
- private:
-  const Member<CrossRealmTransformStream> target_;
-};
-
-// Class for data associated with the writable side of the cross realm transform
-// stream.
-class CrossRealmTransformWritable final : public CrossRealmTransformStream {
- public:
-  CrossRealmTransformWritable(ScriptState* script_state, MessagePort* port)
-      : script_state_(script_state),
-        message_port_(port),
-        backpressure_promise_(
-            MakeGarbageCollected<StreamPromiseResolver>(script_state)) {}
-
-  WritableStreamNative* CreateWritableStream(ExceptionState&);
-
-  ScriptState* GetScriptState() const override { return script_state_; }
-  MessagePort* GetMessagePort() const override { return message_port_; }
-  void HandleMessage(MessageType type, v8::Local<v8::Value> value) override;
-  void HandleError(v8::Local<v8::Value> error) override;
-
-  void Trace(Visitor* visitor) override {
-    visitor->Trace(script_state_);
-    visitor->Trace(message_port_);
-    visitor->Trace(backpressure_promise_);
-    visitor->Trace(controller_);
-    CrossRealmTransformStream::Trace(visitor);
-  }
-
- private:
-  class WriteAlgorithm;
-  class CloseAlgorithm;
-  class AbortAlgorithm;
-
-  const Member<ScriptState> script_state_;
-  const Member<MessagePort> message_port_;
-  Member<StreamPromiseResolver> backpressure_promise_;
-  Member<WritableStreamDefaultController> controller_;
-};
-
-class CrossRealmTransformWritable::WriteAlgorithm final
-    : public StreamAlgorithm {
- public:
-  explicit WriteAlgorithm(CrossRealmTransformWritable* writable)
-      : writable_(writable) {}
-
-  // Sends the chunk to the readable side, possibly after waiting for
-  // backpressure.
-  v8::Local<v8::Promise> Run(ScriptState* script_state,
-                             int argc,
-                             v8::Local<v8::Value> argv[]) override {
-    DCHECK_EQ(argc, 1);
-    auto chunk = argv[0];
-
-    if (!writable_->backpressure_promise_) {
-      return DoWrite(script_state, chunk);
-    }
-
-    auto* isolate = script_state->GetIsolate();
-    return StreamThenPromise(
-        script_state->GetContext(),
-        writable_->backpressure_promise_->V8Promise(isolate),
-        MakeGarbageCollected<DoWriteOnResolve>(script_state, chunk, this));
-  }
-
-  void Trace(Visitor* visitor) override {
-    visitor->Trace(writable_);
-    StreamAlgorithm::Trace(visitor);
-  }
-
- private:
-  // A promise handler which calls DoWrite() when the promise resolves.
-  class DoWriteOnResolve final : public PromiseHandlerWithValue {
-   public:
-    DoWriteOnResolve(ScriptState* script_state,
-                     v8::Local<v8::Value> chunk,
-                     WriteAlgorithm* target)
-        : PromiseHandlerWithValue(script_state),
-          chunk_(script_state->GetIsolate(), chunk),
-          target_(target) {}
-
-    v8::Local<v8::Value> CallWithLocal(v8::Local<v8::Value>) override {
-      ScriptState* script_state = GetScriptState();
-      return target_->DoWrite(script_state,
-                              chunk_.NewLocal(script_state->GetIsolate()));
-    }
-
-    void Trace(Visitor* visitor) override {
-      visitor->Trace(chunk_);
-      visitor->Trace(target_);
-      PromiseHandlerWithValue::Trace(visitor);
-    }
-
-   private:
-    const TraceWrapperV8Reference<v8::Value> chunk_;
-    const Member<WriteAlgorithm> target_;
-  };
-
-  // Sends a chunk over the message port to the readable side.
-  v8::Local<v8::Promise> DoWrite(ScriptState* script_state,
-                                 v8::Local<v8::Value> chunk) {
-    writable_->backpressure_promise_ =
-        MakeGarbageCollected<StreamPromiseResolver>(script_state);
-    ExceptionState exception_state(script_state->GetIsolate(),
-                                   ExceptionState::kUnknownContext, "", "");
-    PackAndPostMessage(script_state, writable_->message_port_,
-                       MessageType::kChunk, chunk, exception_state);
-    if (exception_state.HadException()) {
-      auto exception = exception_state.GetException();
-      exception_state.ClearException();
-
-      PackAndPostMessage(
-          script_state, writable_->message_port_, MessageType::kError,
-          PackReason(writable_->script_state_, exception), exception_state);
-      if (exception_state.HadException()) {
-        DLOG(WARNING) << "Disregarding exception while sending error";
-        exception_state.ClearException();
-      }
-
-      writable_->message_port_->close();
-      return PromiseReject(script_state, exception);
-    }
-
-    return PromiseResolveWithUndefined(script_state);
-  }
-
-  const Member<CrossRealmTransformWritable> writable_;
-};
-
-class CrossRealmTransformWritable::CloseAlgorithm final
-    : public StreamAlgorithm {
- public:
-  explicit CloseAlgorithm(CrossRealmTransformWritable* writable)
-      : writable_(writable) {}
-
-  // Sends a close message to the readable side and closes the message port.
-  v8::Local<v8::Promise> Run(ScriptState* script_state,
-                             int argc,
-                             v8::Local<v8::Value> argv[]) override {
-    DCHECK_EQ(argc, 0);
-    ExceptionState exception_state(script_state->GetIsolate(),
-                                   ExceptionState::kUnknownContext, "", "");
-    PackAndPostMessage(
-        script_state, writable_->message_port_, MessageType::kClose,
-        v8::Undefined(script_state->GetIsolate()), exception_state);
-    if (exception_state.HadException()) {
-      DLOG(WARNING) << "Ignoring exception from PackAndPostMessage kClose";
-      exception_state.ClearException();
-    }
-
-    writable_->message_port_->close();
-    return PromiseResolveWithUndefined(script_state);
-  }
-
-  void Trace(Visitor* visitor) override {
-    visitor->Trace(writable_);
-    StreamAlgorithm::Trace(visitor);
-  }
-
- private:
-  const Member<CrossRealmTransformWritable> writable_;
-};
-
-class CrossRealmTransformWritable::AbortAlgorithm final
-    : public StreamAlgorithm {
- public:
-  explicit AbortAlgorithm(CrossRealmTransformWritable* writable)
-      : writable_(writable) {}
-
-  // Sends an abort message to the readable side and closes the message port.
-  v8::Local<v8::Promise> Run(ScriptState* script_state,
-                             int argc,
-                             v8::Local<v8::Value> argv[]) override {
-    DCHECK_EQ(argc, 1);
-    auto reason = argv[0];
-    ExceptionState exception_state(script_state->GetIsolate(),
-                                   ExceptionState::kUnknownContext, "", "");
-    PackAndPostMessage(
-        script_state, writable_->message_port_, MessageType::kAbort,
-        PackReason(writable_->script_state_, reason), exception_state);
-    if (exception_state.HadException()) {
-      DLOG(WARNING) << "Ignoring exception from PackAndPostMessage kAbort";
-      exception_state.ClearException();
-    }
-    writable_->message_port_->close();
-    return PromiseResolveWithUndefined(script_state);
-  }
-
-  void Trace(Visitor* visitor) override {
-    visitor->Trace(writable_);
-    StreamAlgorithm::Trace(visitor);
-  }
-
- private:
-  const Member<CrossRealmTransformWritable> writable_;
-};
-
-WritableStreamNative* CrossRealmTransformWritable::CreateWritableStream(
-    ExceptionState& exception_state) {
-  DCHECK(!controller_) << "CreateWritableStream() can only be called once";
-
-  message_port_->setOnmessage(
-      MakeGarbageCollected<CrossRealmTransformMessageListener>(this));
-  message_port_->setOnmessageerror(
-      MakeGarbageCollected<CrossRealmTransformErrorListener>(this));
-
-  auto* stream = WritableStreamNative::Create(
-      script_state_, CreateTrivialStartAlgorithm(),
-      MakeGarbageCollected<WriteAlgorithm>(this),
-      MakeGarbageCollected<CloseAlgorithm>(this),
-      MakeGarbageCollected<AbortAlgorithm>(this), 1,
-      CreateDefaultSizeAlgorithm(), exception_state);
-
-  if (exception_state.HadException()) {
-    return nullptr;
-  }
-
-  controller_ = stream->Controller();
-  return stream;
-}
-
-void CrossRealmTransformWritable::HandleMessage(MessageType type,
-                                                v8::Local<v8::Value> value) {
-  switch (type) {
-    case MessageType::kPull:
-      DCHECK(backpressure_promise_);
-      backpressure_promise_->ResolveWithUndefined(script_state_);
-      backpressure_promise_ = nullptr;
-      return;
-
-    case MessageType::kCancel:
-    case MessageType::kError: {
-      v8::Local<v8::Value> reason;
-      if (!UnpackReason(script_state_, value, &reason)) {
-        DLOG(WARNING)
-            << "Invalid message from peer ignored (unable to unpack value)";
-        return;
-      }
-      WritableStreamDefaultController::ErrorIfNeeded(script_state_, controller_,
-                                                     reason);
-      if (backpressure_promise_) {
-        backpressure_promise_->ResolveWithUndefined(script_state_);
-        backpressure_promise_ = nullptr;
-      }
-      return;
-    }
-
-    default:
-      DLOG(WARNING) << "Invalid message from peer ignored (invalid type): "
-                    << static_cast<int>(type);
-      return;
-  }
-}
-
-void CrossRealmTransformWritable::HandleError(v8::Local<v8::Value> error) {
-  WritableStreamDefaultController::ErrorIfNeeded(script_state_, controller_,
-                                                 error);
-}
-
-// Class for data associated with the readable side of the cross realm transform
-// stream.
-class CrossRealmTransformReadable final : public CrossRealmTransformStream {
- public:
-  CrossRealmTransformReadable(ScriptState* script_state, MessagePort* port)
-      : script_state_(script_state),
-        message_port_(port),
-        backpressure_promise_(
-            MakeGarbageCollected<StreamPromiseResolver>(script_state)) {}
-
-  ReadableStreamNative* CreateReadableStream(ExceptionState&);
-
-  ScriptState* GetScriptState() const override { return script_state_; }
-  MessagePort* GetMessagePort() const override { return message_port_; }
-  void HandleMessage(MessageType type, v8::Local<v8::Value> value) override;
-  void HandleError(v8::Local<v8::Value> error) override;
-
-  void Trace(Visitor* visitor) override {
-    visitor->Trace(script_state_);
-    visitor->Trace(message_port_);
-    visitor->Trace(backpressure_promise_);
-    visitor->Trace(controller_);
-    CrossRealmTransformStream::Trace(visitor);
-  }
-
- private:
-  class PullAlgorithm;
-  class CancelAlgorithm;
-
-  const Member<ScriptState> script_state_;
-  const Member<MessagePort> message_port_;
-  Member<StreamPromiseResolver> backpressure_promise_;
-  Member<ReadableStreamDefaultController> controller_;
-  bool finished_ = false;
-};
-
-class CrossRealmTransformReadable::PullAlgorithm final
-    : public StreamAlgorithm {
- public:
-  explicit PullAlgorithm(CrossRealmTransformReadable* readable)
-      : readable_(readable) {}
-
-  // Sends a pull message to the writable side and then waits for backpressure
-  // to clear.
-  v8::Local<v8::Promise> Run(ScriptState* script_state,
-                             int argc,
-                             v8::Local<v8::Value> argv[]) override {
-    DCHECK_EQ(argc, 0);
-    auto* isolate = script_state->GetIsolate();
-    ExceptionState exception_state(isolate, ExceptionState::kUnknownContext, "",
-                                   "");
-
-    PackAndPostMessage(
-        script_state, readable_->message_port_, MessageType::kPull,
-        v8::Undefined(script_state->GetIsolate()), exception_state);
-    if (exception_state.HadException()) {
-      DLOG(WARNING) << "Ignoring exception from PackAndPostMessage kClose";
-      exception_state.ClearException();
-    }
-
-    return readable_->backpressure_promise_->V8Promise(isolate);
-  }
-
-  void Trace(Visitor* visitor) override {
-    visitor->Trace(readable_);
-    StreamAlgorithm::Trace(visitor);
-  }
-
- private:
-  const Member<CrossRealmTransformReadable> readable_;
-};
-
-class CrossRealmTransformReadable::CancelAlgorithm final
-    : public StreamAlgorithm {
- public:
-  explicit CancelAlgorithm(CrossRealmTransformReadable* readable)
-      : readable_(readable) {}
-
-  // Sends a cancel message to the writable side and closes the message port.
-  v8::Local<v8::Promise> Run(ScriptState* script_state,
-                             int argc,
-                             v8::Local<v8::Value> argv[]) override {
-    DCHECK_EQ(argc, 1);
-    auto reason = argv[0];
-    readable_->finished_ = true;
-    ExceptionState exception_state(script_state->GetIsolate(),
-                                   ExceptionState::kUnknownContext, "", "");
-
-    PackAndPostMessage(script_state, readable_->message_port_,
-                       MessageType::kCancel, PackReason(script_state, reason),
-                       exception_state);
-    if (exception_state.HadException()) {
-      DLOG(WARNING) << "Ignoring exception from PackAndPostMessage kClose";
-      exception_state.ClearException();
-    }
-
-    readable_->message_port_->close();
-    return PromiseResolveWithUndefined(script_state);
-  }
-
-  void Trace(Visitor* visitor) override {
-    visitor->Trace(readable_);
-    StreamAlgorithm::Trace(visitor);
-  }
-
- private:
-  const Member<CrossRealmTransformReadable> readable_;
-};
-
-ReadableStreamNative* CrossRealmTransformReadable::CreateReadableStream(
-    ExceptionState& exception_state) {
-  DCHECK(!controller_) << "CreateReadableStream can only be called once";
-
-  message_port_->setOnmessage(
-      MakeGarbageCollected<CrossRealmTransformMessageListener>(this));
-  message_port_->setOnmessageerror(
-      MakeGarbageCollected<CrossRealmTransformErrorListener>(this));
-
-  auto* stream = ReadableStreamNative::Create(
-      script_state_, CreateTrivialStartAlgorithm(),
-      MakeGarbageCollected<PullAlgorithm>(this),
-      MakeGarbageCollected<CancelAlgorithm>(this),
-      /* highWaterMark = */ 0, CreateDefaultSizeAlgorithm(), exception_state);
-
-  if (exception_state.HadException()) {
-    return nullptr;
-  }
-
-  controller_ = stream->GetController();
-  return stream;
-}
-
-void CrossRealmTransformReadable::HandleMessage(MessageType type,
-                                                v8::Local<v8::Value> value) {
-  switch (type) {
-    case MessageType::kChunk: {
-      // This can't throw because we always use the default strategy size
-      // algorithm, which doesn't throw, and always returns a valid value of
-      // 1.0.
-      ReadableStreamDefaultController::Enqueue(script_state_, controller_,
-                                               value, ASSERT_NO_EXCEPTION);
-
-      backpressure_promise_->ResolveWithUndefined(script_state_);
-      backpressure_promise_ =
-          MakeGarbageCollected<StreamPromiseResolver>(script_state_);
-      return;
-    }
-
-    case MessageType::kClose:
-      finished_ = true;
-      ReadableStreamDefaultController::Close(script_state_, controller_);
-      message_port_->close();
-      return;
-
-    case MessageType::kAbort:
-    case MessageType::kError: {
-      finished_ = true;
-      v8::Local<v8::Value> reason;
-      if (!UnpackReason(script_state_, value, &reason)) {
-        DLOG(WARNING)
-            << "Invalid message from peer ignored (unable to unpack value)";
-        return;
-      }
-
-      ReadableStreamDefaultController::Error(script_state_, controller_,
-                                             reason);
-      message_port_->close();
-      return;
-    }
-
-    default:
-      DLOG(WARNING) << "Invalid message from peer ignored (invalid type): "
-                    << static_cast<int>(type);
-      return;
-  }
-}
-
-void CrossRealmTransformReadable::HandleError(v8::Local<v8::Value> error) {
-  ReadableStreamDefaultController::Error(script_state_, controller_, error);
-}
-
-}  // namespace
-
-CORE_EXPORT WritableStreamNative* CreateCrossRealmTransformWritable(
-    ScriptState* script_state,
-    MessagePort* port,
-    ExceptionState& exception_state) {
-  return MakeGarbageCollected<CrossRealmTransformWritable>(script_state, port)
-      ->CreateWritableStream(exception_state);
-}
-
-CORE_EXPORT ReadableStreamNative* CreateCrossRealmTransformReadable(
-    ScriptState* script_state,
-    MessagePort* port,
-    ExceptionState& exception_state) {
-  return MakeGarbageCollected<CrossRealmTransformReadable>(script_state, port)
-      ->CreateReadableStream(exception_state);
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/streams/transferable_streams.h b/third_party/blink/renderer/core/streams/transferable_streams.h
deleted file mode 100644
index 62883f1..0000000
--- a/third_party/blink/renderer/core/streams/transferable_streams.h
+++ /dev/null
@@ -1,37 +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.
-
-// Functions used to build transferable streams.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_TRANSFERABLE_STREAMS_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_TRANSFERABLE_STREAMS_H_
-
-#include "third_party/blink/renderer/core/core_export.h"
-
-namespace blink {
-
-class ExceptionState;
-class MessagePort;
-class ReadableStreamNative;
-class ScriptState;
-class WritableStreamNative;
-
-// Creates the writable side of a cross-realm identity transform stream, using
-// |port| for communication. |port| must be entangled with another MessagePort
-// which is passed to CreateCrossRealmTransformReadable().
-CORE_EXPORT WritableStreamNative* CreateCrossRealmTransformWritable(
-    ScriptState*,
-    MessagePort* port,
-    ExceptionState&);
-
-// Creates the readable side of a cross-realm identity transform stream. |port|
-// is used symmetrically with CreateCrossRealmTransformWritable().
-CORE_EXPORT ReadableStreamNative* CreateCrossRealmTransformReadable(
-    ScriptState*,
-    MessagePort* port,
-    ExceptionState&);
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_TRANSFERABLE_STREAMS_H_
diff --git a/third_party/blink/renderer/core/streams/transferable_streams_test.cc b/third_party/blink/renderer/core/streams/transferable_streams_test.cc
deleted file mode 100644
index 3811b05..0000000
--- a/third_party/blink/renderer/core/streams/transferable_streams_test.cc
+++ /dev/null
@@ -1,129 +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 "third_party/blink/renderer/core/streams/transferable_streams.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_iterator_result_value.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_readable_stream_default_reader.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_writable_stream_default_writer.h"
-#include "third_party/blink/renderer/core/messaging/message_channel.h"
-#include "third_party/blink/renderer/core/streams/readable_stream_default_reader.h"
-#include "third_party/blink/renderer/core/streams/readable_stream_native.h"
-#include "third_party/blink/renderer/core/streams/writable_stream_default_writer.h"
-#include "third_party/blink/renderer/core/streams/writable_stream_native.h"
-#include "third_party/blink/renderer/platform/bindings/exception_state.h"
-#include "third_party/blink/renderer/platform/heap/heap.h"
-#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
-
-namespace blink {
-
-namespace {
-
-// We only do minimal testing here. The functionality of transferable streams is
-// tested in the layout tests.
-TEST(TransferableStreamsTest, SmokeTest) {
-  V8TestingScope scope;
-
-  auto* channel =
-      MakeGarbageCollected<MessageChannel>(scope.GetExecutionContext());
-  auto* script_state = scope.GetScriptState();
-  auto* writable = CreateCrossRealmTransformWritable(
-      script_state, channel->port1(), ASSERT_NO_EXCEPTION);
-  ASSERT_TRUE(writable);
-  auto* readable = CreateCrossRealmTransformReadable(
-      script_state, channel->port2(), ASSERT_NO_EXCEPTION);
-  ASSERT_TRUE(readable);
-
-  auto* writer = V8WritableStreamDefaultWriter::ToImpl(
-      writable->getWriter(script_state, ASSERT_NO_EXCEPTION)
-          .V8Value()
-          .As<v8::Object>());
-  auto* reader = V8ReadableStreamDefaultReader::ToImpl(
-      readable->getReader(script_state, ASSERT_NO_EXCEPTION)
-          .V8Value()
-          .As<v8::Object>());
-
-  writer->write(script_state, ScriptValue::CreateNull(script_state));
-
-  class ExpectNullResponse : public ScriptFunction {
-   public:
-    static v8::Local<v8::Function> Create(ScriptState* script_state,
-                                          bool* got_response) {
-      auto* self =
-          MakeGarbageCollected<ExpectNullResponse>(script_state, got_response);
-      return self->BindToV8Function();
-    }
-
-    ExpectNullResponse(ScriptState* script_state, bool* got_response)
-        : ScriptFunction(script_state), got_response_(got_response) {}
-
-   private:
-    ScriptValue Call(ScriptValue value) override {
-      *got_response_ = true;
-      if (!value.IsObject()) {
-        ADD_FAILURE() << "iterator must be an object";
-        return ScriptValue();
-      }
-      bool done = false;
-      auto* script_state = GetScriptState();
-      auto chunk_maybe =
-          V8UnpackIteratorResult(script_state,
-                                 value.V8Value()
-                                     ->ToObject(script_state->GetContext())
-                                     .ToLocalChecked(),
-                                 &done);
-      EXPECT_FALSE(done);
-      v8::Local<v8::Value> chunk;
-      if (!chunk_maybe.ToLocal(&chunk)) {
-        ADD_FAILURE() << "V8UnpackIteratorResult failed";
-        return ScriptValue();
-      }
-      EXPECT_TRUE(chunk->IsNull());
-      return ScriptValue();
-    }
-
-    bool* got_response_;
-  };
-
-  // TODO(ricea): This is copy-and-pasted from transform_stream_test.cc. Put it
-  // in a shared location.
-  class ExpectNotReached : public ScriptFunction {
-   public:
-    static v8::Local<v8::Function> Create(ScriptState* script_state) {
-      auto* self = MakeGarbageCollected<ExpectNotReached>(script_state);
-      return self->BindToV8Function();
-    }
-
-    explicit ExpectNotReached(ScriptState* script_state)
-        : ScriptFunction(script_state) {}
-
-   private:
-    ScriptValue Call(ScriptValue) override {
-      ADD_FAILURE() << "ExpectNotReached was reached";
-      return ScriptValue();
-    }
-  };
-
-  bool got_response = false;
-  reader->read(script_state)
-      .Then(ExpectNullResponse::Create(script_state, &got_response),
-            ExpectNotReached::Create(script_state));
-
-  // Need to run the event loop to pass messages through the MessagePort.
-  test::RunPendingTasks();
-
-  // Resolve promises.
-  v8::MicrotasksScope::PerformCheckpoint(scope.GetIsolate());
-
-  EXPECT_TRUE(got_response);
-}
-
-}  // namespace
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/streams/writable_stream.cc b/third_party/blink/renderer/core/streams/writable_stream.cc
index 3d6f944..da3db6e 100644
--- a/third_party/blink/renderer/core/streams/writable_stream.cc
+++ b/third_party/blink/renderer/core/streams/writable_stream.cc
@@ -57,10 +57,7 @@
 WritableStream* WritableStream::Deserialize(ScriptState* script_state,
                                             MessagePort* port,
                                             ExceptionState& exception_state) {
-  if (RuntimeEnabledFeatures::StreamsNativeEnabled()) {
-    return WritableStreamNative::Deserialize(script_state, port,
-                                             exception_state);
-  }
+  // TODO(ricea): Switch on Blink feature.
   return WritableStreamWrapper::Deserialize(script_state, port,
                                             exception_state);
 }
diff --git a/third_party/blink/renderer/core/streams/writable_stream_default_writer.h b/third_party/blink/renderer/core/streams/writable_stream_default_writer.h
index fbe239e..1bb5bea 100644
--- a/third_party/blink/renderer/core/streams/writable_stream_default_writer.h
+++ b/third_party/blink/renderer/core/streams/writable_stream_default_writer.h
@@ -6,7 +6,6 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_WRITABLE_STREAM_DEFAULT_WRITER_H_
 
 #include "base/optional.h"
-#include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
 #include "v8/include/v8.h"
 
@@ -22,7 +21,7 @@
 class WritableStreamNative;
 
 // https://streams.spec.whatwg.org/#default-writer-class
-class CORE_EXPORT WritableStreamDefaultWriter final : public ScriptWrappable {
+class WritableStreamDefaultWriter final : public ScriptWrappable {
   DEFINE_WRAPPERTYPEINFO();
 
  public:
diff --git a/third_party/blink/renderer/core/streams/writable_stream_native.cc b/third_party/blink/renderer/core/streams/writable_stream_native.cc
index c0ee787..262a9833 100644
--- a/third_party/blink/renderer/core/streams/writable_stream_native.cc
+++ b/third_party/blink/renderer/core/streams/writable_stream_native.cc
@@ -7,9 +7,7 @@
 #include "third_party/blink/renderer/bindings/core/v8/script_value.h"
 #include "third_party/blink/renderer/core/streams/miscellaneous_operations.h"
 #include "third_party/blink/renderer/core/streams/promise_handler.h"
-#include "third_party/blink/renderer/core/streams/readable_stream_native.h"
 #include "third_party/blink/renderer/core/streams/stream_promise_resolver.h"
-#include "third_party/blink/renderer/core/streams/transferable_streams.h"
 #include "third_party/blink/renderer/core/streams/writable_stream_default_controller.h"
 #include "third_party/blink/renderer/core/streams/writable_stream_default_writer.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
@@ -217,41 +215,6 @@
   return stream;
 }
 
-void WritableStreamNative::Serialize(ScriptState* script_state,
-                                     MessagePort* port,
-                                     ExceptionState& exception_state) {
-  if (IsLocked(this)) {
-    exception_state.ThrowTypeError("Cannot transfer a locked stream");
-    return;
-  }
-
-  auto* readable =
-      CreateCrossRealmTransformReadable(script_state, port, exception_state);
-  if (exception_state.HadException()) {
-    return;
-  }
-
-  auto promise = ReadableStreamNative::PipeTo(
-      script_state, readable, this, ReadableStreamNative::PipeOptions());
-  promise.MarkAsHandled();
-}
-
-WritableStreamNative* WritableStreamNative::Deserialize(
-    ScriptState* script_state,
-    MessagePort* port,
-    ExceptionState& exception_state) {
-  // We need to execute JavaScript to call "Then" on v8::Promises. We will not
-  // run author code.
-  v8::Isolate::AllowJavascriptExecutionScope allow_js(
-      script_state->GetIsolate());
-  auto* writable =
-      CreateCrossRealmTransformWritable(script_state, port, exception_state);
-  if (exception_state.HadException()) {
-    return nullptr;
-  }
-  return writable;
-}
-
 WritableStreamDefaultWriter* WritableStreamNative::AcquireDefaultWriter(
     ScriptState* script_state,
     WritableStreamNative* stream,
diff --git a/third_party/blink/renderer/core/streams/writable_stream_native.h b/third_party/blink/renderer/core/streams/writable_stream_native.h
index e1848c6..64f80fc2 100644
--- a/third_party/blink/renderer/core/streams/writable_stream_native.h
+++ b/third_party/blink/renderer/core/streams/writable_stream_native.h
@@ -83,11 +83,9 @@
     return stream->writer_;
   }
 
-  void Serialize(ScriptState*, MessagePort*, ExceptionState&) override;
-
-  static WritableStreamNative* Deserialize(ScriptState*,
-                                           MessagePort*,
-                                           ExceptionState&);
+  void Serialize(ScriptState*, MessagePort*, ExceptionState&) override {
+    // TODO(ricea): Implement this.
+  }
 
   //
   // Methods used by ReadableStreamNative::PipeTo
diff --git a/third_party/blink/renderer/core/streams/writable_stream_test.cc b/third_party/blink/renderer/core/streams/writable_stream_test.cc
index e87946d1..5401cc7 100644
--- a/third_party/blink/renderer/core/streams/writable_stream_test.cc
+++ b/third_party/blink/renderer/core/streams/writable_stream_test.cc
@@ -60,6 +60,12 @@
 }
 
 TEST_P(WritableStreamTest, Serialize) {
+  // Disable the test when StreamsNative is enabled as WritableStreamNative
+  // doesn't support serialization yet.
+  // TODO(ricea): Re-enable this test when serialization is supported.
+  if (GetParam())
+    return;
+
   ScopedTransferableStreamsForTest enable_transferable_streams(true);
 
   V8TestingScope scope;
diff --git a/third_party/blink/renderer/core/testing/page_test_base.cc b/third_party/blink/renderer/core/testing/page_test_base.cc
index f4745dc..f2ab10fb 100644
--- a/third_party/blink/renderer/core/testing/page_test_base.cc
+++ b/third_party/blink/renderer/core/testing/page_test_base.cc
@@ -114,6 +114,14 @@
   UpdateAllLifecyclePhasesForTest();
 }
 
+void PageTestBase::NavigateTo(const KURL& url) {
+  GetFrame().Loader().CommitNavigation(
+      WebNavigationParams::CreateWithHTMLBuffer(SharedBuffer::Create(), url),
+      nullptr /* extra_data */);
+  blink::test::RunPendingTasks();
+  ASSERT_EQ(url.GetString(), GetDocument().Url().GetString());
+}
+
 void PageTestBase::UpdateAllLifecyclePhasesForTest() {
   GetDocument().View()->UpdateAllLifecyclePhases(
       DocumentLifecycle::LifecycleUpdateReason::kTest);
diff --git a/third_party/blink/renderer/core/testing/page_test_base.h b/third_party/blink/renderer/core/testing/page_test_base.h
index a88ee48..41e34543 100644
--- a/third_party/blink/renderer/core/testing/page_test_base.h
+++ b/third_party/blink/renderer/core/testing/page_test_base.h
@@ -33,6 +33,10 @@
   void SetBodyInnerHTML(const String&);
   void SetHtmlInnerHTML(const std::string&);
 
+  // Navigate to |url| providing an empty response but
+  // URL and security origin of the Document will be set to |url|.
+  void NavigateTo(const KURL& url);
+
   Document& GetDocument() const;
   Page& GetPage() const;
   LocalFrame& GetFrame() const;
diff --git a/third_party/blink/renderer/core/timing/performance_observer.idl b/third_party/blink/renderer/core/timing/performance_observer.idl
index c4348fb..8d28a31 100644
--- a/third_party/blink/renderer/core/timing/performance_observer.idl
+++ b/third_party/blink/renderer/core/timing/performance_observer.idl
@@ -15,5 +15,5 @@
     [RaisesException] void observe(optional PerformanceObserverInit options);
     void disconnect();
     PerformanceEntryList takeRecords();
-    [CallWith=ScriptState] static readonly attribute FrozenArray<DOMString> supportedEntryTypes;
+    [SameObject, SaveSameObject, CallWith=ScriptState] static readonly attribute FrozenArray<DOMString> supportedEntryTypes;
 };
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker.cc b/third_party/blink/renderer/core/workers/dedicated_worker.cc
index 33a6f92..5738e86 100644
--- a/third_party/blink/renderer/core/workers/dedicated_worker.cc
+++ b/third_party/blink/renderer/core/workers/dedicated_worker.cc
@@ -20,6 +20,7 @@
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/events/message_event.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/core/fetch/request.h"
 #include "third_party/blink/renderer/core/fileapi/public_url_manager.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/local_frame_client.h"
@@ -211,6 +212,18 @@
   if (auto* scope = DynamicTo<WorkerGlobalScope>(*GetExecutionContext()))
     scope->EnsureFetcher();
   if (blink::features::IsPlzDedicatedWorkerEnabled()) {
+    // For classic script, always use "same-origin" credentials mode.
+    // https://html.spec.whatwg.org/C/#fetch-a-classic-worker-script
+    // For module script, respect the credentials mode specified by
+    // WorkerOptions.
+    // https://html.spec.whatwg.org/C/#workeroptions
+    auto credentials_mode = network::mojom::FetchCredentialsMode::kSameOrigin;
+    if (options_->type() == "module") {
+      bool result = Request::ParseCredentialsMode(options_->credentials(),
+                                                  &credentials_mode);
+      DCHECK(result);
+    }
+
     mojom::blink::BlobURLTokenPtr blob_url_token;
     if (script_request_url_.ProtocolIs("blob") &&
         BlobUtils::MojoBlobURLsEnabled()) {
@@ -221,7 +234,7 @@
     factory_client_->CreateWorkerHost(
         script_request_url_,
         WebSecurityOrigin(GetExecutionContext()->GetSecurityOrigin()),
-        blob_url_token.PassInterface().PassHandle());
+        credentials_mode, blob_url_token.PassInterface().PassHandle());
     // Continue in OnScriptLoadStarted() or OnScriptLoadStartFailed().
     return;
   }
diff --git a/third_party/blink/renderer/core/workers/main_thread_worklet_test.cc b/third_party/blink/renderer/core/workers/main_thread_worklet_test.cc
index 77dc5346..6ba6b52 100644
--- a/third_party/blink/renderer/core/workers/main_thread_worklet_test.cc
+++ b/third_party/blink/renderer/core/workers/main_thread_worklet_test.cc
@@ -51,9 +51,8 @@
   }
   void SetUpScope(const String& csp_header) {
     PageTestBase::SetUp(IntSize());
+    NavigateTo(KURL("https://example.com/"));
     Document* document = &GetDocument();
-    document->SetURL(KURL("https://example.com/"));
-    document->UpdateSecurityOrigin(SecurityOrigin::Create(document->Url()));
 
     // Set up the CSP for Document before starting MainThreadWorklet because
     // MainThreadWorklet inherits the owner Document's CSP.
diff --git a/third_party/blink/renderer/core/workers/threaded_worklet_test.cc b/third_party/blink/renderer/core/workers/threaded_worklet_test.cc
index 9a2128a..e03a79e 100644
--- a/third_party/blink/renderer/core/workers/threaded_worklet_test.cc
+++ b/third_party/blink/renderer/core/workers/threaded_worklet_test.cc
@@ -230,9 +230,13 @@
  public:
   void SetUp() override {
     page_ = std::make_unique<DummyPageHolder>();
-    Document* document = page_->GetFrame().GetDocument();
-    document->SetURL(KURL("https://example.com/"));
-    document->UpdateSecurityOrigin(SecurityOrigin::Create(document->Url()));
+    KURL url("https://example.com/");
+    page_->GetFrame().Loader().CommitNavigation(
+        WebNavigationParams::CreateWithHTMLBuffer(SharedBuffer::Create(), url),
+        nullptr /* extra_data */);
+    blink::test::RunPendingTasks();
+    ASSERT_EQ(url.GetString(), GetDocument().Url().GetString());
+
     messaging_proxy_ =
         MakeGarbageCollected<ThreadedWorkletMessagingProxyForTest>(
             &page_->GetDocument());
diff --git a/third_party/blink/renderer/modules/BUILD.gn b/third_party/blink/renderer/modules/BUILD.gn
index 726a16e3..4ea796ad 100644
--- a/third_party/blink/renderer/modules/BUILD.gn
+++ b/third_party/blink/renderer/modules/BUILD.gn
@@ -330,6 +330,7 @@
     "mediastream/media_constraints_test.cc",
     "mediastream/media_devices_test.cc",
     "mediastream/media_stream_video_capturer_source_test.cc",
+    "mediastream/media_stream_video_renderer_sink_test.cc",
     "mediastream/mock_mojo_media_stream_dispatcher_host.cc",
     "mediastream/mock_mojo_media_stream_dispatcher_host.h",
     "mediastream/video_track_adapter_unittest.cc",
diff --git a/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope_test.cc b/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope_test.cc
index ad4f6ef..ab51390 100644
--- a/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope_test.cc
+++ b/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope_test.cc
@@ -73,9 +73,7 @@
 
   void SetUp() override {
     PageTestBase::SetUp(IntSize());
-    Document* document = &GetDocument();
-    document->SetURL(KURL("https://example.com/"));
-    document->UpdateSecurityOrigin(SecurityOrigin::Create(document->Url()));
+    NavigateTo(KURL("https://example.com/"));
     reporting_proxy_ = std::make_unique<WorkerReportingProxy>();
   }
 
diff --git a/third_party/blink/renderer/modules/credentialmanager/credentials_container_test.cc b/third_party/blink/renderer/modules/credentialmanager/credentials_container_test.cc
index 47f5e845..416bb9f 100644
--- a/third_party/blink/renderer/modules/credentialmanager/credentials_container_test.cc
+++ b/third_party/blink/renderer/modules/credentialmanager/credentials_container_test.cc
@@ -123,9 +123,8 @@
 
  public:
   CredentialManagerTestingContext(
-      MockCredentialManager* mock_credential_manager) {
-    dummy_context_.GetDocument().SetSecurityOrigin(
-        SecurityOrigin::CreateFromString("https://example.test"));
+      MockCredentialManager* mock_credential_manager)
+      : dummy_context_(KURL("https://example.test")) {
     dummy_context_.GetDocument().SetSecureContextStateForTesting(
         SecureContextState::kSecure);
     mojom::blink::DocumentInterfaceBrokerPtr doc;
diff --git a/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_test.cc b/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_test.cc
index 3d1bb160..2dce5f4 100644
--- a/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_test.cc
+++ b/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_test.cc
@@ -31,10 +31,7 @@
 
   void SetUp() override {
     PageTestBase::SetUp(IntSize());
-    Document* document = &GetDocument();
-    document->SetURL(KURL("https://example.com/"));
-    document->UpdateSecurityOrigin(SecurityOrigin::Create(document->Url()));
-
+    NavigateTo(KURL("https://example.com/"));
     dispatcher_ = base::MakeRefCounted<PaintWorkletPaintDispatcher>();
     proxy_client_ =
         MakeGarbageCollected<PaintWorkletProxyClient>(1, nullptr, dispatcher_);
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_factory_test.cc b/third_party/blink/renderer/modules/indexeddb/idb_factory_test.cc
index bbe65a2..7edf805 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_factory_test.cc
+++ b/third_party/blink/renderer/modules/indexeddb/idb_factory_test.cc
@@ -55,9 +55,7 @@
 };
 
 TEST_F(IDBFactoryTest, WebIDBGetDBInfoCallbacksResolvesPromise) {
-  V8TestingScope scope;
-  scope.GetDocument().SetSecurityOrigin(
-      SecurityOrigin::Create(KURL("https://example.com")));
+  V8TestingScope scope(KURL("https://example.com"));
   auto web_factory = std::make_unique<MockWebIDBFactory>();
   std::unique_ptr<WebIDBCallbacks> callbacks;
   web_factory->SetCallbacksPointer(&callbacks);
@@ -88,9 +86,7 @@
 }
 
 TEST_F(IDBFactoryTest, WebIDBGetDBNamesCallbacksRejectsPromise) {
-  V8TestingScope scope;
-  scope.GetDocument().SetSecurityOrigin(
-      SecurityOrigin::Create(KURL("https://example.com")));
+  V8TestingScope scope(KURL("https://example.com"));
   auto web_factory = std::make_unique<MockWebIDBFactory>();
   std::unique_ptr<WebIDBCallbacks> callbacks;
   web_factory->SetCallbacksPointer(&callbacks);
diff --git a/third_party/blink/renderer/modules/mediacapturefromelement/html_audio_element_capturer_source_unittest.cc b/third_party/blink/renderer/modules/mediacapturefromelement/html_audio_element_capturer_source_unittest.cc
index 10a4331..0d8917ba 100644
--- a/third_party/blink/renderer/modules/mediacapturefromelement/html_audio_element_capturer_source_unittest.cc
+++ b/third_party/blink/renderer/modules/mediacapturefromelement/html_audio_element_capturer_source_unittest.cc
@@ -19,12 +19,6 @@
 #include "third_party/blink/public/platform/webaudiosourceprovider_impl.h"
 #include "third_party/blink/public/web/web_heap.h"
 
-using ::testing::_;
-using ::testing::AllOf;
-using ::testing::InSequence;
-using ::testing::Mock;
-using ::testing::Property;
-
 namespace blink {
 
 static const int kNumChannelsForTest = 1;
@@ -129,20 +123,20 @@
 // This test verifies that Audio can be properly captured when injected in the
 // WebAudioSourceProviderImpl.
 TEST_F(HTMLAudioElementCapturerSourceTest, CaptureAudio) {
-  InSequence s;
+  testing::InSequence s;
 
   base::RunLoop run_loop;
   base::OnceClosure quit_closure = run_loop.QuitClosure();
 
   MockMediaStreamAudioSink sink;
   track()->AddSink(&sink);
-  EXPECT_CALL(sink, OnSetFormat(_)).Times(1);
-  EXPECT_CALL(
-      sink,
-      OnData(AllOf(Property(&media::AudioBus::channels, kNumChannelsForTest),
-                   Property(&media::AudioBus::frames,
-                            kAudioTrackSamplesPerBuffer)),
-             _))
+  EXPECT_CALL(sink, OnSetFormat(testing::_)).Times(1);
+  EXPECT_CALL(sink, OnData(testing::AllOf(
+                               testing::Property(&media::AudioBus::channels,
+                                                 kNumChannelsForTest),
+                               testing::Property(&media::AudioBus::frames,
+                                                 kAudioTrackSamplesPerBuffer)),
+                           testing::_))
       .Times(1)
       .WillOnce([&](const auto&, auto) { std::move(quit_closure).Run(); });
 
@@ -160,7 +154,7 @@
 // delivered in this case.
 TEST_F(HTMLAudioElementCapturerSourceTest,
        StartAndStopInSameTaskCapturesZeroFrames) {
-  InSequence s;
+  testing::InSequence s;
 
   // Stop the original track and start a new one so that it can be stopped in
   // in the same task.
@@ -170,12 +164,12 @@
 
   MockMediaStreamAudioSink sink;
   track()->AddSink(&sink);
-  EXPECT_CALL(
-      sink,
-      OnData(AllOf(Property(&media::AudioBus::channels, kNumChannelsForTest),
-                   Property(&media::AudioBus::frames,
-                            kAudioTrackSamplesPerBuffer)),
-             _))
+  EXPECT_CALL(sink, OnData(testing::AllOf(
+                               testing::Property(&media::AudioBus::channels,
+                                                 kNumChannelsForTest),
+                               testing::Property(&media::AudioBus::frames,
+                                                 kAudioTrackSamplesPerBuffer)),
+                           testing::_))
       .Times(0);
 
   std::unique_ptr<media::AudioBus> bus =
diff --git a/third_party/blink/renderer/modules/mediarecorder/audio_track_recorder_unittest.cc b/third_party/blink/renderer/modules/mediarecorder/audio_track_recorder_unittest.cc
index 073d35d..22b1df20 100644
--- a/third_party/blink/renderer/modules/mediarecorder/audio_track_recorder_unittest.cc
+++ b/third_party/blink/renderer/modules/mediarecorder/audio_track_recorder_unittest.cc
@@ -24,13 +24,6 @@
 
 using base::TimeTicks;
 using ::testing::_;
-using ::testing::DoAll;
-using ::testing::InSequence;
-using ::testing::Mock;
-using ::testing::Return;
-using ::testing::SaveArg;
-using ::testing::TestWithParam;
-using ::testing::ValuesIn;
 
 namespace {
 
@@ -92,7 +85,7 @@
      AudioTrackRecorder::CodecId::PCM},
 };
 
-class AudioTrackRecorderTest : public TestWithParam<ATRTestParams> {
+class AudioTrackRecorderTest : public testing::TestWithParam<ATRTestParams> {
  public:
   // Initialize |first_params_| based on test parameters, and |second_params_|
   // to always be the same thing.
@@ -260,7 +253,7 @@
   if (codec_ != AudioTrackRecorder::CodecId::OPUS)
     return;
 
-  InSequence s;
+  testing::InSequence s;
   base::RunLoop run_loop;
   base::Closure quit_closure = run_loop.QuitClosure();
 
@@ -301,14 +294,14 @@
     audio_track_recorder_->OnData(*GetSecondSourceAudioBus(), TimeTicks::Now());
 
   run_loop.Run();
-  Mock::VerifyAndClearExpectations(this);
+  testing::Mock::VerifyAndClearExpectations(this);
 }
 
 TEST_P(AudioTrackRecorderTest, OnDataPcm) {
   if (codec_ != AudioTrackRecorder::CodecId::PCM)
     return;
 
-  InSequence s;
+  testing::InSequence s;
   base::RunLoop run_loop;
   base::Closure quit_closure = run_loop.QuitClosure();
 
@@ -323,14 +316,14 @@
     audio_track_recorder_->OnData(*GetFirstSourceAudioBus(), TimeTicks::Now());
 
   run_loop.Run();
-  Mock::VerifyAndClearExpectations(this);
+  testing::Mock::VerifyAndClearExpectations(this);
 }
 
 TEST_P(AudioTrackRecorderTest, PauseResume) {
   if (codec_ != AudioTrackRecorder::CodecId::OPUS)
     return;
 
-  InSequence s;
+  testing::InSequence s;
   base::RunLoop run_loop;
   base::Closure quit_closure = run_loop.QuitClosure();
 
@@ -355,8 +348,10 @@
     audio_track_recorder_->OnData(*GetFirstSourceAudioBus(), TimeTicks::Now());
 
   run_loop.Run();
-  Mock::VerifyAndClearExpectations(this);
+  testing::Mock::VerifyAndClearExpectations(this);
 }
 
-INSTANTIATE_TEST_SUITE_P(, AudioTrackRecorderTest, ValuesIn(kATRTestParams));
+INSTANTIATE_TEST_SUITE_P(,
+                         AudioTrackRecorderTest,
+                         testing::ValuesIn(kATRTestParams));
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/mediastream/BUILD.gn b/third_party/blink/renderer/modules/mediastream/BUILD.gn
index dbfe955..3bf45c0 100644
--- a/third_party/blink/renderer/modules/mediastream/BUILD.gn
+++ b/third_party/blink/renderer/modules/mediastream/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/jumbo.gni")
 import("//third_party/blink/renderer/modules/modules.gni")
 
 blink_modules_sources("mediastream") {
@@ -32,6 +33,7 @@
     "media_stream_track_event.cc",
     "media_stream_track_event.h",
     "media_stream_video_capturer_source.cc",
+    "media_stream_video_renderer_sink.cc",
     "media_stream_video_sink.cc",
     "media_stream_video_source.cc",
     "media_stream_video_track.cc",
@@ -53,3 +55,20 @@
     "web_media_stream_utils.cc",
   ]
 }
+
+jumbo_source_set("test_support") {
+  testonly = true
+
+  sources = [
+    "mock_media_stream_registry.cc",
+    "mock_media_stream_video_source.cc",
+  ]
+
+  deps = [
+    "//base",
+    "//base/test:test_support",
+    "//skia",
+    "//testing/gmock",
+    "//third_party/blink/public/mojom:mojom_platform_blink_headers",
+  ]
+}
diff --git a/third_party/blink/renderer/modules/mediastream/DEPS b/third_party/blink/renderer/modules/mediastream/DEPS
index fa2cd1f..e47c304 100644
--- a/third_party/blink/renderer/modules/mediastream/DEPS
+++ b/third_party/blink/renderer/modules/mediastream/DEPS
@@ -25,7 +25,7 @@
 ]
 
 specific_include_rules = {
-    "media_stream_video_capturer_source_test\.cc" : [
+    ".*test\.cc" : [
         "+base/run_loop.h",
     ],
 }
diff --git a/content/renderer/media/stream/media_stream_video_renderer_sink.cc b/third_party/blink/renderer/modules/mediastream/media_stream_video_renderer_sink.cc
similarity index 72%
rename from content/renderer/media/stream/media_stream_video_renderer_sink.cc
rename to third_party/blink/renderer/modules/mediastream/media_stream_video_renderer_sink.cc
index cdf3b92..4af12d7 100644
--- a/content/renderer/media/stream/media_stream_video_renderer_sink.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_video_renderer_sink.cc
@@ -2,24 +2,22 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/renderer/media/stream/media_stream_video_renderer_sink.h"
+#include "third_party/blink/public/web/modules/mediastream/media_stream_video_renderer_sink.h"
 
 #include <utility>
 
 #include "base/bind.h"
-#include "base/feature_list.h"
-#include "base/memory/weak_ptr.h"
-#include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
 #include "base/trace_event/trace_event.h"
 #include "media/base/video_frame.h"
 #include "media/base/video_frame_metadata.h"
 #include "media/base/video_util.h"
+#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
+#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
 
 const int kMinFrameSize = 2;
 
-namespace content {
+namespace blink {
 
 // FrameDeliverer is responsible for delivering frames received on
 // OnVideoFrame() to |repaint_cb_| on the IO thread.
@@ -60,11 +58,11 @@
     if (state_ != STARTED) {
       if (emit_frame_drop_events_) {
         emit_frame_drop_events_ = false;
-        main_render_task_runner_->PostTask(
-            FROM_HERE,
-            base::BindOnce(frame_dropped_cb_,
-                           media::VideoCaptureFrameDropReason::
-                               kRendererSinkFrameDelivererIsNotStarted));
+        PostCrossThreadTask(
+            *main_render_task_runner_, FROM_HERE,
+            CrossThreadBind(frame_dropped_cb_,
+                            media::VideoCaptureFrameDropReason::
+                                kRendererSinkFrameDelivererIsNotStarted));
       }
       return;
     }
@@ -132,7 +130,7 @@
 };
 
 MediaStreamVideoRendererSink::MediaStreamVideoRendererSink(
-    const blink::WebMediaStreamTrack& video_track,
+    const WebMediaStreamTrack& video_track,
     const RepaintCB& repaint_cb,
     scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> main_render_task_runner)
@@ -151,36 +149,39 @@
 
   frame_deliverer_.reset(new MediaStreamVideoRendererSink::FrameDeliverer(
       repaint_cb_,
-      base::BindRepeating(&blink::MediaStreamVideoSink::OnFrameDropped,
-                          weak_factory_.GetWeakPtr()),
+      ConvertToBaseCallback(CrossThreadBind(
+          &MediaStreamVideoSink::OnFrameDropped, weak_factory_.GetWeakPtr())),
       main_render_task_runner_));
-  io_task_runner_->PostTask(
-      FROM_HERE, base::BindOnce(&FrameDeliverer::Start,
-                                base::Unretained(frame_deliverer_.get())));
+  PostCrossThreadTask(
+      *io_task_runner_, FROM_HERE,
+      CrossThreadBindOnce(&FrameDeliverer::Start,
+                          WTF::CrossThreadUnretained(frame_deliverer_.get())));
 
-  blink::MediaStreamVideoSink::ConnectToTrack(
+  MediaStreamVideoSink::ConnectToTrack(
       video_track_,
       // This callback is run on IO thread. It is safe to use base::Unretained
       // here because |frame_receiver_| will be destroyed on IO thread after
       // sink is disconnected from track.
-      base::Bind(&FrameDeliverer::OnVideoFrame,
-                 base::Unretained(frame_deliverer_.get())),
+      ConvertToBaseCallback(WTF::CrossThreadBind(
+          &FrameDeliverer::OnVideoFrame,
+          WTF::CrossThreadUnretained(frame_deliverer_.get()))),
       // Local display video rendering is considered a secure link.
       true);
 
   if (video_track_.Source().GetReadyState() ==
-          blink::WebMediaStreamSource::kReadyStateEnded ||
+          WebMediaStreamSource::kReadyStateEnded ||
       !video_track_.IsEnabled()) {
-    io_task_runner_->PostTask(
-        FROM_HERE, base::BindOnce(&FrameDeliverer::RenderEndOfStream,
-                                  base::Unretained(frame_deliverer_.get())));
+    PostCrossThreadTask(*io_task_runner_, FROM_HERE,
+                        WTF::CrossThreadBind(&FrameDeliverer::RenderEndOfStream,
+                                             WTF::CrossThreadUnretained(
+                                                 frame_deliverer_.get())));
   }
 }
 
 void MediaStreamVideoRendererSink::Stop() {
   DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
 
-  blink::MediaStreamVideoSink::DisconnectFromTrack();
+  MediaStreamVideoSink::DisconnectFromTrack();
   if (frame_deliverer_)
     io_task_runner_->DeleteSoon(FROM_HERE, frame_deliverer_.release());
 }
@@ -190,9 +191,10 @@
   if (!frame_deliverer_)
     return;
 
-  io_task_runner_->PostTask(
-      FROM_HERE, base::BindOnce(&FrameDeliverer::Resume,
-                                base::Unretained(frame_deliverer_.get())));
+  PostCrossThreadTask(*io_task_runner_, FROM_HERE,
+                      WTF::CrossThreadBindOnce(
+                          &FrameDeliverer::Resume,
+                          WTF::CrossThreadUnretained(frame_deliverer_.get())));
 }
 
 void MediaStreamVideoRendererSink::Pause() {
@@ -200,19 +202,21 @@
   if (!frame_deliverer_)
     return;
 
-  io_task_runner_->PostTask(
-      FROM_HERE, base::BindOnce(&FrameDeliverer::Pause,
-                                base::Unretained(frame_deliverer_.get())));
+  PostCrossThreadTask(*io_task_runner_, FROM_HERE,
+                      WTF::CrossThreadBindOnce(
+                          &FrameDeliverer::Pause,
+                          WTF::CrossThreadUnretained(frame_deliverer_.get())));
 }
 
 void MediaStreamVideoRendererSink::OnReadyStateChanged(
-    blink::WebMediaStreamSource::ReadyState state) {
+    WebMediaStreamSource::ReadyState state) {
   DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
-  if (state == blink::WebMediaStreamSource::kReadyStateEnded &&
-      frame_deliverer_) {
-    io_task_runner_->PostTask(
-        FROM_HERE, base::BindOnce(&FrameDeliverer::RenderEndOfStream,
-                                  base::Unretained(frame_deliverer_.get())));
+  if (state == WebMediaStreamSource::kReadyStateEnded && frame_deliverer_) {
+    PostCrossThreadTask(
+        *io_task_runner_, FROM_HERE,
+        WTF::CrossThreadBindOnce(
+            &FrameDeliverer::RenderEndOfStream,
+            WTF::CrossThreadUnretained(frame_deliverer_.get())));
   }
 }
 
@@ -224,4 +228,4 @@
   return frame_deliverer_->state_;
 }
 
-}  // namespace content
+}  // namespace blink
diff --git a/content/renderer/media/stream/media_stream_video_renderer_sink_unittest.cc b/third_party/blink/renderer/modules/mediastream/media_stream_video_renderer_sink_test.cc
similarity index 73%
rename from content/renderer/media/stream/media_stream_video_renderer_sink_unittest.cc
rename to third_party/blink/renderer/modules/mediastream/media_stream_video_renderer_sink_test.cc
index e99f51f..b1729e51 100644
--- a/content/renderer/media/stream/media_stream_video_renderer_sink_unittest.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_video_renderer_sink_test.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/renderer/media/stream/media_stream_video_renderer_sink.h"
+#include "third_party/blink/public/web/modules/mediastream/media_stream_video_renderer_sink.h"
 
 #include <memory>
 #include <vector>
@@ -11,17 +11,17 @@
 #include "base/macros.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_task_environment.h"
-#include "content/child/child_process.h"
-#include "content/renderer/media/stream/mock_media_stream_registry.h"
-#include "content/renderer/media/stream/mock_media_stream_video_source.h"
 #include "media/base/video_frame.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
 #include "third_party/blink/public/platform/web_string.h"
 #include "third_party/blink/public/web/modules/mediastream/media_stream_video_track.h"
+#include "third_party/blink/public/web/modules/mediastream/mock_media_stream_registry.h"
+#include "third_party/blink/public/web/modules/mediastream/mock_media_stream_video_source.h"
 #include "third_party/blink/public/web/web_heap.h"
+#include "third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h"
 
 using ::testing::_;
 using ::testing::AtLeast;
@@ -29,25 +29,20 @@
 using ::testing::Lt;
 using ::testing::Mock;
 
-namespace content {
-
-ACTION_P(RunClosure, closure) {
-  closure.Run();
-}
+namespace blink {
 
 class MediaStreamVideoRendererSinkTest : public testing::Test {
  public:
   MediaStreamVideoRendererSinkTest()
-      : child_process_(new ChildProcess()),
-        mock_source_(new MockMediaStreamVideoSource()) {
-    blink_source_.Initialize(blink::WebString::FromASCII("dummy_source_id"),
-                             blink::WebMediaStreamSource::kTypeVideo,
-                             blink::WebString::FromASCII("dummy_source_name"),
+      : mock_source_(new MockMediaStreamVideoSource()) {
+    blink_source_.Initialize(WebString::FromASCII("dummy_source_id"),
+                             WebMediaStreamSource::kTypeVideo,
+                             WebString::FromASCII("dummy_source_name"),
                              false /* remote */);
     blink_source_.SetPlatformSource(base::WrapUnique(mock_source_));
-    blink_track_ = blink::MediaStreamVideoTrack::CreateVideoTrack(
-        mock_source_,
-        blink::WebPlatformMediaStreamSource::ConstraintsCallback(), true);
+    blink_track_ = MediaStreamVideoTrack::CreateVideoTrack(
+        mock_source_, WebPlatformMediaStreamSource::ConstraintsCallback(),
+        true);
     mock_source_->StartMockedSource();
     base::RunLoop().RunUntilIdle();
 
@@ -55,8 +50,8 @@
         blink_track_,
         base::Bind(&MediaStreamVideoRendererSinkTest::RepaintCallback,
                    base::Unretained(this)),
-        child_process_->io_task_runner(),
-        blink::scheduler::GetSingleThreadTaskRunnerForTesting());
+        Platform::Current()->GetIOTaskRunner(),
+        scheduler::GetSingleThreadTaskRunnerForTesting());
     base::RunLoop().RunUntilIdle();
 
     EXPECT_TRUE(IsInStoppedState());
@@ -66,7 +61,7 @@
     media_stream_video_renderer_sink_ = nullptr;
     blink_source_.Reset();
     blink_track_.Reset();
-    blink::WebHeap::CollectAllGarbageForTesting();
+    WebHeap::CollectAllGarbageForTesting();
 
     // Let the message loop run to finish destroying the pool.
     base::RunLoop().RunUntilIdle();
@@ -100,26 +95,22 @@
   scoped_refptr<MediaStreamVideoRendererSink> media_stream_video_renderer_sink_;
 
  protected:
-  // A ChildProcess is needed to fool the Tracks and Sources into believing they
-  // are on the right threads. A ScopedTaskEnvironment must be instantiated
-  // before ChildProcess to prevent it from leaking a ThreadPool.
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
-  const std::unique_ptr<ChildProcess> child_process_;
+  ScopedTestingPlatformSupport<IOTaskRunnerTestingPlatformSupport> platform_;
 
-  blink::WebMediaStreamTrack blink_track_;
+  WebMediaStreamTrack blink_track_;
 
  private:
   void RunIOUntilIdle() const {
     // |blink_track_| uses IO thread to send frames to sinks. Make sure that
     // tasks on IO thread are completed before moving on.
     base::RunLoop run_loop;
-    child_process_->io_task_runner()->PostTaskAndReply(
+    Platform::Current()->GetIOTaskRunner()->PostTaskAndReply(
         FROM_HERE, base::BindOnce([] {}), run_loop.QuitClosure());
     run_loop.Run();
     base::RunLoop().RunUntilIdle();
   }
 
-  blink::WebMediaStreamSource blink_source_;
+  WebMediaStreamSource blink_source_;
   MockMediaStreamVideoSource* mock_source_;
 
   DISALLOW_COPY_AND_ASSIGN(MediaStreamVideoRendererSinkTest);
@@ -165,8 +156,8 @@
         base::Bind(&MediaStreamVideoRendererSinkTransparencyTest::
                        VerifyTransparentFrame,
                    base::Unretained(this)),
-        child_process_->io_task_runner(),
-        blink::scheduler::GetSingleThreadTaskRunnerForTesting());
+        Platform::Current()->GetIOTaskRunner(),
+        scheduler::GetSingleThreadTaskRunnerForTesting());
   }
 
   void VerifyTransparentFrame(scoped_refptr<media::VideoFrame> frame) {
@@ -174,8 +165,7 @@
   }
 };
 
-TEST_F(MediaStreamVideoRendererSinkTransparencyTest,
-       SendTransparentFrame) {
+TEST_F(MediaStreamVideoRendererSinkTransparencyTest, SendTransparentFrame) {
   media_stream_video_renderer_sink_->Start();
 
   InSequence s;
@@ -190,4 +180,4 @@
   media_stream_video_renderer_sink_->Stop();
 }
 
-}  // namespace content
+}  // namespace blink
diff --git a/content/renderer/media/stream/mock_media_stream_registry.cc b/third_party/blink/renderer/modules/mediastream/mock_media_stream_registry.cc
similarity index 61%
rename from content/renderer/media/stream/mock_media_stream_registry.cc
rename to third_party/blink/renderer/modules/mediastream/mock_media_stream_registry.cc
index 4c1ce265..d8e0de92 100644
--- a/content/renderer/media/stream/mock_media_stream_registry.cc
+++ b/third_party/blink/renderer/modules/mediastream/mock_media_stream_registry.cc
@@ -2,12 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/renderer/media/stream/mock_media_stream_registry.h"
+#include "third_party/blink/public/web/modules/mediastream/mock_media_stream_registry.h"
 
 #include <memory>
 
 #include "base/strings/utf_string_conversions.h"
-#include "content/renderer/media/stream/mock_media_stream_video_source.h"
 #include "third_party/blink/public/platform/modules/mediastream/media_stream_audio_source.h"
 #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
 #include "third_party/blink/public/platform/web_media_stream_source.h"
@@ -15,29 +14,28 @@
 #include "third_party/blink/public/platform/web_string.h"
 #include "third_party/blink/public/platform/web_vector.h"
 #include "third_party/blink/public/web/modules/mediastream/media_stream_video_track.h"
+#include "third_party/blink/public/web/modules/mediastream/mock_media_stream_video_source.h"
 #include "third_party/blink/public/web/modules/mediastream/video_track_adapter_settings.h"
 
-namespace content {
+namespace blink {
 
 namespace {
 
 const char kTestStreamLabel[] = "stream_label";
 
-class MockCDQualityAudioSource : public blink::MediaStreamAudioSource {
+class MockCDQualityAudioSource : public MediaStreamAudioSource {
  public:
   MockCDQualityAudioSource()
-      : blink::MediaStreamAudioSource(
-            blink::scheduler::GetSingleThreadTaskRunnerForTesting(),
-            true) {
+      : MediaStreamAudioSource(scheduler::GetSingleThreadTaskRunnerForTesting(),
+                               true) {
     SetFormat(media::AudioParameters(
         media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
         media::CHANNEL_LAYOUT_STEREO,
         media::AudioParameters::kAudioCDSampleRate,
         media::AudioParameters::kAudioCDSampleRate / 100));
-    SetDevice(blink::MediaStreamDevice(
-        blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE,
-        "mock_audio_device_id", "Mock audio device",
-        media::AudioParameters::kAudioCDSampleRate,
+    SetDevice(MediaStreamDevice(
+        mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE, "mock_audio_device_id",
+        "Mock audio device", media::AudioParameters::kAudioCDSampleRate,
         media::CHANNEL_LAYOUT_STEREO,
         media::AudioParameters::kAudioCDSampleRate / 100));
   }
@@ -51,53 +49,52 @@
 MockMediaStreamRegistry::MockMediaStreamRegistry() {}
 
 void MockMediaStreamRegistry::Init() {
-  const blink::WebVector<blink::WebMediaStreamTrack> webkit_audio_tracks;
-  const blink::WebVector<blink::WebMediaStreamTrack> webkit_video_tracks;
-  const blink::WebString label(kTestStreamLabel);
+  const WebVector<WebMediaStreamTrack> webkit_audio_tracks;
+  const WebVector<WebMediaStreamTrack> webkit_video_tracks;
+  const WebString label(kTestStreamLabel);
   test_stream_.Initialize(label, webkit_audio_tracks, webkit_video_tracks);
 }
 
 void MockMediaStreamRegistry::AddVideoTrack(
     const std::string& track_id,
-    const blink::VideoTrackAdapterSettings& adapter_settings,
+    const VideoTrackAdapterSettings& adapter_settings,
     const base::Optional<bool>& noise_reduction,
     bool is_screencast,
     double min_frame_rate) {
-  blink::WebMediaStreamSource blink_source;
+  WebMediaStreamSource blink_source;
   blink_source.Initialize("mock video source id",
-                          blink::WebMediaStreamSource::kTypeVideo,
+                          WebMediaStreamSource::kTypeVideo,
                           "mock video source name", false /* remote */);
   MockMediaStreamVideoSource* native_source = new MockMediaStreamVideoSource();
   blink_source.SetPlatformSource(base::WrapUnique(native_source));
-  blink::WebMediaStreamTrack blink_track;
-  blink_track.Initialize(blink::WebString::FromUTF8(track_id), blink_source);
+  WebMediaStreamTrack blink_track;
+  blink_track.Initialize(WebString::FromUTF8(track_id), blink_source);
 
-  blink_track.SetPlatformTrack(std::make_unique<blink::MediaStreamVideoTrack>(
+  blink_track.SetPlatformTrack(std::make_unique<MediaStreamVideoTrack>(
       native_source, adapter_settings, noise_reduction, is_screencast,
-      min_frame_rate, blink::MediaStreamVideoSource::ConstraintsCallback(),
+      min_frame_rate, MediaStreamVideoSource::ConstraintsCallback(),
       true /* enabled */));
   test_stream_.AddTrack(blink_track);
 }
 
 void MockMediaStreamRegistry::AddVideoTrack(const std::string& track_id) {
-  AddVideoTrack(track_id, blink::VideoTrackAdapterSettings(),
-                base::Optional<bool>(), false /* is_screncast */,
-                0.0 /* min_frame_rate */);
+  AddVideoTrack(track_id, VideoTrackAdapterSettings(), base::Optional<bool>(),
+                false /* is_screncast */, 0.0 /* min_frame_rate */);
 }
 
 void MockMediaStreamRegistry::AddAudioTrack(const std::string& track_id) {
-  blink::WebMediaStreamSource blink_source;
+  WebMediaStreamSource blink_source;
   blink_source.Initialize("mock audio source id",
-                          blink::WebMediaStreamSource::kTypeAudio,
+                          WebMediaStreamSource::kTypeAudio,
                           "mock audio source name", false /* remote */);
-  blink::MediaStreamAudioSource* const source = new MockCDQualityAudioSource();
+  MediaStreamAudioSource* const source = new MockCDQualityAudioSource();
   blink_source.SetPlatformSource(base::WrapUnique(source));  // Takes ownership.
 
-  blink::WebMediaStreamTrack blink_track;
+  WebMediaStreamTrack blink_track;
   blink_track.Initialize(blink_source);
   CHECK(source->ConnectToTrack(blink_track));
 
   test_stream_.AddTrack(blink_track);
 }
 
-}  // namespace content
+}  // namespace blink
diff --git a/content/renderer/media/stream/mock_media_stream_video_source.cc b/third_party/blink/renderer/modules/mediastream/mock_media_stream_video_source.cc
similarity index 76%
rename from content/renderer/media/stream/mock_media_stream_video_source.cc
rename to third_party/blink/renderer/modules/mediastream/mock_media_stream_video_source.cc
index 6032421..a6a4a36 100644
--- a/content/renderer/media/stream/mock_media_stream_video_source.cc
+++ b/third_party/blink/renderer/modules/mediastream/mock_media_stream_video_source.cc
@@ -2,15 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/renderer/media/stream/mock_media_stream_video_source.h"
+#include "third_party/blink/public/web/modules/mediastream/mock_media_stream_video_source.h"
 
 #include "base/bind.h"
-#include "base/callback_helpers.h"
 #include "base/location.h"
 #include "base/single_thread_task_runner.h"
-#include "third_party/blink/public/mojom/mediastream/media_stream.mojom-shared.h"
+#include "third_party/blink/public/mojom/mediastream/media_stream.mojom-blink.h"
+#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
+#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
 
-namespace content {
+namespace blink {
 
 MockMediaStreamVideoSource::MockMediaStreamVideoSource()
     : MockMediaStreamVideoSource(false) {}
@@ -38,14 +39,14 @@
 void MockMediaStreamVideoSource::StartMockedSource() {
   DCHECK(attempted_to_start_);
   attempted_to_start_ = false;
-  OnStartDone(blink::mojom::MediaStreamRequestResult::OK);
+  OnStartDone(mojom::blink::MediaStreamRequestResult::OK);
 }
 
 void MockMediaStreamVideoSource::FailToStartMockedSource() {
   DCHECK(attempted_to_start_);
   attempted_to_start_ = false;
   OnStartDone(
-      blink::mojom::MediaStreamRequestResult::TRACK_START_FAILURE_VIDEO);
+      mojom::blink::MediaStreamRequestResult::TRACK_START_FAILURE_VIDEO);
 }
 
 void MockMediaStreamVideoSource::RequestRefreshFrame() {
@@ -54,8 +55,10 @@
     const scoped_refptr<media::VideoFrame> frame =
         media::VideoFrame::CreateColorFrame(format_.frame_size, 0, 0, 0,
                                             base::TimeDelta());
-    io_task_runner()->PostTask(
-        FROM_HERE, base::BindOnce(frame_callback_, frame, base::TimeTicks()));
+    // TODO(crbug.com/964947): Remove the rebind of |frame_callback_|.
+    PostCrossThreadTask(
+        *io_task_runner(), FROM_HERE,
+        CrossThreadBind(frame_callback_, frame, base::TimeTicks()));
   }
 }
 
@@ -64,19 +67,18 @@
 }
 
 void MockMediaStreamVideoSource::DoChangeSource(
-    const blink::MediaStreamDevice& new_device) {
+    const MediaStreamDevice& new_device) {
   ChangeSourceImpl(new_device);
 }
 
 void MockMediaStreamVideoSource::StartSourceImpl(
-    const blink::VideoCaptureDeliverFrameCB& frame_callback) {
+    const VideoCaptureDeliverFrameCB& frame_callback) {
   DCHECK(frame_callback_.is_null());
   attempted_to_start_ = true;
   frame_callback_ = frame_callback;
 }
 
-void MockMediaStreamVideoSource::StopSourceImpl() {
-}
+void MockMediaStreamVideoSource::StopSourceImpl() {}
 
 base::Optional<media::VideoCaptureFormat>
 MockMediaStreamVideoSource::GetCurrentFormat() const {
@@ -95,9 +97,10 @@
     scoped_refptr<media::VideoFrame> frame) {
   DCHECK(!is_stopped_for_restart_);
   DCHECK(!frame_callback_.is_null());
-  io_task_runner()->PostTask(
-      FROM_HERE,
-      base::BindOnce(frame_callback_, std::move(frame), base::TimeTicks()));
+  // TODO(crbug.com/964947): Remove the rebind of |frame_callback_|.
+  PostCrossThreadTask(
+      *io_task_runner(), FROM_HERE,
+      CrossThreadBind(frame_callback_, std::move(frame), base::TimeTicks()));
 }
 
 void MockMediaStreamVideoSource::StopSourceForRestartImpl() {
@@ -118,4 +121,4 @@
   OnRestartDone(true);
 }
 
-}  // namespace content
+}  // namespace blink
diff --git a/third_party/blink/renderer/modules/payments/abort_test.cc b/third_party/blink/renderer/modules/payments/abort_test.cc
index b7af810..744bf20 100644
--- a/third_party/blink/renderer/modules/payments/abort_test.cc
+++ b/third_party/blink/renderer/modules/payments/abort_test.cc
@@ -15,9 +15,8 @@
 // If request.abort() is called without calling request.show() first, then
 // abort() should reject with exception.
 TEST(AbortTest, CannotAbortBeforeShow) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), scope.GetExceptionState());
@@ -29,9 +28,8 @@
 // If request.abort() is called again before the previous abort() resolved, then
 // the second abort() should reject with exception.
 TEST(AbortTest, CannotAbortTwiceConcurrently) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), scope.GetExceptionState());
@@ -45,9 +43,8 @@
 // If request.abort() is called after calling request.show(), then abort()
 // should not reject with exception.
 TEST(AbortTest, CanAbortAfterShow) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), scope.GetExceptionState());
@@ -60,9 +57,8 @@
 // If the browser is unable to abort the payment, then the request.abort()
 // promise should be rejected.
 TEST(AbortTest, FailedAbortShouldRejectAbortPromise) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), scope.GetExceptionState());
@@ -78,9 +74,8 @@
 // After the browser is unable to abort the payment once, the second abort()
 // call should not be rejected, as it's not a duplicate request anymore.
 TEST(AbortTest, CanAbortAgainAfterFirstAbortRejected) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), scope.GetExceptionState());
@@ -96,9 +91,8 @@
 // If the browser successfully aborts the payment, then the request.show()
 // promise should be rejected, and request.abort() promise should be resolved.
 TEST(AbortTest, SuccessfulAbortShouldRejectShowPromiseAndResolveAbortPromise) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), scope.GetExceptionState());
diff --git a/third_party/blink/renderer/modules/payments/can_make_payment_test.cc b/third_party/blink/renderer/modules/payments/can_make_payment_test.cc
index 6b19d75..609b744 100644
--- a/third_party/blink/renderer/modules/payments/can_make_payment_test.cc
+++ b/third_party/blink/renderer/modules/payments/can_make_payment_test.cc
@@ -27,9 +27,8 @@
 };
 
 TEST_F(HasEnrolledInstrumentTest, RejectPromiseOnUserCancel) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), scope.GetExceptionState());
@@ -42,9 +41,8 @@
 }
 
 TEST_F(HasEnrolledInstrumentTest, RejectPromiseOnUnknownError) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), scope.GetExceptionState());
@@ -57,9 +55,8 @@
 }
 
 TEST_F(HasEnrolledInstrumentTest, RejectDuplicateRequest) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), scope.GetExceptionState());
@@ -69,9 +66,8 @@
 }
 
 TEST_F(HasEnrolledInstrumentTest, RejectQueryQuotaExceeded) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), scope.GetExceptionState());
@@ -84,9 +80,8 @@
 }
 
 TEST_F(HasEnrolledInstrumentTest, ReturnHasNoEnrolledInstrument) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), scope.GetExceptionState());
@@ -102,9 +97,8 @@
 }
 
 TEST_F(HasEnrolledInstrumentTest, ReturnHasEnrolledInstrument) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), scope.GetExceptionState());
@@ -134,9 +128,8 @@
 };
 
 TEST_P(CanMakePaymentTest, RejectPromiseOnUserCancel) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), scope.GetExceptionState());
@@ -149,9 +142,9 @@
 }
 
 TEST_P(CanMakePaymentTest, RejectPromiseOnUnknownError) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
+
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), scope.GetExceptionState());
@@ -164,9 +157,8 @@
 }
 
 TEST_P(CanMakePaymentTest, RejectDuplicateRequest) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), scope.GetExceptionState());
@@ -177,9 +169,8 @@
 }
 
 TEST_P(CanMakePaymentTest, RejectQueryQuotaExceeded) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), scope.GetExceptionState());
@@ -192,9 +183,8 @@
 }
 
 TEST_P(CanMakePaymentTest, ReturnCannotMakePayment) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), scope.GetExceptionState());
@@ -210,9 +200,8 @@
 }
 
 TEST_P(CanMakePaymentTest, ReturnCanMakePayment) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), scope.GetExceptionState());
diff --git a/third_party/blink/renderer/modules/payments/complete_test.cc b/third_party/blink/renderer/modules/payments/complete_test.cc
index 052e14e..002181f7 100644
--- a/third_party/blink/renderer/modules/payments/complete_test.cc
+++ b/third_party/blink/renderer/modules/payments/complete_test.cc
@@ -13,9 +13,8 @@
 namespace {
 
 TEST(CompleteTest, CannotCallCompleteTwice) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), scope.GetExceptionState());
@@ -33,9 +32,8 @@
 }
 
 TEST(CompleteTest, ResolveCompletePromiseOnUnknownError) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), scope.GetExceptionState());
@@ -54,9 +52,8 @@
 }
 
 TEST(CompleteTest, ResolveCompletePromiseOnUserClosingUI) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), scope.GetExceptionState());
@@ -77,9 +74,8 @@
 // If user cancels the transaction during processing, the complete() promise
 // should be rejected.
 TEST(CompleteTest, RejectCompletePromiseAfterError) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), scope.GetExceptionState());
@@ -97,9 +93,8 @@
 }
 
 TEST(CompleteTest, ResolvePromiseOnComplete) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), scope.GetExceptionState());
@@ -118,9 +113,8 @@
 }
 
 TEST(CompleteTest, RejectCompletePromiseOnUpdateDetailsFailure) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), scope.GetExceptionState());
@@ -143,9 +137,8 @@
 }
 
 TEST(CompleteTest, RejectCompletePromiseAfterTimeout) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), scope.GetExceptionState());
diff --git a/third_party/blink/renderer/modules/payments/on_payment_response_test.cc b/third_party/blink/renderer/modules/payments/on_payment_response_test.cc
index 5ea4e91..4876a31 100644
--- a/third_party/blink/renderer/modules/payments/on_payment_response_test.cc
+++ b/third_party/blink/renderer/modules/payments/on_payment_response_test.cc
@@ -19,9 +19,8 @@
 // If the merchant requests shipping information, but the browser does not
 // provide the shipping option, reject the show() promise.
 TEST(OnPaymentResponseTest, RejectMissingShippingOption) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentOptions* options = PaymentOptions::Create();
   options->setRequestShipping(true);
   PaymentRequest* request = PaymentRequest::Create(
@@ -43,9 +42,8 @@
 // If the merchant requests shipping information, but the browser does not
 // provide a shipping address, reject the show() promise.
 TEST(OnPaymentResponseTest, RejectMissingAddress) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentOptions* options = PaymentOptions::Create();
   options->setRequestShipping(true);
   PaymentRequest* request = PaymentRequest::Create(
@@ -66,9 +64,8 @@
 // If the merchant requests a payer name, but the browser does not provide it,
 // reject the show() promise.
 TEST(OnPaymentResponseTest, RejectMissingName) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentOptions* options = PaymentOptions::Create();
   options->setRequestPayerName(true);
   PaymentRequest* request = PaymentRequest::Create(
@@ -88,9 +85,8 @@
 // If the merchant requests an email address, but the browser does not provide
 // it, reject the show() promise.
 TEST(OnPaymentResponseTest, RejectMissingEmail) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentOptions* options = PaymentOptions::Create();
   options->setRequestPayerEmail(true);
   PaymentRequest* request = PaymentRequest::Create(
@@ -110,9 +106,8 @@
 // If the merchant requests a phone number, but the browser does not provide it,
 // reject the show() promise.
 TEST(OnPaymentResponseTest, RejectMissingPhone) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentOptions* options = PaymentOptions::Create();
   options->setRequestPayerPhone(true);
   PaymentRequest* request = PaymentRequest::Create(
@@ -132,9 +127,8 @@
 // If the merchant requests shipping information, but the browser provides an
 // empty string for shipping option, reject the show() promise.
 TEST(OnPaymentResponseTest, RejectEmptyShippingOption) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentOptions* options = PaymentOptions::Create();
   options->setRequestShipping(true);
   PaymentRequest* request = PaymentRequest::Create(
@@ -157,9 +151,8 @@
 // If the merchant requests shipping information, but the browser provides an
 // empty shipping address, reject the show() promise.
 TEST(OnPaymentResponseTest, RejectEmptyAddress) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentOptions* options = PaymentOptions::Create();
   options->setRequestShipping(true);
   PaymentRequest* request = PaymentRequest::Create(
@@ -181,9 +174,8 @@
 // If the merchant requests a payer name, but the browser provides an empty
 // string for name, reject the show() promise.
 TEST(OnPaymentResponseTest, RejectEmptyName) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentOptions* options = PaymentOptions::Create();
   options->setRequestPayerName(true);
   PaymentRequest* request = PaymentRequest::Create(
@@ -204,9 +196,8 @@
 // If the merchant requests an email, but the browser provides an empty string
 // for email, reject the show() promise.
 TEST(OnPaymentResponseTest, RejectEmptyEmail) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentOptions* options = PaymentOptions::Create();
   options->setRequestPayerEmail(true);
   PaymentRequest* request = PaymentRequest::Create(
@@ -227,9 +218,8 @@
 // If the merchant requests a phone number, but the browser provides an empty
 // string for the phone number, reject the show() promise.
 TEST(OnPaymentResponseTest, RejectEmptyPhone) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentOptions* options = PaymentOptions::Create();
   options->setRequestPayerPhone(true);
   PaymentRequest* request = PaymentRequest::Create(
@@ -250,9 +240,8 @@
 // If the merchant does not request shipping information, but the browser
 // provides a shipping address, reject the show() promise.
 TEST(OnPaymentResponseTest, RejectNotRequestedAddress) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentOptions* options = PaymentOptions::Create();
   options->setRequestShipping(false);
   PaymentRequest* request = PaymentRequest::Create(
@@ -274,9 +263,8 @@
 // If the merchant does not request shipping information, but the browser
 // provides a shipping option, reject the show() promise.
 TEST(OnPaymentResponseTest, RejectNotRequestedShippingOption) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentOptions* options = PaymentOptions::Create();
   options->setRequestShipping(false);
   PaymentRequest* request = PaymentRequest::Create(
@@ -297,9 +285,8 @@
 // If the merchant does not request a payer name, but the browser provides it,
 // reject the show() promise.
 TEST(OnPaymentResponseTest, RejectNotRequestedName) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentOptions* options = PaymentOptions::Create();
   options->setRequestPayerName(false);
   PaymentRequest* request = PaymentRequest::Create(
@@ -320,9 +307,8 @@
 // If the merchant does not request an email, but the browser provides it,
 // reject the show() promise.
 TEST(OnPaymentResponseTest, RejectNotRequestedEmail) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentOptions* options = PaymentOptions::Create();
   options->setRequestPayerEmail(false);
   PaymentRequest* request = PaymentRequest::Create(
@@ -343,9 +329,8 @@
 // If the merchant does not request a phone number, but the browser provides it,
 // reject the show() promise.
 TEST(OnPaymentResponseTest, RejectNotRequestedPhone) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentOptions* options = PaymentOptions::Create();
   options->setRequestPayerPhone(false);
   PaymentRequest* request = PaymentRequest::Create(
@@ -366,9 +351,8 @@
 // If the merchant requests shipping information, but the browser provides an
 // invalid shipping address, reject the show() promise.
 TEST(OnPaymentResponseTest, RejectInvalidAddress) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentOptions* options = PaymentOptions::Create();
   options->setRequestShipping(true);
   PaymentRequest* request = PaymentRequest::Create(
@@ -415,9 +399,8 @@
 // If the merchant requests shipping information, the resolved show() promise
 // should contain a shipping option and an address.
 TEST(OnPaymentResponseTest, CanRequestShippingInformation) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentOptions* options = PaymentOptions::Create();
   options->setRequestShipping(true);
   PaymentRequest* request = PaymentRequest::Create(
@@ -446,9 +429,8 @@
 // If the merchant requests a payer name, the resolved show() promise should
 // contain a payer name.
 TEST(OnPaymentResponseTest, CanRequestName) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentOptions* options = PaymentOptions::Create();
   options->setRequestPayerName(true);
   PaymentRequest* request = PaymentRequest::Create(
@@ -476,9 +458,8 @@
 // If the merchant requests an email address, the resolved show() promise should
 // contain an email address.
 TEST(OnPaymentResponseTest, CanRequestEmail) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentOptions* options = PaymentOptions::Create();
   options->setRequestPayerEmail(true);
   PaymentRequest* request = PaymentRequest::Create(
@@ -505,9 +486,8 @@
 // If the merchant requests a phone number, the resolved show() promise should
 // contain a phone number.
 TEST(OnPaymentResponseTest, CanRequestPhone) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentOptions* options = PaymentOptions::Create();
   options->setRequestPayerPhone(true);
   PaymentRequest* request = PaymentRequest::Create(
@@ -535,9 +515,8 @@
 // If the merchant does not request shipping information, the resolved show()
 // promise should contain null shipping option and address.
 TEST(OnPaymentResponseTest, ShippingInformationNotRequired) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentOptions* options = PaymentOptions::Create();
   options->setRequestShipping(false);
   PaymentRequest* request = PaymentRequest::Create(
@@ -562,9 +541,8 @@
 // If the merchant does not request a phone number, the resolved show() promise
 // should contain null phone number.
 TEST(OnPaymentResponseTest, PhoneNotRequred) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentOptions* options = PaymentOptions::Create();
   options->setRequestPayerPhone(false);
   PaymentRequest* request = PaymentRequest::Create(
@@ -591,9 +569,8 @@
 // If the merchant does not request a payer name, the resolved show() promise
 // should contain null payer name.
 TEST(OnPaymentResponseTest, NameNotRequired) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentOptions* options = PaymentOptions::Create();
   options->setRequestPayerName(false);
   PaymentRequest* request = PaymentRequest::Create(
@@ -620,9 +597,8 @@
 // If the merchant does not request an email address, the resolved show()
 // promise should contain null email address.
 TEST(OnPaymentResponseTest, EmailNotRequired) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentOptions* options = PaymentOptions::Create();
   options->setRequestPayerEmail(false);
   PaymentRequest* request = PaymentRequest::Create(
diff --git a/third_party/blink/renderer/modules/payments/payment_request_details_test.cc b/third_party/blink/renderer/modules/payments/payment_request_details_test.cc
index 0697b9c..772ad9dc 100644
--- a/third_party/blink/renderer/modules/payments/payment_request_details_test.cc
+++ b/third_party/blink/renderer/modules/payments/payment_request_details_test.cc
@@ -125,11 +125,7 @@
     : public testing::TestWithParam<DetailsTestCase> {};
 
 TEST_P(PaymentRequestDetailsTest, ValidatesDetails) {
-  V8TestingScope scope;
-  scope.GetDocument().SetSecurityOrigin(
-      SecurityOrigin::Create(KURL("https://www.example.com/")));
-  scope.GetDocument().SetSecureContextStateForTesting(
-      SecureContextState::kSecure);
+  PaymentRequestV8TestingScope scope;
   PaymentOptions* options = PaymentOptions::Create();
   options->setRequestShipping(true);
   PaymentRequest::Create(
diff --git a/third_party/blink/renderer/modules/payments/payment_request_test.cc b/third_party/blink/renderer/modules/payments/payment_request_test.cc
index 8f6e899b502..6080022b 100644
--- a/third_party/blink/renderer/modules/payments/payment_request_test.cc
+++ b/third_party/blink/renderer/modules/payments/payment_request_test.cc
@@ -15,8 +15,7 @@
 namespace {
 
 TEST(PaymentRequestTest, NoExceptionWithValidData) {
-  V8TestingScope scope;
-  MakePaymentRequestOriginSecure(scope.GetDocument());
+  PaymentRequestV8TestingScope scope;
   PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), scope.GetExceptionState());
@@ -25,8 +24,7 @@
 }
 
 TEST(PaymentRequestTest, SupportedMethodListRequired) {
-  V8TestingScope scope;
-  MakePaymentRequestOriginSecure(scope.GetDocument());
+  PaymentRequestV8TestingScope scope;
   PaymentRequest::Create(
       scope.GetExecutionContext(), HeapVector<Member<PaymentMethodData>>(),
       BuildPaymentDetailsInitForTest(), scope.GetExceptionState());
@@ -37,8 +35,7 @@
 }
 
 TEST(PaymentRequestTest, NullShippingOptionWhenNoOptionsAvailable) {
-  V8TestingScope scope;
-  MakePaymentRequestOriginSecure(scope.GetDocument());
+  PaymentRequestV8TestingScope scope;
   PaymentDetailsInit* details = PaymentDetailsInit::Create();
   details->setTotal(BuildPaymentItemForTest());
   PaymentOptions* options = PaymentOptions::Create();
@@ -52,8 +49,7 @@
 }
 
 TEST(PaymentRequestTest, NullShippingOptionWhenMultipleOptionsAvailable) {
-  V8TestingScope scope;
-  MakePaymentRequestOriginSecure(scope.GetDocument());
+  PaymentRequestV8TestingScope scope;
   PaymentDetailsInit* details = PaymentDetailsInit::Create();
   details->setTotal(BuildPaymentItemForTest());
   HeapVector<Member<PaymentShippingOption>> shipping_options;
@@ -71,8 +67,7 @@
 }
 
 TEST(PaymentRequestTest, DontSelectSingleAvailableShippingOptionByDefault) {
-  V8TestingScope scope;
-  MakePaymentRequestOriginSecure(scope.GetDocument());
+  PaymentRequestV8TestingScope scope;
   PaymentDetailsInit* details = PaymentDetailsInit::Create();
   details->setTotal(BuildPaymentItemForTest());
   details->setShippingOptions(HeapVector<Member<PaymentShippingOption>>(
@@ -88,8 +83,7 @@
 
 TEST(PaymentRequestTest,
      DontSelectSingleAvailableShippingOptionWhenShippingNotRequested) {
-  V8TestingScope scope;
-  MakePaymentRequestOriginSecure(scope.GetDocument());
+  PaymentRequestV8TestingScope scope;
   PaymentDetailsInit* details = PaymentDetailsInit::Create();
   details->setTotal(BuildPaymentItemForTest());
   details->setShippingOptions(HeapVector<Member<PaymentShippingOption>>(
@@ -106,8 +100,7 @@
 
 TEST(PaymentRequestTest,
      DontSelectSingleUnselectedShippingOptionWhenShippingRequested) {
-  V8TestingScope scope;
-  MakePaymentRequestOriginSecure(scope.GetDocument());
+  PaymentRequestV8TestingScope scope;
   PaymentDetailsInit* details = PaymentDetailsInit::Create();
   details->setTotal(BuildPaymentItemForTest());
   details->setShippingOptions(HeapVector<Member<PaymentShippingOption>>(
@@ -124,8 +117,7 @@
 
 TEST(PaymentRequestTest,
      SelectSingleSelectedShippingOptionWhenShippingRequested) {
-  V8TestingScope scope;
-  MakePaymentRequestOriginSecure(scope.GetDocument());
+  PaymentRequestV8TestingScope scope;
   PaymentDetailsInit* details = PaymentDetailsInit::Create();
   details->setTotal(BuildPaymentItemForTest());
   HeapVector<Member<PaymentShippingOption>> shipping_options(
@@ -145,8 +137,7 @@
 
 TEST(PaymentRequestTest,
      SelectOnlySelectedShippingOptionWhenShippingRequested) {
-  V8TestingScope scope;
-  MakePaymentRequestOriginSecure(scope.GetDocument());
+  PaymentRequestV8TestingScope scope;
   PaymentDetailsInit* details = PaymentDetailsInit::Create();
   details->setTotal(BuildPaymentItemForTest());
   HeapVector<Member<PaymentShippingOption>> shipping_options(2);
@@ -168,8 +159,7 @@
 
 TEST(PaymentRequestTest,
      SelectLastSelectedShippingOptionWhenShippingRequested) {
-  V8TestingScope scope;
-  MakePaymentRequestOriginSecure(scope.GetDocument());
+  PaymentRequestV8TestingScope scope;
   PaymentDetailsInit* details = PaymentDetailsInit::Create();
   details->setTotal(BuildPaymentItemForTest());
   HeapVector<Member<PaymentShippingOption>> shipping_options(2);
@@ -191,8 +181,7 @@
 }
 
 TEST(PaymentRequestTest, NullShippingTypeWhenRequestShippingIsFalse) {
-  V8TestingScope scope;
-  MakePaymentRequestOriginSecure(scope.GetDocument());
+  PaymentRequestV8TestingScope scope;
   PaymentDetailsInit* details = PaymentDetailsInit::Create();
   details->setTotal(BuildPaymentItemForTest());
   PaymentOptions* options = PaymentOptions::Create();
@@ -207,8 +196,7 @@
 
 TEST(PaymentRequestTest,
      DefaultShippingTypeWhenRequestShippingIsTrueWithNoSpecificType) {
-  V8TestingScope scope;
-  MakePaymentRequestOriginSecure(scope.GetDocument());
+  PaymentRequestV8TestingScope scope;
   PaymentDetailsInit* details = PaymentDetailsInit::Create();
   details->setTotal(BuildPaymentItemForTest());
   PaymentOptions* options = PaymentOptions::Create();
@@ -222,8 +210,7 @@
 }
 
 TEST(PaymentRequestTest, DeliveryShippingTypeWhenShippingTypeIsDelivery) {
-  V8TestingScope scope;
-  MakePaymentRequestOriginSecure(scope.GetDocument());
+  PaymentRequestV8TestingScope scope;
   PaymentDetailsInit* details = PaymentDetailsInit::Create();
   details->setTotal(BuildPaymentItemForTest());
   PaymentOptions* options = PaymentOptions::Create();
@@ -238,8 +225,7 @@
 }
 
 TEST(PaymentRequestTest, PickupShippingTypeWhenShippingTypeIsPickup) {
-  V8TestingScope scope;
-  MakePaymentRequestOriginSecure(scope.GetDocument());
+  PaymentRequestV8TestingScope scope;
   PaymentDetailsInit* details = PaymentDetailsInit::Create();
   details->setTotal(BuildPaymentItemForTest());
   PaymentOptions* options = PaymentOptions::Create();
@@ -254,9 +240,8 @@
 }
 
 TEST(PaymentRequestTest, RejectShowPromiseOnInvalidShippingAddress) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), scope.GetExceptionState());
@@ -270,9 +255,8 @@
 }
 
 TEST(PaymentRequestTest, OnShippingOptionChange) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), scope.GetExceptionState());
@@ -286,9 +270,8 @@
 }
 
 TEST(PaymentRequestTest, CannotCallShowTwice) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), scope.GetExceptionState());
@@ -300,9 +283,8 @@
 }
 
 TEST(PaymentRequestTest, CannotShowAfterAborted) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), scope.GetExceptionState());
@@ -317,9 +299,8 @@
 }
 
 TEST(PaymentRequestTest, RejectShowPromiseOnErrorPaymentMethodNotSupported) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), scope.GetExceptionState());
@@ -338,9 +319,8 @@
 }
 
 TEST(PaymentRequestTest, RejectShowPromiseOnErrorCancelled) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), scope.GetExceptionState());
@@ -358,9 +338,8 @@
 }
 
 TEST(PaymentRequestTest, RejectShowPromiseOnUpdateDetailsFailure) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), scope.GetExceptionState());
@@ -379,9 +358,8 @@
 }
 
 TEST(PaymentRequestTest, IgnoreUpdatePaymentDetailsAfterShowPromiseResolved) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), scope.GetExceptionState());
@@ -396,9 +374,8 @@
 }
 
 TEST(PaymentRequestTest, RejectShowPromiseOnNonPaymentDetailsUpdate) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), scope.GetExceptionState());
@@ -414,9 +391,8 @@
 }
 
 TEST(PaymentRequestTest, RejectShowPromiseOnInvalidPaymentDetailsUpdate) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), scope.GetExceptionState());
@@ -438,9 +414,8 @@
 
 TEST(PaymentRequestTest,
      ClearShippingOptionOnPaymentDetailsUpdateWithoutShippingOptions) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentDetailsInit* details = PaymentDetailsInit::Create();
   details->setTotal(BuildPaymentItemForTest());
   PaymentOptions* options = PaymentOptions::Create();
@@ -488,9 +463,8 @@
 TEST(
     PaymentRequestTest,
     ClearShippingOptionOnPaymentDetailsUpdateWithMultipleUnselectedShippingOptions) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentOptions* options = PaymentOptions::Create();
   options->setRequestShipping(true);
   PaymentRequest* request = PaymentRequest::Create(
@@ -518,9 +492,8 @@
 }
 
 TEST(PaymentRequestTest, UseTheSelectedShippingOptionFromPaymentDetailsUpdate) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentOptions* options = PaymentOptions::Create();
   options->setRequestShipping(true);
   PaymentRequest* request = PaymentRequest::Create(
@@ -550,9 +523,8 @@
 }
 
 TEST(PaymentRequestTest, NoExceptionWithErrorMessageInUpdate) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), scope.GetExceptionState());
@@ -576,9 +548,8 @@
 
 TEST(PaymentRequestTest,
      ShouldResolveWithExceptionIfIDsOfShippingOptionsAreDuplicated) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentDetailsInit* details = PaymentDetailsInit::Create();
   details->setTotal(BuildPaymentItemForTest());
   HeapVector<Member<PaymentShippingOption>> shipping_options(2);
@@ -597,8 +568,7 @@
 }
 
 TEST(PaymentRequestTest, DetailsIdIsSet) {
-  V8TestingScope scope;
-  MakePaymentRequestOriginSecure(scope.GetDocument());
+  PaymentRequestV8TestingScope scope;
   PaymentDetailsInit* details = PaymentDetailsInit::Create();
   details->setTotal(BuildPaymentItemForTest());
   details->setId("my_payment_id");
diff --git a/third_party/blink/renderer/modules/payments/payment_request_update_event_test.cc b/third_party/blink/renderer/modules/payments/payment_request_update_event_test.cc
index ca4d769..e52fcb3 100644
--- a/third_party/blink/renderer/modules/payments/payment_request_update_event_test.cc
+++ b/third_party/blink/renderer/modules/payments/payment_request_update_event_test.cc
@@ -135,9 +135,8 @@
 }
 
 TEST(PaymentRequestUpdateEventTest, AddressChangeUpdateWithTimeout) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), scope.GetExceptionState());
@@ -173,9 +172,8 @@
 }
 
 TEST(PaymentRequestUpdateEventTest, OptionChangeUpdateWithTimeout) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), scope.GetExceptionState());
@@ -211,9 +209,8 @@
 }
 
 TEST(PaymentRequestUpdateEventTest, AddressChangePromiseTimeout) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), scope.GetExceptionState());
@@ -246,9 +243,8 @@
 }
 
 TEST(PaymentRequestUpdateEventTest, OptionChangePromiseTimeout) {
-  V8TestingScope scope;
+  PaymentRequestV8TestingScope scope;
   PaymentRequestMockFunctionScope funcs(scope.GetScriptState());
-  MakePaymentRequestOriginSecure(scope.GetDocument());
   PaymentRequest* request = PaymentRequest::Create(
       scope.GetExecutionContext(), BuildPaymentMethodDataForTest(),
       BuildPaymentDetailsInitForTest(), scope.GetExceptionState());
diff --git a/third_party/blink/renderer/modules/payments/payment_test_helper.cc b/third_party/blink/renderer/modules/payments/payment_test_helper.cc
index e4126f5a..6a0a28e 100644
--- a/third_party/blink/renderer/modules/payments/payment_test_helper.cc
+++ b/third_party/blink/renderer/modules/payments/payment_test_helper.cc
@@ -212,10 +212,9 @@
   return result;
 }
 
-void MakePaymentRequestOriginSecure(Document& document) {
-  document.SetSecurityOrigin(
-      SecurityOrigin::Create(KURL("https://www.example.com/")));
-  document.SetSecureContextStateForTesting(SecureContextState::kSecure);
+PaymentRequestV8TestingScope::PaymentRequestV8TestingScope()
+    : V8TestingScope(KURL("https://www.example.com/")) {
+  GetDocument().SetSecureContextStateForTesting(SecureContextState::kSecure);
 }
 
 PaymentRequestMockFunctionScope::PaymentRequestMockFunctionScope(
diff --git a/third_party/blink/renderer/modules/payments/payment_test_helper.h b/third_party/blink/renderer/modules/payments/payment_test_helper.h
index 1042389..dad9726 100644
--- a/third_party/blink/renderer/modules/payments/payment_test_helper.h
+++ b/third_party/blink/renderer/modules/payments/payment_test_helper.h
@@ -21,10 +21,10 @@
 
 namespace blink {
 
-class Document;
 class PaymentMethodData;
 class ScriptState;
 class ScriptValue;
+class V8TestingScope;
 
 enum PaymentTestDetailToChange {
   kPaymentTestDetailNone,
@@ -87,7 +87,12 @@
 
 payments::mojom::blink::PaymentAddressPtr BuildPaymentAddressForTest();
 
-void MakePaymentRequestOriginSecure(Document&);
+class PaymentRequestV8TestingScope : public V8TestingScope {
+  STACK_ALLOCATED();
+
+ public:
+  PaymentRequestV8TestingScope();
+};
 
 class PaymentRequestMockFunctionScope {
   STACK_ALLOCATED();
diff --git a/third_party/blink/renderer/modules/presentation/presentation_request_test.cc b/third_party/blink/renderer/modules/presentation/presentation_request_test.cc
index 0623740..1f1ca04 100644
--- a/third_party/blink/renderer/modules/presentation/presentation_request_test.cc
+++ b/third_party/blink/renderer/modules/presentation/presentation_request_test.cc
@@ -58,9 +58,7 @@
 }
 
 TEST(PresentationRequestTest, TestMixedContentNotCheckedForNonHttpFamily) {
-  V8TestingScope scope;
-  scope.GetExecutionContext()->GetSecurityContext().SetSecurityOrigin(
-      SecurityOrigin::CreateFromString("https://example.test"));
+  V8TestingScope scope(KURL("https://example.test"));
 
   PresentationRequest* request = PresentationRequest::Create(
       scope.GetExecutionContext(), "cast://deadbeef?param=foo",
@@ -74,9 +72,7 @@
 }
 
 TEST(PresentationRequestTest, TestSingleUrlConstructorMixedContent) {
-  V8TestingScope scope;
-  scope.GetExecutionContext()->GetSecurityContext().SetSecurityOrigin(
-      SecurityOrigin::CreateFromString("https://example.test"));
+  V8TestingScope scope(KURL("https://example.test"));
 
   PresentationRequest::Create(scope.GetExecutionContext(), "http://example.com",
                               scope.GetExceptionState());
@@ -86,9 +82,7 @@
 }
 
 TEST(PresentationRequestTest, TestMultipleUrlConstructorMixedContent) {
-  V8TestingScope scope;
-  scope.GetExecutionContext()->GetSecurityContext().SetSecurityOrigin(
-      SecurityOrigin::CreateFromString("https://example.test"));
+  V8TestingScope scope(KURL("https://example.test"));
 
   WTF::Vector<String> urls;
   urls.push_back("http://example.com");
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_container_test.cc b/third_party/blink/renderer/modules/service_worker/service_worker_container_test.cc
index 6c04a4a..ca07a97 100644
--- a/third_party/blink/renderer/modules/service_worker/service_worker_container_test.cc
+++ b/third_party/blink/renderer/modules/service_worker/service_worker_container_test.cc
@@ -188,11 +188,7 @@
   }
 
   void SetPageURL(const String& url) {
-    // For URL completion.
-    GetDocument().SetURL(KURL(NullURL(), url));
-
-    // The basis for security checks.
-    GetDocument().SetSecurityOrigin(SecurityOrigin::CreateFromString(url));
+    NavigateTo(KURL(NullURL(), url));
 
     if (url.StartsWith("https://") || url.StartsWith("http://localhost/")) {
       GetDocument().SetSecureContextStateForTesting(
diff --git a/third_party/blink/renderer/modules/service_worker/web_embedded_worker_impl_test.cc b/third_party/blink/renderer/modules/service_worker/web_embedded_worker_impl_test.cc
index c041ccef..797d66e 100644
--- a/third_party/blink/renderer/modules/service_worker/web_embedded_worker_impl_test.cc
+++ b/third_party/blink/renderer/modules/service_worker/web_embedded_worker_impl_test.cc
@@ -59,7 +59,7 @@
         nullptr);
   }
 
-  blink::mojom::ControllerServiceWorkerMode IsControlledByServiceWorker()
+  blink::mojom::ControllerServiceWorkerMode GetControllerServiceWorkerMode()
       override {
     return blink::mojom::ControllerServiceWorkerMode::kNoController;
   }
@@ -133,7 +133,7 @@
     return nullptr;
   }
   void WillSendRequest(WebURLRequest&) override {}
-  mojom::ControllerServiceWorkerMode IsControlledByServiceWorker()
+  mojom::ControllerServiceWorkerMode GetControllerServiceWorkerMode()
       const override {
     return mojom::ControllerServiceWorkerMode::kNoController;
   }
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope_test.cc b/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope_test.cc
index e3a04a6..f59da23a 100644
--- a/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope_test.cc
+++ b/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope_test.cc
@@ -57,9 +57,7 @@
   void SetUp() override {
     AudioWorkletThread::EnsureSharedBackingThread();
     PageTestBase::SetUp(IntSize());
-    Document* document = &GetDocument();
-    document->SetURL(KURL("https://example.com/"));
-    document->UpdateSecurityOrigin(SecurityOrigin::Create(document->Url()));
+    NavigateTo(KURL("https://example.com/"));
     reporting_proxy_ = std::make_unique<WorkerReportingProxy>();
   }
 
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet_thread_test.cc b/third_party/blink/renderer/modules/webaudio/audio_worklet_thread_test.cc
index 63181d1..18842432 100644
--- a/third_party/blink/renderer/modules/webaudio/audio_worklet_thread_test.cc
+++ b/third_party/blink/renderer/modules/webaudio/audio_worklet_thread_test.cc
@@ -40,9 +40,7 @@
   void SetUp() override {
     AudioWorkletThread::EnsureSharedBackingThread();
     PageTestBase::SetUp(IntSize());
-    Document* document = &GetDocument();
-    document->SetURL(KURL("https://example.com/"));
-    document->UpdateSecurityOrigin(SecurityOrigin::Create(document->Url()));
+    NavigateTo(KURL("https://example.com/"));
     reporting_proxy_ = std::make_unique<WorkerReportingProxy>();
   }
 
diff --git a/third_party/blink/renderer/modules/webshare/navigator_share_test.cc b/third_party/blink/renderer/modules/webshare/navigator_share_test.cc
index 615647fa..7da87c1 100644
--- a/third_party/blink/renderer/modules/webshare/navigator_share_test.cc
+++ b/third_party/blink/renderer/modules/webshare/navigator_share_test.cc
@@ -105,8 +105,11 @@
 
  protected:
   void SetUp() override {
-    GetDocument().SetSecurityOrigin(
-        SecurityOrigin::Create(KURL("https://example.com")));
+    GetFrame().Loader().CommitNavigation(
+        WebNavigationParams::CreateWithHTMLBuffer(SharedBuffer::Create(),
+                                                  KURL("https://example.com")),
+        nullptr /* extra_data */);
+    test::RunPendingTasks();
 
     service_manager::InterfaceProvider::TestApi test_api(
         &GetFrame().GetInterfaceProvider());
diff --git a/third_party/blink/renderer/modules/websockets/dom_websocket_test.cc b/third_party/blink/renderer/modules/websockets/dom_websocket_test.cc
index b2f83b88..c7a6c143 100644
--- a/third_party/blink/renderer/modules/websockets/dom_websocket_test.cc
+++ b/third_party/blink/renderer/modules/websockets/dom_websocket_test.cc
@@ -277,7 +277,7 @@
 TEST(DOMWebSocketTest, mixedContentAutoUpgrade) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndEnableFeature(features::kMixedContentAutoupgrade);
-  V8TestingScope scope;
+  V8TestingScope scope(KURL("https://example.com"));
   DOMWebSocketTestScope websocket_scope(scope.GetExecutionContext());
   {
     InSequence s;
@@ -285,8 +285,6 @@
                 Connect(KURL("wss://example.com/endpoint"), String()))
         .WillOnce(Return(true));
   }
-  scope.GetDocument().SetSecurityOrigin(
-      SecurityOrigin::Create(KURL("https://example.com")));
   scope.GetDocument().SetInsecureRequestPolicy(kLeaveInsecureRequestsAlone);
   websocket_scope.Socket().Connect("ws://example.com/endpoint",
                                    Vector<String>(), scope.GetExceptionState());
diff --git a/third_party/blink/renderer/modules/websockets/websocket_channel_impl_test.cc b/third_party/blink/renderer/modules/websockets/websocket_channel_impl_test.cc
index 8ef63ee..c7989347 100644
--- a/third_party/blink/renderer/modules/websockets/websocket_channel_impl_test.cc
+++ b/third_party/blink/renderer/modules/websockets/websocket_channel_impl_test.cc
@@ -132,6 +132,8 @@
 
   void SetUp() override {
     PageTestBase::SetUp(IntSize());
+    const KURL page_url("http://example.com/");
+    NavigateTo(page_url);
     channel_ = WebSocketChannelImpl::CreateForTesting(
         &GetDocument(), channel_client_.Get(), SourceLocation::Capture(),
         Handle(), base::WrapUnique(handshake_throttle_));
@@ -210,13 +212,8 @@
     EXPECT_CALL(*ChannelClient(), DidConnect(String("a"), String("b")));
   }
 
-  const KURL page_url("http://example.com/");
-  GetFrame().GetSecurityContext()->SetSecurityOrigin(
-      SecurityOrigin::Create(page_url));
-  Document& document = GetDocument();
-  document.SetURL(page_url);
   // Make sure that firstPartyForCookies() is set to the given value.
-  EXPECT_EQ("http://example.com/", document.SiteForCookies().GetString());
+  EXPECT_EQ("http://example.com/", GetDocument().SiteForCookies().GetString());
 
   EXPECT_TRUE(Channel()->Connect(KURL("ws://localhost/"), "x"));
 
diff --git a/third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread_test.cc b/third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread_test.cc
index dfa053a..32018480 100644
--- a/third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread_test.cc
+++ b/third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread_test.cc
@@ -46,9 +46,7 @@
  public:
   void SetUp() override {
     PageTestBase::SetUp(IntSize());
-    Document* document = &GetDocument();
-    document->SetURL(KURL("https://example.com/"));
-    document->UpdateSecurityOrigin(SecurityOrigin::Create(document->Url()));
+    NavigateTo(KURL("https://example.com/"));
     reporting_proxy_ = std::make_unique<WorkerReportingProxy>();
   }
 
diff --git a/third_party/blink/renderer/platform/bindings/v8_private_property.h b/third_party/blink/renderer/platform/bindings/v8_private_property.h
index 9eb1a25d..a0a07915 100644
--- a/third_party/blink/renderer/platform/bindings/v8_private_property.h
+++ b/third_party/blink/renderer/platform/bindings/v8_private_property.h
@@ -22,36 +22,37 @@
 // TODO(peria): Remove properties just to keep V8 objects alive.
 // e.g. IDBCursor.Request.
 // Apply |X| for each pair of (InterfaceName, PrivateKeyName).
-#define V8_PRIVATE_PROPERTY_FOR_EACH(X)               \
-  X(CustomElement, Document)                          \
-  X(CustomElement, IsInterfacePrototypeObject)        \
-  X(CustomElement, NamespaceURI)                      \
-  X(CustomElement, TagName)                           \
-  X(CustomElement, Type)                              \
-  X(CustomElementLifecycle, AttachedCallback)         \
-  X(CustomElementLifecycle, AttributeChangedCallback) \
-  X(CustomElementLifecycle, CreatedCallback)          \
-  X(CustomElementLifecycle, DetachedCallback)         \
-  X(DOMException, Error)                              \
-  X(Global, Event)                                    \
-  X(IDBCursor, Request)                               \
-  X(IntersectionObserver, Callback)                   \
-  X(MessageChannel, Port1)                            \
-  X(MessageChannel, Port2)                            \
-  X(MessageEvent, CachedData)                         \
-  X(MutationObserver, Callback)                       \
-  X(NamedConstructor, Initialized)                    \
-  X(PopStateEvent, State)                             \
-  X(SameObject, DetectedBarcodeCornerPoints)          \
-  X(SameObject, DetectedFaceLandmarks)                \
-  X(SameObject, NotificationActions)                  \
-  X(SameObject, NotificationData)                     \
-  X(SameObject, NotificationVibrate)                  \
-  X(SameObject, PerformanceLongTaskTimingAttribution) \
-  X(SameObject, PushManagerSupportedContentEncodings) \
-  X(SameObject, XRPresentationContextCanvas)          \
-  X(SameObject, XRWebGLLayerContext)                  \
-  SCRIPT_PROMISE_PROPERTIES(X, Promise)               \
+#define V8_PRIVATE_PROPERTY_FOR_EACH(X)                 \
+  X(CustomElement, Document)                            \
+  X(CustomElement, IsInterfacePrototypeObject)          \
+  X(CustomElement, NamespaceURI)                        \
+  X(CustomElement, TagName)                             \
+  X(CustomElement, Type)                                \
+  X(CustomElementLifecycle, AttachedCallback)           \
+  X(CustomElementLifecycle, AttributeChangedCallback)   \
+  X(CustomElementLifecycle, CreatedCallback)            \
+  X(CustomElementLifecycle, DetachedCallback)           \
+  X(DOMException, Error)                                \
+  X(Global, Event)                                      \
+  X(IDBCursor, Request)                                 \
+  X(IntersectionObserver, Callback)                     \
+  X(MessageChannel, Port1)                              \
+  X(MessageChannel, Port2)                              \
+  X(MessageEvent, CachedData)                           \
+  X(MutationObserver, Callback)                         \
+  X(NamedConstructor, Initialized)                      \
+  X(PopStateEvent, State)                               \
+  X(SameObject, DetectedBarcodeCornerPoints)            \
+  X(SameObject, DetectedFaceLandmarks)                  \
+  X(SameObject, NotificationActions)                    \
+  X(SameObject, NotificationData)                       \
+  X(SameObject, NotificationVibrate)                    \
+  X(SameObject, PerformanceLongTaskTimingAttribution)   \
+  X(SameObject, PerformanceObserverSupportedEntryTypes) \
+  X(SameObject, PushManagerSupportedContentEncodings)   \
+  X(SameObject, XRPresentationContextCanvas)            \
+  X(SameObject, XRWebGLLayerContext)                    \
+  SCRIPT_PROMISE_PROPERTIES(X, Promise)                 \
   SCRIPT_PROMISE_PROPERTIES(X, Resolver)
 
 // The getter's name for a private property.
diff --git a/third_party/blink/renderer/platform/exported/mediastream/media_stream_audio_processor_options.cc b/third_party/blink/renderer/platform/exported/mediastream/media_stream_audio_processor_options.cc
index 00c875af..43e17e60 100644
--- a/third_party/blink/renderer/platform/exported/mediastream/media_stream_audio_processor_options.cc
+++ b/third_party/blink/renderer/platform/exported/mediastream/media_stream_audio_processor_options.cc
@@ -29,8 +29,10 @@
 namespace blink {
 namespace {
 
+using NoiseSuppression = webrtc::AudioProcessing::Config::NoiseSuppression;
+
 base::Optional<double> GetGainControlCompressionGain(
-    const base::Value* config) {
+    const base::Optional<base::Value>& config) {
   if (!config)
     return base::nullopt;
   const base::Value* found =
@@ -42,7 +44,8 @@
   return gain;
 }
 
-base::Optional<double> GetPreAmplifierGainFactor(const base::Value* config) {
+base::Optional<double> GetPreAmplifierGainFactor(
+    const base::Optional<base::Value>& config) {
   if (!config)
     return base::nullopt;
   const base::Value* found = config->FindKey("pre_amplifier_fixed_gain_factor");
@@ -53,6 +56,19 @@
   return factor;
 }
 
+void GetExtraGainConfig(
+    const std::string& audio_processing_platform_config_json,
+    base::Optional<double>* gain_control_compression_gain_db,
+    base::Optional<double>* pre_amplifier_fixed_gain_factor) {
+  auto config = base::JSONReader::Read(audio_processing_platform_config_json);
+  if (!config) {
+    LOG(ERROR) << "Failed to parse platform config JSON.";
+    return;
+  }
+  *gain_control_compression_gain_db = GetGainControlCompressionGain(config);
+  *pre_amplifier_fixed_gain_factor = GetPreAmplifierGainFactor(config);
+}
+
 }  // namespace
 
 AudioProcessingProperties::AudioProcessingProperties() = default;
@@ -113,22 +129,6 @@
   return out;
 }
 
-void EnableEchoCancellation(AudioProcessing::Config* apm_config) {
-  apm_config->echo_canceller.enabled = true;
-#if defined(OS_ANDROID)
-  apm_config->echo_canceller.mobile_mode = true;
-#else
-  apm_config->echo_canceller.mobile_mode = false;
-#endif
-}
-
-void EnableNoiseSuppression(
-    AudioProcessing::Config* apm_config,
-    AudioProcessing::Config::NoiseSuppression::Level ns_level) {
-  apm_config->noise_suppression.enabled = true;
-  apm_config->noise_suppression.level = ns_level;
-}
-
 void EnableTypingDetection(AudioProcessing::Config* apm_config,
                            webrtc::TypingDetection* typing_detector) {
   apm_config->voice_detection.enabled = true;
@@ -160,24 +160,6 @@
   audio_processing->DetachAecDump();
 }
 
-void GetExtraGainConfig(
-    const base::Optional<std::string>& audio_processing_platform_config_json,
-    base::Optional<double>* pre_amplifier_fixed_gain_factor,
-    base::Optional<double>* gain_control_compression_gain_db) {
-  if (!audio_processing_platform_config_json)
-    return;
-  std::unique_ptr<base::Value> config;
-  config =
-      base::JSONReader::ReadDeprecated(*audio_processing_platform_config_json);
-  if (!config) {
-    LOG(ERROR) << "Failed to parse platform config JSON.";
-    return;
-  }
-  *pre_amplifier_fixed_gain_factor = GetPreAmplifierGainFactor(config.get());
-  *gain_control_compression_gain_db =
-      GetGainControlCompressionGain(config.get());
-}
-
 void ConfigAutomaticGainControl(
     AudioProcessing::Config* apm_config,
     bool agc_enabled,
@@ -234,11 +216,40 @@
   }
 }
 
-void ConfigPreAmplifier(AudioProcessing::Config* apm_config,
-                        base::Optional<double> fixed_gain_factor) {
-  if (!!fixed_gain_factor) {
+void PopulateApmConfig(
+    AudioProcessing::Config* apm_config,
+    const AudioProcessingProperties& properties,
+    const base::Optional<std::string>& audio_processing_platform_config_json,
+    base::Optional<double>* gain_control_compression_gain_db) {
+  // TODO(saza): When Chrome uses AGC2, handle all JSON config via the
+  // webrtc::AudioProcessing::Config, crbug.com/895814.
+  base::Optional<double> pre_amplifier_fixed_gain_factor;
+  if (audio_processing_platform_config_json.has_value()) {
+    GetExtraGainConfig(audio_processing_platform_config_json.value(),
+                       gain_control_compression_gain_db,
+                       &pre_amplifier_fixed_gain_factor);
+  }
+
+  apm_config->high_pass_filter.enabled = properties.goog_highpass_filter;
+
+  if (pre_amplifier_fixed_gain_factor.has_value()) {
     apm_config->pre_amplifier.enabled = true;
-    apm_config->pre_amplifier.fixed_gain_factor = fixed_gain_factor.value();
+    apm_config->pre_amplifier.fixed_gain_factor =
+        pre_amplifier_fixed_gain_factor.value();
+  }
+
+  if (properties.goog_noise_suppression) {
+    apm_config->noise_suppression.enabled = true;
+    apm_config->noise_suppression.level = NoiseSuppression::kHigh;
+  }
+
+  if (properties.EchoCancellationIsWebRtcProvided()) {
+    apm_config->echo_canceller.enabled = true;
+#if defined(OS_ANDROID)
+    apm_config->echo_canceller.mobile_mode = true;
+#else
+    apm_config->echo_canceller.mobile_mode = false;
+#endif
   }
 }
 
diff --git a/third_party/blink/renderer/platform/exported/mediastream/media_stream_audio_processor_options_test.cc b/third_party/blink/renderer/platform/exported/mediastream/media_stream_audio_processor_options_test.cc
index ab73a2f2..b9ab5a5b 100644
--- a/third_party/blink/renderer/platform/exported/mediastream/media_stream_audio_processor_options_test.cc
+++ b/third_party/blink/renderer/platform/exported/mediastream/media_stream_audio_processor_options_test.cc
@@ -71,4 +71,32 @@
       saturation_margin);
 }
 
+TEST(PopulateApmConfigTest, SetGainsInConfigJson) {
+  webrtc::AudioProcessing::Config apm_config;
+  AudioProcessingProperties properties;
+  base::Optional<std::string> audio_processing_platform_config_json =
+      "{\"gain_control_compression_gain_db\": 10, "
+      "\"pre_amplifier_fixed_gain_factor\": 2.0}";
+  base::Optional<double> gain_control_compression_gain_db;
+
+  PopulateApmConfig(&apm_config, properties,
+                    audio_processing_platform_config_json,
+                    &gain_control_compression_gain_db);
+  EXPECT_TRUE(gain_control_compression_gain_db.has_value());
+  EXPECT_EQ(gain_control_compression_gain_db.value(), 10);
+  EXPECT_TRUE(apm_config.high_pass_filter.enabled);
+  EXPECT_TRUE(apm_config.pre_amplifier.enabled);
+  EXPECT_FLOAT_EQ(apm_config.pre_amplifier.fixed_gain_factor, 2.0);
+  EXPECT_TRUE(apm_config.noise_suppression.enabled);
+  EXPECT_EQ(apm_config.noise_suppression.level,
+            webrtc::AudioProcessing::Config::NoiseSuppression::kHigh);
+  EXPECT_TRUE(apm_config.echo_canceller.enabled);
+#if defined(OS_ANDROID)
+  EXPECT_TRUE(
+#else
+  EXPECT_FALSE(
+#endif
+      apm_config.echo_canceller.mobile_mode);
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/exported/web_runtime_features.cc b/third_party/blink/renderer/platform/exported/web_runtime_features.cc
index acf7a67..de44df93 100644
--- a/third_party/blink/renderer/platform/exported/web_runtime_features.cc
+++ b/third_party/blink/renderer/platform/exported/web_runtime_features.cc
@@ -128,10 +128,6 @@
   RuntimeEnabledFeatures::SetCacheInlineScriptCodeEnabled(enable);
 }
 
-void WebRuntimeFeatures::EnableIsolatedCodeCache(bool enable) {
-  RuntimeEnabledFeatures::SetIsolatedCodeCacheEnabled(enable);
-}
-
 void WebRuntimeFeatures::EnableWasmCodeCache(bool enable) {
   RuntimeEnabledFeatures::SetWasmCodeCacheEnabled(enable);
 }
diff --git a/third_party/blink/renderer/platform/graphics/color.h b/third_party/blink/renderer/platform/graphics/color.h
index c682ad4..031d7353 100644
--- a/third_party/blink/renderer/platform/graphics/color.h
+++ b/third_party/blink/renderer/platform/graphics/color.h
@@ -72,8 +72,8 @@
   DISALLOW_NEW();
 
  public:
-  Color() : color_(Color::kTransparent) {}
-  Color(RGBA32 color) : color_(color) {}
+  constexpr Color() : color_(Color::kTransparent) {}
+  constexpr Color(RGBA32 color) : color_(color) {}
   Color(int r, int g, int b) : color_(MakeRGB(r, g, b)) {}
   Color(int r, int g, int b, int a) : color_(MakeRGBA(r, g, b, a)) {}
   // Color is currently limited to 32bit RGBA. Perhaps some day we'll support
@@ -84,11 +84,11 @@
   Color(float c, float m, float y, float k, float a)
       : color_(MakeRGBAFromCMYKA(c, m, y, k, a)) {}
 
-  static Color CreateUnchecked(int r, int g, int b) {
+  static constexpr Color CreateUnchecked(int r, int g, int b) {
     RGBA32 color = 0xFF000000 | r << 16 | g << 8 | b;
     return Color(color);
   }
-  static Color CreateUnchecked(int r, int g, int b, int a) {
+  static constexpr Color CreateUnchecked(int r, int g, int b, int a) {
     RGBA32 color = a << 24 | r << 16 | g << 8 | b;
     return Color(color);
   }
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index e5dfef6..5d3c627 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -962,10 +962,6 @@
       status: {"Android": "", "default": "stable"},
     },
     {
-      name: "NavigatorDeviceMemory",
-      status: "stable",
-    },
-    {
       // Allows the navigator.language and navigator.languages APIs in insecure
       // contexts, which https://github.com/WICG/lang-client-hint proposes that
       // we deprecate.
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_unittest.cc b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_unittest.cc
index 5d8c88c..179094cb 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_unittest.cc
@@ -5,16 +5,19 @@
 #include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread.h"
 
 #include <stddef.h>
+
 #include <memory>
 
 #include "base/bind.h"
 #include "base/location.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_pump.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
-#include "base/task/sequence_manager/test/sequence_manager_for_test.h"
+#include "base/task/sequence_manager/sequence_manager.h"
+#include "base/test/scoped_task_environment.h"
 #include "base/test/simple_test_tick_clock.h"
+#include "base/threading/thread_task_runner_handle.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/platform/platform.h"
@@ -48,7 +51,8 @@
   void SetUp() override {
     clock_.Advance(base::TimeDelta::FromMicroseconds(5000));
     scheduler_.reset(new MainThreadSchedulerImpl(
-        base::sequence_manager::SequenceManagerForTest::CreateOnCurrentThread(
+        base::sequence_manager::CreateSequenceManagerOnCurrentThreadWithPump(
+            base::MessagePump::Create(base::MessagePump::Type::DEFAULT),
             base::sequence_manager::SequenceManager::Settings::Builder()
                 .SetTickClock(&clock_)
                 .Build()),
@@ -68,7 +72,6 @@
   void TearDown() override { scheduler_->Shutdown(); }
 
  protected:
-  base::MessageLoop message_loop_;
   base::SimpleTestTickClock clock_;
   std::unique_ptr<MainThreadSchedulerImpl> scheduler_;
   std::unique_ptr<ScopedSchedulerOverrider> scheduler_overrider_;
@@ -89,7 +92,7 @@
     EXPECT_CALL(observer, DidProcessTask(_));
   }
 
-  message_loop_.task_runner()->PostTask(
+  scheduler_->DefaultTaskRunner()->PostTask(
       FROM_HERE, WTF::Bind(&MockTask::Run, WTF::Unretained(&task)));
   base::RunLoop().RunUntilIdle();
   thread_->RemoveTaskObserver(&observer);
@@ -108,7 +111,7 @@
     EXPECT_CALL(observer, DidProcessTask(_));
   }
 
-  message_loop_.task_runner()->PostTask(
+  scheduler_->DefaultTaskRunner()->PostTask(
       FROM_HERE, WTF::Bind(&MockTask::Run, WTF::Unretained(&task)));
   base::RunLoop().RunUntilIdle();
   thread_->RemoveTaskObserver(&observer);
@@ -132,9 +135,9 @@
     EXPECT_CALL(observer, DidProcessTask(_));
   }
 
-  message_loop_.task_runner()->PostTask(
+  scheduler_->DefaultTaskRunner()->PostTask(
       FROM_HERE, WTF::Bind(&MockTask::Run, WTF::Unretained(&task1)));
-  message_loop_.task_runner()->PostTask(
+  scheduler_->DefaultTaskRunner()->PostTask(
       FROM_HERE, WTF::Bind(&MockTask::Run, WTF::Unretained(&task2)));
   base::RunLoop().RunUntilIdle();
   thread_->RemoveTaskObserver(&observer);
@@ -163,21 +166,21 @@
     EXPECT_CALL(observer, DidProcessTask(_));
   }
 
-  message_loop_.task_runner()->PostTask(
+  scheduler_->DefaultTaskRunner()->PostTask(
       FROM_HERE, WTF::Bind(&MockTask::Run, WTF::Unretained(&task1)));
-  message_loop_.task_runner()->PostTask(
+  scheduler_->DefaultTaskRunner()->PostTask(
       FROM_HERE, WTF::Bind(&MockTask::Run, WTF::Unretained(&task2)));
-  message_loop_.task_runner()->PostTask(
+  scheduler_->DefaultTaskRunner()->PostTask(
       FROM_HERE, WTF::Bind(&MockTask::Run, WTF::Unretained(&task3)));
   base::RunLoop().RunUntilIdle();
   thread_->RemoveTaskObserver(&observer);
 }
 
-void EnterRunLoop(base::MessageLoop* message_loop, Thread* thread) {
+void EnterRunLoop(scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
   // Note: blink::Threads do not support nested run loops, which is why we use a
   // run loop directly.
   base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
-  message_loop->task_runner()->PostTask(
+  task_runner->PostTask(
       FROM_HERE, WTF::Bind(&base::RunLoop::Quit, WTF::Unretained(&run_loop)));
   run_loop.Run();
 }
@@ -200,9 +203,9 @@
     EXPECT_CALL(observer, DidProcessTask(_));
   }
 
-  message_loop_.task_runner()->PostTask(
-      FROM_HERE, base::BindOnce(&EnterRunLoop, base::Unretained(&message_loop_),
-                                base::Unretained(thread_)));
+  scheduler_->DefaultTaskRunner()->PostTask(
+      FROM_HERE,
+      base::BindOnce(&EnterRunLoop, scheduler_->DefaultTaskRunner()));
   base::RunLoop().RunUntilIdle();
   thread_->RemoveTaskObserver(&observer);
 }
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index be4e9cf..393f36ae 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -294,22 +294,52 @@
 # These fail when device_scale_factor is changed, but only for anti-aliasing:
 crbug.com/968791 virtual/scalefactor200/css3/filters/effect-blur-hw.html [ Failure ]
 crbug.com/968791 virtual/scalefactor200/css3/filters/filterRegions.html [ Failure ]
-crbug.com/968791 virtual/scalefactor200/external/wpt/css/filter-effects/css-filters-animation-blur.html [ Failure ]
-crbug.com/968791 virtual/scalefactor200/external/wpt/css/filter-effects/css-filters-animation-combined-001.html [ Failure ]
-crbug.com/968791 virtual/scalefactor200/external/wpt/css/filter-effects/filter-subregion-01.html [ Failure ]
 
 # These appear to be actually incorrect at device_scale_factor 2.0:
-crbug.com/968791 virtual/scalefactor200/css3/filters/effect-reference-image-hw.html [ Failure ]
 crbug.com/968791 virtual/scalefactor200/css3/filters/effect-reference-image-lazy-attach.html [ Failure ]
 crbug.com/968791 virtual/scalefactor200/css3/filters/effect-reference-image.html [ Failure ]
-crbug.com/968791 virtual/scalefactor200/external/wpt/css/filter-effects/filtered-inline-applies-to-float.html [ Failure ]
 crbug.com/968791 virtual/scalefactor200/external/wpt/css/filter-effects/filters-test-brightness-003.html [ Failure ]
 
 # These seem flaky on scalefactor200:
-crbug.com/968791 virtual/scalefactor200/css3/filters/effect-reference-hw.html [ Pass Failure Timeout ]
-crbug.com/968791 virtual/scalefactor200/css3/filters/effect-reference-subregion-hw.html [ Pass Failure Timeout ]
 crbug.com/968791 virtual/scalefactor200/css3/filters/effect-contrast-hw.html [ Pass Failure Timeout ]
 
+# Copying these from elsewhere in TestExpectations (for non-scalefactor200 virtual suite)
+crbug.com/658305 virtual/scalefactor200/css3/filters/buffer-offset.html [ Failure Pass ]
+crbug.com/658305 virtual/scalefactor200/css3/filters/effect-all-on-background-hw.html [ Failure Pass Timeout ]
+crbug.com/658305 virtual/scalefactor200/css3/filters/effect-reference-after.html [ Failure Pass ]
+crbug.com/658305 virtual/scalefactor200/css3/filters/effect-reference-colorspace.html [ Failure Pass ]
+crbug.com/658305 crbug.com/758133 virtual/scalefactor200/css3/filters/effect-reference-colorspace-hw.html [ Failure Pass Timeout ]
+crbug.com/658305 virtual/scalefactor200/css3/filters/effect-reference-composite.html [ Failure Pass ]
+crbug.com/658305 virtual/scalefactor200/css3/filters/effect-reference-composite-hw.html [ Failure Pass ]
+crbug.com/658305 virtual/scalefactor200/css3/filters/effect-reference-external.html [ Failure Pass ]
+crbug.com/658305 virtual/scalefactor200/css3/filters/effect-reference-external-stylesheet.html [ Failure Pass ]
+crbug.com/658305 virtual/scalefactor200/css3/filters/effect-reference-hidpi.html [ Failure Pass ]
+crbug.com/658305 virtual/scalefactor200/css3/filters/effect-reference-hidpi-hw.html [ Failure Pass Timeout ]
+crbug.com/658305 virtual/scalefactor200/css3/filters/effect-reference.html [ Failure Pass ]
+crbug.com/658305 crbug.com/758133 virtual/scalefactor200/css3/filters/effect-reference-hw.html [ Failure Pass Timeout ]
+crbug.com/658305 virtual/scalefactor200/css3/filters/effect-reference-ordering.html [ Failure Pass ]
+crbug.com/658305 virtual/scalefactor200/css3/filters/effect-reference-ordering-hw.html [ Failure Pass ]
+crbug.com/658305 virtual/scalefactor200/css3/filters/effect-reference-rename.html [ Failure Pass ]
+crbug.com/658305 virtual/scalefactor200/css3/filters/effect-reference-subregion-chained.html [ Failure Pass ]
+crbug.com/658305 virtual/scalefactor200/css3/filters/effect-reference-subregion-chained-hw.html [ Failure Pass ]
+crbug.com/658305 virtual/scalefactor200/css3/filters/effect-reference-subregion-colormatrix.html [ Failure Pass ]
+crbug.com/658305 virtual/scalefactor200/css3/filters/effect-reference-subregion.html [ Failure Pass ]
+crbug.com/658305 virtual/scalefactor200/css3/filters/effect-reference-subregion-hw.html [ Failure Pass Timeout ]
+crbug.com/658305 virtual/scalefactor200/css3/filters/effect-reference-tile.html [ Failure Pass ]
+crbug.com/658305 virtual/scalefactor200/css3/filters/effect-reference-tile-hw.html [ Failure Pass ]
+crbug.com/658305 virtual/scalefactor200/css3/filters/effect-reference-zoom.html [ Failure Pass ]
+crbug.com/658305 virtual/scalefactor200/css3/filters/effect-reference-zoom-hw.html [ Failure Pass ]
+crbug.com/658305 virtual/scalefactor200/css3/filters/filter-effect-removed.html [ Failure Pass ]
+crbug.com/862716 [ Mac ] virtual/scalefactor200/css3/filters/effect-brightness-clamping-hw.html [ Failure Pass Timeout ]
+crbug.com/862716 [ Linux ] virtual/scalefactor200/css3/filters/effect-brightness-clamping-hw.html [ Failure Pass Timeout ]
+crbug.com/862716 [ Win ] virtual/scalefactor200/css3/filters/effect-brightness-clamping-hw.html [ Failure Pass Timeout ]
+crbug.com/869364 virtual/scalefactor200/css3/filters/filter-repaint-composited-fallback.html [ Pass Timeout ]
+crbug.com/873454 virtual/scalefactor200/css3/filters/effect-reference-image-hw.html [ Failure Pass ]
+crbug.com/903383 virtual/scalefactor200/external/wpt/css/filter-effects/css-filters-animation-combined-001.html [ Failure ]
+crbug.com/903383 virtual/scalefactor200/external/wpt/css/filter-effects/css-filters-animation-blur.html [ Failure ]
+crbug.com/626703 virtual/scalefactor200/external/wpt/css/filter-effects/filter-subregion-01.html [ Failure ]
+crbug.com/591099 virtual/scalefactor200/external/wpt/css/filter-effects/filtered-inline-applies-to-float.html [ Failure ]
+
 # ==== Regressions introduced by BlinkGenPropertyTrees =====
 # Reflection / mask ordering issue
 crbug.com/767318 compositing/reflections/nested-reflection-mask-change.html [ Failure ]
@@ -5304,6 +5334,12 @@
 
 crbug.com/919272 external/wpt/resource-timing/resource-timing.html [ Skip ]
 
+### virtual/streams-native/http/tests/streams/transferable/
+crbug.com/902633 virtual/streams-native/http/tests/streams/transferable/writable-stream.html [ Timeout ]
+crbug.com/902633 virtual/streams-native/http/tests/streams/transferable/shared-worker.html [ Pass Failure ]
+crbug.com/902633 virtual/streams-native/http/tests/streams/transferable/worker.html [ Pass Failure ]
+
+
 # Sheriff 2019-01-03
 crbug.com/918905 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/sizing/block-size-with-min-or-max-content-table-1b.html [ Pass Failure ]
 
@@ -5815,3 +5851,6 @@
 crbug.com/971590 fast/dom/timer-throttling-out-of-view-cross-origin-page.html [ Pass Failure ]
 crbug.com/971590 [ Mac ] fast/dom/timer-throttling-hidden-page.html [ Pass Failure ]
 crbug.com/971612 fast/canvas/OffscreenCanvas-MessageChannel-transfer.html [ Pass Failure ]
+
+# Sheriff 2019-06-10
+crbug.com/972516 [ Win ] netinfo/gc-unused-listeners.html [ Pass Failure ]
diff --git a/third_party/blink/web_tests/external/wpt/performance-timeline/supportedEntryTypes.any.js b/third_party/blink/web_tests/external/wpt/performance-timeline/supportedEntryTypes.any.js
index a0225ad2..25f1959 100644
--- a/third_party/blink/web_tests/external/wpt/performance-timeline/supportedEntryTypes.any.js
+++ b/third_party/blink/web_tests/external/wpt/performance-timeline/supportedEntryTypes.any.js
@@ -10,3 +10,10 @@
       "' are repeated or they are not in alphabetical order.")
   }
 }, "supportedEntryTypes exists and returns entries in alphabetical order");
+
+test(() => {
+  if (typeof PerformanceObserver.supportedEntryTypes === "undefined")
+    assert_unreached("supportedEntryTypes is not supported.");
+  assert_true(PerformanceObserver.supportedEntryTypes ===
+      PerformanceObserver.supportedEntryTypes);
+}, "supportedEntryTypes caches result");
diff --git a/third_party/blink/web_tests/external/wpt/signed-exchange/resources/generate-test-sxgs.sh b/third_party/blink/web_tests/external/wpt/signed-exchange/resources/generate-test-sxgs.sh
index a777611..16750f2 100755
--- a/third_party/blink/web_tests/external/wpt/signed-exchange/resources/generate-test-sxgs.sh
+++ b/third_party/blink/web_tests/external/wpt/signed-exchange/resources/generate-test-sxgs.sh
@@ -28,7 +28,12 @@
 echo -n OCSP >$tmpdir/ocsp
 gen-certurl -pem $certfile -ocsp $tmpdir/ocsp > $certfile.cbor
 
-cert_base64=$(base64 -w 0 $certfile.cbor)
+option="-w 0"
+if [ "$(uname -s)" = "Darwin" ]; then
+    option=""
+fi
+
+cert_base64=$(base64 ${option} ${certfile}.cbor)
 data_cert_url="data:application/cert-chain+cbor;base64,$cert_base64"
 
 
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 44d97f3..9ea2b99 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
@@ -1347,6 +1347,11 @@
     method sort
     method toString
     method values
+interface UserActivation
+    attribute @@toStringTag
+    getter hasBeenActive
+    getter isActive
+    method constructor
 interface WebGL2ComputeRenderingContext
     attribute @@toStringTag
     attribute ACTIVE_ATOMIC_COUNTER_BUFFERS
diff --git a/third_party/blink/web_tests/virtual/omt-worker-fetch/external/wpt/workers/modules/dedicated-worker-options-credentials-expected.txt b/third_party/blink/web_tests/virtual/omt-worker-fetch/external/wpt/workers/modules/dedicated-worker-options-credentials-expected.txt
deleted file mode 100644
index 819ccf6..0000000
--- a/third_party/blink/web_tests/virtual/omt-worker-fetch/external/wpt/workers/modules/dedicated-worker-options-credentials-expected.txt
+++ /dev/null
@@ -1,36 +0,0 @@
-This is a testharness.js-based test.
-PASS Test initialization: setting up cross-origin cookie
-PASS new Worker() with type=module and default credentials option should behave as credentials=same-origin and send the credentials
-FAIL new Worker() with type=module and credentials=omit should not send the credentials assert_equals: expected "" but got "1"
-PASS new Worker() with type=module and credentials=same-origin should send the credentials
-PASS new Worker() with type=module and credentials=include should send the credentials
-PASS new Worker() with type=module and default credentials option should behave as credentials=same-origin and send the credentials for same-origin static imports
-PASS new Worker() with type=module and credentials=omit should not send the credentials for same-origin static imports
-PASS new Worker() with type=module and credentials=same-origin should send the credentials for same-origin static imports
-PASS new Worker() with type=module and credentials=include should send the credentials for same-origin static imports
-PASS new Worker() with type=module and default credentials option should behave as credentials=same-origin and not send the credentials for cross-origin static imports
-PASS new Worker() with type-module credentials=omit should not send the credentials for cross-origin static imports
-PASS new Worker() with type=module and credentials=same-origin should not send the credentials for cross-origin static imports
-PASS new Worker() with type=module and credentials=include should send the credentials for cross-origin static imports
-PASS new Worker() with type=module and default credentials option should behave as credentials=same-origin and send the credentials for same-origin dynamic imports
-PASS new Worker() with type=module and credentials=omit should not send the credentials for same-origin dynamic imports
-PASS new Worker() with type=module and credentials=same-origin should send the credentials for same-origin dynamic imports
-PASS new Worker() with type=module and credentials=include should send the credentials for same-origin dynamic imports
-PASS new Worker() with type=module and default credentials option should behave as credentials=same-origin and not send the credentials for cross-origin dynamic imports
-PASS new Worker() with type-module credentials=omit should not send the credentials for cross-origin dynamic imports
-PASS new Worker() with type=module and credentials=same-origin should not send the credentials for cross-origin dynamic imports
-PASS new Worker() with type=module and credentials=include should send the credentials for cross-origin dynamic imports
-PASS new Worker() with type=classic should always send the credentials regardless of the credentials option (default).
-PASS new Worker() with type=classic should always send the credentials regardless of the credentials option (omit).
-PASS new Worker() with type=classic should always send the credentials regardless of the credentials option (same-origin).
-PASS new Worker() with type=classic should always send the credentials regardless of the credentials option (include).
-PASS new Worker() with type=classic should always send the credentials for same-origin dynamic imports regardless of the credentials option (default).
-PASS new Worker() with type=classic should always send the credentials for same-origin dynamic imports regardless of the credentials option (omit).
-PASS new Worker() with type=classic should always send the credentials for same-origin dynamic imports regardless of the credentials option (same-origin).
-PASS new Worker() with type=classic should always send the credentials for same-origin dynamic imports regardless of the credentials option (include).
-PASS new Worker() with type=classic should never send the credentials for cross-origin dynamic imports regardless of the credentials option (default).
-PASS new Worker() with type=classic should never send the credentials for cross-origin dynamic imports regardless of the credentials option (omit).
-PASS new Worker() with type=classic should never send the credentials for cross-origin dynamic imports regardless of the credentials option (same-origin).
-PASS new Worker() with type=classic should never send the credentials for cross-origin dynamic imports regardless of the credentials option (include).
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
index f292e3a0..a970244 100644
--- a/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
+++ b/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -1207,6 +1207,11 @@
     method sort
     method toString
     method values
+interface UserActivation
+    attribute @@toStringTag
+    getter hasBeenActive
+    getter isActive
+    method constructor
 interface WebGL2RenderingContext
     attribute @@toStringTag
     attribute ACTIVE_ATTRIBUTES
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt
index 16ef786..e4eab19 100644
--- a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt
+++ b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -1239,6 +1239,11 @@
 [Worker]     getter bytesWritten
 [Worker]     getter status
 [Worker]     method constructor
+[Worker] interface UserActivation
+[Worker]     attribute @@toStringTag
+[Worker]     getter hasBeenActive
+[Worker]     getter isActive
+[Worker]     method constructor
 [Worker] interface WebGL2RenderingContext
 [Worker]     attribute @@toStringTag
 [Worker]     attribute ACTIVE_ATTRIBUTES
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt
index ee82e68..ce7790a 100644
--- a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt
+++ b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -1135,6 +1135,11 @@
 [Worker]     method sort
 [Worker]     method toString
 [Worker]     method values
+[Worker] interface UserActivation
+[Worker]     attribute @@toStringTag
+[Worker]     getter hasBeenActive
+[Worker]     getter isActive
+[Worker]     method constructor
 [Worker] interface WebGL2RenderingContext
 [Worker]     attribute @@toStringTag
 [Worker]     attribute ACTIVE_ATTRIBUTES
diff --git a/third_party/blink/web_tests/virtual/streams-native/http/tests/streams/transferable/readable-stream-expected.txt b/third_party/blink/web_tests/virtual/streams-native/http/tests/streams/transferable/readable-stream-expected.txt
new file mode 100644
index 0000000..a398705f
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/streams-native/http/tests/streams/transferable/readable-stream-expected.txt
@@ -0,0 +1,19 @@
+This is a testharness.js-based test.
+FAIL sending one chunk through a transferred stream should work promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
+FAIL sending ten chunks through a transferred stream should work promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
+FAIL sending ten chunks one at a time should work promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
+FAIL sending ten chunks on demand should work promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
+FAIL transferring a stream should relieve backpressure assert_array_equals: pull() should have been called lengths differ, expected 1 got 0
+FAIL transferring a stream should add one chunk to the queue size promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
+FAIL the extra queue from transferring is counted in chunks promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
+FAIL cancel should be propagated to the original promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
+FAIL cancel should abort a pending read() promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
+FAIL stream cancel should not wait for underlying source cancel promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
+FAIL serialization should not happen until the value is read promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
+FAIL transferring a non-serializable chunk should error both sides promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
+FAIL errors should be passed through promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
+FAIL race between cancel() and error() should leave sides in different states promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
+FAIL race between cancel() and close() should be benign promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
+FAIL race between cancel() and enqueue() should be benign promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/virtual/streams-native/http/tests/streams/transferable/reason-expected.txt b/third_party/blink/web_tests/virtual/streams-native/http/tests/streams/transferable/reason-expected.txt
new file mode 100644
index 0000000..e381006
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/streams-native/http/tests/streams/transferable/reason-expected.txt
@@ -0,0 +1,25 @@
+This is a testharness.js-based test.
+FAIL reason with a simple value of 'hi' should be preserved promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
+FAIL reason with a simple value of '	\r
+' should be preserved promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
+FAIL reason with a simple value of '7' should be preserved promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
+FAIL reason with a simple value of '3' should be preserved promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
+FAIL reason with a simple value of 'undefined' should be preserved promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
+FAIL reason with a simple value of 'null' should be preserved promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
+FAIL reason with a simple value of 'true' should be preserved promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
+FAIL reason with a simple value of 'false' should be preserved promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
+FAIL reason with a type of 'symbol' should be squished to undefined promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
+FAIL reason with a type of 'function' should be squished to undefined promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
+FAIL number with a value of 'NaN' should be squished to null promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
+FAIL number with a value of 'Infinity' should be squished to null promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
+FAIL objects that can be completely expressed in JSON should be preserved promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
+FAIL objects that cannot be expressed in JSON should result in a TypeError promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
+FAIL the type and message of a TypeError should be preserved promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
+FAIL other attributes of a TypeError should not be preserved promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
+FAIL a TypeError message should not be preserved if it is not a string promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
+FAIL a TypeError message should not be preserved if it is a getter promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
+FAIL a TypeError message should not be preserved if it is inherited promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
+FAIL DOMException errors should be preserved promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
+FAIL RangeErrors should not be preserved promise_test: Unhandled rejection with value: object "Error: what is this thing: "null"?"
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/virtual/streams-native/http/tests/streams/transferable/service-worker-expected.txt b/third_party/blink/web_tests/virtual/streams-native/http/tests/streams/transferable/service-worker-expected.txt
new file mode 100644
index 0000000..d487631
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/streams-native/http/tests/streams/transferable/service-worker-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+PASS service-worker
+FAIL serviceWorker.controller.postMessage should be able to transfer a ReadableStream assert_true: the original stream should be locked expected true got false
+FAIL postMessage in a service worker should be able to transfer ReadableStream promise_test: Unhandled rejection with value: "BAD: TypeError: Cannot read property 'constructor' of null"
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/virtual/streams-native/http/tests/streams/transferable/shared-worker-expected.txt b/third_party/blink/web_tests/virtual/streams-native/http/tests/streams/transferable/shared-worker-expected.txt
new file mode 100644
index 0000000..a61ccf35
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/streams-native/http/tests/streams/transferable/shared-worker-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+FAIL worker.postMessage should be able to transfer a ReadableStream assert_true: the original stream should be locked expected true got false
+FAIL postMessage in a worker should be able to transfer a ReadableStream promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'constructor' of null"
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/virtual/streams-native/http/tests/streams/transferable/transform-stream-expected.txt b/third_party/blink/web_tests/virtual/streams-native/http/tests/streams/transferable/transform-stream-expected.txt
new file mode 100644
index 0000000..fddd996
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/streams-native/http/tests/streams/transferable/transform-stream-expected.txt
@@ -0,0 +1,8 @@
+This is a testharness.js-based test.
+FAIL window.postMessage should be able to transfer a TransformStream assert_true: the readable side should be locked expected true got false
+PASS a TransformStream with a locked writable should not be transferable
+PASS a TransformStream with a locked readable should not be transferable
+PASS a TransformStream with both sides locked should not be transferable
+FAIL piping through transferred transforms should work Cannot read property 'source' of null
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/virtual/streams-native/http/tests/streams/transferable/window-expected.txt b/third_party/blink/web_tests/virtual/streams-native/http/tests/streams/transferable/window-expected.txt
new file mode 100644
index 0000000..8e6fa50
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/streams-native/http/tests/streams/transferable/window-expected.txt
@@ -0,0 +1,13 @@
+CONSOLE ERROR: line 23: Uncaught TypeError: Cannot read property 'start' of null
+CONSOLE ERROR: line 17: Uncaught (in promise) TypeError: Cannot read property 'constructor' of null
+CONSOLE ERROR: line 41: Uncaught (in promise) TypeError: Cannot read property 'addEventListener' of null
+CONSOLE ERROR: line 45: Uncaught (in promise) Error: assert_array_equals: there should be no ports in the event lengths differ, expected 0 got 1
+CONSOLE ERROR: line 5: Uncaught TypeError: Failed to execute 'postMessage' on 'Window': Value at index 0 is an untransferable 'null' value.
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = assert_array_equals: there should be no ports in the event lengths differ, expected 0 got 1
+FAIL window.postMessage should be able to transfer a ReadableStream assert_true: the original stream should be locked expected true got false
+FAIL port.postMessage should be able to transfer a ReadableStream assert_true: the original stream should be locked expected true got false
+FAIL the same ReadableStream posted multiple times should arrive together object null is not iterable (cannot read property Symbol(Symbol.iterator))
+FAIL transfer to and from an iframe should work assert_array_equals: there should be no ports in the event lengths differ, expected 0 got 1
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/virtual/streams-native/http/tests/streams/transferable/worker-expected.txt b/third_party/blink/web_tests/virtual/streams-native/http/tests/streams/transferable/worker-expected.txt
new file mode 100644
index 0000000..d3ca9a3
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/streams-native/http/tests/streams/transferable/worker-expected.txt
@@ -0,0 +1,8 @@
+CONSOLE ERROR: line 2: Uncaught TypeError: Failed to execute 'postMessage' on 'DedicatedWorkerGlobalScope': Value at index 0 is an untransferable 'null' value.
+CONSOLE ERROR: line 2: Uncaught TypeError: Failed to execute 'postMessage' on 'DedicatedWorkerGlobalScope': Value at index 0 is an untransferable 'null' value.
+This is a testharness.js-based test.
+FAIL worker.postMessage should be able to transfer a ReadableStream assert_true: the original stream should be locked expected true got false
+FAIL postMessage in a worker should be able to transfer a ReadableStream promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'constructor' of null"
+FAIL terminating a worker should not error the stream promise_test: Unhandled rejection with value: "error in worker"
+Harness: the test ran to completion.
+
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 16929ff..b7060e3 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
@@ -1399,6 +1399,11 @@
 [Worker]     getter bytesWritten
 [Worker]     getter status
 [Worker]     method constructor
+[Worker] interface UserActivation
+[Worker]     attribute @@toStringTag
+[Worker]     getter hasBeenActive
+[Worker]     getter isActive
+[Worker]     method constructor
 [Worker] interface WebGL2ComputeRenderingContext
 [Worker]     attribute @@toStringTag
 [Worker]     attribute ACTIVE_ATOMIC_COUNTER_BUFFERS
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 3bcd6c8..42307e0 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
@@ -1256,6 +1256,11 @@
 [Worker]     method sort
 [Worker]     method toString
 [Worker]     method values
+[Worker] interface UserActivation
+[Worker]     attribute @@toStringTag
+[Worker]     getter hasBeenActive
+[Worker]     getter isActive
+[Worker]     method constructor
 [Worker] interface WebGL2ComputeRenderingContext
 [Worker]     attribute @@toStringTag
 [Worker]     attribute ACTIVE_ATOMIC_COUNTER_BUFFERS
diff --git a/third_party/freetype/README.chromium b/third_party/freetype/README.chromium
index 3171e26..2b8faca 100644
--- a/third_party/freetype/README.chromium
+++ b/third_party/freetype/README.chromium
@@ -1,7 +1,7 @@
 Name: FreeType
 URL: http://www.freetype.org/
-Version: VER-2-10-0-56-g711b593e4
-Revision: 711b593e4b589fbd726a4962ad492fc4e416355d
+Version: VER-2-10-0-57-g7fde521bd
+Revision: 7fde521bd918d2299cce80c306ecc2cac9f51303
 License: Custom license "inspired by the BSD, Artistic, and IJG (Independent
          JPEG Group) licenses"
 License File: src/docs/FTL.TXT
diff --git a/third_party/zlib/BUILD.gn b/third_party/zlib/BUILD.gn
index 1a9cd3b..3b8e5e9f 100644
--- a/third_party/zlib/BUILD.gn
+++ b/third_party/zlib/BUILD.gn
@@ -89,7 +89,7 @@
   source_set("zlib_arm_crc32") {
     visibility = [ ":*" ]
 
-    if (is_clang && !is_ios) {
+    if (!is_ios) {
       include_dirs = [ "." ]
 
       if (is_android) {
@@ -101,6 +101,10 @@
         } else {
           assert(false, "CPU detection requires the Android NDK")
         }
+      } else if (!is_win && !is_clang) {
+        assert(!thin_lto_enable_optimizations,
+               "ThinLTO fails mixing different module-level targets")
+        cflags_c = [ "-march=armv8-a+crc" ]
       }
 
       sources = [
diff --git a/third_party/zlib/crc32_simd.c b/third_party/zlib/crc32_simd.c
index 03698adf..2fef610e 100644
--- a/third_party/zlib/crc32_simd.c
+++ b/third_party/zlib/crc32_simd.c
@@ -161,6 +161,7 @@
  * TODO: implement a version using the PMULL instruction.
  */
 
+#if defined(__clang__)
 /* CRC32 intrinsics are #ifdef'ed out of arm_acle.h unless we build with an
  * armv8 target, which is incompatible with ThinLTO optimizations on Android.
  * (Namely, mixing and matching different module-level targets makes ThinLTO
@@ -183,8 +184,18 @@
 
 #if defined(__aarch64__)
 #define TARGET_ARMV8_WITH_CRC __attribute__((target("crc")))
-#else
+#else  // !defined(__aarch64__)
 #define TARGET_ARMV8_WITH_CRC __attribute__((target("armv8-a,crc")))
+#endif  // defined(__aarch64__)
+
+#elif defined(__GNUC__)
+/* For GCC, we are setting CRC extensions at module level, so ThinLTO is not
+ * allowed. We can just include arm_acle.h.
+ */
+#include <arm_acle.h>
+#define TARGET_ARMV8_WITH_CRC
+#else  // !defined(__GNUC__) && !defined(_aarch64__)
+#error ARM CRC32 SIMD extensions only supported for Clang and GCC
 #endif
 
 TARGET_ARMV8_WITH_CRC
@@ -248,5 +259,4 @@
     return ret;
 }
 
-
 #endif
diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py
index 84455a1..a286652 100755
--- a/tools/clang/scripts/update.py
+++ b/tools/clang/scripts/update.py
@@ -55,7 +55,7 @@
                               'Release+Asserts')
 
 STAMP_FILE = os.path.normpath(
-    os.path.join(LLVM_BUILD_DIR, '..', 'cr_build_revision'))
+    os.path.join(LLVM_BUILD_DIR, 'cr_build_revision'))
 FORCE_HEAD_REVISION_FILE = os.path.normpath(os.path.join(LLVM_BUILD_DIR, '..',
                                                    'force_head_revision'))
 
@@ -248,8 +248,8 @@
   if ReadStampFile(STAMP_FILE) == expected_stamp:
     return 0
 
-  if os.path.exists(os.path.dirname(LLVM_BUILD_DIR)):
-    RmTree(os.path.dirname(LLVM_BUILD_DIR))
+  if os.path.exists(LLVM_BUILD_DIR):
+    RmTree(LLVM_BUILD_DIR)
 
   DownloadAndUnpackClangPackage(sys.platform, LLVM_BUILD_DIR)
   if 'win' in target_os:
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index db81257..e779ee5 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -3605,6 +3605,7 @@
 </action>
 
 <action name="BrowserActions.MenuOpened">
+  <obsolete>Deprecated in M77 with the removal of Browser Actions.</obsolete>
   <owner>ltian@chromium.org</owner>
   <description>
     A Browser Actions menu is opened in Chrome. A Browser Actions menu is a
@@ -3613,6 +3614,7 @@
 </action>
 
 <action name="BrowserActions.TabOpenedNotificationClicked">
+  <obsolete>Deprecated in M77 with the removal of Browser Actions.</obsolete>
   <owner>ltian@chromium.org</owner>
   <description>
     Users click the notification of opening tab in background.
@@ -3620,6 +3622,7 @@
 </action>
 
 <action name="BrowserActions.TabOpenedNotificationCreated">
+  <obsolete>Deprecated in M77 with the removal of Browser Actions.</obsolete>
   <owner>ltian@chromium.org</owner>
   <description>
     Browser Actions creates a notifcation of opening tab in background.
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index a31d5b8..12395ef 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -3925,6 +3925,13 @@
   <int value="10" label="All Bits"/>
 </enum>
 
+<enum name="AutofillPredictionSource">
+  <int value="0" label="PREDICTION_SOURCE_UNKNOWN"/>
+  <int value="1" label="PREDICTION_SOURCE_HEURISTIC"/>
+  <int value="2" label="PREDICTION_SOURCE_SERVER"/>
+  <int value="3" label="PREDICTION_SOURCE_OVERALL"/>
+</enum>
+
 <enum name="AutofillProfileAction">
   <int value="0" label="Existing profile used"/>
   <int value="1" label="Existing profile updated"/>
@@ -3940,6 +3947,12 @@
   <int value="3" label="Upload / conflict resolution in initial sync"/>
 </enum>
 
+<enum name="AutofillQualitiyMetricType">
+  <int value="0" label="TYPE_SUBMISSION"/>
+  <int value="1" label="TYPE_NO_SUBMISSION"/>
+  <int value="2" label="TYPE_AUTOCOMPLETE_BASED"/>
+</enum>
+
 <enum name="AutofillQuality">
   <int value="0" label="Submitted"/>
   <int value="1" label="Autofilled"/>
@@ -4017,6 +4030,91 @@
   <int value="2" label="Some other item selected"/>
 </enum>
 
+<enum name="AutofillServerFieldType">
+  <int value="0" label="NO_SERVER_DATA"/>
+  <int value="1" label="UNKNOWN_TYPE"/>
+  <int value="2" label="EMPTY_TYPE"/>
+  <int value="3" label="NAME_FIRST"/>
+  <int value="4" label="NAME_MIDDLE"/>
+  <int value="5" label="NAME_LAST"/>
+  <int value="6" label="NAME_MIDDLE_INITIAL"/>
+  <int value="7" label="NAME_FULL"/>
+  <int value="8" label="NAME_SUFFIX"/>
+  <int value="9" label="EMAIL_ADDRESS"/>
+  <int value="10" label="PHONE_HOME_NUMBER"/>
+  <int value="11" label="PHONE_HOME_CITY_CODE"/>
+  <int value="12" label="PHONE_HOME_COUNTRY_CODE"/>
+  <int value="13" label="PHONE_HOME_CITY_AND_NUMBER"/>
+  <int value="14" label="PHONE_HOME_WHOLE_NUMBER"/>
+  <int value="20" label="PHONE_FAX_NUMBER"/>
+  <int value="21" label="PHONE_FAX_CITY_CODE"/>
+  <int value="22" label="PHONE_FAX_COUNTRY_CODE"/>
+  <int value="23" label="PHONE_FAX_CITY_AND_NUMBER"/>
+  <int value="24" label="PHONE_FAX_WHOLE_NUMBER"/>
+  <int value="30" label="ADDRESS_HOME_LINE1"/>
+  <int value="31" label="ADDRESS_HOME_LINE2"/>
+  <int value="32" label="ADDRESS_HOME_APT_NUM"/>
+  <int value="33" label="ADDRESS_HOME_CITY"/>
+  <int value="34" label="ADDRESS_HOME_STATE"/>
+  <int value="35" label="ADDRESS_HOME_ZIP"/>
+  <int value="36" label="ADDRESS_HOME_COUNTRY"/>
+  <int value="37" label="ADDRESS_BILLING_LINE1"/>
+  <int value="38" label="ADDRESS_BILLING_LINE2"/>
+  <int value="39" label="ADDRESS_BILLING_APT_NUM"/>
+  <int value="40" label="ADDRESS_BILLING_CITY"/>
+  <int value="41" label="ADDRESS_BILLING_STATE"/>
+  <int value="42" label="ADDRESS_BILLING_ZIP"/>
+  <int value="43" label="ADDRESS_BILLING_COUNTRY"/>
+  <int value="51" label="CREDIT_CARD_NAME_FULL"/>
+  <int value="52" label="CREDIT_CARD_NUMBER"/>
+  <int value="53" label="CREDIT_CARD_EXP_MONTH"/>
+  <int value="54" label="CREDIT_CARD_EXP_2_DIGIT_YEAR"/>
+  <int value="55" label="CREDIT_CARD_EXP_4_DIGIT_YEAR"/>
+  <int value="56" label="CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR"/>
+  <int value="57" label="CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR"/>
+  <int value="58" label="CREDIT_CARD_TYPE"/>
+  <int value="59" label="CREDIT_CARD_VERIFICATION_CODE"/>
+  <int value="60" label="COMPANY_NAME"/>
+  <int value="61" label="FIELD_WITH_DEFAULT_VALUE"/>
+  <int value="62" label="PHONE_BILLING_NUMBER"/>
+  <int value="63" label="PHONE_BILLING_CITY_CODE"/>
+  <int value="64" label="PHONE_BILLING_COUNTRY_CODE"/>
+  <int value="65" label="PHONE_BILLING_CITY_AND_NUMBER"/>
+  <int value="66" label="PHONE_BILLING_WHOLE_NUMBER"/>
+  <int value="67" label="NAME_BILLING_FIRST"/>
+  <int value="68" label="NAME_BILLING_MIDDLE"/>
+  <int value="69" label="NAME_BILLING_LAST"/>
+  <int value="70" label="NAME_BILLING_MIDDLE_INITIAL"/>
+  <int value="71" label="NAME_BILLING_FULL"/>
+  <int value="72" label="NAME_BILLING_SUFFIX"/>
+  <int value="73" label="MERCHANT_EMAIL_SIGNUP"/>
+  <int value="74" label="MERCHANT_PROMO_CODE"/>
+  <int value="75" label="PASSWORD"/>
+  <int value="76" label="ACCOUNT_CREATION_PASSWORD"/>
+  <int value="77" label="ADDRESS_HOME_STREET_ADDRESS"/>
+  <int value="78" label="ADDRESS_BILLING_STREET_ADDRESS"/>
+  <int value="79" label="ADDRESS_HOME_SORTING_CODE"/>
+  <int value="80" label="ADDRESS_BILLING_SORTING_CODE"/>
+  <int value="81" label="ADDRESS_HOME_DEPENDENT_LOCALITY"/>
+  <int value="82" label="ADDRESS_BILLING_DEPENDENT_LOCALITY"/>
+  <int value="83" label="ADDRESS_HOME_LINE3"/>
+  <int value="84" label="ADDRESS_BILLING_LINE3"/>
+  <int value="85" label="NOT_ACCOUNT_CREATION_PASSWORD"/>
+  <int value="86" label="USERNAME"/>
+  <int value="87" label="USERNAME_AND_EMAIL_ADDRESS"/>
+  <int value="88" label="NEW_PASSWORD"/>
+  <int value="89" label="PROBABLY_NEW_PASSWORD"/>
+  <int value="90" label="NOT_NEW_PASSWORD"/>
+  <int value="91" label="CREDIT_CARD_NAME_FIRST"/>
+  <int value="92" label="CREDIT_CARD_NAME_LAST"/>
+  <int value="93" label="PHONE_HOME_EXTENSION"/>
+  <int value="95" label="CONFIRMATION_PASSWORD"/>
+  <int value="96" label="AMBIGUOUS_TYPE"/>
+  <int value="97" label="SEARCH_TERM"/>
+  <int value="98" label="PRICE"/>
+  <int value="99" label="NOT_PASSWORD"/>
+</enum>
+
 <enum name="AutofillSessionStates">
   <int value="0" label="Unknown"/>
   <int value="1" label="No callback from framework"/>
@@ -6491,6 +6589,9 @@
 </enum>
 
 <enum name="BrowserActionsMenuOption">
+  <obsolete>
+    Deprecated in M77 with the removal of Browser Actions.
+  </obsolete>
   <int value="0" label="Open in new Chrome tab"/>
   <int value="1" label="Open in incognito tab"/>
   <int value="2" label="Download page"/>
@@ -33850,6 +33951,7 @@
       label="SupervisedUserCommittedInterstitials:enabled"/>
   <int value="-1096595907" label="disable-new-virtual-keyboard-behavior"/>
   <int value="-1095947169" label="ModalPermissionDialogView:disabled"/>
+  <int value="-1093104008" label="PeriodicBackgroundSync:disabled"/>
   <summary>Chrome flags that lead to Chrome restart on Chrome OS.</summary>
 <!--
 Values in LoginCustomFlags are:  value=(uint32_t)MD5(label).
@@ -34000,6 +34102,7 @@
   <int value="-876148583" label="ArcBootCompletedBroadcast:disabled"/>
   <int value="-874602599" label="HorizontalTabSwitcherAndroid:enabled"/>
   <int value="-872764392" label="ContextualSuggestionsBottomSheet:disabled"/>
+  <int value="-872302695" label="PeriodicBackgroundSync:enabled"/>
   <int value="-867087281" label="enable-virtual-keyboard"/>
   <int value="-866993841" label="OfflinePagesCTV2:disabled"/>
   <int value="-864266073" label="cros-regions-mode"/>
@@ -53114,8 +53217,8 @@
   <int value="1" label="TokenService::LoadCredentials"/>
   <int value="2" label="SupervisedUser::InitSync"/>
   <int value="3" label="InlineLoginHandler::Signin"/>
-  <int value="4" label="SigninManager::ClearPrimaryAccount"/>
-  <int value="5" label="SigninManager::LegacyPreDiceSigninFlow"/>
+  <int value="4" label="PrimaryAccountManager::ClearPrimaryAccount"/>
+  <int value="5" label="PrimaryAccountManager::LegacyPreDiceSigninFlow"/>
   <int value="6" label="UserMenu:RemoveAccount"/>
   <int value="7" label="UserMenu::SignOutAllAccounts"/>
   <int value="8" label="Settings::Signout"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index bc0b86d..32edc27 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -15277,6 +15277,9 @@
 </histogram>
 
 <histogram name="BrowserActions.NumTabCreatedInBackground" units="tabNum">
+  <obsolete>
+    Deprecated in M77 with the removal of Browser Actions.
+  </obsolete>
   <owner>peconn@chromium.org</owner>
   <summary>
     The number of tabs currently opened when users tap &quot;Open in new Chrome
@@ -15286,6 +15289,9 @@
 </histogram>
 
 <histogram name="BrowserActions.SelectedOption" enum="BrowserActionsMenuOption">
+  <obsolete>
+    Deprecated in M77 with the removal of Browser Actions.
+  </obsolete>
   <owner>peconn@chromium.org</owner>
   <summary>
     The option that the user selected from a Browser Actions context menu.
@@ -15470,6 +15476,19 @@
 </histogram>
 
 <histogram name="BrowserServices.TwaOpenTime" units="ms" expires_after="M78">
+  <obsolete>
+    Retired in M77 in favour of BrowserServices.TwaOpenTime.V2 which uses a more
+    appropriate timescale.
+  </obsolete>
+  <owner>peconn@chromium.org</owner>
+  <owner>peter@chromium.org</owner>
+  <summary>
+    Triggered when a TrustedWebActivity is paused, recording the time since it
+    had been resumed.
+  </summary>
+</histogram>
+
+<histogram name="BrowserServices.TwaOpenTime.V2" units="ms" expires_after="M82">
   <owner>peconn@chromium.org</owner>
   <owner>peter@chromium.org</owner>
   <summary>
@@ -115353,6 +115372,19 @@
   </summary>
 </histogram>
 
+<histogram name="SendTabToSelf.AndroidShareSheet.ClickResult"
+    enum="SendTabToSelfNotification" expires_after="M78">
+  <owner>tgupta@chromium.org</owner>
+  <summary>
+    The use of Android notification for SendTabToSelf.
+
+    These notifications are tied to a sync type so there is a distinction
+    between user initiated actions (Opened, Dismissed) and actions that are
+    initiated by changes to the sync model or Android (Shown,
+    DismissedRemotely).
+  </summary>
+</histogram>
+
 <histogram base="true" name="SendTabToSelf.ClickResult"
     enum="SendTabToSelfClickResult" expires_after="M78">
   <owner>jeffreycohen@chromium.org</owner>
@@ -134427,6 +134459,21 @@
 </histogram>
 
 <histogram name="TrustedWebActivity.TimeInVerifiedOrigin" units="ms"
+    expires_after="M82">
+  <obsolete>
+    Retired in M77 in favour of TrustedWebActivity.TimeInVerifiedOrigin.V2 which
+    uses a more appropriate timescale.
+  </obsolete>
+  <owner>pshmakov@chromium.org</owner>
+  <owner>peconn@chromium.org</owner>
+  <owner>peter@chromium.org</owner>
+  <summary>
+    Time spent in a verified origin until navigating to an unverified one or
+    pausing the Trusted Web Activity.
+  </summary>
+</histogram>
+
+<histogram name="TrustedWebActivity.TimeInVerifiedOrigin.V2" units="ms"
     expires_after="M78">
   <owner>pshmakov@chromium.org</owner>
   <owner>peconn@chromium.org</owner>
@@ -134438,6 +134485,21 @@
 </histogram>
 
 <histogram name="TrustedWebActivity.TimeOutOfVerifiedOrigin" units="ms"
+    expires_after="M82">
+  <obsolete>
+    Retired in M77 in favour of TrustedWebActivity.TimeOutOfVerifiedOrigin.V2
+    which uses a more appropriate timescale.
+  </obsolete>
+  <owner>pshmakov@chromium.org</owner>
+  <owner>peconn@chromium.org</owner>
+  <owner>peter@chromium.org</owner>
+  <summary>
+    Time spent out of verified origins until navigating back to a verified one
+    or pausing the Trusted Web Activity.
+  </summary>
+</histogram>
+
+<histogram name="TrustedWebActivity.TimeOutOfVerifiedOrigin.V2" units="ms"
     expires_after="M78">
   <owner>pshmakov@chromium.org</owner>
   <owner>peconn@chromium.org</owner>
diff --git a/tools/metrics/rappor/rappor.xml b/tools/metrics/rappor/rappor.xml
index 68ad6632..e9dd2738 100644
--- a/tools/metrics/rappor/rappor.xml
+++ b/tools/metrics/rappor/rappor.xml
@@ -297,6 +297,9 @@
 
 <rappor-metric name="BrowserActions.ServiceClient.PackageName"
     type="UMA_RAPPOR_TYPE">
+  <obsolete>
+    Deprecated in M77 with the removal of Browser Actions.
+  </obsolete>
   <owner>ltian@chromium.org</owner>
   <summary>
     The package name for a client that requests for the Browser Actions context
@@ -306,6 +309,9 @@
 
 <rappor-metric name="BrowserActions.ServiceClient.PackageNameThirdParty"
     type="UMA_RAPPOR_TYPE">
+  <obsolete>
+    Deprecated in M77 with the removal of Browser Actions.
+  </obsolete>
   <owner>ltian@chromium.org</owner>
   <summary>
     The package name for a client that requests for the Browser Actions context
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml
index 430d7e4..a6a4564 100644
--- a/tools/metrics/ukm/ukm.xml
+++ b/tools/metrics/ukm/ukm.xml
@@ -725,10 +725,19 @@
     Recorded when Chrome validates field type predictions (on submit, on leaving
     a form, on receiving a form with autocomplete attributes).
   </summary>
-  <metric name="ActualType">
+  <metric name="ActualType" enum="AutofillServerFieldType">
     <summary>
       The observed type of the field. See: autofill::ServerFieldType
     </summary>
+    <aggregation>
+      <history>
+        <index fields="metrics.PredictedType"/>
+        <index fields="metrics.PredictionSource,metrics.PredictedType"/>
+        <statistics>
+          <enumeration/>
+        </statistics>
+      </history>
+    </aggregation>
   </metric>
   <metric name="FieldSignature">
     <summary>
@@ -744,22 +753,53 @@
     <summary>
       Time since form parse.
     </summary>
+    <aggregation>
+      <history>
+        <index fields="metrics.ValidationEvent"/>
+        <statistics>
+          <quantiles type="std-percentiles"/>
+        </statistics>
+      </history>
+    </aggregation>
   </metric>
-  <metric name="PredictedType">
+  <metric name="PredictedType" enum="AutofillServerFieldType">
     <summary>
       The predicted type of the field. See: autofill::ServerFieldType
     </summary>
+    <aggregation>
+      <history>
+        <index fields="metrics.ActualType"/>
+        <index fields="metrics.ActualType,metrics.PredictionSource"/>
+        <statistics>
+          <enumeration/>
+        </statistics>
+      </history>
+    </aggregation>
   </metric>
-  <metric name="PredictionSource">
+  <metric name="PredictionSource" enum="AutofillPredictionSource">
     <summary>
       The system which generated the prediction: heuristics, server, overall.
     </summary>
+    <aggregation>
+      <history>
+        <statistics export="False">
+          <enumeration/>
+        </statistics>
+      </history>
+    </aggregation>
   </metric>
-  <metric name="ValidationEvent">
+  <metric name="ValidationEvent" enum="AutofillQualitiyMetricType">
     <summary>
       The event which triggered the validation: Submission, Left Form, Form has
       Autocomplete attributes.
     </summary>
+    <aggregation>
+      <history>
+        <statistics>
+          <enumeration/>
+        </statistics>
+      </history>
+    </aggregation>
   </metric>
 </event>
 
diff --git a/tools/perf/cli_tools/soundwave/studies/health_study.py b/tools/perf/cli_tools/soundwave/studies/health_study.py
index ba2d8385..f00115b 100644
--- a/tools/perf/cli_tools/soundwave/studies/health_study.py
+++ b/tools/perf/cli_tools/soundwave/studies/health_study.py
@@ -29,6 +29,8 @@
 def IterSystemHealthBots():
   yield 'ChromiumPerf/android-go-perf'
   yield 'ChromiumPerf/android-go_webview-perf'
+  yield 'ChromiumPerf/android-pixel2-perf'
+  yield 'ChromiumPerf/android-pixel2_webview-perf'
 
 
 def GetBrowserFromBot(bot):
diff --git a/tools/perf/page_sets/data/system_health_desktop.json b/tools/perf/page_sets/data/system_health_desktop.json
index f6d79f7..fcdf7dd 100644
--- a/tools/perf/page_sets/data/system_health_desktop.json
+++ b/tools/perf/page_sets/data/system_health_desktop.json
@@ -6,6 +6,9 @@
         "browse:media:googleplaystore:2018": {
             "DEFAULT": "system_health_desktop_ea41d8bc49.wprgo"
         },
+        "browse:media:googleplaystore:2018_oop_raster_disabled": {
+            "DEFAULT": "system_health_desktop_ea41d8bc49.wprgo"
+        },
         "browse:media:imgur": {
             "DEFAULT": "system_health_desktop_025.wprgo"
         },
diff --git a/tools/perf/page_sets/system_health/browsing_stories.py b/tools/perf/page_sets/system_health/browsing_stories.py
index 1ad3b0c..5994b44 100644
--- a/tools/perf/page_sets/system_health/browsing_stories.py
+++ b/tools/perf/page_sets/system_health/browsing_stories.py
@@ -768,6 +768,14 @@
     action_runner.Wait(2)
     action_runner.ScrollPage()
 
+  def __init__(self, story_set, take_memory_measurement,
+               extra_browser_args=None, name_suffix=''):
+    self.NAME = self.NAME + name_suffix
+    super(GooglePlayStoreDesktopStory, self).__init__(story_set,
+      take_memory_measurement,
+      extra_browser_args=extra_browser_args)
+
+
 
 ##############################################################################
 # Emerging market browsing stories.
diff --git a/tools/perf/page_sets/system_health/system_health_stories.py b/tools/perf/page_sets/system_health/system_health_stories.py
index 1d087fb..d19f458 100644
--- a/tools/perf/page_sets/system_health/system_health_stories.py
+++ b/tools/perf/page_sets/system_health/system_health_stories.py
@@ -7,6 +7,7 @@
 from page_sets.system_health import chrome_stories
 from page_sets.system_health import platforms
 from page_sets.system_health import system_health_story
+from page_sets.system_health import browsing_stories
 
 from telemetry import story
 
@@ -32,6 +33,16 @@
         continue
       self.AddStory(story_class(self, take_memory_measurement))
 
+    # TODO(crbug.com/968125): Stop avoiding OOPR once YUV OOPR is in place.
+    if platform in platforms.DESKTOP:
+      self.AddStory(
+        browsing_stories.GooglePlayStoreDesktopStory(
+          self, take_memory_measurement,
+          extra_browser_args=['--force-gpu-rasterization',
+                              '--enable-gpu-rasterization',
+                              '--disable-oop-rasterization'],
+          name_suffix="_oop_raster_disabled"))
+
 
 class SystemHealthBlankStorySet(story.StorySet):
   """A story set containing the chrome:blank story only."""
diff --git a/ui/base/ime/linux/input_method_auralinux.cc b/ui/base/ime/linux/input_method_auralinux.cc
index ae5043c..45066f81 100644
--- a/ui/base/ime/linux/input_method_auralinux.cc
+++ b/ui/base/ime/linux/input_method_auralinux.cc
@@ -29,6 +29,9 @@
       is_sync_mode_(false),
       composition_changed_(false),
       weak_ptr_factory_(this) {
+  DCHECK(LinuxInputMethodContextFactory::instance())
+      << "Trying to initialize InputMethodAuraLinux, but "
+         "LinuxInputMethodContextFactory is not initialized yet.";
   context_ =
       LinuxInputMethodContextFactory::instance()->CreateInputMethodContext(
           this, false);
diff --git a/ui/gfx/linux/native_pixmap_dmabuf.cc b/ui/gfx/linux/native_pixmap_dmabuf.cc
index 074c67c..e0417c0 100644
--- a/ui/gfx/linux/native_pixmap_dmabuf.cc
+++ b/ui/gfx/linux/native_pixmap_dmabuf.cc
@@ -43,6 +43,11 @@
   return handle_.planes[plane].offset;
 }
 
+size_t NativePixmapDmaBuf::GetDmaBufPlaneSize(size_t plane) const {
+  DCHECK_LT(plane, handle_.planes.size());
+  return static_cast<size_t>(handle_.planes[plane].size);
+}
+
 uint64_t NativePixmapDmaBuf::GetBufferFormatModifier() const {
   return handle_.modifier;
 }
diff --git a/ui/gfx/linux/native_pixmap_dmabuf.h b/ui/gfx/linux/native_pixmap_dmabuf.h
index 2033abb0..cd0c665 100644
--- a/ui/gfx/linux/native_pixmap_dmabuf.h
+++ b/ui/gfx/linux/native_pixmap_dmabuf.h
@@ -32,6 +32,7 @@
   int GetDmaBufFd(size_t plane) const override;
   int GetDmaBufPitch(size_t plane) const override;
   int GetDmaBufOffset(size_t plane) const override;
+  size_t GetDmaBufPlaneSize(size_t plane) const override;
   uint64_t GetBufferFormatModifier() const override;
   gfx::BufferFormat GetBufferFormat() const override;
   gfx::Size GetBufferSize() const override;
diff --git a/ui/gfx/linux/native_pixmap_dmabuf_unittest.cc b/ui/gfx/linux/native_pixmap_dmabuf_unittest.cc
index ba10edee..bf9d2cc 100644
--- a/ui/gfx/linux/native_pixmap_dmabuf_unittest.cc
+++ b/ui/gfx/linux/native_pixmap_dmabuf_unittest.cc
@@ -68,6 +68,8 @@
               handle_clone.planes[i].stride);
     EXPECT_EQ(native_pixmap_dmabuf->GetDmaBufOffset(i),
               handle_clone.planes[i].offset);
+    EXPECT_EQ(native_pixmap_dmabuf->GetDmaBufPlaneSize(i),
+              static_cast<size_t>(handle_clone.planes[i].size));
   }
 }
 
diff --git a/ui/gfx/mojo/struct_traits_unittest.cc b/ui/gfx/mojo/struct_traits_unittest.cc
index d0102eb..9f5d471c 100644
--- a/ui/gfx/mojo/struct_traits_unittest.cc
+++ b/ui/gfx/mojo/struct_traits_unittest.cc
@@ -4,7 +4,7 @@
 
 #include <utility>
 
-#include "base/message_loop/message_loop.h"
+#include "base/test/scoped_task_environment.h"
 #include "build/build_config.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "mojo/public/cpp/test_support/test_utils.h"
@@ -64,7 +64,7 @@
     std::move(callback).Run(r);
   }
 
-  base::MessageLoop loop_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
   mojo::BindingSet<TraitsTestService> traits_test_bindings_;
 
   DISALLOW_COPY_AND_ASSIGN(StructTraitsTest);
diff --git a/ui/gfx/native_pixmap.h b/ui/gfx/native_pixmap.h
index 7446359..9c7d52f75 100644
--- a/ui/gfx/native_pixmap.h
+++ b/ui/gfx/native_pixmap.h
@@ -29,6 +29,7 @@
   virtual int GetDmaBufFd(size_t plane) const = 0;
   virtual int GetDmaBufPitch(size_t plane) const = 0;
   virtual int GetDmaBufOffset(size_t plane) const = 0;
+  virtual size_t GetDmaBufPlaneSize(size_t plane) const = 0;
 
   // The following methods return format, modifier and size of the buffer,
   // respectively.
diff --git a/ui/gl/egl_bindings_autogen_mock.cc b/ui/gl/egl_bindings_autogen_mock.cc
index 5cfcad5c..81dd3b7 100644
--- a/ui/gl/egl_bindings_autogen_mock.cc
+++ b/ui/gl/egl_bindings_autogen_mock.cc
@@ -412,6 +412,14 @@
 }
 
 EGLBoolean GL_BINDING_CALL
+MockEGLInterface::Mock_eglQueryDisplayAttribANGLE(EGLDisplay dpy,
+                                                  EGLint attribute,
+                                                  EGLAttrib* value) {
+  MakeEglMockFunctionUnique("eglQueryDisplayAttribANGLE");
+  return interface_->QueryDisplayAttribANGLE(dpy, attribute, value);
+}
+
+EGLBoolean GL_BINDING_CALL
 MockEGLInterface::Mock_eglQueryStreamKHR(EGLDisplay dpy,
                                          EGLStreamKHR stream,
                                          EGLenum attribute,
@@ -435,6 +443,14 @@
   return interface_->QueryString(dpy, name);
 }
 
+const char* GL_BINDING_CALL
+MockEGLInterface::Mock_eglQueryStringiANGLE(EGLDisplay dpy,
+                                            EGLint name,
+                                            EGLint index) {
+  MakeEglMockFunctionUnique("eglQueryStringiANGLE");
+  return interface_->QueryStringiANGLE(dpy, name, index);
+}
+
 EGLBoolean GL_BINDING_CALL
 MockEGLInterface::Mock_eglQuerySurface(EGLDisplay dpy,
                                        EGLSurface surface,
@@ -700,12 +716,17 @@
     return reinterpret_cast<GLFunctionPointerType>(Mock_eglQueryContext);
   if (strcmp(name, "eglQueryDebugKHR") == 0)
     return reinterpret_cast<GLFunctionPointerType>(Mock_eglQueryDebugKHR);
+  if (strcmp(name, "eglQueryDisplayAttribANGLE") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(
+        Mock_eglQueryDisplayAttribANGLE);
   if (strcmp(name, "eglQueryStreamKHR") == 0)
     return reinterpret_cast<GLFunctionPointerType>(Mock_eglQueryStreamKHR);
   if (strcmp(name, "eglQueryStreamu64KHR") == 0)
     return reinterpret_cast<GLFunctionPointerType>(Mock_eglQueryStreamu64KHR);
   if (strcmp(name, "eglQueryString") == 0)
     return reinterpret_cast<GLFunctionPointerType>(Mock_eglQueryString);
+  if (strcmp(name, "eglQueryStringiANGLE") == 0)
+    return reinterpret_cast<GLFunctionPointerType>(Mock_eglQueryStringiANGLE);
   if (strcmp(name, "eglQuerySurface") == 0)
     return reinterpret_cast<GLFunctionPointerType>(Mock_eglQuerySurface);
   if (strcmp(name, "eglQuerySurfacePointerANGLE") == 0)
diff --git a/ui/gl/egl_bindings_autogen_mock.h b/ui/gl/egl_bindings_autogen_mock.h
index 24ccde5..aee9dea 100644
--- a/ui/gl/egl_bindings_autogen_mock.h
+++ b/ui/gl/egl_bindings_autogen_mock.h
@@ -181,6 +181,10 @@
                                                        EGLint* value);
 static EGLBoolean GL_BINDING_CALL Mock_eglQueryDebugKHR(EGLint attribute,
                                                         EGLAttrib* value);
+static EGLBoolean GL_BINDING_CALL
+Mock_eglQueryDisplayAttribANGLE(EGLDisplay dpy,
+                                EGLint attribute,
+                                EGLAttrib* value);
 static EGLBoolean GL_BINDING_CALL Mock_eglQueryStreamKHR(EGLDisplay dpy,
                                                          EGLStreamKHR stream,
                                                          EGLenum attribute,
@@ -192,6 +196,9 @@
                           EGLuint64KHR* value);
 static const char* GL_BINDING_CALL Mock_eglQueryString(EGLDisplay dpy,
                                                        EGLint name);
+static const char* GL_BINDING_CALL Mock_eglQueryStringiANGLE(EGLDisplay dpy,
+                                                             EGLint name,
+                                                             EGLint index);
 static EGLBoolean GL_BINDING_CALL Mock_eglQuerySurface(EGLDisplay dpy,
                                                        EGLSurface surface,
                                                        EGLint attribute,
diff --git a/ui/gl/generate_bindings.py b/ui/gl/generate_bindings.py
index ce909e2..6af504d 100755
--- a/ui/gl/generate_bindings.py
+++ b/ui/gl/generate_bindings.py
@@ -2430,6 +2430,10 @@
                  'client_extensions': ['EGL_KHR_debug'], }],
   'arguments': 'EGLint attribute, EGLAttrib* value', },
 { 'return_type': 'EGLBoolean',
+  'versions': [{ 'name': 'eglQueryDisplayAttribANGLE',
+                 'extensions': ['EGL_ANGLE_feature_control'] }],
+  'arguments': 'EGLDisplay dpy, EGLint attribute, EGLAttrib* value' },
+{ 'return_type': 'EGLBoolean',
   'versions': [{ 'name': 'eglQueryStreamKHR',
                  'extensions': ['EGL_KHR_stream'] }],
   'arguments':
@@ -2444,6 +2448,10 @@
 { 'return_type': 'const char*',
   'names': ['eglQueryString'],
   'arguments': 'EGLDisplay dpy, EGLint name', },
+{ 'return_type': 'const char *',
+  'versions': [{ 'name': 'eglQueryStringiANGLE',
+                 'extensions': ['EGL_ANGLE_feature_control'] }],
+  'arguments': 'EGLDisplay dpy, EGLint name, EGLint index' },
 { 'return_type': 'EGLBoolean',
   'names': ['eglQuerySurface'],
   'arguments':
@@ -2776,6 +2784,7 @@
     ],
     [
       'EGL_ANGLE_d3d_share_handle_client_buffer',
+      'EGL_ANGLE_feature_control',
       'EGL_ANGLE_surface_d3d_texture_2d_share_handle',
     ],
   ],
diff --git a/ui/gl/gl_bindings_api_autogen_egl.h b/ui/gl/gl_bindings_api_autogen_egl.h
index 7b033d0..ea1e59a 100644
--- a/ui/gl/gl_bindings_api_autogen_egl.h
+++ b/ui/gl/gl_bindings_api_autogen_egl.h
@@ -156,6 +156,9 @@
                              EGLint attribute,
                              EGLint* value) override;
 EGLBoolean eglQueryDebugKHRFn(EGLint attribute, EGLAttrib* value) override;
+EGLBoolean eglQueryDisplayAttribANGLEFn(EGLDisplay dpy,
+                                        EGLint attribute,
+                                        EGLAttrib* value) override;
 EGLBoolean eglQueryStreamKHRFn(EGLDisplay dpy,
                                EGLStreamKHR stream,
                                EGLenum attribute,
@@ -165,6 +168,9 @@
                                   EGLenum attribute,
                                   EGLuint64KHR* value) override;
 const char* eglQueryStringFn(EGLDisplay dpy, EGLint name) override;
+const char* eglQueryStringiANGLEFn(EGLDisplay dpy,
+                                   EGLint name,
+                                   EGLint index) override;
 EGLBoolean eglQuerySurfaceFn(EGLDisplay dpy,
                              EGLSurface surface,
                              EGLint attribute,
diff --git a/ui/gl/gl_bindings_autogen_egl.cc b/ui/gl/gl_bindings_autogen_egl.cc
index 42f12de..565d5438 100644
--- a/ui/gl/gl_bindings_autogen_egl.cc
+++ b/ui/gl/gl_bindings_autogen_egl.cc
@@ -157,6 +157,8 @@
       gfx::HasExtension(extensions, "EGL_ANDROID_native_fence_sync");
   ext.b_EGL_ANGLE_d3d_share_handle_client_buffer =
       gfx::HasExtension(extensions, "EGL_ANGLE_d3d_share_handle_client_buffer");
+  ext.b_EGL_ANGLE_feature_control =
+      gfx::HasExtension(extensions, "EGL_ANGLE_feature_control");
   ext.b_EGL_ANGLE_query_surface_pointer =
       gfx::HasExtension(extensions, "EGL_ANGLE_query_surface_pointer");
   ext.b_EGL_ANGLE_stream_producer_d3d_texture =
@@ -283,6 +285,12 @@
         GetGLProcAddress("eglPostSubBufferNV"));
   }
 
+  if (ext.b_EGL_ANGLE_feature_control) {
+    fn.eglQueryDisplayAttribANGLEFn =
+        reinterpret_cast<eglQueryDisplayAttribANGLEProc>(
+            GetGLProcAddress("eglQueryDisplayAttribANGLE"));
+  }
+
   if (ext.b_EGL_KHR_stream) {
     fn.eglQueryStreamKHRFn = reinterpret_cast<eglQueryStreamKHRProc>(
         GetGLProcAddress("eglQueryStreamKHR"));
@@ -293,6 +301,11 @@
         GetGLProcAddress("eglQueryStreamu64KHR"));
   }
 
+  if (ext.b_EGL_ANGLE_feature_control) {
+    fn.eglQueryStringiANGLEFn = reinterpret_cast<eglQueryStringiANGLEProc>(
+        GetGLProcAddress("eglQueryStringiANGLE"));
+  }
+
   if (ext.b_EGL_ANGLE_query_surface_pointer) {
     fn.eglQuerySurfacePointerANGLEFn =
         reinterpret_cast<eglQuerySurfacePointerANGLEProc>(
@@ -662,6 +675,12 @@
   return driver_->fn.eglQueryDebugKHRFn(attribute, value);
 }
 
+EGLBoolean EGLApiBase::eglQueryDisplayAttribANGLEFn(EGLDisplay dpy,
+                                                    EGLint attribute,
+                                                    EGLAttrib* value) {
+  return driver_->fn.eglQueryDisplayAttribANGLEFn(dpy, attribute, value);
+}
+
 EGLBoolean EGLApiBase::eglQueryStreamKHRFn(EGLDisplay dpy,
                                            EGLStreamKHR stream,
                                            EGLenum attribute,
@@ -680,6 +699,12 @@
   return driver_->fn.eglQueryStringFn(dpy, name);
 }
 
+const char* EGLApiBase::eglQueryStringiANGLEFn(EGLDisplay dpy,
+                                               EGLint name,
+                                               EGLint index) {
+  return driver_->fn.eglQueryStringiANGLEFn(dpy, name, index);
+}
+
 EGLBoolean EGLApiBase::eglQuerySurfaceFn(EGLDisplay dpy,
                                          EGLSurface surface,
                                          EGLint attribute,
@@ -1160,6 +1185,13 @@
   return egl_api_->eglQueryDebugKHRFn(attribute, value);
 }
 
+EGLBoolean TraceEGLApi::eglQueryDisplayAttribANGLEFn(EGLDisplay dpy,
+                                                     EGLint attribute,
+                                                     EGLAttrib* value) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::eglQueryDisplayAttribANGLE")
+  return egl_api_->eglQueryDisplayAttribANGLEFn(dpy, attribute, value);
+}
+
 EGLBoolean TraceEGLApi::eglQueryStreamKHRFn(EGLDisplay dpy,
                                             EGLStreamKHR stream,
                                             EGLenum attribute,
@@ -1181,6 +1213,13 @@
   return egl_api_->eglQueryStringFn(dpy, name);
 }
 
+const char* TraceEGLApi::eglQueryStringiANGLEFn(EGLDisplay dpy,
+                                                EGLint name,
+                                                EGLint index) {
+  TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::eglQueryStringiANGLE")
+  return egl_api_->eglQueryStringiANGLEFn(dpy, name, index);
+}
+
 EGLBoolean TraceEGLApi::eglQuerySurfaceFn(EGLDisplay dpy,
                                           EGLSurface surface,
                                           EGLint attribute,
@@ -1889,6 +1928,18 @@
   return result;
 }
 
+EGLBoolean DebugEGLApi::eglQueryDisplayAttribANGLEFn(EGLDisplay dpy,
+                                                     EGLint attribute,
+                                                     EGLAttrib* value) {
+  GL_SERVICE_LOG("eglQueryDisplayAttribANGLE"
+                 << "(" << dpy << ", " << attribute << ", "
+                 << static_cast<const void*>(value) << ")");
+  EGLBoolean result =
+      egl_api_->eglQueryDisplayAttribANGLEFn(dpy, attribute, value);
+  GL_SERVICE_LOG("GL_RESULT: " << result);
+  return result;
+}
+
 EGLBoolean DebugEGLApi::eglQueryStreamKHRFn(EGLDisplay dpy,
                                             EGLStreamKHR stream,
                                             EGLenum attribute,
@@ -1923,6 +1974,16 @@
   return result;
 }
 
+const char* DebugEGLApi::eglQueryStringiANGLEFn(EGLDisplay dpy,
+                                                EGLint name,
+                                                EGLint index) {
+  GL_SERVICE_LOG("eglQueryStringiANGLE"
+                 << "(" << dpy << ", " << name << ", " << index << ")");
+  const char* result = egl_api_->eglQueryStringiANGLEFn(dpy, name, index);
+  GL_SERVICE_LOG("GL_RESULT: " << result);
+  return result;
+}
+
 EGLBoolean DebugEGLApi::eglQuerySurfaceFn(EGLDisplay dpy,
                                           EGLSurface surface,
                                           EGLint attribute,
diff --git a/ui/gl/gl_bindings_autogen_egl.h b/ui/gl/gl_bindings_autogen_egl.h
index 4ff1248..4858e1c 100644
--- a/ui/gl/gl_bindings_autogen_egl.h
+++ b/ui/gl/gl_bindings_autogen_egl.h
@@ -191,6 +191,10 @@
                                                          EGLint* value);
 typedef EGLBoolean(GL_BINDING_CALL* eglQueryDebugKHRProc)(EGLint attribute,
                                                           EGLAttrib* value);
+typedef EGLBoolean(GL_BINDING_CALL* eglQueryDisplayAttribANGLEProc)(
+    EGLDisplay dpy,
+    EGLint attribute,
+    EGLAttrib* value);
 typedef EGLBoolean(GL_BINDING_CALL* eglQueryStreamKHRProc)(EGLDisplay dpy,
                                                            EGLStreamKHR stream,
                                                            EGLenum attribute,
@@ -202,6 +206,9 @@
     EGLuint64KHR* value);
 typedef const char*(GL_BINDING_CALL* eglQueryStringProc)(EGLDisplay dpy,
                                                          EGLint name);
+typedef const char*(GL_BINDING_CALL* eglQueryStringiANGLEProc)(EGLDisplay dpy,
+                                                               EGLint name,
+                                                               EGLint index);
 typedef EGLBoolean(GL_BINDING_CALL* eglQuerySurfaceProc)(EGLDisplay dpy,
                                                          EGLSurface surface,
                                                          EGLint attribute,
@@ -271,6 +278,7 @@
   bool b_EGL_ANDROID_get_native_client_buffer;
   bool b_EGL_ANDROID_native_fence_sync;
   bool b_EGL_ANGLE_d3d_share_handle_client_buffer;
+  bool b_EGL_ANGLE_feature_control;
   bool b_EGL_ANGLE_query_surface_pointer;
   bool b_EGL_ANGLE_stream_producer_d3d_texture;
   bool b_EGL_ANGLE_surface_d3d_texture_2d_share_handle;
@@ -343,9 +351,11 @@
   eglQueryAPIProc eglQueryAPIFn;
   eglQueryContextProc eglQueryContextFn;
   eglQueryDebugKHRProc eglQueryDebugKHRFn;
+  eglQueryDisplayAttribANGLEProc eglQueryDisplayAttribANGLEFn;
   eglQueryStreamKHRProc eglQueryStreamKHRFn;
   eglQueryStreamu64KHRProc eglQueryStreamu64KHRFn;
   eglQueryStringProc eglQueryStringFn;
+  eglQueryStringiANGLEProc eglQueryStringiANGLEFn;
   eglQuerySurfaceProc eglQuerySurfaceFn;
   eglQuerySurfacePointerANGLEProc eglQuerySurfacePointerANGLEFn;
   eglReleaseTexImageProc eglReleaseTexImageFn;
@@ -531,6 +541,9 @@
                                        EGLint attribute,
                                        EGLint* value) = 0;
   virtual EGLBoolean eglQueryDebugKHRFn(EGLint attribute, EGLAttrib* value) = 0;
+  virtual EGLBoolean eglQueryDisplayAttribANGLEFn(EGLDisplay dpy,
+                                                  EGLint attribute,
+                                                  EGLAttrib* value) = 0;
   virtual EGLBoolean eglQueryStreamKHRFn(EGLDisplay dpy,
                                          EGLStreamKHR stream,
                                          EGLenum attribute,
@@ -540,6 +553,9 @@
                                             EGLenum attribute,
                                             EGLuint64KHR* value) = 0;
   virtual const char* eglQueryStringFn(EGLDisplay dpy, EGLint name) = 0;
+  virtual const char* eglQueryStringiANGLEFn(EGLDisplay dpy,
+                                             EGLint name,
+                                             EGLint index) = 0;
   virtual EGLBoolean eglQuerySurfaceFn(EGLDisplay dpy,
                                        EGLSurface surface,
                                        EGLint attribute,
@@ -662,9 +678,12 @@
 #define eglQueryAPI ::gl::g_current_egl_context->eglQueryAPIFn
 #define eglQueryContext ::gl::g_current_egl_context->eglQueryContextFn
 #define eglQueryDebugKHR ::gl::g_current_egl_context->eglQueryDebugKHRFn
+#define eglQueryDisplayAttribANGLE \
+  ::gl::g_current_egl_context->eglQueryDisplayAttribANGLEFn
 #define eglQueryStreamKHR ::gl::g_current_egl_context->eglQueryStreamKHRFn
 #define eglQueryStreamu64KHR ::gl::g_current_egl_context->eglQueryStreamu64KHRFn
 #define eglQueryString ::gl::g_current_egl_context->eglQueryStringFn
+#define eglQueryStringiANGLE ::gl::g_current_egl_context->eglQueryStringiANGLEFn
 #define eglQuerySurface ::gl::g_current_egl_context->eglQuerySurfaceFn
 #define eglQuerySurfacePointerANGLE \
   ::gl::g_current_egl_context->eglQuerySurfacePointerANGLEFn
diff --git a/ui/gl/gl_enums_implementation_autogen.h b/ui/gl/gl_enums_implementation_autogen.h
index 030e0c7a..d36be8b 100644
--- a/ui/gl/gl_enums_implementation_autogen.h
+++ b/ui/gl/gl_enums_implementation_autogen.h
@@ -1009,6 +1009,10 @@
         "GL_LATENCY_QUERY_CHROMIUM",
     },
     {
+        0x6009,
+        "GL_PROGRAM_COMPLETION_QUERY_CHROMIUM",
+    },
+    {
         0x78EC,
         "GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM",
     },
diff --git a/ui/gl/gl_mock_autogen_egl.h b/ui/gl/gl_mock_autogen_egl.h
index a8b2b6c..4bf7a2c 100644
--- a/ui/gl/gl_mock_autogen_egl.h
+++ b/ui/gl/gl_mock_autogen_egl.h
@@ -174,6 +174,8 @@
                         EGLint attribute,
                         EGLint* value));
 MOCK_METHOD2(QueryDebugKHR, EGLBoolean(EGLint attribute, EGLAttrib* value));
+MOCK_METHOD3(QueryDisplayAttribANGLE,
+             EGLBoolean(EGLDisplay dpy, EGLint attribute, EGLAttrib* value));
 MOCK_METHOD4(QueryStreamKHR,
              EGLBoolean(EGLDisplay dpy,
                         EGLStreamKHR stream,
@@ -185,6 +187,8 @@
                         EGLenum attribute,
                         EGLuint64KHR* value));
 MOCK_METHOD2(QueryString, const char*(EGLDisplay dpy, EGLint name));
+MOCK_METHOD3(QueryStringiANGLE,
+             const char*(EGLDisplay dpy, EGLint name, EGLint index));
 MOCK_METHOD4(QuerySurface,
              EGLBoolean(EGLDisplay dpy,
                         EGLSurface surface,
diff --git a/ui/gl/gl_surface_egl.cc b/ui/gl/gl_surface_egl.cc
index 4ed501ef..615f434 100644
--- a/ui/gl/gl_surface_egl.cc
+++ b/ui/gl/gl_surface_egl.cc
@@ -162,6 +162,7 @@
 bool g_egl_create_context_client_arrays_supported = false;
 bool g_egl_android_native_fence_sync_supported = false;
 bool g_egl_ext_pixel_format_float_supported = false;
+bool g_egl_angle_feature_control_supported = false;
 
 constexpr const char kSwapEventTraceCategories[] = "gpu";
 
@@ -777,6 +778,9 @@
   g_egl_ext_pixel_format_float_supported =
       HasEGLExtension("EGL_EXT_pixel_format_float");
 
+  g_egl_angle_feature_control_supported =
+      HasEGLExtension("EGL_ANGLE_feature_control");
+
   initialized_ = true;
   return true;
 }
@@ -812,6 +816,7 @@
   g_egl_robust_resource_init_supported = false;
   g_egl_display_texture_share_group_supported = false;
   g_egl_create_context_client_arrays_supported = false;
+  g_egl_angle_feature_control_supported = false;
 
   initialized_ = false;
 }
@@ -884,6 +889,10 @@
   return g_egl_ext_pixel_format_float_supported;
 }
 
+bool GLSurfaceEGL::IsANGLEFeatureControlSupported() {
+  return g_egl_angle_feature_control_supported;
+}
+
 GLSurfaceEGL::~GLSurfaceEGL() {}
 
 // InitializeDisplay is necessary because the static binding code
diff --git a/ui/gl/gl_surface_egl.h b/ui/gl/gl_surface_egl.h
index 79aca84..6bda8be 100644
--- a/ui/gl/gl_surface_egl.h
+++ b/ui/gl/gl_surface_egl.h
@@ -91,6 +91,7 @@
   static bool IsCreateContextClientArraysSupported();
   static bool IsAndroidNativeFenceSyncSupported();
   static bool IsPixelFormatFloatSupported();
+  static bool IsANGLEFeatureControlSupported();
 
  protected:
   ~GLSurfaceEGL() override;
diff --git a/ui/ozone/common/linux/gbm_wrapper.cc b/ui/ozone/common/linux/gbm_wrapper.cc
index dc4bc04..ccc5b32 100644
--- a/ui/ozone/common/linux/gbm_wrapper.cc
+++ b/ui/ozone/common/linux/gbm_wrapper.cc
@@ -136,7 +136,7 @@
   }
   size_t GetPlaneSize(size_t plane) const override {
     DCHECK_LT(plane, handle_.planes.size());
-    return handle_.planes[plane].size;
+    return static_cast<size_t>(handle_.planes[plane].size);
   }
   uint32_t GetPlaneHandle(size_t plane) const override {
     DCHECK_LT(plane, handle_.planes.size());
diff --git a/ui/ozone/platform/cast/surface_factory_cast.cc b/ui/ozone/platform/cast/surface_factory_cast.cc
index 11ccb3c..4643843 100644
--- a/ui/ozone/platform/cast/surface_factory_cast.cc
+++ b/ui/ozone/platform/cast/surface_factory_cast.cc
@@ -53,6 +53,7 @@
   int GetDmaBufFd(size_t plane) const override { return -1; }
   int GetDmaBufPitch(size_t plane) const override { return 0; }
   int GetDmaBufOffset(size_t plane) const override { return 0; }
+  size_t GetDmaBufPlaneSize(size_t plane) const override { return 0; }
   uint64_t GetBufferFormatModifier() const override { return 0; }
   gfx::BufferFormat GetBufferFormat() const override {
     return gfx::BufferFormat::BGRA_8888;
diff --git a/ui/ozone/platform/drm/gpu/gbm_pixmap.cc b/ui/ozone/platform/drm/gpu/gbm_pixmap.cc
index fbe77fbb4..2055555 100644
--- a/ui/ozone/platform/drm/gpu/gbm_pixmap.cc
+++ b/ui/ozone/platform/drm/gpu/gbm_pixmap.cc
@@ -44,6 +44,10 @@
   return buffer_->GetPlaneOffset(plane);
 }
 
+size_t GbmPixmap::GetDmaBufPlaneSize(size_t plane) const {
+  return buffer_->GetPlaneSize(plane);
+}
+
 uint64_t GbmPixmap::GetBufferFormatModifier() const {
   return buffer_->GetFormatModifier();
 }
diff --git a/ui/ozone/platform/drm/gpu/gbm_pixmap.h b/ui/ozone/platform/drm/gpu/gbm_pixmap.h
index d6de7628..db22bbf9 100644
--- a/ui/ozone/platform/drm/gpu/gbm_pixmap.h
+++ b/ui/ozone/platform/drm/gpu/gbm_pixmap.h
@@ -29,6 +29,7 @@
   int GetDmaBufFd(size_t plane) const override;
   int GetDmaBufPitch(size_t plane) const override;
   int GetDmaBufOffset(size_t plane) const override;
+  size_t GetDmaBufPlaneSize(size_t plane) const override;
   uint64_t GetBufferFormatModifier() const override;
   gfx::BufferFormat GetBufferFormat() const override;
   gfx::Size GetBufferSize() const override;
diff --git a/ui/ozone/platform/drm/gpu/mock_gbm_device.cc b/ui/ozone/platform/drm/gpu/mock_gbm_device.cc
index b52e071..d2fb2a5 100644
--- a/ui/ozone/platform/drm/gpu/mock_gbm_device.cc
+++ b/ui/ozone/platform/drm/gpu/mock_gbm_device.cc
@@ -59,7 +59,7 @@
   }
   size_t GetPlaneSize(size_t plane) const override {
     DCHECK_LT(plane, planes_.size());
-    return planes_[plane].size;
+    return static_cast<size_t>(planes_[plane].size);
   }
   uint32_t GetPlaneHandle(size_t plane) const override {
     DCHECK_LT(plane, planes_.size());
diff --git a/ui/ozone/platform/headless/headless_surface_factory.cc b/ui/ozone/platform/headless/headless_surface_factory.cc
index 4647a53..73ab3cd 100644
--- a/ui/ozone/platform/headless/headless_surface_factory.cc
+++ b/ui/ozone/platform/headless/headless_surface_factory.cc
@@ -85,6 +85,7 @@
   int GetDmaBufFd(size_t plane) const override { return -1; }
   int GetDmaBufPitch(size_t plane) const override { return 0; }
   int GetDmaBufOffset(size_t plane) const override { return 0; }
+  size_t GetDmaBufPlaneSize(size_t plane) const override { return 0; }
   uint64_t GetBufferFormatModifier() const override { return 0; }
   gfx::BufferFormat GetBufferFormat() const override { return format_; }
   gfx::Size GetBufferSize() const override { return gfx::Size(); }
diff --git a/ui/ozone/platform/scenic/sysmem_buffer_collection.cc b/ui/ozone/platform/scenic/sysmem_buffer_collection.cc
index 344799cb7..aef7b7d 100644
--- a/ui/ozone/platform/scenic/sysmem_buffer_collection.cc
+++ b/ui/ozone/platform/scenic/sysmem_buffer_collection.cc
@@ -33,6 +33,10 @@
     NOTREACHED();
     return 0;
   }
+  size_t GetDmaBufPlaneSize(size_t plane) const override {
+    NOTREACHED();
+    return 0;
+  }
   uint64_t GetBufferFormatModifier() const override {
     NOTREACHED();
     return 0;
diff --git a/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.cc b/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.cc
index 5d8167bd..c4f97786 100644
--- a/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.cc
+++ b/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.cc
@@ -102,6 +102,10 @@
   return gbm_bo_->GetPlaneOffset(plane);
 }
 
+size_t GbmPixmapWayland::GetDmaBufPlaneSize(size_t plane) const {
+  return gbm_bo_->GetPlaneSize(plane);
+}
+
 uint64_t GbmPixmapWayland::GetBufferFormatModifier() const {
   return gbm_bo_->GetFormatModifier();
 }
diff --git a/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.h b/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.h
index b605120..baee537 100644
--- a/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.h
+++ b/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.h
@@ -34,6 +34,7 @@
   int GetDmaBufFd(size_t plane) const override;
   int GetDmaBufPitch(size_t plane) const override;
   int GetDmaBufOffset(size_t plane) const override;
+  size_t GetDmaBufPlaneSize(size_t plane) const override;
   uint64_t GetBufferFormatModifier() const override;
   gfx::BufferFormat GetBufferFormat() const override;
   gfx::Size GetBufferSize() const override;
diff --git a/ui/ozone/platform/wayland/host/wayland_connection.cc b/ui/ozone/platform/wayland/host/wayland_connection.cc
index 477ee110..72617b5 100644
--- a/ui/ozone/platform/wayland/host/wayland_connection.cc
+++ b/ui/ozone/platform/wayland/host/wayland_connection.cc
@@ -160,6 +160,16 @@
   return nullptr;
 }
 
+std::vector<WaylandWindow*> WaylandConnection::GetWindowsOnOutput(
+    uint32_t output_id) {
+  std::vector<WaylandWindow*> result;
+  for (auto entry : window_map_) {
+    if (entry.second->GetEnteredOutputsIds().count(output_id) > 0)
+      result.push_back(entry.second);
+  }
+  return result;
+}
+
 void WaylandConnection::AddWindow(gfx::AcceleratedWidget widget,
                                   WaylandWindow* window) {
   DCHECK(buffer_manager_host_);
diff --git a/ui/ozone/platform/wayland/host/wayland_connection.h b/ui/ozone/platform/wayland/host/wayland_connection.h
index 65c1333..9ae6527 100644
--- a/ui/ozone/platform/wayland/host/wayland_connection.h
+++ b/ui/ozone/platform/wayland/host/wayland_connection.h
@@ -62,6 +62,9 @@
   WaylandWindow* GetWindowWithLargestBounds() const;
   WaylandWindow* GetCurrentFocusedWindow() const;
   WaylandWindow* GetCurrentKeyboardFocusedWindow() const;
+  // TODO(crbug.com/971525): remove this in favor of targeted subscription of
+  // windows to their outputs.
+  std::vector<WaylandWindow*> GetWindowsOnOutput(uint32_t output_id);
   void AddWindow(gfx::AcceleratedWidget widget, WaylandWindow* window);
   void RemoveWindow(gfx::AcceleratedWidget widget);
 
@@ -163,7 +166,7 @@
   // xdg_shell_listener
   static void Ping(void* data, xdg_shell* shell, uint32_t serial);
 
-  std::map<gfx::AcceleratedWidget, WaylandWindow*> window_map_;
+  base::flat_map<gfx::AcceleratedWidget, WaylandWindow*> window_map_;
 
   wl::Object<wl_display> display_;
   wl::Object<wl_registry> registry_;
diff --git a/ui/ozone/platform/wayland/host/wayland_output.cc b/ui/ozone/platform/wayland/host/wayland_output.cc
index 0b36d95..701f167 100644
--- a/ui/ozone/platform/wayland/host/wayland_output.cc
+++ b/ui/ozone/platform/wayland/host/wayland_output.cc
@@ -11,14 +11,10 @@
 
 namespace ui {
 
-namespace {
-constexpr float kDefaultScaleFactor = 1.0f;
-}
-
 WaylandOutput::WaylandOutput(const uint32_t output_id, wl_output* output)
     : output_id_(output_id),
       output_(output),
-      device_scale_factor_(kDefaultScaleFactor),
+      scale_factor_(kDefaultScaleFactor),
       rect_in_physical_pixels_(gfx::Rect()) {}
 
 WaylandOutput::~WaylandOutput() = default;
@@ -38,7 +34,7 @@
 void WaylandOutput::TriggerDelegateNotification() const {
   DCHECK(!rect_in_physical_pixels_.IsEmpty());
   delegate_->OnOutputHandleMetrics(output_id_, rect_in_physical_pixels_,
-                                   device_scale_factor_);
+                                   scale_factor_);
 }
 
 // static
@@ -82,7 +78,7 @@
                                       int32_t factor) {
   WaylandOutput* wayland_output = static_cast<WaylandOutput*>(data);
   if (wayland_output)
-    wayland_output->device_scale_factor_ = factor;
+    wayland_output->scale_factor_ = factor;
 }
 
 }  // namespace ui
diff --git a/ui/ozone/platform/wayland/host/wayland_output.h b/ui/ozone/platform/wayland/host/wayland_output.h
index 464689e..36f8c89 100644
--- a/ui/ozone/platform/wayland/host/wayland_output.h
+++ b/ui/ozone/platform/wayland/host/wayland_output.h
@@ -36,12 +36,15 @@
 
   uint32_t output_id() const { return output_id_; }
   bool has_output(wl_output* output) const { return output_.get() == output; }
+  int32_t scale_factor() const { return scale_factor_; }
 
   // Tells if the output has already received physical screen dimensions in the
   // global compositor space.
   bool is_ready() const { return !rect_in_physical_pixels_.IsEmpty(); }
 
  private:
+  static constexpr int32_t kDefaultScaleFactor = 1;
+
   // Callback functions used for setting geometric properties of the output
   // and available modes.
   static void OutputHandleGeometry(void* data,
@@ -68,7 +71,7 @@
 
   const uint32_t output_id_ = 0;
   wl::Object<wl_output> output_;
-  float device_scale_factor_;
+  int32_t scale_factor_ = kDefaultScaleFactor;
   gfx::Rect rect_in_physical_pixels_;
 
   Delegate* delegate_ = nullptr;
diff --git a/ui/ozone/platform/wayland/host/wayland_output_manager.cc b/ui/ozone/platform/wayland/host/wayland_output_manager.cc
index 38dad07..1f403f4 100644
--- a/ui/ozone/platform/wayland/host/wayland_output_manager.cc
+++ b/ui/ozone/platform/wayland/host/wayland_output_manager.cc
@@ -26,10 +26,7 @@
   // Make sure an output with |output_id| has not been added yet. It's very
   // unlikely to happen, unless a compositor has a bug in the numeric names
   // representation of global objects.
-  auto output_it = std::find_if(output_list_.begin(), output_list_.end(),
-                                [output_id](const auto& output) {
-                                  return output->output_id() == output_id;
-                                });
+  auto output_it = GetOutputItById(output_id);
   DCHECK(output_it == output_list_.end());
   auto wayland_output = std::make_unique<WaylandOutput>(output_id, output);
   WaylandOutput* wayland_output_ptr = wayland_output.get();
@@ -44,10 +41,7 @@
 }
 
 void WaylandOutputManager::RemoveWaylandOutput(const uint32_t output_id) {
-  auto output_it = std::find_if(output_list_.begin(), output_list_.end(),
-                                [output_id](const auto& output) {
-                                  return output->output_id() == output_id;
-                                });
+  auto output_it = GetOutputItById(output_id);
 
   // Check the comment in the WaylandConnetion::GlobalRemove.
   if (output_it == output_list_.end())
@@ -89,6 +83,13 @@
   return output_it->get()->output_id();
 }
 
+WaylandOutput* WaylandOutputManager::GetOutput(uint32_t id) const {
+  auto output_it = GetOutputItById(id);
+  // This is unlikely to happen, but better to be explicit here.
+  DCHECK(output_it != output_list_.end());
+  return output_it->get();
+}
+
 void WaylandOutputManager::OnWaylandOutputAdded(uint32_t output_id) {
   if (wayland_screen_)
     wayland_screen_->OnOutputAdded(output_id);
@@ -107,4 +108,11 @@
                                             scale_factor);
 }
 
+WaylandOutputManager::OutputList::const_iterator
+WaylandOutputManager::GetOutputItById(uint32_t id) const {
+  return std::find_if(
+      output_list_.begin(), output_list_.end(),
+      [id](const auto& item) { return item->output_id() == id; });
+}
+
 }  // namespace ui
diff --git a/ui/ozone/platform/wayland/host/wayland_output_manager.h b/ui/ozone/platform/wayland/host/wayland_output_manager.h
index 8123232..f05828a6 100644
--- a/ui/ozone/platform/wayland/host/wayland_output_manager.h
+++ b/ui/ozone/platform/wayland/host/wayland_output_manager.h
@@ -39,6 +39,9 @@
       WaylandConnection* connection);
 
   uint32_t GetIdForOutput(wl_output* output) const;
+  WaylandOutput* GetOutput(uint32_t id) const;
+
+  WaylandScreen* wayland_screen() const { return wayland_screen_.get(); }
 
  private:
   void OnWaylandOutputAdded(uint32_t output_id);
@@ -49,7 +52,11 @@
                              const gfx::Rect& new_bounds,
                              int32_t scale_factor) override;
 
-  std::vector<std::unique_ptr<WaylandOutput>> output_list_;
+  using OutputList = std::vector<std::unique_ptr<WaylandOutput>>;
+
+  OutputList::const_iterator GetOutputItById(uint32_t id) const;
+
+  OutputList output_list_;
 
   // Non-owned wayland screen instance.
   base::WeakPtr<WaylandScreen> wayland_screen_;
diff --git a/ui/ozone/platform/wayland/host/wayland_screen.cc b/ui/ozone/platform/wayland/host/wayland_screen.cc
index e53a959..694c13f4 100644
--- a/ui/ozone/platform/wayland/host/wayland_screen.cc
+++ b/ui/ozone/platform/wayland/host/wayland_screen.cc
@@ -23,14 +23,12 @@
 WaylandScreen::~WaylandScreen() = default;
 
 void WaylandScreen::OnOutputAdded(uint32_t output_id) {
-  display::Display new_display(output_id);
-  display_list_.AddDisplay(std::move(new_display),
+  display_list_.AddDisplay(display::Display(output_id),
                            display::DisplayList::Type::NOT_PRIMARY);
 }
 
 void WaylandScreen::OnOutputRemoved(uint32_t output_id) {
-  display::Display primary_display = GetPrimaryDisplay();
-  if (primary_display.id() == output_id) {
+  if (output_id == GetPrimaryDisplay().id()) {
     // First, set a new primary display as required by the |display_list_|. It's
     // safe to set any of the displays to be a primary one. Once the output is
     // completely removed, Wayland updates geometry of other displays. And a
@@ -49,9 +47,10 @@
 
 void WaylandScreen::OnOutputMetricsChanged(uint32_t output_id,
                                            const gfx::Rect& new_bounds,
-                                           float device_pixel_ratio) {
+                                           int32_t device_pixel_ratio) {
   display::Display changed_display(output_id);
-  changed_display.set_device_scale_factor(device_pixel_ratio);
+  if (!display::Display::HasForceDeviceScaleFactor())
+    changed_display.set_device_scale_factor(device_pixel_ratio);
   changed_display.set_bounds(new_bounds);
   changed_display.set_work_area(new_bounds);
 
@@ -81,6 +80,9 @@
   display_list_.UpdateDisplay(
       changed_display, is_primary ? display::DisplayList::Type::PRIMARY
                                   : display::DisplayList::Type::NOT_PRIMARY);
+
+  for (auto* window : connection_->GetWindowsOnOutput(output_id))
+    window->UpdateBufferScale(true);
 }
 
 base::WeakPtr<WaylandScreen> WaylandScreen::GetWeakPtr() {
@@ -99,13 +101,13 @@
 
 display::Display WaylandScreen::GetDisplayForAcceleratedWidget(
     gfx::AcceleratedWidget widget) const {
-  auto* wayland_window = connection_->GetWindow(widget);
+  auto* window = connection_->GetWindow(widget);
   // A window might be destroyed by this time on shutting down the browser.
-  if (!wayland_window)
+  if (!window)
     return GetPrimaryDisplay();
 
-  const std::set<uint32_t> entered_outputs_ids =
-      wayland_window->GetEnteredOutputsIds();
+  const auto* parent_window = window->parent_window();
+  const std::set<uint32_t> entered_outputs_ids = window->GetEnteredOutputsIds();
   // Although spec says a surface receives enter/leave surface events on
   // create/move/resize actions, this might be called right after a window is
   // created, but it has not been configured by a Wayland compositor and it has
@@ -114,14 +116,19 @@
   // events immediately, which can result in empty container of entered ids
   // (check comments in WaylandWindow::RemoveEnteredOutputId). In this case,
   // it's also safe to return the primary display.
-  if (entered_outputs_ids.empty())
+  // A child window will most probably enter the same display than its parent
+  // so we return the parent's display if there is a parent.
+  if (entered_outputs_ids.empty()) {
+    if (parent_window)
+      return GetDisplayForAcceleratedWidget(parent_window->GetWidget());
     return GetPrimaryDisplay();
+  }
 
   DCHECK(!display_list_.displays().empty());
 
   // A widget can be located on two or more displays. It would be better if the
-  // most in pixels occupied display was returned, but it's impossible to do in
-  // Wayland. Thus, return the one, which was the very first used.
+  // most in DIP occupied display was returned, but it's impossible to do so in
+  // Wayland. Thus, return the one that was used the earliest.
   for (const auto& display : display_list_.displays()) {
     if (display.id() == *entered_outputs_ids.begin())
       return display;
diff --git a/ui/ozone/platform/wayland/host/wayland_screen.h b/ui/ozone/platform/wayland/host/wayland_screen.h
index f395b9b..c81b47a3 100644
--- a/ui/ozone/platform/wayland/host/wayland_screen.h
+++ b/ui/ozone/platform/wayland/host/wayland_screen.h
@@ -29,7 +29,7 @@
   void OnOutputRemoved(uint32_t output_id);
   void OnOutputMetricsChanged(uint32_t output_id,
                               const gfx::Rect& bounds,
-                              float device_pixel_ratio);
+                              int32_t output_scale);
 
   base::WeakPtr<WaylandScreen> GetWeakPtr();
 
diff --git a/ui/ozone/platform/wayland/host/wayland_screen_unittest.cc b/ui/ozone/platform/wayland/host/wayland_screen_unittest.cc
index 54e72fb5..f93ac20d 100644
--- a/ui/ozone/platform/wayland/host/wayland_screen_unittest.cc
+++ b/ui/ozone/platform/wayland/host/wayland_screen_unittest.cc
@@ -223,9 +223,8 @@
   EXPECT_EQ(observer.GetAndClearChangedMetrics(), changed_values);
   EXPECT_EQ(observer.GetDisplay().bounds(), new_rect);
 
-  const float new_scale_value = 2.0f;
-  wl_output_send_scale(output_->resource(), new_scale_value);
-  wl_output_send_done(output_->resource());
+  const int32_t new_scale_value = 2;
+  output_->SetScale(new_scale_value);
 
   Sync();
 
@@ -580,6 +579,23 @@
   EXPECT_EQ(gfx::Point(1912, 1071), platform_screen_->GetCursorScreenPoint());
 }
 
+// Checks that the surface that backs the window receives new scale of the
+// output that it is in.
+TEST_P(WaylandScreenTest, SetBufferScale) {
+  // Place the window onto the output.
+  wl_surface_send_enter(surface_->resource(), output_->resource());
+
+  // Change the scale of the output.  Windows looking into that output must get
+  // the new scale and update scale of their buffers.
+  const int32_t kNewScale = 3;
+  EXPECT_CALL(*surface_, SetBufferScale(kNewScale));
+  output_->SetScale(kNewScale);
+
+  Sync();
+
+  EXPECT_EQ(window_->buffer_scale(), kNewScale);
+}
+
 INSTANTIATE_TEST_SUITE_P(XdgVersionV5Test,
                          WaylandScreenTest,
                          ::testing::Values(kXdgShellV5));
diff --git a/ui/ozone/platform/wayland/host/wayland_window.cc b/ui/ozone/platform/wayland/host/wayland_window.cc
index 153c8e87..193bd2a 100644
--- a/ui/ozone/platform/wayland/host/wayland_window.cc
+++ b/ui/ozone/platform/wayland/host/wayland_window.cc
@@ -123,7 +123,11 @@
 bool WaylandWindow::Initialize(PlatformWindowInitProperties properties) {
   DCHECK(xdg_shell_objects_factory_);
 
-  bounds_ = properties.bounds;
+  // Properties contain DIP bounds but the buffer scale is initially 1 so it's
+  // OK to assign.  The bounds will be recalculated when the buffer scale
+  // changes.
+  DCHECK_EQ(buffer_scale_, 1);
+  bounds_px_ = properties.bounds;
   opacity_ = properties.opacity;
 
   surface_.reset(wl_compositor_create_surface(connection_->compositor()));
@@ -140,6 +144,10 @@
     case ui::PlatformWindowType::kPopup:
       parent_window_ = GetParentWindow(properties.parent_widget);
 
+      // Popups need to know their scale earlier to position themselves.
+      DCHECK(parent_window_);
+      SetBufferScale(parent_window_->buffer_scale_, false);
+
       // TODO(msisov, jkim): Handle notification windows, which are marked
       // as popup windows as well. Those are the windows that do not have
       // parents and pop up when the browser receives a notification.
@@ -160,10 +168,35 @@
   PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this);
   delegate_->OnAcceleratedWidgetAvailable(GetWidget());
 
+  // Will do nothing for popups because they have got their scale above.
+  UpdateBufferScale(false);
+
   MaybeUpdateOpaqueRegion();
   return true;
 }
 
+void WaylandWindow::UpdateBufferScale(bool update_bounds) {
+  DCHECK(connection_->wayland_output_manager());
+  const auto* screen = connection_->wayland_output_manager()->wayland_screen();
+  DCHECK(screen);
+  const auto widget = GetWidget();
+
+  int32_t new_scale = 0;
+  if (parent_window_) {
+    new_scale = parent_window_->buffer_scale_;
+  } else if (widget == gfx::kNullAcceleratedWidget) {
+    new_scale = screen->GetPrimaryDisplay().device_scale_factor();
+  } else {
+    // This is the main window that is fully set up so we can ask which display
+    // we are at currently.
+    new_scale =
+        connection_->wayland_output_manager()
+            ->GetOutput(screen->GetDisplayForAcceleratedWidget(widget).id())
+            ->scale_factor();
+  }
+  SetBufferScale(new_scale, update_bounds);
+}
+
 gfx::AcceleratedWidget WaylandWindow::GetWidget() const {
   if (!surface_)
     return gfx::kNullAcceleratedWidget;
@@ -175,7 +208,7 @@
 }
 
 void WaylandWindow::CreateXdgPopup() {
-  if (bounds_.IsEmpty())
+  if (bounds_px_.IsEmpty())
     return;
 
   // TODO(jkim): Consider how to support DropArrow window on tabstrip.
@@ -193,11 +226,11 @@
 
   DCHECK(parent_window_ && !xdg_popup_);
 
-  auto bounds = AdjustPopupWindowPosition();
+  auto bounds_px = AdjustPopupWindowPosition();
 
   xdg_popup_ = xdg_shell_objects_factory_->CreateXDGPopup(connection_, this);
-  if (!xdg_popup_ ||
-      !xdg_popup_->Initialize(connection_, surface(), parent_window_, bounds)) {
+  if (!xdg_popup_ || !xdg_popup_->Initialize(connection_, surface(),
+                                             parent_window_, bounds_px)) {
     CHECK(false) << "Failed to create xdg_popup";
   }
 
@@ -234,22 +267,24 @@
   }
 
   DCHECK(tooltip_subsurface_);
-  wl_subsurface_set_position(tooltip_subsurface_.get(), bounds_.x(),
-                             bounds_.y());
+  // Convert position to DIP.
+  wl_subsurface_set_position(tooltip_subsurface_.get(),
+                             bounds_px_.x() / buffer_scale_,
+                             bounds_px_.y() / buffer_scale_);
   wl_subsurface_set_desync(tooltip_subsurface_.get());
   wl_surface_commit(parent_window_->surface());
   connection_->ScheduleFlush();
 }
 
 void WaylandWindow::ApplyPendingBounds() {
-  if (pending_bounds_.IsEmpty())
+  if (pending_bounds_dip_.IsEmpty())
     return;
   DCHECK(xdg_surface_);
 
-  SetBounds(pending_bounds_);
-  xdg_surface_->SetWindowGeometry(bounds_);
+  SetBoundsDip(pending_bounds_dip_);
+  xdg_surface_->SetWindowGeometry(pending_bounds_dip_);
   xdg_surface_->AckConfigure();
-  pending_bounds_ = gfx::Rect();
+  pending_bounds_dip_ = gfx::Rect();
   connection_->ScheduleFlush();
 
   // Opaque region is based on the size of the window. Thus, update the region
@@ -293,9 +328,17 @@
   }
 
   if (!xdg_popup_) {
+    // When showing a sub-menu after it has been previously shown and hidden,
+    // Wayland sends SetBounds prior to Show, and |bounds_px| takes the pixel
+    // bounds.  This makes a difference against the normal flow when the
+    // window is created (see |Initialize|).  To equalize things, rescale
+    // |bounds_px_| to DIP.  It will be adjusted while creating the popup.
+    bounds_px_ = gfx::ScaleToRoundedRect(bounds_px_, 1.0 / buffer_scale_);
     CreateXdgPopup();
     connection_->ScheduleFlush();
   }
+
+  UpdateBufferScale(false);
 }
 
 void WaylandWindow::Hide() {
@@ -322,15 +365,25 @@
 
 void WaylandWindow::PrepareForShutdown() {}
 
-void WaylandWindow::SetBounds(const gfx::Rect& bounds) {
-  if (bounds == bounds_)
+void WaylandWindow::SetBounds(const gfx::Rect& bounds_px) {
+  // TODO(crbug.com/958314): figure out if this return is legitimate.
+  //
+  // The X11 implementation says that even if the pixel bounds didn't change, we
+  // still need to forward this call to the delegate, and that the device scale
+  // factor may have changed which effectively changes the bounds.  Perhaps we
+  // need to do the same here.
+  //
+  // After this is resolved, update test expectations for calls to
+  // delegate's OnBoundsChanged.
+  if (bounds_px_ == bounds_px)
     return;
-  bounds_ = bounds;
-  delegate_->OnBoundsChanged(bounds);
+  bounds_px_ = bounds_px;
+
+  delegate_->OnBoundsChanged(bounds_px_);
 }
 
 gfx::Rect WaylandWindow::GetBounds() {
-  return bounds_;
+  return bounds_px_;
 }
 
 void WaylandWindow::SetTitle(const base::string16& title) {
@@ -452,12 +505,12 @@
   NOTIMPLEMENTED();
 }
 
-void WaylandWindow::SetRestoredBoundsInPixels(const gfx::Rect& bounds) {
-  restored_bounds_ = bounds;
+void WaylandWindow::SetRestoredBoundsInPixels(const gfx::Rect& bounds_px) {
+  restored_bounds_px_ = bounds_px;
 }
 
 gfx::Rect WaylandWindow::GetRestoredBoundsInPixels() const {
-  return restored_bounds_;
+  return restored_bounds_px_;
 }
 
 bool WaylandWindow::CanDispatchEvent(const PlatformEvent& event) {
@@ -488,6 +541,10 @@
   Event* event = static_cast<Event*>(native_event);
 
   if (event->IsLocatedEvent()) {
+    // Wayland sends locations in DIP so they need to be translated to
+    // physical pixels.
+    event->AsLocatedEvent()->set_location_f(gfx::ScalePoint(
+        event->AsLocatedEvent()->location_f(), buffer_scale_, buffer_scale_));
     auto copied_event = Event::Clone(*event);
     UpdateCursorPositionFromEvent(std::move(copied_event));
   }
@@ -569,11 +626,13 @@
   // explicitly set the bounds to the current desired ones or the previous
   // bounds.
   if (width > 1 && height > 1) {
-    pending_bounds_ = gfx::Rect(0, 0, width, height);
+    pending_bounds_dip_ = gfx::Rect(0, 0, width, height);
   } else if (is_normal) {
-    pending_bounds_.set_size(restored_bounds_.IsEmpty()
-                                 ? GetBounds().size()
-                                 : restored_bounds_.size());
+    pending_bounds_dip_.set_size(gfx::ScaleToRoundedSize(
+        restored_bounds_px_.IsEmpty() ? GetBounds().size()
+                                      : restored_bounds_px_.size(),
+
+        1.0 / buffer_scale_));
   }
 
   if (state_changed) {
@@ -585,8 +644,8 @@
     if (is_normal) {
       SetRestoredBoundsInPixels({});
     } else if (old_state == PlatformWindowState::PLATFORM_WINDOW_STATE_NORMAL ||
-               restored_bounds_.IsEmpty()) {
-      SetRestoredBoundsInPixels(bounds_);
+               restored_bounds_px_.IsEmpty()) {
+      SetRestoredBoundsInPixels(bounds_px_);
     }
 
     delegate_->OnWindowStateChanged(state_);
@@ -598,9 +657,13 @@
   MaybeTriggerPendingStateChange();
 }
 
-void WaylandWindow::HandlePopupConfigure(const gfx::Rect& bounds) {
+void WaylandWindow::HandlePopupConfigure(const gfx::Rect& bounds_dip) {
   DCHECK(xdg_popup());
-  gfx::Rect new_bounds = bounds;
+  DCHECK(parent_window_);
+
+  SetBufferScale(parent_window_->buffer_scale_, true);
+
+  gfx::Rect new_bounds_dip = bounds_dip;
 
   // It's not enough to just set new bounds. If it is a menu window, whose
   // parent is a top level window aka browser window, it can be flipped
@@ -618,10 +681,10 @@
     gfx::Rect parent_bounds = parent_window_->GetBounds();
     // The menu window is flipped along y-axis and have x,-y origin. Shift the
     // parent top level window instead.
-    if (new_bounds.y() < 0) {
+    if (new_bounds_dip.y() < 0) {
       // Move parent bounds along y-axis.
-      parent_bounds.set_y(-(new_bounds.y()));
-      new_bounds.set_y(0);
+      parent_bounds.set_y(-(new_bounds_dip.y() * buffer_scale_));
+      new_bounds_dip.set_y(0);
     } else {
       // If the menu window is located at correct origin from the browser point
       // of view, return the top level window back to 0,0.
@@ -633,11 +696,15 @@
     // Thus, the location must be translated to be relative to the top level
     // window, which automatically becomes the same as relative to an origin of
     // a display.
-    new_bounds = TranslateBoundsToTopLevelCoordinates(
-        new_bounds, parent_window_->GetBounds());
-    DCHECK(new_bounds.y() >= 0);
+    new_bounds_dip = gfx::ScaleToRoundedRect(
+        TranslateBoundsToTopLevelCoordinates(
+            gfx::ScaleToRoundedRect(new_bounds_dip, buffer_scale_),
+            parent_window_->GetBounds()),
+        1.0 / buffer_scale_);
+    DCHECK(new_bounds_dip.y() >= 0);
   }
-  SetBounds(new_bounds);
+
+  SetBoundsDip(new_bounds_dip);
 }
 
 void WaylandWindow::OnCloseRequest() {
@@ -685,6 +752,26 @@
   connection_->ResetPointerFlags();
 }
 
+void WaylandWindow::SetBoundsDip(const gfx::Rect& bounds_dip) {
+  SetBounds(gfx::ScaleToRoundedRect(bounds_dip, buffer_scale_));
+}
+
+void WaylandWindow::SetBufferScale(int32_t new_scale, bool update_bounds) {
+  DCHECK_GT(new_scale, 0);
+
+  if (new_scale == buffer_scale_)
+    return;
+
+  auto old_scale = buffer_scale_;
+  buffer_scale_ = new_scale;
+  if (update_bounds)
+    SetBoundsDip(gfx::ScaleToRoundedRect(bounds_px_, 1.0 / old_scale));
+
+  DCHECK(surface());
+  wl_surface_set_buffer_scale(surface(), buffer_scale_);
+  connection_->ScheduleFlush();
+}
+
 bool WaylandWindow::IsMinimized() const {
   return state_ == PlatformWindowState::PLATFORM_WINDOW_STATE_MINIMIZED;
 }
@@ -740,14 +827,28 @@
 }
 
 void WaylandWindow::AddEnteredOutputId(struct wl_output* output) {
+  // Wayland does weird things for popups so instead of tracking outputs that
+  // we entered or left, we take that from the parent window and ignore this
+  // event.
+  if (xdg_popup())
+    return;
+
   const uint32_t entered_output_id =
       connection_->wayland_output_manager()->GetIdForOutput(output);
   DCHECK_NE(entered_output_id, 0u);
   auto result = entered_outputs_ids_.insert(entered_output_id);
   DCHECK(result.first != entered_outputs_ids_.end());
+
+  UpdateBufferScale(true);
 }
 
 void WaylandWindow::RemoveEnteredOutputId(struct wl_output* output) {
+  // Wayland does weird things for popups so instead of tracking outputs that
+  // we entered or left, we take that from the parent window and ignore this
+  // event.
+  if (xdg_popup())
+    return;
+
   const uint32_t left_output_id =
       connection_->wayland_output_manager()->GetIdForOutput(output);
   auto entered_output_id_it = entered_outputs_ids_.find(left_output_id);
@@ -759,6 +860,8 @@
   // output only if it was stored before.
   if (entered_output_id_it != entered_outputs_ids_.end())
     entered_outputs_ids_.erase(entered_output_id_it);
+
+  UpdateBufferScale(true);
 }
 
 void WaylandWindow::UpdateCursorPositionFromEvent(
@@ -807,11 +910,14 @@
                             ? parent_window_->parent_window_
                             : parent_window_;
   DCHECK(parent_window);
+  DCHECK(buffer_scale_ == parent_window->buffer_scale_);
+
   // Chromium positions windows in screen coordinates, but Wayland requires them
   // to be in local surface coordinates aka relative to parent window.
-  const gfx::Rect parent_bounds = parent_window_->GetBounds();
+  const gfx::Rect parent_bounds_px =
+      gfx::ScaleToRoundedRect(parent_window_->GetBounds(), 1.0 / buffer_scale_);
   gfx::Rect new_bounds =
-      TranslateBoundsToParentCoordinates(bounds_, parent_bounds);
+      TranslateBoundsToParentCoordinates(bounds_px_, parent_bounds_px);
 
   // Chromium may decide to position nested menu windows on the left side
   // instead of the right side of parent menu windows when the size of the
@@ -835,7 +941,8 @@
       // Position the child menu window on the right side of the parent window
       // and let the Wayland compositor decide how to do constraint
       // adjustements.
-      int new_x = parent_bounds.width() - (new_bounds.width() + new_bounds.x());
+      int new_x =
+          parent_bounds_px.width() - (new_bounds.width() + new_bounds.x());
       new_bounds.set_x(new_x);
     }
   }
@@ -852,7 +959,7 @@
 
   wl::Object<wl_region> region(
       wl_compositor_create_region(connection_->compositor()));
-  wl_region_add(region.get(), 0, 0, bounds_.width(), bounds_.height());
+  wl_region_add(region.get(), 0, 0, bounds_px_.width(), bounds_px_.height());
   wl_surface_set_opaque_region(surface(), region.get());
 
   connection_->ScheduleFlush();
diff --git a/ui/ozone/platform/wayland/host/wayland_window.h b/ui/ozone/platform/wayland/host/wayland_window.h
index be9bb33..f54115e 100644
--- a/ui/ozone/platform/wayland/host/wayland_window.h
+++ b/ui/ozone/platform/wayland/host/wayland_window.h
@@ -51,10 +51,19 @@
 
   bool Initialize(PlatformWindowInitProperties properties);
 
+  // Updates the surface buffer scale of the window.  Top level windows take
+  // scale according to the scale of their current display or the primary one if
+  // their widget is not yet created, children inherit scale from their parent.
+  // The method recalculates window bounds appropriately if asked to do so
+  // (this is not needed upon window initialization).
+  void UpdateBufferScale(bool update_bounds);
+
   wl_surface* surface() const { return surface_.get(); }
   XDGSurfaceWrapper* xdg_surface() const { return xdg_surface_.get(); }
   XDGPopupWrapper* xdg_popup() const { return xdg_popup_.get(); }
 
+  WaylandWindow* parent_window() const { return parent_window_; }
+
   gfx::AcceleratedWidget GetWidget() const;
 
   // Returns the list of wl_outputs aka displays, which this window occupies.
@@ -89,6 +98,8 @@
   void set_has_implicit_grab(bool value) { has_implicit_grab_ = value; }
   bool has_implicit_grab() const { return has_implicit_grab_; }
 
+  int32_t buffer_scale() const { return buffer_scale_; }
+
   bool is_active() const { return is_active_; }
 
   // WmMoveResizeHandler
@@ -128,6 +139,10 @@
   bool CanDispatchEvent(const PlatformEvent& event) override;
   uint32_t DispatchEvent(const PlatformEvent& event) override;
 
+  // Handles the configuration events coming from the surface (see
+  // |XDGSurfaceWrapperV5::Configure| and
+  // |XDGSurfaceWrapperV6::ConfigureTopLevel|.  The width and height come in
+  // DIP of the output that the surface is currently bound to.
   void HandleSurfaceConfigure(int32_t widht,
                               int32_t height,
                               bool is_maximized,
@@ -146,6 +161,9 @@
   void OnDragSessionClose(uint32_t dnd_action);
 
  private:
+  void SetBoundsDip(const gfx::Rect& bounds_dip);
+  void SetBufferScale(int32_t scale, bool update_bounds);
+
   bool IsMinimized() const;
   bool IsMaximized() const;
   bool IsFullscreen() const;
@@ -213,14 +231,27 @@
 
   base::OnceCallback<void(int)> drag_closed_callback_;
 
-  gfx::Rect bounds_;
-  gfx::Rect pending_bounds_;
-  // The bounds of the window before it went maximized or fullscreen.
-  gfx::Rect restored_bounds_;
+  // These bounds attributes below have suffices that indicate units used.
+  // Wayland operates in DIP but the platform operates in physical pixels so
+  // our WaylandWindow is the link that has to translate the units.  See also
+  // comments in the implementation.
+  //
+  // Bounds that will be applied when the window state is finalized.  The window
+  // may get several configuration events that update the pending bounds, and
+  // only upon finalizing the state is the latest value stored as the current
+  // bounds via |ApplyPendingBounds|.  Measured in DIP because updated in the
+  // handler that receives DIP from Wayland.
+  gfx::Rect pending_bounds_dip_;
+  // Current bounds of the platform window.
+  gfx::Rect bounds_px_;
+  // The bounds of the platform window before it went maximized or fullscreen.
+  gfx::Rect restored_bounds_px_;
+
   bool has_pointer_focus_ = false;
   bool has_keyboard_focus_ = false;
   bool has_touch_focus_ = false;
   bool has_implicit_grab_ = false;
+  int32_t buffer_scale_ = 1;
 
   // Stores current states of the window.
   ui::PlatformWindowState state_;
@@ -236,7 +267,14 @@
 
   bool is_tooltip_ = false;
 
-  // Stores the list of entered outputs that the window is currently in.
+  // For top level window, stores the list of entered outputs that the window
+  // is currently in.
+  //
+  // Not used by popups.  When sub-menus are hidden and shown again, Wayland
+  // 'repositions' sub-menus to wrong outputs by sending them leave and enter
+  // events so their list of entered outputs becomes meaningless after they have
+  // been hidden at least once.  To determine which output the popup belongs to,
+  // we ask its parent.
   std::set<uint32_t> entered_outputs_ids_;
 
   DISALLOW_COPY_AND_ASSIGN(WaylandWindow);
diff --git a/ui/ozone/platform/wayland/host/xdg_popup_wrapper_v6.cc b/ui/ozone/platform/wayland/host/xdg_popup_wrapper_v6.cc
index a17719ea..742f8d4 100644
--- a/ui/ozone/platform/wayland/host/xdg_popup_wrapper_v6.cc
+++ b/ui/ozone/platform/wayland/host/xdg_popup_wrapper_v6.cc
@@ -257,8 +257,10 @@
     menu_type = MenuType::TYPE_3DOT_PARENT_MENU;
 
   // Place anchor to the end of the possible position.
-  gfx::Rect anchor_rect =
-      GetAnchorRect(menu_type, bounds, parent_window->GetBounds());
+  gfx::Rect anchor_rect = GetAnchorRect(
+      menu_type, bounds,
+      gfx::ScaleToRoundedRect(parent_window->GetBounds(),
+                              1.0 / parent_window->buffer_scale()));
 
   zxdg_positioner_v6_set_anchor_rect(positioner, anchor_rect.x(),
                                      anchor_rect.y(), anchor_rect.width(),
@@ -284,11 +286,10 @@
   // Wayland requires doing so in respect to parent window's origin. To properly
   // place windows, the bounds are translated and adjusted according to the
   // Wayland compositor needs during WaylandWindow::CreateXdgPopup call.
-  gfx::Rect new_bounds(x, y, width, height);
   WaylandWindow* window =
       static_cast<XDGPopupWrapperV6*>(data)->wayland_window_;
   DCHECK(window);
-  window->HandlePopupConfigure(new_bounds);
+  window->HandlePopupConfigure({x, y, width, height});
 }
 
 // static
diff --git a/ui/ozone/platform/wayland/test/mock_surface.cc b/ui/ozone/platform/wayland/test/mock_surface.cc
index 9d23336..b086bdc 100644
--- a/ui/ozone/platform/wayland/test/mock_surface.cc
+++ b/ui/ozone/platform/wayland/test/mock_surface.cc
@@ -47,6 +47,10 @@
   GetUserDataAs<MockSurface>(resource)->Commit();
 }
 
+void SetBufferScale(wl_client* client, wl_resource* resource, int32_t scale) {
+  GetUserDataAs<MockSurface>(resource)->SetBufferScale(scale);
+}
+
 void DamageBuffer(struct wl_client* client,
                   struct wl_resource* resource,
                   int32_t x,
@@ -67,7 +71,7 @@
     SetInputRegion,   // set_input_region
     Commit,           // commit
     nullptr,          // set_buffer_transform
-    nullptr,          // set_buffer_scale
+    SetBufferScale,   // set_buffer_scale
     DamageBuffer,     // damage_buffer
 };
 
diff --git a/ui/ozone/platform/wayland/test/mock_surface.h b/ui/ozone/platform/wayland/test/mock_surface.h
index 1ea9c52..d283e44b 100644
--- a/ui/ozone/platform/wayland/test/mock_surface.h
+++ b/ui/ozone/platform/wayland/test/mock_surface.h
@@ -37,6 +37,7 @@
   MOCK_METHOD4(Damage,
                void(int32_t x, int32_t y, int32_t width, int32_t height));
   MOCK_METHOD0(Commit, void());
+  MOCK_METHOD1(SetBufferScale, void(int32_t scale));
   MOCK_METHOD4(DamageBuffer,
                void(int32_t x, int32_t y, int32_t width, int32_t height));
 
diff --git a/ui/ozone/platform/wayland/test/test_output.cc b/ui/ozone/platform/wayland/test/test_output.cc
index 4abdc319..bbc6475 100644
--- a/ui/ozone/platform/wayland/test/test_output.cc
+++ b/ui/ozone/platform/wayland/test/test_output.cc
@@ -31,4 +31,9 @@
   wl_output_send_done(resource());
 }
 
+void TestOutput::SetScale(int32_t factor) {
+  wl_output_send_scale(resource(), factor);
+  wl_output_send_done(resource());
+}
+
 }  // namespace wl
diff --git a/ui/ozone/platform/wayland/test/test_output.h b/ui/ozone/platform/wayland/test/test_output.h
index bbd6848c..8dffd41 100644
--- a/ui/ozone/platform/wayland/test/test_output.h
+++ b/ui/ozone/platform/wayland/test/test_output.h
@@ -20,6 +20,8 @@
   const gfx::Rect GetRect() { return rect_; }
   void OnBind() override;
 
+  void SetScale(int32_t factor);
+
  private:
   gfx::Rect rect_;
 
diff --git a/ui/ozone/platform/wayland/test/wayland_test.cc b/ui/ozone/platform/wayland/test/wayland_test.cc
index f894644..1da8b15 100644
--- a/ui/ozone/platform/wayland/test/wayland_test.cc
+++ b/ui/ozone/platform/wayland/test/wayland_test.cc
@@ -6,6 +6,8 @@
 
 #include "base/run_loop.h"
 #include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
+#include "ui/ozone/platform/wayland/host/wayland_output_manager.h"
+#include "ui/ozone/platform/wayland/host/wayland_screen.h"
 #include "ui/ozone/platform/wayland/test/mock_surface.h"
 #include "ui/platform_window/platform_window_init_properties.h"
 
@@ -42,6 +44,8 @@
 void WaylandTest::SetUp() {
   ASSERT_TRUE(server_.Start(GetParam()));
   ASSERT_TRUE(connection_->Initialize());
+  screen_ = connection_->wayland_output_manager()->CreateWaylandScreen(
+      connection_.get());
   EXPECT_CALL(delegate_, OnAcceleratedWidgetAvailable(_))
       .WillOnce(SaveArg<0>(&widget_));
   PlatformWindowInitProperties properties;
diff --git a/ui/ozone/platform/wayland/test/wayland_test.h b/ui/ozone/platform/wayland/test/wayland_test.h
index 0acdf07..85a095df 100644
--- a/ui/ozone/platform/wayland/test/wayland_test.h
+++ b/ui/ozone/platform/wayland/test/wayland_test.h
@@ -28,6 +28,8 @@
 
 namespace ui {
 
+class WaylandScreen;
+
 const uint32_t kXdgShellV5 = 5;
 const uint32_t kXdgShellV6 = 6;
 
@@ -53,6 +55,7 @@
   std::unique_ptr<WaylandSurfaceFactory> surface_factory_;
   std::unique_ptr<WaylandBufferManagerGpu> buffer_manager_gpu_;
   std::unique_ptr<WaylandConnection> connection_;
+  std::unique_ptr<WaylandScreen> screen_;
   std::unique_ptr<WaylandWindow> window_;
   gfx::AcceleratedWidget widget_ = gfx::kNullAcceleratedWidget;